work in progress direct-draw annotations
This commit is contained in:
parent
64cbfbeca4
commit
8236467579
@ -60,6 +60,7 @@ import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { ProjectMemberGuard } from './auth/project-member-guard.service';
|
||||
import { HumanizePipe } from './utils/humanize.pipe';
|
||||
|
||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -84,7 +85,8 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
SimpleDoughnutChartComponent,
|
||||
ManualRedactionDialogComponent,
|
||||
AnnotationIconComponent,
|
||||
AuthErrorComponent
|
||||
AuthErrorComponent,
|
||||
HumanizePipe
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
|
||||
@ -16,6 +16,7 @@ import { AddEditProjectDialogComponent } from './add-edit-project-dialog/add-edi
|
||||
import { AssignOwnerDialogComponent } from './assign-owner-dialog/assign-owner-dialog.component';
|
||||
import { ManualRedactionDialogComponent } from './manual-redaction-dialog/manual-redaction-dialog.component';
|
||||
import { Annotations } from '@pdftron/webviewer';
|
||||
import { ManualRedactionEntryWrapper } from '../screens/file/model/manual-redaction-entry.wrapper';
|
||||
|
||||
const dialogConfig = {
|
||||
width: '600px',
|
||||
@ -79,7 +80,7 @@ export class DialogService {
|
||||
}
|
||||
|
||||
public openManualRedactionDialog(
|
||||
$event: ManualRedactionEntry,
|
||||
$event: ManualRedactionEntryWrapper,
|
||||
cb?: Function
|
||||
): MatDialogRef<ManualRedactionDialogComponent> {
|
||||
const ref = this._dialog.open(ManualRedactionDialogComponent, {
|
||||
@ -89,6 +90,7 @@ export class DialogService {
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe((result) => {
|
||||
console.log(result);
|
||||
if (cb) {
|
||||
cb(result);
|
||||
}
|
||||
|
||||
@ -1,36 +1,39 @@
|
||||
<section class="dialog">
|
||||
<form (submit)="handleAddRedaction()" [formGroup]="redactionForm">
|
||||
<div class="dialog-header heading-l" translate="manual-redaction.dialog.header.label"></div>
|
||||
<div class="dialog-header heading-l" [translate]="title"></div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<div class="red-input-group">
|
||||
<label translate="manual-redaction.dialog.content.text.label"></label>
|
||||
</div>
|
||||
{{ addRedactionRequest.value }}
|
||||
{{ manualRedactionEntryWrapper.manualRedactionEntry.value }}
|
||||
|
||||
<div class="red-input-group">
|
||||
<label translate="manual-redaction.dialog.content.reason.label"></label>
|
||||
<textarea formControlName="reason" name="reason" type="text" rows="2"></textarea>
|
||||
<input formControlName="reason" name="reason" type="text" rows="2" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<label translate="manual-redaction.dialog.content.comment.label"></label>
|
||||
<textarea formControlName="comment" name="comment" type="text" rows="2"></textarea>
|
||||
<textarea formControlName="comment" name="comment" type="text" rows="4"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<label translate="manual-redaction.dialog.content.dictionary.label"></label>
|
||||
<mat-select formControlName="dictionary">
|
||||
<mat-option
|
||||
*ngFor="let dictionary of dictionaries | async"
|
||||
*ngFor="let dictionary of dictionaryOptions"
|
||||
[value]="dictionary.type"
|
||||
>
|
||||
{{ dictionary.type }}
|
||||
{{ dictionary.label }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<div
|
||||
class="red-input-group"
|
||||
[class.hidden]="this.manualRedactionEntryWrapper.type === 'HINT'"
|
||||
>
|
||||
<mat-checkbox color="primary" formControlName="addToDictionary">{{
|
||||
'manual-redaction.dialog.content.dictionary.add.label' | translate
|
||||
}}</mat-checkbox>
|
||||
|
||||
@ -10,9 +10,8 @@ import {
|
||||
} from '@redaction/red-ui-http';
|
||||
import { NotificationService, NotificationType } from '../../notification/notification.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs';
|
||||
import { UserService } from '../../user/user.service';
|
||||
import { ManualRedactionEntryWrapper } from '../../screens/file/model/manual-redaction-entry.wrapper';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-manual-redaction-dialog',
|
||||
@ -20,8 +19,8 @@ import { UserService } from '../../user/user.service';
|
||||
styleUrls: ['./manual-redaction-dialog.component.scss']
|
||||
})
|
||||
export class ManualRedactionDialogComponent implements OnInit {
|
||||
dictionaryOptions: TypeValue[] = [];
|
||||
redactionForm: FormGroup;
|
||||
dictionaries: Observable<Array<TypeValue>>;
|
||||
isDocumentAdmin: boolean;
|
||||
|
||||
constructor(
|
||||
@ -33,7 +32,7 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
private readonly _manualRedactionControllerService: ManualRedactionControllerService,
|
||||
private readonly _dictionaryControllerService: DictionaryControllerService,
|
||||
public dialogRef: MatDialogRef<ManualRedactionDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public addRedactionRequest: AddRedactionRequest
|
||||
@Inject(MAT_DIALOG_DATA) public manualRedactionEntryWrapper: ManualRedactionEntryWrapper
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -47,9 +46,18 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
dictionary: [null, Validators.required],
|
||||
comment: commentField
|
||||
});
|
||||
this.dictionaries = this._dictionaryControllerService
|
||||
.getAllTypes()
|
||||
.pipe(map((r) => r.types));
|
||||
|
||||
for (let key of Object.keys(this._appStateService.dictionaryData)) {
|
||||
const dictionaryData = this._appStateService.dictionaryData[key];
|
||||
if (!dictionaryData.virtual) {
|
||||
if (dictionaryData.hint && this.manualRedactionEntryWrapper.type === 'HINT') {
|
||||
this.dictionaryOptions.push(dictionaryData);
|
||||
}
|
||||
if (!dictionaryData.hint && this.manualRedactionEntryWrapper.type === 'REDACTION') {
|
||||
this.dictionaryOptions.push(dictionaryData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleAddRedaction() {
|
||||
@ -61,7 +69,7 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
}
|
||||
|
||||
suggestManualRedaction() {
|
||||
const mre = Object.assign({}, this.addRedactionRequest);
|
||||
const mre = Object.assign({}, this.manualRedactionEntryWrapper.manualRedactionEntry);
|
||||
this._enhanceManualRedaction(mre);
|
||||
this._manualRedactionControllerService
|
||||
.requestAddRedaction(
|
||||
@ -71,7 +79,6 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
)
|
||||
.subscribe(
|
||||
(ok) => {
|
||||
this._appStateService.reanalyseActiveFile();
|
||||
this._notificationService.showToastNotification(
|
||||
this._translateService.instant(
|
||||
'manual-redaction.dialog.add-redaction.success.label'
|
||||
@ -79,7 +86,7 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
null,
|
||||
NotificationType.SUCCESS
|
||||
);
|
||||
this.dialogRef.close();
|
||||
this.dialogRef.close({ mode: 'suggestion', request: mre });
|
||||
},
|
||||
(err) => {
|
||||
this._notificationService.showToastNotification(
|
||||
@ -95,7 +102,7 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
}
|
||||
|
||||
addManualRedaction() {
|
||||
const mre = Object.assign({}, this.addRedactionRequest);
|
||||
const mre = Object.assign({}, this.manualRedactionEntryWrapper.manualRedactionEntry);
|
||||
this._enhanceManualRedaction(mre);
|
||||
this._manualRedactionControllerService
|
||||
.addRedaction(
|
||||
@ -105,7 +112,6 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
)
|
||||
.subscribe(
|
||||
(ok) => {
|
||||
this._appStateService.reanalyseActiveFile();
|
||||
this._notificationService.showToastNotification(
|
||||
this._translateService.instant(
|
||||
'manual-redaction.dialog.add-redaction.success.label'
|
||||
@ -113,7 +119,7 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
null,
|
||||
NotificationType.SUCCESS
|
||||
);
|
||||
this.dialogRef.close();
|
||||
this.dialogRef.close({ mode: 'redaction', request: mre });
|
||||
},
|
||||
(err) => {
|
||||
this._notificationService.showToastNotification(
|
||||
@ -128,9 +134,28 @@ export class ManualRedactionDialogComponent implements OnInit {
|
||||
);
|
||||
}
|
||||
|
||||
get title() {
|
||||
if (this.isDocumentAdmin) {
|
||||
if (this.manualRedactionEntryWrapper.type === 'HINT') {
|
||||
return 'manual-redaction.dialog.header.hint.label';
|
||||
} else {
|
||||
return 'manual-redaction.dialog.header.redaction.label';
|
||||
}
|
||||
} else {
|
||||
if (this.manualRedactionEntryWrapper.type === 'HINT') {
|
||||
return 'manual-redaction.dialog.header.request-hint.label';
|
||||
} else {
|
||||
return 'manual-redaction.dialog.header.request-redaction.label';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _enhanceManualRedaction(addRedactionRequest: AddRedactionRequest) {
|
||||
addRedactionRequest.type = this.redactionForm.get('dictionary').value;
|
||||
addRedactionRequest.addToDictionary = this.redactionForm.get('addToDictionary').value;
|
||||
addRedactionRequest.addToDictionary =
|
||||
this.manualRedactionEntryWrapper.type === 'HINT'
|
||||
? true
|
||||
: this.redactionForm.get('addToDictionary').value;
|
||||
addRedactionRequest.reason = this.redactionForm.get('reason').value;
|
||||
const commentValue = this.redactionForm.get('comment').value;
|
||||
addRedactionRequest.comment = commentValue ? { text: commentValue } : null;
|
||||
|
||||
@ -23,6 +23,7 @@ import { saveAs } from 'file-saver';
|
||||
import { FileType } from '../model/file-type';
|
||||
import { DialogService } from '../../../dialogs/dialog.service';
|
||||
import { MatDialogRef, MatDialogState } from '@angular/material/dialog';
|
||||
import { ManualRedactionEntryWrapper } from '../model/manual-redaction-entry.wrapper';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-preview-screen',
|
||||
@ -94,7 +95,8 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
this._reloadFiles();
|
||||
this.appStateService.fileStatusChanged.subscribe((fileStatus) => {
|
||||
if (fileStatus.fileId === this.fileId) {
|
||||
this._reloadFiles();
|
||||
// no more automatic reloads
|
||||
// this._reloadFiles();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -185,23 +187,29 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
this._scrollAnnotationsToPage(pageNumber, 'always');
|
||||
}
|
||||
|
||||
public openManualRedactionDialog($event: ManualRedactionEntry) {
|
||||
public openManualRedactionDialog($event: ManualRedactionEntryWrapper) {
|
||||
this.ngZone.run(() => {
|
||||
this._dialogRef = this._dialogService.openManualRedactionDialog(
|
||||
$event,
|
||||
(annotation) => {
|
||||
// const annotManager = this.activeViewer.annotManager;
|
||||
// const rectangleAnnot = new this.activeViewer.Annotations.RectangleAnnotation();
|
||||
// rectangleAnnot.PageNumber = 1;
|
||||
// // values are in page coordinates with (0, 0) in the top left
|
||||
// rectangleAnnot.X = 100;
|
||||
// rectangleAnnot.Y = 150;
|
||||
// rectangleAnnot.Width = 200;
|
||||
// rectangleAnnot.Height = 50;
|
||||
// rectangleAnnot.Author = annotManager.getCurrentUser();
|
||||
//
|
||||
// annotManager.addAnnotation(rectangleAnnot,true);
|
||||
// annotManager.redrawAnnotation(rectangleAnnot);
|
||||
(response: any) => {
|
||||
const request: ManualRedactionEntry = response.request;
|
||||
|
||||
const annotManager = this.activeViewer.annotManager;
|
||||
const originalQuads = request.quads;
|
||||
for (const key of Object.keys(originalQuads)) {
|
||||
const pageNumber = parseInt(key, 10);
|
||||
const highlight = new this.activeViewer.Annotations.TextHighlightAnnotation();
|
||||
highlight.PageNumber = pageNumber;
|
||||
highlight.StrokeColor = new this.activeViewer.Annotations.Color(
|
||||
255,
|
||||
255,
|
||||
0
|
||||
);
|
||||
highlight.Quads = originalQuads[key];
|
||||
highlight.Id = this._computeId($event.type, request);
|
||||
annotManager.addAnnotation(highlight, true);
|
||||
annotManager.redrawAnnotation(highlight);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
@ -487,4 +495,8 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
this.applyFilters();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
private _computeId(type: 'HINT' | 'REDACTION', request: ManualRedactionEntry) {
|
||||
return 'request:' + type.toLowerCase() + ':' + new Date().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
import { ManualRedactionEntry } from '@redaction/red-ui-http';
|
||||
|
||||
export class ManualRedactionEntryWrapper {
|
||||
public mode: 'REQUEST' | 'ACTUAL';
|
||||
|
||||
constructor(
|
||||
public readonly manualRedactionEntry: ManualRedactionEntry,
|
||||
public readonly type: 'HINT' | 'REDACTION'
|
||||
) {}
|
||||
}
|
||||
@ -4,6 +4,7 @@ import {
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Input,
|
||||
NgZone,
|
||||
OnChanges,
|
||||
OnInit,
|
||||
Output,
|
||||
@ -17,6 +18,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { FileDownloadService } from '../service/file-download.service';
|
||||
import { Subject } from 'rxjs';
|
||||
import { throttleTime } from 'rxjs/operators';
|
||||
import { ManualRedactionEntryWrapper } from '../model/manual-redaction-entry.wrapper';
|
||||
|
||||
export interface ViewerState {
|
||||
displayMode?: any;
|
||||
@ -43,7 +45,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
@Output() fileReady = new EventEmitter();
|
||||
@Output() annotationsAdded = new EventEmitter<Annotations.Annotation[]>();
|
||||
@Output() annotationSelected = new EventEmitter<Annotations.Annotation>();
|
||||
@Output() manualAnnotationRequested = new EventEmitter<ManualRedactionEntry>();
|
||||
@Output() manualAnnotationRequested = new EventEmitter<ManualRedactionEntryWrapper>();
|
||||
@Output() pageChanged = new EventEmitter<number>();
|
||||
@Output() keyUp = new EventEmitter<KeyboardEvent>();
|
||||
|
||||
@ -57,17 +59,21 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
constructor(
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _fileDownloadService: FileDownloadService,
|
||||
private readonly _appConfigService: AppConfigService
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _ngZone: NgZone
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this._restoreViewerState = this._restoreViewerState.bind(this);
|
||||
// always publish all existing annotations this way everything gets drawn always
|
||||
this._annotationEventDebouncer
|
||||
.pipe(throttleTime(300))
|
||||
.subscribe((value) =>
|
||||
this.annotationsAdded.emit(this.instance.annotManager.getAnnotationsList())
|
||||
this._annotationEventDebouncer.pipe(throttleTime(300)).subscribe((value) => {
|
||||
this.annotationsAdded.emit(this.instance.annotManager.getAnnotationsList());
|
||||
// nasty double-emit fix, the annotationList is not updated when the event is fired
|
||||
setTimeout(
|
||||
() => this.annotationsAdded.emit(this.instance.annotManager.getAnnotationsList()),
|
||||
200
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
@ -95,6 +101,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
this._configureTextPopup();
|
||||
this._configureHeader();
|
||||
instance.annotManager.on('annotationChanged', (annotations, action) => {
|
||||
console.log(action, annotations);
|
||||
if (action === 'add') {
|
||||
this._annotationEventDebouncer.next(annotations);
|
||||
}
|
||||
@ -109,7 +116,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
});
|
||||
|
||||
instance.docViewer.on('pageComplete', (p) => {
|
||||
this.pageChanged.emit(p);
|
||||
this._ngZone.run(() => this.pageChanged.emit(p));
|
||||
});
|
||||
|
||||
instance.docViewer.on('documentLoaded', this._restoreViewerState);
|
||||
@ -153,6 +160,37 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
}
|
||||
|
||||
private _configureTextPopup() {
|
||||
this.instance.textPopup.add(<any>{
|
||||
type: 'actionButton',
|
||||
img: '/assets/icons/general/search-viewer.svg',
|
||||
title: this._translateService.instant('pdf-viewer.text-popup.actions.search.label'),
|
||||
onClick: () => {
|
||||
const text = this.instance.docViewer.getSelectedText();
|
||||
const searchOptions = {
|
||||
caseSensitive: true, // match case
|
||||
wholeWord: true, // match whole words only
|
||||
wildcard: false, // allow using '*' as a wildcard value
|
||||
regex: false, // string is treated as a regular expression
|
||||
searchUp: false, // search from the end of the document upwards
|
||||
ambientString: true // return ambient string as part of the result
|
||||
};
|
||||
this.instance.openElements(['searchPanel']);
|
||||
setTimeout(() => {
|
||||
this.instance.searchTextFull(text, searchOptions);
|
||||
}, 250);
|
||||
}
|
||||
});
|
||||
this.instance.textPopup.add(<any>{
|
||||
type: 'actionButton',
|
||||
img: '/assets/icons/general/add-hint.svg',
|
||||
title: this._translateService.instant(
|
||||
'pdf-viewer.text-popup.actions.suggestion-hint.label'
|
||||
),
|
||||
onClick: () => {
|
||||
const mre = this._getManualRedactionEntry();
|
||||
this.manualAnnotationRequested.emit(new ManualRedactionEntryWrapper(mre, 'HINT'));
|
||||
}
|
||||
});
|
||||
this.instance.textPopup.add(<any>{
|
||||
type: 'actionButton',
|
||||
img: '/assets/icons/general/add-redaction.svg',
|
||||
@ -160,20 +198,28 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
'pdf-viewer.text-popup.actions.suggestion-redaction.label'
|
||||
),
|
||||
onClick: () => {
|
||||
const selectedQuads = this.instance.docViewer.getSelectedTextQuads();
|
||||
const text = this.instance.docViewer.getSelectedText();
|
||||
const entry: ManualRedactionEntry = { positions: [] };
|
||||
for (const key of Object.keys(selectedQuads)) {
|
||||
for (const quad of selectedQuads[key]) {
|
||||
entry.positions.push(this.toPosition(parseInt(key, 10), quad));
|
||||
}
|
||||
}
|
||||
entry.value = text;
|
||||
this.manualAnnotationRequested.emit(entry);
|
||||
const mre = this._getManualRedactionEntry();
|
||||
this.manualAnnotationRequested.emit(
|
||||
new ManualRedactionEntryWrapper(mre, 'REDACTION')
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _getManualRedactionEntry(): ManualRedactionEntry {
|
||||
const selectedQuads = this.instance.docViewer.getSelectedTextQuads();
|
||||
const text = this.instance.docViewer.getSelectedText();
|
||||
const entry: ManualRedactionEntry = { positions: [] };
|
||||
for (const key of Object.keys(selectedQuads)) {
|
||||
for (const quad of selectedQuads[key]) {
|
||||
entry.positions.push(this.toPosition(parseInt(key, 10), quad));
|
||||
}
|
||||
}
|
||||
entry.quads = selectedQuads;
|
||||
entry.value = text;
|
||||
return entry;
|
||||
}
|
||||
|
||||
private toPosition(page: number, selectedQuad: any): Rectangle {
|
||||
const pageHeight = this.instance.docViewer.getPageHeight(page);
|
||||
const height = selectedQuad.y2 - selectedQuad.y4;
|
||||
|
||||
@ -103,7 +103,7 @@ export class AppStateService {
|
||||
}
|
||||
|
||||
getDictionaryLabel(type: string) {
|
||||
return this._dictionaryData[type]['label'];
|
||||
return this._dictionaryData[type].label;
|
||||
}
|
||||
|
||||
get isActiveFileDocumentReviewer() {
|
||||
@ -362,30 +362,42 @@ export class AppStateService {
|
||||
tap((colors) => {
|
||||
this._dictionaryData['request'] = {
|
||||
hexColor: colors.requestAdd,
|
||||
type: 'request'
|
||||
type: 'request',
|
||||
virtual: true
|
||||
};
|
||||
this._dictionaryData['ignore'] = {
|
||||
hexColor: colors.notRedacted,
|
||||
type: 'ignore'
|
||||
type: 'ignore',
|
||||
virtual: true
|
||||
};
|
||||
this._dictionaryData['default'] = {
|
||||
hexColor: colors.defaultColor,
|
||||
type: 'default'
|
||||
type: 'default',
|
||||
virtual: true
|
||||
};
|
||||
this._dictionaryData['add'] = {
|
||||
hexColor: colors.requestAdd,
|
||||
type: 'add',
|
||||
virtual: true
|
||||
};
|
||||
this._dictionaryData['add'] = { hexColor: colors.requestAdd, type: 'add' };
|
||||
this._dictionaryData['remove'] = {
|
||||
hexColor: colors.requestRemove,
|
||||
type: 'remove'
|
||||
type: 'remove',
|
||||
virtual: true
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const result = await forkJoin([typeObs, colorsObs]).toPromise();
|
||||
|
||||
this._dictionaryData['hint'] = { hexColor: '#283241', type: 'hint' };
|
||||
this._dictionaryData['redaction'] = { hexColor: '#283241', type: 'redaction' };
|
||||
this._dictionaryData['hint'] = { hexColor: '#283241', type: 'hint', virtual: true };
|
||||
this._dictionaryData['redaction'] = {
|
||||
hexColor: '#283241',
|
||||
type: 'redaction',
|
||||
virtual: true
|
||||
};
|
||||
for (const key of Object.keys(this._dictionaryData)) {
|
||||
this._dictionaryData[key]['label'] = humanize(key);
|
||||
this._dictionaryData[key].label = humanize(key);
|
||||
}
|
||||
} else {
|
||||
return this._dictionaryData;
|
||||
|
||||
11
apps/red-ui/src/app/utils/humanize.pipe.ts
Normal file
11
apps/red-ui/src/app/utils/humanize.pipe.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { humanize } from './functions';
|
||||
|
||||
@Pipe({
|
||||
name: 'humanize'
|
||||
})
|
||||
export class HumanizePipe implements PipeTransform {
|
||||
transform(item: string): any {
|
||||
return humanize(item);
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,18 @@
|
||||
},
|
||||
"dialog": {
|
||||
"header": {
|
||||
"label": "Add Manual Redaction"
|
||||
"hint": {
|
||||
"label": "Add Hint"
|
||||
},
|
||||
"redaction": {
|
||||
"label": "Add Redaction"
|
||||
},
|
||||
"request-hint": {
|
||||
"label": "Request Hint"
|
||||
},
|
||||
"request-redaction": {
|
||||
"label": "Request Redaction"
|
||||
}
|
||||
},
|
||||
"add-redaction": {
|
||||
"success": {
|
||||
@ -47,7 +58,7 @@
|
||||
},
|
||||
"actions": {
|
||||
"save": {
|
||||
"label": "Save Manual Redaction"
|
||||
"label": "Save"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
@ -92,6 +103,12 @@
|
||||
"actions": {
|
||||
"suggestion-redaction": {
|
||||
"label": "Suggest Redaction"
|
||||
},
|
||||
"suggestion-hint": {
|
||||
"label": "Suggest Hint"
|
||||
},
|
||||
"search": {
|
||||
"label": "Search for selection"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
apps/red-ui/src/assets/icons/general/add-hint.svg
Normal file
4
apps/red-ui/src/assets/icons/general/add-hint.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg height="512pt" viewBox="-82 0 512 512.00163" width="512pt" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="rgb(136,142,149)"
|
||||
d="m329.089844 94.824219c-1.921875-3.75-6.515625-5.230469-10.265625-3.3125-3.75 1.921875-5.234375 6.519531-3.3125 10.269531 11.523437 22.5 17.367187 46.820312 17.367187 72.285156 0 34.808594-11.054687 67.855469-31.96875 95.5625-8.675781 11.496094-13.453125 25.953125-13.453125 40.707032v.972656c0 20.777344-16.902343 37.679687-37.675781 37.679687h-68.085938v-96.597656c27.527344-3.738281 48.820313-27.382813 48.820313-55.917969 0-4.214844-3.417969-7.628906-7.628906-7.628906-4.214844 0-7.628907 3.414062-7.628907 7.628906 0 22.710938-18.476562 41.191406-41.191406 41.191406s-41.191406-18.480468-41.191406-41.191406c0-4.214844-3.414062-7.628906-7.628906-7.628906-4.210938 0-7.628906 3.414062-7.628906 7.628906 0 28.535156 21.292968 52.179688 48.820312 55.917969v96.597656h-68.085938c-20.773437 0-37.675781-16.902343-37.675781-37.679687v-.984375c0-14.839844-4.816406-29.128907-13.929687-41.324219-20.273438-27.144531-31.160156-59.441406-31.484375-93.394531-.402344-42.5 15.941406-82.65625 46.015625-113.074219 30.066406-30.40625 70.015625-47.195312 112.492187-47.273438h.300781c49.964844 0 96.007813 22.804688 126.355469 62.601563 2.558594 3.347656 7.34375 3.992187 10.691407 1.4375 3.351562-2.554687 3.996093-7.339844 1.441406-10.6875-15.933594-20.898437-36.722656-38.191406-60.117188-50.007813-24.539062-12.394531-51.058594-18.6718745-78.699218-18.601562-46.574219.0859375-90.367188 18.484375-123.3125 51.800781-32.957032 33.332031-50.863282 77.351563-50.4218755 123.949219.3554685 37.21875 12.2890625 72.621094 34.5195315 102.378906 7.125 9.539063 10.890625 20.671875 10.890625 32.195313v.984375c0 16.269531 7.382812 30.839844 18.964843 40.558594-11.171874 5.074218-18.964843 16.328124-18.964843 29.375 0 14.832031 10.070312 27.351562 23.726562 31.101562-3.539062 5.175781-5.609375 11.425781-5.609375 18.152344 0 17.785156 14.46875 32.253906 32.253906 32.253906h21.652344c3.742188 27.769531 27.578125 49.25 56.355469 49.25s52.613281-21.484375 56.351563-49.25h21.652343c17.785157 0 32.253907-14.46875 32.253907-32.253906 0-6.726563-2.070313-12.976563-5.605469-18.152344 13.65625-3.75 23.722656-16.269531 23.722656-31.101562 0-12.910157-7.628906-24.066407-18.609375-29.214844 11.691406-9.71875 19.152344-24.359375 19.152344-40.714844v-.972656c0-11.460938 3.683594-22.652344 10.371094-31.519532 22.925781-30.375 35.046874-66.601562 35.046874-104.75 0-27.910156-6.40625-54.570312-19.042968-79.246093zm-155.292969 401.921875c-20.347656 0-37.316406-14.679688-40.910156-33.996094h81.820312c-3.59375 19.316406-20.566406 33.996094-40.910156 33.996094zm96.121094-132.5c9.375 0 17 7.625 17 16.996094 0 9.375-7.625 17-17 17h-132.792969c-4.210938 0-7.628906 3.414062-7.628906 7.625 0 4.214843 3.417968 7.628906 7.628906 7.628906h114.675781c9.375 0 17 7.625 17 17 0 9.371094-7.625 16.996094-17 16.996094h-156.011719c-9.371093 0-16.996093-7.625-16.996093-16.996094 0-9.375 7.625-17 16.996093-17h10.824219c4.210938 0 7.625-3.414063 7.625-7.628906 0-4.210938-3.414062-7.625-7.625-7.625h-28.941406c-9.371094 0-16.996094-7.628907-16.996094-17 0-9.375 7.625-16.996094 16.996094-16.996094zm0 0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
11
apps/red-ui/src/assets/icons/general/search-viewer.svg
Normal file
11
apps/red-ui/src/assets/icons/general/search-viewer.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 512.005 512.005" style="enable-background:new 0 0 512.005 512.005;" xml:space="preserve">
|
||||
<g fill="rgb(136,142,149)">
|
||||
<path d="M505.749,475.587l-145.6-145.6c28.203-34.837,45.184-79.104,45.184-127.317c0-111.744-90.923-202.667-202.667-202.667
|
||||
S0,90.925,0,202.669s90.923,202.667,202.667,202.667c48.213,0,92.48-16.981,127.317-45.184l145.6,145.6
|
||||
c4.16,4.16,9.621,6.251,15.083,6.251s10.923-2.091,15.083-6.251C514.091,497.411,514.091,483.928,505.749,475.587z
|
||||
M202.667,362.669c-88.235,0-160-71.765-160-160s71.765-160,160-160s160,71.765,160,160S290.901,362.669,202.667,362.669z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 875 B |
@ -22,6 +22,7 @@ export interface ManualRedactionEntry {
|
||||
type?: string;
|
||||
user?: string;
|
||||
value?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export namespace ManualRedactionEntry {
|
||||
|
||||
@ -30,4 +30,6 @@ export interface TypeValue {
|
||||
* The nonnull entry type.
|
||||
*/
|
||||
type?: string;
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user