remove file from fileData
This commit is contained in:
parent
7acaa9f965
commit
440063c3b3
@ -19,7 +19,6 @@ export class FileDataModel {
|
||||
allAnnotations: AnnotationWrapper[];
|
||||
readonly hasChangeLog$ = new BehaviorSubject<boolean>(false);
|
||||
readonly blob$ = new BehaviorSubject<Blob>(undefined);
|
||||
readonly file$ = new BehaviorSubject<File>(undefined);
|
||||
|
||||
constructor(
|
||||
private readonly _file: File,
|
||||
@ -29,19 +28,10 @@ export class FileDataModel {
|
||||
private _dictionaryData?: { [p: string]: Dictionary },
|
||||
private _areDevFeaturesEnabled?: boolean,
|
||||
) {
|
||||
this.file$.next(_file);
|
||||
this.blob$.next(_blob);
|
||||
this._buildAllAnnotations();
|
||||
}
|
||||
|
||||
get file(): File {
|
||||
return this.file$.value;
|
||||
}
|
||||
|
||||
set file(file: File) {
|
||||
this.file$.next(file);
|
||||
}
|
||||
|
||||
get redactionLog(): IRedactionLog {
|
||||
return this._redactionLog;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { Dossier, IManualRedactionEntry } from '@red/domain';
|
||||
import { Dossier, File, IManualRedactionEntry } from '@red/domain';
|
||||
import WebViewer, { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
@ -37,7 +37,7 @@ import { toPosition } from '../../../../utils/pdf-calculation.utils';
|
||||
import { ViewModeService } from '../../services/view-mode.service';
|
||||
import { MultiSelectService } from '../../services/multi-select.service';
|
||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||
import { filter, switchMap, tap } from 'rxjs/operators';
|
||||
import { filter, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import Tools = Core.Tools;
|
||||
import TextTool = Tools.TextTool;
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
@ -126,18 +126,19 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
switchMap(fileData => fileData.blob$),
|
||||
// Skip document reload if file content hasn't changed
|
||||
shareDistinctLast(),
|
||||
tap(() => this._loadDocument()),
|
||||
withLatestFrom(this.stateService.file$),
|
||||
tap(([blob, file]) => this._loadDocument(blob, file)),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
async ngOnChanges(changes: SimpleChanges): Promise<void> {
|
||||
if (!this.instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (changes.canPerformActions) {
|
||||
this._handleCustomActions();
|
||||
await this._handleCustomActions();
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,12 +164,13 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this._loadingService.start();
|
||||
this.utils.ready = false;
|
||||
const mergedDocument = await pdfNet.PDFDoc.create();
|
||||
const file = await this.stateService.file;
|
||||
await loadCompareDocumentWrapper(
|
||||
currentDocument,
|
||||
compareDocument,
|
||||
mergedDocument,
|
||||
this.instance,
|
||||
this.stateService.fileData.file,
|
||||
file,
|
||||
() => {
|
||||
this.viewModeService.compareMode = true;
|
||||
},
|
||||
@ -211,9 +213,10 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
const pdfNet = this.instance.Core.PDFNet;
|
||||
await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null);
|
||||
const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.stateService.fileData.blob$.value.arrayBuffer());
|
||||
this.instance.UI.loadDocument(currentDocument, {
|
||||
filename: this.stateService.fileData?.file?.filename ?? 'document.pdf',
|
||||
});
|
||||
|
||||
const filename = (await this.stateService.file).filename ?? 'document.pdf';
|
||||
this.instance.UI.loadDocument(currentDocument, { filename });
|
||||
|
||||
this.instance.UI.disableElements([dataElements.CLOSE_COMPARE_BUTTON]);
|
||||
this.instance.UI.enableElements([dataElements.COMPARE_BUTTON]);
|
||||
this.utils.navigateToPage(1);
|
||||
@ -238,7 +241,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this._setSelectionMode();
|
||||
this._configureElements();
|
||||
this.utils.disableHotkeys();
|
||||
this._configureTextPopup();
|
||||
await this._configureTextPopup();
|
||||
|
||||
this.annotationManager.addEventListener('annotationSelected', (annotations: Annotation[], action) => {
|
||||
this.annotationSelected.emit(this.annotationManager.getSelectedAnnotations().map(ann => ann.Id));
|
||||
@ -265,7 +268,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this.utils.deselectAllAnnotations();
|
||||
}
|
||||
this._ngZone.run(() => this.pageChanged.emit(pageNumber));
|
||||
this._handleCustomActions();
|
||||
return this._handleCustomActions();
|
||||
});
|
||||
|
||||
this.documentViewer.addEventListener('documentLoaded', this._setReadyAndInitialState);
|
||||
@ -288,11 +291,12 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
}
|
||||
});
|
||||
|
||||
this.documentViewer.addEventListener('textSelected', (quads, selectedText) => {
|
||||
this.documentViewer.addEventListener('textSelected', async (quads, selectedText) => {
|
||||
this._selectedText = selectedText;
|
||||
const textActions = [dataElements.ADD_DICTIONARY, dataElements.ADD_FALSE_POSITIVE];
|
||||
|
||||
if (selectedText.length > 2 && this.canPerformActions && !this.utils.isCurrentPageExcluded(this.stateService.fileData.file)) {
|
||||
const file = await this.stateService.file;
|
||||
if (selectedText.length > 2 && this.canPerformActions && !this.utils.isCurrentPageExcluded(file)) {
|
||||
this.instance.UI.enableElements(textActions);
|
||||
} else {
|
||||
this.instance.UI.disableElements(textActions);
|
||||
@ -479,14 +483,13 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
]);
|
||||
}
|
||||
|
||||
this.instance.UI.annotationPopup.add(
|
||||
this._annotationActionsService.getViewerAvailableActions(
|
||||
this.instance,
|
||||
this.stateService.fileData.file,
|
||||
annotationWrappers,
|
||||
this.annotationsChanged,
|
||||
),
|
||||
const actions = this._annotationActionsService.getViewerAvailableActions(
|
||||
this.instance,
|
||||
this.dossier,
|
||||
annotationWrappers,
|
||||
this.annotationsChanged,
|
||||
);
|
||||
this.instance.UI.annotationPopup.add(actions);
|
||||
}
|
||||
|
||||
private _configureRectangleAnnotationPopup() {
|
||||
@ -576,7 +579,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
},
|
||||
]);
|
||||
|
||||
this._handleCustomActions();
|
||||
return this._handleCustomActions();
|
||||
}
|
||||
|
||||
private _addManualRedactionOfType(type: ManualRedactionEntryType) {
|
||||
@ -586,7 +589,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this.manualAnnotationRequested.emit(new ManualRedactionEntryWrapper(selectedQuads, manualRedaction, type));
|
||||
}
|
||||
|
||||
private _handleCustomActions() {
|
||||
private async _handleCustomActions() {
|
||||
this.instance.UI.setToolMode('AnnotationEdit');
|
||||
const { ANNOTATION_POPUP, ADD_RECTANGLE, ADD_REDACTION, SHAPE_TOOL_GROUP_BUTTON } = dataElements;
|
||||
const elements = [
|
||||
@ -598,7 +601,9 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
ANNOTATION_POPUP,
|
||||
];
|
||||
|
||||
if (this.canPerformActions && !this.utils.isCurrentPageExcluded(this.stateService.fileData.file)) {
|
||||
const isCurrentPageExcluded = this.utils.isCurrentPageExcluded(await this.stateService.file);
|
||||
|
||||
if (this.canPerformActions && !isCurrentPageExcluded) {
|
||||
try {
|
||||
this.instance.UI.enableTools(['AnnotationCreateRectangle']);
|
||||
} catch (e) {
|
||||
@ -615,7 +620,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
let elementsToDisable = [...elements, ADD_RECTANGLE];
|
||||
|
||||
if (this.utils.isCurrentPageExcluded(this.stateService.fileData.file)) {
|
||||
if (isCurrentPageExcluded) {
|
||||
const allowedActionsWhenPageExcluded: string[] = [ANNOTATION_POPUP, ADD_RECTANGLE, ADD_REDACTION, SHAPE_TOOL_GROUP_BUTTON];
|
||||
elementsToDisable = elementsToDisable.filter(element => !allowedActionsWhenPageExcluded.includes(element));
|
||||
} else {
|
||||
@ -645,9 +650,10 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
return entry;
|
||||
}
|
||||
|
||||
private _loadDocument() {
|
||||
this.instance.UI.loadDocument(this.stateService.fileData.blob$.value, {
|
||||
filename: this.stateService.fileData?.file?.filename ?? 'document.pdf',
|
||||
private _loadDocument(blob: Blob, file: File) {
|
||||
console.log(blob, file);
|
||||
this.instance.UI.loadDocument(blob, {
|
||||
filename: file?.filename ?? 'document.pdf',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<ng-container *ngIf="dossier$ | async as dossier">
|
||||
<ng-container *ngIf="stateService.dossier$ | async as dossier">
|
||||
<ng-container *ngIf="stateService.file$ | async as file">
|
||||
<section [class.fullscreen]="fullScreen">
|
||||
<div class="page-header">
|
||||
|
||||
@ -22,9 +22,9 @@ 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 '../../services/annotation-processing.service';
|
||||
import { Dossier, File, ViewMode } from '@red/domain';
|
||||
import { File, ViewMode } from '@red/domain';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { combineLatest, Observable, timer } from 'rxjs';
|
||||
import { combineLatest, firstValueFrom, Observable, timer } from 'rxjs';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { PdfViewerDataService } from '../../services/pdf-viewer-data.service';
|
||||
import { download } from '@utils/file-download-utils';
|
||||
@ -36,7 +36,7 @@ import { handleFilterDelta } from '@utils/filter-utils';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { map, switchMap, tap } from 'rxjs/operators';
|
||||
import { filter, map, switchMap, tap } 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';
|
||||
@ -45,12 +45,10 @@ import { MultiSelectService } from './services/multi-select.service';
|
||||
import { DocumentInfoService } from './services/document-info.service';
|
||||
import { ReanalysisService } from '../../../../services/reanalysis.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { CommentingService } from './services/commenting.service';
|
||||
import { SkippedService } from './services/skipped.service';
|
||||
import { AnnotationActionsService } from './services/annotation-actions.service';
|
||||
import { FilePreviewStateService } from './services/file-preview-state.service';
|
||||
import { FileDataModel } from '../../../../models/file/file-data.model';
|
||||
import { AnnotationReferencesService } from './services/annotation-references.service';
|
||||
import { filePreviewScreenProviders } from './utils';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
import PDFNet = Core.PDFNet;
|
||||
|
||||
@ -59,20 +57,7 @@ const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f', 'ArrowUp', 'ArrowDown'];
|
||||
@Component({
|
||||
templateUrl: './file-preview-screen.component.html',
|
||||
styleUrls: ['./file-preview-screen.component.scss'],
|
||||
providers: [
|
||||
FilterService,
|
||||
ExcludedPagesService,
|
||||
ViewModeService,
|
||||
MultiSelectService,
|
||||
DocumentInfoService,
|
||||
CommentingService,
|
||||
SkippedService,
|
||||
AnnotationDrawService,
|
||||
AnnotationActionsService,
|
||||
FilePreviewStateService,
|
||||
PdfViewerDataService,
|
||||
AnnotationReferencesService,
|
||||
],
|
||||
providers: filePreviewScreenProviders,
|
||||
})
|
||||
export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnInit, OnDestroy, OnAttach, OnDetach {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
@ -84,10 +69,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
displayPdfViewer = false;
|
||||
activeViewerPage: number = null;
|
||||
@ViewChild(PdfViewerComponent) readonly viewerComponent: PdfViewerComponent;
|
||||
readonly dossierId: string;
|
||||
readonly canPerformAnnotationActions$: Observable<boolean>;
|
||||
readonly dossier$: Observable<Dossier>;
|
||||
readonly fileId: string;
|
||||
readonly fileId = this.stateService.fileId;
|
||||
readonly dossierId = this.stateService.dossierId;
|
||||
ready = false;
|
||||
private _instance: WebViewerInstance;
|
||||
private _lastPage: string;
|
||||
@ -128,9 +112,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
readonly documentInfoService: DocumentInfoService,
|
||||
) {
|
||||
super();
|
||||
this.dossierId = _activatedRoute.snapshot.paramMap.get('dossierId');
|
||||
this.dossier$ = _dossiersService.getEntityChanged$(this.dossierId);
|
||||
this.fileId = _activatedRoute.snapshot.paramMap.get('fileId');
|
||||
this.canPerformAnnotationActions$ = this._canPerformAnnotationActions$;
|
||||
|
||||
document.documentElement.addEventListener('fullscreenchange', () => {
|
||||
@ -466,19 +447,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}, 100);
|
||||
}
|
||||
|
||||
private async _reloadFile(file: File): Promise<void> {
|
||||
const previousFile = this._fileData?.file;
|
||||
await this._loadFileData(file);
|
||||
|
||||
// file already loaded at least once
|
||||
if (previousFile) {
|
||||
// If it has been OCRd, we need to wait for it to load into the viewer
|
||||
if (previousFile.lastOCRTime !== this._fileData?.file?.lastOCRTime) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async _stampPDF() {
|
||||
if (!this._instance?.Core.documentViewer.getDocument()) {
|
||||
return;
|
||||
@ -534,23 +502,22 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
}
|
||||
|
||||
private async _fileUpdated(file: File): Promise<File> {
|
||||
if (!this._fileData || file.lastProcessed === this._fileData.file.lastProcessed) {
|
||||
await this._reloadFile(file);
|
||||
} else {
|
||||
// File reanalysed
|
||||
const previousAnnotations = this.visibleAnnotations;
|
||||
await this._loadFileData(file);
|
||||
await this._reloadAnnotations(previousAnnotations);
|
||||
}
|
||||
private async _fileUpdated(file: File): Promise<void> {
|
||||
const hasBeenProcessed = await firstValueFrom(this.stateService.hasBeenProcessed$);
|
||||
await this._loadFileData(file);
|
||||
|
||||
return file;
|
||||
if (hasBeenProcessed) {
|
||||
await this._reloadAnnotations();
|
||||
}
|
||||
}
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
this.addActiveScreenSubscription = this._filesMapService
|
||||
.watch$(this.dossierId, this.fileId)
|
||||
.pipe(switchMap(file => this._fileUpdated(file)))
|
||||
.pipe(
|
||||
filter(f => !!f),
|
||||
switchMap(file => this._fileUpdated(file)),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
this.addActiveScreenSubscription = timer(0, 5000)
|
||||
@ -589,13 +556,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return this._router.navigate([this._dossiersService.find(this.dossierId).routerLink]);
|
||||
}
|
||||
|
||||
const fileData = await this._pdfViewerDataService.loadDataFor(file).toPromise();
|
||||
|
||||
if (file.isPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.stateService.fileData = fileData;
|
||||
this.stateService.fileData = await firstValueFrom(this._pdfViewerDataService.loadDataFor(file));
|
||||
}
|
||||
|
||||
@Debounce(0)
|
||||
@ -604,25 +569,24 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._workloadComponent?.scrollAnnotations();
|
||||
}
|
||||
|
||||
private async _reloadAnnotations(previousAnnotations?: AnnotationWrapper[]) {
|
||||
private async _reloadAnnotations() {
|
||||
this._deleteAnnotations();
|
||||
await this._cleanupAndRedrawAnnotations(previousAnnotations);
|
||||
await this._cleanupAndRedrawAnnotations();
|
||||
}
|
||||
|
||||
private async _reloadAnnotationsForPage(page: number) {
|
||||
this._fileData.file = await this._filesService.reload(this.dossierId, this.fileId).toPromise();
|
||||
|
||||
const file = await firstValueFrom(this._filesService.reload(this.dossierId, this.fileId));
|
||||
// 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 (this._fileData.file.isProcessing) {
|
||||
if (file.isProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPageAnnotations = this.visibleAnnotations.filter(a => a.pageNumber === page);
|
||||
this._fileData.redactionLog = await this._pdfViewerDataService.loadRedactionLogFor(this.dossierId, this.fileId).toPromise();
|
||||
this._fileData.redactionLog = await firstValueFrom(this._pdfViewerDataService.loadRedactionLogFor(this.dossierId, this.fileId));
|
||||
|
||||
this._deleteAnnotations(currentPageAnnotations);
|
||||
await this._cleanupAndRedrawAnnotations(currentPageAnnotations, annotation => annotation.pageNumber === page);
|
||||
await this._cleanupAndRedrawAnnotations(annotation => annotation.pageNumber === page);
|
||||
}
|
||||
|
||||
private _deleteAnnotations(annotationsToDelete?: AnnotationWrapper[]) {
|
||||
@ -641,10 +605,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
});
|
||||
}
|
||||
|
||||
private async _cleanupAndRedrawAnnotations(
|
||||
currentAnnotations?: AnnotationWrapper[],
|
||||
newAnnotationsFilter?: (annotation: AnnotationWrapper) => boolean,
|
||||
) {
|
||||
private async _cleanupAndRedrawAnnotations(newAnnotationsFilter?: (annotation: AnnotationWrapper) => boolean) {
|
||||
if (!this._instance?.Core.documentViewer.getDocument()) {
|
||||
return;
|
||||
}
|
||||
@ -652,17 +613,18 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
const currentFilters = this._filterService.getGroup('primaryFilters')?.filters || [];
|
||||
this.rebuildFilters();
|
||||
|
||||
if (this.viewModeService.viewMode === 'STANDARD') {
|
||||
const startTime = new Date().getTime();
|
||||
const newAnnotations = newAnnotationsFilter ? this.visibleAnnotations.filter(newAnnotationsFilter) : this.visibleAnnotations;
|
||||
if (currentFilters) {
|
||||
this._handleDeltaAnnotationFilters(currentFilters, this.visibleAnnotations);
|
||||
}
|
||||
await this._redrawAnnotations(newAnnotations);
|
||||
console.log(
|
||||
`[REDACTION] Annotations redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`,
|
||||
);
|
||||
if (!this.viewModeService.isStandard) {
|
||||
return;
|
||||
}
|
||||
|
||||
const startTime = new Date().getTime();
|
||||
const newAnnotations = newAnnotationsFilter ? this.visibleAnnotations.filter(newAnnotationsFilter) : this.visibleAnnotations;
|
||||
|
||||
if (currentFilters) {
|
||||
this._handleDeltaAnnotationFilters(currentFilters, this.visibleAnnotations);
|
||||
}
|
||||
await this._redrawAnnotations(newAnnotations);
|
||||
console.log(`[REDACTION] Annotations redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`);
|
||||
}
|
||||
|
||||
private _redrawAnnotations(annotations = this.allAnnotations) {
|
||||
|
||||
@ -23,6 +23,7 @@ import {
|
||||
import { defaultDialogConfig } from '@iqser/common-ui';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
@Injectable()
|
||||
@ -38,6 +39,7 @@ export class AnnotationActionsService {
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _annotationDrawService: AnnotationDrawService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _screenStateService: FilePreviewStateService,
|
||||
) {}
|
||||
|
||||
acceptSuggestion(
|
||||
@ -215,13 +217,11 @@ export class AnnotationActionsService {
|
||||
|
||||
getViewerAvailableActions(
|
||||
viewer: WebViewerInstance,
|
||||
file: File,
|
||||
dossier: Dossier,
|
||||
annotations: AnnotationWrapper[],
|
||||
annotationsChanged: EventEmitter<AnnotationWrapper>,
|
||||
): Record<string, unknown>[] {
|
||||
const availableActions = [];
|
||||
const dossier = this._dossier(file);
|
||||
|
||||
const annotationPermissions = annotations.map(annotation => ({
|
||||
annotation,
|
||||
permissions: AnnotationPermissions.forUser(
|
||||
@ -241,21 +241,19 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/check.svg'),
|
||||
title: this._translateService.instant('annotation-actions.resize-accept.label'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.acceptResize(null, viewer, file, firstAnnotation, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
availableActions.push({
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/close.svg'),
|
||||
title: this._translateService.instant('annotation-actions.resize-cancel.label'),
|
||||
onClick: () => {
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.cancelResize(null, viewer, firstAnnotation, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
return availableActions;
|
||||
}
|
||||
@ -264,11 +262,7 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/resize.svg'),
|
||||
title: this._translateService.instant('annotation-actions.resize.label'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
this.resize(null, viewer, annotations[0]);
|
||||
});
|
||||
},
|
||||
onClick: () => this._ngZone.run(() => this.resize(null, viewer, annotations[0])),
|
||||
});
|
||||
}
|
||||
|
||||
@ -278,11 +272,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/edit.svg'),
|
||||
title: this._translateService.instant('annotation-actions.edit-reason.label'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.changeLegalBasis(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -292,11 +285,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-down.svg'),
|
||||
title: this._translateService.instant('annotation-actions.recategorize-image'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.recategorizeImages(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -309,11 +301,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/remove-from-dict.svg'),
|
||||
title: this._translateService.instant('annotation-actions.remove-annotation.remove-from-dict'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.removeOrSuggestRemoveAnnotation(null, annotations, file, true, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -323,11 +314,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/check.svg'),
|
||||
title: this._translateService.instant('annotation-actions.accept-recommendation.label'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.convertRecommendationToAnnotation(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -337,11 +327,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/check.svg'),
|
||||
title: this._translateService.instant('annotation-actions.accept-suggestion.label'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.acceptSuggestion(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -351,11 +340,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/undo.svg'),
|
||||
title: this._translateService.instant('annotation-actions.undo'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.undoDirectAction(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -365,11 +353,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-down.svg'),
|
||||
title: this._translateService.instant('annotation-actions.remove-annotation.false-positive'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.markAsFalsePositive(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -379,11 +366,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-up.svg'),
|
||||
title: this._translateService.instant('annotation-actions.force-redaction.label'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.forceAnnotation(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -393,11 +379,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/thumb-up.svg'),
|
||||
title: this._translateService.instant('annotation-actions.force-hint.label'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.forceAnnotation(null, annotations, file, annotationsChanged, true);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -407,11 +392,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/close.svg'),
|
||||
title: this._translateService.instant('annotation-actions.reject-suggestion'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.rejectSuggestion(null, annotations, file, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -424,11 +408,10 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/trash.svg'),
|
||||
title: this._translateService.instant('annotation-actions.remove-annotation.only-here'),
|
||||
onClick: () => {
|
||||
this._ngZone.run(() => {
|
||||
onClick: () =>
|
||||
this._runForCurrentFile(file => {
|
||||
this.removeOrSuggestRemoveAnnotation(null, annotations, file, false, annotationsChanged);
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -503,6 +486,13 @@ export class AnnotationActionsService {
|
||||
annotationsChanged.emit(annotationWrapper);
|
||||
}
|
||||
|
||||
private async _runForCurrentFile(func: (file: File) => unknown): Promise<void> {
|
||||
const file = await this._screenStateService.file;
|
||||
this._ngZone.run(() => {
|
||||
func(file);
|
||||
});
|
||||
}
|
||||
|
||||
private _dossier(file: File): Dossier {
|
||||
return this._dossiersService.find(file.dossierId);
|
||||
}
|
||||
|
||||
@ -1,28 +1,40 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable, switchMap } from 'rxjs';
|
||||
import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs';
|
||||
import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { DossiersService } from '../../../../../services/entity-services/dossiers.service';
|
||||
import { shareLast } from '../../../../../../../../../libs/common-ui/src';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FilesMapService } from '../../../../../services/entity-services/files-map.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class FilePreviewStateService {
|
||||
readonly fileData$: Observable<FileDataModel>;
|
||||
readonly file$: Observable<File>;
|
||||
readonly dossier$: Observable<Dossier>;
|
||||
readonly dossierId: string;
|
||||
readonly fileId: string;
|
||||
readonly hasBeenProcessed$: Observable<boolean>;
|
||||
private readonly _fileData$ = new BehaviorSubject<FileDataModel>(undefined);
|
||||
private _lastProcessed = '';
|
||||
|
||||
constructor(
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
activatedRoute: ActivatedRoute,
|
||||
) {
|
||||
this.dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
|
||||
this.dossier$ = _dossiersService.getEntityChanged$(this.dossierId);
|
||||
this.fileId = activatedRoute.snapshot.paramMap.get('fileId');
|
||||
|
||||
constructor(private readonly _dossiersService: DossiersService) {
|
||||
this.fileData$ = this._fileData$.asObservable();
|
||||
this.file$ = this.fileData$.pipe(
|
||||
filter(fileData => !!fileData),
|
||||
switchMap(fileData => fileData.file$),
|
||||
shareLast(),
|
||||
);
|
||||
this.dossier$ = this.file$.pipe(
|
||||
switchMap(file => this._dossiersService.getEntityChanged$(file.dossierId)),
|
||||
shareLast(),
|
||||
this.file$ = _filesMapService.watch$(this.dossierId, this.fileId);
|
||||
this.hasBeenProcessed$ = this.file$.pipe(
|
||||
map(file => {
|
||||
const hasBeenProcessed = file.lastProcessed !== this._lastProcessed;
|
||||
this._lastProcessed = file.lastProcessed;
|
||||
return hasBeenProcessed;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -33,4 +45,8 @@ export class FilePreviewStateService {
|
||||
set fileData(fileDataModel: FileDataModel) {
|
||||
this._fileData$.next(fileDataModel);
|
||||
}
|
||||
|
||||
get file(): Promise<File> {
|
||||
return firstValueFrom(this.file$);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
import { ExcludedPagesService } from './services/excluded-pages.service';
|
||||
import { ViewModeService } from './services/view-mode.service';
|
||||
import { MultiSelectService } from './services/multi-select.service';
|
||||
import { DocumentInfoService } from './services/document-info.service';
|
||||
import { CommentingService } from './services/commenting.service';
|
||||
import { SkippedService } from './services/skipped.service';
|
||||
import { AnnotationDrawService } from './services/annotation-draw.service';
|
||||
import { AnnotationActionsService } from './services/annotation-actions.service';
|
||||
import { FilePreviewStateService } from './services/file-preview-state.service';
|
||||
import { PdfViewerDataService } from '../../services/pdf-viewer-data.service';
|
||||
import { AnnotationReferencesService } from './services/annotation-references.service';
|
||||
import { FilterService } from '../../../../../../../../libs/common-ui/src';
|
||||
|
||||
export const filePreviewScreenProviders = [
|
||||
FilterService,
|
||||
ExcludedPagesService,
|
||||
ViewModeService,
|
||||
MultiSelectService,
|
||||
DocumentInfoService,
|
||||
CommentingService,
|
||||
SkippedService,
|
||||
AnnotationDrawService,
|
||||
AnnotationActionsService,
|
||||
FilePreviewStateService,
|
||||
PdfViewerDataService,
|
||||
AnnotationReferencesService,
|
||||
];
|
||||
Loading…
x
Reference in New Issue
Block a user