diff --git a/apps/red-ui/proxy.conf.json b/apps/red-ui/proxy.conf.json
index 91033ed01..53049ec45 100644
--- a/apps/red-ui/proxy.conf.json
+++ b/apps/red-ui/proxy.conf.json
@@ -52,5 +52,11 @@
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
+ },
+ "/color": {
+ "target": "https://timo-redaction-dev.iqser.cloud/",
+ "secure": false,
+ "changeOrigin": true,
+ "logLevel": "debug"
}
}
diff --git a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.html b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.html
index f5fe7f12d..b42260938 100644
--- a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.html
+++ b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.html
@@ -1,3 +1,3 @@
-
-
{{ type[0] }}
+
+ {{ typeValue.type[0] }}
diff --git a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss
index 360662073..cb9a7dd42 100644
--- a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss
+++ b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.scss
@@ -40,33 +40,10 @@
}
.hint,
-.comment,
.ignore {
border-radius: 50%;
}
-.hint,
-.redaction,
-.comment {
- background-color: $grey-1;
-}
-
-.request {
- background-color: $blue-1;
-}
-
.ignore {
background-color: $grey-5;
}
-
-.hint_only {
- background-color: $orange-1;
-}
-
-.vertebrate {
- background-color: $green-1;
-}
-
-.names {
- background-color: $yellow-2;
-}
diff --git a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.ts b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.ts
index b317716b9..35dc28774 100644
--- a/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.ts
+++ b/apps/red-ui/src/app/components/annotation-icon/annotation-icon.component.ts
@@ -1,4 +1,5 @@
import { Component, Input, OnInit } from '@angular/core';
+import { TypeValue } from '@redaction/red-ui-http';
@Component({
selector: 'redaction-annotation-icon',
@@ -6,7 +7,7 @@ import { Component, Input, OnInit } from '@angular/core';
styleUrls: ['./annotation-icon.component.scss']
})
export class AnnotationIconComponent implements OnInit {
- @Input() public type: 'hint' | 'redaction' | 'suggestion' | 'ignore' | 'comment' | 'request';
+ @Input() typeValue: TypeValue;
constructor() {}
diff --git a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.ts b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.ts
index 9fe639c75..57274bfca 100644
--- a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.ts
+++ b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-redaction-dialog.component.ts
@@ -38,9 +38,8 @@ export class ManualRedactionDialogComponent implements OnInit {
async ngOnInit() {
this.isDocumentAdmin =
- (this._appStateService.isActiveProjectOwner ||
- this._appStateService.isActiveFileDocumentReviewer) &&
- this._userService.user.isManager;
+ this._appStateService.isActiveProjectOwner && this._userService.user.isManager;
+ this.isDocumentAdmin = false;
const commentField = this.isDocumentAdmin ? [null] : [null, Validators.required];
this.redactionForm = this._formBuilder.group({
addToDictionary: [false],
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html
index 0a09f089f..84e6a33fa 100644
--- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html
+++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html
@@ -145,8 +145,9 @@
color="primary"
>
+
{{ 'file-preview.filter-menu.' + key + '.label' | translate }}
@@ -162,15 +163,11 @@
color="primary"
>
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts
index 890ddf6d3..a150195aa 100644
--- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts
+++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts
@@ -8,7 +8,12 @@ import {
ViewChild
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
-import { ManualRedactionEntry, ReanalysisControllerService } from '@redaction/red-ui-http';
+import {
+ DictionaryControllerService,
+ ManualRedactionEntry,
+ ReanalysisControllerService,
+ TypeValue
+} from '@redaction/red-ui-http';
import { AppStateService } from '../../../state/app-state.service';
import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component';
@@ -56,6 +61,7 @@ export class FilePreviewScreenComponent implements OnInit {
private readonly _activatedRoute: ActivatedRoute,
private readonly _dialogService: DialogService,
private readonly _router: Router,
+ private readonly _dictionaryControllerService: DictionaryControllerService,
private readonly _userService: UserService,
private readonly _fileDownloadService: FileDownloadService,
private readonly _reanalysisControllerService: ReanalysisControllerService,
@@ -67,7 +73,6 @@ export class FilePreviewScreenComponent implements OnInit {
this.fileId = params.fileId;
this.appStateService.activateFile(this.projectId, this.fileId);
});
- this.filters = _filtersService.filters;
}
public get user() {
@@ -91,7 +96,7 @@ export class FilePreviewScreenComponent implements OnInit {
}
public ngOnInit(): void {
- // PDFTRON cache fix
+ this.filters = this._filtersService.getFilters(this.appStateService.dictionaryData);
this._reloadFiles();
this.appStateService.fileStatusChanged.subscribe((fileStatus) => {
if (fileStatus.fileId === this.fileId) {
@@ -273,7 +278,7 @@ export class FilePreviewScreenComponent implements OnInit {
});
}
- public setAllFilters(filter: AnnotationFilters, value: boolean, rootKey?: string) {
+ public setAllFilters(filter: string, value: boolean, rootKey?: string) {
if (rootKey) {
this.filters[rootKey] = value;
} else {
diff --git a/apps/red-ui/src/app/screens/file/service/filters.service.ts b/apps/red-ui/src/app/screens/file/service/filters.service.ts
index 406d0f58c..a1ab6b48a 100644
--- a/apps/red-ui/src/app/screens/file/service/filters.service.ts
+++ b/apps/red-ui/src/app/screens/file/service/filters.service.ts
@@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { AnnotationFilters } from '../../../utils/types';
+import { TypeValue } from '@redaction/red-ui-http';
@Injectable({
providedIn: 'root'
@@ -8,18 +9,23 @@ export class FiltersService {
constructor() {}
private _filters: AnnotationFilters = {
- hint: {
- hint_only: false,
- vertebrate: false,
- names: false
- },
- redaction: false,
- comment: false,
- suggestion: false,
+ hint: {},
+ redaction: {},
+ request: false,
ignore: false
};
- public get filters(): AnnotationFilters {
- return JSON.parse(JSON.stringify(this._filters));
+ public getFilters(dictionaryData: { [key: string]: TypeValue }): AnnotationFilters {
+ const filtersCopy = JSON.parse(JSON.stringify(this._filters));
+ for (let key of Object.keys(dictionaryData)) {
+ const typeValue = dictionaryData[key];
+ if (typeValue.hint === true) {
+ filtersCopy.hint[key] = false;
+ }
+ if (typeValue.hint === false) {
+ filtersCopy.redaction[key] = false;
+ }
+ }
+ return filtersCopy;
}
}
diff --git a/apps/red-ui/src/app/state/app-state.guard.ts b/apps/red-ui/src/app/state/app-state.guard.ts
index 9ba4ff530..0813c2472 100644
--- a/apps/red-ui/src/app/state/app-state.guard.ts
+++ b/apps/red-ui/src/app/state/app-state.guard.ts
@@ -15,6 +15,7 @@ export class AppStateGuard implements CanActivate {
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise {
await this._userService.loadAllUsersIfNecessary();
await this._appStateService.loadAllProjectsIfNecessary();
+ await this._appStateService.loadDictionaryDataIfNecessary();
return true;
}
diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts
index faedae0cc..f42edd9dc 100644
--- a/apps/red-ui/src/app/state/app-state.service.ts
+++ b/apps/red-ui/src/app/state/app-state.service.ts
@@ -1,19 +1,22 @@
import { EventEmitter, Injectable } from '@angular/core';
import {
+ DictionaryControllerService,
FileStatus,
FileUploadControllerService,
Project,
ProjectControllerService,
ReanalysisControllerService,
- StatusControllerService
+ StatusControllerService,
+ TypeValue
} from '@redaction/red-ui-http';
import { NotificationService, NotificationType } from '../notification/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { Router } from '@angular/router';
import { UserService } from '../user/user.service';
-import { interval } from 'rxjs';
+import { forkJoin, interval } from 'rxjs';
import { tap } from 'rxjs/operators';
import { download } from '../utils/file-download-utils';
+import { humanize } from '../utils/functions';
export interface AppState {
projects: ProjectWrapper[];
@@ -37,6 +40,7 @@ export class ProjectWrapper {
})
export class AppStateService {
private _appState: AppState;
+ private _dictionaryData: { [key: string]: TypeValue } = null;
public fileStatusChanged = new EventEmitter();
@@ -48,6 +52,7 @@ export class AppStateService {
private readonly _notificationService: NotificationService,
private readonly _reanalysisControllerService: ReanalysisControllerService,
private readonly _translateService: TranslateService,
+ private readonly _dictionaryControllerService: DictionaryControllerService,
private readonly _statusControllerService: StatusControllerService
) {
this._appState = {
@@ -90,6 +95,19 @@ export class AppStateService {
);
}
+ get dictionaryData() {
+ return this._dictionaryData;
+ }
+
+ getDictionaryColor(type: string) {
+ const color = this._dictionaryData[type].hexColor;
+ return color ? color : this._dictionaryData['default'].hexColor;
+ }
+
+ getDictionaryLabel(type: string) {
+ return this._dictionaryData[type]['label'];
+ }
+
get isActiveFileDocumentReviewer() {
return this._appState.activeFile?.currentReviewer === this._userService.userId;
}
@@ -331,4 +349,53 @@ export class AppStateService {
download(data, 'redaction-report-' + file.filename + '.docx');
});
}
+
+ async loadDictionaryDataIfNecessary() {
+ if (!this._dictionaryData) {
+ this._dictionaryData = {};
+ const typeObs = this._dictionaryControllerService.getAllTypes().pipe(
+ tap((typesResponse) => {
+ for (let type of typesResponse.types) {
+ this._dictionaryData[type.type] = type;
+ }
+ })
+ );
+ const colorsObs = this._dictionaryControllerService.getColors().pipe(
+ tap((colors) => {
+ this._dictionaryData['request'] = {
+ hexColor: colors.requestAdd,
+ type: 'request'
+ };
+ this._dictionaryData['ignore'] = {
+ hexColor: colors.notRedacted,
+ type: 'ignore'
+ };
+ this._dictionaryData['default'] = {
+ hexColor: colors.defaultColor,
+ type: 'default'
+ };
+ this._dictionaryData['add'] = { hexColor: colors.requestAdd, type: 'add' };
+ this._dictionaryData['remove'] = {
+ hexColor: colors.requestRemove,
+ type: 'remove'
+ };
+ })
+ );
+
+ const result = await forkJoin([typeObs, colorsObs]).toPromise();
+
+ this._dictionaryData['hint'] = { hexColor: '#283241', type: 'hint' };
+ this._dictionaryData['redaction'] = { hexColor: '#283241', type: 'redaction' };
+ for (let key of Object.keys(this._dictionaryData)) {
+ this._dictionaryData[key]['label'] = humanize(key);
+ }
+ } else {
+ return this._dictionaryData;
+ }
+ }
+
+ getDictionaryTypeValue(key: string) {
+ const data = this._dictionaryData[key];
+ return data ? data : this._dictionaryData['default'];
+ }
}
diff --git a/apps/red-ui/src/app/utils/annotation-utils.ts b/apps/red-ui/src/app/utils/annotation-utils.ts
index 8ac39c182..ece0ddb0d 100644
--- a/apps/red-ui/src/app/utils/annotation-utils.ts
+++ b/apps/red-ui/src/app/utils/annotation-utils.ts
@@ -72,8 +72,7 @@ export class AnnotationUtils {
annotations: [],
hint: 0,
redaction: 0,
- comment: 0,
- suggestion: 0,
+ request: 0,
ignore: 0
};
}
diff --git a/apps/red-ui/src/app/utils/functions.ts b/apps/red-ui/src/app/utils/functions.ts
index 1ce38d109..87ebe129c 100644
--- a/apps/red-ui/src/app/utils/functions.ts
+++ b/apps/red-ui/src/app/utils/functions.ts
@@ -4,3 +4,11 @@ export function groupBy(xs: any[], key: string) {
return rv;
}, {});
}
+
+export function humanize(str: string) {
+ let frags = str.split(/[ \-_]+/);
+ for (let i = 0; i < frags.length; i++) {
+ frags[i] = frags[i].charAt(0).toUpperCase() + frags[i].slice(1);
+ }
+ return frags.join(' ');
+}
diff --git a/apps/red-ui/src/app/utils/types.d.ts b/apps/red-ui/src/app/utils/types.d.ts
index 9c0ad57e7..40d6aa603 100644
--- a/apps/red-ui/src/app/utils/types.d.ts
+++ b/apps/red-ui/src/app/utils/types.d.ts
@@ -2,8 +2,6 @@ import { FileStatus } from '@redaction/red-ui-http';
export type Color = FileStatus.StatusEnum | ProjectStatus.StatusEnum;
-export type AnnotationType = 'hint' | 'redaction' | 'suggestion' | 'comment' | 'ignore';
-
export class SortingOption {
label: string;
order: string;
@@ -11,5 +9,5 @@ export class SortingOption {
}
export class AnnotationFilters {
- [key: AnnotationType]: boolean;
+ [key: string]: boolean | {};
}
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index a058d158f..c5fe5854b 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -442,26 +442,14 @@
"filter-types": {
"label": "Filter types"
},
- "hint": {
- "label": "Hint annotation",
- "hint_only": {
- "label": "Hint only"
- },
- "vertebrate": {
- "label": "Vertebrate"
- },
- "names": {
- "label": "Names"
- }
- },
"redaction": {
"label": "Redaction"
},
- "comment": {
- "label": "Comment annotation"
+ "hint": {
+ "label": "Hint"
},
- "suggestion": {
- "label": "Suggested redaction"
+ "request": {
+ "label": "Redaction Request"
},
"ignore": {
"label": "Ignored redaction"
diff --git a/docker/common/nginx/nginx.conf.template b/docker/common/nginx/nginx.conf.template
index 23ae4c03a..a76a14591 100644
--- a/docker/common/nginx/nginx.conf.template
+++ b/docker/common/nginx/nginx.conf.template
@@ -17,6 +17,9 @@ server {
location /project {
proxy_pass $API_URL;
}
+ location /color {
+ proxy_pass $API_URL;
+ }
location /user {
proxy_pass $API_URL;
}