Merge branch 'VM/RED-10332' into 'master'

RED-10332 - Dossier Template not changeable when comparing dossier...

Closes RED-10332

See merge request redactmanager/red-ui!491
This commit is contained in:
Dan Percic 2024-11-08 16:08:36 +01:00
commit f5639ec79d
5 changed files with 143 additions and 120 deletions

View File

@ -54,8 +54,8 @@
[currentDossierTemplateId]="dossier.dossierTemplateId"
[hint]="selectedDictionary.hint"
[initialEntries]="entriesToDisplay || []"
[selectedDictionaryTypeLabel]="selectedDictionary.label"
[selectedDictionaryType]="selectedDictionary.type"
[activeDictionary]="selectedDictionary"
[withFloatingActions]="false"
>
<ng-container slot="typeSwitch">

View File

@ -83,7 +83,7 @@ export class EditDossierDictionaryComponent implements OnInit {
try {
await this._dictionaryService.saveEntries(
this._dictionaryManager.editor.currentEntries,
this._dictionaryManager.initialEntries,
this._dictionaryManager.initialEntries(),
this.dossier.dossierTemplateId,
this.selectedDictionary.type,
this.dossier.id,

View File

@ -24,8 +24,8 @@ export class FileDownloadBtnComponent implements OnChanges {
readonly tooltipPosition = input<'above' | 'below' | 'before' | 'after'>('above');
readonly type = input<CircleButtonType>(CircleButtonTypes.default);
readonly tooltipClass = input<string>();
readonly disabled = input<boolean>(false);
readonly singleFileDownload = input<boolean>(false);
readonly disabled = input(false, { transform: booleanAttribute });
readonly singleFileDownload = input(false, { transform: booleanAttribute });
readonly dossierDownload = input(false, { transform: booleanAttribute });
readonly dropdownButton = computed(() => this.isDocumine && (this.dossierDownload() || this.singleFileDownload()));
tooltip: string;

View File

@ -5,7 +5,7 @@
<iqser-circle-button
(action)="download()"
*ngIf="canDownload"
*ngIf="canDownload()"
[attr.help-mode-key]="helpModeKey"
[matTooltip]="'dictionary-overview.download' | translate"
class="ml-8"
@ -29,63 +29,73 @@
</div>
<ng-container>
<div *ngIf="dossierTemplates" class="iqser-input-group w-200 mt-0 mr-8">
<mat-form-field>
<mat-select
[(ngModel)]="selectedDossierTemplate"
[disabled]="!compare || dossierTemplates.length === 1"
[placeholder]="
selectedDossierTemplate.id ? selectedDossierTemplate.name : (selectedDossierTemplate.name | translate)
"
>
<ng-container *ngFor="let dossierTemplate of dossierTemplates">
<mat-option
*ngIf="!initialDossierTemplateId || dossierTemplate?.id !== selectedDossierTemplate.id"
[class.mat-mdc-option-active]="false"
[value]="dossierTemplate"
>
{{ dossierTemplate.id ? dossierTemplate.name : (dossierTemplate.name | translate) }}
</mat-option>
</ng-container>
</mat-select>
</mat-form-field>
</div>
@if (dossierTemplates) {
<div class="iqser-input-group w-200 mt-0 mr-8">
<mat-form-field>
<mat-select
[(ngModel)]="selectedDossierTemplate"
[disabled]="!compare || dossierTemplates.length === 1"
[placeholder]="
selectedDossierTemplate.id ? selectedDossierTemplate.name : (selectedDossierTemplate.name | translate)
"
>
@for (dossierTemplate of dossierTemplates; track dossierTemplate) {
@if (!initialDossierTemplateId || dossierTemplate?.id !== selectedDossierTemplate.id) {
<mat-option [class.mat-mdc-option-active]="false" [value]="dossierTemplate">
{{ dossierTemplate.id ? dossierTemplate.name : (dossierTemplate.name | translate) }}
</mat-option>
}
}
</mat-select>
</mat-form-field>
</div>
}
<div class="iqser-input-group w-200 mt-0">
<mat-form-field *ngIf="initialDossierTemplateId">
<mat-select
[(ngModel)]="selectedDossier"
[disabled]="!compare || (dossiers.length === 1 && !optionNotSelected)"
[placeholder]="selectedDossier.dossierId ? selectedDossier.dossierName : (selectDictionary.label | translate)"
>
<ng-container *ngFor="let dossier of dossiers; let index = index">
<mat-option
*ngIf="dossier.dossierId !== selectedDossier.dossierId"
[class.mat-mdc-option-active]="false"
[value]="dossier"
>
{{ dossier.dossierName }}
</mat-option>
<mat-divider
*ngIf="index === dossiers.length - 2 && !selectedDossier.dossierId?.includes('template')"
></mat-divider>
</ng-container>
</mat-select>
</mat-form-field>
@if (initialDossierTemplateId) {
<mat-form-field>
<mat-select
[(ngModel)]="selectedDossier"
[disabled]="!compare || (dossiers.length === 1 && !optionNotSelected)"
[placeholder]="
selectedDossier.dossierId ? selectedDossier.dossierName : (selectDictionary.label | translate)
"
>
@for (dossier of dossiers; track dossier; let index = $index) {
@if (dossier.dossierId !== selectedDossier.dossierId) {
@if (!activeDictionary().dossierDictionaryOnly) {
<mat-option [class.mat-mdc-option-active]="false" [value]="dossier">
{{ dossier.dossierName }}
</mat-option>
@if (index === dossiers.length - 2 && !selectedDossier.dossierId?.includes('template')) {
<mat-divider></mat-divider>
}
} @else if (!dossier.dossierId?.includes('template')) {
<mat-option [class.mat-mdc-option-active]="false" [value]="dossier">
{{ dossier.dossierName }}
</mat-option>
}
}
}
</mat-select>
</mat-form-field>
}
<mat-form-field *ngIf="!initialDossierTemplateId">
<mat-select
[(ngModel)]="selectedDictionary"
[disabled]="!compare || !templateSelected"
[placeholder]="selectedDictionary.id ? selectedDictionary.label : (selectDictionary.label | translate)"
>
<ng-container *ngFor="let dictionary of dictionaries; let index = index">
<mat-option [value]="dictionary">
{{ dictionary.id ? dictionary.label : (dictionary.label | translate) }}
</mat-option>
</ng-container>
</mat-select>
</mat-form-field>
@if (!initialDossierTemplateId) {
<mat-form-field>
<mat-select
[(ngModel)]="selectedDictionary"
[disabled]="!compare || !templateSelected"
[placeholder]="selectedDictionary.id ? selectedDictionary.label : (selectDictionary.label | translate)"
>
@for (dictionary of dictionaries; track dictionary; let index = $index) {
<mat-option [value]="dictionary">
{{ dictionary.id ? dictionary.label : (dictionary.label | translate) }}
</mat-option>
}
</mat-select>
</mat-form-field>
}
</div>
</ng-container>
</div>
@ -94,26 +104,30 @@
<div class="editor-container">
<redaction-editor
[(isSearchOpen)]="_isSearchOpen"
[canEdit]="canEdit"
[canEdit]="canEdit()"
[diffEditorText]="diffEditorText"
[initialEntries]="initialEntries"
[initialEntries]="initialEntries()"
[showDiffEditor]="compare && showDiffEditor"
></redaction-editor>
<div *ngIf="compare && optionNotSelected" class="no-dictionary-selected">
<mat-icon svgIcon="red:dictionary"></mat-icon>
<span class="heading-l" translate="dictionary-overview.select-dictionary"></span>
</div>
@if (compare && optionNotSelected) {
<div class="no-dictionary-selected">
<mat-icon svgIcon="red:dictionary"></mat-icon>
<span class="heading-l" translate="dictionary-overview.select-dictionary"></span>
</div>
}
</div>
<div *ngIf="withFloatingActions && !!editor?.hasChanges && canEdit && !isLeavingPage" [class.offset]="compare" class="changes-box">
<iqser-icon-button
(action)="saveDictionary.emit()"
[disabled]="!!_loadingService.isLoading()"
[label]="'dictionary-overview.save-changes' | translate"
[type]="iconButtonTypes.primary"
icon="iqser:check"
></iqser-icon-button>
<div (click)="revert()" class="all-caps-label cancel" translate="dictionary-overview.revert-changes"></div>
</div>
@if (withFloatingActions() && !!editor?.hasChanges && canEdit() && !isLeavingPage()) {
<div [class.offset]="compare" class="changes-box">
<iqser-icon-button
(action)="saveDictionary.emit()"
[disabled]="!!_loadingService.isLoading()"
[label]="'dictionary-overview.save-changes' | translate"
[type]="iconButtonTypes.primary"
icon="iqser:check"
></iqser-icon-button>
<div (click)="revert()" class="all-caps-label cancel" translate="dictionary-overview.revert-changes"></div>
</div>
}
</div>

View File

@ -1,10 +1,15 @@
import {
booleanAttribute,
ChangeDetectorRef,
Component,
effect,
EventEmitter,
input,
Input,
model,
OnChanges,
OnInit,
output,
Output,
signal,
SimpleChanges,
@ -60,21 +65,21 @@ const HELP_MODE_KEYS = {
EditorComponent,
],
})
export class DictionaryManagerComponent implements OnChanges, OnInit {
@Input() type: DictionaryType = 'dictionary';
@Input() entityType?: string;
@Input() currentDossierId: string;
@Input() currentDossierTemplateId: string;
@Input() withFloatingActions = true;
@Input() initialEntries: List;
@Input() canEdit = false;
@Input() canDownload = false;
@Input() isLeavingPage = false;
@Input() hint = false;
@Input() selectedDictionaryType = 'dossier_redaction';
@Input() selectedDictionaryTypeLabel: string;
@Input() activeEntryType: DictionaryEntryType = DictionaryEntryTypes.ENTRY;
@Output() readonly saveDictionary = new EventEmitter<string[]>();
export class DictionaryManagerComponent implements OnInit {
readonly type = input<DictionaryType>('dictionary');
readonly entityType = input<string>();
readonly currentDossierId = input<string>();
readonly currentDossierTemplateId = model<string>();
readonly withFloatingActions = input(true, { transform: booleanAttribute });
readonly initialEntries = input.required<List>();
readonly canEdit = input(false, { transform: booleanAttribute });
readonly canDownload = input(false, { transform: booleanAttribute });
readonly isLeavingPage = input(false, { transform: booleanAttribute });
readonly hint = input(false, { transform: booleanAttribute });
readonly activeDictionary = input<Dictionary>();
readonly selectedDictionaryType = model<string>('dossier_redaction');
readonly activeEntryType = input<DictionaryEntryType>(DictionaryEntryTypes.ENTRY);
readonly saveDictionary = output();
@ViewChild(EditorComponent) readonly editor: EditorComponent;
readonly iconButtonTypes = IconButtonTypes;
dossiers: Dossier[];
@ -102,7 +107,24 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
private readonly _changeRef: ChangeDetectorRef,
private readonly _dossierTemplatesService: DossierTemplatesService,
protected readonly _loadingService: LoadingService,
) {}
) {
effect(() => {
if (this.activeEntryType() && this.#dossier?.dossierTemplateId && this.selectedDossier?.dossierId) {
this.#onDossierChanged(this.#dossier.dossierTemplateId, this.#dossier.dossierId).then(entries =>
this.#updateDiffEditorText(entries),
);
}
});
effect(
() => {
if (this.selectedDictionaryType()) {
this.#disableDiffEditor();
this.#updateDropdownsOptions();
}
},
{ allowSignalWrites: true },
);
}
get selectedDossierTemplate() {
return this.#dossierTemplate;
@ -115,12 +137,12 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
: this.selectDossierTemplate;
}
this.#dossierTemplate = value;
this.currentDossierTemplateId = value.dossierTemplateId;
this.currentDossierTemplateId.set(value.dossierTemplateId);
this.#dossier = this.selectDossier;
this.dictionaries = this.#dictionaries;
this.#disableDiffEditor();
if (!this.initialDossierTemplateId && !this.currentDossierId) {
if (!this.initialDossierTemplateId && !this.currentDossierId()) {
this.selectedDictionary = this.selectDictionary;
}
@ -148,7 +170,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
set selectedDictionary(dictionary: Dictionary) {
if (dictionary.type) {
this.selectedDictionaryType = dictionary.type;
this.selectedDictionaryType.set(dictionary.type);
this.#dictionary = dictionary;
this.#onDossierChanged(this.#dossier.dossierTemplateId).then(entries => this.#updateDiffEditorText(entries));
}
@ -181,7 +203,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
get #templatesWithCurrentEntityType() {
return this._dossierTemplatesService.all.filter(t =>
this._dictionaryService.hasType(t.dossierTemplateId, this.selectedDictionaryType),
this._dictionaryService.hasType(t.dossierTemplateId, this.selectedDictionaryType()),
);
}
@ -190,7 +212,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
this.dossierTemplates = this._dossierTemplatesService.all;
await firstValueFrom(this._dictionaryService.loadDictionaryDataForDossierTemplates(this.dossierTemplates.map(t => t.id)));
this.#dossierTemplate = this._dossierTemplatesService.all[0];
this.initialDossierTemplateId = this.currentDossierTemplateId;
this.initialDossierTemplateId = this.currentDossierTemplateId();
this.#updateDropdownsOptions();
}
@ -199,7 +221,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
const blob = new Blob([content], {
type: 'text/plain;charset=utf-8',
});
saveAs(blob, `${this.entityType}-${this.type}.txt`);
saveAs(blob, `${this.entityType()}-${this.type()}.txt`);
}
revert() {
@ -213,43 +235,30 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
}
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.activeEntryType && this.#dossier?.dossierTemplateId && this.selectedDossier?.dossierId) {
this.#onDossierChanged(this.#dossier.dossierTemplateId, this.#dossier.dossierId).then(entries =>
this.#updateDiffEditorText(entries),
);
}
if (changes.selectedDictionaryType) {
this.#disableDiffEditor();
this.#updateDropdownsOptions();
}
}
async #onDossierChanged(dossierTemplateId: string, dossierId?: string) {
let dictionary: IDictionary;
if (dossierId === 'template') {
dictionary = await this._dictionaryService.getForType(dossierTemplateId, this.selectedDictionaryType);
dictionary = await this._dictionaryService.getForType(dossierTemplateId, this.selectedDictionaryType());
} else {
if (dossierId) {
dictionary = (
await firstValueFrom(
this._dictionaryService.loadDictionaryEntriesByType([this.selectedDictionaryType], dossierTemplateId, dossierId),
this._dictionaryService.loadDictionaryEntriesByType([this.selectedDictionaryType()], dossierTemplateId, dossierId),
).catch(() => {
return [{ entries: [COMPARE_ENTRIES_ERROR], type: '' }];
})
)[0];
} else {
dictionary = this.selectedDictionaryType
? await this._dictionaryService.getForType(this.currentDossierTemplateId, this.selectedDictionaryType)
dictionary = this.selectedDictionaryType()
? await this._dictionaryService.getForType(this.currentDossierTemplateId(), this.selectedDictionaryType())
: { entries: [COMPARE_ENTRIES_ERROR], type: '' };
}
}
const activeEntries =
this.activeEntryType === DictionaryEntryTypes.ENTRY || this.hint
this.activeEntryType() === DictionaryEntryTypes.ENTRY || this.hint()
? [...dictionary.entries]
: this.activeEntryType === DictionaryEntryTypes.FALSE_POSITIVE
: this.activeEntryType() === DictionaryEntryTypes.FALSE_POSITIVE
? [...dictionary.falsePositiveEntries]
: [...dictionary.falseRecommendationEntries];
return activeEntries.join('\n');
@ -257,23 +266,23 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
#updateDropdownsOptions(updateSelectedDossierTemplate = true) {
if (updateSelectedDossierTemplate) {
this.currentDossierTemplateId = this.initialDossierTemplateId ?? this.currentDossierTemplateId;
this.currentDossierTemplateId.set(this.initialDossierTemplateId ?? this.currentDossierTemplateId());
this.dossierTemplates = this.currentDossierTemplateId
? this.#templatesWithCurrentEntityType
: this._dossierTemplatesService.all;
if (!this.currentDossierTemplateId) {
this.dossierTemplates = [this.selectDossierTemplate, ...this.dossierTemplates];
}
this.selectedDossierTemplate = this.dossierTemplates.find(t => t.id === this.currentDossierTemplateId);
this.selectedDossierTemplate = this.dossierTemplates.find(t => t.id === this.currentDossierTemplateId());
}
this.dossiers = this._activeDossiersService.all.filter(
d => d.dossierTemplateId === this.currentDossierTemplateId && d.id !== this.currentDossierId,
d => d.dossierTemplateId === this.currentDossierTemplateId() && d.id !== this.currentDossierId(),
);
const templateDictionary = {
id: 'template',
dossierId: 'template',
dossierName: 'Template Dictionary',
dossierTemplateId: this.currentDossierTemplateId,
dossierTemplateId: this.currentDossierTemplateId(),
} as Dossier;
this.dossiers.push(templateDictionary);
}