From 4953ed2e68020cd1d4aeaf73cc73c39cb58ee333 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Fri, 5 Jan 2024 18:58:18 +0200 Subject: [PATCH] RED-8045 - Dossier template selection/filter at dossier dictionary comparison --- .../dictionary-screen.component.html | 3 +- .../dictionary/dictionary-screen.component.ts | 8 +- .../dictionary-manager.component.html | 66 +++--- .../dictionary-manager.component.ts | 195 +++++++----------- .../entity-services/dictionary.service.ts | 4 + 5 files changed, 118 insertions(+), 158 deletions(-) diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.html index 4200737b1..df83513b9 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.html @@ -4,8 +4,9 @@ [canDownload]="permissionsService.canDownloadEntityDictionary()" [canEdit]="currentUser.isAdmin && (iqserPermissionsService.has$(roles.dictionaryEntries.write) | async)" [entityType]="entityType" - [filterByDossierTemplate]="true" [initialEntries]="initialEntries$ | async" [isLeavingPage]="isLeavingPage" + [currentDossierTemplateId]="dossierTemplateId" + [selectedDictionaryType]="entityType" [type]="type" > diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts index ecbec474f..30dff241a 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts @@ -20,10 +20,10 @@ export class DictionaryScreenComponent implements OnInit { readonly currentUser = getCurrentUser(); readonly roles = Roles; readonly initialEntries$ = new BehaviorSubject([]); - isLeavingPage = false; readonly type: DictionaryType; readonly entityType = getParam(ENTITY_TYPE); - readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); + isLeavingPage = false; + dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); @ViewChild('dictionaryManager', { static: false }) private readonly _dictionaryManager: DictionaryManagerComponent; @@ -55,7 +55,7 @@ export class DictionaryScreenComponent implements OnInit { await this._dictionaryService.saveEntries( entries, this.initialEntries$.value, - this.#dossierTemplateId, + this.dossierTemplateId, this.entityType, null, true, @@ -70,7 +70,7 @@ export class DictionaryScreenComponent implements OnInit { async #loadEntries() { this._loadingService.start(); try { - const data = await this._dictionaryService.getForType(this.#dossierTemplateId, this.entityType); + const data = await this._dictionaryService.getForType(this.dossierTemplateId, this.entityType); const entries: List = data[DICTIONARY_TYPE_KEY_MAP[this.type]]; this.initialEntries$.next(entries); } catch (e) { diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html index 9800d50dc..c4e368f2c 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html @@ -41,55 +41,45 @@ - -
+ +
- - {{ selectDossierTemplate.name | translate }} - - {{ dossierTemplate.name }} - + + + + {{ dossierTemplate.name }} + +
- - {{ selectDictionary.label | translate }} - - {{ dictionary.label }} - + + + + {{ dossier.dossierName }} + + +
- -
- - - - - {{ dossier.dossierName }} - - - - - -
diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts index 55a0ad55a..494678bb2 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts @@ -1,15 +1,6 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; -import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; -import { - Dictionary, - DICTIONARY_TYPE_KEY_MAP, - DictionaryEntryType, - DictionaryEntryTypes, - DictionaryType, - Dossier, - DossierTemplate, - IDictionary, -} from '@red/domain'; +import { IconButtonTypes, LoadingService } from '@iqser/common-ui'; +import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, DictionaryType, Dossier, DossierTemplate, IDictionary } from '@red/domain'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DictionaryService } from '@services/entity-services/dictionary.service'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; @@ -22,6 +13,7 @@ import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration; import FindMatch = monaco.editor.FindMatch; import { firstValueFrom } from 'rxjs'; +const COMPARE_ENTRIES_ERROR = 'compare-entries-error'; const SMOOTH_SCROLL = 0; const HELP_MODE_KEYS = { dictionary: 'dictionary_entity', @@ -40,9 +32,8 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { @Input() type: DictionaryType = 'dictionary'; @Input() entityType?: string; @Input() currentDossierId: string; - @Input() currentDossierTemplateId: string; + @Input() currentDossierTemplateId!: string; @Input() withFloatingActions = true; - @Input() filterByDossierTemplate = false; @Input() initialEntries: List; @Input() canEdit = false; @Input() canDownload = false; @@ -54,7 +45,8 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { @Output() readonly saveDictionary = new EventEmitter(); @ViewChild(EditorComponent) readonly editor: EditorComponent; readonly iconButtonTypes = IconButtonTypes; - readonly dossiers: Dossier[]; + dossiers: Dossier[]; + dossierTemplates: DossierTemplate[]; currentMatch = 0; findMatches: FindMatch[] = []; diffEditorText = ''; @@ -64,110 +56,64 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { selectDictionary = { label: _('dictionary-overview.compare.select-dictionary'), } as Dictionary; - #compareDictionary = this.selectDictionary; selectDossierTemplate = { name: _('dictionary-overview.compare.select-dossier-template') } as DossierTemplate; compare = false; dictionaries: List = this.#dictionaries; + #dossierTemplate = this.dossierTemplatesService.all[0]; + #dossier = this.selectDossier; + #initialDossierTemplateId: string; constructor( private readonly _dictionaryService: DictionaryService, private readonly _dictionariesMapService: DictionariesMapService, protected readonly _loadingService: LoadingService, - private readonly _changeRef: ChangeDetectorRef, private readonly _activeDossiersService: ActiveDossiersService, - private readonly _toaster: Toaster, readonly dossierTemplatesService: DossierTemplatesService, - ) { - this.dossiers = _activeDossiersService.all; - } + ) {} ngOnInit() { - const templateDictionary = { - id: 'template', - dossierId: 'template', - dossierName: 'Template Dictionary', - dossierTemplateId: this.currentDossierTemplateId, - } as Dossier; - this.dossiers.push(templateDictionary); + this.#initialDossierTemplateId = this.currentDossierTemplateId; + this.#updateDropdownsOptions(); } - private _dossierTemplate = this.selectDossierTemplate; - - get dossierTemplate() { - return this._dossierTemplate; + get selectedDossierTemplate() { + return this.#dossierTemplate; } - set dossierTemplate(value: DossierTemplate) { - this._dossierTemplate = value; + set selectedDossierTemplate(value: DossierTemplate) { + if (!value) { + value = this.dossierTemplates.find(t => t.id === this.#initialDossierTemplateId); + } + this.#dossierTemplate = value; + this.currentDossierTemplateId = value.dossierTemplateId; + this.#dossier = this.selectDossier; this.dictionaries = this.#dictionaries; - this.#compareDictionary = this.selectDictionary; - this.showDiffEditor = false; - } + this.#disableDiffEditor(); - private _dossier = this.selectDossier; + this.#updateDropdownsOptions(false); + } get selectedDossier() { - return this._dossier; + return this.#dossier; } set selectedDossier(dossier: Dossier) { - this._dossier = dossier; + this.#dossier = dossier; if (dossier.dossierName === this.selectDossier.dossierName) { - this.showDiffEditor = false; - this.diffEditorText = ''; + this.#disableDiffEditor(); return; } this.#onDossierChanged(dossier.dossierTemplateId, dossier.id).then(entries => { - this.diffEditorText = entries; - this.showDiffEditor = true; + if (!entries.startsWith(COMPARE_ENTRIES_ERROR)) { + this.diffEditorText = entries; + this.showDiffEditor = true; + } }); } - get compareDictionary() { - return this.#compareDictionary; - } - - set compareDictionary(dictionary: Dictionary) { - this._loadingService.start(); - this.#compareDictionary = dictionary; - - if (dictionary.label === this.selectDictionary.label) { - this.showDiffEditor = false; - this.diffEditorText = ''; - return; - } - const entries: List = - this.#compareDictionary.getEntries(this.type) ?? - this._dictionariesMapService.get(this.#compareDictionary.dossierTemplateId, this.#compareDictionary.type).getEntries(this.type); - - if (entries.length) { - this.diffEditorText = entries.join('\n'); - this.showDiffEditor = true; - return; - } - - this._dictionaryService - .getForType(this.#compareDictionary.dossierTemplateId, this.#compareDictionary.type) - .then(values => { - this.#compareDictionary.setEntries([...values[DICTIONARY_TYPE_KEY_MAP[this.type]]] ?? [], this.type); - this.diffEditorText = [...(this.#compareDictionary.getEntries(this.type) as string[])].join('\n'); - this.showDiffEditor = true; - this._changeRef.markForCheck(); - this._loadingService.stop(); - }) - .catch(() => this.#compareDictionary.setEntries([], this.type)); - } - - get dossierTemplateIsNotSelected() { - return this.filterByDossierTemplate && this._dossierTemplate.name === this.selectDossierTemplate.name; - } - get optionNotSelected() { - if (this.filterByDossierTemplate) { - return this.selectDictionary.label === this.#compareDictionary.label; - } return this.selectedDossier.dossierName === this.selectDossier.dossierName; } @@ -176,10 +122,16 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { } get #dictionaries(): Dictionary[] { - if (!this._dossierTemplate || this._dossierTemplate.name === this.selectDossierTemplate.name) { + if (!this.#dossierTemplate || this.#dossierTemplate.name === this.selectDossierTemplate.name) { return; } - return this._dictionariesMapService.get(this.dossierTemplate?.dossierTemplateId).filter(dict => !dict.virtual); + return this._dictionariesMapService.get(this.selectedDossierTemplate?.dossierTemplateId).filter(dict => !dict.virtual); + } + + get #templatesWithCurrentEntityType() { + return this.dossierTemplatesService.all.filter(t => + this._dictionaryService.hasType(t.dossierTemplateId, this.selectedDictionaryType), + ); } download(): void { @@ -198,8 +150,8 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { @Debounce() searchChanged(text: string) { - this.findMatches = this._getMatches(text.toLowerCase()); - this._applySearchDecorations(); + this.findMatches = this.#getMatches(text.toLowerCase()); + this.#applySearchDecorations(); this.currentMatch = 0; this.nextSearchMatch(); @@ -211,7 +163,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { } this.currentMatch = this.currentMatch < this.findMatches.length ? this.currentMatch + 1 : 1; - this._scrollToCurrentMatch(); + this.#scrollToCurrentMatch(); } previousSearchMatch(): void { @@ -220,7 +172,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { } this.currentMatch = this.currentMatch > 1 ? this.currentMatch - 1 : this.findMatches.length; - this._scrollToCurrentMatch(); + this.#scrollToCurrentMatch(); } toggleCompareMode() { @@ -231,39 +183,39 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { } ngOnChanges(changes: SimpleChanges): void { - if ( - (changes.selectedDictionaryType || changes.activeEntryType) && - this._dossier?.dossierTemplateId && - this.selectedDossier?.dossierId - ) { - this.#onDossierChanged(this._dossier.dossierTemplateId, this._dossier.dossierId).then(entries => { - this.diffEditorText = entries; - this.showDiffEditor = true; + if (changes.activeEntryType && this.#dossier?.dossierTemplateId && this.selectedDossier?.dossierId) { + this.#onDossierChanged(this.#dossier.dossierTemplateId, this.#dossier.dossierId).then(entries => { + if (!entries.startsWith(COMPARE_ENTRIES_ERROR)) { + this.diffEditorText = entries; + this.showDiffEditor = true; + } }); } + if (changes.selectedDictionaryType) { - this.searchText = ''; + this.#disableDiffEditor(); + this.#updateDropdownsOptions(); } } - private _applySearchDecorations() { + #applySearchDecorations() { this._searchDecorations = this.editor.codeEditor?.deltaDecorations(this._searchDecorations, []) || []; - const decorations = this.findMatches.map(match => this._getSearchDecoration(match)); + const decorations = this.findMatches.map(match => this.#getSearchDecoration(match)); this._searchDecorations = this.editor.codeEditor?.deltaDecorations(this._searchDecorations, decorations) || []; } - private _getMatches(text: string): FindMatch[] { + #getMatches(text: string): FindMatch[] { const model = this.editor.codeEditor?.getModel(); return model?.findMatches(text, false, false, false, null, false) || []; } - private _getSearchDecoration(match: FindMatch): IModelDeltaDecoration { + #getSearchDecoration(match: FindMatch): IModelDeltaDecoration { return { range: match.range, options: { inlineClassName: 'search-marker' } }; } - private _scrollToCurrentMatch(): void { + #scrollToCurrentMatch(): void { const range = this.findMatches[this.currentMatch - 1].range; this.editor.codeEditor.setSelection(range); @@ -279,14 +231,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { await firstValueFrom( this._dictionaryService.loadDictionaryEntriesByType([this.selectedDictionaryType], dossierTemplateId, dossierId), ).catch(() => { - const selectedDossierTemplate = this.dossierTemplatesService.find(dossierTemplateId); - this._toaster.error(_('dictionary-overview.compare-error'), { - params: { - type: this.selectedDictionaryTypeLabel, - template: selectedDossierTemplate.name, - }, - }); - return [{ entries: [], type: '' }]; + return [{ entries: [COMPARE_ENTRIES_ERROR], type: '' }]; }) )[0]; } @@ -294,8 +239,28 @@ export class DictionaryManagerComponent implements OnChanges, OnInit { this.activeEntryType === DictionaryEntryTypes.ENTRY || this.hint ? [...dictionary.entries] : this.activeEntryType === DictionaryEntryTypes.FALSE_POSITIVE - ? [...dictionary.falsePositiveEntries] - : [...dictionary.falseRecommendationEntries]; + ? [...dictionary.falsePositiveEntries] + : [...dictionary.falseRecommendationEntries]; return activeEntries.join('\n'); } + + #updateDropdownsOptions(updateSelectedDossierTemplate = true) { + if (updateSelectedDossierTemplate) { + this.dossierTemplates = this.#templatesWithCurrentEntityType; + this.selectedDossierTemplate = this.dossierTemplates.find(t => t.id === this.currentDossierTemplateId); + } + this.dossiers = this._activeDossiersService.all.filter(d => d.dossierTemplateId === this.currentDossierTemplateId); + const templateDictionary = { + id: 'template', + dossierId: 'template', + dossierName: 'Template Dictionary', + dossierTemplateId: this.currentDossierTemplateId, + } as Dossier; + this.dossiers.push(templateDictionary); + } + + #disableDiffEditor() { + this.showDiffEditor = false; + this.diffEditorText = ''; + } } 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 04ed5d4ca..a94c5c167 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 @@ -133,6 +133,10 @@ export class DictionaryService extends EntitiesService return !!this._dictionariesMapService.get(dossierTemplateId).find(e => e.type === SuperTypes.ManualRedaction && !e.virtual); } + hasType(dossierTemplateId: string, type: string): boolean { + return !!this._dictionariesMapService.get(dossierTemplateId).find(e => e.type === type && !e.virtual); + } + getRedactTextDictionaries(dossierTemplateId: string, dossierDictionaryOnly: boolean): Dictionary[] { return this._dictionariesMapService .get(dossierTemplateId)