diff --git a/apps/red-ui/src/app/models/file/file-data.model.ts b/apps/red-ui/src/app/models/file/file-data.model.ts index eee719700..8644abaf0 100644 --- a/apps/red-ui/src/app/models/file/file-data.model.ts +++ b/apps/red-ui/src/app/models/file/file-data.model.ts @@ -1,5 +1,5 @@ import { RedactionChangeLog, RedactionLog, ViewedPages } from '@redaction/red-ui-http'; -import { FileStatusWrapper } from './file-status.wrapper'; +import { File } from './file'; import { AnnotationWrapper } from './annotation.wrapper'; import { RedactionLogEntryWrapper } from './redaction-log-entry.wrapper'; import { ViewMode } from './view-mode'; @@ -13,7 +13,7 @@ export class AnnotationData { export class FileDataModel { constructor( - public fileStatus: FileStatusWrapper, + public file: File, public fileData: Blob, public redactionLog: RedactionLog, public redactionChangeLog: RedactionChangeLog, @@ -29,7 +29,7 @@ export class FileDataModel { const entries: RedactionLogEntryWrapper[] = this._convertData(); let allAnnotations = entries .map(entry => AnnotationWrapper.fromData(entry)) - .filter(ann => !this.fileStatus.excludedPages.includes(ann.pageNumber)); + .filter(ann => !this.file.excludedPages.includes(ann.pageNumber)); if (!areDevFeaturesEnabled) { allAnnotations = allAnnotations.filter(annotation => !annotation.isFalsePositive); diff --git a/apps/red-ui/src/app/models/file/file-status.wrapper.ts b/apps/red-ui/src/app/models/file/file-status.wrapper.ts deleted file mode 100644 index 220bc522a..000000000 --- a/apps/red-ui/src/app/models/file/file-status.wrapper.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { IListable } from '@iqser/common-ui'; -import { FileAttributesConfig, FileStatus } from '@redaction/red-ui-http'; -import { StatusSorter } from '@utils/sorters/status-sorter'; - -const processingStatuses = [ - FileStatus.StatusEnum.REPROCESS, - FileStatus.StatusEnum.FULLREPROCESS, - FileStatus.StatusEnum.OCRPROCESSING, - FileStatus.StatusEnum.INDEXING, - FileStatus.StatusEnum.PROCESSING -] as const; - -export class FileStatusWrapper implements FileStatus, IListable { - readonly added = this.fileStatus.added; - readonly allManualRedactionsApplied = this.fileStatus.allManualRedactionsApplied; - readonly analysisDuration = this.fileStatus.analysisDuration; - readonly analysisRequired = this.fileStatus.analysisRequired && !this.fileStatus.excluded; - readonly approvalDate = this.fileStatus.approvalDate; - readonly currentReviewer = this.fileStatus.currentReviewer; - readonly dictionaryVersion = this.fileStatus.dictionaryVersion; - readonly dossierDictionaryVersion = this.fileStatus.dossierDictionaryVersion; - readonly dossierId = this.fileStatus.dossierId; - readonly excluded = this.fileStatus.excluded; - readonly fileAttributes = this.fileStatus.fileAttributes; - readonly fileId = this.fileStatus.fileId; - readonly filename = this.fileStatus.filename; - readonly hasAnnotationComments = this.fileStatus.hasAnnotationComments; - readonly hasHints = this.fileStatus.hasHints; - readonly hasImages = this.fileStatus.hasImages; - readonly hasRedactions = this.fileStatus.hasRedactions; - readonly hasUpdates = this.fileStatus.hasUpdates; - readonly lastOCRTime = this.fileStatus.lastOCRTime; - readonly lastProcessed = this.fileStatus.lastProcessed; - readonly lastReviewer = this.fileStatus.lastReviewer; - readonly lastUpdated = this.fileStatus.lastUpdated; - readonly lastUploaded = this.fileStatus.lastUploaded; - readonly legalBasisVersion = this.fileStatus.legalBasisVersion; - readonly numberOfAnalyses = this.fileStatus.numberOfAnalyses; - readonly numberOfPages = this.fileStatus.numberOfPages; - readonly rulesVersion = this.fileStatus.rulesVersion; - readonly status = this._status; - readonly uploader = this.fileStatus.uploader; - readonly excludedPages = this.fileStatus.excludedPages; - readonly hasSuggestions = this.fileStatus.hasSuggestions; - readonly dossierTemplateId = this.fileStatus.dossierTemplateId; - - primaryAttribute: string; - lastOpened: boolean; - - constructor(readonly fileStatus: FileStatus, public reviewerName: string, fileAttributesConfig?: FileAttributesConfig) { - if (fileAttributesConfig) { - const primary = fileAttributesConfig.fileAttributeConfigs?.find(c => c.primaryAttribute); - if (primary && fileStatus.fileAttributes?.attributeIdToValue) { - this.primaryAttribute = fileStatus.fileAttributes?.attributeIdToValue[primary.id]; - } - - if (!this.primaryAttribute) { - // Fallback here - this.primaryAttribute = '-'; - } - } - if (!this.fileAttributes || !this.fileAttributes.attributeIdToValue) { - this.fileAttributes = { attributeIdToValue: {} }; - } - } - - readonly statusSort = StatusSorter[this.status]; - readonly pages = this._pages; - readonly cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime); - - readonly hintsOnly = this.hasHints && !this.hasRedactions; - readonly hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions; - - readonly isUnassigned = !this.currentReviewer; - readonly isError = this.status === FileStatus.StatusEnum.ERROR; - readonly isProcessing = processingStatuses.includes(this.status); - readonly isApproved = this.status === FileStatus.StatusEnum.APPROVED; - readonly isPending = this.status === FileStatus.StatusEnum.UNPROCESSED; - readonly isUnderReview = this.status === FileStatus.StatusEnum.UNDERREVIEW; - readonly isUnderApproval = this.status === FileStatus.StatusEnum.UNDERAPPROVAL; - readonly canBeApproved = !this.analysisRequired && !this.hasSuggestions; - readonly canBeOpened = !this.isError && !this.isPending; - readonly isWorkable = !this.isProcessing && this.canBeOpened; - readonly canBeOCRed = !this.excluded && !this.lastOCRTime && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(this.status); - - get id(): string { - return this.fileId; - } - - get searchKey(): string { - return this.filename; - } - - private get _pages() { - if (this.fileStatus.status === 'ERROR') { - return -1; - } - return this.fileStatus.numberOfPages ? this.fileStatus.numberOfPages : 0; - } - - private get _status(): FileStatus.StatusEnum { - return this.fileStatus.status === FileStatus.StatusEnum.REPROCESS || this.fileStatus.status === FileStatus.StatusEnum.FULLREPROCESS - ? FileStatus.StatusEnum.PROCESSING - : this.fileStatus.status; - } -} diff --git a/apps/red-ui/src/app/models/file/file.ts b/apps/red-ui/src/app/models/file/file.ts new file mode 100644 index 000000000..d2085b208 --- /dev/null +++ b/apps/red-ui/src/app/models/file/file.ts @@ -0,0 +1,138 @@ +import { IListable } from '@iqser/common-ui'; +import { FileAttributes, FileAttributesConfig, FileStatus, FileStatuses, IFile, List } from '@redaction/red-ui-http'; +import { StatusSorter } from '@utils/sorters/status-sorter'; + +const processingStatuses: List = [ + FileStatuses.REPROCESS, + FileStatuses.FULLREPROCESS, + FileStatuses.OCR_PROCESSING, + FileStatuses.INDEXING, + FileStatuses.PROCESSING +] as const; + +export class File implements IFile, IListable { + readonly added: string; + readonly allManualRedactionsApplied: boolean; + readonly analysisDuration: number; + readonly analysisRequired: boolean; + readonly approvalDate: string; + readonly currentReviewer: string; + readonly dictionaryVersion: number; + readonly dossierDictionaryVersion: number; + readonly dossierId: string; + readonly excluded: boolean; + readonly fileAttributes: FileAttributes; + readonly fileId: string; + readonly filename: string; + readonly hasAnnotationComments: boolean; + readonly hasHints: boolean; + readonly hasImages: boolean; + readonly hasRedactions: boolean; + readonly hasUpdates: boolean; + readonly lastOCRTime: string; + readonly lastProcessed: string; + readonly lastReviewer: string; + readonly lastUpdated: string; + readonly lastUploaded: string; + readonly legalBasisVersion: number; + readonly numberOfAnalyses: number; + readonly numberOfPages: number; + readonly rulesVersion: number; + readonly status: FileStatus; + readonly uploader: string; + readonly excludedPages: number[]; + readonly hasSuggestions: boolean; + readonly dossierTemplateId: string; + + primaryAttribute: string; + lastOpened: boolean; + readonly statusSort: number; + readonly cacheIdentifier: string; + readonly hintsOnly: boolean; + readonly hasNone: boolean; + readonly isUnassigned: boolean; + readonly isError: boolean; + readonly isProcessing: boolean; + readonly isApproved: boolean; + readonly isPending: boolean; + readonly isUnderReview: boolean; + readonly isUnderApproval: boolean; + readonly canBeApproved: boolean; + readonly canBeOpened: boolean; + readonly isWorkable: boolean; + readonly canBeOCRed: boolean; + + constructor(file: IFile, public reviewerName: string, fileAttributesConfig?: FileAttributesConfig) { + this.added = file.added; + this.allManualRedactionsApplied = file.allManualRedactionsApplied; + this.analysisDuration = file.analysisDuration; + this.analysisRequired = file.analysisRequired && !file.excluded; + this.approvalDate = file.approvalDate; + this.currentReviewer = file.currentReviewer; + this.dictionaryVersion = file.dictionaryVersion; + this.dossierDictionaryVersion = file.dossierDictionaryVersion; + this.dossierId = file.dossierId; + this.excluded = file.excluded; + this.fileAttributes = file.fileAttributes; + this.fileId = file.fileId; + this.filename = file.filename; + this.hasAnnotationComments = file.hasAnnotationComments; + this.hasHints = file.hasHints; + this.hasImages = file.hasImages; + this.hasRedactions = file.hasRedactions; + this.hasUpdates = file.hasUpdates; + this.lastOCRTime = file.lastOCRTime; + this.lastProcessed = file.lastProcessed; + this.lastReviewer = file.lastReviewer; + this.lastUpdated = file.lastUpdated; + this.lastUploaded = file.lastUploaded; + this.legalBasisVersion = file.legalBasisVersion; + this.numberOfAnalyses = file.numberOfAnalyses; + this.status = ['REPROCESS', 'FULLREPROCESS'].includes(file.status) ? FileStatuses.PROCESSING : file.status; + this.isError = this.status === FileStatuses.ERROR; + this.numberOfPages = this.isError ? -1 : file.numberOfPages ?? 0; + this.rulesVersion = file.rulesVersion; + this.uploader = file.uploader; + this.excludedPages = file.excludedPages; + this.hasSuggestions = file.hasSuggestions; + this.dossierTemplateId = file.dossierTemplateId; + + this.statusSort = StatusSorter[this.status]; + this.cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime); + this.hintsOnly = this.hasHints && !this.hasRedactions; + this.hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions; + this.isUnassigned = !this.currentReviewer; + this.isProcessing = processingStatuses.includes(this.status); + this.isApproved = this.status === FileStatuses.APPROVED; + this.isPending = this.status === FileStatuses.UNPROCESSED; + this.isUnderReview = this.status === FileStatuses.UNDER_REVIEW; + this.isUnderApproval = this.status === FileStatuses.UNDER_APPROVAL; + this.canBeApproved = !this.analysisRequired && !this.hasSuggestions; + this.canBeOpened = !this.isError && !this.isPending; + this.isWorkable = !this.isProcessing && this.canBeOpened; + this.canBeOCRed = !this.excluded && !this.lastOCRTime && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(this.status); + + if (fileAttributesConfig) { + const primary = fileAttributesConfig.fileAttributeConfigs?.find(c => c.primaryAttribute); + if (primary && file.fileAttributes?.attributeIdToValue) { + this.primaryAttribute = file.fileAttributes?.attributeIdToValue[primary.id]; + } + + if (!this.primaryAttribute) { + // Fallback here + this.primaryAttribute = '-'; + } + } + if (!this.fileAttributes || !this.fileAttributes.attributeIdToValue) { + this.fileAttributes = { attributeIdToValue: {} }; + } + } + + get id(): string { + return this.fileId; + } + + get searchKey(): string { + return this.filename; + } +} diff --git a/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts b/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts index bd4ea102d..f98e39318 100644 --- a/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts @@ -2,7 +2,7 @@ import { Component, EventEmitter, Output } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http'; import { PermissionsService } from '@services/permissions.service'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { FileActionService } from '../../services/file-action.service'; import { Observable } from 'rxjs'; import { DossiersDialogService } from '../../services/dossiers-dialog.service'; @@ -19,8 +19,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; export class DossierOverviewBulkActionsComponent { readonly circleButtonTypes = CircleButtonTypes; - @Output() - reload = new EventEmitter(); + @Output() readonly reload = new EventEmitter(); constructor( private readonly _appStateService: AppStateService, @@ -31,14 +30,14 @@ export class DossierOverviewBulkActionsComponent { private readonly _fileActionService: FileActionService, private readonly _loadingService: LoadingService, private readonly _translateService: TranslateService, - private readonly _entitiesService: EntitiesService + private readonly _entitiesService: EntitiesService ) {} get dossier() { return this._appStateService?.activeDossier; } - get selectedFiles(): FileStatusWrapper[] { + get selectedFiles(): File[] { return this._entitiesService.selected; } @@ -91,21 +90,18 @@ export class DossierOverviewBulkActionsComponent { return this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true); } - get fileStatuses() { - return this.selectedFiles.map(file => file.fileStatus.status); + get files() { + return this.selectedFiles.map(file => file.status); } - // Under review get canSetToUnderReview() { return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true); } - // Under approval get canSetToUnderApproval() { return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true); } - // Approve get isReadyForApproval() { return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true); } @@ -114,7 +110,6 @@ export class DossierOverviewBulkActionsComponent { return this.selectedFiles.reduce((acc, file) => acc && file.canBeApproved, true); } - // Undo approval get canUndoApproval() { return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true); } @@ -156,7 +151,7 @@ export class DossierOverviewBulkActionsComponent { this._assignFiles('approver', true); } else { this._performBulkAction( - this._fileActionService.setFileUnderApproval(this.selectedFiles, this._appStateService.activeDossier.approverIds[0]) + this._fileActionService.setFilesUnderApproval(this.selectedFiles, this._appStateService.activeDossier.approverIds[0]) ); } } @@ -169,11 +164,11 @@ export class DossierOverviewBulkActionsComponent { } ocr() { - this._performBulkAction(this._fileActionService.ocrFile(this.selectedFiles)); + this._performBulkAction(this._fileActionService.ocrFiles(this.selectedFiles)); } setToUnderReview() { - this._performBulkAction(this._fileActionService.setFileUnderReview(this.selectedFiles)); + this._performBulkAction(this._fileActionService.setFilesUnderReview(this.selectedFiles)); } approveDocuments() { @@ -187,11 +182,11 @@ export class DossierOverviewBulkActionsComponent { question: _('confirmation-dialog.approve-multiple-files.question') }), () => { - this._performBulkAction(this._fileActionService.setFileApproved(this.selectedFiles)); + this._performBulkAction(this._fileActionService.setFilesApproved(this.selectedFiles)); } ); } else { - this._performBulkAction(this._fileActionService.setFileApproved(this.selectedFiles)); + this._performBulkAction(this._fileActionService.setFilesApproved(this.selectedFiles)); } } diff --git a/apps/red-ui/src/app/modules/dossier/components/document-info/document-info.component.ts b/apps/red-ui/src/app/modules/dossier/components/document-info/document-info.component.ts index 899820d09..638890d3d 100644 --- a/apps/red-ui/src/app/modules/dossier/components/document-info/document-info.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/document-info/document-info.component.ts @@ -3,7 +3,7 @@ import { FileAttributesConfig } from '@redaction/red-ui-http'; import { AppStateService } from '@state/app-state.service'; import { DossiersDialogService } from '../../services/dossiers-dialog.service'; import { AutoUnsubscribe } from '@iqser/common-ui'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; @Component({ selector: 'redaction-document-info', @@ -11,7 +11,7 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper'; styleUrls: ['./document-info.component.scss'] }) export class DocumentInfoComponent extends AutoUnsubscribe implements OnInit { - @Input() file: FileStatusWrapper; + @Input() file: File; @Output() closeDocumentInfoView = new EventEmitter(); fileAttributesConfig: FileAttributesConfig; diff --git a/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html b/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html index 8b35c60be..5cabf1c9b 100644 --- a/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html @@ -7,8 +7,8 @@ - -
+ +
@@ -150,7 +148,7 @@ (); + @Output() readonly actionPerformed = new EventEmitter(); - statusBarConfig?: readonly StatusBarConfig[]; + statusBarConfig?: readonly StatusBarConfig[]; tooltipPosition?: 'below' | 'above'; toggleTooltip?: string; assignTooltip?: string; @@ -84,7 +84,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD return _('file-preview.toggle-analysis.only-managers'); } - return this.fileStatus?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable'); + return this.file?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable'); } ngOnInit(): void { @@ -92,12 +92,10 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD this.fileStatus = this.appStateService.activeFile; } this._setup(); - this.addSubscription = this.appStateService.fileChanged$ - .pipe(filter(file => file.fileId === this.fileStatus?.fileId)) - .subscribe(fileStatus => { - this.fileStatus = fileStatus; - this._setup(); - }); + this.addSubscription = this.appStateService.fileChanged$.pipe(filter(file => file.fileId === this.file?.fileId)).subscribe(file => { + this.file = file; + this._setup(); + }); this.addSubscription = this.appStateService.dossierChanged$.subscribe(() => { this._setup(); @@ -127,7 +125,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD async () => { this._loadingService.start(); await this._fileManagementControllerService - .deleteFiles([this.fileStatus.fileId], this.fileStatus.dossierId) + .deleteFiles([this.file.fileId], this.file.dossierId) .toPromise() .catch(error => { this._toaster.error(_('error.http.generic'), { params: error }); @@ -140,8 +138,8 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD } assign($event: MouseEvent) { - const mode = this.fileStatus.isUnderApproval ? 'approver' : 'reviewer'; - const files = [this.fileStatus]; + const mode = this.file.isUnderApproval ? 'approver' : 'reviewer'; + const files = [this.file]; this._dialogService.openDialog('assignFile', $event, { mode, files }, () => { this.actionPerformed.emit('assign-reviewer'); }); @@ -150,7 +148,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD async assignToMe($event: MouseEvent) { $event.stopPropagation(); - await this._fileActionService.assignToMe(this.fileStatus, () => { + await this._fileActionService.assignToMe([this.file], () => { this.reloadDossiers('reanalyse'); }); } @@ -159,7 +157,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD if ($event) { $event.stopPropagation(); } - this.addSubscription = this._fileActionService.reanalyseFile(this.fileStatus).subscribe(() => { + this.addSubscription = this._fileActionService.reanalyseFile(this.file).subscribe(() => { this.reloadDossiers('reanalyse'); }); } @@ -167,9 +165,9 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD setFileUnderApproval($event: MouseEvent) { $event.stopPropagation(); if (this.appStateService.activeDossier.approverIds.length > 1) { - this._fileActionService.assignFile('approver', $event, this.fileStatus, () => this.reloadDossiers('assign-reviewer'), true); + this._fileActionService.assignFile('approver', $event, this.file, () => this.reloadDossiers('assign-reviewer'), true); } else { - this.addSubscription = this._fileActionService.setFileUnderApproval(this.fileStatus).subscribe(() => { + this.addSubscription = this._fileActionService.setFilesUnderApproval([this.file]).subscribe(() => { this.reloadDossiers('set-under-approval'); }); } @@ -177,7 +175,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD setFileApproved($event: MouseEvent) { $event.stopPropagation(); - if (this.fileStatus.hasUpdates) { + if (this.file.hasUpdates) { this._dialogService.openDialog( 'confirm', $event, @@ -196,7 +194,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD ocrFile($event: MouseEvent) { $event.stopPropagation(); - this.addSubscription = this._fileActionService.ocrFile(this.fileStatus).subscribe(() => { + this.addSubscription = this._fileActionService.ocrFiles([this.file]).subscribe(() => { this.reloadDossiers('ocr-file'); }); } @@ -205,7 +203,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD this._fileActionService.assignFile( 'reviewer', $event, - this.fileStatus, + this.file, () => this.reloadDossiers('assign-reviewer'), ignoreDialogChanges ); @@ -218,9 +216,9 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD } async toggleAnalysis() { - await this._fileActionService.toggleAnalysis(this.fileStatus).toPromise(); + await this._fileActionService.toggleAnalysis(this.file).toPromise(); await this.appStateService.getFiles(); - this.actionPerformed.emit(this.fileStatus?.excluded ? 'enable-analysis' : 'disable-analysis'); + this.actionPerformed.emit(this.file?.excluded ? 'enable-analysis' : 'disable-analysis'); } ngOnChanges(changes: SimpleChanges): void { @@ -231,12 +229,12 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD forceReanalysisAction($event: LongPressEvent) { if (this._userPreferenceService.areDevFeaturesEnabled) { - this.canReanalyse = $event.touchEnd ? this.permissionsService.canReanalyseFile(this.fileStatus) : true; + this.canReanalyse = $event.touchEnd ? this.permissionsService.canReanalyseFile(this.file) : true; } } private _setFileApproved() { - this.addSubscription = this._fileActionService.setFileApproved(this.fileStatus).subscribe(() => { + this.addSubscription = this._fileActionService.setFilesApproved([this.file]).subscribe(() => { this.reloadDossiers('set-approved'); }); } diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html index 05ec345ea..31e2e95ba 100644 --- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html @@ -93,7 +93,7 @@
- + {{ 'file-preview.tabs.annotations.page-is' | translate }}
@@ -187,7 +187,7 @@
diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts index 3dc3b67b9..a0fc2b05a 100644 --- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts @@ -43,8 +43,10 @@ export class FileWorkloadComponent { @Output() readonly actionPerformed = new EventEmitter(); displayedPages: number[] = []; pagesPanelActive = true; + readonly displayedAnnotations$ = this._displayedAnnotations$; @ViewChild('annotationsElement') private readonly _annotationsElement: ElementRef; @ViewChild('quickNavigation') private readonly _quickNavigationElement: ElementRef; + private _annotations$ = new BehaviorSubject([]); constructor( private readonly _permissionsService: PermissionsService, @@ -53,9 +55,6 @@ export class FileWorkloadComponent { private readonly _annotationProcessingService: AnnotationProcessingService ) {} - private _annotations$ = new BehaviorSubject([]); - readonly displayedAnnotations$ = this._displayedAnnotations$; - @Input() set annotations(value: AnnotationWrapper[]) { this._annotations$.next(value); @@ -78,7 +77,7 @@ export class FileWorkloadComponent { } get isProcessing(): boolean { - return this.fileData?.fileStatus?.isProcessing; + return this.fileData?.file?.isProcessing; } get activeAnnotations(): AnnotationWrapper[] | undefined { @@ -93,6 +92,14 @@ export class FileWorkloadComponent { return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null; } + private get _displayedAnnotations$(): Observable> { + const primary$ = this._filterService.getFilterModels$('primaryFilters'); + const secondary$ = this._filterService.getFilterModels$('secondaryFilters'); + return combineLatest([this._annotations$, primary$, secondary$]).pipe( + map(([annotations, primary, secondary]) => this._filterAnnotations(annotations, primary, secondary)) + ); + } + private static _scrollToFirstElement(elements: HTMLElement[], mode: 'always' | 'if-needed' = 'if-needed') { if (elements.length > 0) { scrollIntoView(elements[0], { @@ -120,19 +127,6 @@ export class FileWorkloadComponent { this.deselectAnnotations.emit(this.activeAnnotations); } - private _filterAnnotations( - annotations: AnnotationWrapper[], - primary: INestedFilter[], - secondary: INestedFilter[] = [] - ): Map { - if (!primary) { - return; - } - this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary); - this.displayedPages = [...this.displayedAnnotations.keys()]; - return this.displayedAnnotations; - } - @HostListener('window:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent): void { if ( @@ -210,7 +204,7 @@ export class FileWorkloadComponent { } scrollQuickNavLast(): void { - this.selectPage.emit(this.fileData.fileStatus.numberOfPages); + this.selectPage.emit(this.fileData.file.numberOfPages); } pageSelectedByClick($event: number): void { @@ -232,12 +226,17 @@ export class FileWorkloadComponent { this.selectPage.emit(this._nextPageWithAnnotations()); } - private get _displayedAnnotations$(): Observable> { - const primary$ = this._filterService.getFilterModels$('primaryFilters'); - const secondary$ = this._filterService.getFilterModels$('secondaryFilters'); - return combineLatest([this._annotations$, primary$, secondary$]).pipe( - map(([annotations, primary, secondary]) => this._filterAnnotations(annotations, primary, secondary)) - ); + private _filterAnnotations( + annotations: AnnotationWrapper[], + primary: INestedFilter[], + secondary: INestedFilter[] = [] + ): Map { + if (!primary) { + return; + } + this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary); + this.displayedPages = [...this.displayedAnnotations.keys()]; + return this.displayedAnnotations; } private _selectFirstAnnotationOnCurrentPageIfNecessary() { diff --git a/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts b/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts index a2e1885ad..b04bb5e76 100644 --- a/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts @@ -1,6 +1,6 @@ import { Component, Input } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { Dossier } from '../../../../state/model/dossier'; @Component({ @@ -9,7 +9,7 @@ import { Dossier } from '../../../../state/model/dossier'; styleUrls: ['./needs-work-badge.component.scss'] }) export class NeedsWorkBadgeComponent { - @Input() needsWorkInput: FileStatusWrapper | Dossier; + @Input() needsWorkInput: File | Dossier; constructor(private readonly _appStateService: AppStateService) {} @@ -38,15 +38,15 @@ export class NeedsWorkBadgeComponent { } get hasImages() { - return this.needsWorkInput instanceof FileStatusWrapper && this.needsWorkInput.hasImages; + return this.needsWorkInput instanceof File && this.needsWorkInput.hasImages; } get hasUpdates() { - return this.needsWorkInput instanceof FileStatusWrapper && this.needsWorkInput.hasUpdates; + return this.needsWorkInput instanceof File && this.needsWorkInput.hasUpdates; } get hasAnnotationComments(): boolean { - return this.needsWorkInput instanceof FileStatusWrapper && (this.needsWorkInput).hasAnnotationComments; + return this.needsWorkInput instanceof File && (this.needsWorkInput).hasAnnotationComments; } reanalysisRequired() { diff --git a/apps/red-ui/src/app/modules/dossier/components/page-exclusion/page-exclusion.component.ts b/apps/red-ui/src/app/modules/dossier/components/page-exclusion/page-exclusion.component.ts index 95c64f892..901096a0a 100644 --- a/apps/red-ui/src/app/modules/dossier/components/page-exclusion/page-exclusion.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/page-exclusion/page-exclusion.component.ts @@ -1,9 +1,9 @@ import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; import { PageRange, ReanalysisControllerService } from '@redaction/red-ui-http'; -import { InputWithActionComponent, Toaster, LoadingService } from '@iqser/common-ui'; +import { InputWithActionComponent, LoadingService, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; @Component({ selector: 'redaction-page-exclusion', @@ -11,7 +11,7 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper'; styleUrls: ['./page-exclusion.component.scss'] }) export class PageExclusionComponent implements OnChanges { - @Input() fileStatus: FileStatusWrapper; + @Input() file: File; @Output() readonly actionPerformed = new EventEmitter(); excludedPagesRanges: PageRange[] = []; @@ -25,7 +25,7 @@ export class PageExclusionComponent implements OnChanges { ) {} ngOnChanges(): void { - const excludedPages = (this.fileStatus?.excludedPages || []).sort((p1, p2) => p1 - p2); + const excludedPages = (this.file?.excludedPages || []).sort((p1, p2) => p1 - p2); this.excludedPagesRanges = excludedPages.reduce((ranges, page) => { if (!ranges.length) { return [{ startPage: page, endPage: page }]; @@ -60,8 +60,8 @@ export class PageExclusionComponent implements OnChanges { { pageRanges: pageRanges }, - this.fileStatus.dossierId, - this.fileStatus.fileId + this.file.dossierId, + this.file.fileId ) .toPromise(); this._inputComponent.reset(); @@ -79,8 +79,8 @@ export class PageExclusionComponent implements OnChanges { { pageRanges: [range] }, - this.fileStatus.dossierId, - this.fileStatus.fileId + this.file.dossierId, + this.file.fileId ) .toPromise(); this._inputComponent.reset(); diff --git a/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.html b/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.html index e20a2f31b..251630448 100644 --- a/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.html @@ -1,5 +1,5 @@
-
+
diff --git a/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts index 13a55434d..94b20a5d0 100644 --- a/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/pdf-viewer/pdf-viewer.component.ts @@ -17,7 +17,7 @@ import { TranslateService } from '@ngx-translate/core'; import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ManualAnnotationService } from '../../services/manual-annotation.service'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { environment } from '@environments/environment'; import { AnnotationDrawService } from '../../services/annotation-draw.service'; import { AnnotationActionsService } from '../../services/annotation-actions.service'; @@ -43,18 +43,18 @@ import Annotation = Core.Annotations.Annotation; }) export class PdfViewerComponent implements OnInit, OnChanges { @Input() fileData: Blob; - @Input() fileStatus: FileStatusWrapper; + @Input() file: File; @Input() canPerformActions = false; @Input() annotations: AnnotationWrapper[]; @Input() shouldDeselectAnnotationsOnPageChange = true; @Input() multiSelectActive: boolean; - @Output() fileReady = new EventEmitter(); - @Output() annotationSelected = new EventEmitter(); - @Output() manualAnnotationRequested = new EventEmitter(); - @Output() pageChanged = new EventEmitter(); - @Output() keyUp = new EventEmitter(); - @Output() viewerReady = new EventEmitter(); - @Output() annotationsChanged = new EventEmitter(); + @Output() readonly fileReady = new EventEmitter(); + @Output() readonly annotationSelected = new EventEmitter(); + @Output() readonly manualAnnotationRequested = new EventEmitter(); + @Output() readonly pageChanged = new EventEmitter(); + @Output() readonly keyUp = new EventEmitter(); + @Output() readonly viewerReady = new EventEmitter(); + @Output() readonly annotationsChanged = new EventEmitter(); @ViewChild('viewer', { static: true }) viewer: ElementRef; @ViewChild('compareFileInput', { static: true }) compareFileInput: ElementRef; instance: WebViewerInstance; @@ -146,7 +146,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { compareDocument, mergedDocument, this.instance, - this.fileStatus, + this.file, () => { this.viewMode = 'COMPARE'; }, @@ -188,7 +188,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null); const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.fileData.arrayBuffer()); this.instance.UI.loadDocument(currentDocument, { - filename: this.fileStatus ? this.fileStatus.filename : 'document.pdf' + filename: this.file ? this.file.filename : 'document.pdf' }); this.instance.UI.disableElements(['closeCompareButton']); this.instance.UI.enableElements(['compareButton']); @@ -571,7 +571,7 @@ export class PdfViewerComponent implements OnInit, OnChanges { private _loadDocument() { if (this.fileData) { this.instance.UI.loadDocument(this.fileData, { - filename: this.fileStatus ? this.fileStatus.filename : 'document.pdf' + filename: this.file ? this.file.filename : 'document.pdf' }); } } diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts index 95f3394f8..ad3464181 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component.ts @@ -5,14 +5,14 @@ import { AppStateService } from '@state/app-state.service'; import { UserService } from '@services/user.service'; import { Toaster } from '@iqser/common-ui'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { Dossier } from '../../../../state/model/dossier'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; class DialogData { mode: 'approver' | 'reviewer'; dossier?: Dossier; - files?: FileStatusWrapper[]; + files?: File[]; ignoreChanged?: boolean; } diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/document-info-dialog/document-info-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/document-info-dialog/document-info-dialog.component.ts index 3ffd8e5bc..39d6f0c31 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/document-info-dialog/document-info-dialog.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/document-info-dialog/document-info-dialog.component.ts @@ -1,9 +1,9 @@ import { Component, Inject, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { FileAttributesControllerService, FileStatus, IFileAttributeConfig } from '@redaction/red-ui-http'; +import { FileAttributesControllerService, IFile, IFileAttributeConfig } from '@redaction/red-ui-http'; import { AppStateService } from '@state/app-state.service'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { Dossier } from '../../../../state/model/dossier'; +import { Dossier } from '@state/model/dossier'; @Component({ templateUrl: './document-info-dialog.component.html', @@ -11,7 +11,7 @@ import { Dossier } from '../../../../state/model/dossier'; }) export class DocumentInfoDialogComponent implements OnInit { documentInfoForm: FormGroup; - file: FileStatus; + file: IFile; attributes: IFileAttributeConfig[]; private _dossier: Dossier; @@ -21,7 +21,7 @@ export class DocumentInfoDialogComponent implements OnInit { private readonly _formBuilder: FormBuilder, private readonly _fileAttributesService: FileAttributesControllerService, public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: FileStatus + @Inject(MAT_DIALOG_DATA) public data: IFile ) { this.file = this.data; this._dossier = this._appStateService.getDossierById(this.file.dossierId); diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.ts index b742ff20f..6e588c51b 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.ts @@ -10,7 +10,7 @@ import { SortingOrders, TableColumnConfig } from '@iqser/common-ui'; -import { FileManagementControllerService, FileStatus, StatusControllerService } from '@redaction/red-ui-http'; +import { FileManagementControllerService, IFile, StatusControllerService } from '@redaction/red-ui-http'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import * as moment from 'moment'; import { ConfigService } from '@services/config.service'; @@ -21,7 +21,7 @@ import { ConfirmationDialogInput, TitleColors } from '@shared/dialogs/confirmati import { DossiersDialogService } from '../../../services/dossiers-dialog.service'; import { AppStateService } from '@state/app-state.service'; -interface FileListItem extends FileStatus, IListable { +interface FileListItem extends IFile, IListable { readonly canRestore: boolean; readonly restoreDate: string; } @@ -156,11 +156,11 @@ export class EditDossierDeletedDocumentsComponent extends ListingComponent this._toListItem(file)); } - private _toListItem(file: FileStatus): FileListItem { + private _toListItem(file: IFile): FileListItem { const restoreDate = this._getRestoreDate(file.softDeleted); return { id: file.fileId, 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 264ba5947..4c90dc77e 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 @@ -91,7 +91,7 @@
- +
@@ -109,71 +109,71 @@
- +
-
- {{ fileStatus.added | date: 'd MMM. yyyy, hh:mm a' }} +
+ {{ file.added | date: 'd MMM. yyyy, hh:mm a' }}
- +
- {{ fileStatus.fileAttributes.attributeIdToValue[config.id] }} + {{ file.fileAttributes.attributeIdToValue[config.id] }}
- + -
+
-
- +
+
- -
- + +
+
- -
+ +
- {{ fileStatus.numberOfPages }} + {{ file.numberOfPages }}
- -
-
-
+ +
+
+
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts index 800c3060d..1e21619a9 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts @@ -19,13 +19,13 @@ import { StatusOverlayService } from '@upload-download/services/status-overlay.s import { TranslateService } from '@ngx-translate/core'; import * as moment from 'moment'; import { DossierDetailsComponent } from '../../components/dossier-details/dossier-details.component'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { UserService } from '@services/user.service'; import { timer } from 'rxjs'; import { tap } from 'rxjs/operators'; import { RedactionFilterSorter } from '@utils/sorters/redaction-filter-sorter'; import { StatusSorter } from '@utils/sorters/status-sorter'; -import { convertFiles, handleFileDrop } from '@utils/file-drop-utils'; +import { convertFiles, Files, handleFileDrop } from '@utils/file-drop-utils'; import { DossiersDialogService } from '../../services/dossiers-dialog.service'; import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy'; import { ConfigService } from '@services/config.service'; @@ -63,7 +63,7 @@ import StatusEnum = FileStatus.StatusEnum; styleUrls: ['./dossier-overview-screen.component.scss'], providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DossierOverviewScreenComponent) }] }) -export class DossierOverviewScreenComponent extends ListingComponent implements OnInit, OnDestroy, OnDetach, OnAttach { +export class DossierOverviewScreenComponent extends ListingComponent implements OnInit, OnDestroy, OnDetach, OnAttach { readonly listingModes = ListingModes; readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = this._userService.currentUser; @@ -77,7 +77,7 @@ export class DossierOverviewScreenComponent extends ListingComponent[] = []; + tableColumnConfigs: readonly TableColumnConfig[] = []; collapsedDetails = false; dossierAttributes: DossierAttributeWithValue[] = []; fileAttributeConfigs: IFileAttributeConfig[]; @@ -303,7 +303,7 @@ export class DossierOverviewScreenComponent extends ListingComponent { + async uploadFiles(files: Files): Promise { await this._uploadFiles(convertFiles(files, this.currentDossier)); this._fileInput.nativeElement.value = null; } @@ -335,11 +335,11 @@ export class DossierOverviewScreenComponent extends ListingComponent + recentlyModifiedChecker = (file: File) => moment(file.lastUpdated).add(this._configService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment()); private _configureTableColumns() { - const dynamicColumns: TableColumnConfig[] = []; + const dynamicColumns: TableColumnConfig[] = []; for (const config of this.displayedInFileListAttributes) { if (config.displayedInFileList) { dynamicColumns.push({ label: config.label, notTranslatable: true, template: this.attributeTemplate, extra: config }); @@ -372,7 +372,7 @@ export class DossierOverviewScreenComponent extends ListingComponent filter.id === input.fileAttributes.attributeIdToValue[id] + checker: (input: File, filter: INestedFilter) => filter.id === input.fileAttributes.attributeIdToValue[id] }); }); this.filterService.addFilterGroup({ slug: 'quickFilters', filters: this._createQuickFilters(), - checker: (file: FileStatusWrapper) => + checker: (file: File) => this.checkedRequiredFilters.reduce((acc, f) => acc && f.checker(file), true) && (this.checkedNotRequiredFilters.length === 0 || this.checkedNotRequiredFilters.reduce((acc, f) => acc || f.checker(file), false)) @@ -586,17 +586,17 @@ export class DossierOverviewScreenComponent extends ListingComponent file.currentReviewer === this.currentUser.id + checker: (file: File) => file.currentReviewer === this.currentUser.id }, { id: 'unassigned', label: this._translateService.instant('dossier-overview.quick-filters.unassigned'), - checker: (file: FileStatusWrapper) => !file.currentReviewer + checker: (file: File) => !file.currentReviewer }, { id: 'assigned-to-others', label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-others'), - checker: (file: FileStatusWrapper) => !!file.currentReviewer && file.currentReviewer !== this.currentUser.id + checker: (file: File) => !!file.currentReviewer && file.currentReviewer !== this.currentUser.id } ].map(filter => new NestedFilter(filter)); } diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html index 3a33b9286..583a45ec0 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html @@ -142,7 +142,7 @@ [annotations]="annotations" [canPerformActions]="canPerformAnnotationActions" [fileData]="displayData" - [fileStatus]="appStateService.activeFile" + [file]="appStateService.activeFile" [multiSelectActive]="multiSelectActive" [shouldDeselectAnnotationsOnPageChange]="shouldDeselectAnnotationsOnPageChange" > @@ -159,7 +159,7 @@ ; - @ViewChild('fileActions') fileActions: FileActionsComponent; constructor( readonly appStateService: AppStateService, @@ -148,11 +148,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } get canSwitchToRedactedView(): boolean { - return this.fileData && !this.fileData.fileStatus.analysisRequired && !this.fileData.fileStatus.excluded; + return this.fileData && !this.fileData.file.analysisRequired && !this.fileData.file.excluded; } get canSwitchToDeltaView(): boolean { - return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.fileStatus.excluded; + return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.file.excluded; } get canAssign(): boolean { @@ -176,7 +176,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } get lastReviewer(): string | undefined { - return this.appStateService.activeFile.fileStatus.lastReviewer; + return this.appStateService.activeFile.lastReviewer; } get assignOrChangeReviewerTooltip(): string { @@ -189,11 +189,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni return this.appStateService.activeFile.currentReviewer; } - get status(): FileStatus.StatusEnum { + get status(): FileStatus { return this.appStateService.activeFile.status; } - get statusBarConfig(): [{ length: number; color: FileStatus.StatusEnum }] { + get statusBarConfig(): [{ length: number; color: FileStatus }] { return [{ length: 1, color: this.status }]; } @@ -261,7 +261,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._updateCanPerformActions(); this._subscribeToFileUpdates(); - if (this.fileData?.fileStatus?.analysisRequired) { + if (this.fileData?.file?.analysisRequired) { this.fileActions.reanalyseFile(); } } @@ -355,7 +355,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni response.manualRedactionEntryWrapper.rectId ); this._instance.Core.annotationManager.deleteAnnotation(annotation); - this.fileData.fileStatus = await this.appStateService.reloadActiveFile(); + this.fileData.file = await this.appStateService.reloadActiveFile(); const distinctPages = entryWrapper.manualRedactionEntry.positions .map(p => p.page) .filter((item, pos, self) => self.indexOf(item) === pos); @@ -490,7 +490,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } async assignToMe() { - await this._fileActionService.assignToMe(this.fileData.fileStatus, async () => { + await this._fileActionService.assignToMe([this.fileData.file], async () => { await this.appStateService.reloadActiveFile(); this._updateCanPerformActions(); }); @@ -500,7 +500,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni const reviewerId = typeof user === 'string' ? user : user.id; const reviewerName = this.userService.getNameForId(reviewerId); - const { dossierId, fileId, filename } = this.fileData.fileStatus; + const { dossierId, fileId, filename } = this.fileData.file; await this._statusControllerService.setFileReviewer(dossierId, fileId, reviewerId).toPromise(); this._toaster.info(_('assignment.reviewer'), { params: { reviewerName, filename } }); @@ -523,9 +523,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni downloadOriginalFile() { this.addSubscription = this._fileManagementControllerService - .downloadOriginalFile(this.dossierId, this.fileId, true, this.fileData.fileStatus.cacheIdentifier, 'response') + .downloadOriginalFile(this.dossierId, this.fileId, true, this.fileData.file.cacheIdentifier, 'response') .subscribe(data => { - download(data, this.fileData.fileStatus.filename); + download(data, this.fileData.file.filename); }); } @@ -561,7 +561,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni if (excludedPages && excludedPages.length > 0) { const pdfNet = this._instance.Core.PDFNet; const document = await this._instance.Core.documentViewer.getDocument().getPDFDoc(); - await clearStamps(document, pdfNet, [...Array(this.fileData.fileStatus.numberOfPages).keys()]); + await clearStamps(document, pdfNet, [...Array(this.fileData.file.numberOfPages).keys()]); await stampPDFPage( document, pdfNet, @@ -577,7 +577,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } private async _stampExcludedPages() { - await this._doStampExcludedPages(this.fileData.fileStatus.excludedPages); + await this._doStampExcludedPages(this.fileData.file.excludedPages); this._instance.Core.documentViewer.refreshAll(); this._instance.Core.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage); this._changeDetectorRef.detectChanges(); @@ -585,8 +585,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni private _subscribeToFileUpdates(): void { this.addSubscription = timer(0, 5000).subscribe(async () => await this.appStateService.reloadActiveFile()); - this.addSubscription = this.appStateService.fileReanalysed$.subscribe(async (fileStatus: FileStatusWrapper) => { - if (fileStatus.fileId === this.fileId) { + this.addSubscription = this.appStateService.fileReanalysed$.subscribe(async (file: File) => { + if (file.fileId === this.fileId) { await this._loadFileData(!this._reloadFileOnReanalysis); this._reloadFileOnReanalysis = false; this._loadingService.stop(); @@ -606,11 +606,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni private async _loadFileData(performUpdate = false): Promise { const fileData = await this._fileDownloadService.loadActiveFileData().toPromise(); - if (!fileData.fileStatus?.isPending && !fileData.fileStatus?.isError) { + if (!fileData.file?.isPending && !fileData.file?.isError) { if (performUpdate) { this.fileData.redactionLog = fileData.redactionLog; this.fileData.redactionChangeLog = fileData.redactionChangeLog; - this.fileData.fileStatus = fileData.fileStatus; + this.fileData.file = fileData.file; this.rebuildFilters(true); } else { this.fileData = fileData; @@ -620,7 +620,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni return; } - if (fileData.fileStatus.isError) { + if (fileData.file.isError) { await this._router.navigate(['/main/dossiers/' + this.dossierId]); } } @@ -648,7 +648,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni private async _cleanupAndRedrawManualAnnotationsForEntirePage(page: number) { const currentPageAnnotations = this.annotations.filter(a => a.pageNumber === page); const currentPageAnnotationIds = currentPageAnnotations.map(a => a.id); - this.fileData.fileStatus = await this.appStateService.reloadActiveFile(); + this.fileData.file = await this.appStateService.reloadActiveFile(); this._fileDownloadService.loadActiveFileRedactionLog().subscribe(redactionLogPreview => { this.fileData.redactionLog = redactionLogPreview; diff --git a/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts b/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts index 4ab77db57..c147d2ddc 100644 --- a/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts @@ -2,9 +2,8 @@ import { Injectable } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; import { UserService } from '@services/user.service'; import { ReanalysisControllerService, StatusControllerService } from '@redaction/red-ui-http'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { PermissionsService } from '@services/permissions.service'; -import { isArray } from 'rxjs/internal-compatibility'; import { DossiersDialogService } from './dossiers-dialog.service'; import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -21,108 +20,87 @@ export class FileActionService { private readonly _appStateService: AppStateService ) {} - reanalyseFile(fileStatusWrapper?: FileStatusWrapper) { - if (!fileStatusWrapper) { - fileStatusWrapper = this._appStateService.activeFile; - } - return this._reanalysisControllerService.reanalyzeFile(this._appStateService.activeDossier.id, fileStatusWrapper.fileId, true); + reanalyseFile(file = this._appStateService.activeFile) { + return this._reanalysisControllerService.reanalyzeFile(this._appStateService.activeDossier.id, file.fileId, true); } - toggleAnalysis(fileStatusWrapper?: FileStatusWrapper) { - if (!fileStatusWrapper) { - fileStatusWrapper = this._appStateService.activeFile; - } - return this._reanalysisControllerService.toggleAnalysis( - fileStatusWrapper.dossierId, - fileStatusWrapper.fileId, - !fileStatusWrapper.excluded - ); + toggleAnalysis(file = this._appStateService.activeFile) { + return this._reanalysisControllerService.toggleAnalysis(file.dossierId, file.fileId, !file.excluded); } - async assignToMe(fileStatus?: FileStatusWrapper | FileStatusWrapper[], callback?: Function) { + async assignToMe(files?: File[], callback?: Function) { return new Promise((resolve, reject) => { - if (!isArray(fileStatus)) { - fileStatus = [fileStatus]; - } - - const atLeastOneFileHasReviewer = fileStatus.reduce((acc, fs) => acc || !!fs.currentReviewer, false); + const atLeastOneFileHasReviewer = files.reduce((acc, fs) => acc || !!fs.currentReviewer, false); if (atLeastOneFileHasReviewer) { const data = new ConfirmationDialogInput({ title: _('confirmation-dialog.assign-file-to-me.title'), question: _('confirmation-dialog.assign-file-to-me.question') }); this._dialogService.openDialog('confirm', null, data, () => { - this._assignReviewerToCurrentUser(fileStatus, callback) + this._assignReviewerToCurrentUser(files, callback) .then(() => resolve()) .catch(() => reject()); }); } else { - this._assignReviewerToCurrentUser(fileStatus, callback) + this._assignReviewerToCurrentUser(files, callback) .then(() => resolve()) .catch(() => reject()); } }); } - setFileUnderApproval(fileStatus: FileStatusWrapper | FileStatusWrapper[], approverId?: string) { - if (!isArray(fileStatus)) { - fileStatus = [fileStatus]; - } - + setFilesUnderApproval(files: File[], approverId?: string) { if (!approverId) { approverId = this._appStateService.activeDossier.approverIds[0]; } return this._statusControllerService.setStatusUnderApprovalForList( - fileStatus.map(f => f.fileId), + files.map(f => f.fileId), approverId, this._appStateService.activeDossierId ); } - setFileApproved(fileStatus: FileStatusWrapper | FileStatusWrapper[]): Observable { - if (!isArray(fileStatus)) { - fileStatus = [fileStatus]; - } + setFilesApproved(files: File[]) { return this._statusControllerService.setStatusApprovedForList( - fileStatus.map(f => f.fileId), + files.map(f => f.fileId), this._appStateService.activeDossierId ); } - setFileUnderReview(fileStatus: FileStatusWrapper | FileStatusWrapper[]) { - if (!isArray(fileStatus)) { - fileStatus = [fileStatus]; - } + setFilesUnderReview(files: File[]) { return this._statusControllerService.setStatusUnderReviewForList( - fileStatus.map(f => f.fileId), + files.map(f => f.fileId), this._appStateService.activeDossierId ); } - ocrFile(fileStatus: FileStatusWrapper | FileStatusWrapper[]) { - if (!isArray(fileStatus)) { - fileStatus = [fileStatus]; - } + ocrFiles(files: File[]) { return this._reanalysisControllerService.ocrFiles( - fileStatus.map(f => f.fileId), + files.map(f => f.fileId), this._appStateService.activeDossierId ); } - assignFile(mode: 'reviewer' | 'approver', $event: MouseEvent, file?: FileStatusWrapper, callback?: Function, ignoreChanged = false) { - const files = file ? [file] : [this._appStateService.activeFile]; - const data = { mode, files, ignoreChanged }; - this._dialogService.openDialog('assignFile', $event, data, callback); + assignFile( + mode: 'reviewer' | 'approver', + $event: MouseEvent, + file = this._appStateService.activeFile, + callback?: Function, + ignoreChanged = false + ) { + const data = { mode, files: [file], ignoreChanged }; + this._dialogService.openDialog('assignFile', $event, data, async () => { + if (callback) { + callback(); + } + }); } - private async _assignReviewerToCurrentUser(fileStatus: FileStatusWrapper | FileStatusWrapper[], callback?: Function) { - if (!isArray(fileStatus)) { - fileStatus = [fileStatus]; - } + private async _assignReviewerToCurrentUser(files: File[], callback?: Function) { await this._statusControllerService .setFileReviewerForList( - fileStatus.map(f => f.fileId), + files.map(f => f.fileId), this._appStateService.activeDossierId, this._userService.currentUser.id ) diff --git a/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts b/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts index b27639250..d5f0ebaaf 100644 --- a/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts @@ -10,7 +10,7 @@ import { import { FileDataModel } from '@models/file/file-data.model'; import { AppStateService } from '@state/app-state.service'; import { PermissionsService } from '@services/permissions.service'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; @Injectable() export class PdfViewerDataService { @@ -59,13 +59,7 @@ export class PdfViewerDataService { return of({ pages: [] }); } - downloadOriginalFile(fileStatus: FileStatusWrapper): Observable { - return this._fileManagementControllerService.downloadOriginalFile( - fileStatus.dossierId, - fileStatus.fileId, - true, - fileStatus.cacheIdentifier, - 'body' - ); + downloadOriginalFile(file: File): Observable { + return this._fileManagementControllerService.downloadOriginalFile(file.dossierId, file.fileId, true, file.cacheIdentifier, 'body'); } } diff --git a/apps/red-ui/src/app/modules/dossier/translations/file-status-translations.ts b/apps/red-ui/src/app/modules/dossier/translations/file-status-translations.ts index a72e50900..26432c048 100644 --- a/apps/red-ui/src/app/modules/dossier/translations/file-status-translations.ts +++ b/apps/red-ui/src/app/modules/dossier/translations/file-status-translations.ts @@ -1,7 +1,7 @@ import { FileStatus } from '@redaction/red-ui-http'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -export const fileStatusTranslations: { [key in FileStatus.StatusEnum]: string } = { +export const fileStatusTranslations: { [key in FileStatus]: string } = { APPROVED: _('file-status.approved'), DELETED: _('file-status.deleted'), ERROR: _('file-status.error'), diff --git a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts index 6ce9e9688..1d41ba93f 100644 --- a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; import { Dossier } from '../../../../../state/model/dossier'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { FileDownloadService } from '@upload-download/services/file-download.service'; import { Toaster } from '@iqser/common-ui'; import { AutoUnsubscribe, CircleButtonType, CircleButtonTypes } from '@iqser/common-ui'; @@ -18,7 +18,7 @@ export type MenuState = 'OPEN' | 'CLOSED'; }) export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestroy { @Input() dossier: Dossier; - @Input() file: FileStatusWrapper | FileStatusWrapper[]; + @Input() file: File | File[]; @Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above'; @Input() type: CircleButtonType = CircleButtonTypes.default; @Input() tooltipClass: string; 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 57716aea0..74230877b 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 @@ -4,7 +4,7 @@ import { interval, Observable } from 'rxjs'; import { ConfigService } from '@services/config.service'; import { TranslateService } from '@ngx-translate/core'; import { Dossier } from '@state/model/dossier'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { mergeMap, tap } from 'rxjs/operators'; import { DownloadStatusWrapper } from '../model/download-status.wrapper'; import { AppStateService } from '@state/app-state.service'; @@ -34,10 +34,10 @@ export class FileDownloadService { }); } - downloadFiles(fileStatusWrappers: FileStatusWrapper[], dossier: Dossier): Observable { + downloadFiles(files: File[], dossier: Dossier): Observable { return this._downloadControllerService .prepareDownload({ - fileIds: fileStatusWrappers.map(f => f.fileId), + fileIds: files.map(f => f.fileId), dossierId: dossier.id }) .pipe(mergeMap(() => this.getDownloadStatus())); diff --git a/apps/red-ui/src/app/services/permissions.service.ts b/apps/red-ui/src/app/services/permissions.service.ts index 56f13cc3d..02a6d9658 100644 --- a/apps/red-ui/src/app/services/permissions.service.ts +++ b/apps/red-ui/src/app/services/permissions.service.ts @@ -1,9 +1,9 @@ import { Injectable } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; import { UserService } from './user.service'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { Comment } from '@redaction/red-ui-http'; -import { Dossier } from '../state/model/dossier'; +import { Dossier } from '@state/model/dossier'; @Injectable({ providedIn: 'root' @@ -11,7 +11,7 @@ import { Dossier } from '../state/model/dossier'; export class PermissionsService { constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService) {} - private get _activeFile(): FileStatusWrapper | undefined { + private get _activeFile(): File | undefined { return this._appStateService.activeFile; } @@ -19,42 +19,39 @@ export class PermissionsService { return this._appStateService.activeDossier; } - isReviewerOrApprover(fileStatus?: FileStatusWrapper): boolean { - return this.isFileReviewer(fileStatus) || this.isApprover(); + isReviewerOrApprover(file?: File): boolean { + return this.isFileReviewer(file) || this.isApprover(); } displayReanalyseBtn(dossier = this._activeDossier): boolean { return this.isApprover(dossier) && dossier.files.filter(file => file.analysisRequired).length > 0; } - canToggleAnalysis(fileStatus: FileStatusWrapper): boolean { - return this.isReviewerOrApprover(fileStatus) && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status); + canToggleAnalysis(file: File): boolean { + return this.isReviewerOrApprover(file) && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status); } - canReanalyseFile(fileStatus = this._activeFile): boolean { - return ( - (fileStatus.analysisRequired && (this.isReviewerOrApprover(fileStatus) || fileStatus.isUnassigned)) || - (fileStatus.isError && fileStatus.isUnassigned) - ); + canReanalyseFile(file = this._activeFile): boolean { + return (file.analysisRequired && (this.isReviewerOrApprover(file) || file.isUnassigned)) || (file.isError && file.isUnassigned); } - isFileReviewer(fileStatus = this._activeFile): boolean { - return fileStatus.currentReviewer === this._userService.currentUser.id; + isFileReviewer(file = this._activeFile): boolean { + return file.currentReviewer === this._userService.currentUser.id; } - canDeleteFile(fileStatus = this._activeFile, dossier?: Dossier): boolean { - return (this.isOwner(dossier) && !fileStatus.isApproved) || fileStatus.isUnassigned; + canDeleteFile(file = this._activeFile, dossier?: Dossier): boolean { + return (this.isOwner(dossier) && !file.isApproved) || file.isUnassigned; } - canAssignToSelf(fileStatus = this._activeFile): boolean { - const precondition = this.isDossierMember() && !fileStatus.isProcessing && !fileStatus.isError && !fileStatus.isApproved; + canAssignToSelf(file = this._activeFile): boolean { + const precondition = this.isDossierMember() && !file.isProcessing && !file.isError && !file.isApproved; const isTheOnlyReviewer = !this._appStateService.activeDossier?.hasReviewers; if (precondition) { if ( - (fileStatus.isUnassigned || (fileStatus.isUnderReview && !this.isFileReviewer(fileStatus))) && - (this.isApprover() || isTheOnlyReviewer || (this.isDossierReviewer() && fileStatus.isUnassigned)) + (file.isUnassigned || (file.isUnderReview && !this.isFileReviewer(file))) && + (this.isApprover() || isTheOnlyReviewer || (this.isDossierReviewer() && file.isUnassigned)) ) { return true; } @@ -62,30 +59,30 @@ export class PermissionsService { return false; } - canAssignUser(fileStatus = this._activeFile): boolean { - const precondition = !fileStatus.isProcessing && !fileStatus.isError && !fileStatus.isApproved && this.isApprover(); + canAssignUser(file = this._activeFile): boolean { + const precondition = !file.isProcessing && !file.isError && !file.isApproved && this.isApprover(); if (precondition) { - if ((fileStatus.isUnassigned || fileStatus.isUnderReview) && this._activeDossier.hasReviewers) { + if ((file.isUnassigned || file.isUnderReview) && this._activeDossier.hasReviewers) { return true; } - if (fileStatus.isUnderApproval && this._activeDossier.approverIds.length > 1) { + if (file.isUnderApproval && this._activeDossier.approverIds.length > 1) { return true; } } return false; } - canSetUnderReview(fileStatus = this._activeFile): boolean { - return fileStatus?.isUnderApproval && this.isApprover(); + canSetUnderReview(file = this._activeFile): boolean { + return file?.isUnderApproval && this.isApprover(); } - isReadyForApproval(fileStatus = this._activeFile): boolean { - return this.canSetUnderReview(fileStatus); + isReadyForApproval(file = this._activeFile): boolean { + return this.canSetUnderReview(file); } - canSetUnderApproval(fileStatus = this._activeFile): boolean { - return fileStatus?.isUnderReview && this.isReviewerOrApprover(fileStatus); + canSetUnderApproval(file = this._activeFile): boolean { + return file?.isUnderReview && this.isReviewerOrApprover(file); } isOwner(dossier = this._activeDossier, user = this._userService.currentUser): boolean { @@ -104,25 +101,25 @@ export class PermissionsService { return dossier?.memberIds.includes(user.id); } - canPerformAnnotationActions(fileStatus = this._activeFile): boolean { - return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus?.status) && this.isFileReviewer(fileStatus); + canPerformAnnotationActions(file = this._activeFile): boolean { + return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file?.status) && this.isFileReviewer(file); } - canUndoApproval(fileStatus = this._activeFile): boolean { - return fileStatus?.isApproved && this.isApprover(); + canUndoApproval(file = this._activeFile): boolean { + return file?.isApproved && this.isApprover(); } - canMarkPagesAsViewed(fileStatus = this._activeFile): boolean { - return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus?.status) && this.isFileReviewer(fileStatus); + canMarkPagesAsViewed(file = this._activeFile): boolean { + return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file?.status) && this.isFileReviewer(file); } - canDownloadFiles(fileStatus = this._activeFile): boolean { - const dossier = this._appStateService.getDossierById(fileStatus?.dossierId); + canDownloadFiles(file = this._activeFile): boolean { + const dossier = this._appStateService.getDossierById(file?.dossierId); if (!dossier) { return false; } - return fileStatus.isApproved && this.isApprover(dossier); + return file.isApproved && this.isApprover(dossier); } canDeleteDossier(dossier = this._activeDossier): boolean { @@ -133,15 +130,15 @@ export class PermissionsService { return user.isAdmin; } - canAddComment(fileStatus = this._activeFile): boolean { - return (this.isFileReviewer(fileStatus) || this.isApprover()) && !fileStatus.isApproved; + canAddComment(file = this._activeFile): boolean { + return (this.isFileReviewer(file) || this.isApprover()) && !file.isApproved; } - canExcludePages(fileStatus = this._activeFile): boolean { - return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status) && (this.isFileReviewer(fileStatus) || this.isApprover()); + canExcludePages(file = this._activeFile): boolean { + return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status) && (this.isFileReviewer(file) || this.isApprover()); } - canDeleteComment(comment: Comment, fileStatus = this._activeFile) { - return (comment.user === this._userService.currentUser.id || this.isApprover()) && !fileStatus.isApproved; + canDeleteComment(comment: Comment, file = this._activeFile) { + return (comment.user === this._userService.currentUser.id || this.isApprover()) && !file.isApproved; } } 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 07f8844da..a10e59040 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -4,8 +4,8 @@ import { DossierTemplateControllerService, FileAttributesConfig, FileAttributesControllerService, - FileStatus, IDossier, + IFile, ReanalysisControllerService, StatusControllerService } from '@redaction/red-ui-http'; @@ -16,7 +16,7 @@ import { UserService } from '@services/user.service'; import { forkJoin, Observable, of, Subject } from 'rxjs'; import { catchError, map, tap } from 'rxjs/operators'; import { FALLBACK_COLOR, hexToRgb } from '@utils/functions'; -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { Dossier } from './model/dossier'; import { TypeValue } from '@models/file/type-value'; import { DossierTemplate } from '@models/file/dossier-template'; @@ -40,8 +40,8 @@ export interface AppState { providedIn: 'root' }) export class AppStateService { - readonly fileChanged$ = new Subject(); - readonly fileReanalysed$ = new Subject(); + readonly fileChanged$ = new Subject(); + readonly fileReanalysed$ = new Subject(); readonly dossierChanged$ = new Subject(); readonly dossierTemplateChanged$ = new Subject(); @@ -91,7 +91,7 @@ export class AppStateService { return this._dictionaryData; } - get aggregatedFiles(): FileStatusWrapper[] { + get aggregatedFiles(): File[] { return this.allDossiers.reduce((acc, { files }) => [...acc, ...files], []); } @@ -133,7 +133,7 @@ export class AppStateService { return this.allDossiers?.length > 0; } - get activeFile(): FileStatusWrapper | undefined { + get activeFile(): File | undefined { return this.activeDossier?.files.find(f => f.fileId === this.activeFileId); } @@ -242,7 +242,7 @@ export class AppStateService { const activeFile = await this._statusControllerService.getFileStatus(this.activeDossierId, this.activeFileId).toPromise(); activeFile.dossierTemplateId = dossierTemplateId; - const activeFileWrapper = new FileStatusWrapper( + const activeFileWrapper = new File( activeFile, this._userService.getNameForId(activeFile.currentReviewer), this.getFileAttributeConfig(activeFile.dossierTemplateId) @@ -659,12 +659,12 @@ export class AppStateService { await this._userPreferenceService.saveLastOpenedFileForDossier(dossierId, fileId); } - private _getExistingFiles(dossierId: string): FileStatusWrapper[] { + private _getExistingFiles(dossierId: string): File[] { const dossier = this.allDossiers.find(p => p.id === dossierId); return dossier?.files ?? []; } - private _processFiles(dossier: Dossier, files: FileStatus[], emitEvents: boolean = true) { + private _processFiles(dossier: Dossier, files: IFile[], emitEvents: boolean = true) { const oldFiles = [...dossier.files]; const fileStatusChangedEvent = []; @@ -677,7 +677,7 @@ export class AppStateService { for (const oldFile of oldFiles) { if (oldFile.fileId === file.fileId) { // emit when analysis count changed - const fileStatusWrapper = new FileStatusWrapper( + const fileStatusWrapper = new File( file, this._userService.getNameForId(file.currentReviewer), this.getFileAttributeConfig(file.dossierTemplateId) @@ -696,7 +696,7 @@ export class AppStateService { } // emit for new file if (!found) { - const fsw = new FileStatusWrapper( + const fsw = new File( file, this._userService.getNameForId(file.currentReviewer), this.getFileAttributeConfig(file.dossierTemplateId) @@ -707,11 +707,7 @@ export class AppStateService { dossier.files = files.map( file => - new FileStatusWrapper( - file, - this._userService.getNameForId(file.currentReviewer), - this.getFileAttributeConfig(file.dossierTemplateId) - ) + new File(file, this._userService.getNameForId(file.currentReviewer), this.getFileAttributeConfig(file.dossierTemplateId)) ); this._computeStats(); diff --git a/apps/red-ui/src/app/state/model/dossier.ts b/apps/red-ui/src/app/state/model/dossier.ts index f5fa74681..ea47c18e9 100644 --- a/apps/red-ui/src/app/state/model/dossier.ts +++ b/apps/red-ui/src/app/state/model/dossier.ts @@ -1,4 +1,4 @@ -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { Dictionary, DossierStatus, DownloadFileType, IDossier, List } from '@redaction/red-ui-http'; import { IListable } from '@iqser/common-ui'; @@ -36,7 +36,7 @@ export class Dossier implements IDossier, IListable { allFilesApproved?: boolean; type?: Dictionary; - constructor(dossier: IDossier, private _files: FileStatusWrapper[] = []) { + constructor(dossier: IDossier, private _files: File[] = []) { this.id = dossier.dossierId; this.dossierId = dossier.dossierId; this.approverIds = dossier.approverIds; @@ -63,11 +63,11 @@ export class Dossier implements IDossier, IListable { return this.dossierName; } - get files() { + get files(): File[] { return this._files; } - set files(files: FileStatusWrapper[]) { + set files(files: File[]) { this._files = files ? files : []; this._recomputeFileStatus(); } @@ -76,7 +76,7 @@ export class Dossier implements IDossier, IListable { return !!this._files.find(f => f.status === status); } - hasMember(memberId: string) { + hasMember(memberId: string): boolean { return this.memberIds.indexOf(memberId) >= 0; } diff --git a/apps/red-ui/src/app/utils/file-drop-utils.ts b/apps/red-ui/src/app/utils/file-drop-utils.ts index d9ea0c46c..fb0d1efa1 100644 --- a/apps/red-ui/src/app/utils/file-drop-utils.ts +++ b/apps/red-ui/src/app/utils/file-drop-utils.ts @@ -1,5 +1,5 @@ import { FileUploadModel } from '@upload-download/model/file-upload.model'; -import { Dossier } from '../state/model/dossier'; +import { Dossier } from '@state/model/dossier'; export function handleFileDrop(event: DragEvent, dossier: Dossier, uploadFiles: (files: FileUploadModel[]) => void) { event.preventDefault(); @@ -30,6 +30,8 @@ export function isCsv(file: FileUploadModel): boolean { return file.file.type?.toLowerCase() === 'text/csv' || file.file.name.toLowerCase().endsWith('.csv'); } +export type Files = FileList | File[]; + export function convertFiles(files: FileList | File[], dossier: Dossier): FileUploadModel[] { let uploadFiles: FileUploadModel[] = []; for (let i = 0; i < files.length; i++) { diff --git a/apps/red-ui/src/app/utils/filter-utils.ts b/apps/red-ui/src/app/utils/filter-utils.ts index cb5be195d..2763afba0 100644 --- a/apps/red-ui/src/app/utils/filter-utils.ts +++ b/apps/red-ui/src/app/utils/filter-utils.ts @@ -1,4 +1,4 @@ -import { FileStatusWrapper } from '@models/file/file-status.wrapper'; +import { File } from '@models/file/file'; import { Dossier } from '../state/model/dossier'; import { handleCheckedValue, INestedFilter } from '@iqser/common-ui'; @@ -45,7 +45,7 @@ export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INest }); } -export const annotationFilterChecker = (input: FileStatusWrapper | Dossier, filter: INestedFilter) => { +export const annotationFilterChecker = (input: File | Dossier, filter: INestedFilter) => { switch (filter.id) { case 'analysis': { if (input instanceof Dossier) { @@ -67,13 +67,13 @@ export const annotationFilterChecker = (input: FileStatusWrapper | Dossier, filt return input.hasNone; } case 'updated': { - return input instanceof FileStatusWrapper && input.hasUpdates; + return input instanceof File && input.hasUpdates; } case 'image': { - return input instanceof FileStatusWrapper && input.hasImages; + return input instanceof File && input.hasImages; } case 'comment': { - return input instanceof FileStatusWrapper && input.hasAnnotationComments; + return input instanceof File && input.hasAnnotationComments; } } }; diff --git a/apps/red-ui/src/app/utils/types.d.ts b/apps/red-ui/src/app/utils/types.d.ts index 5b10a4181..acc52b81e 100644 --- a/apps/red-ui/src/app/utils/types.d.ts +++ b/apps/red-ui/src/app/utils/types.d.ts @@ -1,3 +1,3 @@ import { FileStatus } from '@redaction/red-ui-http'; -export type Color = FileStatus.StatusEnum | DossierStatus.StatusEnum; +export type Color = FileStatus | DossierStatus.StatusEnum; diff --git a/libs/red-ui-http/src/lib/api/statusController.service.ts b/libs/red-ui-http/src/lib/api/statusController.service.ts index 8597d3038..d7afabc56 100644 --- a/libs/red-ui-http/src/lib/api/statusController.service.ts +++ b/libs/red-ui-http/src/lib/api/statusController.service.ts @@ -10,16 +10,16 @@ * Do not edit the class manually. */ /* tslint:disable:no-unused-variable member-ordering */ -import { Inject, Injectable, Optional } from '@angular/core'; -import { HttpClient, HttpEvent, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http'; -import { CustomHttpUrlEncodingCodec } from '../encoder'; +import { Inject, Injectable, Optional } from "@angular/core"; +import { HttpClient, HttpEvent, HttpHeaders, HttpParams, HttpResponse } from "@angular/common/http"; +import { CustomHttpUrlEncodingCodec } from "../encoder"; -import { Observable } from 'rxjs'; +import { Observable } from "rxjs"; -import { FileStatus } from '../model/fileStatus'; +import { IFile } from "../model/file"; -import { BASE_PATH } from '../variables'; -import { Configuration } from '../configuration'; +import { BASE_PATH } from "../variables"; +import { Configuration } from "../configuration"; @Injectable() export class StatusControllerService { @@ -48,13 +48,9 @@ export class StatusControllerService { * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. * @param reportProgress flag to report request and response progress. */ - public getDeletedFileStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable>; - public getDeletedFileStatus( - dossierId: string, - observe?: 'response', - reportProgress?: boolean - ): Observable>>; - public getDeletedFileStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable>>; + public getDeletedFileStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable>; + public getDeletedFileStatus(dossierId: string, observe?: 'response', reportProgress?: boolean): Observable>>; + public getDeletedFileStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable>>; public getDeletedFileStatus(dossierId: string, observe: any = 'body', reportProgress: boolean = false): Observable { if (dossierId === null || dossierId === undefined) { throw new Error('Required parameter dossierId was null or undefined when calling getDeletedFileStatus.'); @@ -76,7 +72,7 @@ export class StatusControllerService { headers = headers.set('Accept', httpHeaderAcceptSelected); } - return this.httpClient.request>( + return this.httpClient.request>( 'get', `${this.basePath}/status/softdeleted/${encodeURIComponent(String(dossierId))}`, { @@ -95,11 +91,11 @@ export class StatusControllerService { * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. * @param reportProgress flag to report request and response progress. */ - public getDossierStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable>; + public getDossierStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable>; - public getDossierStatus(dossierId: string, observe?: 'response', reportProgress?: boolean): Observable>>; + public getDossierStatus(dossierId: string, observe?: 'response', reportProgress?: boolean): Observable>>; - public getDossierStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable>>; + public getDossierStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable>>; public getDossierStatus(dossierId: string, observe: any = 'body', reportProgress: boolean = false): Observable { if (dossierId === null || dossierId === undefined) { @@ -122,7 +118,7 @@ export class StatusControllerService { headers = headers.set('Accept', httpHeaderAcceptSelected); } - return this.httpClient.request>('get', `${this.basePath}/status/${encodeURIComponent(String(dossierId))}`, { + return this.httpClient.request>('get', `${this.basePath}/status/${encodeURIComponent(String(dossierId))}`, { withCredentials: this.configuration.withCredentials, headers: headers, observe: observe, @@ -138,21 +134,16 @@ export class StatusControllerService { * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. * @param reportProgress flag to report request and response progress. */ - public getFileStatus(dossierId: string, fileId: string, observe?: 'body', reportProgress?: boolean): Observable; + public getFileStatus(dossierId: string, fileId: string, observe?: 'body', reportProgress?: boolean): Observable; public getFileStatus( dossierId: string, fileId: string, observe?: 'response', reportProgress?: boolean - ): Observable>; + ): Observable>; - public getFileStatus( - dossierId: string, - fileId: string, - observe?: 'events', - reportProgress?: boolean - ): Observable>; + public getFileStatus(dossierId: string, fileId: string, observe?: 'events', reportProgress?: boolean): Observable>; public getFileStatus(dossierId: string, fileId: string, observe: any = 'body', reportProgress: boolean = false): Observable { if (dossierId === null || dossierId === undefined) { @@ -179,7 +170,7 @@ export class StatusControllerService { headers = headers.set('Accept', httpHeaderAcceptSelected); } - return this.httpClient.request( + return this.httpClient.request( 'get', `${this.basePath}/status/${encodeURIComponent(String(dossierId))}/${encodeURIComponent(String(fileId))}`, { @@ -202,19 +193,19 @@ export class StatusControllerService { body: Array, observe?: 'body', reportProgress?: boolean - ): Observable<{ [key: string]: Array }>; + ): Observable<{ [key: string]: Array }>; public getFileStatusForDossiers( body: Array, observe?: 'response', reportProgress?: boolean - ): Observable }>>; + ): Observable }>>; public getFileStatusForDossiers( body: Array, observe?: 'events', reportProgress?: boolean - ): Observable }>>; + ): Observable }>>; public getFileStatusForDossiers(body: Array, observe: any = 'body', reportProgress: boolean = false): Observable { if (body === null || body === undefined) { @@ -244,7 +235,7 @@ export class StatusControllerService { headers = headers.set('Content-Type', httpContentTypeSelected); } - return this.httpClient.request<{ [key: string]: Array }>('post', `${this.basePath}/status`, { + return this.httpClient.request<{ [key: string]: Array }>('post', `${this.basePath}/status`, { body: body, withCredentials: this.configuration.withCredentials, headers: headers, diff --git a/libs/red-ui-http/src/lib/model/fileStatus.ts b/libs/red-ui-http/src/lib/model/file.ts similarity index 58% rename from libs/red-ui-http/src/lib/model/fileStatus.ts rename to libs/red-ui-http/src/lib/model/file.ts index 773c3cf48..1d5212519 100644 --- a/libs/red-ui-http/src/lib/model/fileStatus.ts +++ b/libs/red-ui-http/src/lib/model/file.ts @@ -14,43 +14,43 @@ import { FileAttributes } from './fileAttributes'; /** * Object containing information on a specific file. */ -export interface FileStatus { +export interface IFile { /** * Date and time when the file was added to the system. */ - added?: string; + readonly added?: string; /** * Shows if all manual changes have been applied by a reanalysis. */ - allManualRedactionsApplied?: boolean; + readonly allManualRedactionsApplied?: boolean; /** * Shows how long the last analysis took */ - analysisDuration?: number; + readonly analysisDuration?: number; /** * Shows if the file requires reanalysis. */ - analysisRequired?: boolean; + readonly analysisRequired?: boolean; /** * Shows the date of approval, if approved. */ - approvalDate?: string; + readonly approvalDate?: string; /** * The current reviewer's (if any) user id. */ - currentReviewer?: string; + readonly currentReviewer?: string; /** * Shows which dictionary versions was used during the analysis. */ - dictionaryVersion?: number; + readonly dictionaryVersion?: number; /** * Shows which dossier dictionary versions was used during the analysis. */ - dossierDictionaryVersion?: number; + readonly dossierDictionaryVersion?: number; /** * The ID of the dossier the file belongs to. */ - dossierId?: string; + readonly dossierId?: string; /** * The dossierTemplateId for this file. */ @@ -58,130 +58,116 @@ export interface FileStatus { /** * Shows if the file was excluded from analysis. */ - excluded?: boolean; + readonly excluded?: boolean; /** * Set of excluded pages for this file. */ - excludedPages?: Array; + readonly excludedPages?: Array; fileAttributes?: FileAttributes; /** * The ID of the file. */ - fileId?: string; + readonly fileId?: string; /** * The file's name. */ - filename?: string; + readonly filename?: string; /** * Shows if this file has comments on annotations. */ - hasAnnotationComments?: boolean; + readonly hasAnnotationComments?: boolean; /** * Shows if any hints were found during the analysis. */ - hasHints?: boolean; + readonly hasHints?: boolean; /** * Shows if any images were found during the analysis. */ - hasImages?: boolean; + readonly hasImages?: boolean; /** * Shows if any redactions were found during the analysis. */ - hasRedactions?: boolean; + readonly hasRedactions?: boolean; /** * Shows if any requests were found during the analysis. */ - hasRequests?: boolean; + readonly hasRequests?: boolean; /** * Shows if there are any Suggestions in this file. */ - hasSuggestions?: boolean; + readonly hasSuggestions?: boolean; /** * Shows if there is any change between the previous and current analysis. */ - hasUpdates?: boolean; + readonly hasUpdates?: boolean; /** * Date and time when the files attributes was last updated. */ - lastFileAttributeChange?: string; + readonly lastFileAttributeChange?: string; /** * Shows if this file has been OCRed by us. Last Time of OCR. */ - lastOCRTime?: string; + readonly lastOCRTime?: string; /** * Shows the last date of a successful analysis. */ - lastProcessed?: string; + readonly lastProcessed?: string; /** * The last reviewer's (if any) user id. */ - lastReviewer?: string; + readonly lastReviewer?: string; /** * Date and time when the file was last updated. */ - lastUpdated?: string; + readonly lastUpdated?: string; /** * Shows last date the document was uploaded. */ - lastUploaded?: string; + readonly lastUploaded?: string; /** * Shows which legal basis versions was used during the analysis. */ - legalBasisVersion?: number; + readonly legalBasisVersion?: number; /** * The number of times the file has been analyzed. */ - numberOfAnalyses?: number; + readonly numberOfAnalyses?: number; /** * The number of pages of the file. */ - numberOfPages?: number; + readonly numberOfPages?: number; /** * Shows which rules versions was used during the analysis. */ - rulesVersion?: number; + readonly rulesVersion?: number; /** * Shows if the file is soft deleted. */ - softDeleted?: string; + readonly softDeleted?: string; /** * The status of the file with regard to its analysis an review processes. */ - status?: FileStatus.StatusEnum; + readonly status?: FileStatus; /** * The ID of the user who uploaded the file. */ - uploader?: string; + readonly uploader?: string; } -export namespace FileStatus { - export type StatusEnum = - | 'APPROVED' - | 'DELETED' - | 'ERROR' - | 'EXCLUDED' - | 'FULLREPROCESS' - | 'INDEXING' - | 'OCR_PROCESSING' - | 'PROCESSING' - | 'REPROCESS' - | 'UNASSIGNED' - | 'UNDER_APPROVAL' - | 'UNDER_REVIEW' - | 'UNPROCESSED'; - export const StatusEnum = { - APPROVED: 'APPROVED' as StatusEnum, - DELETED: 'DELETED' as StatusEnum, - ERROR: 'ERROR' as StatusEnum, - EXCLUDED: 'EXCLUDED' as StatusEnum, - FULLREPROCESS: 'FULLREPROCESS' as StatusEnum, - INDEXING: 'INDEXING' as StatusEnum, - OCRPROCESSING: 'OCR_PROCESSING' as StatusEnum, - PROCESSING: 'PROCESSING' as StatusEnum, - REPROCESS: 'REPROCESS' as StatusEnum, - UNASSIGNED: 'UNASSIGNED' as StatusEnum, - UNDERAPPROVAL: 'UNDER_APPROVAL' as StatusEnum, - UNDERREVIEW: 'UNDER_REVIEW' as StatusEnum, - UNPROCESSED: 'UNPROCESSED' as StatusEnum - } as const; -} +export const FileStatuses = { + APPROVED: 'APPROVED', + DELETED: 'DELETED', + ERROR: 'ERROR', + EXCLUDED: 'EXCLUDED', + FULLREPROCESS: 'FULLREPROCESS', + INDEXING: 'INDEXING', + OCR_PROCESSING: 'OCR_PROCESSING', + PROCESSING: 'PROCESSING', + REPROCESS: 'REPROCESS', + UNASSIGNED: 'UNASSIGNED', + UNDER_APPROVAL: 'UNDER_APPROVAL', + UNDER_REVIEW: 'UNDER_REVIEW', + UNPROCESSED: 'UNPROCESSED' +} as const; + +export type FileStatus = keyof typeof FileStatuses; diff --git a/libs/red-ui-http/src/lib/model/models.ts b/libs/red-ui-http/src/lib/model/models.ts index e45355189..0bea96612 100644 --- a/libs/red-ui-http/src/lib/model/models.ts +++ b/libs/red-ui-http/src/lib/model/models.ts @@ -31,7 +31,7 @@ export * from './downloadStatusResponse'; export * from './fileAttributeConfig'; export * from './fileAttributes'; export * from './fileAttributesConfig'; -export * from './fileStatus'; +export * from './file'; export * from './fileUploadResult'; export * from './forceRedactionRequest'; export * from './generalConfigurationModel'; diff --git a/libs/red-ui-http/src/lib/model/reportData.ts b/libs/red-ui-http/src/lib/model/reportData.ts index 562ac25f1..d5fba5555 100644 --- a/libs/red-ui-http/src/lib/model/reportData.ts +++ b/libs/red-ui-http/src/lib/model/reportData.ts @@ -41,12 +41,12 @@ export namespace ReportData { ERROR: 'ERROR' as StatusEnum, EXCLUDED: 'EXCLUDED' as StatusEnum, FULLREPROCESS: 'FULLREPROCESS' as StatusEnum, - OCRPROCESSING: 'OCR_PROCESSING' as StatusEnum, + OCR_PROCESSING: 'OCR_PROCESSING' as StatusEnum, PROCESSING: 'PROCESSING' as StatusEnum, REPROCESS: 'REPROCESS' as StatusEnum, UNASSIGNED: 'UNASSIGNED' as StatusEnum, - UNDERAPPROVAL: 'UNDER_APPROVAL' as StatusEnum, - UNDERREVIEW: 'UNDER_REVIEW' as StatusEnum, + UNDER_APPROVAL: 'UNDER_APPROVAL' as StatusEnum, + UNDER_REVIEW: 'UNDER_REVIEW' as StatusEnum, UNPROCESSED: 'UNPROCESSED' as StatusEnum }; } diff --git a/package.json b/package.json index d574ce9fb..e76a3957f 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "lint": "nx workspace-lint && nx lint", "lint-fix": "nx workspace-lint --fix && nx lint --fix", "nx": "nx", - "start": "nx serve", + "start": "nx serve --hmr", "test": "nx test", "update": "nx migrate latest", "migrate": "nx migrate --run-migrations",