Ignored hint port and fix for no red roles

This commit is contained in:
Timo Bejan 2022-01-10 17:32:17 +02:00
parent a939232d60
commit e05bbb017e
35 changed files with 1324 additions and 992 deletions

View File

@ -36,6 +36,9 @@ import { KeycloakService } from 'keycloak-angular';
import { GeneralSettingsService } from '@services/general-settings.service'; import { GeneralSettingsService } from '@services/general-settings.service';
import { BreadcrumbsComponent } from '@components/breadcrumbs/breadcrumbs.component'; import { BreadcrumbsComponent } from '@components/breadcrumbs/breadcrumbs.component';
import { UserPreferenceService } from '@services/user-preference.service'; import { UserPreferenceService } from '@services/user-preference.service';
import * as german from '../assets/i18n/de.json';
import * as english from '../assets/i18n/en.json';
import { UserService } from '@services/user.service';
export function httpLoaderFactory(httpClient: HttpClient): PruningTranslationLoader { export function httpLoaderFactory(httpClient: HttpClient): PruningTranslationLoader {
return new PruningTranslationLoader(httpClient, '/assets/i18n/', '.json'); return new PruningTranslationLoader(httpClient, '/assets/i18n/', '.json');
@ -114,7 +117,7 @@ const components = [AppComponent, AuthErrorComponent, NotificationsComponent, Sp
provide: APP_INITIALIZER, provide: APP_INITIALIZER,
multi: true, multi: true,
useFactory: configurationInitializer, useFactory: configurationInitializer,
deps: [KeycloakService, Title, ConfigService, GeneralSettingsService, LanguageService, UserPreferenceService], deps: [KeycloakService, Title, ConfigService, GeneralSettingsService, LanguageService, UserService, UserPreferenceService],
}, },
{ {
provide: MissingTranslationHandler, provide: MissingTranslationHandler,
@ -136,6 +139,7 @@ const components = [AppComponent, AuthErrorComponent, NotificationsComponent, Sp
export class AppModule { export class AppModule {
constructor(private readonly _router: Router, private readonly _route: ActivatedRoute) { constructor(private readonly _router: Router, private readonly _route: ActivatedRoute) {
this._configureKeyCloakRouteHandling(); this._configureKeyCloakRouteHandling();
// this._test();
} }
private _configureKeyCloakRouteHandling() { private _configureKeyCloakRouteHandling() {
@ -152,4 +156,60 @@ export class AppModule {
} }
}); });
} }
// private _test(){
//
// const flatGerman = flatten(german);
//
//
// const flatEnglish = flatten(english);
//
// const tmfc = new TranslateMessageFormatCompiler();
//
//
//
// for (const key of Object.keys(flatGerman)) {
// try {
// const result = tmfc.compile(flatGerman[key], 'de');
// //console.log(result);
// } catch (e) {
// console.error('ERROR AT: ', flatGerman[key]);
// }
// }
//
// for (const key of Object.keys(flatEnglish)) {
// try {
// const result = tmfc.compile(flatEnglish[key], 'de');
// //console.log(result);
// } catch (e) {
// console.error('ERROR AT: ', flatEnglish[key]);
// }
// }
// console.log('done');
// }
} }
//
// function flatten(data: any) {
// const result: any = {};
//
// function recurse(cur: any, prop: any) {
// if (Object(cur) !== cur) {
// result[prop] = cur;
// } else if (Array.isArray(cur)) {
// let l = 0;
// for (let i = 0, l = cur.length; i < l; i++) recurse(cur[i], prop + '[' + i + ']');
// if (l === 0) result[prop] = [];
// } else {
// let isEmpty = true;
// for (const p in cur) {
// isEmpty = false;
// recurse(cur[p], prop ? prop + '.' + p : p);
// }
// if (isEmpty && prop) result[prop] = {};
// }
// }
//
// recurse(data, '');
// return result;
// }

View File

@ -14,6 +14,7 @@ export class AnnotationPermissions {
canChangeLegalBasis = true; canChangeLegalBasis = true;
canResizeAnnotation = true; canResizeAnnotation = true;
canRecategorizeImage = true; canRecategorizeImage = true;
canForceHint = true;
static forUser(isApprover: boolean, user: User, annotations: AnnotationWrapper | AnnotationWrapper[]) { static forUser(isApprover: boolean, user: User, annotations: AnnotationWrapper | AnnotationWrapper[]) {
if (!isArray(annotations)) { if (!isArray(annotations)) {
@ -29,12 +30,13 @@ export class AnnotationPermissions {
permissions.canAcceptSuggestion = isApprover && (annotation.isSuggestion || annotation.isDeclinedSuggestion); permissions.canAcceptSuggestion = isApprover && (annotation.isSuggestion || annotation.isDeclinedSuggestion);
permissions.canRejectSuggestion = isApprover && annotation.isSuggestion; permissions.canRejectSuggestion = isApprover && annotation.isSuggestion;
permissions.canForceHint = annotation.isIgnoredHint;
permissions.canForceRedaction = annotation.isSkipped && !annotation.isFalsePositive; permissions.canForceRedaction = annotation.isSkipped && !annotation.isFalsePositive;
permissions.canAcceptRecommendation = annotation.isRecommendation; permissions.canAcceptRecommendation = annotation.isRecommendation;
permissions.canMarkAsFalsePositive = annotation.canBeMarkedAsFalsePositive; permissions.canMarkAsFalsePositive = annotation.canBeMarkedAsFalsePositive;
permissions.canRemoveOrSuggestToRemoveOnlyHere = annotation.isRedacted; permissions.canRemoveOrSuggestToRemoveOnlyHere = annotation.isRedacted || annotation.isHint;
permissions.canRemoveOrSuggestToRemoveFromDictionary = permissions.canRemoveOrSuggestToRemoveFromDictionary =
annotation.isModifyDictionary && (annotation.isRedacted || annotation.isSkipped || annotation.isHint); annotation.isModifyDictionary && (annotation.isRedacted || annotation.isSkipped || annotation.isHint);

View File

@ -12,6 +12,7 @@ export type AnnotationSuperType =
| 'suggestion-remove-dictionary' | 'suggestion-remove-dictionary'
| 'suggestion-add' | 'suggestion-add'
| 'suggestion-remove' | 'suggestion-remove'
| 'ignored-hint'
| 'skipped' | 'skipped'
| 'redaction' | 'redaction'
| 'manual-redaction' | 'manual-redaction'
@ -43,6 +44,7 @@ export class AnnotationWrapper {
legalBasisChangeValue?: string; legalBasisChangeValue?: string;
resizing?: boolean; resizing?: boolean;
rectangle?: boolean; rectangle?: boolean;
hintDictionary?: boolean;
section?: string; section?: string;
manual?: boolean; manual?: boolean;
@ -87,7 +89,7 @@ export class AnnotationWrapper {
} }
get isSuperTypeBasedColor() { get isSuperTypeBasedColor() {
return this.isSkipped || this.isSuggestion || this.isDeclinedSuggestion; return this.isSkipped || this.isSuggestion || this.isDeclinedSuggestion || this.isIgnoredHint;
} }
get isSkipped() { get isSkipped() {
@ -106,6 +108,20 @@ export class AnnotationWrapper {
return this.recategorizationType || this.typeValue; return this.recategorizationType || this.typeValue;
} }
get topLevelFilter() {
return (
this.superType !== 'hint' &&
this.superType !== 'redaction' &&
this.superType !== 'recommendation' &&
this.superType !== 'ignored-hint' &&
this.superType !== 'skipped'
);
}
get filterKey() {
return this.topLevelFilter ? this.superType : this.superType + this.type;
}
get isManuallySkipped() { get isManuallySkipped() {
return this.isSkipped && this.manual; return this.isSkipped && this.manual;
} }
@ -113,7 +129,10 @@ export class AnnotationWrapper {
get isFalsePositive() { get isFalsePositive() {
return ( return (
this.type?.toLowerCase() === 'false_positive' && this.type?.toLowerCase() === 'false_positive' &&
(this.superType === 'skipped' || this.superType === 'hint' || this.superType === 'redaction') (this.superType === 'skipped' ||
this.superType === 'hint' ||
this.superType === 'ignored-hint' ||
this.superType === 'redaction')
); );
} }
@ -133,6 +152,10 @@ export class AnnotationWrapper {
return this.superType === 'hint'; return this.superType === 'hint';
} }
get isIgnoredHint() {
return this.superType === 'ignored-hint';
}
get isRedacted() { get isRedacted() {
return this.superType === 'redaction' || this.superType === 'manual-redaction'; return this.superType === 'redaction' || this.superType === 'manual-redaction';
} }
@ -242,6 +265,7 @@ export class AnnotationWrapper {
annotationWrapper.hasLegalBasisChanged = redactionLogEntry.hasLegalBasisChanged; annotationWrapper.hasLegalBasisChanged = redactionLogEntry.hasLegalBasisChanged;
annotationWrapper.hasBeenForced = redactionLogEntry.hasBeenForced; annotationWrapper.hasBeenForced = redactionLogEntry.hasBeenForced;
annotationWrapper.hasBeenRemovedByManualOverride = redactionLogEntry.hasBeenRemovedByManualOverride; annotationWrapper.hasBeenRemovedByManualOverride = redactionLogEntry.hasBeenRemovedByManualOverride;
annotationWrapper.hintDictionary = redactionLogEntry.hintDictionary;
this._createContent(annotationWrapper, redactionLogEntry); this._createContent(annotationWrapper, redactionLogEntry);
this._setSuperType(annotationWrapper, redactionLogEntry); this._setSuperType(annotationWrapper, redactionLogEntry);
@ -280,7 +304,7 @@ export class AnnotationWrapper {
if (redactionLogEntryWrapper.status === 'REQUESTED') { if (redactionLogEntryWrapper.status === 'REQUESTED') {
annotationWrapper.superType = 'suggestion-force-redaction'; annotationWrapper.superType = 'suggestion-force-redaction';
} else if (redactionLogEntryWrapper.status === 'APPROVED') { } else if (redactionLogEntryWrapper.status === 'APPROVED') {
annotationWrapper.superType = 'redaction'; annotationWrapper.superType = redactionLogEntryWrapper.hint ? 'hint' : 'redaction';
} else { } else {
annotationWrapper.superType = 'skipped'; annotationWrapper.superType = 'skipped';
} }
@ -408,6 +432,11 @@ export class AnnotationWrapper {
if (!annotationWrapper.superType) { if (!annotationWrapper.superType) {
annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'skipped'; annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'skipped';
} }
if (annotationWrapper.superType === 'skipped') {
if (redactionLogEntryWrapper.hintDictionary) {
annotationWrapper.superType = 'ignored-hint';
}
}
} }
private static _createContent(annotationWrapper: AnnotationWrapper, entry: RedactionLogEntryWrapper) { private static _createContent(annotationWrapper: AnnotationWrapper, entry: RedactionLogEntryWrapper) {

View File

@ -21,7 +21,7 @@ export class FileDataModel {
viewMode: ViewMode, viewMode: ViewMode,
areDevFeaturesEnabled: boolean, areDevFeaturesEnabled: boolean,
): AnnotationData { ): AnnotationData {
const entries: RedactionLogEntryWrapper[] = this._convertData(); const entries: RedactionLogEntryWrapper[] = this._convertData(dictionaryData);
let allAnnotations = entries let allAnnotations = entries
.map(entry => AnnotationWrapper.fromData(entry)) .map(entry => AnnotationWrapper.fromData(entry))
.filter(ann => ann.manual || !this.file.excludedPages.includes(ann.pageNumber)); .filter(ann => ann.manual || !this.file.excludedPages.includes(ann.pageNumber));
@ -46,7 +46,7 @@ export class FileDataModel {
}; };
} }
private _convertData(): RedactionLogEntryWrapper[] { private _convertData(dictionaryData: { [p: string]: Dictionary }): RedactionLogEntryWrapper[] {
let result: RedactionLogEntryWrapper[] = []; let result: RedactionLogEntryWrapper[] = [];
const reasonAnnotationIds: { [key: string]: RedactionLogEntryWrapper[] } = {}; const reasonAnnotationIds: { [key: string]: RedactionLogEntryWrapper[] } = {};
@ -55,6 +55,7 @@ export class FileDataModel {
const redactionLogEntryWrapper: RedactionLogEntryWrapper = {}; const redactionLogEntryWrapper: RedactionLogEntryWrapper = {};
Object.assign(redactionLogEntryWrapper, redactionLogEntry); Object.assign(redactionLogEntryWrapper, redactionLogEntry);
redactionLogEntryWrapper.type = redactionLogEntry.type; redactionLogEntryWrapper.type = redactionLogEntry.type;
redactionLogEntryWrapper.hintDictionary = dictionaryData[redactionLogEntry.type].hint;
this._isChangeLogEntry(redactionLogEntry, redactionLogEntryWrapper); this._isChangeLogEntry(redactionLogEntry, redactionLogEntryWrapper);

View File

@ -11,6 +11,7 @@ export interface RedactionLogEntryWrapper {
startOffset?: number; startOffset?: number;
type?: string; type?: string;
rectangle?: boolean; rectangle?: boolean;
hintDictionary?: boolean;
color?: Array<number>; color?: Array<number>;
dictionaryEntry?: boolean; dictionaryEntry?: boolean;

View File

@ -11,4 +11,5 @@ export const defaultColorsTranslations: { [key in DefaultColorType]: string } =
requestAdd: _('default-colors-screen.types.requestAdd'), requestAdd: _('default-colors-screen.types.requestAdd'),
requestRemove: _('default-colors-screen.types.requestRemove'), requestRemove: _('default-colors-screen.types.requestRemove'),
updatedColor: _('default-colors-screen.types.updatedColor'), updatedColor: _('default-colors-screen.types.updatedColor'),
ignoredHintColor: _('default-colors-screen.types.ignoredHintColor'),
}; };

View File

@ -1,9 +1,10 @@
<section class="dialog"> <section class="dialog">
<form (submit)="handleForceRedaction()" [formGroup]="redactionForm"> <form (submit)="handleForceAnnotation()" [formGroup]="redactionForm">
<div class="dialog-header heading-l" translate="manual-annotation.dialog.header.force"></div> <div class="dialog-header heading-l" translate="manual-annotation.dialog.header.force-redaction" *ngIf="!isHintDialog"></div>
<div class="dialog-header heading-l" translate="manual-annotation.dialog.header.force-hint" *ngIf="isHintDialog"></div>
<div class="dialog-content"> <div class="dialog-content">
<div class="iqser-input-group required w-400"> <div class="iqser-input-group required w-400" *ngIf="!isHintDialog">
<label translate="manual-annotation.dialog.content.reason"></label> <label translate="manual-annotation.dialog.content.reason"></label>
<mat-select <mat-select
[placeholder]="'manual-annotation.dialog.content.reason-placeholder' | translate" [placeholder]="'manual-annotation.dialog.content.reason-placeholder' | translate"
@ -16,14 +17,14 @@
</mat-select> </mat-select>
</div> </div>
<div class="iqser-input-group w-400"> <div class="iqser-input-group w-400" *ngIf="!isHintDialog">
<label translate="manual-annotation.dialog.content.legalBasis"></label> <label translate="manual-annotation.dialog.content.legalBasis"></label>
<input [value]="redactionForm.get('reason').value?.legalBasis" disabled type="text" /> <input [value]="redactionForm.get('reason').value?.legalBasis" disabled type="text" />
</div> </div>
<div [class.required]="!isDocumentAdmin" class="iqser-input-group w-300"> <div [class.required]="!isDocumentAdmin" class="iqser-input-group w-300">
<label translate="manual-annotation.dialog.content.comment"></label> <label translate="manual-annotation.dialog.content.comment"></label>
<textarea formControlName="comment" iqserHasScrollbar name="comment" rows="4" type="text"></textarea> <textarea formControlName="comment" iqserHasScrollbar name="comment" rows="4"></textarea>
</div> </div>
</div> </div>

View File

@ -17,11 +17,11 @@ export interface LegalBasisOption {
} }
@Component({ @Component({
selector: 'redaction-force-redaction-dialog', selector: 'redaction-force-annotation-dialog',
templateUrl: './force-redaction-dialog.component.html', templateUrl: './force-annotation-dialog.component.html',
styleUrls: ['./force-redaction-dialog.component.scss'], styleUrls: ['./force-annotation-dialog.component.scss'],
}) })
export class ForceRedactionDialogComponent implements OnInit { export class ForceAnnotationDialogComponent implements OnInit {
redactionForm: FormGroup; redactionForm: FormGroup;
isDocumentAdmin: boolean; isDocumentAdmin: boolean;
legalOptions: LegalBasisOption[] = []; legalOptions: LegalBasisOption[] = [];
@ -35,17 +35,21 @@ export class ForceRedactionDialogComponent implements OnInit {
private readonly _justificationsService: JustificationsService, private readonly _justificationsService: JustificationsService,
private readonly _manualAnnotationService: ManualAnnotationService, private readonly _manualAnnotationService: ManualAnnotationService,
private readonly _permissionsService: PermissionsService, private readonly _permissionsService: PermissionsService,
public dialogRef: MatDialogRef<ForceRedactionDialogComponent>, public dialogRef: MatDialogRef<ForceAnnotationDialogComponent>,
@Inject(MAT_DIALOG_DATA) private readonly _data: { readonly dossier: Dossier }, @Inject(MAT_DIALOG_DATA) private readonly _data: { readonly dossier: Dossier; readonly hint: boolean },
) { ) {
this.redactionForm = this._getForm(); this.redactionForm = this._getForm();
} }
get isHintDialog() {
return this._data.hint;
}
private _getForm(): FormGroup { private _getForm(): FormGroup {
this.isDocumentAdmin = this._permissionsService.isApprover(this._data.dossier); this.isDocumentAdmin = this._permissionsService.isApprover(this._data.dossier);
return this._formBuilder.group({ return this._formBuilder.group({
reason: [null, Validators.required], reason: this._data.hint ? ['Forced Hint'] : [null, Validators.required],
comment: this.isDocumentAdmin ? [null] : [null, Validators.required], comment: this.isDocumentAdmin ? [null] : [null, Validators.required],
}); });
} }
@ -62,7 +66,7 @@ export class ForceRedactionDialogComponent implements OnInit {
this.legalOptions.sort((a, b) => a.label.localeCompare(b.label)); this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));
} }
handleForceRedaction() { handleForceAnnotation() {
this.dialogRef.close(this._createForceRedactionRequest()); this.dialogRef.close(this._createForceRedactionRequest());
} }

View File

@ -4,7 +4,7 @@
(data.removeFromDictionary (data.removeFromDictionary
? 'remove-annotations-dialog.remove-from-dictionary.title' ? 'remove-annotations-dialog.remove-from-dictionary.title'
: 'remove-annotations-dialog.remove-only-here.title' : 'remove-annotations-dialog.remove-only-here.title'
) | translate ) | translate: { hint: data.hint }
}} }}
</div> </div>
<form (submit)="confirm()" [formGroup]="redactionForm"> <form (submit)="confirm()" [formGroup]="redactionForm">
@ -13,7 +13,7 @@
(data.removeFromDictionary (data.removeFromDictionary
? 'remove-annotations-dialog.remove-from-dictionary.question' ? 'remove-annotations-dialog.remove-from-dictionary.question'
: 'remove-annotations-dialog.remove-only-here.question' : 'remove-annotations-dialog.remove-only-here.question'
) | translate ) | translate: { hint: data.hint }
}} }}
<div *ngIf="data.removeFromDictionary" class="content-wrapper"> <div *ngIf="data.removeFromDictionary" class="content-wrapper">

View File

@ -10,6 +10,7 @@ import { Dossier } from '@red/domain';
export interface RemoveAnnotationsDialogInput { export interface RemoveAnnotationsDialogInput {
annotationsToRemove: AnnotationWrapper[]; annotationsToRemove: AnnotationWrapper[];
removeFromDictionary: boolean; removeFromDictionary: boolean;
hint: boolean;
dossier: Dossier; dossier: Dossier;
} }

View File

@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
import { AddDossierDialogComponent } from './dialogs/add-dossier-dialog/add-dossier-dialog.component'; import { AddDossierDialogComponent } from './dialogs/add-dossier-dialog/add-dossier-dialog.component';
import { AssignReviewerApproverDialogComponent } from './dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component'; import { AssignReviewerApproverDialogComponent } from './dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dialog/manual-annotation-dialog.component'; import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
import { ForceRedactionDialogComponent } from './dialogs/force-redaction-dialog/force-redaction-dialog.component'; import { ForceAnnotationDialogComponent } from './dialogs/force-redaction-dialog/force-annotation-dialog.component';
import { RemoveAnnotationsDialogComponent } from './dialogs/remove-annotations-dialog/remove-annotations-dialog.component'; import { RemoveAnnotationsDialogComponent } from './dialogs/remove-annotations-dialog/remove-annotations-dialog.component';
import { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component'; import { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component';
import { SharedModule } from '@shared/shared.module'; import { SharedModule } from '@shared/shared.module';
@ -35,7 +35,7 @@ const dialogs = [
AddDossierDialogComponent, AddDossierDialogComponent,
EditDossierDialogComponent, EditDossierDialogComponent,
ManualAnnotationDialogComponent, ManualAnnotationDialogComponent,
ForceRedactionDialogComponent, ForceAnnotationDialogComponent,
RemoveAnnotationsDialogComponent, RemoveAnnotationsDialogComponent,
ResizeAnnotationDialogComponent, ResizeAnnotationDialogComponent,
DocumentInfoDialogComponent, DocumentInfoDialogComponent,

View File

@ -88,7 +88,7 @@
></iqser-circle-button> ></iqser-circle-button>
<iqser-circle-button <iqser-circle-button
(action)="annotationActionsService.forceRedaction($event, annotations, file, annotationsChanged)" (action)="annotationActionsService.forceAnnotation($event, annotations, file, annotationsChanged, false)"
*ngIf="annotationPermissions.canForceRedaction" *ngIf="annotationPermissions.canForceRedaction"
[tooltipPosition]="tooltipPosition" [tooltipPosition]="tooltipPosition"
[tooltip]="'annotation-actions.force-redaction.label' | translate" [tooltip]="'annotation-actions.force-redaction.label' | translate"
@ -96,6 +96,15 @@
icon="red:thumb-up" icon="red:thumb-up"
></iqser-circle-button> ></iqser-circle-button>
<iqser-circle-button
(action)="annotationActionsService.forceAnnotation($event, annotations, file, annotationsChanged, true)"
*ngIf="annotationPermissions.canForceHint"
[tooltipPosition]="tooltipPosition"
[tooltip]="'annotation-actions.force-hint.label' | translate"
[type]="buttonType"
icon="red:thumb-up"
></iqser-circle-button>
<iqser-circle-button <iqser-circle-button
(action)="hideAnnotation($event)" (action)="hideAnnotation($event)"
*ngIf="isImage && isVisible" *ngIf="isImage && isVisible"

View File

@ -33,7 +33,7 @@ export class TypeAnnotationIconComponent implements OnChanges {
this.type = this.type =
this.annotation.isSuggestion || this.annotation.isDeclinedSuggestion this.annotation.isSuggestion || this.annotation.isDeclinedSuggestion
? 'rhombus' ? 'rhombus'
: this.annotation.isHint : this.annotation.isHint || this.annotation.isIgnoredHint
? 'circle' ? 'circle'
: this.annotation.isRecommendation : this.annotation.isRecommendation
? 'hexagon' ? 'hexagon'

View File

@ -143,7 +143,7 @@
<ng-container *ngIf="!filter.topLevelFilter"> <ng-container *ngIf="!filter.topLevelFilter">
<redaction-dictionary-annotation-icon [dictionaryKey]="filter.id" [dossierTemplateId]="dossier.dossierTemplateId"> <redaction-dictionary-annotation-icon [dictionaryKey]="filter.id" [dossierTemplateId]="dossier.dossierTemplateId">
</redaction-dictionary-annotation-icon> </redaction-dictionary-annotation-icon>
{{ filter.id | humanize: false }} {{ filter.label | humanize: false }}
</ng-container> </ng-container>
</ng-template> </ng-template>
</ng-container> </ng-container>

View File

@ -59,9 +59,15 @@ export class AnnotationActionsService {
}); });
} }
forceRedaction($event: MouseEvent, annotations: AnnotationWrapper[], file: File, annotationsChanged: EventEmitter<AnnotationWrapper>) { forceAnnotation(
const data = { dossier: this._dossier(file) }; $event: MouseEvent,
this._dialogService.openDialog('forceRedaction', $event, data, (request: ILegalBasisChangeRequest) => { annotations: AnnotationWrapper[],
file: File,
annotationsChanged: EventEmitter<AnnotationWrapper>,
hint: boolean = false,
) {
const data = { dossier: this._dossier(file), hint };
this._dialogService.openDialog('forceAnnotation', $event, data, (request: ILegalBasisChangeRequest) => {
annotations.forEach(annotation => { annotations.forEach(annotation => {
this._processObsAndEmit( this._processObsAndEmit(
this._manualAnnotationService.force( this._manualAnnotationService.force(
@ -114,7 +120,12 @@ export class AnnotationActionsService {
removeFromDictionary: boolean, removeFromDictionary: boolean,
annotationsChanged: EventEmitter<AnnotationWrapper>, annotationsChanged: EventEmitter<AnnotationWrapper>,
) { ) {
const data = { annotationsToRemove: annotations, removeFromDictionary, dossier: this._dossier(file) }; const data = {
annotationsToRemove: annotations,
removeFromDictionary,
dossier: this._dossier(file),
hint: annotations[0].hintDictionary,
};
this._dialogService.openDialog('removeAnnotations', $event, data, (result: { comment: string }) => { this._dialogService.openDialog('removeAnnotations', $event, data, (result: { comment: string }) => {
annotations.forEach(annotation => { annotations.forEach(annotation => {
this._processObsAndEmit( this._processObsAndEmit(
@ -349,7 +360,21 @@ export class AnnotationActionsService {
title: this._translateService.instant('annotation-actions.force-redaction.label'), title: this._translateService.instant('annotation-actions.force-redaction.label'),
onClick: () => { onClick: () => {
this._ngZone.run(() => { this._ngZone.run(() => {
this.forceRedaction(null, annotations, file, annotationsChanged); this.forceAnnotation(null, annotations, file, annotationsChanged);
});
},
});
}
const canForceHint = annotationPermissions.reduce((acc, next) => acc && next.permissions.canForceHint, true);
if (canForceHint) {
availableActions.push({
type: 'actionButton',
img: this._convertPath('/assets/icons/general/thumb-up.svg'),
title: this._translateService.instant('annotation-actions.force-hint.label'),
onClick: () => {
this._ngZone.run(() => {
this.forceAnnotation(null, annotations, file, annotationsChanged, true);
}); });
}, },
}); });

View File

@ -42,27 +42,26 @@ export class AnnotationProcessingService {
const filters: INestedFilter[] = []; const filters: INestedFilter[] = [];
annotations?.forEach(a => { annotations?.forEach(a => {
const topLevelFilter = !['hint', 'redaction', 'recommendation', 'skipped'].includes(a.superType); const topLevelFilter = a.topLevelFilter;
const key = topLevelFilter ? a.superType : a.superType + a.type; const filter = filterMap.get(a.filterKey);
const filter = filterMap.get(key);
if (filter) { if (filter) {
filter.matches += 1; filter.matches += 1;
} else { } else {
// top level filter // top level filter
if (topLevelFilter) { if (topLevelFilter) {
this._createParentFilter(key, filterMap, filters); this._createParentFilter(a.superType, filterMap, filters);
} else { } else {
let parentFilter = filterMap.get(a.superType); let parentFilter = filterMap.get(a.superType);
if (!parentFilter) { if (!parentFilter) {
parentFilter = this._createParentFilter(a.superType, filterMap, filters); parentFilter = this._createParentFilter(a.superType, filterMap, filters);
} }
const childFilter: IFilter = { const childFilter: IFilter = {
id: a.type, id: a.filterKey,
label: a.type, label: a.type,
checked: false, checked: false,
matches: 1, matches: 1,
}; };
filterMap.set(key, childFilter); filterMap.set(a.filterKey, childFilter);
parentFilter.children.push(new Filter(childFilter)); parentFilter.children.push(new Filter(childFilter));
} }
} }
@ -173,12 +172,7 @@ export class AnnotationProcessingService {
return true; return true;
}; };
private _checkByFilterKey = (filter: INestedFilter, annotation: AnnotationWrapper) => { private _checkByFilterKey = (filter: NestedFilter | IFilter, annotation: AnnotationWrapper) => filter.id === annotation.filterKey;
const superType = annotation.superType;
const isNotTopLevelFilter = superType === 'hint' || superType === 'redaction' || superType === 'recommendation';
return filter.id === superType || (filter.id === annotation.type && isNotTopLevelFilter);
};
private _sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] { private _sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] {
return annotations.sort((ann1, ann2) => { return annotations.sort((ann1, ann2) => {

View File

@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { AddDossierDialogComponent } from '../dialogs/add-dossier-dialog/add-dossier-dialog.component'; import { AddDossierDialogComponent } from '../dialogs/add-dossier-dialog/add-dossier-dialog.component';
import { RemoveAnnotationsDialogComponent } from '../dialogs/remove-annotations-dialog/remove-annotations-dialog.component'; import { RemoveAnnotationsDialogComponent } from '../dialogs/remove-annotations-dialog/remove-annotations-dialog.component';
import { ForceRedactionDialogComponent } from '../dialogs/force-redaction-dialog/force-redaction-dialog.component'; import { ForceAnnotationDialogComponent } from '../dialogs/force-redaction-dialog/force-annotation-dialog.component';
import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component'; import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component';
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component'; import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component'; import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
@ -22,7 +22,7 @@ type DialogType =
| 'changeLegalBasis' | 'changeLegalBasis'
| 'removeAnnotations' | 'removeAnnotations'
| 'resizeAnnotation' | 'resizeAnnotation'
| 'forceRedaction' | 'forceAnnotation'
| 'manualAnnotation'; | 'manualAnnotation';
@Injectable() @Injectable()
@ -58,8 +58,8 @@ export class DossiersDialogService extends DialogService<DialogType> {
resizeAnnotation: { resizeAnnotation: {
component: ResizeAnnotationDialogComponent, component: ResizeAnnotationDialogComponent,
}, },
forceRedaction: { forceAnnotation: {
component: ForceRedactionDialogComponent, component: ForceAnnotationDialogComponent,
}, },
manualAnnotation: { manualAnnotation: {
component: ManualAnnotationDialogComponent, component: ManualAnnotationDialogComponent,

View File

@ -24,6 +24,12 @@
label="S" label="S"
type="square" type="square"
></redaction-annotation-icon> ></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="filter.id === 'ignored-hint'"
[color]="dictionaryColor"
label="I"
type="circle"
></redaction-annotation-icon>
<redaction-annotation-icon <redaction-annotation-icon
*ngIf="isSuggestion(filter.id)" *ngIf="isSuggestion(filter.id)"
[color]="dictionaryColor" [color]="dictionaryColor"

View File

@ -14,7 +14,6 @@ import { FileDropOverlayService } from './services/file-drop-overlay.service';
@NgModule({ @NgModule({
imports: [CommonModule, SharedModule, OverlayModule], imports: [CommonModule, SharedModule, OverlayModule],
declarations: [FileDropComponent, UploadStatusOverlayComponent, OverwriteFilesDialogComponent], declarations: [FileDropComponent, UploadStatusOverlayComponent, OverwriteFilesDialogComponent],
entryComponents: [FileDropComponent, UploadStatusOverlayComponent],
providers: [UploadDownloadDialogService, FileUploadService, FileDownloadService, StatusOverlayService, FileDropOverlayService], providers: [UploadDownloadDialogService, FileUploadService, FileDownloadService, StatusOverlayService, FileDropOverlayService],
exports: [FileDropComponent, UploadStatusOverlayComponent], exports: [FileDropComponent, UploadStatusOverlayComponent],
}) })

View File

@ -50,15 +50,17 @@ export class UserService extends EntitiesService<User, IUser> {
); );
} }
async loadCurrentUser() { async loadCurrentUser(): Promise<User> {
const token = await this._keycloakService.getToken(); const token = await this._keycloakService.getToken();
const decoded = jwt_decode(token); const decoded = jwt_decode(token);
const userId = (<{ sub: string }>decoded).sub; const userId = (<{ sub: string }>decoded).sub;
const roles = this._keycloakService.getUserRoles(true).filter(role => role.startsWith('RED_')); const roles = this._keycloakService.getUserRoles(true).filter(role => role.startsWith('RED_'));
this.replace(new User(await this._keycloakService.loadUserProfile(true), roles, userId)); const user = new User(await this._keycloakService.loadUserProfile(true), roles, userId);
this.replace(user);
this._currentUser$.next(this.find(userId)); this._currentUser$.next(this.find(userId));
return user;
} }
getNameForId(userId: string): string | undefined { getNameForId(userId: string): string | undefined {

View File

@ -176,6 +176,14 @@ export class AppStateService {
true, true,
); );
dictionaryData['ignored-hint'] = new Dictionary(
{
hexColor: colors.ignoredHintColor,
type: 'ignored-hint',
},
true,
);
dictionaryData['manual-redaction'] = new Dictionary( dictionaryData['manual-redaction'] = new Dictionary(
{ {
hexColor: colors.manualRedactionColor || FALLBACK_COLOR, hexColor: colors.manualRedactionColor || FALLBACK_COLOR,

View File

@ -4,6 +4,7 @@ import { AnnotationSuperType } from '../models/file/annotation.wrapper';
export const annotationTypesTranslations: { [key in AnnotationSuperType]: string } = { export const annotationTypesTranslations: { [key in AnnotationSuperType]: string } = {
'declined-suggestion': _('annotation-type.declined-suggestion'), 'declined-suggestion': _('annotation-type.declined-suggestion'),
hint: _('annotation-type.hint'), hint: _('annotation-type.hint'),
'ignored-hint': _('annotation-type.ignored-hint'),
'manual-redaction': _('annotation-type.manual-redaction'), 'manual-redaction': _('annotation-type.manual-redaction'),
recommendation: _('annotation-type.recommendation'), recommendation: _('annotation-type.recommendation'),
redaction: _('annotation-type.redaction'), redaction: _('annotation-type.redaction'),

View File

@ -1,11 +1,12 @@
import { catchError, filter, mapTo, switchMap, take, tap } from 'rxjs/operators'; import { catchError, filter, mergeMap, switchMap, take, tap } from 'rxjs/operators';
import { ConfigService } from '@services/config.service'; import { ConfigService } from '@services/config.service';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { from, of, throwError } from 'rxjs';
import { KeycloakEventType, KeycloakService } from 'keycloak-angular'; import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
import { GeneralSettingsService } from '@services/general-settings.service'; import { GeneralSettingsService } from '@services/general-settings.service';
import { LanguageService } from '@i18n/language.service'; import { LanguageService } from '@i18n/language.service';
import { UserPreferenceService } from '@services/user-preference.service'; import { UserPreferenceService } from '@services/user-preference.service';
import { from, iif, of, throwError } from 'rxjs'; import { UserService } from '@services/user.service';
export function configurationInitializer( export function configurationInitializer(
keycloakService: KeycloakService, keycloakService: KeycloakService,
@ -13,28 +14,25 @@ export function configurationInitializer(
configService: ConfigService, configService: ConfigService,
generalSettingsService: GeneralSettingsService, generalSettingsService: GeneralSettingsService,
languageService: LanguageService, languageService: LanguageService,
userService: UserService,
userPreferenceService: UserPreferenceService, userPreferenceService: UserPreferenceService,
) { ) {
const userConfig$ = generalSettingsService.getGeneralConfigurations().pipe(
switchMap(config => from(userPreferenceService.reload()).pipe(mapTo(config))),
tap(() => languageService.chooseAndSetInitialLanguage()),
);
return () => return () =>
keycloakService.keycloakEvents$ keycloakService.keycloakEvents$
.pipe( .pipe(
filter(event => event.type === KeycloakEventType.OnReady), filter(event => event.type === KeycloakEventType.OnReady),
switchMap(() => from(keycloakService.isLoggedIn())), switchMap(() => from(keycloakService.isLoggedIn())),
switchMap(loggedIn => { switchMap(loggedIn => (!loggedIn ? throwError('Not Logged In') : of({}))),
const hasAnyRedRoles = !!keycloakService.getUserRoles().find(role => role.startsWith('RED_')); switchMap(() => from(userService.loadCurrentUser())),
return !loggedIn ? throwError('Not Logged In') : of(hasAnyRedRoles); switchMap(user => (!user.hasAnyREDRoles ? throwError('Not user has no red roles') : of({}))),
}), mergeMap(() => generalSettingsService.getGeneralConfigurations()),
switchMap(hasRoles => iif(() => !!hasRoles, userConfig$, of({ displayName: 'RedactManager' }))),
tap(configuration => configService.updateDisplayName(configuration.displayName)), tap(configuration => configService.updateDisplayName(configuration.displayName)),
switchMap(() => userPreferenceService.reload()),
catchError(() => { catchError(() => {
title.setTitle('RedactManager'); title.setTitle('RedactManager');
return of({}); return of({});
}), }),
tap(() => languageService.chooseAndSetInitialLanguage()),
take(1), take(1),
) )
.toPromise(); .toPromise();

View File

@ -10,6 +10,7 @@ export const SuperTypeSorter: { [key in AnnotationSuperType]: number } = {
'suggestion-remove-dictionary': 13, 'suggestion-remove-dictionary': 13,
'suggestion-add': 10, 'suggestion-add': 10,
'suggestion-remove': 11, 'suggestion-remove': 11,
'ignored-hint': 45,
skipped: 50, skipped: 50,
redaction: 1, redaction: 1,
'manual-redaction': 2, 'manual-redaction': 2,

View File

@ -1,7 +1,7 @@
{ {
"ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_NAME": null,
"ADMIN_CONTACT_URL": null, "ADMIN_CONTACT_URL": null,
"API_URL": "https://dev-03.iqser.cloud/redaction-gateway-v1", "API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1",
"APP_NAME": "RedactManager", "APP_NAME": "RedactManager",
"AUTO_READ_TIME": 1.5, "AUTO_READ_TIME": 1.5,
"BACKEND_APP_VERSION": "4.4.40", "BACKEND_APP_VERSION": "4.4.40",
@ -17,7 +17,7 @@
"MAX_RETRIES_ON_SERVER_ERROR": 3, "MAX_RETRIES_ON_SERVER_ERROR": 3,
"OAUTH_CLIENT_ID": "redaction", "OAUTH_CLIENT_ID": "redaction",
"OAUTH_IDP_HINT": null, "OAUTH_IDP_HINT": null,
"OAUTH_URL": "https://dev-03.iqser.cloud/auth/realms/redaction", "OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction",
"RECENT_PERIOD_IN_HOURS": 24, "RECENT_PERIOD_IN_HOURS": 24,
"SELECTION_MODE": "structural" "SELECTION_MODE": "structural"
} }

View File

@ -473,7 +473,8 @@
"previewColor": "Vorschau", "previewColor": "Vorschau",
"requestAdd": "Neuen Wörterbucheintrag vorschlagen", "requestAdd": "Neuen Wörterbucheintrag vorschlagen",
"requestRemove": "Anfrage entfernt", "requestRemove": "Anfrage entfernt",
"updatedColor": "Aktualisiert" "updatedColor": "Aktualisiert",
"ignoredHintColor": "Ignorierter Hinweis"
} }
}, },
"dev-mode": "DEV", "dev-mode": "DEV",

View File

@ -142,6 +142,9 @@
}, },
"annotation": "Annotation", "annotation": "Annotation",
"annotation-actions": { "annotation-actions": {
"force-hint": {
"label": "Force Hint"
},
"accept-recommendation": { "accept-recommendation": {
"label": "Accept Recommendation" "label": "Accept Recommendation"
}, },
@ -277,6 +280,7 @@
"annotation-type": { "annotation-type": {
"declined-suggestion": "Declined Suggestion", "declined-suggestion": "Declined Suggestion",
"hint": "Hint", "hint": "Hint",
"ignored-hint": "Ignored Hint",
"manual-redaction": "Manual Redaction", "manual-redaction": "Manual Redaction",
"recommendation": "Recommendation", "recommendation": "Recommendation",
"redaction": "Redaction", "redaction": "Redaction",
@ -474,7 +478,8 @@
"previewColor": "Preview", "previewColor": "Preview",
"requestAdd": "Request Add", "requestAdd": "Request Add",
"requestRemove": "Request Remove", "requestRemove": "Request Remove",
"updatedColor": "Updated" "updatedColor": "Updated",
"ignoredHintColor": "Ignored Hint"
} }
}, },
"dev-mode": "DEV", "dev-mode": "DEV",
@ -1282,7 +1287,8 @@
"header": { "header": {
"dictionary": "Add to dictionary", "dictionary": "Add to dictionary",
"false-positive": "Set false positive", "false-positive": "Set false positive",
"force": "Force Redaction", "force-redaction": "Force Redaction",
"force-hint": "Force Hint",
"redaction": "Redaction", "redaction": "Redaction",
"request-dictionary": "Request add to dictionary", "request-dictionary": "Request add to dictionary",
"request-false-positive": "Request false positive", "request-false-positive": "Request false positive",

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.atlassian.bamboo:bamboo-specs-api:8.0.2" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:20.1.0" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.12.0" level="project" />
<orderEntry type="library" name="Maven: com.atlassian.bamboo:bamboo-specs:8.0.2" level="project" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.6" level="project" />
<orderEntry type="library" name="Maven: commons-validator:commons-validator:1.7" level="project" />
<orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.9.4" level="project" />
<orderEntry type="library" name="Maven: commons-digester:commons-digester:2.1" level="project" />
<orderEntry type="library" name="Maven: commons-logging:commons-logging:1.2" level="project" />
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.2" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.28" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.13" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.13" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.11" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.13.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
</component>
</module>

View File

@ -9,4 +9,5 @@ export interface IColors {
requestAdd?: string; requestAdd?: string;
requestRemove?: string; requestRemove?: string;
updatedColor?: string; updatedColor?: string;
ignoredHintColor?: string;
} }

View File

@ -3,6 +3,7 @@ export type DefaultColorType =
| 'defaultColor' | 'defaultColor'
| 'dictionaryRequestColor' | 'dictionaryRequestColor'
| 'manualRedactionColor' | 'manualRedactionColor'
| 'ignoredHintColor'
| 'notRedacted' | 'notRedacted'
| 'previewColor' | 'previewColor'
| 'requestAdd' | 'requestAdd'

0
package-lock.json generated
View File

View File

@ -1,6 +1,6 @@
{ {
"name": "redaction", "name": "redaction",
"version": "3.133.0", "version": "3.134.0",
"private": true, "private": true,
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
@ -23,36 +23,36 @@
} }
}, },
"dependencies": { "dependencies": {
"@angular/animations": "13.0.2", "@angular/animations": "13.1.1",
"@angular/cdk": "13.0.2", "@angular/cdk": "13.1.1",
"@angular/common": "13.0.2", "@angular/common": "13.1.1",
"@angular/compiler": "13.0.2", "@angular/compiler": "13.1.1",
"@angular/core": "13.0.2", "@angular/core": "13.1.1",
"@angular/forms": "13.0.2", "@angular/forms": "13.1.1",
"@angular/material": "13.0.2", "@angular/material": "13.1.1",
"@angular/material-moment-adapter": "^13.0.2", "@angular/material-moment-adapter": "^13.0.2",
"@angular/platform-browser": "13.0.2", "@angular/platform-browser": "13.1.1",
"@angular/platform-browser-dynamic": "13.0.2", "@angular/platform-browser-dynamic": "13.1.1",
"@angular/router": "13.0.2", "@angular/router": "13.1.1",
"@angular/service-worker": "13.0.2", "@angular/service-worker": "13.1.1",
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0", "@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
"@materia-ui/ngx-monaco-editor": "^6.0.0-beta.1", "@materia-ui/ngx-monaco-editor": "^6.0.0-beta.1",
"@ngx-translate/core": "^13.0.0", "@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^6.0.0", "@ngx-translate/http-loader": "^7.0.0",
"@nrwl/angular": "13.2.3", "@nrwl/angular": "13.2.3",
"@pdftron/webviewer": "8.2.0", "@pdftron/webviewer": "8.2.0",
"@swimlane/ngx-charts": "^17.0.1", "@swimlane/ngx-charts": "^17.0.1",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"keycloak-angular": "^8.4.0", "keycloak-angular": "^9.0.0",
"keycloak-js": "15.0.2", "keycloak-js": "^16.0.0",
"lodash.orderby": "^4.6.0", "lodash.orderby": "^4.6.0",
"messageformat": "^2.3.0", "messageformat": "^2.3.0",
"moment": "^2.29.1", "moment": "^2.29.1",
"monaco-editor": "^0.30.1", "monaco-editor": "^0.30.1",
"ngx-color-picker": "^11.0.0", "ngx-color-picker": "^11.0.0",
"ngx-toastr": "^14.1.3", "ngx-toastr": "^14.1.3",
"ngx-translate-messageformat-compiler": "^4.10.0", "ngx-translate-messageformat-compiler": "^4.11.0",
"papaparse": "^5.3.1", "papaparse": "^5.3.1",
"rxjs": "~6.6.7", "rxjs": "~6.6.7",
"sass": "^1.39.2", "sass": "^1.39.2",
@ -62,13 +62,13 @@
"zone.js": "0.11.4" "zone.js": "0.11.4"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "13.0.3", "@angular-devkit/build-angular": "13.1.2",
"@angular-eslint/eslint-plugin": "13.0.1", "@angular-eslint/eslint-plugin": "13.0.1",
"@angular-eslint/eslint-plugin-template": "13.0.1", "@angular-eslint/eslint-plugin-template": "13.0.1",
"@angular-eslint/template-parser": "13.0.1", "@angular-eslint/template-parser": "13.0.1",
"@angular/cli": "13.0.3", "@angular/cli": "13.1.2",
"@angular/compiler-cli": "13.0.2", "@angular/compiler-cli": "13.1.1",
"@angular/language-service": "13.0.2", "@angular/language-service": "13.1.1",
"@nrwl/cli": "13.2.3", "@nrwl/cli": "13.2.3",
"@nrwl/cypress": "13.2.3", "@nrwl/cypress": "13.2.3",
"@nrwl/eslint-plugin-nx": "13.2.3", "@nrwl/eslint-plugin-nx": "13.2.3",

View File

@ -9,10 +9,10 @@
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"importHelpers": true, "importHelpers": true,
"target": "es2015", "target": "es2017",
"module": "esnext", "module": "es2020",
"typeRoots": ["node_modules/@types"], "typeRoots": ["node_modules/@types"],
"lib": ["es2019", "dom"], "lib": ["es2020", "dom"],
"skipLibCheck": true, "skipLibCheck": true,
"skipDefaultLibCheck": true, "skipDefaultLibCheck": true,
"baseUrl": ".", "baseUrl": ".",

1948
yarn.lock

File diff suppressed because it is too large Load Diff