Ignored hint port and fix for no red roles
This commit is contained in:
parent
a939232d60
commit
e05bbb017e
@ -36,6 +36,9 @@ import { KeycloakService } from 'keycloak-angular';
|
||||
import { GeneralSettingsService } from '@services/general-settings.service';
|
||||
import { BreadcrumbsComponent } from '@components/breadcrumbs/breadcrumbs.component';
|
||||
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 {
|
||||
return new PruningTranslationLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -114,7 +117,7 @@ const components = [AppComponent, AuthErrorComponent, NotificationsComponent, Sp
|
||||
provide: APP_INITIALIZER,
|
||||
multi: true,
|
||||
useFactory: configurationInitializer,
|
||||
deps: [KeycloakService, Title, ConfigService, GeneralSettingsService, LanguageService, UserPreferenceService],
|
||||
deps: [KeycloakService, Title, ConfigService, GeneralSettingsService, LanguageService, UserService, UserPreferenceService],
|
||||
},
|
||||
{
|
||||
provide: MissingTranslationHandler,
|
||||
@ -136,6 +139,7 @@ const components = [AppComponent, AuthErrorComponent, NotificationsComponent, Sp
|
||||
export class AppModule {
|
||||
constructor(private readonly _router: Router, private readonly _route: ActivatedRoute) {
|
||||
this._configureKeyCloakRouteHandling();
|
||||
// this._test();
|
||||
}
|
||||
|
||||
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;
|
||||
// }
|
||||
|
||||
@ -14,6 +14,7 @@ export class AnnotationPermissions {
|
||||
canChangeLegalBasis = true;
|
||||
canResizeAnnotation = true;
|
||||
canRecategorizeImage = true;
|
||||
canForceHint = true;
|
||||
|
||||
static forUser(isApprover: boolean, user: User, annotations: AnnotationWrapper | AnnotationWrapper[]) {
|
||||
if (!isArray(annotations)) {
|
||||
@ -29,12 +30,13 @@ export class AnnotationPermissions {
|
||||
permissions.canAcceptSuggestion = isApprover && (annotation.isSuggestion || annotation.isDeclinedSuggestion);
|
||||
permissions.canRejectSuggestion = isApprover && annotation.isSuggestion;
|
||||
|
||||
permissions.canForceHint = annotation.isIgnoredHint;
|
||||
permissions.canForceRedaction = annotation.isSkipped && !annotation.isFalsePositive;
|
||||
permissions.canAcceptRecommendation = annotation.isRecommendation;
|
||||
|
||||
permissions.canMarkAsFalsePositive = annotation.canBeMarkedAsFalsePositive;
|
||||
|
||||
permissions.canRemoveOrSuggestToRemoveOnlyHere = annotation.isRedacted;
|
||||
permissions.canRemoveOrSuggestToRemoveOnlyHere = annotation.isRedacted || annotation.isHint;
|
||||
permissions.canRemoveOrSuggestToRemoveFromDictionary =
|
||||
annotation.isModifyDictionary && (annotation.isRedacted || annotation.isSkipped || annotation.isHint);
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ export type AnnotationSuperType =
|
||||
| 'suggestion-remove-dictionary'
|
||||
| 'suggestion-add'
|
||||
| 'suggestion-remove'
|
||||
| 'ignored-hint'
|
||||
| 'skipped'
|
||||
| 'redaction'
|
||||
| 'manual-redaction'
|
||||
@ -43,6 +44,7 @@ export class AnnotationWrapper {
|
||||
legalBasisChangeValue?: string;
|
||||
resizing?: boolean;
|
||||
rectangle?: boolean;
|
||||
hintDictionary?: boolean;
|
||||
section?: string;
|
||||
|
||||
manual?: boolean;
|
||||
@ -87,7 +89,7 @@ export class AnnotationWrapper {
|
||||
}
|
||||
|
||||
get isSuperTypeBasedColor() {
|
||||
return this.isSkipped || this.isSuggestion || this.isDeclinedSuggestion;
|
||||
return this.isSkipped || this.isSuggestion || this.isDeclinedSuggestion || this.isIgnoredHint;
|
||||
}
|
||||
|
||||
get isSkipped() {
|
||||
@ -106,6 +108,20 @@ export class AnnotationWrapper {
|
||||
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() {
|
||||
return this.isSkipped && this.manual;
|
||||
}
|
||||
@ -113,7 +129,10 @@ export class AnnotationWrapper {
|
||||
get isFalsePositive() {
|
||||
return (
|
||||
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';
|
||||
}
|
||||
|
||||
get isIgnoredHint() {
|
||||
return this.superType === 'ignored-hint';
|
||||
}
|
||||
|
||||
get isRedacted() {
|
||||
return this.superType === 'redaction' || this.superType === 'manual-redaction';
|
||||
}
|
||||
@ -242,6 +265,7 @@ export class AnnotationWrapper {
|
||||
annotationWrapper.hasLegalBasisChanged = redactionLogEntry.hasLegalBasisChanged;
|
||||
annotationWrapper.hasBeenForced = redactionLogEntry.hasBeenForced;
|
||||
annotationWrapper.hasBeenRemovedByManualOverride = redactionLogEntry.hasBeenRemovedByManualOverride;
|
||||
annotationWrapper.hintDictionary = redactionLogEntry.hintDictionary;
|
||||
|
||||
this._createContent(annotationWrapper, redactionLogEntry);
|
||||
this._setSuperType(annotationWrapper, redactionLogEntry);
|
||||
@ -280,7 +304,7 @@ export class AnnotationWrapper {
|
||||
if (redactionLogEntryWrapper.status === 'REQUESTED') {
|
||||
annotationWrapper.superType = 'suggestion-force-redaction';
|
||||
} else if (redactionLogEntryWrapper.status === 'APPROVED') {
|
||||
annotationWrapper.superType = 'redaction';
|
||||
annotationWrapper.superType = redactionLogEntryWrapper.hint ? 'hint' : 'redaction';
|
||||
} else {
|
||||
annotationWrapper.superType = 'skipped';
|
||||
}
|
||||
@ -408,6 +432,11 @@ export class AnnotationWrapper {
|
||||
if (!annotationWrapper.superType) {
|
||||
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) {
|
||||
|
||||
@ -21,7 +21,7 @@ export class FileDataModel {
|
||||
viewMode: ViewMode,
|
||||
areDevFeaturesEnabled: boolean,
|
||||
): AnnotationData {
|
||||
const entries: RedactionLogEntryWrapper[] = this._convertData();
|
||||
const entries: RedactionLogEntryWrapper[] = this._convertData(dictionaryData);
|
||||
let allAnnotations = entries
|
||||
.map(entry => AnnotationWrapper.fromData(entry))
|
||||
.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[] = [];
|
||||
|
||||
const reasonAnnotationIds: { [key: string]: RedactionLogEntryWrapper[] } = {};
|
||||
@ -55,6 +55,7 @@ export class FileDataModel {
|
||||
const redactionLogEntryWrapper: RedactionLogEntryWrapper = {};
|
||||
Object.assign(redactionLogEntryWrapper, redactionLogEntry);
|
||||
redactionLogEntryWrapper.type = redactionLogEntry.type;
|
||||
redactionLogEntryWrapper.hintDictionary = dictionaryData[redactionLogEntry.type].hint;
|
||||
|
||||
this._isChangeLogEntry(redactionLogEntry, redactionLogEntryWrapper);
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ export interface RedactionLogEntryWrapper {
|
||||
startOffset?: number;
|
||||
type?: string;
|
||||
rectangle?: boolean;
|
||||
hintDictionary?: boolean;
|
||||
|
||||
color?: Array<number>;
|
||||
dictionaryEntry?: boolean;
|
||||
|
||||
@ -11,4 +11,5 @@ export const defaultColorsTranslations: { [key in DefaultColorType]: string } =
|
||||
requestAdd: _('default-colors-screen.types.requestAdd'),
|
||||
requestRemove: _('default-colors-screen.types.requestRemove'),
|
||||
updatedColor: _('default-colors-screen.types.updatedColor'),
|
||||
ignoredHintColor: _('default-colors-screen.types.ignoredHintColor'),
|
||||
};
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
<section class="dialog">
|
||||
<form (submit)="handleForceRedaction()" [formGroup]="redactionForm">
|
||||
<div class="dialog-header heading-l" translate="manual-annotation.dialog.header.force"></div>
|
||||
<form (submit)="handleForceAnnotation()" [formGroup]="redactionForm">
|
||||
<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="iqser-input-group required w-400">
|
||||
<div class="iqser-input-group required w-400" *ngIf="!isHintDialog">
|
||||
<label translate="manual-annotation.dialog.content.reason"></label>
|
||||
<mat-select
|
||||
[placeholder]="'manual-annotation.dialog.content.reason-placeholder' | translate"
|
||||
@ -16,14 +17,14 @@
|
||||
</mat-select>
|
||||
</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>
|
||||
<input [value]="redactionForm.get('reason').value?.legalBasis" disabled type="text" />
|
||||
</div>
|
||||
|
||||
<div [class.required]="!isDocumentAdmin" class="iqser-input-group w-300">
|
||||
<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>
|
||||
|
||||
@ -17,11 +17,11 @@ export interface LegalBasisOption {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-force-redaction-dialog',
|
||||
templateUrl: './force-redaction-dialog.component.html',
|
||||
styleUrls: ['./force-redaction-dialog.component.scss'],
|
||||
selector: 'redaction-force-annotation-dialog',
|
||||
templateUrl: './force-annotation-dialog.component.html',
|
||||
styleUrls: ['./force-annotation-dialog.component.scss'],
|
||||
})
|
||||
export class ForceRedactionDialogComponent implements OnInit {
|
||||
export class ForceAnnotationDialogComponent implements OnInit {
|
||||
redactionForm: FormGroup;
|
||||
isDocumentAdmin: boolean;
|
||||
legalOptions: LegalBasisOption[] = [];
|
||||
@ -35,17 +35,21 @@ export class ForceRedactionDialogComponent implements OnInit {
|
||||
private readonly _justificationsService: JustificationsService,
|
||||
private readonly _manualAnnotationService: ManualAnnotationService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
public dialogRef: MatDialogRef<ForceRedactionDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) private readonly _data: { readonly dossier: Dossier },
|
||||
public dialogRef: MatDialogRef<ForceAnnotationDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) private readonly _data: { readonly dossier: Dossier; readonly hint: boolean },
|
||||
) {
|
||||
this.redactionForm = this._getForm();
|
||||
}
|
||||
|
||||
get isHintDialog() {
|
||||
return this._data.hint;
|
||||
}
|
||||
|
||||
private _getForm(): FormGroup {
|
||||
this.isDocumentAdmin = this._permissionsService.isApprover(this._data.dossier);
|
||||
|
||||
return this._formBuilder.group({
|
||||
reason: [null, Validators.required],
|
||||
reason: this._data.hint ? ['Forced Hint'] : [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));
|
||||
}
|
||||
|
||||
handleForceRedaction() {
|
||||
handleForceAnnotation() {
|
||||
this.dialogRef.close(this._createForceRedactionRequest());
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
(data.removeFromDictionary
|
||||
? 'remove-annotations-dialog.remove-from-dictionary.title'
|
||||
: 'remove-annotations-dialog.remove-only-here.title'
|
||||
) | translate
|
||||
) | translate: { hint: data.hint }
|
||||
}}
|
||||
</div>
|
||||
<form (submit)="confirm()" [formGroup]="redactionForm">
|
||||
@ -13,7 +13,7 @@
|
||||
(data.removeFromDictionary
|
||||
? 'remove-annotations-dialog.remove-from-dictionary.question'
|
||||
: 'remove-annotations-dialog.remove-only-here.question'
|
||||
) | translate
|
||||
) | translate: { hint: data.hint }
|
||||
}}
|
||||
|
||||
<div *ngIf="data.removeFromDictionary" class="content-wrapper">
|
||||
|
||||
@ -10,6 +10,7 @@ import { Dossier } from '@red/domain';
|
||||
export interface RemoveAnnotationsDialogInput {
|
||||
annotationsToRemove: AnnotationWrapper[];
|
||||
removeFromDictionary: boolean;
|
||||
hint: boolean;
|
||||
dossier: Dossier;
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
|
||||
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 { 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 { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
@ -35,7 +35,7 @@ const dialogs = [
|
||||
AddDossierDialogComponent,
|
||||
EditDossierDialogComponent,
|
||||
ManualAnnotationDialogComponent,
|
||||
ForceRedactionDialogComponent,
|
||||
ForceAnnotationDialogComponent,
|
||||
RemoveAnnotationsDialogComponent,
|
||||
ResizeAnnotationDialogComponent,
|
||||
DocumentInfoDialogComponent,
|
||||
|
||||
@ -88,7 +88,7 @@
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="annotationActionsService.forceRedaction($event, annotations, file, annotationsChanged)"
|
||||
(action)="annotationActionsService.forceAnnotation($event, annotations, file, annotationsChanged, false)"
|
||||
*ngIf="annotationPermissions.canForceRedaction"
|
||||
[tooltipPosition]="tooltipPosition"
|
||||
[tooltip]="'annotation-actions.force-redaction.label' | translate"
|
||||
@ -96,6 +96,15 @@
|
||||
icon="red:thumb-up"
|
||||
></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
|
||||
(action)="hideAnnotation($event)"
|
||||
*ngIf="isImage && isVisible"
|
||||
|
||||
@ -33,7 +33,7 @@ export class TypeAnnotationIconComponent implements OnChanges {
|
||||
this.type =
|
||||
this.annotation.isSuggestion || this.annotation.isDeclinedSuggestion
|
||||
? 'rhombus'
|
||||
: this.annotation.isHint
|
||||
: this.annotation.isHint || this.annotation.isIgnoredHint
|
||||
? 'circle'
|
||||
: this.annotation.isRecommendation
|
||||
? 'hexagon'
|
||||
|
||||
@ -143,7 +143,7 @@
|
||||
<ng-container *ngIf="!filter.topLevelFilter">
|
||||
<redaction-dictionary-annotation-icon [dictionaryKey]="filter.id" [dossierTemplateId]="dossier.dossierTemplateId">
|
||||
</redaction-dictionary-annotation-icon>
|
||||
{{ filter.id | humanize: false }}
|
||||
{{ filter.label | humanize: false }}
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
@ -59,9 +59,15 @@ export class AnnotationActionsService {
|
||||
});
|
||||
}
|
||||
|
||||
forceRedaction($event: MouseEvent, annotations: AnnotationWrapper[], file: File, annotationsChanged: EventEmitter<AnnotationWrapper>) {
|
||||
const data = { dossier: this._dossier(file) };
|
||||
this._dialogService.openDialog('forceRedaction', $event, data, (request: ILegalBasisChangeRequest) => {
|
||||
forceAnnotation(
|
||||
$event: MouseEvent,
|
||||
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 => {
|
||||
this._processObsAndEmit(
|
||||
this._manualAnnotationService.force(
|
||||
@ -114,7 +120,12 @@ export class AnnotationActionsService {
|
||||
removeFromDictionary: boolean,
|
||||
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 }) => {
|
||||
annotations.forEach(annotation => {
|
||||
this._processObsAndEmit(
|
||||
@ -349,7 +360,21 @@ export class AnnotationActionsService {
|
||||
title: this._translateService.instant('annotation-actions.force-redaction.label'),
|
||||
onClick: () => {
|
||||
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);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -42,27 +42,26 @@ export class AnnotationProcessingService {
|
||||
const filters: INestedFilter[] = [];
|
||||
|
||||
annotations?.forEach(a => {
|
||||
const topLevelFilter = !['hint', 'redaction', 'recommendation', 'skipped'].includes(a.superType);
|
||||
const key = topLevelFilter ? a.superType : a.superType + a.type;
|
||||
const filter = filterMap.get(key);
|
||||
const topLevelFilter = a.topLevelFilter;
|
||||
const filter = filterMap.get(a.filterKey);
|
||||
if (filter) {
|
||||
filter.matches += 1;
|
||||
} else {
|
||||
// top level filter
|
||||
if (topLevelFilter) {
|
||||
this._createParentFilter(key, filterMap, filters);
|
||||
this._createParentFilter(a.superType, filterMap, filters);
|
||||
} else {
|
||||
let parentFilter = filterMap.get(a.superType);
|
||||
if (!parentFilter) {
|
||||
parentFilter = this._createParentFilter(a.superType, filterMap, filters);
|
||||
}
|
||||
const childFilter: IFilter = {
|
||||
id: a.type,
|
||||
id: a.filterKey,
|
||||
label: a.type,
|
||||
checked: false,
|
||||
matches: 1,
|
||||
};
|
||||
filterMap.set(key, childFilter);
|
||||
filterMap.set(a.filterKey, childFilter);
|
||||
parentFilter.children.push(new Filter(childFilter));
|
||||
}
|
||||
}
|
||||
@ -173,12 +172,7 @@ export class AnnotationProcessingService {
|
||||
return true;
|
||||
};
|
||||
|
||||
private _checkByFilterKey = (filter: INestedFilter, annotation: AnnotationWrapper) => {
|
||||
const superType = annotation.superType;
|
||||
const isNotTopLevelFilter = superType === 'hint' || superType === 'redaction' || superType === 'recommendation';
|
||||
|
||||
return filter.id === superType || (filter.id === annotation.type && isNotTopLevelFilter);
|
||||
};
|
||||
private _checkByFilterKey = (filter: NestedFilter | IFilter, annotation: AnnotationWrapper) => filter.id === annotation.filterKey;
|
||||
|
||||
private _sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] {
|
||||
return annotations.sort((ann1, ann2) => {
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AddDossierDialogComponent } from '../dialogs/add-dossier-dialog/add-dossier-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 { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
||||
import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
|
||||
@ -22,7 +22,7 @@ type DialogType =
|
||||
| 'changeLegalBasis'
|
||||
| 'removeAnnotations'
|
||||
| 'resizeAnnotation'
|
||||
| 'forceRedaction'
|
||||
| 'forceAnnotation'
|
||||
| 'manualAnnotation';
|
||||
|
||||
@Injectable()
|
||||
@ -58,8 +58,8 @@ export class DossiersDialogService extends DialogService<DialogType> {
|
||||
resizeAnnotation: {
|
||||
component: ResizeAnnotationDialogComponent,
|
||||
},
|
||||
forceRedaction: {
|
||||
component: ForceRedactionDialogComponent,
|
||||
forceAnnotation: {
|
||||
component: ForceAnnotationDialogComponent,
|
||||
},
|
||||
manualAnnotation: {
|
||||
component: ManualAnnotationDialogComponent,
|
||||
|
||||
@ -24,6 +24,12 @@
|
||||
label="S"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'ignored-hint'"
|
||||
[color]="dictionaryColor"
|
||||
label="I"
|
||||
type="circle"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="isSuggestion(filter.id)"
|
||||
[color]="dictionaryColor"
|
||||
|
||||
@ -14,7 +14,6 @@ import { FileDropOverlayService } from './services/file-drop-overlay.service';
|
||||
@NgModule({
|
||||
imports: [CommonModule, SharedModule, OverlayModule],
|
||||
declarations: [FileDropComponent, UploadStatusOverlayComponent, OverwriteFilesDialogComponent],
|
||||
entryComponents: [FileDropComponent, UploadStatusOverlayComponent],
|
||||
providers: [UploadDownloadDialogService, FileUploadService, FileDownloadService, StatusOverlayService, FileDropOverlayService],
|
||||
exports: [FileDropComponent, UploadStatusOverlayComponent],
|
||||
})
|
||||
|
||||
@ -50,15 +50,17 @@ export class UserService extends EntitiesService<User, IUser> {
|
||||
);
|
||||
}
|
||||
|
||||
async loadCurrentUser() {
|
||||
async loadCurrentUser(): Promise<User> {
|
||||
const token = await this._keycloakService.getToken();
|
||||
const decoded = jwt_decode(token);
|
||||
const userId = (<{ sub: string }>decoded).sub;
|
||||
|
||||
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));
|
||||
return user;
|
||||
}
|
||||
|
||||
getNameForId(userId: string): string | undefined {
|
||||
|
||||
@ -176,6 +176,14 @@ export class AppStateService {
|
||||
true,
|
||||
);
|
||||
|
||||
dictionaryData['ignored-hint'] = new Dictionary(
|
||||
{
|
||||
hexColor: colors.ignoredHintColor,
|
||||
type: 'ignored-hint',
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
dictionaryData['manual-redaction'] = new Dictionary(
|
||||
{
|
||||
hexColor: colors.manualRedactionColor || FALLBACK_COLOR,
|
||||
|
||||
@ -4,6 +4,7 @@ import { AnnotationSuperType } from '../models/file/annotation.wrapper';
|
||||
export const annotationTypesTranslations: { [key in AnnotationSuperType]: string } = {
|
||||
'declined-suggestion': _('annotation-type.declined-suggestion'),
|
||||
hint: _('annotation-type.hint'),
|
||||
'ignored-hint': _('annotation-type.ignored-hint'),
|
||||
'manual-redaction': _('annotation-type.manual-redaction'),
|
||||
recommendation: _('annotation-type.recommendation'),
|
||||
redaction: _('annotation-type.redaction'),
|
||||
|
||||
@ -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 { Title } from '@angular/platform-browser';
|
||||
import { from, of, throwError } from 'rxjs';
|
||||
import { KeycloakEventType, KeycloakService } from 'keycloak-angular';
|
||||
import { GeneralSettingsService } from '@services/general-settings.service';
|
||||
import { LanguageService } from '@i18n/language.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { from, iif, of, throwError } from 'rxjs';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
export function configurationInitializer(
|
||||
keycloakService: KeycloakService,
|
||||
@ -13,28 +14,25 @@ export function configurationInitializer(
|
||||
configService: ConfigService,
|
||||
generalSettingsService: GeneralSettingsService,
|
||||
languageService: LanguageService,
|
||||
userService: UserService,
|
||||
userPreferenceService: UserPreferenceService,
|
||||
) {
|
||||
const userConfig$ = generalSettingsService.getGeneralConfigurations().pipe(
|
||||
switchMap(config => from(userPreferenceService.reload()).pipe(mapTo(config))),
|
||||
tap(() => languageService.chooseAndSetInitialLanguage()),
|
||||
);
|
||||
|
||||
return () =>
|
||||
keycloakService.keycloakEvents$
|
||||
.pipe(
|
||||
filter(event => event.type === KeycloakEventType.OnReady),
|
||||
switchMap(() => from(keycloakService.isLoggedIn())),
|
||||
switchMap(loggedIn => {
|
||||
const hasAnyRedRoles = !!keycloakService.getUserRoles().find(role => role.startsWith('RED_'));
|
||||
return !loggedIn ? throwError('Not Logged In') : of(hasAnyRedRoles);
|
||||
}),
|
||||
switchMap(hasRoles => iif(() => !!hasRoles, userConfig$, of({ displayName: 'RedactManager' }))),
|
||||
switchMap(loggedIn => (!loggedIn ? throwError('Not Logged In') : of({}))),
|
||||
switchMap(() => from(userService.loadCurrentUser())),
|
||||
switchMap(user => (!user.hasAnyREDRoles ? throwError('Not user has no red roles') : of({}))),
|
||||
mergeMap(() => generalSettingsService.getGeneralConfigurations()),
|
||||
tap(configuration => configService.updateDisplayName(configuration.displayName)),
|
||||
switchMap(() => userPreferenceService.reload()),
|
||||
catchError(() => {
|
||||
title.setTitle('RedactManager');
|
||||
return of({});
|
||||
}),
|
||||
tap(() => languageService.chooseAndSetInitialLanguage()),
|
||||
take(1),
|
||||
)
|
||||
.toPromise();
|
||||
|
||||
@ -10,6 +10,7 @@ export const SuperTypeSorter: { [key in AnnotationSuperType]: number } = {
|
||||
'suggestion-remove-dictionary': 13,
|
||||
'suggestion-add': 10,
|
||||
'suggestion-remove': 11,
|
||||
'ignored-hint': 45,
|
||||
skipped: 50,
|
||||
redaction: 1,
|
||||
'manual-redaction': 2,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"ADMIN_CONTACT_NAME": 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",
|
||||
"AUTO_READ_TIME": 1.5,
|
||||
"BACKEND_APP_VERSION": "4.4.40",
|
||||
@ -17,7 +17,7 @@
|
||||
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
||||
"OAUTH_CLIENT_ID": "redaction",
|
||||
"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,
|
||||
"SELECTION_MODE": "structural"
|
||||
}
|
||||
|
||||
@ -473,7 +473,8 @@
|
||||
"previewColor": "Vorschau",
|
||||
"requestAdd": "Neuen Wörterbucheintrag vorschlagen",
|
||||
"requestRemove": "Anfrage entfernt",
|
||||
"updatedColor": "Aktualisiert"
|
||||
"updatedColor": "Aktualisiert",
|
||||
"ignoredHintColor": "Ignorierter Hinweis"
|
||||
}
|
||||
},
|
||||
"dev-mode": "DEV",
|
||||
|
||||
@ -142,6 +142,9 @@
|
||||
},
|
||||
"annotation": "Annotation",
|
||||
"annotation-actions": {
|
||||
"force-hint": {
|
||||
"label": "Force Hint"
|
||||
},
|
||||
"accept-recommendation": {
|
||||
"label": "Accept Recommendation"
|
||||
},
|
||||
@ -277,6 +280,7 @@
|
||||
"annotation-type": {
|
||||
"declined-suggestion": "Declined Suggestion",
|
||||
"hint": "Hint",
|
||||
"ignored-hint": "Ignored Hint",
|
||||
"manual-redaction": "Manual Redaction",
|
||||
"recommendation": "Recommendation",
|
||||
"redaction": "Redaction",
|
||||
@ -474,7 +478,8 @@
|
||||
"previewColor": "Preview",
|
||||
"requestAdd": "Request Add",
|
||||
"requestRemove": "Request Remove",
|
||||
"updatedColor": "Updated"
|
||||
"updatedColor": "Updated",
|
||||
"ignoredHintColor": "Ignored Hint"
|
||||
}
|
||||
},
|
||||
"dev-mode": "DEV",
|
||||
@ -1282,7 +1287,8 @@
|
||||
"header": {
|
||||
"dictionary": "Add to dictionary",
|
||||
"false-positive": "Set false positive",
|
||||
"force": "Force Redaction",
|
||||
"force-redaction": "Force Redaction",
|
||||
"force-hint": "Force Hint",
|
||||
"redaction": "Redaction",
|
||||
"request-dictionary": "Request add to dictionary",
|
||||
"request-false-positive": "Request false positive",
|
||||
|
||||
@ -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>
|
||||
@ -9,4 +9,5 @@ export interface IColors {
|
||||
requestAdd?: string;
|
||||
requestRemove?: string;
|
||||
updatedColor?: string;
|
||||
ignoredHintColor?: string;
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ export type DefaultColorType =
|
||||
| 'defaultColor'
|
||||
| 'dictionaryRequestColor'
|
||||
| 'manualRedactionColor'
|
||||
| 'ignoredHintColor'
|
||||
| 'notRedacted'
|
||||
| 'previewColor'
|
||||
| 'requestAdd'
|
||||
|
||||
0
package-lock.json
generated
0
package-lock.json
generated
42
package.json
42
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "redaction",
|
||||
"version": "3.133.0",
|
||||
"version": "3.134.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@ -23,36 +23,36 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "13.0.2",
|
||||
"@angular/cdk": "13.0.2",
|
||||
"@angular/common": "13.0.2",
|
||||
"@angular/compiler": "13.0.2",
|
||||
"@angular/core": "13.0.2",
|
||||
"@angular/forms": "13.0.2",
|
||||
"@angular/material": "13.0.2",
|
||||
"@angular/animations": "13.1.1",
|
||||
"@angular/cdk": "13.1.1",
|
||||
"@angular/common": "13.1.1",
|
||||
"@angular/compiler": "13.1.1",
|
||||
"@angular/core": "13.1.1",
|
||||
"@angular/forms": "13.1.1",
|
||||
"@angular/material": "13.1.1",
|
||||
"@angular/material-moment-adapter": "^13.0.2",
|
||||
"@angular/platform-browser": "13.0.2",
|
||||
"@angular/platform-browser-dynamic": "13.0.2",
|
||||
"@angular/router": "13.0.2",
|
||||
"@angular/service-worker": "13.0.2",
|
||||
"@angular/platform-browser": "13.1.1",
|
||||
"@angular/platform-browser-dynamic": "13.1.1",
|
||||
"@angular/router": "13.1.1",
|
||||
"@angular/service-worker": "13.1.1",
|
||||
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
|
||||
"@materia-ui/ngx-monaco-editor": "^6.0.0-beta.1",
|
||||
"@ngx-translate/core": "^13.0.0",
|
||||
"@ngx-translate/http-loader": "^6.0.0",
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"@ngx-translate/http-loader": "^7.0.0",
|
||||
"@nrwl/angular": "13.2.3",
|
||||
"@pdftron/webviewer": "8.2.0",
|
||||
"@swimlane/ngx-charts": "^17.0.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"keycloak-angular": "^8.4.0",
|
||||
"keycloak-js": "15.0.2",
|
||||
"keycloak-angular": "^9.0.0",
|
||||
"keycloak-js": "^16.0.0",
|
||||
"lodash.orderby": "^4.6.0",
|
||||
"messageformat": "^2.3.0",
|
||||
"moment": "^2.29.1",
|
||||
"monaco-editor": "^0.30.1",
|
||||
"ngx-color-picker": "^11.0.0",
|
||||
"ngx-toastr": "^14.1.3",
|
||||
"ngx-translate-messageformat-compiler": "^4.10.0",
|
||||
"ngx-translate-messageformat-compiler": "^4.11.0",
|
||||
"papaparse": "^5.3.1",
|
||||
"rxjs": "~6.6.7",
|
||||
"sass": "^1.39.2",
|
||||
@ -62,13 +62,13 @@
|
||||
"zone.js": "0.11.4"
|
||||
},
|
||||
"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-template": "13.0.1",
|
||||
"@angular-eslint/template-parser": "13.0.1",
|
||||
"@angular/cli": "13.0.3",
|
||||
"@angular/compiler-cli": "13.0.2",
|
||||
"@angular/language-service": "13.0.2",
|
||||
"@angular/cli": "13.1.2",
|
||||
"@angular/compiler-cli": "13.1.1",
|
||||
"@angular/language-service": "13.1.1",
|
||||
"@nrwl/cli": "13.2.3",
|
||||
"@nrwl/cypress": "13.2.3",
|
||||
"@nrwl/eslint-plugin-nx": "13.2.3",
|
||||
|
||||
@ -9,10 +9,10 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"module": "esnext",
|
||||
"target": "es2017",
|
||||
"module": "es2020",
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"lib": ["es2019", "dom"],
|
||||
"lib": ["es2020", "dom"],
|
||||
"skipLibCheck": true,
|
||||
"skipDefaultLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user