Revision of the dossier dictionary presentation
This commit is contained in:
parent
63e53cb2ed
commit
5de6b359ee
@ -18,12 +18,15 @@
|
||||
<div class="small-label stats-subtitle">
|
||||
<div>
|
||||
<mat-icon svgIcon="red:entries"></mat-icon>
|
||||
{{
|
||||
dictionary.entries.length +
|
||||
dictionary.falsePositiveEntries.length +
|
||||
dictionary.falseRecommendationEntries.length
|
||||
}}
|
||||
entries
|
||||
<span
|
||||
[translateParams]="{
|
||||
count:
|
||||
dictionary.entries.length +
|
||||
dictionary.falsePositiveEntries.length +
|
||||
dictionary.falseRecommendationEntries.length,
|
||||
}"
|
||||
translate="edit-dossier-dialog.dictionary.entries-count"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -36,12 +39,12 @@
|
||||
<div class="flex-align-items-center">
|
||||
{{ selectedDictionary?.label }}
|
||||
<iqser-circle-button
|
||||
*ngIf="selectedDictionary.dossierDictionaryOnly && selectedDictionary.hasDictionary"
|
||||
(action)="openEditDictionaryModal()"
|
||||
*ngIf="selectedDictionary.dossierDictionaryOnly && selectedDictionary.hasDictionary"
|
||||
[size]="20"
|
||||
[tooltip]="'edit-dossier-dialog.dictionary.edit-button-tooltip' | translate"
|
||||
icon="iqser:edit"
|
||||
class="p-left-8"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
<div class="small-label stats-subtitle">
|
||||
@ -68,23 +71,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!selectedDictionary.hint" [class.read-only]="!canEdit" class="header-right flex">
|
||||
<iqser-icon-button
|
||||
(click)="selectEntryType(entryTypes.ENTRY)"
|
||||
[active]="activeEntryType === entryTypes.ENTRY"
|
||||
[label]="'edit-dossier-dialog.dictionary.to-redact' | translate"
|
||||
></iqser-icon-button>
|
||||
<iqser-icon-button
|
||||
(click)="selectEntryType(entryTypes.FALSE_POSITIVE)"
|
||||
[active]="activeEntryType === entryTypes.FALSE_POSITIVE"
|
||||
[label]="'edit-dossier-dialog.dictionary.false-positives' | translate"
|
||||
></iqser-icon-button>
|
||||
<iqser-icon-button
|
||||
(click)="selectEntryType(entryTypes.FALSE_RECOMMENDATION)"
|
||||
[active]="activeEntryType === entryTypes.FALSE_RECOMMENDATION"
|
||||
[label]="'edit-dossier-dialog.dictionary.false-recommendations' | translate"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<redaction-dictionary-manager
|
||||
@ -97,6 +83,32 @@
|
||||
[selectedDictionaryTypeLabel]="selectedDictionary.label"
|
||||
[selectedDictionaryType]="selectedDictionary.type"
|
||||
[withFloatingActions]="false"
|
||||
></redaction-dictionary-manager>
|
||||
>
|
||||
<ng-container slot="typeSwitch">
|
||||
<div *ngIf="!selectedDictionary.hint" [class.read-only]="!canEdit" class="header-right flex">
|
||||
<iqser-icon-button
|
||||
(click)="selectEntryType(entryTypes.ENTRY)"
|
||||
[active]="activeEntryType === entryTypes.ENTRY"
|
||||
[label]="'edit-dossier-dialog.dictionary.to-redact' | translate: { count: selectedDictionary.entries.length }"
|
||||
></iqser-icon-button>
|
||||
<iqser-icon-button
|
||||
(click)="selectEntryType(entryTypes.FALSE_POSITIVE)"
|
||||
[active]="activeEntryType === entryTypes.FALSE_POSITIVE"
|
||||
[label]="
|
||||
'edit-dossier-dialog.dictionary.false-positives'
|
||||
| translate: { count: selectedDictionary.falsePositiveEntries.length }
|
||||
"
|
||||
></iqser-icon-button>
|
||||
<iqser-icon-button
|
||||
(click)="selectEntryType(entryTypes.FALSE_RECOMMENDATION)"
|
||||
[active]="activeEntryType === entryTypes.FALSE_RECOMMENDATION"
|
||||
[label]="
|
||||
'edit-dossier-dialog.dictionary.false-recommendations'
|
||||
| translate: { count: selectedDictionary.falseRecommendationEntries.length }
|
||||
"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-container>
|
||||
</redaction-dictionary-manager>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,29 +1,7 @@
|
||||
<div class="content-container">
|
||||
<div class="actions-bar">
|
||||
<div class="flex-align-items-center mr-32">
|
||||
<div class="iqser-input-group w-250">
|
||||
<input
|
||||
#inputElement
|
||||
(keyup)="searchChanged(searchText)"
|
||||
[(ngModel)]="searchText"
|
||||
[class.with-matches]="searchText.length > 0"
|
||||
[placeholder]="'dictionary-overview.search' | translate"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
<div class="input-icons">
|
||||
<div *ngIf="searchText.length === 0" class="no-input">
|
||||
<mat-icon svgIcon="iqser:search"></mat-icon>
|
||||
</div>
|
||||
|
||||
<div *ngIf="searchText.length > 0" class="with-input">
|
||||
{{ currentMatch + '/' + findMatches.length }}
|
||||
<mat-icon (click)="previousSearchMatch()" class="pointer" svgIcon="red:arrow-up"></mat-icon>
|
||||
<mat-icon (click)="nextSearchMatch()" class="pointer" svgIcon="iqser:arrow-down"></mat-icon>
|
||||
<mat-icon (click)="revert(); inputElement.focus()" class="pointer" svgIcon="iqser:close"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-content select="[slot=typeSwitch]"></ng-content>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="download()"
|
||||
@ -33,6 +11,13 @@
|
||||
class="ml-8"
|
||||
icon="iqser:download"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="editor.openFindPanel()"
|
||||
[matTooltip]="'dictionary-overview.search' | translate"
|
||||
class="ml-8"
|
||||
icon="iqser:search"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
|
||||
<div class="compare">
|
||||
|
||||
@ -8,9 +8,7 @@ import { DossierTemplatesService } from '@services/dossier-templates/dossier-tem
|
||||
import { EditorComponent } from '@shared/components/editor/editor.component';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
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 { List } from '@iqser/common-ui/lib/utils';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
@ -23,7 +21,6 @@ import { MatOption, MatSelect } from '@angular/material/select';
|
||||
import { MatDivider } from '@angular/material/divider';
|
||||
|
||||
const COMPARE_ENTRIES_ERROR = 'compare-entries-error';
|
||||
const SMOOTH_SCROLL = 0;
|
||||
const HELP_MODE_KEYS = {
|
||||
dictionary: 'dictionary_entity',
|
||||
'false-positive': 'false_recommendations_entity',
|
||||
@ -53,8 +50,6 @@ const HELP_MODE_KEYS = {
|
||||
],
|
||||
})
|
||||
export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
private _searchDecorations: string[] = [];
|
||||
readonly #currentTab = window.location.href.split('/').pop();
|
||||
@Input() type: DictionaryType = 'dictionary';
|
||||
@Input() entityType?: string;
|
||||
@Input() currentDossierId: string;
|
||||
@ -73,11 +68,8 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
dossiers: Dossier[];
|
||||
dossierTemplates: DossierTemplate[] = this.dossierTemplatesService.all;
|
||||
currentMatch = 0;
|
||||
findMatches: FindMatch[] = [];
|
||||
diffEditorText = '';
|
||||
showDiffEditor = false;
|
||||
searchText = '';
|
||||
selectDossier = { dossierName: _('dictionary-overview.compare.select-dossier') } as Dossier;
|
||||
selectDictionary = {
|
||||
label: _('dictionary-overview.compare.select-dictionary'),
|
||||
@ -85,10 +77,11 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
selectDossierTemplate = { name: _('dictionary-overview.compare.select-dossier-template') } as DossierTemplate;
|
||||
compare = false;
|
||||
dictionaries: List<Dictionary> = this.#dictionaries;
|
||||
protected initialDossierTemplateId: string;
|
||||
readonly #currentTab = window.location.href.split('/').pop();
|
||||
#dossierTemplate = this.dossierTemplatesService.all[0];
|
||||
#dossier = this.selectDossier;
|
||||
#dictionary = this.selectDictionary;
|
||||
protected initialDossierTemplateId: string;
|
||||
|
||||
constructor(
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
@ -99,11 +92,6 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
readonly dossierTemplatesService: DossierTemplatesService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.initialDossierTemplateId = this.currentDossierTemplateId;
|
||||
this.#updateDropdownsOptions();
|
||||
}
|
||||
|
||||
get selectedDossierTemplate() {
|
||||
return this.#dossierTemplate;
|
||||
}
|
||||
@ -150,6 +138,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
if (dictionary.type) {
|
||||
this.selectedDictionaryType = dictionary.type;
|
||||
this.#dictionary = dictionary;
|
||||
console.log(dictionary);
|
||||
this.#onDossierChanged(this.#dossier.dossierTemplateId).then(entries => this.#updateDiffEditorText(entries));
|
||||
}
|
||||
}
|
||||
@ -185,6 +174,11 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.initialDossierTemplateId = this.currentDossierTemplateId;
|
||||
this.#updateDropdownsOptions();
|
||||
}
|
||||
|
||||
download(): void {
|
||||
const content = this.editor.currentEntries.join('\n');
|
||||
const blob = new Blob([content], {
|
||||
@ -195,35 +189,6 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
|
||||
revert() {
|
||||
this.editor?.revert();
|
||||
this.searchText = '';
|
||||
this.searchChanged('');
|
||||
}
|
||||
|
||||
@Debounce()
|
||||
searchChanged(text: string) {
|
||||
this.findMatches = this.#getMatches(text.toLowerCase());
|
||||
this.#applySearchDecorations();
|
||||
|
||||
this.currentMatch = 0;
|
||||
this.nextSearchMatch();
|
||||
}
|
||||
|
||||
nextSearchMatch(): void {
|
||||
if (this.findMatches.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentMatch = this.currentMatch < this.findMatches.length ? this.currentMatch + 1 : 1;
|
||||
this.#scrollToCurrentMatch();
|
||||
}
|
||||
|
||||
previousSearchMatch(): void {
|
||||
if (this.findMatches.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentMatch = this.currentMatch > 1 ? this.currentMatch - 1 : this.findMatches.length;
|
||||
this.#scrollToCurrentMatch();
|
||||
}
|
||||
|
||||
toggleCompareMode() {
|
||||
@ -246,30 +211,6 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
#applySearchDecorations() {
|
||||
this._searchDecorations = this.editor.codeEditor?.deltaDecorations(this._searchDecorations, []) || [];
|
||||
|
||||
const decorations = this.findMatches.map(match => this.#getSearchDecoration(match));
|
||||
|
||||
this._searchDecorations = this.editor.codeEditor?.deltaDecorations(this._searchDecorations, decorations) || [];
|
||||
}
|
||||
|
||||
#getMatches(text: string): FindMatch[] {
|
||||
const model = this.editor.codeEditor?.getModel();
|
||||
return model?.findMatches(text, false, false, false, null, false) || [];
|
||||
}
|
||||
|
||||
#getSearchDecoration(match: FindMatch): IModelDeltaDecoration {
|
||||
return { range: match.range, options: { inlineClassName: 'search-marker' } };
|
||||
}
|
||||
|
||||
#scrollToCurrentMatch(): void {
|
||||
const range = this.findMatches[this.currentMatch - 1].range;
|
||||
|
||||
this.editor.codeEditor.setSelection(range);
|
||||
this.editor.codeEditor.revealLineInCenter(range.startLineNumber, SMOOTH_SCROLL);
|
||||
}
|
||||
|
||||
async #onDossierChanged(dossierTemplateId: string, dossierId?: string) {
|
||||
let dictionary: IDictionary;
|
||||
if (dossierId === 'template') {
|
||||
|
||||
@ -5,15 +5,15 @@ import { Subject } from 'rxjs';
|
||||
import { debounceTime, filter, tap } from 'rxjs/operators';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { List, OnChange } from '@iqser/common-ui/lib/utils';
|
||||
import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions;
|
||||
import ICodeEditor = monaco.editor.ICodeEditor;
|
||||
import IDiffEditor = monaco.editor.IDiffEditor;
|
||||
import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration;
|
||||
import ILineChange = monaco.editor.ILineChange;
|
||||
import IEditorMouseEvent = monaco.editor.IEditorMouseEvent;
|
||||
import { MonacoEditorModule, MonacoStandaloneCodeEditor, MonacoStandaloneDiffEditor } from '@materia-ui/ngx-monaco-editor';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NgIf } from '@angular/common';
|
||||
import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions;
|
||||
import IDiffEditor = monaco.editor.IDiffEditor;
|
||||
import ICodeEditor = monaco.editor.ICodeEditor;
|
||||
import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration;
|
||||
import ILineChange = monaco.editor.ILineChange;
|
||||
import IEditorMouseEvent = monaco.editor.IEditorMouseEvent;
|
||||
|
||||
const MIN_WORD_LENGTH = 2;
|
||||
const lineChangeToDecoration = ({ originalEndLineNumber, originalStartLineNumber }: ILineChange) =>
|
||||
@ -35,10 +35,6 @@ const notZero = (lineChange: ILineChange) => lineChange.originalEndLineNumber !=
|
||||
imports: [MonacoEditorModule, FormsModule, NgIf],
|
||||
})
|
||||
export class EditorComponent implements OnInit, OnChanges {
|
||||
#initialEntriesSet = new Set<string>();
|
||||
private _diffEditor: IDiffEditor;
|
||||
private _decorations: string[] = [];
|
||||
protected readonly _editorTextChanged$ = new Subject<string>();
|
||||
@Input() showDiffEditor = false;
|
||||
@Input() diffEditorText: string;
|
||||
@Input() @OnChange<List, EditorComponent>('revert') initialEntries: List;
|
||||
@ -51,6 +47,10 @@ export class EditorComponent implements OnInit, OnChanges {
|
||||
editorOptions: IStandaloneEditorConstructionOptions = {};
|
||||
codeEditor: ICodeEditor;
|
||||
value: string;
|
||||
protected readonly _editorTextChanged$ = new Subject<string>();
|
||||
#initialEntriesSet = new Set<string>();
|
||||
private _diffEditor: IDiffEditor;
|
||||
private _decorations: string[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly _loadingService: LoadingService,
|
||||
@ -84,6 +84,11 @@ export class EditorComponent implements OnInit, OnChanges {
|
||||
return this.currentEntries.length;
|
||||
}
|
||||
|
||||
async openFindPanel(): Promise<void> {
|
||||
const editor = this.showDiffEditor ? this._diffEditor.getOriginalEditor() : this.codeEditor;
|
||||
await editor.getAction('actions.find').run();
|
||||
}
|
||||
|
||||
onPaste(event: ClipboardEvent) {
|
||||
if ((event.target as HTMLTextAreaElement).ariaRoleDescription === 'editor') {
|
||||
this._loadingService.start();
|
||||
|
||||
@ -1234,11 +1234,12 @@
|
||||
"title": "{label} bearbeiten"
|
||||
},
|
||||
"entries": "{length} {length, plural, one{Eintrag} other{Einträge}}",
|
||||
"entries-count": "",
|
||||
"false-positive-entries": "{length} {length, plural, one{Falsch-Positiver} other{Falsch-Positive}}",
|
||||
"false-positives": "Falsch-Positive",
|
||||
"false-positives": "Falsch-Positive ({count})",
|
||||
"false-recommendation-entries": "{length} {length, plural, one{falsche Empfehlung} other{falsche Empfehlungen}}",
|
||||
"false-recommendations": "Falsche Empfehlungen",
|
||||
"to-redact": "Schwärzungen"
|
||||
"false-recommendations": "Falsche Empfehlungen ({count})",
|
||||
"to-redact": "Schwärzungen ({count})"
|
||||
},
|
||||
"general-info": {
|
||||
"form": {
|
||||
|
||||
@ -1234,11 +1234,12 @@
|
||||
"title": "Edit {label}"
|
||||
},
|
||||
"entries": "{length} {length, plural, one{entry} other{entries}} to redact",
|
||||
"entries-count": "{count} {count, plural, one{entry} other{entries}}",
|
||||
"false-positive-entries": "{length} false positive {length, plural, one{entry} other{entries}}",
|
||||
"false-positives": "False positives",
|
||||
"false-positives": "False positives ({count})",
|
||||
"false-recommendation-entries": "{length} false recommendation {length, plural, one{entry} other{entries}}",
|
||||
"false-recommendations": "False recommendations",
|
||||
"to-redact": "To redact"
|
||||
"false-recommendations": "False recommendations ({count})",
|
||||
"to-redact": "Entries ({count})"
|
||||
},
|
||||
"general-info": {
|
||||
"form": {
|
||||
@ -1264,7 +1265,7 @@
|
||||
"choose-download": "Select the documents for your download:",
|
||||
"dictionary": "Dictionaries",
|
||||
"dossier-attributes": "Dossier attributes",
|
||||
"dossier-dictionary": "Dictionaries",
|
||||
"dossier-dictionary": "Dossier entries",
|
||||
"dossier-info": "Dossier info",
|
||||
"download-package": "Download package",
|
||||
"general-info": "General information",
|
||||
|
||||
@ -1234,11 +1234,12 @@
|
||||
"title": ""
|
||||
},
|
||||
"entries": "{length} {length, plural, one{entry} other{entries}} to {hint, select, true{annotate} other{redact}}",
|
||||
"entries-count": "",
|
||||
"false-positive-entries": "{length} false positive {length, plural, one{entry} other{entries}}",
|
||||
"false-positives": "False positives",
|
||||
"false-positives": "False positives ({count})",
|
||||
"false-recommendation-entries": "{length} false recommendation {length, plural, one{entry} other{entries}}",
|
||||
"false-recommendations": "False recommendations",
|
||||
"to-redact": "To redact"
|
||||
"false-recommendations": "False recommendations ({count})",
|
||||
"to-redact": "To redact ({count})"
|
||||
},
|
||||
"general-info": {
|
||||
"form": {
|
||||
|
||||
@ -1234,11 +1234,12 @@
|
||||
"title": ""
|
||||
},
|
||||
"entries": "{length} {length, plural, one{entry} other{entries}} to {hint, select, true{annotate} other{redact}}",
|
||||
"entries-count": "{count} {count, plural, one{entry} other{entries}}",
|
||||
"false-positive-entries": "{length} false positive {length, plural, one{entry} other{entries}}",
|
||||
"false-positives": "False positives",
|
||||
"false-positives": "False positives ({count})",
|
||||
"false-recommendation-entries": "{length} false recommendation {length, plural, one{entry} other{entries}}",
|
||||
"false-recommendations": "False recommendations",
|
||||
"to-redact": "To redact"
|
||||
"false-recommendations": "False recommendations ({count})",
|
||||
"to-redact": "To redact ({count})"
|
||||
},
|
||||
"general-info": {
|
||||
"form": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user