wip: draw only changed annotations
This commit is contained in:
parent
c8a2e0b580
commit
7399f44881
@ -10,8 +10,11 @@ import {
|
||||
SuperType,
|
||||
SuperTypes,
|
||||
} from '@models/file/super-types';
|
||||
import { List } from '@iqser/common-ui';
|
||||
|
||||
export class AnnotationWrapper implements Record<string, unknown> {
|
||||
[x: string]: unknown;
|
||||
|
||||
export class AnnotationWrapper {
|
||||
superType: SuperType;
|
||||
|
||||
typeValue: string;
|
||||
@ -33,10 +36,10 @@ export class AnnotationWrapper {
|
||||
recommendationType: string;
|
||||
legalBasisValue: string;
|
||||
legalBasisChangeValue?: string;
|
||||
resizing?: boolean;
|
||||
resizing = false;
|
||||
rectangle?: boolean;
|
||||
section?: string;
|
||||
reference: Array<string>;
|
||||
reference: List;
|
||||
|
||||
imported?: boolean;
|
||||
image?: boolean;
|
||||
@ -58,7 +61,6 @@ export class AnnotationWrapper {
|
||||
hasBeenForcedHint: boolean;
|
||||
hasBeenForcedRedaction: boolean;
|
||||
hasBeenRemovedByManualOverride: boolean;
|
||||
redactionLogEntry: any;
|
||||
|
||||
get isChangeLogRemoved() {
|
||||
return this.changeLogType === 'REMOVED';
|
||||
@ -287,7 +289,6 @@ export class AnnotationWrapper {
|
||||
this._handleRecommendations(annotationWrapper, redactionLogEntry);
|
||||
annotationWrapper.typeLabel = annotationTypesTranslations[annotationWrapper.superType];
|
||||
|
||||
annotationWrapper.redactionLogEntry = redactionLogEntry;
|
||||
return annotationWrapper;
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { ViewModeService } from '../../services/view-mode.service';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { TextHighlightsGroup } from '@red/domain';
|
||||
import { FilePreviewDialogService } from '../../services/file-preview-dialog.service';
|
||||
import { PdfViewer } from '../../services/pdf-viewer.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-annotations-list',
|
||||
@ -23,7 +23,6 @@ export class AnnotationsListComponent implements OnChanges {
|
||||
|
||||
@Output() readonly pagesPanelActive = new EventEmitter<boolean>();
|
||||
@Output() readonly selectAnnotations = new EventEmitter<AnnotationWrapper[]>();
|
||||
@Output() readonly deselectAnnotations = new EventEmitter<AnnotationWrapper[]>();
|
||||
|
||||
highlightGroups$ = new BehaviorSubject<TextHighlightsGroup[]>([]);
|
||||
|
||||
@ -33,7 +32,7 @@ export class AnnotationsListComponent implements OnChanges {
|
||||
private readonly _filterService: FilterService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _viewModeService: ViewModeService,
|
||||
private readonly _dialogService: FilePreviewDialogService,
|
||||
private readonly _pdf: PdfViewer,
|
||||
) {}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
@ -58,7 +57,7 @@ export class AnnotationsListComponent implements OnChanges {
|
||||
this.pagesPanelActive.emit(false);
|
||||
|
||||
if (this.isSelected(annotation.annotationId)) {
|
||||
this.deselectAnnotations.emit([annotation]);
|
||||
this._pdf.deselectAnnotations([annotation]);
|
||||
} else {
|
||||
const canMultiSelect = this.multiSelectService.isEnabled;
|
||||
if (canMultiSelect && ($event?.ctrlKey || $event?.metaKey) && this.selectedAnnotations.length > 0) {
|
||||
|
||||
@ -209,7 +209,6 @@
|
||||
</ng-container>
|
||||
|
||||
<redaction-annotations-list
|
||||
(deselectAnnotations)="deselectAnnotations.emit($event)"
|
||||
(pagesPanelActive)="pagesPanelActive = $event"
|
||||
(selectAnnotations)="selectAnnotations.emit($event)"
|
||||
[activeViewerPage]="activeViewerPage"
|
||||
|
||||
@ -35,6 +35,7 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi
|
||||
import { ViewModeService } from '../../services/view-mode.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FileDataService } from '../../services/file-data.service';
|
||||
import { PdfViewer } from '../../services/pdf-viewer.service';
|
||||
|
||||
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
|
||||
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
||||
@ -56,7 +57,6 @@ export class FileWorkloadComponent {
|
||||
@Input() file!: File;
|
||||
@Input() annotationActionsTemplate: TemplateRef<unknown>;
|
||||
@Output() readonly selectAnnotations = new EventEmitter<AnnotationWrapper[]>();
|
||||
@Output() readonly deselectAnnotations = new EventEmitter<AnnotationWrapper[]>();
|
||||
@Output() readonly selectPage = new EventEmitter<number>();
|
||||
@Output() readonly annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||
displayedPages: number[] = [];
|
||||
@ -78,6 +78,7 @@ export class FileWorkloadComponent {
|
||||
readonly excludedPagesService: ExcludedPagesService,
|
||||
readonly fileDataService: FileDataService,
|
||||
private readonly _viewModeService: ViewModeService,
|
||||
private readonly _pdf: PdfViewer,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _annotationProcessingService: AnnotationProcessingService,
|
||||
) {
|
||||
@ -170,7 +171,7 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
|
||||
deselectAllOnActivePage(): void {
|
||||
this.deselectAnnotations.emit(this.activeAnnotations);
|
||||
this._pdf.deselectAnnotations(this.activeAnnotations);
|
||||
}
|
||||
|
||||
@HostListener('window:keyup', ['$event'])
|
||||
|
||||
@ -66,7 +66,6 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
@Output() readonly manualAnnotationRequested = new EventEmitter<ManualRedactionEntryWrapper>();
|
||||
@Output() readonly pageChanged = new EventEmitter<number>();
|
||||
@Output() readonly keyUp = new EventEmitter<KeyboardEvent>();
|
||||
@Output() readonly viewerReady = new EventEmitter<WebViewerInstance>();
|
||||
@Output() readonly annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||
@ViewChild('viewer', { static: true }) viewer: ElementRef;
|
||||
@ViewChild('compareFileInput', { static: true }) compareFileInput: ElementRef;
|
||||
@ -238,7 +237,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
const visibleAnnotations = await this._fileDataService.visibleAnnotations;
|
||||
this.pdf.deselectAnnotations(visibleAnnotations.filter(wrapper => !nextAnnotations.find(ann => ann.Id === wrapper.id)));
|
||||
}
|
||||
this.#configureAnnotationSpecificActions(annotations);
|
||||
await this.#configureAnnotationSpecificActions(annotations);
|
||||
this._toggleRectangleAnnotationAction(annotations.length === 1 && annotations[0].ReadOnly);
|
||||
});
|
||||
|
||||
@ -694,7 +693,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
private _setReadyAndInitialState(): void {
|
||||
this._ngZone.run(() => {
|
||||
this.viewerReady.emit(this.instance);
|
||||
this.pdf.documentLoaded$.next(true);
|
||||
const routePageNumber: number = this._activatedRoute.snapshot.queryParams.page;
|
||||
this.pageChanged.emit(routePageNumber || 1);
|
||||
this._setInitialDisplayMode();
|
||||
|
||||
@ -63,11 +63,10 @@
|
||||
<div class="content-container">
|
||||
<redaction-pdf-viewer
|
||||
(annotationSelected)="handleAnnotationSelected($event)"
|
||||
(annotationsChanged)="annotationsChangedByReviewAction($event)"
|
||||
(annotationsChanged)="annotationsChangedByReviewAction()"
|
||||
(keyUp)="handleKeyEvent($event); handleArrowEvent($event)"
|
||||
(manualAnnotationRequested)="openManualAnnotationDialog($event)"
|
||||
(pageChanged)="viewerPageChanged($event)"
|
||||
(viewerReady)="viewerReady()"
|
||||
*ngIf="displayPdfViewer"
|
||||
[canPerformActions]="canPerformAnnotationActions$ | async"
|
||||
[class.hidden]="!ready"
|
||||
@ -87,8 +86,7 @@
|
||||
|
||||
<redaction-file-workload
|
||||
#fileWorkloadComponent
|
||||
(annotationsChanged)="annotationsChangedByReviewAction($event)"
|
||||
(deselectAnnotations)="deselectAnnotations($event)"
|
||||
(annotationsChanged)="annotationsChangedByReviewAction()"
|
||||
(selectAnnotations)="selectAnnotations($event)"
|
||||
(selectPage)="selectPage($event)"
|
||||
*ngIf="!file.excluded"
|
||||
@ -105,7 +103,7 @@
|
||||
|
||||
<ng-template #annotationActionsTemplate let-annotation="annotation">
|
||||
<redaction-annotation-actions
|
||||
(annotationsChanged)="annotationsChangedByReviewAction($event)"
|
||||
(annotationsChanged)="annotationsChangedByReviewAction()"
|
||||
[annotations]="[annotation]"
|
||||
[canPerformAnnotationActions]="canPerformAnnotationActions$ | async"
|
||||
></redaction-annotation-actions>
|
||||
|
||||
@ -18,19 +18,18 @@ import {
|
||||
import { MatDialogRef, MatDialogState } from '@angular/material/dialog';
|
||||
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { ManualAnnotationResponse } from '@models/file/manual-annotation-response';
|
||||
import { AnnotationDrawService } from './services/annotation-draw.service';
|
||||
import { AnnotationProcessingService } from '../dossier/services/annotation-processing.service';
|
||||
import { File, ViewMode } from '@red/domain';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { combineLatest, firstValueFrom, Observable, of, timer } from 'rxjs';
|
||||
import { combineLatest, firstValueFrom, Observable, of, pairwise, timer } from 'rxjs';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { clearStamps, download, handleFilterDelta, stampPDFPage } from '../../utils';
|
||||
import { FileWorkloadComponent } from './components/file-workload/file-workload.component';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { catchError, filter, map, startWith, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { WatermarkService } from '@shared/services/watermark.service';
|
||||
import { ExcludedPagesService } from './services/excluded-pages.service';
|
||||
@ -69,7 +68,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
readonly canPerformAnnotationActions$: Observable<boolean>;
|
||||
readonly fileId = this.stateService.fileId;
|
||||
readonly dossierId = this.stateService.dossierId;
|
||||
readonly file$ = this.stateService.file$.pipe(tap(file => this._fileUpdated(file)));
|
||||
readonly file$ = this.stateService.file$.pipe(tap(file => this._loadFileData(file)));
|
||||
ready = false;
|
||||
private _lastPage: string;
|
||||
|
||||
@ -112,6 +111,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
readonly documentInfoService: DocumentInfoService,
|
||||
) {
|
||||
super();
|
||||
this.bla();
|
||||
this.canPerformAnnotationActions$ = this._canPerformAnnotationActions$;
|
||||
|
||||
document.documentElement.addEventListener('fullscreenchange', () => {
|
||||
@ -283,10 +283,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
}
|
||||
|
||||
deselectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
this._pdf.deselectAnnotations(annotations);
|
||||
}
|
||||
|
||||
selectPage(pageNumber: number) {
|
||||
this._pdf.navigateToPage(pageNumber);
|
||||
this._workloadComponent?.scrollAnnotationsToPage(pageNumber, 'always');
|
||||
@ -299,23 +295,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
'manualAnnotation',
|
||||
null,
|
||||
{ manualRedactionEntryWrapper, dossierId: this.dossierId },
|
||||
async (entryWrapper: ManualRedactionEntryWrapper) => {
|
||||
const addAnnotation$ = this._manualAnnotationService
|
||||
.addAnnotation(entryWrapper.manualRedactionEntry, this.dossierId, this.fileId)
|
||||
.pipe(catchError(() => of(undefined)));
|
||||
const addAnnotationResponse = await firstValueFrom(addAnnotation$);
|
||||
const response = new ManualAnnotationResponse(entryWrapper, addAnnotationResponse);
|
||||
|
||||
if (response?.annotationId) {
|
||||
this._pdf.deleteAnnotations([response.manualRedactionEntryWrapper.rectId]);
|
||||
const distinctPages = manualRedactionEntryWrapper.manualRedactionEntry.positions
|
||||
.map(p => p.page)
|
||||
.filter((item, pos, self) => self.indexOf(item) === pos);
|
||||
for (const page of distinctPages) {
|
||||
await this._reloadAnnotationsForPage(page);
|
||||
}
|
||||
await this.updateViewMode();
|
||||
}
|
||||
async ({ manualRedactionEntry }: ManualRedactionEntryWrapper) => {
|
||||
const addAnnotation$ = this._manualAnnotationService.addAnnotation(manualRedactionEntry, this.dossierId, this.fileId);
|
||||
await firstValueFrom(addAnnotation$.pipe(catchError(() => of(undefined))));
|
||||
await this._fileDataService.load(await this.stateService.file);
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -384,12 +367,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
@Debounce()
|
||||
async viewerReady() {
|
||||
viewerReady() {
|
||||
this.ready = true;
|
||||
this._pdf.ready = true;
|
||||
|
||||
await this._reloadAnnotations();
|
||||
this._setExcludedPageStyles();
|
||||
|
||||
this._pdf.documentViewer.addEventListener('pageComplete', () => {
|
||||
@ -412,13 +393,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
async annotationsChangedByReviewAction(annotation?: AnnotationWrapper) {
|
||||
async annotationsChangedByReviewAction() {
|
||||
this.multiSelectService.deactivate();
|
||||
const file = await this.stateService.file;
|
||||
const fileReloaded = await firstValueFrom(this._filesService.reload(this.dossierId, file));
|
||||
if (!fileReloaded) {
|
||||
await this._reloadAnnotationsForPage(annotation?.pageNumber ?? this.activeViewerPage);
|
||||
}
|
||||
await firstValueFrom(this._filesService.reload(this.dossierId, file));
|
||||
}
|
||||
|
||||
closeFullScreen() {
|
||||
@ -443,6 +421,69 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
download(await firstValueFrom(originalFile), file.filename);
|
||||
}
|
||||
|
||||
bla() {
|
||||
const documentLoaded$ = this._pdf.documentLoaded$.pipe(tap(() => this.viewerReady()));
|
||||
let start;
|
||||
combineLatest([documentLoaded$, this._fileDataService.annotations$])
|
||||
.pipe(
|
||||
withLatestFrom(this.stateService.file$),
|
||||
filter(([, file]) => !file.isProcessing),
|
||||
tap(() => (start = new Date().getTime())),
|
||||
map(([[, annotations]]) => annotations),
|
||||
startWith([] as AnnotationWrapper[]),
|
||||
pairwise(),
|
||||
tap(annotations => this.deleteAnnotations(...annotations)),
|
||||
switchMap(annotations => this.drawChangedAnnotations(...annotations)),
|
||||
tap(() => console.log(`%c [ANNOTATIONS] Processing time: ${new Date().getTime() - start}`, 'color: aqua')),
|
||||
tap(() => this.updateViewMode()),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
deleteAnnotations(oldAnnotations: AnnotationWrapper[], newAnnotations: AnnotationWrapper[]) {
|
||||
const annotationsToDelete = oldAnnotations.filter(
|
||||
oldAnnotation => !newAnnotations.some(newAnnotation => newAnnotation.id === oldAnnotation.id),
|
||||
);
|
||||
|
||||
if (annotationsToDelete.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('%c [ANNOTATIONS] To delete: ', 'color: aqua', annotationsToDelete);
|
||||
this._pdf.deleteAnnotations(annotationsToDelete.map(annotation => annotation.id));
|
||||
}
|
||||
|
||||
drawChangedAnnotations(oldAnnotations: AnnotationWrapper[], newAnnotations: AnnotationWrapper[]) {
|
||||
const annotationsToDraw = newAnnotations.filter(newAnnotation => {
|
||||
const oldAnnotation = oldAnnotations.find(annotation => annotation.id === newAnnotation.id);
|
||||
if (!oldAnnotation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const changed = JSON.stringify(oldAnnotation) !== JSON.stringify(newAnnotation);
|
||||
if (changed && this.userPreferenceService.areDevFeaturesEnabled) {
|
||||
import('@iqser/common-ui').then(commonUi => {
|
||||
console.log('%c [ANNOTATIONS] Changed annotation: ', 'color: aqua', {
|
||||
value: oldAnnotation.value,
|
||||
before: commonUi.deepDiffObj(newAnnotation, oldAnnotation),
|
||||
after: commonUi.deepDiffObj(oldAnnotation, newAnnotation),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return changed;
|
||||
});
|
||||
|
||||
if (annotationsToDraw.length === 0) {
|
||||
return firstValueFrom(of({}));
|
||||
}
|
||||
|
||||
console.log('%c [ANNOTATIONS] To draw: ', 'color: aqua', annotationsToDraw);
|
||||
const annotationsToDrawIds = annotationsToDraw.map(a => a.annotationId);
|
||||
this._pdf.deleteAnnotations(annotationsToDrawIds);
|
||||
return this._cleanupAndRedrawAnnotations(annotation => annotationsToDrawIds.includes(annotation.annotationId));
|
||||
}
|
||||
|
||||
async #deactivateMultiSelect() {
|
||||
this.multiSelectService.deactivate();
|
||||
this._pdf.deselectAllAnnotations();
|
||||
@ -524,11 +565,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
}
|
||||
|
||||
private async _fileUpdated(file: File): Promise<void> {
|
||||
await this._loadFileData(file);
|
||||
await this._reloadAnnotations();
|
||||
}
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
this.addActiveScreenSubscription = timer(0, 5000)
|
||||
.pipe(
|
||||
@ -583,31 +619,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._workloadComponent?.scrollAnnotations();
|
||||
}
|
||||
|
||||
private async _reloadAnnotations() {
|
||||
if (!this._fileDataService.shouldUpdateAnnotations) {
|
||||
console.log('skip reloading annotations');
|
||||
return;
|
||||
}
|
||||
this._pdf.deleteAnnotations();
|
||||
await this._cleanupAndRedrawAnnotations();
|
||||
await this.updateViewMode();
|
||||
}
|
||||
|
||||
private async _reloadAnnotationsForPage(page: number) {
|
||||
const file = await this.stateService.file;
|
||||
// if this action triggered a re-processing,
|
||||
// we don't want to redraw for this page since they will get redrawn as soon as processing ends;
|
||||
if (file.isProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPageAnnotations = (await this._fileDataService.visibleAnnotations).filter(a => a.pageNumber === page);
|
||||
await this._fileDataService.loadRedactionLog();
|
||||
|
||||
this._pdf.deleteAnnotations(currentPageAnnotations.map(a => a.id));
|
||||
await this._cleanupAndRedrawAnnotations(annotation => annotation.pageNumber === page);
|
||||
}
|
||||
|
||||
private async _cleanupAndRedrawAnnotations(newAnnotationsFilter?: (annotation: AnnotationWrapper) => boolean) {
|
||||
if (!this._pdf.ready) {
|
||||
return;
|
||||
@ -626,7 +637,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
await this._annotationDrawService.drawAnnotations(newAnnotations);
|
||||
console.log(`[REDACTION] Annotations redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`);
|
||||
console.log(
|
||||
`%c [ANNOTATIONS] Redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`,
|
||||
'color: aqua',
|
||||
);
|
||||
}
|
||||
|
||||
private _handleDeltaAnnotationFilters(currentFilters: NestedFilter[], newAnnotations: AnnotationWrapper[]) {
|
||||
|
||||
@ -96,8 +96,8 @@ export class AnnotationDrawService {
|
||||
await document.lock();
|
||||
|
||||
const annotations = annotationWrappers.map(annotation => this._computeAnnotation(annotation)).filter(a => !!a);
|
||||
this._pdf.instance.Core.annotationManager.addAnnotations(annotations, { imported: true });
|
||||
await this._pdf.instance.Core.annotationManager.drawAnnotationsFromList(annotations);
|
||||
this._pdf.annotationManager.addAnnotations(annotations, { imported: true });
|
||||
await this._pdf.annotationManager.drawAnnotationsFromList(annotations);
|
||||
|
||||
if (this._userPreferenceService.areDevFeaturesEnabled) {
|
||||
const { dossierId, fileId } = this._state;
|
||||
|
||||
@ -22,7 +22,7 @@ import { DictionariesMapService } from '../../../services/entity-services/dictio
|
||||
import { catchError, map, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { PermissionsService } from '../../../services/permissions.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { log, shareLast, Toaster } from '../../../../../../../libs/common-ui/src';
|
||||
import { shareLast, Toaster } from '../../../../../../../libs/common-ui/src';
|
||||
import { RedactionLogService } from '../../dossier/services/redaction-log.service';
|
||||
import { TextHighlightService } from '../../dossier/services/text-highlight.service';
|
||||
import { ViewModeService } from './view-mode.service';
|
||||
@ -41,8 +41,6 @@ export class FileDataService {
|
||||
readonly visibleAnnotations$: Observable<AnnotationWrapper[]>;
|
||||
readonly hiddenAnnotations = new Set<string>();
|
||||
|
||||
#redactionLog: IRedactionLog;
|
||||
#redactionLogHash = '';
|
||||
readonly #redactionLog$ = new BehaviorSubject<IRedactionLog>({});
|
||||
readonly #textHighlights$ = new BehaviorSubject<AnnotationWrapper[]>([]);
|
||||
|
||||
@ -66,7 +64,6 @@ export class FileDataService {
|
||||
this.annotations$.pipe(map(annotations => this.getVisibleAnnotations(annotations, viewMode))),
|
||||
),
|
||||
),
|
||||
log('visible annotations: '),
|
||||
shareLast(),
|
||||
);
|
||||
}
|
||||
@ -87,6 +84,7 @@ export class FileDataService {
|
||||
return this.#redactionLog$.pipe(
|
||||
withLatestFrom(this._state.file$),
|
||||
map(([redactionLog, file]) => this.#buildAnnotations(redactionLog, file)),
|
||||
tap(() => this.checkMissingTypes()),
|
||||
map(annotations =>
|
||||
this._userPreferenceService.areDevFeaturesEnabled ? annotations : annotations.filter(a => !a.isFalsePositive),
|
||||
),
|
||||
@ -94,30 +92,18 @@ export class FileDataService {
|
||||
);
|
||||
}
|
||||
|
||||
setRedactionLog(redactionLog: IRedactionLog) {
|
||||
this.#redactionLog = redactionLog;
|
||||
const hash = require('object-hash');
|
||||
const newRedactionLogHash = hash(redactionLog.redactionLogEntry ?? []);
|
||||
|
||||
if (newRedactionLogHash === this.#redactionLogHash) {
|
||||
this.shouldUpdateAnnotations = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.shouldUpdateAnnotations = true;
|
||||
this.#redactionLogHash = newRedactionLogHash;
|
||||
this.missingTypes.clear();
|
||||
}
|
||||
|
||||
async load(file: File) {
|
||||
this.viewedPages = await firstValueFrom(this.getViewedPagesFor(file));
|
||||
await this.loadRedactionLog();
|
||||
}
|
||||
|
||||
checkMissingTypes() {
|
||||
if (this.missingTypes.size > 0) {
|
||||
this._toaster.error(_('error.missing-types'), {
|
||||
disableTimeOut: true,
|
||||
params: { missingTypes: Array.from(this.missingTypes).join(', ') },
|
||||
});
|
||||
this.missingTypes.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,14 +123,14 @@ export class FileDataService {
|
||||
return of([] as IViewedPage[]);
|
||||
}
|
||||
|
||||
async loadRedactionLog() {
|
||||
loadRedactionLog() {
|
||||
const redactionLog$ = this._redactionLogService.getRedactionLog(this._state.dossierId, this._state.fileId).pipe(
|
||||
tap(redactionLog => redactionLog.redactionLogEntry.sort((a, b) => a.positions[0].page - b.positions[0].page)),
|
||||
catchError(() => of({})),
|
||||
tap(redactionLog => this.#redactionLog$.next(redactionLog)),
|
||||
);
|
||||
|
||||
this.setRedactionLog(await firstValueFrom(redactionLog$));
|
||||
return firstValueFrom(redactionLog$);
|
||||
}
|
||||
|
||||
getVisibleAnnotations(annotations: AnnotationWrapper[], viewMode: ViewMode) {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { translateQuads } from '../../../utils/pdf-coordinates';
|
||||
import { translateQuads } from '../../../utils';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import WebViewer, { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { ViewModeService } from './view-mode.service';
|
||||
@ -7,6 +7,7 @@ import { Inject, Injectable } from '@angular/core';
|
||||
import { BASE_HREF } from '../../../tokens';
|
||||
import { environment } from '@environments/environment';
|
||||
import { DISABLED_HOTKEYS } from '../shared/constants';
|
||||
import { Subject } from 'rxjs';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
import DocumentViewer = Core.DocumentViewer;
|
||||
import AnnotationManager = Core.AnnotationManager;
|
||||
@ -17,6 +18,7 @@ export class PdfViewer {
|
||||
instance: WebViewerInstance;
|
||||
documentViewer: DocumentViewer;
|
||||
annotationManager: AnnotationManager;
|
||||
readonly documentLoaded$ = new Subject();
|
||||
|
||||
constructor(@Inject(BASE_HREF) private readonly _baseHref: string, readonly viewModeService: ViewModeService) {}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UserService } from './user.service';
|
||||
import { Dossier, File, IComment, IDossier } from '@red/domain';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { FeaturesService } from '@services/features.service';
|
||||
import { DOSSIERS_ARCHIVE } from '@utils/constants';
|
||||
@ -10,8 +9,6 @@ import { DOSSIERS_ARCHIVE } from '@utils/constants';
|
||||
export class PermissionsService {
|
||||
constructor(
|
||||
private readonly _userService: UserService,
|
||||
private readonly _route: ActivatedRoute,
|
||||
private readonly _injector: Injector,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _featuresService: FeaturesService,
|
||||
) {}
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 8a992aa440ff24d1244e24edea3ce75fdadbebd5
|
||||
Subproject commit 3e1b124bd9439fabf1eaa67e265c212ad9cb09e7
|
||||
Loading…
x
Reference in New Issue
Block a user