From 5427de6f586da4a06fe7ba3dfa0b42505a2fbcd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Thu, 14 Jul 2022 12:43:38 +0300 Subject: [PATCH] RED-4639: Refactor annotation colors --- .../src/app/models/file/annotation.wrapper.ts | 42 +++---- .../edit-color-dialog.component.ts | 20 +-- .../default-colors-screen.component.html | 10 +- .../default-colors-screen.component.ts | 69 +++-------- .../entities-listing-screen.component.html | 2 +- .../file-workload/file-workload.component.ts | 22 ++-- .../dossier-overview/config.service.ts | 9 +- .../dossier-overview-screen.component.ts | 1 + .../dossier-workload-column.component.ts | 10 +- .../annotation-card.component.html | 4 +- .../file-preview-screen.component.ts | 4 +- .../services/annotation-actions.service.ts | 2 +- .../services/annotation-processing.service.ts | 22 ++-- .../services/file-data.service.ts | 6 +- .../services/pdf-proxy.service.ts | 12 +- .../services/annotation-draw.service.ts | 30 ++--- .../type-filter/type-filter.component.ts | 11 +- .../dossier-templates.service.ts | 7 +- .../entity-services/default-colors.service.ts | 38 ++++++ .../dictionaries-map.service.ts | 20 --- .../entity-services/dictionary.service.ts | 114 +++--------------- .../annotation-types-translations.ts | 2 +- .../app/utils/sorters/super-type-sorter.ts | 2 +- libs/red-domain/src/index.ts | 1 + .../src/lib/colors/annotation-color-config.ts | 48 ++++++++ .../src/lib/colors/default-color-type.ts | 15 +++ .../src/lib/colors/default-colors.model.ts | 43 +++++++ .../src/lib/colors/default-colors.ts | 3 + libs/red-domain/src/lib/colors/index.ts | 4 + .../red-domain/src/lib/dictionaries/colors.ts | 14 --- libs/red-domain/src/lib/dictionaries/index.ts | 1 - libs/red-domain/src/lib/files/index.ts | 1 + .../red-domain/src/lib/files}/super-types.ts | 2 +- .../src/lib/shared/default-color-type.ts | 3 - libs/red-domain/src/lib/shared/index.ts | 1 - 35 files changed, 306 insertions(+), 289 deletions(-) create mode 100644 apps/red-ui/src/app/services/entity-services/default-colors.service.ts create mode 100644 libs/red-domain/src/lib/colors/annotation-color-config.ts create mode 100644 libs/red-domain/src/lib/colors/default-color-type.ts create mode 100644 libs/red-domain/src/lib/colors/default-colors.model.ts create mode 100644 libs/red-domain/src/lib/colors/default-colors.ts create mode 100644 libs/red-domain/src/lib/colors/index.ts delete mode 100644 libs/red-domain/src/lib/dictionaries/colors.ts rename {apps/red-ui/src/app/models/file => libs/red-domain/src/lib/files}/super-types.ts (100%) delete mode 100644 libs/red-domain/src/lib/shared/default-color-type.ts diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index c772b3163..481eeca19 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -1,26 +1,27 @@ import { annotationTypesTranslations, SuggestionAddFalsePositive } from '@translations/annotation-types-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { + annotationDefaultColorConfig, + annotationEntityColorConfig, AnnotationIconType, + DefaultColors, Dictionary, + FalsePositiveSuperTypes, Highlight, IComment, IManualChange, IPoint, IRectangle, LogEntryStatus, - ManualRedactionType, -} from '@red/domain'; -import { RedactionLogEntry } from '@models/file/redaction-log.entry'; -import { - FalsePositiveSuperTypes, LowLevelFilterTypes, + ManualRedactionType, SuggestionAddSuperTypes, SuggestionsSuperTypes, SuperType, SuperTypes, -} from '@models/file/super-types'; -import { IListable, KeysOf, List } from '@iqser/common-ui'; +} from '@red/domain'; +import { RedactionLogEntry } from '@models/file/redaction-log.entry'; +import { IListable, List } from '@iqser/common-ui'; export class AnnotationWrapper implements IListable, Record { [x: string]: unknown; @@ -29,7 +30,7 @@ export class AnnotationWrapper implements IListable, Record { typeValue: string; recategorizationType: string; color: string; - dictionary: Dictionary; + entity: Dictionary; comments: IComment[] = []; firstTopLeftPoint: IPoint; annotationId: string; @@ -102,18 +103,6 @@ export class AnnotationWrapper implements IListable, Record { return this.isSuggestion || this.isDeclinedSuggestion; } - get colorKey(): KeysOf { - if (this.isSkipped || this.isIgnoredHint) { - return 'skippedHexColor'; - } - - if (this.isRecommendation) { - return 'recommendationHexColor'; - } - - return 'hexColor'; - } - get isSkipped() { return this.superType === SuperTypes.Skipped; } @@ -283,7 +272,7 @@ export class AnnotationWrapper implements IListable, Record { return annotationWrapper; } - static fromData(redactionLogEntry: RedactionLogEntry, dictionaries: Dictionary[]) { + static fromData(redactionLogEntry: RedactionLogEntry, dictionaries: Dictionary[], defaultColors: DefaultColors) { const annotationWrapper = new AnnotationWrapper(); annotationWrapper.annotationId = redactionLogEntry.id; @@ -333,10 +322,13 @@ export class AnnotationWrapper implements IListable, Record { this._handleRecommendations(annotationWrapper, redactionLogEntry); annotationWrapper.typeLabel = this.#getTypeLabel(redactionLogEntry, annotationWrapper); - const type = annotationWrapper.isSuperTypeBasedColor ? annotationWrapper.superType : annotationWrapper.type; - const dictionary = dictionaries.find(d => d.type === type); - annotationWrapper.dictionary = dictionary; - annotationWrapper.color = dictionary[annotationWrapper.colorKey] as string; + const entity = dictionaries.find(d => d.type === annotationWrapper.typeValue); + annotationWrapper.entity = entity.virtual ? null : entity; + + const colorKey = annotationWrapper.isSuperTypeBasedColor + ? annotationDefaultColorConfig[annotationWrapper.superType] + : annotationEntityColorConfig[annotationWrapper.superType]; + annotationWrapper.color = annotationWrapper.isSuperTypeBasedColor ? defaultColors[colorKey] : (entity[colorKey] as string); return annotationWrapper; } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts index e73585a07..ae687d0bb 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts @@ -1,16 +1,15 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { DefaultColorType, IColors } from '@red/domain'; +import { DefaultColorType } from '@red/domain'; import { BaseDialogComponent } from '@iqser/common-ui'; import { UntypedFormGroup, Validators } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { defaultColorsTranslations } from '@translations/default-colors-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { DictionaryService } from '@services/entity-services/dictionary.service'; import { firstValueFrom } from 'rxjs'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; interface IEditColorData { - colors: IColors; colorKey: DefaultColorType; dossierTemplateId: string; } @@ -23,7 +22,7 @@ export class EditColorDialogComponent extends BaseDialogComponent { readonly translations = defaultColorsTranslations; constructor( - private readonly _dictionaryService: DictionaryService, + private readonly _defaultColorsService: DefaultColorsService, private readonly _translateService: TranslateService, protected readonly _dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) readonly data: IEditColorData, @@ -35,24 +34,29 @@ export class EditColorDialogComponent extends BaseDialogComponent { } async save() { - const colors = { - ...this.data.colors, + const colors: Partial> = { [this.data.colorKey]: this.form.get('color').value, }; + this._loadingService.start(); try { - await firstValueFrom(this._dictionaryService.setColors(colors, this.data.dossierTemplateId)); + await firstValueFrom(this._defaultColorsService.update(colors, this.data.dossierTemplateId)); this._dialogRef.close(true); + this._loadingService.stop(); const color = this._translateService.instant(defaultColorsTranslations[this.data.colorKey]); this._toaster.info(_('edit-color-dialog.success'), { params: { color: color } }); } catch (e) { this._toaster.error(_('edit-color-dialog.error')); } + this._loadingService.stop(); } private _getForm(): UntypedFormGroup { return this._formBuilder.group({ - color: [this.data.colors[this.data.colorKey], [Validators.required, Validators.minLength(7)]], + color: [ + this._defaultColorsService.find(this.data.dossierTemplateId)[this.data.colorKey], + [Validators.required, Validators.minLength(7)], + ], }); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html index 747671e52..7e3a16045 100644 --- a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html @@ -1,4 +1,4 @@ -
+
-
+
-
+
-
+
implements OnInit { +export class DefaultColorsScreenComponent extends ListingComponent { readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = getCurrentUser(); readonly translations = defaultColorsTranslations; @@ -36,50 +29,22 @@ export class DefaultColorsScreenComponent extends ListingComponent imp { label: _('default-colors-screen.table-col-names.key'), sortByKey: 'searchKey', width: '2fr' }, { label: _('default-colors-screen.table-col-names.color'), class: 'flex-center' }, ]; - - #colorsObj: IColors; + readonly context$; readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); - constructor( - private readonly _loadingService: LoadingService, - private readonly _dialogService: AdminDialogService, - private readonly _dictionaryService: DictionaryService, - ) { + constructor(private readonly _dialogService: AdminDialogService, private readonly _defaultColorsService: DefaultColorsService) { super(); - } - openEditColorDialog($event: MouseEvent, color: { key: DefaultColorType | string; value: string }) { - this._dialogService.openDialog( - 'editColor', - $event, - { - colors: this.#colorsObj, - colorKey: color.key, - dossierTemplateId: this.#dossierTemplateId, - }, - async () => { - await this._loadColors(); - }, + this.context$ = combineLatest([this._defaultColorsService.all$]).pipe( + map(([allDefaultColors]) => { + const color = allDefaultColors.find(c => c.id === this.#dossierTemplateId); + return DefaultColorTypes.map(key => ({ id: key, key, searchKey: key, value: color[key] })); + }), + tap(colors => this.entitiesService.setEntities(colors)), ); } - async ngOnInit(): Promise { - await this._loadColors(); - } - - private async _loadColors() { - this._loadingService.start(); - const data = await firstValueFrom(this._dictionaryService.getColors(this.#dossierTemplateId)); - this.#colorsObj = data; - const entities = Object.keys(data) - .map(key => ({ - id: key, - key, - searchKey: key, - value: data[key], - })) - .filter(entry => entry.id !== DOSSIER_TEMPLATE_ID); - this.entitiesService.setEntities(entities); - this._loadingService.stop(); + openEditColorDialog($event: MouseEvent, color: ListItem) { + this._dialogService.openDialog('editColor', $event, { colorKey: color.key, dossierTemplateId: this.#dossierTemplateId }); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.html index d723e5278..baab6ec47 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/entities-listing/entities-listing-screen.component.html @@ -85,7 +85,7 @@
diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts index 06233304b..8e0f9cc1a 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts @@ -1,8 +1,8 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; -import { File } from '@red/domain'; +import { annotationDefaultColorConfig, DefaultBasedColorType, File } from '@red/domain'; import { UserService } from '@services/user.service'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; @Component({ selector: 'redaction-file-workload', @@ -15,36 +15,36 @@ export class FileWorkloadComponent { constructor( readonly userService: UserService, - private readonly _dictionariesMapService: DictionariesMapService, + private readonly _defaultColorsService: DefaultColorsService, private readonly _dossiersService: DossiersService, ) {} get suggestionColor() { - return this._getDictionaryColor('suggestion'); + return this._getDefaultColor('suggestion'); } get imageColor() { - return this._getDictionaryColor('image'); + return this._getDefaultColor('recommendation'); } get updatedColor() { - return this._getDictionaryColor('updated'); + return this._getDefaultColor('updated'); } get analysisColor() { - return this._getDictionaryColor('analysis'); + return this._getDefaultColor('analysis'); } get hintColor() { - return this._getDictionaryColor('hint'); + return this._getDefaultColor('hint'); } get redactionColor() { - return this._getDictionaryColor('redaction'); + return this._getDefaultColor('redaction'); } - private _getDictionaryColor(type: string) { + private _getDefaultColor(type: DefaultBasedColorType) { const dossierTemplateId = this._dossiersService.find(this.file.dossierId).dossierTemplateId; - return this._dictionariesMapService.getDictionaryColor(type, dossierTemplateId); + return this._defaultColorsService.getColor(dossierTemplateId, annotationDefaultColorConfig[type]); } } 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 01eb465d9..f7431de14 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 @@ -12,6 +12,7 @@ import { WorkflowConfig, } from '@iqser/common-ui'; import { + annotationDefaultColorConfig, AnnotationShapeMap, Dossier, File, @@ -33,6 +34,7 @@ import { ConfigService as AppConfigService } from '@services/config.service'; import { BehaviorSubject, Observable } from 'rxjs'; import { BulkActionsService } from './services/bulk-actions.service'; import dayjs from 'dayjs'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; @Injectable() export class ConfigService { @@ -46,6 +48,7 @@ export class ConfigService { private readonly _dialogService: DossiersDialogService, private readonly _appConfigService: AppConfigService, private readonly _bulkActionsService: BulkActionsService, + private readonly _defaultColorsService: DefaultColorsService, ) { this.listingMode$ = this._listingMode$.asObservable(); } @@ -171,6 +174,7 @@ export class ConfigService { filterGroups( entities: File[], fileAttributeConfigs: IFileAttributeConfig[], + dossierTemplateId: string, needsWorkFilterTemplate: TemplateRef, checkedRequiredFilters: () => NestedFilter[], checkedNotRequiredFilters: () => NestedFilter[], @@ -286,7 +290,10 @@ export class ConfigService { new NestedFilter({ id: item, label: workloadTranslations[item], - metadata: { shape: AnnotationShapeMap[item] }, + metadata: { + color: this._defaultColorsService.getColor(dossierTemplateId, annotationDefaultColorConfig[item]), + shape: AnnotationShapeMap[item], + }, }), ); diff --git a/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts index 0d69ec13e..ed92adc82 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/screen/dossier-overview-screen.component.ts @@ -211,6 +211,7 @@ export class DossierOverviewScreenComponent extends ListingComponent imple const filterGroups = this.configService.filterGroups( this.entitiesService.all, this._fileAttributeConfigs, + this.dossierTemplateId, this._needsWorkFilterTemplate, () => this.checkedRequiredFilters, () => this.checkedNotRequiredFilters, diff --git a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts index ae96f8997..21c3b881f 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { Dossier, DossierStats } from '@red/domain'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; @Component({ selector: 'redaction-dossier-workload-column', @@ -12,17 +12,17 @@ export class DossierWorkloadColumnComponent { @Input() dossier: Dossier; @Input() dossierStats: DossierStats; - constructor(private readonly _dictionariesMapService: DictionariesMapService) {} + constructor(private readonly _colorsService: DefaultColorsService) {} get suggestionColor() { - return this._dictionariesMapService.getDictionaryColor('suggestion', this.dossier.dossierTemplateId); + return this._colorsService.getColor(this.dossier.dossierTemplateId, 'requestAddColor'); } get hintColor() { - return this._dictionariesMapService.getDictionaryColor('hint', this.dossier.dossierTemplateId); + return this._colorsService.getColor(this.dossier.dossierTemplateId, 'hintColor'); } get redactionColor() { - return this._dictionariesMapService.getDictionaryColor('redaction', this.dossier.dossierTemplateId); + return this._colorsService.getColor(this.dossier.dossierTemplateId, 'redactionColor'); } } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html index 890bcdfd8..349b8a93f 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html @@ -14,12 +14,12 @@ {{ 'annotation.pending' | translate }}
-
+
{{ annotation.descriptor | translate }}: - {{ annotation.dictionary.label }} + {{ annotation.entity.label }}
: {{ annotation.shortContent }} diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index 339078909..430085a43 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -181,7 +181,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._loadingService.start(); this._annotationManager.hide(annotations); const highlights = await this._fileDataService.loadTextHighlights(); - await this._annotationDrawService.draw(highlights, this._skippedService.hideSkipped, this.state.dictionaries); + await this._annotationDrawService.draw(highlights, this._skippedService.hideSkipped, this.state.dossierTemplateId); this._loadingService.stop(); } } @@ -574,7 +574,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._handleDeltaAnnotationFilters(currentFilters); } - await this._annotationDrawService.draw(newAnnotations, this._skippedService.hideSkipped, this.state.dictionaries); + await this._annotationDrawService.draw(newAnnotations, this._skippedService.hideSkipped, this.state.dossierTemplateId); } private _handleDeltaAnnotationFilters(currentFilters: NestedFilter[]) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts index 074e4ba6a..5742f1896 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts @@ -235,7 +235,7 @@ export class AnnotationActionsService { annotationWrapper.resizing = false; this._annotationManager.delete(annotationWrapper); - await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped, this._state.dictionaries); + await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped, this._state.dossierTemplateId); this._annotationManager.deselect(); await this._fileDataService.annotationsChanged(); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts index ad83c8df4..f5f91a700 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts @@ -1,19 +1,21 @@ -import { inject, Injectable } from '@angular/core'; +import { Injectable } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { SuperTypeSorter } from '../../../utils'; import { Filter, handleCheckedValue, IFilter, INestedFilter, NestedFilter } from '@iqser/common-ui'; import { annotationTypesTranslations } from '@translations/annotation-types-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { IViewedPage } from '@red/domain'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; +import { annotationDefaultColorConfig, IViewedPage } from '@red/domain'; import { FilePreviewStateService } from './file-preview-state.service'; import { FileDataService } from './file-data.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; @Injectable() export class AnnotationProcessingService { - readonly #fileDataService = inject(FileDataService); - readonly #state = inject(FilePreviewStateService); - readonly #dictionariesMapService = inject(DictionariesMapService); + constructor( + private readonly _fileDataService: FileDataService, + private readonly _state: FilePreviewStateService, + private readonly _defaultColorsService: DefaultColorsService, + ) {} static secondaryAnnotationFilters(viewedPages?: IViewedPage[]): INestedFilter[] { const _viewedPages = viewedPages ? viewedPages.map(page => page.page) : []; @@ -57,7 +59,7 @@ export class AnnotationProcessingService { const filterMap = new Map(); const filters: INestedFilter[] = []; - this.#fileDataService.all?.forEach(a => { + this._fileDataService.all?.forEach(a => { const topLevelFilter = a.topLevelFilter; const filter = filterMap.get(a.filterKey); if (filter) { @@ -76,11 +78,15 @@ export class AnnotationProcessingService { if (!parentFilter) { parentFilter = this._createParentFilter(a.superType, filterMap, filters, false, { shape: a.iconShape, + color: this._defaultColorsService.getColor( + this._state.dossierTemplateId, + annotationDefaultColorConfig[a.superType], + ), }); } const childFilter: IFilter = { id: a.filterKey, - label: a.dictionary.label, + label: a.entity.label, checked: false, matches: 1, metadata: { diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index fbb2cd2d7..3040b94b6 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -18,6 +18,7 @@ import dayjs from 'dayjs'; import { NGXLogger } from 'ngx-logger'; import { MultiSelectService } from './multi-select.service'; import { FilesService } from '@services/files/files.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; const DELTA_VIEW_TIME = 10 * 60 * 1000; // 10 minutes; @@ -44,6 +45,7 @@ export class FileDataService extends EntitiesService { private readonly _filesService: FilesService, private readonly _toaster: Toaster, private readonly _logger: NGXLogger, + private readonly _defaultColorsService: DefaultColorsService, ) { super(); this.annotations$ = this.#annotations$; @@ -144,7 +146,9 @@ export class FileDataService extends EntitiesService { #buildAnnotations(redactionLog: IRedactionLog, file: File) { const entries: RedactionLogEntry[] = this.#convertData(redactionLog, file); - const annotations = entries.map(entry => AnnotationWrapper.fromData(entry, this._state.dictionaries)); + const annotations = entries.map(entry => + AnnotationWrapper.fromData(entry, this._state.dictionaries, this._defaultColorsService.find(this._state.dossierTemplateId)), + ); return annotations.filter(ann => ann.manual || !file.excludedPages.includes(ann.pageNumber)); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index 641c6ee8d..2077f3c8f 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -6,9 +6,9 @@ import { ManualRedactionEntryType, ManualRedactionEntryTypes, ManualRedactionEntryWrapper, -} from '../../../models/file/manual-redaction-entry.wrapper'; +} from '@models/file/manual-redaction-entry.wrapper'; import { AnnotationDrawService } from '../../pdf-viewer/services/annotation-draw.service'; -import { UserPreferenceService } from '../../../services/user-preference.service'; +import { UserPreferenceService } from '@services/user-preference.service'; import { BASE_HREF_FN, BaseHrefFn } from '../../../tokens'; import { shareDistinctLast } from '@iqser/common-ui'; import { toPosition } from '../utils/pdf-calculation.utils'; @@ -25,9 +25,10 @@ import { ALLOWED_ACTIONS_WHEN_PAGE_EXCLUDED, HEADER_ITEMS_TO_TOGGLE, TEXT_POPUPS import { REDDocumentViewer } from '../../pdf-viewer/services/document-viewer.service'; import { combineLatest, Observable, Subject } from 'rxjs'; import { ViewModeService } from './view-mode.service'; -import { PermissionsService } from '../../../services/permissions.service'; +import { PermissionsService } from '@services/permissions.service'; import { AnnotationsListingService } from './annotations-listing.service'; import { PdfAnnotationActionsService } from './pdf-annotation-actions.service'; +import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import Annotation = Core.Annotations.Annotation; import Quad = Core.Math.Quad; @@ -69,6 +70,7 @@ export class PdfProxyService { private readonly _multiSelectService: MultiSelectService, private readonly _listingService: AnnotationsListingService, private readonly _changeDetectorRef: ChangeDetectorRef, + private readonly _dictionariesMapService: DictionariesMapService, ) { this.canPerformAnnotationActions$ = this.#canPerformAnnotationActions$; } @@ -148,7 +150,9 @@ export class PdfProxyService { } private _configureElements() { - const color = this._annotationDrawService.convertColor(this._state.dictionaries.find(d => d.type === 'manual').hexColor); + const color = this._annotationDrawService.convertColor( + this._dictionariesMapService.get(this._state.dossierTemplateId, 'manual').hexColor, + ); this._documentViewer.setRectangleToolStyles(color); } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index 750f5a805..b406c63f7 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -5,15 +5,16 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { UserPreferenceService } from '@services/user-preference.service'; import { RedactionLogService } from '@services/files/redaction-log.service'; -import { Dictionary, IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain'; +import { IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain'; import { firstValueFrom } from 'rxjs'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; -import { SuperTypes } from '@models/file/super-types'; +import { SuperTypes } from '@red/domain'; import { PdfViewer } from './pdf-viewer.service'; import { ActivatedRoute } from '@angular/router'; import { REDAnnotationManager } from './annotation-manager.service'; import { List } from '@iqser/common-ui'; import { REDDocumentViewer } from './document-viewer.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; import Annotation = Core.Annotations.Annotation; import Quad = Core.Math.Quad; @@ -30,13 +31,14 @@ export class AnnotationDrawService { private readonly _annotationManager: REDAnnotationManager, private readonly _pdf: PdfViewer, private readonly _documentViewer: REDDocumentViewer, + private readonly _defaultColorsService: DefaultColorsService, ) {} - async draw(annotations: List, hideSkipped: boolean, dictionaries: Dictionary[]) { + async draw(annotations: List, hideSkipped: boolean, dossierTemplateId: string) { try { - await this._draw(annotations, hideSkipped, dictionaries); + await this._draw(annotations, hideSkipped, dossierTemplateId); } catch (e) { - console.log(e); + console.error(e); } } @@ -60,10 +62,10 @@ export class AnnotationDrawService { return this._pdf.quad(x1, y1, x2, y2, x3, y3, x4, y4); } - private async _draw(annotationWrappers: List, hideSkipped: boolean, dictionaries: Dictionary[]) { + private async _draw(annotationWrappers: List, hideSkipped: boolean, dossierTemplateId: string) { const totalPages = await firstValueFrom(this._pdf.totalPages$); const annotations = annotationWrappers - .map(annotation => this._computeAnnotation(annotation, hideSkipped, totalPages, dictionaries)) + .map(annotation => this._computeAnnotation(annotation, hideSkipped, totalPages, dossierTemplateId)) .filterTruthy(); const documentLoaded = await firstValueFrom(this._documentViewer.loaded$); if (!documentLoaded) { @@ -75,22 +77,22 @@ export class AnnotationDrawService { const { dossierId, fileId } = this._pdf; const sectionsGrid$ = this._redactionLogService.getSectionGrid(dossierId, fileId); const sectionsGrid = await firstValueFrom(sectionsGrid$).catch(() => ({ rectanglesPerPage: {} })); - await this._drawSections(sectionsGrid, dictionaries); + await this._drawSections(sectionsGrid, dossierTemplateId); } } - private async _drawSections(sectionGrid: ISectionGrid, dictionaries: Dictionary[]) { + private async _drawSections(sectionGrid: ISectionGrid, dossierTemplateId: string) { const sections: Core.Annotations.RectangleAnnotation[] = []; for (const page of Object.keys(sectionGrid.rectanglesPerPage)) { const sectionRectangles = sectionGrid.rectanglesPerPage[page]; sectionRectangles.forEach(sectionRectangle => { - sections.push(this._computeSection(parseInt(page, 10), sectionRectangle, dictionaries)); + sections.push(this._computeSection(parseInt(page, 10), sectionRectangle, dossierTemplateId)); }); } await this._annotationManager.add(sections); } - private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dictionaries: Dictionary[]) { + private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dossierTemplateId: string) { const rectangleAnnot = this._pdf.rectangle(); const pageHeight = this._documentViewer.getHeight(pageNumber); const rectangle: IRectangle = { @@ -105,13 +107,13 @@ export class AnnotationDrawService { rectangleAnnot.Width = rectangle.width + 2; rectangleAnnot.Height = rectangle.height + 2; rectangleAnnot.ReadOnly = true; - rectangleAnnot.StrokeColor = this.convertColor(dictionaries.find(d => d.type === 'analysis').hexColor); + rectangleAnnot.StrokeColor = this.convertColor(this._defaultColorsService.getColor(dossierTemplateId, 'analysisColor')); rectangleAnnot.StrokeThickness = 1; return rectangleAnnot; } - private _computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dictionaries: Dictionary[]) { + private _computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dossierTemplateId: string) { const pageNumber = this._pdf.isCompare ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber; if (pageNumber > totalPages) { // skip imported annotations from files that have more pages than the current one @@ -155,7 +157,7 @@ export class AnnotationDrawService { annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry)); annotation.setCustomData('changeLogRemoved', String(annotationWrapper.isChangeLogRemoved)); annotation.setCustomData('opacity', String(annotation.Opacity)); - annotation.setCustomData('redactionColor', String(dictionaries.find(d => d.type === 'preview').hexColor)); + annotation.setCustomData('redactionColor', String(this._defaultColorsService.getColor(dossierTemplateId, 'previewColor'))); annotation.setCustomData('annotationColor', String(annotationWrapper.color)); return annotation; diff --git a/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts b/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts index 65f63d63a..5fd9241df 100644 --- a/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts @@ -1,7 +1,7 @@ import { Component, Input, OnChanges } from '@angular/core'; import { INestedFilter } from '@iqser/common-ui'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; -import { SuperTypes } from '@models/file/super-types'; +import { SuperTypes } from '@red/domain'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; @Component({ selector: 'redaction-type-filter [dossierTemplateId]', @@ -13,7 +13,6 @@ export class TypeFilterComponent implements OnChanges { @Input() dossierTemplateId: string; @Input() dossierId: string; - dictionaryColor: string; label: string; color: string; @@ -28,10 +27,9 @@ export class TypeFilterComponent implements OnChanges { ]; private _needsAnalysisKeys: string[] = ['remove-only-here', 'analysis']; - constructor(private readonly _dictionariesMapService: DictionariesMapService) {} + constructor(private readonly _defaultColorsService: DefaultColorsService) {} ngOnChanges(): void { - this.dictionaryColor = this._dictionariesMapService.getDictionaryColor(this.filter.id, this.dossierTemplateId); this.label = this.filter.metadata?.shortLabel === '' ? '' @@ -42,6 +40,7 @@ export class TypeFilterComponent implements OnChanges { : this._suggestionsKeys.includes(this.filter.id) ? 'S' : this.filter.id.charAt(0); - this.color = this.filter.metadata?.color || (this.filter.id === 'none' ? 'transparent' : this.dictionaryColor); + + this.color = this.filter.metadata?.color || 'transparent'; } } diff --git a/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts b/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts index 50ae0e7ab..2b019a522 100644 --- a/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts +++ b/apps/red-ui/src/app/services/dossier-templates/dossier-templates.service.ts @@ -3,11 +3,12 @@ import { DossierTemplate, IDossierTemplate } from '@red/domain'; import { Injectable } from '@angular/core'; import { forkJoin, Observable, of } from 'rxjs'; import { FileAttributesService } from '../entity-services/file-attributes.service'; -import { catchError, mapTo, switchMap, tap } from 'rxjs/operators'; +import { catchError, map, mapTo, switchMap, tap } from 'rxjs/operators'; import { DossierTemplateStatsService } from '../entity-services/dossier-template-stats.service'; import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DictionaryService } from '../entity-services/dictionary.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; const DOSSIER_TEMPLATE_CONFLICT_MSG = _('dossier-templates-listing.error.conflict'); const GENERIC_MSG = _('dossier-templates-listing.error.generic'); @@ -24,6 +25,7 @@ export class DossierTemplatesService extends EntitiesService templates)); } return of(templates); }), diff --git a/apps/red-ui/src/app/services/entity-services/default-colors.service.ts b/apps/red-ui/src/app/services/entity-services/default-colors.service.ts new file mode 100644 index 000000000..89bf9d835 --- /dev/null +++ b/apps/red-ui/src/app/services/entity-services/default-colors.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@angular/core'; +import { EntitiesService, mapEach, RequiredParam, Validate } from '@iqser/common-ui'; +import { DefaultColors, DefaultColorType, IDefaultColors } from '@red/domain'; +import { forkJoin, Observable } from 'rxjs'; +import { map, switchMap, tap } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root', +}) +export class DefaultColorsService extends EntitiesService { + protected readonly _defaultModelPath = 'color'; + protected readonly _entityClass = DefaultColors; + + getColor(dossierTemplateId: string, colorType: DefaultColorType): string { + return this.find(dossierTemplateId)[colorType]; + } + + loadAll(dossierTemplateIds: string[]): Observable { + return forkJoin(dossierTemplateIds.map(id => super.getFor(id))).pipe( + mapEach(defaultColors => new DefaultColors(defaultColors)), + tap(defaultColors => this.setEntities(defaultColors)), + ); + } + + @Validate() + update( + @RequiredParam() newColor: Partial>, + @RequiredParam() dossierTemplateId: string, + ): Observable { + const oldColors = this.find(dossierTemplateId); + const body = { ...oldColors, ...newColor }; + return this._post(body, `${this._defaultModelPath}/${dossierTemplateId}`).pipe( + switchMap(() => super.getFor(dossierTemplateId)), + map(defaultColors => new DefaultColors(defaultColors)), + tap(defaultColors => this.replace(defaultColors)), + ); + } +} diff --git a/apps/red-ui/src/app/services/entity-services/dictionaries-map.service.ts b/apps/red-ui/src/app/services/entity-services/dictionaries-map.service.ts index 9b7c4e390..22e2fca6c 100644 --- a/apps/red-ui/src/app/services/entity-services/dictionaries-map.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dictionaries-map.service.ts @@ -5,24 +5,4 @@ import { EntitiesMapService } from '@iqser/common-ui'; @Injectable({ providedIn: 'root' }) export class DictionariesMapService extends EntitiesMapService { protected readonly _primaryKey = DOSSIER_TEMPLATE_ID; - - /** If the type is not found, it returns the 'default' type. */ - getDictionary(type: string, dossierTemplateId: string): Dictionary | undefined { - return this.get(dossierTemplateId, type) || this.get(dossierTemplateId, 'default'); - } - - getDictionaryColor(type: string, dossierTemplateId: string, isRecommendation = false, isSkipped = false) { - const defaultColor = '#CCCCCC'; - if (!this.get(dossierTemplateId)) { - return defaultColor; - } - - const dictionary = this.getDictionary(type, dossierTemplateId); - const colorKey = isRecommendation ? 'recommendationHexColor' : isSkipped ? 'skippedHexColor' : 'hexColor'; - if (dictionary && dictionary[colorKey]) { - return dictionary[colorKey]; - } - - return defaultColor; - } } diff --git a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts index 74127b448..aaf0ab737 100644 --- a/apps/red-ui/src/app/services/entity-services/dictionary.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dictionary.service.ts @@ -1,15 +1,13 @@ import { Injectable } from '@angular/core'; -import { firstValueFrom, forkJoin, Observable, of, throwError } from 'rxjs'; +import { firstValueFrom, forkJoin, Observable, throwError } from 'rxjs'; import { EntitiesService, List, QueryParam, RequiredParam, Toaster, Validate } from '@iqser/common-ui'; -import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, IColors, IDictionary, IUpdateDictionary } from '@red/domain'; +import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, IDictionary, IUpdateDictionary, SuperTypes } from '@red/domain'; import { catchError, map, switchMap, tap } from 'rxjs/operators'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DossierTemplateStatsService } from './dossier-template-stats.service'; import { DictionariesMapService } from './dictionaries-map.service'; -import { FALLBACK_COLOR } from '@utils/constants'; -import { hexToRgb } from '@utils/functions'; import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; -import { SuperTypes } from '@models/file/super-types'; +import { FALLBACK_COLOR } from '@utils/constants'; const MIN_WORD_LENGTH = 2; @@ -63,29 +61,6 @@ export class DictionaryService extends EntitiesService return this._getOne<{ types: IDictionary[] }>(['type', dossierTemplateId], this._defaultModelPath, queryParams); } - /** - * Retrieves system colors for redaction. - */ - @Validate() - getColors(@RequiredParam() dossierTemplateId: string) { - return this._getOne([dossierTemplateId], 'color').pipe( - catchError(() => - of({ - analysisColor: FALLBACK_COLOR, - dictionaryRequestColor: FALLBACK_COLOR, - defaultColor: FALLBACK_COLOR, - manualRedactionColor: FALLBACK_COLOR, - notRedacted: FALLBACK_COLOR, - requestAdd: FALLBACK_COLOR, - previewColor: FALLBACK_COLOR, - requestRemove: FALLBACK_COLOR, - updatedColor: FALLBACK_COLOR, - dossierTemplateId: dossierTemplateId, - } as IColors), - ), - ); - } - /** * Updates colors, hint and caseInsensitive of an entry type. */ @@ -105,16 +80,6 @@ export class DictionaryService extends EntitiesService ); } - /** - * Set system colors for redaction - */ - @Validate() - setColors(@RequiredParam() body: IColors, @RequiredParam() dossierTemplateId: string): Observable { - return this._post(body, `color/${dossierTemplateId}`).pipe( - switchMap(() => this.loadDictionaryDataForDossierTemplate(dossierTemplateId)), - ); - } - /** * Creates entry type with colors, hint and caseInsensitive */ @@ -217,73 +182,24 @@ export class DictionaryService extends EntitiesService } loadDictionaryDataForDossierTemplate(dossierTemplateId: string): Observable { - const types$: Observable = this.getAllDictionaries(dossierTemplateId).pipe( + return this.getAllDictionaries(dossierTemplateId).pipe( map(typesResponse => typesResponse.types.map(type => new Dictionary(type))), - ); - - const virtualTypes$: Observable = this.getColors(dossierTemplateId).pipe( - tap(colors => { - for (const key of Object.keys(colors)) { - const color: string = colors[key]; - try { - const rgbValue = hexToRgb(color); - if (!rgbValue) { - colors[key] = FALLBACK_COLOR; - } - } catch (e) { - colors[key] = FALLBACK_COLOR; + map(dictionaries => { + let manualTypeExists = false; + for (const dictionary of dictionaries) { + if (dictionary.type === SuperTypes.ManualRedaction) { + manualTypeExists = true; + break; } } - }), - map(colors => { - const virtualTypes = [ - { hexColor: colors.skippedColor || FALLBACK_COLOR, type: SuperTypes.DeclinedSuggestion }, - // dictionary actions - { hexColor: colors.recommendationColor || FALLBACK_COLOR, type: SuperTypes.Recommendation }, - { hexColor: colors.analysisColor || FALLBACK_COLOR, type: 'remove-only-here' }, - // generic suggestions - { hexColor: colors.requestAddColor || FALLBACK_COLOR, type: 'suggestion' }, - { hexColor: colors.requestAddColor || FALLBACK_COLOR, type: SuperTypes.SuggestionAdd }, - // add suggestions - { hexColor: colors.requestAddColor || FALLBACK_COLOR, type: SuperTypes.SuggestionChangeLegalBasis }, - { hexColor: colors.requestAddColor || FALLBACK_COLOR, type: SuperTypes.SuggestionRecategorizeImage }, - { hexColor: colors.dictionaryRequestColor || FALLBACK_COLOR, type: SuperTypes.SuggestionAddDictionary }, - { hexColor: colors.dictionaryRequestColor || FALLBACK_COLOR, type: SuperTypes.SuggestionResize }, - { hexColor: colors.requestRemoveColor || FALLBACK_COLOR, type: SuperTypes.SuggestionRemove }, - { hexColor: colors.dictionaryRequestColor || FALLBACK_COLOR, type: SuperTypes.SuggestionRemoveDictionary }, - { hexColor: colors.skippedColor || FALLBACK_COLOR, type: SuperTypes.Skipped }, - { hexColor: colors.requestAddColor || FALLBACK_COLOR, type: 'add' }, - { hexColor: colors.analysisColor || FALLBACK_COLOR, type: 'analysis' }, - { hexColor: colors.hintColor || FALLBACK_COLOR, type: SuperTypes.Hint, hint: true }, - { hexColor: colors.ignoredHintColor || FALLBACK_COLOR, type: SuperTypes.IgnoredHint, hint: true }, - { hexColor: colors.redactionColor || FALLBACK_COLOR, type: SuperTypes.Redaction }, - { hexColor: colors.previewColor || FALLBACK_COLOR, type: 'preview' }, - { hexColor: colors.updatedColor || FALLBACK_COLOR, type: 'updated' }, - ]; + if (!manualTypeExists) { + dictionaries.push(new Dictionary({ hexColor: FALLBACK_COLOR, type: SuperTypes.ManualRedaction }, true)); + } - return virtualTypes.map(config => new Dictionary(config, true)); + return dictionaries; }), + tap(dictionaries => this._dictionariesMapService.set(dossierTemplateId, dictionaries)), ); - - return forkJoin([types$, virtualTypes$]) - .pipe(map(([types, virtualTypes]: Dictionary[][]) => [...types, ...virtualTypes])) - .pipe( - map(dictionaries => { - let manualTypeExists = false; - for (const dictionary of dictionaries) { - if (dictionary.type === SuperTypes.ManualRedaction) { - manualTypeExists = true; - break; - } - } - if (!manualTypeExists) { - dictionaries.push(new Dictionary({ hexColor: FALLBACK_COLOR, type: SuperTypes.ManualRedaction }, true)); - } - - return dictionaries; - }), - ) - .pipe(tap(dictionaries => this._dictionariesMapService.set(dossierTemplateId, dictionaries))); } #addUpdateDictionaryErrorToast(error: HttpErrorResponse): Observable { diff --git a/apps/red-ui/src/app/translations/annotation-types-translations.ts b/apps/red-ui/src/app/translations/annotation-types-translations.ts index 289292d8f..c717d2601 100644 --- a/apps/red-ui/src/app/translations/annotation-types-translations.ts +++ b/apps/red-ui/src/app/translations/annotation-types-translations.ts @@ -1,5 +1,5 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { SuperType, SuperTypes } from '@models/file/super-types'; +import { SuperType, SuperTypes } from '@red/domain'; export const SuggestionAddFalsePositive = 'suggestion-add-false-positive' as const; diff --git a/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts b/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts index 5ee68b514..419a3d205 100644 --- a/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts +++ b/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts @@ -1,4 +1,4 @@ -import { SuperType, SuperTypes } from '@models/file/super-types'; +import { SuperType, SuperTypes } from '@red/domain'; export const SuperTypeSorter: { [key in SuperType]: number } = { [SuperTypes.TextHighlight]: 100, diff --git a/libs/red-domain/src/index.ts b/libs/red-domain/src/index.ts index a10ad047a..4301f03d7 100644 --- a/libs/red-domain/src/index.ts +++ b/libs/red-domain/src/index.ts @@ -27,3 +27,4 @@ export * from './lib/permissions'; export * from './lib/license'; export * from './lib/digital-signature'; export * from './lib/watermarks'; +export * from './lib/colors'; diff --git a/libs/red-domain/src/lib/colors/annotation-color-config.ts b/libs/red-domain/src/lib/colors/annotation-color-config.ts new file mode 100644 index 000000000..704500840 --- /dev/null +++ b/libs/red-domain/src/lib/colors/annotation-color-config.ts @@ -0,0 +1,48 @@ +import { DefaultColorType } from './default-color-type'; +import { SuperType, SuperTypes } from '../files'; + +export type DefaultBasedColorType = SuperType | 'updated' | 'image' | 'suggestion' | 'analysis'; + +export const annotationDefaultColorConfig: Record = { + [SuperTypes.TextHighlight]: 'redactionColor', // not actually used + + [SuperTypes.SuggestionChangeLegalBasis]: 'requestAddColor', + [SuperTypes.SuggestionRecategorizeImage]: 'requestAddColor', + [SuperTypes.SuggestionAddDictionary]: 'dictionaryRequestColor', + [SuperTypes.SuggestionForceRedaction]: 'requestAddColor', + [SuperTypes.SuggestionForceHint]: 'requestAddColor', + [SuperTypes.SuggestionResize]: 'dictionaryRequestColor', + [SuperTypes.SuggestionRemoveDictionary]: 'dictionaryRequestColor', + [SuperTypes.SuggestionAdd]: 'requestAddColor', + [SuperTypes.SuggestionRemove]: 'requestRemoveColor', + [SuperTypes.DeclinedSuggestion]: 'skippedColor', + + [SuperTypes.IgnoredHint]: 'ignoredHintColor', + [SuperTypes.Skipped]: 'skippedColor', + [SuperTypes.Redaction]: 'redactionColor', + [SuperTypes.ManualRedaction]: 'redactionColor', + [SuperTypes.Recommendation]: 'recommendationColor', + [SuperTypes.Hint]: 'hintColor', + + updated: 'updatedColor', + image: 'recommendationColor', + suggestion: 'requestAddColor', + analysis: 'analysisColor', +} as const; + +type EntityBasedColorType = + | typeof SuperTypes.IgnoredHint + | typeof SuperTypes.Skipped + | typeof SuperTypes.Redaction + | typeof SuperTypes.ManualRedaction + | typeof SuperTypes.Recommendation + | typeof SuperTypes.Hint; + +export const annotationEntityColorConfig: Record = { + [SuperTypes.IgnoredHint]: 'skippedHexColor', + [SuperTypes.Skipped]: 'skippedHexColor', + [SuperTypes.Redaction]: 'hexColor', + [SuperTypes.ManualRedaction]: 'hexColor', + [SuperTypes.Recommendation]: 'recommendationHexColor', + [SuperTypes.Hint]: 'hexColor', +} as const; diff --git a/libs/red-domain/src/lib/colors/default-color-type.ts b/libs/red-domain/src/lib/colors/default-color-type.ts new file mode 100644 index 000000000..af086eed6 --- /dev/null +++ b/libs/red-domain/src/lib/colors/default-color-type.ts @@ -0,0 +1,15 @@ +export const DefaultColorTypes = [ + 'requestAddColor', + 'requestRemoveColor', + 'dictionaryRequestColor', + 'previewColor', + 'analysisColor', + 'updatedColor', + 'recommendationColor', + 'hintColor', + 'redactionColor', + 'ignoredHintColor', + 'skippedColor', +] as const; + +export type DefaultColorType = typeof DefaultColorTypes[number]; diff --git a/libs/red-domain/src/lib/colors/default-colors.model.ts b/libs/red-domain/src/lib/colors/default-colors.model.ts new file mode 100644 index 000000000..1eecce024 --- /dev/null +++ b/libs/red-domain/src/lib/colors/default-colors.model.ts @@ -0,0 +1,43 @@ +import { Entity } from '@iqser/common-ui'; +import { IDefaultColors } from './default-colors'; + +export class DefaultColors extends Entity implements IDefaultColors { + readonly dossierTemplateId: string; + readonly requestAddColor: string; + readonly requestRemoveColor: string; + readonly dictionaryRequestColor: string; + readonly previewColor: string; + readonly analysisColor: string; + readonly updatedColor: string; + readonly recommendationColor: string; + readonly hintColor: string; + readonly redactionColor: string; + readonly ignoredHintColor: string; + readonly skippedColor: string; + + readonly routerLink = ''; + + constructor(entity: IDefaultColors) { + super(entity); + this.dossierTemplateId = entity.dossierTemplateId; + this.requestAddColor = entity.requestAddColor; + this.requestRemoveColor = entity.requestRemoveColor; + this.dictionaryRequestColor = entity.dictionaryRequestColor; + this.previewColor = entity.previewColor; + this.analysisColor = entity.analysisColor; + this.updatedColor = entity.updatedColor; + this.recommendationColor = entity.recommendationColor; + this.hintColor = entity.hintColor; + this.redactionColor = entity.redactionColor; + this.ignoredHintColor = entity.ignoredHintColor; + this.skippedColor = entity.skippedColor; + } + + get id(): string { + return this.dossierTemplateId; + } + + get searchKey(): string { + return this.dossierTemplateId; + } +} diff --git a/libs/red-domain/src/lib/colors/default-colors.ts b/libs/red-domain/src/lib/colors/default-colors.ts new file mode 100644 index 000000000..7674814e4 --- /dev/null +++ b/libs/red-domain/src/lib/colors/default-colors.ts @@ -0,0 +1,3 @@ +import { DefaultColorType } from './default-color-type'; + +export type IDefaultColors = Record & { dossierTemplateId: string }; diff --git a/libs/red-domain/src/lib/colors/index.ts b/libs/red-domain/src/lib/colors/index.ts new file mode 100644 index 000000000..777cc0e3c --- /dev/null +++ b/libs/red-domain/src/lib/colors/index.ts @@ -0,0 +1,4 @@ +export * from './default-colors.model'; +export * from './default-colors'; +export * from './annotation-color-config'; +export * from './default-color-type'; diff --git a/libs/red-domain/src/lib/dictionaries/colors.ts b/libs/red-domain/src/lib/dictionaries/colors.ts deleted file mode 100644 index ea39086e2..000000000 --- a/libs/red-domain/src/lib/dictionaries/colors.ts +++ /dev/null @@ -1,14 +0,0 @@ -export interface IColors { - dossierTemplateId?: string; - requestAddColor?: string; - requestRemoveColor?: string; - dictionaryRequestColor?: string; - previewColor?: string; - analysisColor?: string; - updatedColor?: string; - recommendationColor?: string; - hintColor?: string; - redactionColor?: string; - ignoredHintColor?: string; - skippedColor?: string; -} diff --git a/libs/red-domain/src/lib/dictionaries/index.ts b/libs/red-domain/src/lib/dictionaries/index.ts index 83c5659e5..babf806d3 100644 --- a/libs/red-domain/src/lib/dictionaries/index.ts +++ b/libs/red-domain/src/lib/dictionaries/index.ts @@ -1,4 +1,3 @@ -export * from './colors'; export * from './dictionary'; export * from './update-dictionary'; export * from './dictionary.model'; diff --git a/libs/red-domain/src/lib/files/index.ts b/libs/red-domain/src/lib/files/index.ts index c27a701c6..c238e8dff 100644 --- a/libs/red-domain/src/lib/files/index.ts +++ b/libs/red-domain/src/lib/files/index.ts @@ -3,3 +3,4 @@ export * from './file.model'; export * from './types'; export * from './file-upload-result'; export * from './overwrite-file-options'; +export * from './super-types'; diff --git a/apps/red-ui/src/app/models/file/super-types.ts b/libs/red-domain/src/lib/files/super-types.ts similarity index 100% rename from apps/red-ui/src/app/models/file/super-types.ts rename to libs/red-domain/src/lib/files/super-types.ts index c3baeb418..283170576 100644 --- a/apps/red-ui/src/app/models/file/super-types.ts +++ b/libs/red-domain/src/lib/files/super-types.ts @@ -11,13 +11,13 @@ export const SuperTypes = { SuggestionRemoveDictionary: 'suggestion-remove-dictionary', SuggestionAdd: 'suggestion-add', SuggestionRemove: 'suggestion-remove', + DeclinedSuggestion: 'suggestion-declined', IgnoredHint: 'hint-ignored', Skipped: 'skipped', Redaction: 'redaction', ManualRedaction: 'manual', Recommendation: 'recommendation', Hint: 'hint', - DeclinedSuggestion: 'suggestion-declined', } as const; export type SuperType = ValuesOf; diff --git a/libs/red-domain/src/lib/shared/default-color-type.ts b/libs/red-domain/src/lib/shared/default-color-type.ts deleted file mode 100644 index 6b93fea28..000000000 --- a/libs/red-domain/src/lib/shared/default-color-type.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { IColors } from '../dictionaries'; - -export type DefaultColorType = keyof IColors; diff --git a/libs/red-domain/src/lib/shared/index.ts b/libs/red-domain/src/lib/shared/index.ts index 6e5026112..3c25911a6 100644 --- a/libs/red-domain/src/lib/shared/index.ts +++ b/libs/red-domain/src/lib/shared/index.ts @@ -2,7 +2,6 @@ export * from './sorters/status-sorter'; export * from './breadcrumb-types'; export * from './types'; export * from './rules'; -export * from './default-color-type'; export * from './colors'; export * from './view-mode'; export * from './expandable-file-actions';