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 { 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;
// }

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

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

View File

@ -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'),
};

View File

@ -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>

View File

@ -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());
}

View File

@ -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">

View File

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

View File

@ -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"

View File

@ -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'

View File

@ -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>

View File

@ -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);
});
},
});

View File

@ -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) => {

View File

@ -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,

View File

@ -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"

View File

@ -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],
})

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 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 {

View File

@ -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,

View File

@ -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'),

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 { 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();

View File

@ -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,

View File

@ -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"
}

View File

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

View File

@ -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",

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;
requestRemove?: string;
updatedColor?: string;
ignoredHintColor?: string;
}

View File

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

0
package-lock.json generated
View File

View File

@ -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",

View File

@ -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": ".",

1948
yarn.lock

File diff suppressed because it is too large Load Diff