From 29d1fc765330d6f25910ad3e4ca85e118da44059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Mon, 11 Jul 2022 19:57:33 +0300 Subject: [PATCH] RED-4416: Annotation colors --- .../src/app/models/file/annotation.wrapper.ts | 18 +++- .../red-ui/src/app/models/file/super-types.ts | 4 +- .../annotation-actions.component.ts | 2 +- .../annotation-card.component.html | 21 +++-- .../annotation-card.component.scss | 5 -- .../annotation-card.component.ts | 38 +-------- .../highlights-separator.component.html | 2 +- .../type-annotation-icon.component.html | 1 - .../type-annotation-icon.component.scss | 0 .../type-annotation-icon.component.ts | 53 ------------ .../manual-annotation-dialog.component.ts | 5 +- .../file-preview-screen.component.ts | 21 ++--- .../file-preview/file-preview.module.ts | 2 - .../services/annotation-actions.service.ts | 15 +--- .../services/annotation-processing.service.ts | 11 +-- .../services/file-data.service.ts | 5 +- .../services/file-preview-state.service.ts | 6 ++ .../services/manual-redaction.service.ts | 11 +-- .../pdf-annotation-actions.service.ts | 3 +- .../services/pdf-proxy.service.ts | 8 +- .../services/annotation-draw.service.ts | 84 +++---------------- .../dictionaries-map.service.ts | 1 - .../entity-services/dictionary.service.ts | 6 -- libs/common-ui | 2 +- 24 files changed, 79 insertions(+), 245 deletions(-) delete mode 100644 apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.html delete mode 100644 apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.scss delete mode 100644 apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.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 148791913..3556cd488 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -29,6 +29,7 @@ export class AnnotationWrapper implements IListable, Record { typeValue: string; recategorizationType: string; color: string; + dictionary: Dictionary; comments: IComment[] = []; firstTopLeftPoint: IPoint; annotationId: string; @@ -102,7 +103,7 @@ export class AnnotationWrapper implements IListable, Record { } get colorKey(): KeysOf { - return this.isSkipped ? 'skippedHexColor' : this.isRecommendation ? 'recommendationHexColor' : 'hexColor'; + return this.isSkipped || this.isIgnoredHint ? 'skippedHexColor' : this.isRecommendation ? 'recommendationHexColor' : 'hexColor'; } get isSkipped() { @@ -154,7 +155,13 @@ export class AnnotationWrapper implements IListable, Record { } get iconShape(): AnnotationIconType { - return this.isRecommendation ? 'hexagon' : this.isHint ? 'circle' : this.isSuggestion ? 'rhombus' : 'square'; + return this.isRecommendation + ? 'hexagon' + : this.isHint || this.isIgnoredHint + ? 'circle' + : this.isSuggestion || this.isDeclinedSuggestion + ? 'rhombus' + : 'square'; } get isIgnoredHint() { @@ -262,7 +269,7 @@ export class AnnotationWrapper implements IListable, Record { return annotationWrapper; } - static fromData(redactionLogEntry?: RedactionLogEntry) { + static fromData(redactionLogEntry: RedactionLogEntry, dictionaries: Dictionary[]) { const annotationWrapper = new AnnotationWrapper(); annotationWrapper.annotationId = redactionLogEntry.id; @@ -312,6 +319,11 @@ 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; + return annotationWrapper; } diff --git a/apps/red-ui/src/app/models/file/super-types.ts b/apps/red-ui/src/app/models/file/super-types.ts index b27c5bd6b..23e1e7483 100644 --- a/apps/red-ui/src/app/models/file/super-types.ts +++ b/apps/red-ui/src/app/models/file/super-types.ts @@ -11,13 +11,13 @@ export const SuperTypes = { SuggestionRemoveDictionary: 'suggestion-remove-dictionary', SuggestionAdd: 'suggestion-add', SuggestionRemove: 'suggestion-remove', - IgnoredHint: 'ignored-hint', + IgnoredHint: 'hint-ignored', Skipped: 'skipped', Redaction: 'redaction', ManualRedaction: 'manual-redaction', Recommendation: 'recommendation', Hint: 'hint', - DeclinedSuggestion: 'declined-suggestion', + DeclinedSuggestion: 'suggestion-declined', } as const; export type SuperType = ValuesOf; diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts index 89ebb9d0b..7e0a3399c 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts @@ -122,7 +122,7 @@ export class AnnotationActionsComponent implements OnChanges { this._permissionsService.isApprover(dossier), this._userService.currentUser, this.annotations, - this._dictionariesMapService.get(dossier.dossierTemplateId), + this._state.dictionaries, ); } } 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 92d177391..890bcdfd8 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 @@ -1,18 +1,25 @@
- +
- {{ annotation.typeLabel | translate }} {{ - 'annotation.pending' | translate - }} + {{ annotation.typeLabel | translate }} +   + + {{ 'annotation.pending' | translate }} +
{{ annotation.descriptor | translate }}: {{ (dictionary$ | async).label }} + >: + + {{ annotation.dictionary.label }}
: {{ annotation.shortContent }} diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss index bda37fef8..79b889eaf 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.scss @@ -9,11 +9,6 @@ min-width: 20px; } -redaction-type-annotation-icon { - margin-top: 6px; - margin-right: 10px; -} - .pending-analysis { color: var(--iqser-red-1); } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts index b29166602..a0aed4893 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts @@ -1,13 +1,6 @@ -import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { MultiSelectService } from '../../services/multi-select.service'; -import { FilePreviewStateService } from '../../services/file-preview-state.service'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; -import { Dictionary, DOSSIER_ID } from '@red/domain'; -import { ActivatedRoute } from '@angular/router'; -import { DossiersService } from '@services/dossiers/dossiers.service'; -import { BehaviorSubject } from 'rxjs'; -import { DictionaryService } from '@services/entity-services/dictionary.service'; @Component({ selector: 'redaction-annotation-card', @@ -15,34 +8,9 @@ import { DictionaryService } from '@services/entity-services/dictionary.service' styleUrls: ['./annotation-card.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class AnnotationCardComponent implements OnChanges { +export class AnnotationCardComponent { @Input() annotation: AnnotationWrapper; @Input() isSelected = false; - readonly dictionary$ = new BehaviorSubject(undefined); - readonly #dossierId: string; - readonly #dossierTemplateId: string; - constructor( - route: ActivatedRoute, - dossiersService: DossiersService, - readonly multiSelectService: MultiSelectService, - private readonly _dictionariesMapService: DictionariesMapService, - private readonly _dictionaryService: DictionaryService, - private readonly _state: FilePreviewStateService, - ) { - this.#dossierId = route.snapshot.paramMap.get(DOSSIER_ID); - this.#dossierTemplateId = dossiersService.find(this.#dossierId).dossierTemplateId; - } - - ngOnChanges(changes: SimpleChanges): void { - if (changes.annotation) { - if (this.annotation.type !== 'manual' && !this.annotation.isHighlight) { - const dictionary = - this.annotation.type === 'dossier_redaction' - ? this._state.dossierDictionary - : this._dictionariesMapService.getDictionary(this.annotation.type, this.#dossierTemplateId); - this.dictionary$.next(dictionary); - } - } - } + constructor(readonly multiSelectService: MultiSelectService) {} } diff --git a/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.html b/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.html index 7b3e9f344..9e6b01ed2 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.html @@ -1,5 +1,5 @@
- +
diff --git a/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.html b/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.html deleted file mode 100644 index 22eb999b5..000000000 --- a/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.scss b/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.ts b/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.ts deleted file mode 100644 index a89c473e9..000000000 --- a/apps/red-ui/src/app/modules/file-preview/components/type-annotation-icon/type-annotation-icon.component.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Component, Input, OnChanges } from '@angular/core'; -import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { FilePreviewStateService } from '../../services/file-preview-state.service'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; - -@Component({ - selector: 'redaction-type-annotation-icon', - templateUrl: './type-annotation-icon.component.html', - styleUrls: ['./type-annotation-icon.component.scss'], -}) -export class TypeAnnotationIconComponent implements OnChanges { - @Input() annotation: AnnotationWrapper; - - label: string; - color: string; - type: 'square' | 'rhombus' | 'circle' | 'hexagon'; - - constructor(private _dictionariesMapService: DictionariesMapService, readonly screenStateService: FilePreviewStateService) {} - - private get _dossierTemplateId(): string { - return this.screenStateService.dossierTemplateId; - } - - ngOnChanges(): void { - if (!this.annotation) { - return; - } - - const { isHighlight, isSuggestion, isRecommendation, isSkipped, isDeclinedSuggestion, isHint, isIgnoredHint } = this.annotation; - - if (isHighlight) { - this.color = this.annotation.color; - } else { - const type = this.annotation.isSuperTypeBasedColor ? this.annotation.superType : this.annotation.type; - if (type === 'dossier_redaction') { - this.color = this.screenStateService.dossierDictionary[this.annotation.colorKey] as string; - } else { - // todo: use annotation.colorKey - this.color = this._dictionariesMapService.getDictionaryColor( - type, - this._dossierTemplateId, - isRecommendation, - isSkipped || isIgnoredHint, - ); - } - } - - this.type = - isSuggestion || isDeclinedSuggestion ? 'rhombus' : isHint || isIgnoredHint ? 'circle' : isRecommendation ? 'hexagon' : 'square'; - - this.label = isHighlight ? '' : isSuggestion || isDeclinedSuggestion || isSkipped ? 'S' : this.annotation.type[0].toUpperCase(); - } -} diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts index b369913ed..ea15d50ce 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts @@ -97,7 +97,10 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme this.isRectangle && !!this.form.get('multiplePages').value ? this.#getRectangles() : [this.data.manualRedactionEntryWrapper]; - this._dialogRef.close(annotations); + this._dialogRef.close({ + annotations, + dictionary: this.possibleDictionaries.find(d => d.type === this.form.get('dictionary').value), + }); } catch (e) { this._toaster.error(_('manual-annotation.dialog.error')); } 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 763591fc1..55b1879c2 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 @@ -22,7 +22,7 @@ import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationDrawService } from '../pdf-viewer/services/annotation-draw.service'; import { AnnotationProcessingService } from './services/annotation-processing.service'; -import { File, ViewMode, ViewModes } from '@red/domain'; +import { Dictionary, File, ViewMode, ViewModes } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; import { combineLatest, firstValueFrom, from, of, pairwise } from 'rxjs'; import { UserPreferenceService } from '@services/user-preference.service'; @@ -194,12 +194,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.state.dossierTemplateId, - this._skippedService.hideSkipped, - this.state.dossierDictionary, - ); + await this._annotationDrawService.draw(highlights, this._skippedService.hideSkipped, this.state.dictionaries); this._loadingService.stop(); } } @@ -256,16 +251,17 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni 'manualAnnotation', null, { manualRedactionEntryWrapper, dossierId: this.dossierId, file }, - (wrappers: ManualRedactionEntryWrapper[]) => { + (result: { annotations: ManualRedactionEntryWrapper[]; dictionary?: Dictionary }) => { const selectedAnnotations = this._annotationManager.selected; if (selectedAnnotations.length > 0) { this._annotationManager.delete([selectedAnnotations[0].Id]); } const manualRedactionService = this._injector.get(ManualRedactionService); const add$ = manualRedactionService.addAnnotation( - wrappers.map(w => w.manualRedactionEntry).filter(e => e.positions[0].page <= file.numberOfPages), + result.annotations.map(w => w.manualRedactionEntry).filter(e => e.positions[0].page <= file.numberOfPages), this.dossierId, this.fileId, + result.dictionary?.label, ); const filesService = this._injector.get(FilesService); const addAndReload$ = add$.pipe(switchMap(() => filesService.reload(this.dossierId, file))); @@ -600,12 +596,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._handleDeltaAnnotationFilters(currentFilters); } - await this._annotationDrawService.draw( - newAnnotations, - this.state.dossierTemplateId, - this._skippedService.hideSkipped, - this.state.dossierDictionary, - ); + await this._annotationDrawService.draw(newAnnotations, this._skippedService.hideSkipped, this.state.dictionaries); } private _handleDeltaAnnotationFilters(currentFilters: NestedFilter[]) { diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts index 7d2e3ec45..3731600ee 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts @@ -14,7 +14,6 @@ import { PageExclusionComponent } from './components/page-exclusion/page-exclusi import { AnnotationActionsComponent } from './components/annotation-actions/annotation-actions.component'; import { CommentsComponent } from './components/comments/comments.component'; import { DocumentInfoComponent } from './components/document-info/document-info.component'; -import { TypeAnnotationIconComponent } from './components/type-annotation-icon/type-annotation-icon.component'; import { OverlayModule } from '@angular/cdk/overlay'; import { ViewSwitchComponent } from './components/view-switch/view-switch.component'; import { UserManagementComponent } from './components/user-management/user-management.component'; @@ -72,7 +71,6 @@ const components = [ AnnotationActionsComponent, CommentsComponent, DocumentInfoComponent, - TypeAnnotationIconComponent, ViewSwitchComponent, UserManagementComponent, AnnotationReferencesListComponent, 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 3388097be..074e4ba6a 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,12 +235,7 @@ export class AnnotationActionsService { annotationWrapper.resizing = false; this._annotationManager.delete(annotationWrapper); - await this._annotationDrawService.draw( - [annotationWrapper], - this._state.dossierTemplateId, - this._skippedService.hideSkipped, - this._state.dossierDictionary, - ); + await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped, this._state.dictionaries); this._annotationManager.deselect(); await this._fileDataService.annotationsChanged(); } @@ -276,13 +271,7 @@ export class AnnotationActionsService { annotation.ReadOnly = false; annotation.Hidden = false; annotation.disableRotationControl(); - const dossierTemplateId = this._state.dossierTemplateId; - annotation.FillColor = this._annotationDrawService.getAndConvertColor( - annotationWrapper.superType, - dossierTemplateId, - this._state.dossierDictionary, - annotationWrapper.type, - ); + annotation.FillColor = this._annotationDrawService.convertColor(annotationWrapper.color); annotation.StrokeColor = annotation.FillColor; annotation.Opacity = 0.6; annotation.StrokeThickness = 1; 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 1bb5d36da..ad83c8df4 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 @@ -66,18 +66,13 @@ export class AnnotationProcessingService { // top level filter if (topLevelFilter) { this._createParentFilter(a.isHighlight ? a.filterKey : a.superType, filterMap, filters, a.isHighlight, { - color: a.isHighlight ? a.color : null, + color: a.color, shortLabel: a.isHighlight ? '' : null, shape: a.iconShape, }); } else { let parentFilter = filterMap.get(a.superType); - const dictionary = - a.type === 'dossier_redaction' - ? this.#state.dossierDictionary - : this.#dictionariesMapService.getDictionary(a.type, this.#state.dossierTemplateId); - if (!parentFilter) { parentFilter = this._createParentFilter(a.superType, filterMap, filters, false, { shape: a.iconShape, @@ -85,11 +80,11 @@ export class AnnotationProcessingService { } const childFilter: IFilter = { id: a.filterKey, - label: dictionary.label, + label: a.dictionary.label, checked: false, matches: 1, metadata: { - color: dictionary[a.colorKey], + color: a.color, shape: a.iconShape, }, skipTranslation: true, 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 a428363f0..936f3c390 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 @@ -146,7 +146,7 @@ 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)); + const annotations = entries.map(entry => AnnotationWrapper.fromData(entry, this._state.dictionaries)); return annotations.filter(ann => ann.manual || !file.excludedPages.includes(ann.pageNumber)); } @@ -154,11 +154,10 @@ export class FileDataService extends EntitiesService { #convertData(redactionLog: IRedactionLog, file: File): RedactionLogEntry[] { let result: RedactionLogEntry[] = []; const sourceIdAnnotationIds: { [key: string]: RedactionLogEntry[] } = {}; - const dictionaries = this._dictionariesMapService.get(this._state.dossierTemplateId); redactionLog.redactionLogEntry?.forEach(redactionLogEntry => { const changeLogValues = this.#getChangeLogValues(redactionLogEntry, file); - const dictionary = dictionaries.find(dict => dict.type === redactionLogEntry.type); + const dictionary = this._state.dictionaries.find(dict => dict.type === redactionLogEntry.type); if (!dictionary) { this.missingTypes.add(redactionLogEntry.type); return; diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts index 4cc249c90..98a393daa 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts @@ -14,6 +14,7 @@ import { FilesService } from '@services/files/files.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; import { HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse } from '@angular/common/http'; import { TranslateService } from '@ngx-translate/core'; +import { DictionariesMapService } from '../../../services/entity-services/dictionaries-map.service'; const ONE_MEGABYTE = 1024 * 1024; @@ -55,6 +56,7 @@ export class FilePreviewStateService { private readonly _dossiersService: DossiersService, private readonly _fileManagementService: FileManagementService, private readonly _dictionaryService: DictionaryService, + private readonly _dictionariesMapService: DictionariesMapService, private readonly _translateService: TranslateService, private readonly _loadingService: LoadingService, ) { @@ -83,6 +85,10 @@ export class FilePreviewStateService { return this.#dossierDictionary; } + get dictionaries(): Dictionary[] { + return this._dictionariesMapService.get(this.dossierTemplateId).concat([this.dossierDictionary]); + } + get blob(): Promise { return firstValueFrom(this.blob$); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts index d457fba40..fbdb5aed6 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts @@ -18,7 +18,6 @@ import { dictionaryActionsTranslations, manualRedactionActionsTranslations } fro import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { type ManualRedactionEntryType } from '@models/file/manual-redaction-entry.wrapper'; import { NGXLogger } from 'ngx-logger'; @@ -46,7 +45,6 @@ export class ManualRedactionService extends GenericService { protected readonly _injector: Injector, private readonly _permissionsService: PermissionsService, private readonly _activeDossiersService: ActiveDossiersService, - private readonly _dictionariesMapService: DictionariesMapService, ) { super(_injector, 'manualRedaction'); } @@ -92,8 +90,8 @@ export class ManualRedactionService extends GenericService { return this.requestRecategorize(body, dossierId, fileId).pipe(this.#showToast('request-image-recategorization')); } - addAnnotation(requests: List, dossierId: string, fileId: string) { - const toast = requests[0].addToDictionary ? this.#showAddToDictionaryToast(requests, dossierId) : this.#showToast('add'); + addAnnotation(requests: List, dossierId: string, fileId: string, dictionaryLabel?: string) { + const toast = requests[0].addToDictionary ? this.#showAddToDictionaryToast(requests, dictionaryLabel) : this.#showToast('add'); if (this._permissionsService.isApprover(this.#dossier(dossierId))) { return this.add(requests, dossierId, fileId).pipe(toast); } @@ -291,7 +289,7 @@ export class ManualRedactionService extends GenericService { }); } - #showAddToDictionaryToast(body: List, dossierId: string) { + #showAddToDictionaryToast(body: List, dictionaryLabel?: string) { return tap({ next: () => this._toaster.success(getDictionaryMessage('add'), { positionClass: 'toast-file-preview' }), error: (error: HttpErrorResponse) => { @@ -299,8 +297,7 @@ export class ManualRedactionService extends GenericService { this._toaster.error(getDictionaryMessage('add', true, isConflict), { error, params: { - dictionaryName: this._dictionariesMapService.getDictionary(body[0].type, this.#dossier(dossierId).dossierTemplateId) - .label, + dictionaryName: dictionaryLabel, content: body[0].value, }, positionClass: 'toast-file-preview', diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts index def05c947..83170696b 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts @@ -144,9 +144,8 @@ export class PdfAnnotationActionsService { #getAnnotationsPermissions(annotations: AnnotationWrapper[]) { const dossier = this.#state.dossier; const isApprover = this.#permissionsService.isApprover(dossier); - const dictionaries = this.#dictionariesMapService.get(dossier.dossierTemplateId); - const permissions = annotations.map(a => AnnotationPermissions.forUser(isApprover, this.#currentUser, a, dictionaries)); + const permissions = annotations.map(a => AnnotationPermissions.forUser(isApprover, this.#currentUser, a, this.#state.dictionaries)); return { canResize: permissions.length === 1 && permissions[0].canResizeAnnotation, canChangeLegalBasis: permissions.reduce((acc, next) => acc && next.canChangeLegalBasis, true), 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 390406702..641c6ee8d 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 @@ -148,13 +148,7 @@ export class PdfProxyService { } private _configureElements() { - const dossierTemplateId = this._state.dossierTemplateId; - const color = this._annotationDrawService.getAndConvertColor( - dossierTemplateId, - dossierTemplateId, - this._state.dossierDictionary, - 'manual', - ); + const color = this._annotationDrawService.convertColor(this._state.dictionaries.find(d => d.type === '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 0f7ce3d18..750f5a805 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 @@ -32,18 +32,14 @@ export class AnnotationDrawService { private readonly _documentViewer: REDDocumentViewer, ) {} - async draw(annotations: List, dossierTemplateId: string, hideSkipped: boolean, dossierDictionary: Dictionary) { + async draw(annotations: List, hideSkipped: boolean, dictionaries: Dictionary[]) { try { - await this._draw(annotations, dossierTemplateId, hideSkipped, dossierDictionary); + await this._draw(annotations, hideSkipped, dictionaries); } catch (e) { console.log(e); } } - getAndConvertColor(superType: string, dossierTemplateId: string, dossierDictionary: Dictionary, type?: string) { - return this.convertColor(this.#getColor(superType, dossierTemplateId, type, dossierDictionary)); - } - convertColor(hexColor: string) { return this._pdf.color(hexToRgb(hexColor)); } @@ -64,45 +60,10 @@ export class AnnotationDrawService { return this._pdf.quad(x1, y1, x2, y2, x3, y3, x4, y4); } - #getColor(superType: string, dossierTemplateId: string, type: string, dossierDictionary: Dictionary) { - let color: string; - let dictionary: Dictionary; - - if (type === 'dossier_redaction') { - dictionary = dossierDictionary; - } else { - dictionary = this._dictionariesMapService.getDictionary(type, dossierTemplateId); - } - - switch (superType) { - case SuperTypes.Hint: - case SuperTypes.Redaction: - color = dictionary.hexColor; - break; - case SuperTypes.Recommendation: - color = dictionary.recommendationHexColor; - break; - case SuperTypes.Skipped: - case SuperTypes.IgnoredHint: - color = dictionary.skippedHexColor; - break; - default: - color = dictionary.hexColor; - break; - } - - return color; - } - - private async _draw( - annotationWrappers: List, - dossierTemplateId: string, - hideSkipped: boolean, - dossierDictionary: Dictionary, - ) { + private async _draw(annotationWrappers: List, hideSkipped: boolean, dictionaries: Dictionary[]) { const totalPages = await firstValueFrom(this._pdf.totalPages$); const annotations = annotationWrappers - .map(annotation => this._computeAnnotation(annotation, dossierTemplateId, hideSkipped, totalPages, dossierDictionary)) + .map(annotation => this._computeAnnotation(annotation, hideSkipped, totalPages, dictionaries)) .filterTruthy(); const documentLoaded = await firstValueFrom(this._documentViewer.loaded$); if (!documentLoaded) { @@ -114,27 +75,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, dossierTemplateId, dossierDictionary); + await this._drawSections(sectionsGrid, dictionaries); } } - private async _drawSections(sectionGrid: ISectionGrid, dossierTemplateId: string, dossierDictionary: Dictionary) { + private async _drawSections(sectionGrid: ISectionGrid, dictionaries: Dictionary[]) { 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(dossierTemplateId, parseInt(page, 10), sectionRectangle, dossierDictionary)); + sections.push(this._computeSection(parseInt(page, 10), sectionRectangle, dictionaries)); }); } await this._annotationManager.add(sections); } - private _computeSection( - dossierTemplateId: string, - pageNumber: number, - sectionRectangle: ISectionRectangle, - dossierDictionary: Dictionary, - ) { + private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle, dictionaries: Dictionary[]) { const rectangleAnnot = this._pdf.rectangle(); const pageHeight = this._documentViewer.getHeight(pageNumber); const rectangle: IRectangle = { @@ -149,19 +105,13 @@ export class AnnotationDrawService { rectangleAnnot.Width = rectangle.width + 2; rectangleAnnot.Height = rectangle.height + 2; rectangleAnnot.ReadOnly = true; - rectangleAnnot.StrokeColor = this.getAndConvertColor('analysis', dossierTemplateId, dossierDictionary, 'analysis'); + rectangleAnnot.StrokeColor = this.convertColor(dictionaries.find(d => d.type === 'analysis').hexColor); rectangleAnnot.StrokeThickness = 1; return rectangleAnnot; } - private _computeAnnotation( - annotationWrapper: AnnotationWrapper, - dossierTemplateId: string, - hideSkipped: boolean, - totalPages: number, - dossierDictionary: Dictionary, - ) { + private _computeAnnotation(annotationWrapper: AnnotationWrapper, hideSkipped: boolean, totalPages: number, dictionaries: Dictionary[]) { 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 @@ -190,12 +140,7 @@ export class AnnotationDrawService { annotation.Opacity = annotationWrapper.isChangeLogRemoved ? DEFAULT_REMOVED_ANNOTATION_OPACITY : DEFAULT_TEXT_ANNOTATION_OPACITY; annotation.setContents(annotationWrapper.content); annotation.PageNumber = pageNumber; - annotation.StrokeColor = this.getAndConvertColor( - annotationWrapper.superType, - dossierTemplateId, - dossierDictionary, - annotationWrapper.type, - ); + annotation.StrokeColor = this.convertColor(annotationWrapper.color); annotation.Id = annotationWrapper.id; annotation.ReadOnly = true; @@ -210,11 +155,8 @@ 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(this.#getColor('redaction', dossierTemplateId, 'preview', dossierDictionary))); - annotation.setCustomData( - 'annotationColor', - String(this.#getColor(annotationWrapper.superType, dossierTemplateId, annotationWrapper.type, dossierDictionary)), - ); + annotation.setCustomData('redactionColor', String(dictionaries.find(d => d.type === 'preview').hexColor)); + annotation.setCustomData('annotationColor', String(annotationWrapper.color)); return annotation; } 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 58c31a035..a7f3aa9dc 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 @@ -13,7 +13,6 @@ export class DictionariesMapService extends EntitiesMapService }), map(colors => { const virtualTypes = [ - { - hexColor: colors.manualRedactionColor || FALLBACK_COLOR, - type: 'dossier_redaction', - hint: false, - recommendation: false, - }, { hexColor: colors.notRedacted || FALLBACK_COLOR, type: SuperTypes.DeclinedSuggestion }, { hexColor: colors.manualRedactionColor || FALLBACK_COLOR, type: 'manual' }, { hexColor: colors.ignoredHintColor || FALLBACK_COLOR, type: SuperTypes.IgnoredHint }, diff --git a/libs/common-ui b/libs/common-ui index 738c38cf5..f2f7283c9 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 738c38cf5f13de9542facd84d8c70f9929b980e6 +Subproject commit f2f7283c9c97e30752fdd4cf56ca3b41999e6962