diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.html b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.html index 09ba451ce..9f2a66a30 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.html +++ b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.html @@ -61,7 +61,7 @@ *ngFor="let config of statusConfig" [attr.help-mode-key]="'dashboard_in_dossier'" [config]="config" - filterKey="processingTypeFilters" + [filterKey]="PendingTypes[config.id] ? 'pendingTypeFilters' : 'processingTypeFilters'" > diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts index 75c7cf9d5..860be6f33 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts @@ -21,7 +21,9 @@ import { DossierAttributeWithValue, DossierStats, File, + FileErrorCodes, IDossierRequest, + PendingTypes, ProcessingTypes, StatusSorter, User, @@ -74,6 +76,7 @@ export class DossierDetailsComponent extends ContextComponent file.errorCode === FileErrorCodes.LOCKED_RULES).length; + const numberOfTimeoutFiles = files.filter(file => file.errorCode === FileErrorCodes.RULES_EXECUTION_TIMEOUT).length; + const numberOfUnknownErrorFiles = stats.processingStats.pending - numberOfRulesLockedFiles - numberOfTimeoutFiles; return [ { id: ProcessingTypes.pending, @@ -161,6 +168,27 @@ export class DossierDetailsComponent extends ContextComponent
-
+
diff --git a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts index 7ffebb28c..b74de56a6 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts @@ -24,6 +24,7 @@ import { FileAttributeConfigType, FileAttributeConfigTypes, IFileAttributeConfig, + PendingType, ProcessingType, StatusSorter, User, @@ -184,6 +185,7 @@ export class ConfigService { const allDistinctPeople = new Set(); const allDistinctNeedsWork = new Set(); const allDistinctProcessingTypes = new Set(); + const allDistinctPendingTypes = new Set(); const dynamicFilters = new Map }>(); @@ -216,6 +218,7 @@ export class ConfigService { } allDistinctProcessingTypes.add(file.processingType); + allDistinctPendingTypes.add(file.pendingType); // extract values for dynamic filters fileAttributeConfigs.forEach(config => { @@ -317,6 +320,14 @@ export class ConfigService { hide: true, }); + const pendingTypesFilters = [...allDistinctPendingTypes].map(item => new NestedFilter({ id: item, label: item })); + filterGroups.push({ + slug: 'pendingTypeFilters', + filters: pendingTypesFilters, + checker: (file: File, filter: INestedFilter) => file.pendingType === filter.id, + hide: true, + }); + dynamicFilters.forEach((value: { filterValue: Set; type: FileAttributeConfigType }, filterKey: string) => { const id = filterKey.split(':')[0]; const key = filterKey.split(':')[1]; diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index b169ead13..6e622586d 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -987,7 +987,7 @@ "download-file-disabled": "Download: Sie müssen Genehmiger im Dossier sein und die initiale Verarbeitung {count, plural, one{der Datei} other{der Dateien}} muss abgeschlossen sein.", "file-listing": { "file-entry": { - "file-error": "Reanalyse erforderlich", + "file-error": "Reanalyse erforderlich ({errorCode, select, RULES_EXECUTION_TIMEOUT{Zeitlimit für Regeln} LOCKED_RULES{Regeln gesperrt} other{unbekannt}})", "file-pending": "Ausstehend ..." } }, @@ -1463,7 +1463,7 @@ "save": { "error": "Erstellung der Datei-Attribute fehlgeschlagen.", "label": "Attribute speichern", - "success": "{count} Datei-{count, plural, one{Attribut} other{Attribute}} erfolgreich erstellt!" + "success": "{count} Datei-{count, plural, one{Attribut} other{Attribute}} erfolgreich erstellt." }, "search": { "placeholder": "Nach Spaltennamen suchen..." @@ -2101,6 +2101,9 @@ "processing-status": { "ocr": "OCR", "pending": "Ausstehend", + "pending-locked-rules": "Ausstehend (Regeln gesperrt)", + "pending-timeout": "Ausstehend (Zeitlimit für Regeln)", + "pending-unknown": "Ausstehend (unbekannt)", "processed": "Verarbeitet", "processing": "Verarbeitung läuft" }, @@ -2371,8 +2374,8 @@ "inactive": "Inaktiv", "manager-admin": "{count, plural, one{Manager & Admin} other{Manager & Admins}}", "no-role": "Keine Rolle definiert", - "red-admin": "Anwendungsadmin", - "red-manager": "Manager", + "red-admin": "{count, plural, one{Anwendungsadmin} other{Anwendungsadmins}}", + "red-manager": "{count, plural, one{Manager} other{Manager}}", "red-user": "Benutzer", "red-user-admin": "{count, plural, one{Benutzeradmin} other{Benutzeradmins}}", "regular": "{number, plural, one{{regulärer Benutzer}} other{reguläre Benutzer}}" diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 98ee2dfb8..39ae0b693 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -987,7 +987,7 @@ "download-file-disabled": "To download, ensure you are an approver in the dossier, and the {count, plural, one{file has undergone} other{files have undergone}} initial processing.", "file-listing": { "file-entry": { - "file-error": "Re-processing required", + "file-error": "Re-processing required ({errorCode, select, RULES_EXECUTION_TIMEOUT{Rules timeout} LOCKED_RULES{Rules locked} other{unknown}})", "file-pending": "Pending..." } }, @@ -2101,6 +2101,9 @@ "processing-status": { "ocr": "OCR", "pending": "Pending", + "pending-locked-rules": "Pending (Rules locked)", + "pending-timeout": "Pending (Rules timeout)", + "pending-unknown": "Pending (unknown)", "processed": "Processed", "processing": "Processing" }, diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 8816f8ac5..18c81a721 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -987,7 +987,7 @@ "download-file-disabled": "Download: Sie müssen Genehmiger im Dossier sein und die initiale Verarbeitung {count, plural, one{der Datei} other{der Dateien}} muss abgeschlossen sein.", "file-listing": { "file-entry": { - "file-error": "Reanalyse erforderlich", + "file-error": "Reanalyse erforderlich ({errorCode, select, RULES_EXECUTION_TIMEOUT{Zeitlimit für Regeln} LOCKED_RULES{Regeln gesperrt} other{unbekannt}})", "file-pending": "Ausstehend ..." } }, @@ -1385,7 +1385,7 @@ }, "file": { "action": "Zurück zum Dossier", - "label": "Diese Datei wurde gelöscht!" + "label": "Diese Datei wurde gelöscht." } }, "file-preview": { @@ -2101,6 +2101,9 @@ "processing-status": { "ocr": "OCR", "pending": "Ausstehend", + "pending-locked-rules": "Ausstehend (Regeln gesperrt)", + "pending-timeout": "Ausstehend (Zeitlimit für Regeln)", + "pending-unknown": "Ausstehend (unbekannt)", "processed": "Verarbeitet", "processing": "Verarbeitung läuft" }, @@ -2294,7 +2297,7 @@ } } }, - "invalid-upload": "Ungültiges Upload-Format ausgewählt! Unterstützt werden Dokumente im .xlsx- und im .docx-Format", + "invalid-upload": "Ungültiges Upload-Format ausgewählt. Unterstützte Formate: .xlsx- und .docx", "multi-file-report": "(Mehrere Dateien)", "report-documents": "Berichtsvorlagen", "setup": "Dieser Platzhalter wird durch die Nummer der Seite ersetzt, auf der sich die Schwärzung befindet.", diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index b79b765ba..19b317511 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -987,7 +987,7 @@ "download-file-disabled": "To download, ensure you are an approver in the dossier, and the {count, plural, one{file has undergone} other{files have undergone}} initial processing.", "file-listing": { "file-entry": { - "file-error": "Re-processing required", + "file-error": "Re-processing required ({errorCode, select, RULES_EXECUTION_TIMEOUT{Rules timeout} LOCKED_RULES{Rules locked} other{unknown}})", "file-pending": "Pending..." } }, @@ -2101,6 +2101,9 @@ "processing-status": { "ocr": "OCR", "pending": "Pending", + "pending-locked-rules": "Pending (Rules locked)", + "pending-timeout": "Pending (Rules timeout)", + "pending-unknown": "Pending (unknown)", "processed": "Processed", "processing": "Processing" }, diff --git a/libs/red-domain/src/lib/dossier-stats/dossier-stats.model.ts b/libs/red-domain/src/lib/dossier-stats/dossier-stats.model.ts index 7a9a2e4ea..61dd2e548 100644 --- a/libs/red-domain/src/lib/dossier-stats/dossier-stats.model.ts +++ b/libs/red-domain/src/lib/dossier-stats/dossier-stats.model.ts @@ -1,22 +1,6 @@ -import { - isProcessingStatuses, - OCR_STATES, - PENDING_STATES, - PROCESSED_STATES, - PROCESSING_STATES, - ProcessingFileStatus, -} from '../files/types'; +import { isProcessingStatuses, OCR_STATES, PENDING_STATES, PROCESSED_STATES, PROCESSING_STATES, ProcessingFileStatus } from '../files'; import { IDossierStats } from './dossier-stats'; -import { FileCountPerProcessingStatus, FileCountPerWorkflowStatus } from './types'; - -export const ProcessingTypes = { - pending: 'pending', - ocr: 'ocr', - processing: 'processing', - processed: 'processed', -} as const; - -export type ProcessingType = keyof typeof ProcessingTypes; +import { FileCountPerProcessingStatus, FileCountPerWorkflowStatus, ProcessingType } from './types'; export type ProcessingStats = Record; diff --git a/libs/red-domain/src/lib/dossier-stats/types.ts b/libs/red-domain/src/lib/dossier-stats/types.ts index b57ca4ecd..04f2e4684 100644 --- a/libs/red-domain/src/lib/dossier-stats/types.ts +++ b/libs/red-domain/src/lib/dossier-stats/types.ts @@ -1,4 +1,21 @@ -import { ProcessingFileStatus, WorkflowFileStatus } from '../files/types'; +import { ProcessingFileStatus, WorkflowFileStatus } from '../files'; export type FileCountPerWorkflowStatus = { [key in WorkflowFileStatus]?: number }; export type FileCountPerProcessingStatus = { [key in ProcessingFileStatus]?: number }; + +export const ProcessingTypes = { + pending: 'pending', + ocr: 'ocr', + processing: 'processing', + processed: 'processed', +} as const; + +export type ProcessingType = keyof typeof ProcessingTypes; + +export const PendingTypes = { + lockedRules: 'lockedRules', + timeout: 'timeout', + unknown: 'unknown', +} as const; + +export type PendingType = keyof typeof PendingTypes; diff --git a/libs/red-domain/src/lib/files/file.model.ts b/libs/red-domain/src/lib/files/file.model.ts index 5146f18fb..181b614d9 100644 --- a/libs/red-domain/src/lib/files/file.model.ts +++ b/libs/red-domain/src/lib/files/file.model.ts @@ -1,10 +1,12 @@ import { Entity } from '@iqser/common-ui'; -import { ProcessingType, ProcessingTypes } from '../dossier-stats/dossier-stats.model'; -import { ARCHIVE_ROUTE, DOSSIERS_ROUTE } from '../dossiers/constants'; -import { FileAttributes } from '../file-attributes/file-attributes'; -import { StatusSorter } from '../shared/sorters/status-sorter'; +import { PendingType, PendingTypes, ProcessingType, ProcessingTypes } from '../dossier-stats'; +import { ARCHIVE_ROUTE, DOSSIERS_ROUTE } from '../dossiers'; +import { FileAttributes } from '../file-attributes'; +import { StatusSorter } from '../shared'; import { IFile } from './file'; import { + FileErrorCode, + FileErrorCodes, isFullProcessingStatuses, isProcessingStatuses, OCR_STATES, @@ -81,6 +83,8 @@ export class File extends Entity implements IFile { readonly canBeOCRed: boolean; readonly processingType: ProcessingType; + readonly errorCode?: FileErrorCode; + readonly pendingType?: PendingType; constructor( file: IFile, @@ -120,7 +124,7 @@ export class File extends Entity implements IFile { this.workflowStatus = file.workflowStatus; this.isError = this.processingStatus === ProcessingFileStatuses.ERROR; this.isUnprocessed = this.processingStatus === ProcessingFileStatuses.UNPROCESSED; - this.numberOfPages = this.isError ? 0 : file.numberOfPages ?? 0; + this.numberOfPages = this.isError ? 0 : (file.numberOfPages ?? 0); this.rulesVersion = file.rulesVersion; this.uploader = file.uploader; this.excludedPages = file.excludedPages || []; @@ -157,6 +161,8 @@ export class File extends Entity implements IFile { file.fileAttributes && file.fileAttributes.attributeIdToValue ? file.fileAttributes : { attributeIdToValue: {} }; this.processingType = this.#processingType; + this.errorCode = file.fileErrorInfo?.errorCode; + this.pendingType = this.processingType === ProcessingTypes.pending ? this.#pendingType : undefined; } get deleted(): boolean { @@ -189,6 +195,16 @@ export class File extends Entity implements IFile { return ProcessingTypes.processed; } + get #pendingType(): PendingType { + if (this.errorCode === FileErrorCodes.LOCKED_RULES) { + return PendingTypes.lockedRules; + } + if (this.errorCode === FileErrorCodes.RULES_EXECUTION_TIMEOUT) { + return PendingTypes.timeout; + } + return PendingTypes.unknown; + } + isPageExcluded(page: number): boolean { return this.excludedPages.includes(page); } diff --git a/libs/red-domain/src/lib/files/file.ts b/libs/red-domain/src/lib/files/file.ts index 1a06145ea..1c0d3c9fa 100644 --- a/libs/red-domain/src/lib/files/file.ts +++ b/libs/red-domain/src/lib/files/file.ts @@ -2,7 +2,7 @@ * Object containing information on a specific file. */ import { FileAttributes } from '../file-attributes'; -import { ProcessingFileStatus, WorkflowFileStatus } from './types'; +import { FileErrorInfo, ProcessingFileStatus, WorkflowFileStatus } from './types'; export interface IFile { /** @@ -147,4 +147,5 @@ export interface IFile { readonly fileManipulationDate: string | null; readonly redactionModificationDate: string | null; readonly lastManualChangeDate?: string; + readonly fileErrorInfo?: FileErrorInfo; } diff --git a/libs/red-domain/src/lib/files/types.ts b/libs/red-domain/src/lib/files/types.ts index 2a3844918..b189186c6 100644 --- a/libs/red-domain/src/lib/files/types.ts +++ b/libs/red-domain/src/lib/files/types.ts @@ -96,3 +96,18 @@ export const PROCESSING_STATES: ProcessingFileStatus[] = [ export const PROCESSED_STATES: ProcessingFileStatus[] = [ProcessingFileStatuses.PROCESSED]; export const OCR_STATES: ProcessingFileStatus[] = [ProcessingFileStatuses.OCR_PROCESSING, ProcessingFileStatuses.OCR_PROCESSING_QUEUED]; + +export const FileErrorCodes = { + RULES_EXECUTION_TIMEOUT: 'RULES_EXECUTION_TIMEOUT', + LOCKED_RULES: 'LOCKED_RULES', +} as const; + +export type FileErrorCode = keyof typeof FileErrorCodes; + +export interface FileErrorInfo { + cause: string; + queue: string; + service: string; + timestamp: string; + errorCode?: FileErrorCode; +}