diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html index 8accd8635..6d727f388 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html @@ -3,43 +3,43 @@ (action)="delete()" *ngIf="canDelete" [tooltip]="'dossier-overview.bulk.delete' | translate" - icon="red:trash" [type]="circleButtonTypes.dark" + icon="red:trash" > - + @@ -56,23 +56,23 @@ (action)="setToUnderApproval()" *ngIf="canUndoApproval" [tooltip]="'dossier-overview.under-approval' | translate" - icon="red:undo" [type]="circleButtonTypes.dark" + icon="red:undo" > diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html index d85606bcb..78323fff6 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html @@ -8,7 +8,7 @@ > diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-actions/dossiers-listing-actions.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-actions/dossiers-listing-actions.component.html index 7c7b364fe..78eac82af 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-actions/dossiers-listing-actions.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-actions/dossiers-listing-actions.component.html @@ -4,17 +4,17 @@ (action)="openEditDossierDialog($event, dossier)" *ngIf="currentUser.isManager" [tooltip]="'dossier-listing.edit.action' | translate" - icon="iqser:edit" [type]="circleButtonTypes.dark" + icon="iqser:edit" > - + diff --git a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.html b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.html index 8d4e6e637..8329657e7 100644 --- a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.html +++ b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.html @@ -48,7 +48,7 @@ ; @Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above'; @Input() type: CircleButtonType = CircleButtonTypes.default; @Input() tooltipClass: string; @@ -34,11 +33,7 @@ export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestr } get canDownloadFiles() { - if (!Array.isArray(this.file)) { - return this._permissionsService.canDownloadFiles(this.file); - } - - return this.file.length > 0 && this.file.reduce((acc, file) => acc && this._permissionsService.canDownloadFiles(file), true); + return this.files.length > 0 && this.files.reduce((acc, file) => acc && this._permissionsService.canDownloadFiles(file), true); } get tooltip() { @@ -50,7 +45,7 @@ export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestr downloadFiles($event: MouseEvent) { $event.stopPropagation(); this.addSubscription = this._fileDownloadService - .downloadFiles(Array.isArray(this.file) ? this.file : [this.file], this.dossier) + .downloadFiles(this.files, this.dossier) .subscribe(() => this._toaster.info(_('download-status.queued'))); } } diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts index 74230877b..45741d33c 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts @@ -10,6 +10,7 @@ import { DownloadStatusWrapper } from '../model/download-status.wrapper'; import { AppStateService } from '@state/app-state.service'; import { KeycloakService } from 'keycloak-angular'; import { UserService } from '@services/user.service'; +import { List } from '@iqser/common-ui'; @Injectable() export class FileDownloadService { @@ -34,7 +35,7 @@ export class FileDownloadService { }); } - downloadFiles(files: File[], dossier: Dossier): Observable { + downloadFiles(files: List, dossier: Dossier): Observable { return this._downloadControllerService .prepareDownload({ fileIds: files.map(f => f.fileId), diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts index eacc863f0..63c013fb9 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; import { Colors, DossierRequest, IFile, ReanalysisControllerService } from '@redaction/red-ui-http'; -import { Toaster } from '@iqser/common-ui'; +import { List, Toaster } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; import { Event, NavigationEnd, ResolveStart, Router } from '@angular/router'; import { UserService } from '@services/user.service'; @@ -246,7 +246,9 @@ export class AppStateService { this._userService.getNameForId(iFile.currentReviewer), this._fileAttributesService.getFileAttributeConfig(iFile.dossierTemplateId) ); - this.activeDossier.files = this.activeDossier?.files.map(file => (file.fileId === activeFile.fileId ? activeFile : file)); + const files = this.activeDossier?.files.map(file => (file.fileId === activeFile.fileId ? activeFile : file)); + const newDossier = new Dossier(this.activeDossier, files); + this._appState.dossiers = [...this._appState.dossiers.filter(d => d.dossierId !== newDossier.dossierId), newDossier]; this._computeStats(); if (activeFile.lastProcessed !== oldProcessedDate) { @@ -672,7 +674,7 @@ export class AppStateService { await this._userPreferenceService.saveLastOpenedFileForDossier(dossierId, fileId); } - private _getExistingFiles(dossierId: string): File[] { + private _getExistingFiles(dossierId: string): List { const dossier = this.allDossiers.find(p => p.id === dossierId); return dossier?.files ?? []; } @@ -717,7 +719,7 @@ export class AppStateService { } } - dossier.files = iFiles.map( + const files = iFiles.map( iFile => new File( iFile, @@ -725,6 +727,12 @@ export class AppStateService { this._fileAttributesService.getFileAttributeConfig(iFile.dossierTemplateId) ) ); + + const lastOpenedFileId = this._userPreferenceService.getLastOpenedFileForDossier(dossier.id); + files.forEach(file => (file.lastOpened = file.fileId === lastOpenedFileId)); + const newDossier = new Dossier(dossier, files); + this._appState.dossiers = [...this._appState.dossiers.filter(d => d.dossierId !== dossier.dossierId), newDossier]; + this._computeStats(); if (emitEvents) { @@ -732,11 +740,7 @@ export class AppStateService { fileChangedEvent.forEach(file => this.fileChanged$.next(file)); } - const lastOpenedFileId = this._userPreferenceService.getLastOpenedFileForDossier(dossier.id); - - dossier.files.forEach(file => (file.lastOpened = file.fileId === lastOpenedFileId)); - - return iFiles; + return files; } private _computeStats() { diff --git a/apps/red-ui/src/app/state/model/dossier.ts b/apps/red-ui/src/app/state/model/dossier.ts index e70dc6972..34acc5b0b 100644 --- a/apps/red-ui/src/app/state/model/dossier.ts +++ b/apps/red-ui/src/app/state/model/dossier.ts @@ -21,21 +21,20 @@ export class Dossier implements IDossier, IListable { readonly watermarkEnabled: boolean; readonly hasReviewers: boolean; - reanalysisRequired = this._files.some(file => file.analysisRequired); - hasFiles = this._files.length > 0; - filesLength = this._files.length; + readonly reanalysisRequired = this.files.some(file => file.analysisRequired); + readonly hasFiles = this.files.length > 0; + readonly filesLength = this.files.length; - totalNumberOfPages = 0; - hintsOnly?: boolean; - hasRedactions?: boolean; - hasSuggestions?: boolean; - hasNone?: boolean; - hasPendingOrProcessing?: boolean; + readonly totalNumberOfPages: number; + readonly hintsOnly: boolean; + readonly hasRedactions: boolean; + readonly hasSuggestions: boolean; + readonly hasNone: boolean; + readonly hasPendingOrProcessing: boolean; - allFilesApproved?: boolean; type?: IDictionary; - constructor(dossier: IDossier, private _files: File[] = []) { + constructor(dossier: IDossier, readonly files: List = []) { this.dossierId = dossier.dossierId; this.approverIds = dossier.approverIds; this.date = dossier.date; @@ -54,7 +53,26 @@ export class Dossier implements IDossier, IListable { this.watermarkEnabled = !!dossier.watermarkEnabled; this.hasReviewers = !!this.memberIds && this.memberIds.length > 1; - this._recomputeFileStatus(); + let hintsOnly = false; + let hasRedactions = false; + let hasSuggestions = false; + let totalNumberOfPages = 0; + let hasPendingOrProcessing = false; + + this.files.forEach(f => { + hintsOnly = hintsOnly || f.hintsOnly; + hasRedactions = hasRedactions || f.hasRedactions; + hasSuggestions = hasSuggestions || f.hasSuggestions; + totalNumberOfPages += f.numberOfPages ?? 0; + hasPendingOrProcessing = hasPendingOrProcessing || f.isPending || f.isProcessing; + }); + + this.hintsOnly = hintsOnly; + this.hasRedactions = hasRedactions; + this.hasSuggestions = hasSuggestions; + this.totalNumberOfPages = totalNumberOfPages; + this.hasPendingOrProcessing = hasPendingOrProcessing; + this.hasNone = !this.hasSuggestions && !this.hasRedactions && !this.hintsOnly; } get id(): string { @@ -69,42 +87,11 @@ export class Dossier implements IDossier, IListable { return this.dossierName; } - get files(): File[] { - return this._files; - } - - set files(files: File[]) { - this._files = files ? files : []; - this._recomputeFileStatus(); - } - hasStatus(status: string): boolean { - return !!this._files.find(f => f.status === status); + return !!this.files.find(f => f.status === status); } hasMember(memberId: string): boolean { return !!this.memberIds && this.memberIds.indexOf(memberId) >= 0; } - - private _recomputeFileStatus() { - this.hintsOnly = false; - this.hasRedactions = false; - this.hasSuggestions = false; - this.hasNone = false; - this.allFilesApproved = true; - this.totalNumberOfPages = 0; - this.hasPendingOrProcessing = false; - this._files.forEach(f => { - this.hintsOnly = this.hintsOnly || f.hintsOnly; - this.hasRedactions = this.hasRedactions || f.hasRedactions; - this.hasSuggestions = this.hasSuggestions || f.hasSuggestions; - this.allFilesApproved = this.allFilesApproved && f.isApproved; - this.totalNumberOfPages += f.numberOfPages ?? 0; - this.hasPendingOrProcessing = this.hasPendingOrProcessing || f.isPending || f.isProcessing; - }); - this.hasNone = !this.hasSuggestions && !this.hasRedactions && !this.hintsOnly; - this.hasFiles = this._files.length > 0; - this.filesLength = this._files.length; - this.reanalysisRequired = this._files.some(file => file.analysisRequired); - } } diff --git a/apps/red-ui/src/app/utils/functions.ts b/apps/red-ui/src/app/utils/functions.ts index 76285fc64..28d8757e9 100644 --- a/apps/red-ui/src/app/utils/functions.ts +++ b/apps/red-ui/src/app/utils/functions.ts @@ -1,8 +1,9 @@ import * as moment from 'moment'; +import { List } from '@iqser/common-ui'; export const FALLBACK_COLOR = '#CCCCCC'; -export function groupBy(xs: any[], key: string) { +export function groupBy(xs: List, key: string) { return xs.reduce((rv, x) => { (rv[x[key]] = rv[x[key]] || []).push(x); return rv;