Pull request #90: RED-929: Dictionary description and guard improvements

Merge in RED/ui from RED-929 to master

* commit '170c3ae20b1c1ac4c91f81514e51deea341f7381':
  Dictionary description and guard improvements
This commit is contained in:
Timo Bejan 2021-01-12 17:16:48 +01:00
commit c8d0b2a522
13 changed files with 179 additions and 50 deletions

View File

@ -43,7 +43,7 @@
<mat-option *ngFor="let dictionary of redactionDictionaries" [value]="dictionary.type">
{{ dictionary.label }}
<br />
<span class="description">{{ dictionaryDescriptions[dictionary.label] }}</span>
<span class="description">{{ dictionary.description }}</span>
</mat-option>
</mat-select>
</div>

View File

@ -31,13 +31,6 @@ export class ManualAnnotationDialogComponent implements OnInit {
redactionDictionaries: TypeValue[] = [];
legalOptions: LegalBasisOption[] = [];
public dictionaryDescriptions = {
'CBI Address': 'Laboratory Address: Redaction in combination with vertebrates',
'CBI Author': 'Study Author: Redaction in combination with vertebrates',
'CBI Sponsor': 'Batch Sponsor: Redaction in combination with "batches produced at"',
PII: 'Personal Identification Information: Employee name, email, phone, fax, ...'
};
get title() {
return this._manualAnnotationService.getTitle(this.manualRedactionEntryWrapper.type);
}

View File

@ -48,6 +48,18 @@
</div>
</div>
<div class="red-input-group w-450">
<label translate="add-edit-dictionary.form.description"></label>
<textarea
redactionHasScrollbar
rows="4"
formControlName="description"
name="description"
type="text"
placeholder="{{ 'add-edit-dictionary.form.description-placeholder' | translate }}"
></textarea>
</div>
<div class="red-input-group slider-row">
<mat-button-toggle-group name="hint" formControlName="hint" appearance="legacy">
<mat-button-toggle [value]="false"> {{ 'add-edit-dictionary.form.redaction' | translate }}</mat-button-toggle>

View File

@ -29,7 +29,8 @@ export class AddEditDictionaryDialogComponent {
this.dictionary = data.dictionary;
this._ruleSetId = data.ruleSetId;
this.dictionaryForm = this._formBuilder.group({
type: [this.dictionary?.type, Validators.required],
type: [this.dictionary?.type, [Validators.required, Validators.minLength(3)]],
description: [this.dictionary?.description],
rank: [this.dictionary?.rank, Validators.required],
hexColor: [this.dictionary?.hexColor, [Validators.required, Validators.minLength(7)]],
hint: [!!this.dictionary?.hint],
@ -72,7 +73,7 @@ export class AddEditDictionaryDialogComponent {
observable.subscribe(
() => {
this.dialogRef.close({ dictionary: typeValue });
this.dialogRef.close({ dictionary: this.dictionary ? null : typeValue });
},
(error) => {
if (error.status === 409) {
@ -93,6 +94,7 @@ export class AddEditDictionaryDialogComponent {
private _formToObject(): TypeValue {
return {
caseInsensitive: !this.dictionaryForm.get('caseSensitive').value,
description: this.dictionaryForm.get('description').value,
hexColor: this.dictionaryForm.get('hexColor').value,
hint: this.dictionaryForm.get('hint').value,
type: this.dictionaryForm.get('type').value,

View File

@ -139,6 +139,11 @@
{{ (dictionary.hint ? 'hint' : 'redaction') | translate }}
</div>
</div>
<div class="pb-32 mt-20" *ngIf="!!dictionary.description">
<div class="heading" translate="dictionary-overview.dictionary-details.description"></div>
<div class="mt-8">{{ dictionary.description }}</div>
</div>
</div>
</div>
</section>

View File

@ -26,8 +26,6 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges {
@ViewChild('editorComponent')
editorComponent: AceEditorComponent;
dictionary: TypeValue;
activeEditMarkers: any[] = [];
activeSearchMarkers: any[] = [];
@ -59,36 +57,37 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges {
) {
super(_translateService);
this._appStateService.activateDictionary(this._activatedRoute.snapshot.params.type, this._activatedRoute.snapshot.params.ruleSetId);
this.dictionary = this._appStateService.activeDictionary;
this._initialize();
}
private _initialize() {
this._dictionaryControllerService.getDictionaryForType(this.dictionary.type, this.dictionary.ruleSetId).subscribe(
(data) => {
this.initialDictionaryEntries = data.entries.sort((str1, str2) => str1.localeCompare(str2, undefined, { sensitivity: 'accent' }));
this.revert();
},
() => {
this.processing = false;
}
);
if (this.dictionary.type)
this._dictionaryControllerService.getDictionaryForType(this.dictionary.type, this.dictionary.ruleSetId).subscribe(
(data) => {
this.initialDictionaryEntries = data.entries.sort((str1, str2) => str1.localeCompare(str2, undefined, { sensitivity: 'accent' }));
this.revert();
},
() => {
this.processing = false;
}
);
}
public get dictionary(): TypeValue {
return this._appStateService.activeDictionary;
}
openEditDictionaryDialog($event: any) {
$event.stopPropagation();
this._dialogService.openAddEditDictionaryDialog(this.dictionary, this.dictionary.ruleSetId, async (newDictionary) => {
if (newDictionary) {
await this._appStateService.loadDictionaryData();
this.dictionary = this._appStateService.dictionaryData[this.dictionary.type];
}
this._dialogService.openAddEditDictionaryDialog(this.dictionary, this.dictionary.ruleSetId, async () => {
await this._appStateService.loadDictionaryData();
});
}
openDeleteDictionaryDialog($event: any) {
this._dialogService.openDeleteDictionaryDialog($event, this.dictionary, this.dictionary.ruleSetId, async () => {
await this._appStateService.loadDictionaryData();
this._router.navigate(['/ui/admin/dictionaries']);
this._router.navigate(['..']);
});
}

View File

@ -47,10 +47,6 @@
}
}
.mt-8 {
margin-top: 8px;
}
.mt-12 {
margin-top: 12px;
}
@ -62,7 +58,3 @@
.mt-24 {
margin-top: 24px;
}
.pb-32 {
padding-bottom: 32px;
}

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot } from '@angular/router';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { AppStateService } from './app-state.service';
import { UserService } from '../user/user.service';
@ -7,7 +7,7 @@ import { UserService } from '../user/user.service';
providedIn: 'root'
})
export class AppStateGuard implements CanActivate {
constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService) {}
constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService, private readonly _router: Router) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
await this._userService.loadAllUsersIfNecessary();
@ -19,6 +19,27 @@ export class AppStateGuard implements CanActivate {
await this._appStateService.loadAllProjectsIfNecessary();
}
const { projectId, fileId, ruleSetId, type } = route.params;
if (projectId && !this._appStateService.getProjectById(projectId)) {
await this._router.navigate(['ui', 'projects']);
return false;
}
if (fileId && !this._appStateService.getFileById(projectId, fileId)) {
await this._router.navigate(['ui', 'projects', projectId]);
return false;
}
if (ruleSetId && !this._appStateService.getRuleSetById(ruleSetId)) {
await this._router.navigate(['ui', 'admin', 'project-templates']);
return false;
}
if (type && !this._appStateService.dictionaryData[ruleSetId][type]) {
await this._router.navigate(['ui', 'admin', 'project-templates', ruleSetId]);
return false;
}
return true;
}
}

View File

@ -576,15 +576,16 @@ export class AppStateService {
}
async loadDictionaryData() {
this._dictionaryData = {};
const obj = {};
const observables = [];
for (const ruleSet of this.ruleSets) {
this.dictionaryData[ruleSet.ruleSetId] = {};
observables.push(...this.getDictionaryDataForRuleSetObservables(ruleSet.ruleSetId, this.dictionaryData[ruleSet.ruleSetId]));
obj[ruleSet.ruleSetId] = {};
observables.push(...this.getDictionaryDataForRuleSetObservables(ruleSet.ruleSetId, obj[ruleSet.ruleSetId]));
}
await forkJoin(observables).toPromise();
this._dictionaryData = obj;
}
async updateDictionaryVersion() {

View File

@ -454,6 +454,8 @@
"hints": "Tipp Wörterbücher"
},
"annotation-type": {
"recommendation": "Empfehlung",
"remove-only-here": "Ausstehende Entfernung (nur hier)",
"add-dictionary": "Ausstehend zum Wörterbuch hinzufügen",
"remove-dictionary": "Ausstehend aus dem Wörterbuch entfernen",
"suggestion-add-dictionary": "Vorgeschlagenes Wörterbuch hinzufügen",
@ -463,7 +465,7 @@
"ignore": "Ignorieren",
"hint": "Hinweis",
"redaction": "Redaktion",
"manual": "Manuelle Redaktion",
"manual-redaction": "Manuelle Redaktion",
"declined-suggestion": "Abgelehnter Vorschlag"
},
"manual-annotation": {
@ -545,6 +547,8 @@
"name": "Wörterbuchname",
"name-placeholder": "Name eingeben",
"name-hint": "Kann nach dem Speichern nicht bearbeitet werden.",
"description": "Beschreibung",
"description-placeholder": "Beschreibung eingeben",
"rank": "Rang",
"rank-placeholder": "1000",
"color": "Hex Farbe",
@ -560,6 +564,20 @@
},
"save": "Wörterbuch speichern"
},
"add-edit-project-template": {
"title": {
"edit": "Bearbeiten Sie die {{name}} Projektvorlage",
"new": "Projektvorlage erstellen"
},
"form": {
"name": "Name der Projektvorlage",
"name-placeholder": "Name eingeben",
"description": "Beschreibung",
"description-placeholder": "Beschreibung eingeben",
"valid-from": "Gültig ab"
},
"save": "Projektvorlage speichern"
},
"dictionary-overview": {
"action": {
"delete": "Wörterbuch löschen",
@ -577,7 +595,10 @@
"search": "Suche...",
"save-changes": "Änderungen speichern",
"revert-changes": "Zurückkehren",
"compare": "Vergleichen Sie"
"compare": "Vergleichen Sie",
"dictionary-details": {
"description": "Beschreibung"
}
},
"dictionary-listing": {
"action": {
@ -597,9 +618,34 @@
},
"table-col-names": {
"type": "Art",
"order-of-importance": "Reihenfolge der Wichtigkeit",
"hint-redaction": "Hinweis / Redaktion"
},
"search": "Suche..."
"search": "Suche...",
"no-data": {
"title": "Es gibt noch keine Wörterbücher.",
"action": "Neues Wörterbuch"
}
},
"project-templates": "Projektvorlagen",
"project-templates-listing": {
"table-header": {
"title": "{{Länge}} Projektvorlagen"
},
"entries": "{{Länge}} Einträge",
"dictionaries": "{{Länge}} Wörterbücher",
"action": {
"delete": "Vorlage löschen",
"edit": "Vorlage bearbeiten"
},
"add-new": "Neue Projektvorlage",
"search": "Suche...",
"table-col-names": {
"name": "Name",
"created-by": "Erstellt von",
"created-on": "Erstellt am",
"modified-on": "Geändert am"
}
},
"user-listing": {
"table-header": {
@ -627,18 +673,20 @@
},
"watermark-screen": {
"form": {
"text": "Text",
"text-placeholder": "Text eingeben",
"opacity": "Opazität",
"color": "Farbe",
"font-size": "Schriftgröße"
"font-size": "Schriftgröße",
"font-type": "Schriftart",
"orientation": "Orientierung"
},
"action": {
"save": "speichern",
"save": "Änderungen speichern",
"revert": "Zurückkehren",
"success": "Wasserzeichen aktualisiert!",
"error": "Wasserzeichen konnte nicht aktualisiert werden"
},
"title": "Wasserzeichen konfigurieren"
"title": "Wasserzeichen"
},
"dictionaries": "Wörterbücher",
"user-management": "Benutzerverwaltung",
@ -650,5 +698,17 @@
"mark-unread": "als ungelesen markieren"
},
"rule-editor": "Regeleditor",
"watermark": "Wasserzeichen"
"watermark": "Wasserzeichen",
"pending-changes-guard": "WARNUNG: Sie haben nicht gespeicherte Änderungen. Drücken Sie Abbrechen, um zurück zu gehen und diese Änderungen zu speichern, oder OK, um diese Änderungen zu verlieren.",
"reset-filters": "Filter zurücksetzen",
"overwrite-files-dialog": {
"title": "Die Datei existiert bereits!",
"question": "<b>{{Dateiname}}</b> existiert bereits. Was möchten Sie tun?",
"options": {
"overwrite": "Überschreiben",
"no-overwrite": "Bewahren Sie die alte Datei auf",
"cancel": "Alle Uploads abbrechen",
"remember": "Option merken"
}
}
}

View File

@ -551,6 +551,8 @@
"name": "Dictionary Name",
"name-placeholder": "Enter Name",
"name-hint": "Cannot be edited after saving.",
"description": "Description",
"description-placeholder": "Enter Description",
"rank": "Rank",
"rank-placeholder": "1000",
"color": "Hex Color",
@ -597,7 +599,10 @@
"search": "Search...",
"save-changes": "Save Changes",
"revert-changes": "Revert",
"compare": "Compare"
"compare": "Compare",
"dictionary-details": {
"description": "Description"
}
},
"dictionary-listing": {
"action": {

View File

@ -186,10 +186,18 @@ body {
margin-top: 5px;
}
.mt-8 {
margin-top: 8px;
}
.mt-20 {
margin-top: 20px;
}
.pb-32 {
padding-bottom: 32px;
}
.break-20 {
height: 20px;
background: transparent;

View File

@ -464,3 +464,34 @@ No members yet.
Select from the list below.|Noch keine Mitglieder. Wählen Sie aus der folgenden Liste.
No members yet.
Select from the list below.|Noch keine Mitglieder. Wählen Sie aus der folgenden Liste.
No members yet.
Select from the list below.|Noch keine Mitglieder. Wählen Sie aus der folgenden Liste.
Recommendation|Empfehlung
Pending removal ( only here )|Ausstehende Entfernung (nur hier)
Edit {{name}} Project Template|Bearbeiten Sie die {{name}} Projektvorlage
Create Project Template|Projektvorlage erstellen
Project Template Name|Name der Projektvorlage
Valid from|Gültig ab
Save Project Template|Projektvorlage speichern
Order Of Importance|Reihenfolge der Wichtigkeit
There are no dictionaries yet.|Es gibt noch keine Wörterbücher.
Project Templates|Projektvorlagen
{{length}} project templates|{{Länge}} Projektvorlagen
{{length}} entries|{{Länge}} Einträge
Delete Template|Vorlage löschen
Edit Template|Vorlage bearbeiten
New Project Template|Neue Projektvorlage
Created by|Erstellt von
Created on|Erstellt am
Modified on|Geändert am
Enter text|Text eingeben
Font Type|Schriftart
Orientation|Orientierung
WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.|WARNUNG: Sie haben nicht gespeicherte Änderungen. Drücken Sie Abbrechen, um zurück zu gehen und diese Änderungen zu speichern, oder OK, um diese Änderungen zu verlieren.
Reset Filters|Filter zurücksetzen
File already exists!|Die Datei existiert bereits!
<b>{{filename}}</b> already exists. What do you want to do?|<b>{{Dateiname}}</b> existiert bereits. Was möchten Sie tun?
Overwrite|Überschreiben
Keep old file|Bewahren Sie die alte Datei auf
Cancel all uploads|Alle Uploads abbrechen
Remember option|Option merken