fixed lint
This commit is contained in:
parent
59f5a884b9
commit
e07599cf27
@ -17,6 +17,12 @@
|
||||
"changeOrigin": true,
|
||||
"logLevel": "debug"
|
||||
},
|
||||
"/redactionLog": {
|
||||
"target": "https://timo-redaction-dev.iqser.cloud/",
|
||||
"secure": false,
|
||||
"changeOrigin": true,
|
||||
"logLevel": "debug"
|
||||
},
|
||||
"/user": {
|
||||
"target": "https://timo-redaction-dev.iqser.cloud/",
|
||||
"secure": false,
|
||||
|
||||
@ -74,14 +74,13 @@
|
||||
<div class="flex red-content-inner">
|
||||
<div class="left-container">
|
||||
<redaction-pdf-viewer
|
||||
*ngIf="annotatedFileData && redactedFileData"
|
||||
[fileData]="redactedView ? redactedFileData : annotatedFileData"
|
||||
*ngIf="fileData"
|
||||
[fileData]="redactedView ? fileData.redactedFileData : fileData.annotatedFileData"
|
||||
[fileStatus]="appStateService.activeFile"
|
||||
(keyUp)="handleKeyEvent($event)"
|
||||
(pageChanged)="viewerPageChanged($event)"
|
||||
(manualAnnotationRequested)="openManualRedactionDialog($event)"
|
||||
(annotationSelected)="handleAnnotationSelected($event)"
|
||||
(annotationsAdded)="handleAnnotationsAdded($event)"
|
||||
(viewerReady)="viewerReady($event)"
|
||||
></redaction-pdf-viewer>
|
||||
</div>
|
||||
@ -121,65 +120,58 @@
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngFor="let key of filterKeys()">
|
||||
<div
|
||||
class="mat-menu-item flex"
|
||||
(click)="setExpanded(key, !expandedFilters[key], $event)"
|
||||
>
|
||||
<div class="arrow-wrapper" *ngIf="hasSubsections(filters[key])">
|
||||
<mat-icon
|
||||
*ngIf="expandedFilters[key]"
|
||||
svgIcon="red:arrow-down"
|
||||
color="accent"
|
||||
>
|
||||
</mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="!expandedFilters[key]"
|
||||
color="accent"
|
||||
svgIcon="red:arrow-right"
|
||||
>
|
||||
</mat-icon>
|
||||
</div>
|
||||
<mat-checkbox
|
||||
[checked]="isChecked(key)"
|
||||
[indeterminate]="isIndeterminate(key)"
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="
|
||||
setAllFilters(
|
||||
filters[key],
|
||||
$event.checked,
|
||||
hasSubsections(filters[key]) ? null : key
|
||||
)
|
||||
"
|
||||
color="primary"
|
||||
>
|
||||
<redaction-annotation-icon
|
||||
[typeValue]="appStateService.getDictionaryTypeValue(key)"
|
||||
></redaction-annotation-icon>
|
||||
<!-- <div *ngFor="let key of filterKeys()">-->
|
||||
<!-- <div-->
|
||||
<!-- class="mat-menu-item flex"-->
|
||||
<!-- (click)="setExpanded(key, !expandedFilters[key], $event)"-->
|
||||
<!-- >-->
|
||||
<!-- <div class="arrow-wrapper" *ngIf="hasSubsections(filters[key])">-->
|
||||
<!-- <mat-icon-->
|
||||
<!-- *ngIf="expandedFilters[key]"-->
|
||||
<!-- svgIcon="red:arrow-down"-->
|
||||
<!-- color="accent"-->
|
||||
<!-- >-->
|
||||
<!-- </mat-icon>-->
|
||||
<!-- <mat-icon-->
|
||||
<!-- *ngIf="!expandedFilters[key]"-->
|
||||
<!-- color="accent"-->
|
||||
<!-- svgIcon="red:arrow-right"-->
|
||||
<!-- >-->
|
||||
<!-- </mat-icon>-->
|
||||
<!-- </div>-->
|
||||
<!-- <mat-checkbox-->
|
||||
<!-- [checked]="isChecked(key)"-->
|
||||
<!-- [indeterminate]="isIndeterminate(key)"-->
|
||||
<!-- (click)="filterClicked($event,key)"-->
|
||||
<!-- color="primary"-->
|
||||
<!-- >-->
|
||||
<!-- <redaction-annotation-icon-->
|
||||
<!-- [typeValue]="appStateService.getDictionaryTypeValue(key)"-->
|
||||
<!-- ></redaction-annotation-icon>-->
|
||||
|
||||
{{ 'file-preview.filter-menu.' + key + '.label' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div *ngIf="hasSubsections(filters[key]) && expandedFilters[key]">
|
||||
<div
|
||||
*ngFor="let subkey of filterKeys(key)"
|
||||
class="padding-left mat-menu-item"
|
||||
(click)="$event.stopPropagation()"
|
||||
>
|
||||
<mat-checkbox
|
||||
[(ngModel)]="filters[key][subkey]"
|
||||
color="primary"
|
||||
>
|
||||
<redaction-annotation-icon
|
||||
[typeValue]="
|
||||
appStateService.getDictionaryTypeValue(subkey)
|
||||
"
|
||||
></redaction-annotation-icon>
|
||||
{{ appStateService.getDictionaryLabel(subkey) }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- {{ 'file-preview.filter-menu.' + key + '.label' | translate }}-->
|
||||
<!-- </mat-checkbox>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div *ngIf="hasSubsections(filters[key]) && expandedFilters[key]">-->
|
||||
<!-- <div-->
|
||||
<!-- *ngFor="let subkey of filterKeys(key)"-->
|
||||
<!-- class="padding-left mat-menu-item"-->
|
||||
<!-- >-->
|
||||
<!-- <mat-checkbox-->
|
||||
<!-- [checked]="filters[key][subkey]"-->
|
||||
<!-- (click)="filterClicked($event,key,subkey)"-->
|
||||
<!-- color="primary"-->
|
||||
<!-- >-->
|
||||
<!-- <redaction-annotation-icon-->
|
||||
<!-- [typeValue]="-->
|
||||
<!-- appStateService.getDictionaryTypeValue(subkey)-->
|
||||
<!-- "-->
|
||||
<!-- ></redaction-annotation-icon>-->
|
||||
<!-- {{ appStateService.getDictionaryLabel(subkey) }}-->
|
||||
<!-- </mat-checkbox>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -16,7 +16,6 @@ import { AnnotationUtils } from '../../../utils/annotation-utils';
|
||||
import { UserService } from '../../../user/user.service';
|
||||
import { debounce } from '../../../utils/debounce';
|
||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||
import { AnnotationFilters } from '../../../utils/types';
|
||||
import { FiltersService } from '../service/filters.service';
|
||||
import { FileDownloadService } from '../service/file-download.service';
|
||||
import { saveAs } from 'file-saver';
|
||||
@ -28,6 +27,8 @@ import { hexToRgb } from '../../../utils/functions';
|
||||
import { AnnotationWrapper } from '../model/annotation.wrapper';
|
||||
import { ManualAnnotationService } from '../service/manual-annotation.service';
|
||||
import { ManualAnnotationResponse } from '../model/manual-annotation-response';
|
||||
import { FileDataModel } from '../model/file-data.model';
|
||||
import { AnnotationFilter } from '../../../utils/types';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-preview-screen',
|
||||
@ -44,14 +45,12 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
@ViewChild('annotations') private _annotationsElement: ElementRef;
|
||||
@ViewChild('quickNavigation') private _quickNavigationElement: ElementRef;
|
||||
|
||||
public annotatedFileData: Blob;
|
||||
public redactedFileData: Blob;
|
||||
public fileData: FileDataModel;
|
||||
public fileId: string;
|
||||
public annotations: AnnotationWrapper[] = [];
|
||||
public displayedAnnotations: { [key: number]: { annotations: AnnotationWrapper[] } } = {};
|
||||
public selectedAnnotation: AnnotationWrapper;
|
||||
public filters: AnnotationFilters;
|
||||
public expandedFilters: AnnotationFilters = { hint: false };
|
||||
public filters: AnnotationFilter[];
|
||||
public pagesPanelActive = true;
|
||||
public viewReady = false;
|
||||
|
||||
@ -97,7 +96,7 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.filters = this._filtersService.getFilters(this.appStateService.dictionaryData);
|
||||
this._reloadFiles();
|
||||
this._loadFileData();
|
||||
this.appStateService.fileStatusChanged.subscribe((fileStatus) => {
|
||||
if (fileStatus.fileId === this.fileId) {
|
||||
// no more automatic reloads
|
||||
@ -106,17 +105,20 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
private _reloadFiles() {
|
||||
this._fileDownloadService
|
||||
.loadFile('ANNOTATED', this.fileId, (data) => {
|
||||
this.annotatedFileData = data;
|
||||
})
|
||||
.subscribe(() => {});
|
||||
this._fileDownloadService
|
||||
.loadFile('REDACTED', this.fileId, (data) => {
|
||||
this.redactedFileData = data;
|
||||
})
|
||||
.subscribe(() => {});
|
||||
private _loadFileData() {
|
||||
this._fileDownloadService.loadFileData(this.fileId).subscribe((fileDataModel) => {
|
||||
this.fileData = fileDataModel;
|
||||
this.annotations = fileDataModel.redactionLog.redactionLogEntry.map(
|
||||
(rde) => new AnnotationWrapper(rde, null)
|
||||
);
|
||||
this.filters = this._filtersService.getFilters(
|
||||
this.appStateService.dictionaryData,
|
||||
this.annotations
|
||||
);
|
||||
this.applyFilters();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
console.log(this.annotations);
|
||||
});
|
||||
}
|
||||
|
||||
public openFileDetailsDialog($event: MouseEvent) {
|
||||
@ -166,8 +168,8 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
return Object.keys(this.displayedAnnotations).map((key) => Number(key));
|
||||
}
|
||||
|
||||
public handleAnnotationSelected(annotation: AnnotationWrapper) {
|
||||
this.selectedAnnotation = annotation;
|
||||
public handleAnnotationSelected(annotationId: string) {
|
||||
this.selectedAnnotation = this.annotations.find((a) => a.id === annotationId);
|
||||
this.scrollToSelectedAnnotation();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
@ -272,7 +274,8 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
public rejectSuggestion($event: MouseEvent, annotation: AnnotationWrapper) {
|
||||
this.ngZone.run(() => {
|
||||
this._dialogRef = this._dialogService.rejectSuggestion($event, annotation, () => {
|
||||
this.activeViewer.annotManager.deleteAnnotation(annotation.annotation, false, true);
|
||||
// TODO DELETE ANNOTATIOn
|
||||
//this.activeViewer.annotManager.deleteAnnotation(annotation, false, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -306,16 +309,17 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
public get hasActiveFilters(): boolean {
|
||||
return AnnotationUtils.hasActiveFilters(this.filters);
|
||||
// return AnnotationUtils.hasActiveFilters(this.filters);
|
||||
return true;
|
||||
}
|
||||
|
||||
public hasSubsections(filter: AnnotationFilters | boolean) {
|
||||
return AnnotationUtils.hasSubsections(filter);
|
||||
public hasSubsections(filter: AnnotationFilter[]) {
|
||||
// return AnnotationUtils.hasSubsections(filter);
|
||||
}
|
||||
|
||||
public setExpanded(key: string, value: boolean, $event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
this.expandedFilters[key] = value;
|
||||
//this.expandedFilters[key] = value;
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
@ -460,18 +464,6 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
handleAnnotationsAdded(annotations: AnnotationWrapper[]) {
|
||||
// replacing array causes UI flicker
|
||||
this.annotations.splice(0, this.annotations.length);
|
||||
this.annotations.push(...annotations);
|
||||
this.filters = this._filtersService.getFilters(
|
||||
this.appStateService.dictionaryData,
|
||||
this.annotations
|
||||
);
|
||||
this.applyFilters();
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
private _computeId(response: ManualAnnotationResponse) {
|
||||
// if owner or not set the request prefix in the id
|
||||
const prefix = this.appStateService.isActiveProjectOwner ? '' : 'request:add:';
|
||||
@ -498,4 +490,16 @@ export class FilePreviewScreenComponent implements OnInit {
|
||||
const rgbColor = hexToRgb(color);
|
||||
return new this.activeViewer.Annotations.Color(rgbColor.r, rgbColor.g, rgbColor.b);
|
||||
}
|
||||
|
||||
filterClicked($event: MouseEvent, key: string, subkey?: string) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
if (subkey) {
|
||||
this.filters[key][subkey] = !this.filters[key][subkey];
|
||||
} else {
|
||||
//this.setAllFilters(this.filters[key],)
|
||||
this.filters[key] = !this.filters[key];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { Annotations } from '@pdftron/webviewer';
|
||||
import { ManualRedactionEntry } from '@redaction/red-ui-http';
|
||||
import {
|
||||
ManualRedactionEntry,
|
||||
ManualRedactions,
|
||||
Point,
|
||||
RedactionLogEntry
|
||||
} from '@redaction/red-ui-http';
|
||||
|
||||
export class AnnotationWrapper {
|
||||
superType: 'request' | 'redaction' | 'hint' | 'ignore';
|
||||
@ -8,25 +12,22 @@ export class AnnotationWrapper {
|
||||
comments: string[] = [];
|
||||
uuid: string;
|
||||
manualRedactionEntry: ManualRedactionEntry;
|
||||
firstTopLeftPoint: Point;
|
||||
id: string;
|
||||
content: string;
|
||||
pageNumber;
|
||||
|
||||
constructor(
|
||||
public annotation: Annotations.Annotation,
|
||||
manualRedactionEntries?: ManualRedactionEntry[]
|
||||
) {
|
||||
this.comments = annotation['Mi'] ? annotation['Mi'].map((m) => m.eC) : [];
|
||||
const parts = annotation.Id.split(':');
|
||||
// first part is always the superType
|
||||
this.superType = parts[0].toLowerCase() as any;
|
||||
if (this.superType === 'redaction' || this.superType === 'hint') {
|
||||
this.dictionary = parts[1];
|
||||
}
|
||||
if (this.superType === 'request') {
|
||||
this.dictionary = parts[2] !== 'only_here' ? parts[2] : undefined;
|
||||
}
|
||||
this.uuid = parts[parts.length - 1];
|
||||
this.manualRedactionEntry = manualRedactionEntries
|
||||
? manualRedactionEntries.find((e) => e.id === this.uuid)
|
||||
: undefined;
|
||||
constructor(public redactionLogEntry: RedactionLogEntry, manualRedactions?: ManualRedactions) {
|
||||
this.superType = redactionLogEntry.redacted
|
||||
? 'redaction'
|
||||
: redactionLogEntry.hint
|
||||
? 'hint'
|
||||
: 'ignore';
|
||||
this.dictionary = redactionLogEntry.type;
|
||||
this.firstTopLeftPoint = redactionLogEntry.positions[0]?.topLeft;
|
||||
this.pageNumber = redactionLogEntry.positions[0]?.page;
|
||||
this.id = redactionLogEntry.id;
|
||||
this.content = redactionLogEntry.reason;
|
||||
}
|
||||
|
||||
get manualRedactionOwner() {
|
||||
@ -34,22 +35,16 @@ export class AnnotationWrapper {
|
||||
}
|
||||
|
||||
get x() {
|
||||
return this.annotation.getX();
|
||||
return this.firstTopLeftPoint.x;
|
||||
}
|
||||
|
||||
get y() {
|
||||
return this.annotation.getY();
|
||||
return this.firstTopLeftPoint.y;
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this.annotation.Id;
|
||||
}
|
||||
|
||||
get content() {
|
||||
return this.annotation.getContents();
|
||||
}
|
||||
|
||||
get pageNumber() {
|
||||
return this.annotation.PageNumber;
|
||||
}
|
||||
// private String createAnnotationContent(Entity entity) {
|
||||
//
|
||||
// return "\nRule " + entity.getMatchedRule() + " matched\n\n" + entity.getRedactionReason() + "\n\nLegal basis:" + entity
|
||||
// .getLegalBasis() + "\n\nIn section: \"" + entity.getHeadline() + "\"";
|
||||
// }
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import { RedactionLog } from '@redaction/red-ui-http';
|
||||
|
||||
export class FileDataModel {
|
||||
constructor(
|
||||
public annotatedFileData: Blob,
|
||||
public redactedFileData: Blob,
|
||||
public redactionLog: RedactionLog
|
||||
) {}
|
||||
}
|
||||
@ -46,14 +46,12 @@ export interface ViewerState {
|
||||
})
|
||||
export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
private _viewerState: ViewerState = null; // no initial state
|
||||
private _annotationEventDebouncer = new Subject<Annotations.Annotation[]>();
|
||||
|
||||
@Input() fileData: Blob;
|
||||
@Input() fileStatus: FileStatus;
|
||||
|
||||
@Output() fileReady = new EventEmitter();
|
||||
@Output() annotationsAdded = new EventEmitter<AnnotationWrapper[]>();
|
||||
@Output() annotationSelected = new EventEmitter<AnnotationWrapper>();
|
||||
@Output() annotationSelected = new EventEmitter<string>();
|
||||
@Output() manualAnnotationRequested = new EventEmitter<ManualRedactionEntryWrapper>();
|
||||
@Output() pageChanged = new EventEmitter<number>();
|
||||
@Output() keyUp = new EventEmitter<KeyboardEvent>();
|
||||
@ -64,7 +62,6 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
|
||||
@ViewChild('viewer', { static: true }) viewer: ElementRef;
|
||||
instance: WebViewerInstance;
|
||||
private _manualAnnotations: ManualRedactions;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
@ -77,26 +74,6 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
|
||||
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(
|
||||
AnnotationUtils.filterAndConvertAnnotations(
|
||||
this.instance.annotManager.getAnnotationsList(),
|
||||
this._manualAnnotationService.manualEntries
|
||||
)
|
||||
);
|
||||
// nasty double-emit fix, the annotationList is not updated when the event is fired
|
||||
setTimeout(
|
||||
() =>
|
||||
this.annotationsAdded.emit(
|
||||
AnnotationUtils.filterAndConvertAnnotations(
|
||||
this.instance.annotManager.getAnnotationsList(),
|
||||
this._manualAnnotationService.manualEntries
|
||||
)
|
||||
),
|
||||
200
|
||||
);
|
||||
});
|
||||
this._manualAnnotationService.loadManualAnnotationsForActiveFile().subscribe(() => {});
|
||||
}
|
||||
|
||||
@ -124,15 +101,11 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
this._disableElements();
|
||||
this._configureTextPopup();
|
||||
this._configureHeader();
|
||||
instance.annotManager.on('annotationChanged', (annotations, action) => {
|
||||
this._annotationEventDebouncer.next(annotations);
|
||||
});
|
||||
|
||||
instance.annotManager.on('annotationSelected', (annotationList, action) => {
|
||||
if (action === 'deselected') {
|
||||
this.annotationSelected.emit(null);
|
||||
} else {
|
||||
this.annotationSelected.emit(new AnnotationWrapper(annotationList[0]));
|
||||
this.annotationSelected.emit(annotationList[0].Id);
|
||||
}
|
||||
});
|
||||
|
||||
@ -273,10 +246,10 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
|
||||
|
||||
public selectAnnotation(annotation: AnnotationWrapper) {
|
||||
this.instance.annotManager.deselectAllAnnotations();
|
||||
if (annotation?.annotation) {
|
||||
this.instance.annotManager.selectAnnotation(annotation.annotation);
|
||||
this.navigateToPage(annotation.pageNumber);
|
||||
}
|
||||
const annotationFromViewer = this.instance.annotManager.getAnnotationById(annotation.id);
|
||||
console.log(annotationFromViewer);
|
||||
this.instance.annotManager.selectAnnotation(annotationFromViewer);
|
||||
this.navigateToPage(annotation.pageNumber);
|
||||
}
|
||||
|
||||
public navigateToPage(pageNumber: number) {
|
||||
|
||||
@ -1,14 +1,28 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { FileUploadControllerService } from '@redaction/red-ui-http';
|
||||
import { forkJoin, Observable, of } from 'rxjs';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { FileUploadControllerService, RedactionLogControllerService } from '@redaction/red-ui-http';
|
||||
import { FileType } from '../model/file-type';
|
||||
import { FileDataModel } from '../model/file-data.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FileDownloadService {
|
||||
constructor(private readonly _fileUploadControllerService: FileUploadControllerService) {}
|
||||
constructor(
|
||||
private readonly _fileUploadControllerService: FileUploadControllerService,
|
||||
private readonly _redactionLogControllerService: RedactionLogControllerService
|
||||
) {}
|
||||
|
||||
public loadFileData(fileId: string): Observable<FileDataModel> {
|
||||
const annotatedObs = this.loadFile('ANNOTATED', fileId);
|
||||
const redactedObs = this.loadFile('REDACTED', fileId);
|
||||
const reactionLogObs = this._redactionLogControllerService.getRedactionLog(fileId);
|
||||
|
||||
return forkJoin([annotatedObs, redactedObs, reactionLogObs]).pipe(
|
||||
map((data) => new FileDataModel(...data))
|
||||
);
|
||||
}
|
||||
|
||||
loadFile(
|
||||
fileType: FileType | string,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AnnotationFilters } from '../../../utils/types';
|
||||
import { AnnotationFilter } from '../../../utils/types';
|
||||
import { TypeValue } from '@redaction/red-ui-http';
|
||||
import { AnnotationWrapper } from '../model/annotation.wrapper';
|
||||
|
||||
@ -9,41 +9,33 @@ import { AnnotationWrapper } from '../model/annotation.wrapper';
|
||||
export class FiltersService {
|
||||
constructor() {}
|
||||
|
||||
private _filters: AnnotationFilters = {
|
||||
hint: {},
|
||||
redaction: {},
|
||||
request: false,
|
||||
ignore: false
|
||||
};
|
||||
|
||||
public getFilters(
|
||||
dictionaryData: { [key: string]: TypeValue },
|
||||
annotations?: AnnotationWrapper[]
|
||||
): AnnotationFilters {
|
||||
): AnnotationFilter[] {
|
||||
const availableAnnotationTypes: Set<string> = new Set<string>();
|
||||
annotations?.forEach((a) => {
|
||||
availableAnnotationTypes.add(a.superType);
|
||||
availableAnnotationTypes.add(a.dictionary);
|
||||
});
|
||||
const filtersCopy = JSON.parse(JSON.stringify(this._filters));
|
||||
const filters: AnnotationFilter[] = [];
|
||||
for (const key of Object.keys(dictionaryData)) {
|
||||
if (availableAnnotationTypes.has(key)) {
|
||||
const typeValue = dictionaryData[key];
|
||||
if (typeValue.hint === true) {
|
||||
filtersCopy.hint[key] = typeValue.defaultFilter;
|
||||
}
|
||||
if (typeValue.hint === false) {
|
||||
filtersCopy.redaction[key] = typeValue.defaultFilter;
|
||||
}
|
||||
const filter: AnnotationFilter = this._addOrGetGroup(
|
||||
filters,
|
||||
typeValue.hint ? 'hint' : 'redaction'
|
||||
);
|
||||
filter.filters.push({
|
||||
key: key
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const key of Object.keys(filtersCopy)) {
|
||||
if (!availableAnnotationTypes.has(key)) {
|
||||
delete filtersCopy[key];
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
return filtersCopy;
|
||||
private _addOrGetGroup(filters: AnnotationFilter[], name: string) {
|
||||
return { key: name, filters: [] };
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,56 +1,53 @@
|
||||
import { Annotations } from '@pdftron/webviewer';
|
||||
import { AnnotationFilters } from './types';
|
||||
import { AnnotationWrapper } from '../screens/file/model/annotation.wrapper';
|
||||
import { ManualRedactionEntry } from '@redaction/red-ui-http';
|
||||
import { AnnotationFilter } from './types';
|
||||
|
||||
export class AnnotationUtils {
|
||||
public static sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] {
|
||||
return annotations.sort((ann1, ann2) => {
|
||||
if (ann1.pageNumber === ann2.pageNumber) {
|
||||
if (ann1.x === ann2.y) {
|
||||
if (ann1.x === ann2.y) {
|
||||
return 0;
|
||||
}
|
||||
return ann1.x < ann2.x ? -1 : 1;
|
||||
if (ann1.y === ann2.y) {
|
||||
return ann1.x < ann2.x ? 1 : -1;
|
||||
} else {
|
||||
return ann1.y < ann2.y ? 1 : -1;
|
||||
}
|
||||
return ann1.y < ann2.y ? -1 : 1;
|
||||
}
|
||||
return ann1.pageNumber < ann2.pageNumber ? -1 : 1;
|
||||
});
|
||||
}
|
||||
|
||||
public static hasSubsections(filter: AnnotationFilters | boolean) {
|
||||
public static hasSubsections(filter: AnnotationFilter | boolean) {
|
||||
return filter instanceof Object;
|
||||
}
|
||||
|
||||
public static checkedSubkeys(filter: AnnotationFilters | boolean) {
|
||||
public static checkedSubkeys(filter: AnnotationFilter | boolean) {
|
||||
return Object.keys(filter).filter((subkey) => this.isChecked(filter[subkey])).length;
|
||||
}
|
||||
|
||||
// Only some of the sub-items are selected
|
||||
public static isIndeterminate(filter: AnnotationFilters | boolean): boolean {
|
||||
public static isIndeterminate(filter: AnnotationFilter | boolean): boolean {
|
||||
return this.hasSubsections(filter)
|
||||
? AnnotationUtils.checkedSubkeys(filter) > 0 && !this.isChecked(filter)
|
||||
: false;
|
||||
}
|
||||
|
||||
// All sub-items are selected
|
||||
public static isChecked(filter: AnnotationFilters | boolean): boolean {
|
||||
public static isChecked(filter: AnnotationFilter | boolean): boolean {
|
||||
return this.hasSubsections(filter)
|
||||
? AnnotationUtils.checkedSubkeys(filter) === Object.keys(filter).length
|
||||
: (filter as boolean);
|
||||
}
|
||||
|
||||
public static hasActiveFilters(filter: AnnotationFilters): boolean {
|
||||
public static hasActiveFilters(filter: AnnotationFilter[]): boolean {
|
||||
const activeFilters = Object.keys(filter).filter((key) => {
|
||||
return this.isChecked(filter[key]) || this.isIndeterminate(filter[key]);
|
||||
});
|
||||
return activeFilters.length > 0;
|
||||
// return activeFilters.length > 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static parseAnnotations(
|
||||
annotations: AnnotationWrapper[],
|
||||
filters: AnnotationFilters
|
||||
filters: AnnotationFilter[]
|
||||
): { [key: number]: { annotations: AnnotationWrapper[] } } {
|
||||
const obj = {};
|
||||
|
||||
@ -86,19 +83,8 @@ export class AnnotationUtils {
|
||||
obj[page].annotations = this.sortAnnotations(obj[page].annotations);
|
||||
});
|
||||
|
||||
console.log(obj);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static filterAndConvertAnnotations(
|
||||
annotations: Annotations.Annotation[],
|
||||
manualRedactions: ManualRedactionEntry[]
|
||||
) {
|
||||
const convertedAnnotations: AnnotationWrapper[] = [];
|
||||
for (const annotation of annotations) {
|
||||
if (annotation.Id.indexOf(':') > 0) {
|
||||
convertedAnnotations.push(new AnnotationWrapper(annotation, manualRedactions));
|
||||
}
|
||||
}
|
||||
return convertedAnnotations;
|
||||
}
|
||||
}
|
||||
|
||||
7
apps/red-ui/src/app/utils/types.d.ts
vendored
7
apps/red-ui/src/app/utils/types.d.ts
vendored
@ -8,6 +8,9 @@ export class SortingOption {
|
||||
column: string;
|
||||
}
|
||||
|
||||
export class AnnotationFilters {
|
||||
[key: string]: boolean | {};
|
||||
export interface AnnotationFilter {
|
||||
key: string;
|
||||
checked?: boolean;
|
||||
indeterminate?: boolean;
|
||||
filters?: AnnotationFilter[];
|
||||
}
|
||||
|
||||
@ -44,6 +44,9 @@ server {
|
||||
location /status {
|
||||
proxy_pass $API_URL;
|
||||
}
|
||||
location /redactionLog {
|
||||
proxy_pass $API_URL;
|
||||
}
|
||||
client_max_body_size 0;
|
||||
gzip_min_length 1000;
|
||||
gzip on;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user