From a7001188ac39e5242cb1a08962451e47fa6cb594 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Tue, 4 Jul 2023 16:26:50 +0300 Subject: [PATCH 1/3] RED-6801 - WIP on Effective dossier dictionary in Dossier Settings --- .../edit-dossier-dictionary.component.html | 86 ++++++++++++++----- .../edit-dossier-dictionary.component.scss | 73 ++++++++++++---- .../edit-dossier-dictionary.component.ts | 20 ++++- .../edit-dossier-dialog.component.scss | 4 +- .../edit-dossier-dialog.component.ts | 2 +- apps/red-ui/src/assets/i18n/redact/de.json | 7 +- apps/red-ui/src/assets/i18n/redact/en.json | 11 +-- apps/red-ui/src/assets/i18n/scm/de.json | 7 +- apps/red-ui/src/assets/i18n/scm/en.json | 11 +-- 9 files changed, 164 insertions(+), 57 deletions(-) diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html index 8c23e65e9..77665de8d 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html @@ -1,28 +1,72 @@ -
-
-
-
{{ dossierDictionary?.label }}
-
-
- - {{ 'edit-dossier-dialog.dictionary.entries' | translate : { length: (dossierDictionary?.entries || []).length } }} +
+
+
+ +
+ {{ dictionary.label }} +
+
+ + {{ dictionary.entries.length }} entries +
+
+
+
+
+
+ {{ dossierDictionary?.label }} + +
+
+
+ + {{ + 'edit-dossier-dialog.dictionary.entries' | translate : { length: (dossierDictionary?.entries || []).length } + }} +
+
+
+
+
+ + + +
+
-
- +
- - diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.scss b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.scss index 7c1305a41..80786cb85 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.scss +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.scss @@ -1,29 +1,68 @@ -:host { - flex: 1; +:host ::ng-deep .content { + padding: 0; +} + +.dictionary-content { display: flex; - flex-direction: column; height: 100%; -} -.header-wrapper { - display: flex; - justify-content: space-between; + .dictionaries { + border-right: 1px solid var(--iqser-separator); + width: 30%; + overflow-y: scroll; - .header-left { - display: flex; + .dictionary { + height: 40px; + padding: 15px; + border: 1px solid var(--iqser-separator); + display: flex; + gap: 10px; + cursor: pointer; - .iqser-input-group { - margin-left: 24px; + span { + font-weight: bold; + white-space: nowrap; + overflow: hidden !important; + text-overflow: ellipsis; + } + + .details { + display: flex; + flex-direction: column; + gap: 5px; + } + + &.active { + background: var(--iqser-grey-8); + box-shadow: 0 5px 4px -4px rgba(0, 0, 0, 0.2); + cursor: default; + } } } + .entries { + width: 100%; + padding: 24px 32px; + .header-wrapper { + display: flex; + justify-content: space-between; - .display-name { - display: flex; - align-items: center; - margin-bottom: 24px; + .header-left { + display: flex; - > div { - font-weight: 600; + .iqser-input-group { + margin-left: 24px; + } + } + + .display-name { + display: flex; + align-items: center; + margin-bottom: 24px; + + > div { + font-weight: 600; + } + } } } } diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts index 30d1e781f..aaaaac9c7 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts @@ -5,8 +5,14 @@ import { PermissionsService } from '@services/permissions.service'; import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component'; import { DictionaryService } from '@services/entity-services/dictionary.service'; import { CircleButtonTypes, LoadingService } from '@iqser/common-ui'; -import { firstValueFrom } from 'rxjs'; import { DossiersDialogService } from '../../../services/dossiers-dialog.service'; +import { tap } from 'rxjs/operators'; + +enum DictionaryTab { + TO_REDACT, + FALSE_POSITIVES, + FALSE_RECOMMENDATIONS, +} @Component({ selector: 'redaction-edit-dossier-dictionary', @@ -18,8 +24,12 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa canEdit = false; dossierDictionary: Dictionary; + dictionaries: Dictionary[]; + selectedDictionary: Dictionary; + activeDictionaryTab = DictionaryTab.TO_REDACT; readonly circleButtonTypes = CircleButtonTypes; + readonly dictionaryTab = DictionaryTab; @ViewChild(DictionaryManagerComponent, { static: false }) private readonly _dictionaryManager: DictionaryManagerComponent; constructor( @@ -77,8 +87,16 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa }); } + selectDictionaryTab(selectedDictionaryTab: DictionaryTab) { + this.activeDictionaryTab = selectedDictionaryTab; + } + async #updateDossierDictionary() { const { dossierId, dossierTemplateId } = this.dossier; this.dossierDictionary = await this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId); + + this.dictionaries = this._dictionaryService.getPossibleDictionaries(dossierTemplateId, false); + this.dictionaries.forEach(d => console.log(d.hexColor)); + this.selectedDictionary = this.dictionaries[0]; } } diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.scss b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.scss index 47f54c0b8..2b8c3be56 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.scss +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.scss @@ -13,14 +13,16 @@ flex: 1; .content { - padding: 24px 32px; overflow: auto; @include common-mixins.scroll-bar; flex: 1; box-sizing: border-box; + padding: 24px 32px; + margin-right: 16px; &.no-padding { padding: 0; + overflow: hidden; } &.no-actions { diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts index ece30b9ba..5922a419a 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts @@ -89,7 +89,7 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A } get noPaddingTab(): boolean { - return ['dossierAttributes'].includes(this.activeNav); + return ['dossierAttributes', 'dossierDictionary'].includes(this.activeNav); } get showHeading(): boolean { diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 294073cf1..d3acfcf53 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -1132,7 +1132,10 @@ "dictionary": { "edit": "", "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "" + "false-positives": "", + "false-recommendations": "", + "info": "", + "to-redact": "" }, "general-info": { "form": { @@ -1647,8 +1650,6 @@ "license-info-screen": { "backend-version": "Backend-Version der Anwendung", "chart": { - "cumulative": "Seiten insgesamt", - "legend": "", "pages-per-month": "Seiten pro Monat", "total-pages": "Gesamtzahl der Seiten" }, diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 0c2d1092d..228b58935 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -686,7 +686,7 @@ }, "revert-changes": "Revert", "save-changes": "Save Changes", - "search": "Search...", + "search": "Search entries ...", "select-dictionary": "Select a dictionary above to compare with the current one.", "success": { "generic": "Dictionary updated!" @@ -1131,8 +1131,11 @@ "delete-successful": "Dossier {dossierName} was deleted.", "dictionary": { "edit": "Edit", - "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "Info" + "entries": "{length} {length, plural, one{entry} other{entries}} to redact", + "false-positives": "False Positives", + "false-recommendations": "False Recommendations", + "info": "Info", + "to-redact": "To Redact" }, "general-info": { "form": { @@ -1647,8 +1650,6 @@ "license-info-screen": { "backend-version": "Backend Application Version", "chart": { - "cumulative": "Cumulative Pages", - "legend": "Legend", "pages-per-month": "Pages per Month", "total-pages": "Total Pages" }, diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 33d99d99a..7e64332e8 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -1132,7 +1132,10 @@ "dictionary": { "edit": "", "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "" + "false-positives": "", + "false-recommendations": "", + "info": "", + "to-redact": "" }, "general-info": { "form": { @@ -1647,8 +1650,6 @@ "license-info-screen": { "backend-version": "Backend-Version der Anwendung", "chart": { - "cumulative": "Seiten insgesamt", - "legend": "", "pages-per-month": "Seiten pro Monat", "total-pages": "Gesamtzahl der Seiten" }, diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 62c9bc50b..3b2d245c7 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -686,7 +686,7 @@ }, "revert-changes": "Revert", "save-changes": "Save Changes", - "search": "Search...", + "search": "Search entries ...", "select-dictionary": "Select a dictionary above to compare with the current one.", "success": { "generic": "Dictionary updated!" @@ -1131,8 +1131,11 @@ "delete-successful": "Dossier {dossierName} was deleted.", "dictionary": { "edit": "Edit", - "entries": "{length} {length, plural, one{entry} other{entries}}", - "info": "Info" + "entries": "{length} {length, plural, one{entry} other{entries}} to redact", + "false-positives": "False Positives", + "false-recommendations": "False Recommendations", + "info": "Info", + "to-redact": "To Redact" }, "general-info": { "form": { @@ -1647,8 +1650,6 @@ "license-info-screen": { "backend-version": "Backend Application Version", "chart": { - "cumulative": "Cumulative Pages", - "legend": "Legend", "pages-per-month": "Pages per Month", "total-pages": "Total Pages" }, From ca02cf46b5683e3c918ef9457e201975793c676e Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Tue, 18 Jul 2023 22:18:18 +0300 Subject: [PATCH 2/3] RED-6801 - Effective dossier dictionary in Dossier Settings --- .../edit-dossier-dictionary.component.html | 35 +++-- .../edit-dossier-dictionary.component.ts | 40 ++++-- .../entity-services/dictionary.service.ts | 135 +++++++++++++++++- apps/red-ui/src/assets/i18n/redact/de.json | 8 +- apps/red-ui/src/assets/i18n/redact/en.json | 8 +- apps/red-ui/src/assets/i18n/scm/de.json | 10 +- apps/red-ui/src/assets/i18n/scm/en.json | 10 +- 7 files changed, 199 insertions(+), 47 deletions(-) diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html index e2072ba77..7c2e296d8 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html @@ -1,10 +1,10 @@ -
+
@@ -12,7 +12,12 @@
- {{ dictionary.entries.length }} entries + {{ + dictionary.entries.length + + dictionary.falsePositiveEntries.length + + dictionary.falseRecommendationEntries.length + }} + entries
@@ -23,14 +28,26 @@
- {{ dossierDictionary?.label }} + {{ selectedDictionary?.label }}
- {{ - 'edit-dossier-dialog.dictionary.entries' | translate : { length: (dossierDictionary?.entries || []).length } - }} + + {{ 'edit-dossier-dialog.dictionary.entries' | translate : { length: entriesToDisplay.length } }} + + + {{ + 'edit-dossier-dialog.dictionary.false-positive-entries' + | translate : { length: entriesToDisplay.length } + }} + + + {{ + 'edit-dossier-dialog.dictionary.false-recommendation-entries' + | translate : { length: entriesToDisplay.length } + }} +
@@ -56,7 +73,7 @@
diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts index b60af4fa0..f2b55cc78 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts @@ -6,7 +6,8 @@ import { DictionaryManagerComponent } from '@shared/components/dictionary-manage import { DictionaryService } from '@services/entity-services/dictionary.service'; import { CircleButtonTypes, LoadingService } from '@iqser/common-ui'; import { DossiersDialogService } from '../../../services/dossiers-dialog.service'; -import { tap } from 'rxjs/operators'; +import { firstValueFrom } from 'rxjs'; +import { List } from '@iqser/common-ui/lib/utils'; enum DictionaryTab { TO_REDACT, @@ -26,7 +27,8 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa dossierDictionary: Dictionary; dictionaries: Dictionary[]; selectedDictionary: Dictionary; - activeDictionaryTab = DictionaryTab.TO_REDACT; + activeDictionaryTab = DictionaryTab.FALSE_RECOMMENDATIONS; + entriesToDisplay: List = []; readonly circleButtonTypes = CircleButtonTypes; readonly dictionaryTab = DictionaryTab; @@ -40,7 +42,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa ) {} get changed(): boolean { - return this._dictionaryManager.editor.hasChanges; + return this._dictionaryManager?.editor.hasChanges; } get disabled(): boolean { @@ -48,7 +50,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa } get valid(): boolean { - return this._dictionaryManager.editor.hasChanges; + return this._dictionaryManager?.editor.hasChanges; } async ngOnInit() { @@ -80,16 +82,36 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa this._dictionaryManager.revert(); } + selectDictionary(dictionary: Dictionary) { + this.selectedDictionary = dictionary; + this.selectDictionaryTab(DictionaryTab.TO_REDACT); + } + selectDictionaryTab(selectedDictionaryTab: DictionaryTab) { this.activeDictionaryTab = selectedDictionaryTab; + + switch (selectedDictionaryTab) { + case DictionaryTab.TO_REDACT: { + this.entriesToDisplay = this.selectedDictionary.entries; + break; + } + case DictionaryTab.FALSE_POSITIVES: { + this.entriesToDisplay = this.selectedDictionary.falsePositiveEntries; + break; + } + case DictionaryTab.FALSE_RECOMMENDATIONS: { + this.entriesToDisplay = this.selectedDictionary.falseRecommendationEntries; + break; + } + } } async #updateDossierDictionary() { const { dossierId, dossierTemplateId } = this.dossier; - this.dossierDictionary = await this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId); - - this.dictionaries = this._dictionaryService.getPossibleDictionaries(dossierTemplateId, false); - this.dictionaries.forEach(d => console.log(d.hexColor)); - this.selectedDictionary = this.dictionaries[0]; + const dictionaryTypes = this._dictionaryService.getPossibleDictionaries(dossierTemplateId, false, true).map(d => d.type); + this.dictionaries = await firstValueFrom( + this._dictionaryService.loadDictionaryEntriesByType(dictionaryTypes, dossierTemplateId, dossierId), + ); + this.selectDictionary(this.dictionaries[0]); } } 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 35681d847..db8432cd4 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,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { firstValueFrom, forkJoin, Observable, throwError } from 'rxjs'; +import { firstValueFrom, forkJoin, Observable, of, throwError } from 'rxjs'; import { EntitiesService, QueryParam, Toaster } from '@iqser/common-ui'; import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, IDictionary, IUpdateDictionary, SuperTypes } from '@red/domain'; import { catchError, map, switchMap, tap } from 'rxjs/operators'; @@ -14,6 +14,127 @@ import { List } from '@iqser/common-ui/lib/utils'; const MIN_WORD_LENGTH = 2; const IMAGE_TYPES = ['image', 'formula', 'ocr']; +const DICTIONARIES = [ + { + addToDictionaryAction: true, + caseInsensitive: true, + description: 'All site names and addresses, ading the…). Except addresses in published literature and the applicant address.', + dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', + entries: ['test', 'test entry', 'entry 10'], + falsePositiveEntries: ['test false positive entry'], + falseRecommendationEntries: [ + 'false recommendation entry', + 'test', + 'test', + 'test', + 'false recommendation entry', + 'test', + 'test', + 'test', + 'false recommendation entry', + 'test', + 'test', + 'test', + 'false recommendation entry', + 'test', + 'test', + 'test', + 'false recommendation entry', + 'test', + 'test', + 'test', + 'false recommendation entry', + 'test', + 'test', + 'test', + 'false recommendation entry', + 'test', + 'test', + 'test', + 'false recommendation entry', + 'test', + 'test', + 'test', + ], + hexColor: '#9398a0', + recommendationHexColor: '#8df06c', + skippedHexColor: '#c498fa', + hint: false, + label: 'CBI Address', + rank: 140, + recommendation: false, + type: 'CBI_address', + hasDictionary: true, + systemManaged: false, + dossierDictionaryOnly: false, + id: '1', + }, + { + virtual: false, + addToDictionaryAction: true, + caseInsensitive: false, + description: 'All authors named in the study documentation. Except names in published literature.', + dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', + entries: [], + falsePositiveEntries: [], + falseRecommendationEntries: [], + hexColor: '#9398a0', + recommendationHexColor: '#8df06c', + skippedHexColor: '#c498fa', + hint: false, + label: 'CBI Author', + rank: 130, + recommendation: false, + type: 'CBI_author', + hasDictionary: true, + systemManaged: false, + dossierDictionaryOnly: false, + id: '2', + }, + { + addToDictionaryAction: true, + caseInsensitive: true, + description: 'Entries in this dictionary will only be redacted in this dossier.', + dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', + entries: [], + falsePositiveEntries: [], + falseRecommendationEntries: [], + hexColor: '#9398a0', + recommendationHexColor: '#8df06c', + skippedHexColor: '#c498fa', + hint: false, + label: 'Dossier Redaction', + rank: 1500, + recommendation: false, + type: 'dossier_redaction', + hasDictionary: true, + systemManaged: true, + dossierDictionaryOnly: true, + id: '3', + }, + { + addToDictionaryAction: true, + caseInsensitive: false, + description: 'Not authors but listed in the document: Names, signatures, telephone, email etc.; e.g. Reg Manager, QA Manager', + dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', + entries: [], + falsePositiveEntries: [], + falseRecommendationEntries: [], + hexColor: '#9398a0', + recommendationHexColor: '#8df06c', + skippedHexColor: '#c498fa', + hint: false, + label: 'Personal Data', + rank: 150, + recommendation: false, + type: 'PII', + hasDictionary: true, + systemManaged: false, + dossierDictionaryOnly: false, + id: '4', + }, +]; + @Injectable({ providedIn: 'root', }) @@ -261,6 +382,18 @@ export class DictionaryService extends EntitiesService ); } + loadDictionaryEntriesByType(types: string[], dossierTemplateId: string, dossierId: string): Observable { + const queryParams = [{ key: 'dossierId', value: dossierId }]; + const requests = []; + for (const type of types) { + const request = this.getAll(`/${this._defaultModelPath}/${type}/${dossierTemplateId}`, queryParams); + requests.push(request); + } + + // return forkJoin(requests); + return of(DICTIONARIES as any[]); + } + /** * Add dictionary entries with entry type. */ diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 4a120e99a..27011e43b 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -208,9 +208,6 @@ "accept-recommendation": { "label": "Empfehlung annehmen" }, - "accept-suggestion": { - "label": "Genehmigen und zum Wörterbuch hinzufügen" - }, "convert-highlights": { "label": "" }, @@ -328,7 +325,6 @@ } }, "recategorize-image": "neu kategorisieren", - "reject-suggestion": "Vorschlag ablehnen", "remove-annotation": { "remove-redaction": "" }, @@ -1124,11 +1120,11 @@ "change-successful": "Dossier wurde aktualisiert.", "delete-successful": "Dossier wurde gelöscht.", "dictionary": { - "edit": "", "entries": "{length} {length, plural, one{entry} other{entries}}", + "false-positive-entries": "", "false-positives": "", + "false-recommendation-entries": "", "false-recommendations": "", - "info": "", "to-redact": "" }, "general-info": { diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 3fbb132a2..ce89bcf51 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -208,9 +208,6 @@ "accept-recommendation": { "label": "Accept Recommendation" }, - "accept-suggestion": { - "label": "Approve Suggestion" - }, "convert-highlights": { "label": "Convert Selected Earmarks" }, @@ -328,7 +325,6 @@ } }, "recategorize-image": "Recategorize", - "reject-suggestion": "Reject Suggestion", "remove-annotation": { "remove-redaction": "Remove" }, @@ -1124,11 +1120,11 @@ "change-successful": "Dossier {dossierName} was updated.", "delete-successful": "Dossier {dossierName} was deleted.", "dictionary": { - "edit": "Edit", "entries": "{length} {length, plural, one{entry} other{entries}} to redact", + "false-positive-entries": "{length} false positive {length, plural, one{entry} other{entries}}", "false-positives": "False Positives", + "false-recommendation-entries": "{length} false recommendation {length, plural, one{entry} other{entries}}", "false-recommendations": "False Recommendations", - "info": "Info", "to-redact": "To Redact" }, "general-info": { diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 99bfe9ccc..268d843b0 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -1120,11 +1120,11 @@ "change-successful": "Dossier wurde aktualisiert.", "delete-successful": "Dossier wurde gelöscht.", "dictionary": { - "edit": "", "entries": "{length} {length, plural, one{entry} other{entries}}", + "false-positive-entries": "", "false-positives": "", + "false-recommendation-entries": "", "false-recommendations": "", - "info": "", "to-redact": "" }, "general-info": { @@ -2074,12 +2074,6 @@ "undo": "" }, "annotations": "", - "table-header": { - "annotation": "", - "component": "", - "transformation": "", - "value": "" - }, "title": "" }, "rules-screen": { diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 85aa28668..ab2ec6995 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -1120,11 +1120,11 @@ "change-successful": "Dossier {dossierName} was updated.", "delete-successful": "Dossier {dossierName} was deleted.", "dictionary": { - "edit": "Edit", "entries": "{length} {length, plural, one{entry} other{entries}} to redact", + "false-positive-entries": "{length} false positive {length, plural, one{entry} other{entries}}", "false-positives": "False Positives", + "false-recommendation-entries": "{length} false recommendation {length, plural, one{entry} other{entries}}", "false-recommendations": "False Recommendations", - "info": "Info", "to-redact": "To Redact" }, "general-info": { @@ -2074,12 +2074,6 @@ "undo": "Undo to: {value}" }, "annotations": "{type} found on {pageCount, plural, one{page} other{pages}} {pages} by rule #{ruleNumber}", - "table-header": { - "annotation-references": "Annotation references", - "component": "Component", - "transformation-rule": "Transformation rule", - "value": "Value" - }, "title": "Structured Component Management" }, "rules-screen": { From 6531ec1fd3b0175b0a3c3b3074b78e4f9e6b0914 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Wed, 19 Jul 2023 22:40:35 +0300 Subject: [PATCH 3/3] RED-6801 - Effective dossier dictionary in Dossier Settings --- .../edit-dossier-dictionary.component.html | 22 +-- .../edit-dossier-dictionary.component.ts | 45 +++--- .../dictionary-manager.component.ts | 35 ++++- .../entity-services/dictionary.service.ts | 133 +----------------- 4 files changed, 74 insertions(+), 161 deletions(-) diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html index 7c2e296d8..74e4e0b8f 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.html @@ -3,7 +3,7 @@
@@ -33,16 +33,16 @@
- + {{ 'edit-dossier-dialog.dictionary.entries' | translate : { length: entriesToDisplay.length } }} - + {{ 'edit-dossier-dialog.dictionary.false-positive-entries' | translate : { length: entriesToDisplay.length } }} - + {{ 'edit-dossier-dialog.dictionary.false-recommendation-entries' | translate : { length: entriesToDisplay.length } @@ -55,18 +55,18 @@
@@ -75,6 +75,8 @@ [canEdit]="canEdit" [initialEntries]="entriesToDisplay || []" [withFloatingActions]="false" + [selectedDictionaryType]="selectedDictionary.type" + [activeEntryType]="activeEntryType" >
diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts index f2b55cc78..18f531fd3 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit, ViewChild } from '@angular/core'; -import { Dictionary, Dossier } from '@red/domain'; +import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, Dossier } from '@red/domain'; import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface'; import { PermissionsService } from '@services/permissions.service'; import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component'; @@ -9,12 +9,6 @@ import { DossiersDialogService } from '../../../services/dossiers-dialog.service import { firstValueFrom } from 'rxjs'; import { List } from '@iqser/common-ui/lib/utils'; -enum DictionaryTab { - TO_REDACT, - FALSE_POSITIVES, - FALSE_RECOMMENDATIONS, -} - @Component({ selector: 'redaction-edit-dossier-dictionary', templateUrl: './edit-dossier-dictionary.component.html', @@ -24,14 +18,13 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa @Input() dossier: Dossier; canEdit = false; - dossierDictionary: Dictionary; dictionaries: Dictionary[]; selectedDictionary: Dictionary; - activeDictionaryTab = DictionaryTab.FALSE_RECOMMENDATIONS; + activeEntryType = DictionaryEntryTypes.ENTRY; entriesToDisplay: List = []; readonly circleButtonTypes = CircleButtonTypes; - readonly dictionaryTab = DictionaryTab; + readonly entryTypes = DictionaryEntryTypes; @ViewChild(DictionaryManagerComponent, { static: false }) private readonly _dictionaryManager: DictionaryManagerComponent; constructor( @@ -66,9 +59,10 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa this._dictionaryManager.editor.currentEntries, this._dictionaryManager.initialEntries, this.dossier.dossierTemplateId, - this.dossierDictionary.type, + this.selectedDictionary.type, this.dossier.id, false, + this.activeEntryType, ); await this.#updateDossierDictionary(); @@ -82,24 +76,24 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa this._dictionaryManager.revert(); } - selectDictionary(dictionary: Dictionary) { + selectDictionary(dictionary: Dictionary, entryType: DictionaryEntryType = DictionaryEntryTypes.ENTRY) { this.selectedDictionary = dictionary; - this.selectDictionaryTab(DictionaryTab.TO_REDACT); + this.selectEntryType(entryType); } - selectDictionaryTab(selectedDictionaryTab: DictionaryTab) { - this.activeDictionaryTab = selectedDictionaryTab; + selectEntryType(selectedEntryType: DictionaryEntryType) { + this.activeEntryType = selectedEntryType; - switch (selectedDictionaryTab) { - case DictionaryTab.TO_REDACT: { + switch (selectedEntryType) { + case DictionaryEntryTypes.ENTRY: { this.entriesToDisplay = this.selectedDictionary.entries; break; } - case DictionaryTab.FALSE_POSITIVES: { + case DictionaryEntryTypes.FALSE_POSITIVE: { this.entriesToDisplay = this.selectedDictionary.falsePositiveEntries; break; } - case DictionaryTab.FALSE_RECOMMENDATIONS: { + case DictionaryEntryTypes.FALSE_RECOMMENDATION: { this.entriesToDisplay = this.selectedDictionary.falseRecommendationEntries; break; } @@ -112,6 +106,17 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa this.dictionaries = await firstValueFrom( this._dictionaryService.loadDictionaryEntriesByType(dictionaryTypes, dossierTemplateId, dossierId), ); - this.selectDictionary(this.dictionaries[0]); + //TODO remove this when backend will send also the type + this.#setType(dictionaryTypes); + this.selectDictionary(this.dictionaries[0], this.activeEntryType); + } + + //TODO remove this when backend will send also the type + #setType(dictionaryTypes: string[]) { + for (let i = 0; i < this.dictionaries.length; i++) { + const { ...dictionaryWithType } = this.dictionaries[i]; + dictionaryWithType.type = dictionaryTypes[i]; + this.dictionaries[i] = dictionaryWithType as Dictionary; + } } } 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 8f35df1a1..dcada2b58 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,6 +1,14 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core'; import { IconButtonTypes, LoadingService } from '@iqser/common-ui'; -import { Dictionary, DICTIONARY_TYPE_KEY_MAP, DictionaryType, Dossier, DossierTemplate } from '@red/domain'; +import { + Dictionary, + DICTIONARY_TYPE_KEY_MAP, + DictionaryEntryType, + DictionaryEntryTypes, + DictionaryType, + Dossier, + DossierTemplate, +} 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'; @@ -11,6 +19,7 @@ import { saveAs } from 'file-saver'; import { Debounce, List } from '@iqser/common-ui/lib/utils'; import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration; import FindMatch = monaco.editor.FindMatch; +import { firstValueFrom } from 'rxjs'; const SMOOTH_SCROLL = 0; const HELP_MODE_KEYS = { @@ -35,6 +44,8 @@ export class DictionaryManagerComponent implements OnChanges { @Input() canEdit = false; @Input() canDownload = false; @Input() isLeavingPage = false; + @Input() selectedDictionaryType = 'dossier_redaction'; + @Input() activeEntryType: DictionaryEntryType = DictionaryEntryTypes.ENTRY; @Output() readonly saveDictionary = new EventEmitter(); @ViewChild(EditorComponent) readonly editor: EditorComponent; readonly iconButtonTypes = IconButtonTypes; @@ -197,6 +208,12 @@ export class DictionaryManagerComponent implements OnChanges { if (!changes.isLeavingPage) { this.revert(); } + if (changes.activeEntryType && this._dossier?.dossierTemplateId && this.dossier?.dossierId) { + this.#onDossierChanged(this._dossier.dossierTemplateId, this._dossier.dossierId).then(entries => { + this.diffEditorText = entries; + this.showDiffEditor = true; + }); + } } private _applySearchDecorations() { @@ -223,9 +240,19 @@ export class DictionaryManagerComponent implements OnChanges { this.editor.codeEditor.revealLineInCenter(range.startLineNumber, SMOOTH_SCROLL); } - async #onDossierChanged(dossierTemplateId: string, dossierId?: string, type = 'dossier_redaction') { - const dictionary = await this._dictionaryService.getForType(dossierTemplateId, type, dossierId); - return this.#toString([...dictionary.entries]); + async #onDossierChanged(dossierTemplateId: string, dossierId?: string) { + const dictionary = ( + await firstValueFrom( + this._dictionaryService.loadDictionaryEntriesByType([this.selectedDictionaryType], dossierTemplateId, dossierId), + ) + )[0]; + const activeEntries = + this.activeEntryType === DictionaryEntryTypes.ENTRY + ? [...dictionary.entries] + : this.activeEntryType === DictionaryEntryTypes.FALSE_POSITIVE + ? [...dictionary.falsePositiveEntries] + : [...dictionary.falseRecommendationEntries]; + return this.#toString(activeEntries); } #toString(entries: string[]): string { 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 db8432cd4..6402c0485 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 @@ -14,127 +14,6 @@ import { List } from '@iqser/common-ui/lib/utils'; const MIN_WORD_LENGTH = 2; const IMAGE_TYPES = ['image', 'formula', 'ocr']; -const DICTIONARIES = [ - { - addToDictionaryAction: true, - caseInsensitive: true, - description: 'All site names and addresses, ading the…). Except addresses in published literature and the applicant address.', - dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', - entries: ['test', 'test entry', 'entry 10'], - falsePositiveEntries: ['test false positive entry'], - falseRecommendationEntries: [ - 'false recommendation entry', - 'test', - 'test', - 'test', - 'false recommendation entry', - 'test', - 'test', - 'test', - 'false recommendation entry', - 'test', - 'test', - 'test', - 'false recommendation entry', - 'test', - 'test', - 'test', - 'false recommendation entry', - 'test', - 'test', - 'test', - 'false recommendation entry', - 'test', - 'test', - 'test', - 'false recommendation entry', - 'test', - 'test', - 'test', - 'false recommendation entry', - 'test', - 'test', - 'test', - ], - hexColor: '#9398a0', - recommendationHexColor: '#8df06c', - skippedHexColor: '#c498fa', - hint: false, - label: 'CBI Address', - rank: 140, - recommendation: false, - type: 'CBI_address', - hasDictionary: true, - systemManaged: false, - dossierDictionaryOnly: false, - id: '1', - }, - { - virtual: false, - addToDictionaryAction: true, - caseInsensitive: false, - description: 'All authors named in the study documentation. Except names in published literature.', - dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', - entries: [], - falsePositiveEntries: [], - falseRecommendationEntries: [], - hexColor: '#9398a0', - recommendationHexColor: '#8df06c', - skippedHexColor: '#c498fa', - hint: false, - label: 'CBI Author', - rank: 130, - recommendation: false, - type: 'CBI_author', - hasDictionary: true, - systemManaged: false, - dossierDictionaryOnly: false, - id: '2', - }, - { - addToDictionaryAction: true, - caseInsensitive: true, - description: 'Entries in this dictionary will only be redacted in this dossier.', - dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', - entries: [], - falsePositiveEntries: [], - falseRecommendationEntries: [], - hexColor: '#9398a0', - recommendationHexColor: '#8df06c', - skippedHexColor: '#c498fa', - hint: false, - label: 'Dossier Redaction', - rank: 1500, - recommendation: false, - type: 'dossier_redaction', - hasDictionary: true, - systemManaged: true, - dossierDictionaryOnly: true, - id: '3', - }, - { - addToDictionaryAction: true, - caseInsensitive: false, - description: 'Not authors but listed in the document: Names, signatures, telephone, email etc.; e.g. Reg Manager, QA Manager', - dossierTemplateId: '56e8b136-e87e-45fc-851b-434704add3c4', - entries: [], - falsePositiveEntries: [], - falseRecommendationEntries: [], - hexColor: '#9398a0', - recommendationHexColor: '#8df06c', - skippedHexColor: '#c498fa', - hint: false, - label: 'Personal Data', - rank: 150, - recommendation: false, - type: 'PII', - hasDictionary: true, - systemManaged: false, - dossierDictionaryOnly: false, - id: '4', - }, -]; - @Injectable({ providedIn: 'root', }) @@ -386,12 +265,11 @@ export class DictionaryService extends EntitiesService const queryParams = [{ key: 'dossierId', value: dossierId }]; const requests = []; for (const type of types) { - const request = this.getAll(`/${this._defaultModelPath}/${type}/${dossierTemplateId}`, queryParams); + const request = this.getAll(`${this._defaultModelPath}/merged/${type}/${dossierTemplateId}`, queryParams); requests.push(request); } - // return forkJoin(requests); - return of(DICTIONARIES as any[]); + return forkJoin(requests); } /** @@ -424,9 +302,10 @@ export class DictionaryService extends EntitiesService dictionaryEntryType: DictionaryEntryType, dossierId: string, ) { - const queryParams = dossierId - ? [{ key: 'dossierId', value: dossierId }] - : [{ key: 'dictionaryEntryType', value: dictionaryEntryType }]; + const queryParams = [ + { key: 'dossierId', value: dossierId }, + { key: 'dictionaryEntryType', value: dictionaryEntryType }, + ]; const url = `${this._defaultModelPath}/delete/${type}/${dossierTemplateId}`; return firstValueFrom(this._post(entries, url, queryParams)); }