From 887157e58828912a52977b3cf61905441dd5a1b4 Mon Sep 17 00:00:00 2001 From: Nicoleta Panaghiu Date: Wed, 20 Nov 2024 12:20:44 +0200 Subject: [PATCH] RED-10405: added labels and filtering for timeout pending type. --- .../dossier-details.component.html | 3 +- .../dossier-details.component.scss | 4 +++ .../dossier-details.component.ts | 31 +++++++++++-------- .../table-item/table-item.component.html | 11 +++++-- .../dossier-overview/config.service.ts | 11 +++++++ apps/red-ui/src/assets/i18n/redact/de.json | 3 +- apps/red-ui/src/assets/i18n/redact/en.json | 3 +- apps/red-ui/src/assets/i18n/scm/de.json | 3 +- apps/red-ui/src/assets/i18n/scm/en.json | 3 +- .../lib/dossier-stats/dossier-stats.model.ts | 20 ++---------- .../red-domain/src/lib/dossier-stats/types.ts | 15 +++++++++ libs/red-domain/src/lib/files/file.model.ts | 21 ++++++++++--- libs/red-domain/src/lib/files/file.ts | 3 +- libs/red-domain/src/lib/files/types.ts | 15 +++++++++ 14 files changed, 102 insertions(+), 44 deletions(-) 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..3670a7aff 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,8 @@ *ngFor="let config of statusConfig" [attr.help-mode-key]="'dashboard_in_dossier'" [config]="config" - filterKey="processingTypeFilters" + [class.indent]="!!PendingTypes[config.id]" + [filterKey]="PendingTypes[config.id] ? 'pendingTypeFilters' : 'processingTypeFilters'" > diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.scss b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.scss index e415ad1bc..8a1d20f28 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.scss +++ b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.scss @@ -45,3 +45,7 @@ iqser-progress-bar:not(:last-child) { margin-bottom: 10px; } + +.indent { + margin-left: 32px; +} 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..28b16bab9 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 @@ -1,15 +1,7 @@ import { AsyncPipe, NgForOf, NgIf, NgTemplateOutlet } from '@angular/common'; import { Component, EventEmitter, Input, Output } from '@angular/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { - CircleButtonComponent, - CircleButtonTypes, - getConfig, - IqserAllowDirective, - IqserLoadingModule, - ProgressBarConfigModel, - Toaster, -} from '@iqser/common-ui'; +import { CircleButtonComponent, CircleButtonTypes, getConfig, IqserLoadingModule, ProgressBarConfigModel, Toaster } from '@iqser/common-ui'; import { FilterService, INestedFilter } from '@iqser/common-ui/lib/filtering'; import { getCurrentUser, InitialsAvatarComponent } from '@iqser/common-ui/lib/users'; import { ContextComponent, getParam, IqserTooltipPositions, shareLast } from '@iqser/common-ui/lib/utils'; @@ -21,7 +13,9 @@ import { DossierAttributeWithValue, DossierStats, File, + FileErrorCodes, IDossierRequest, + PendingTypes, ProcessingTypes, StatusSorter, User, @@ -58,7 +52,6 @@ interface DossierDetailsContext { NgIf, AsyncPipe, CircleButtonComponent, - IqserAllowDirective, TranslateModule, DonutChartComponent, IqserLoadingModule, @@ -74,6 +67,7 @@ export class DossierDetailsComponent extends ContextComponent this.#calculateChartConfig(stats)), map(([stats]) => stats), ); - const statusConfig$ = dossierStats$.pipe(map(stats => this.#calculateStatusConfig(stats))); - + const statusConfig$ = dossierStats$.pipe( + combineLatestWith(files$), + map(([stats, files]) => this.#calculateStatusConfig(stats, files)), + ); super._initContext({ needsWorkFilters: filterService.getFilterModels$('needsWorkFilters'), dossier: dossier$, @@ -152,7 +149,8 @@ export class DossierDetailsComponent extends ContextComponent sum + file.numberOfPages, 0); } - #calculateStatusConfig(stats: DossierStats): ProgressBarConfigModel[] { + #calculateStatusConfig(stats: DossierStats, files: File[]): ProgressBarConfigModel[] { + const numberOfTimeoutFiles = files.filter(file => file.errorCode === FileErrorCodes.RULES_EXECUTION_TIMEOUT).length; return [ { id: ProcessingTypes.pending, @@ -161,6 +159,13 @@ export class DossierDetailsComponent extends ContextComponent
-
+
@@ -61,8 +66,8 @@ [configs]="[ { color: file.workflowStatus, - length: 1 - } + length: 1, + }, ]" > 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 52bbab8ef..0408fc607 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -969,7 +969,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)} other{}}", "file-pending": "Ausstehend ..." } }, @@ -2041,6 +2041,7 @@ "processing-status": { "ocr": "OCR", "pending": "Ausstehend", + "pending-timeout": "Ausstehend (Zeitlimit für Regeln)", "processed": "verarbeitet", "processing": "Verarbeitung läuft" }, diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 55c80de2c..f4685adcd 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -969,7 +969,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)} other{}}", "file-pending": "Pending..." } }, @@ -2041,6 +2041,7 @@ "processing-status": { "ocr": "OCR", "pending": "Pending", + "pending-timeout": "Pending (Rules timeout)", "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 f953ab37a..c2acb53cc 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -969,7 +969,7 @@ "download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.", "file-listing": { "file-entry": { - "file-error": "Reanalyse erforderlich", + "file-error": "Reanalyse erforderlich {errorCode, select, RULES_EXECUTION_TIMEOUT{(Zeitlimit für Regeln)} other{}}", "file-pending": "Ausstehend ..." } }, @@ -2041,6 +2041,7 @@ "processing-status": { "ocr": "OCR", "pending": "Pending", + "pending-timeout": "Ausstehend (Zeitlimit für Regeln)", "processed": "Processed", "processing": "Processing" }, diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index c1ebf8c4b..765d4015c 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -969,7 +969,7 @@ "download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.", "file-listing": { "file-entry": { - "file-error": "Re-processing required", + "file-error": "Re-processing required {errorCode, select, RULES_EXECUTION_TIMEOUT{(Rules timeout)} other{}}", "file-pending": "Pending..." } }, @@ -2041,6 +2041,7 @@ "processing-status": { "ocr": "OCR", "pending": "Pending", + "pending-timeout": "Pending (Rules timeout)", "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..516aaca96 100644 --- a/libs/red-domain/src/lib/dossier-stats/types.ts +++ b/libs/red-domain/src/lib/dossier-stats/types.ts @@ -2,3 +2,18 @@ import { ProcessingFileStatus, WorkflowFileStatus } from '../files/types'; 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 = { + timeout: 'timeout', +} 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..fdedd8bc0 100644 --- a/libs/red-domain/src/lib/files/file.model.ts +++ b/libs/red-domain/src/lib/files/file.model.ts @@ -1,10 +1,11 @@ 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 { 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, @@ -15,6 +16,7 @@ import { WorkflowFileStatus, WorkflowFileStatuses, } from './types'; +import { PendingType, PendingTypes, ProcessingType, ProcessingTypes } from '../dossier-stats'; export class File extends Entity implements IFile { readonly added?: string; @@ -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, @@ -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 = this.isError ? file.fileErrorInfo?.errorCode : undefined; + this.pendingType = this.processingType === ProcessingTypes.pending ? this.#pendingType : undefined; } get deleted(): boolean { @@ -176,6 +182,13 @@ export class File extends Entity implements IFile { return this.canBeOpened ? `/main/${this.dossierTemplateId}/${routerPath}/${this.dossierId}/file/${this.fileId}` : undefined; } + get #pendingType(): PendingType | undefined { + if (this.errorCode === FileErrorCodes.RULES_EXECUTION_TIMEOUT) { + return PendingTypes.timeout; + } + return undefined; + } + get #processingType(): ProcessingType { if (PENDING_STATES.includes(this.processingStatus)) { return ProcessingTypes.pending; 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; +}