RED-5219: add button to load all annotations in dev mode
This commit is contained in:
parent
78fa79cdfa
commit
ef85665985
@ -5,7 +5,6 @@ import {
|
||||
Component,
|
||||
ElementRef,
|
||||
HostListener,
|
||||
Injector,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
@ -28,6 +27,7 @@ import {
|
||||
OnAttach,
|
||||
OnDetach,
|
||||
processFilters,
|
||||
Toaster,
|
||||
} from '@iqser/common-ui';
|
||||
import { MatDialogState } from '@angular/material/dialog';
|
||||
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||
@ -60,12 +60,13 @@ import { StampService } from './services/stamp.service';
|
||||
import { PdfViewer } from '../pdf-viewer/services/pdf-viewer.service';
|
||||
import { REDAnnotationManager } from '../pdf-viewer/services/annotation-manager.service';
|
||||
import { ViewerHeaderService } from '../pdf-viewer/services/viewer-header.service';
|
||||
import { ROTATION_ACTION_BUTTONS } from '../pdf-viewer/utils/constants';
|
||||
import { ROTATION_ACTION_BUTTONS, ViewerEvents } from '../pdf-viewer/utils/constants';
|
||||
import { SkippedService } from './services/skipped.service';
|
||||
import { REDDocumentViewer } from '../pdf-viewer/services/document-viewer.service';
|
||||
import { AnnotationsListingService } from './services/annotations-listing.service';
|
||||
import { PdfProxyService } from './services/pdf-proxy.service';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
const textActions = [TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE];
|
||||
@ -122,7 +123,12 @@ export class FilePreviewScreenComponent
|
||||
private readonly _annotationDrawService: AnnotationDrawService,
|
||||
private readonly _annotationProcessingService: AnnotationProcessingService,
|
||||
private readonly _stampService: StampService,
|
||||
private readonly _injector: Injector,
|
||||
private readonly _reanalysisService: ReanalysisService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _manualRedactionService: ManualRedactionService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _fileManagementService: FileManagementService,
|
||||
private readonly _translateService: TranslateService,
|
||||
) {
|
||||
super();
|
||||
document.documentElement.addEventListener('fullscreenchange', () => {
|
||||
@ -278,8 +284,7 @@ export class FilePreviewScreenComponent
|
||||
this._subscribeToFileUpdates();
|
||||
|
||||
if (file?.analysisRequired && !file.excludedFromAutomaticAnalysis) {
|
||||
const reanalysisService = this._injector.get(ReanalysisService);
|
||||
const reanalyzeFiles = reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true });
|
||||
const reanalyzeFiles = this._reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true });
|
||||
await firstValueFrom(reanalyzeFiles);
|
||||
}
|
||||
|
||||
@ -306,15 +311,15 @@ export class FilePreviewScreenComponent
|
||||
if (selectedAnnotations.length > 0) {
|
||||
this._annotationManager.delete([selectedAnnotations[0].Id]);
|
||||
}
|
||||
const manualRedactionService = this._injector.get(ManualRedactionService);
|
||||
const add$ = manualRedactionService.addAnnotation(
|
||||
|
||||
const add$ = this._manualRedactionService.addAnnotation(
|
||||
result.annotations.map(w => w.manualRedactionEntry).filter(e => e.positions[0].page <= file.numberOfPages),
|
||||
this.dossierId,
|
||||
this.fileId,
|
||||
result.dictionary?.label,
|
||||
);
|
||||
const filesService = this._injector.get(FilesService);
|
||||
const addAndReload$ = add$.pipe(switchMap(() => filesService.reload(this.dossierId, file)));
|
||||
|
||||
const addAndReload$ = add$.pipe(switchMap(() => this._filesService.reload(this.dossierId, file)));
|
||||
return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined))));
|
||||
},
|
||||
);
|
||||
@ -389,8 +394,7 @@ export class FilePreviewScreenComponent
|
||||
}
|
||||
|
||||
async downloadOriginalFile({ cacheIdentifier, dossierId, fileId, filename }: File) {
|
||||
const fileManagementService = this._injector.get(FileManagementService);
|
||||
const originalFile = fileManagementService.downloadOriginal(dossierId, fileId, 'response', cacheIdentifier);
|
||||
const originalFile = this._fileManagementService.downloadOriginal(dossierId, fileId, 'response', cacheIdentifier);
|
||||
download(await firstValueFrom(originalFile), filename);
|
||||
}
|
||||
|
||||
@ -610,7 +614,25 @@ export class FilePreviewScreenComponent
|
||||
this.addActiveScreenSubscription = this.pdfProxyService.pageChanged$.subscribe(page =>
|
||||
this._ngZone.run(() => this.#updateQueryParamsPage(page)),
|
||||
);
|
||||
|
||||
this.addActiveScreenSubscription = this.pdfProxyService.annotationSelected$.subscribe();
|
||||
|
||||
this.addActiveScreenSubscription = this._viewerHeaderService.events$
|
||||
.pipe(
|
||||
filter(event => event.type === ViewerEvents.LOAD_ALL_ANNOTATIONS),
|
||||
switchMap(() => this._fileDataService.annotations),
|
||||
tap(annotations => {
|
||||
if (annotations.length >= this.configService.values.ANNOTATIONS_THRESHOLD) {
|
||||
this._toaster.warning(_('load-all-annotations-threshold-exceeded'), {
|
||||
params: {
|
||||
threshold: this.configService.values.ANNOTATIONS_THRESHOLD,
|
||||
},
|
||||
});
|
||||
}
|
||||
}),
|
||||
switchMap(annotations => this.drawChangedAnnotations([], annotations)),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private _handleDeletedDossier(): void {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { List } from '@iqser/common-ui';
|
||||
import { List, ValuesOf } from '@iqser/common-ui';
|
||||
|
||||
export const ActionsHelpModeKeys = {
|
||||
redaction: 'redaction_text',
|
||||
@ -13,27 +13,20 @@ export const ActionsHelpModeKeys = {
|
||||
|
||||
export const ALL_HOTKEYS: List = ['Escape', 'F', 'f', 'ArrowUp', 'ArrowDown'] as const;
|
||||
|
||||
export type HeaderElementType =
|
||||
| 'SHAPE_TOOL_GROUP_BUTTON'
|
||||
| 'ROTATE_LEFT_BUTTON'
|
||||
| 'ROTATE_RIGHT_BUTTON'
|
||||
| 'APPLY_ROTATION'
|
||||
| 'DISCARD_ROTATION'
|
||||
| 'TOGGLE_TOOLTIPS'
|
||||
| 'COMPARE_BUTTON'
|
||||
| 'CLOSE_COMPARE_BUTTON';
|
||||
|
||||
export const HeaderElements: Record<HeaderElementType, HeaderElementType> = {
|
||||
export const HeaderElements = {
|
||||
SHAPE_TOOL_GROUP_BUTTON: 'SHAPE_TOOL_GROUP_BUTTON',
|
||||
ROTATE_LEFT_BUTTON: 'ROTATE_LEFT_BUTTON',
|
||||
ROTATE_RIGHT_BUTTON: 'ROTATE_RIGHT_BUTTON',
|
||||
APPLY_ROTATION: 'APPLY_ROTATION',
|
||||
DISCARD_ROTATION: 'DISCARD_ROTATION',
|
||||
TOGGLE_TOOLTIPS: 'TOGGLE_TOOLTIPS',
|
||||
COMPARE_BUTTON: 'COMPARE_BUTTON',
|
||||
CLOSE_COMPARE_BUTTON: 'CLOSE_COMPARE_BUTTON',
|
||||
TOGGLE_TOOLTIPS: 'TOGGLE_TOOLTIPS',
|
||||
LOAD_ALL_ANNOTATIONS: 'LOAD_ALL_ANNOTATIONS',
|
||||
} as const;
|
||||
|
||||
export type HeaderElementType = ValuesOf<typeof HeaderElements>;
|
||||
|
||||
export const TextPopups = {
|
||||
ADD_REDACTION: 'add-redaction',
|
||||
ADD_DICTIONARY: 'add-dictionary',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable, Injector } from '@angular/core';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { IHeaderElement, RotationTypes } from '@red/domain';
|
||||
import { HeaderElements, HeaderElementType } from '../../file-preview/utils/constants';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@ -6,9 +6,13 @@ import { BASE_HREF_FN, BaseHrefFn } from '@iqser/common-ui';
|
||||
import { TooltipsService } from './tooltips.service';
|
||||
import { PageRotationService } from './page-rotation.service';
|
||||
import { PdfViewer } from './pdf-viewer.service';
|
||||
import { ROTATION_ACTION_BUTTONS } from '../utils/constants';
|
||||
import { ROTATION_ACTION_BUTTONS, ViewerEvents } from '../utils/constants';
|
||||
import { FilesMapService } from '@services/files/files-map.service';
|
||||
import { REDDocumentViewer } from './document-viewer.service';
|
||||
import { UserPreferenceService } from '@users/user-preference.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { ViewerEvent } from '../utils/types';
|
||||
|
||||
const divider: IHeaderElement = {
|
||||
type: 'divider',
|
||||
@ -16,10 +20,12 @@ const divider: IHeaderElement = {
|
||||
|
||||
@Injectable()
|
||||
export class ViewerHeaderService {
|
||||
readonly events$: Observable<ViewerEvent>;
|
||||
#buttons: Map<HeaderElementType, IHeaderElement>;
|
||||
readonly #config = new Map<HeaderElementType, boolean>([
|
||||
[HeaderElements.SHAPE_TOOL_GROUP_BUTTON, true],
|
||||
[HeaderElements.TOGGLE_TOOLTIPS, true],
|
||||
[HeaderElements.LOAD_ALL_ANNOTATIONS, false],
|
||||
[HeaderElements.COMPARE_BUTTON, true],
|
||||
[HeaderElements.CLOSE_COMPARE_BUTTON, false],
|
||||
[HeaderElements.ROTATE_LEFT_BUTTON, true],
|
||||
@ -28,16 +34,22 @@ export class ViewerHeaderService {
|
||||
[HeaderElements.DISCARD_ROTATION, false],
|
||||
]);
|
||||
#docBeforeCompare: Blob;
|
||||
readonly #events$ = new Subject<ViewerEvent>();
|
||||
|
||||
constructor(
|
||||
@Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn,
|
||||
private readonly _injector: Injector,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _pdf: PdfViewer,
|
||||
private readonly _documentViewer: REDDocumentViewer,
|
||||
private readonly _rotationService: PageRotationService,
|
||||
private readonly _tooltipsService: TooltipsService,
|
||||
) {}
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _router: Router,
|
||||
) {
|
||||
this.events$ = this.#events$.asObservable();
|
||||
}
|
||||
|
||||
private get _rectangle(): IHeaderElement {
|
||||
return {
|
||||
@ -62,6 +74,17 @@ export class ViewerHeaderService {
|
||||
};
|
||||
}
|
||||
|
||||
private get _loadAllAnnotations(): IHeaderElement {
|
||||
return {
|
||||
type: 'actionButton',
|
||||
element: HeaderElements.LOAD_ALL_ANNOTATIONS,
|
||||
dataElement: HeaderElements.LOAD_ALL_ANNOTATIONS,
|
||||
title: this._translateService.instant('viewer-header.load-all-annotations'),
|
||||
img: this._tooltipsService.toggleTooltipsBtnIcon,
|
||||
onClick: () => this.#events$.next({ type: ViewerEvents.LOAD_ALL_ANNOTATIONS }),
|
||||
};
|
||||
}
|
||||
|
||||
private get _closeCompare(): IHeaderElement {
|
||||
return {
|
||||
type: 'actionButton',
|
||||
@ -167,11 +190,16 @@ export class ViewerHeaderService {
|
||||
[HeaderElements.APPLY_ROTATION, this._applyRotation],
|
||||
[HeaderElements.DISCARD_ROTATION, this._discardRotation],
|
||||
[HeaderElements.TOGGLE_TOOLTIPS, this._toggleTooltips],
|
||||
[HeaderElements.LOAD_ALL_ANNOTATIONS, this._loadAllAnnotations],
|
||||
[HeaderElements.COMPARE_BUTTON, this._compare],
|
||||
[HeaderElements.CLOSE_COMPARE_BUTTON, this._closeCompare],
|
||||
]);
|
||||
|
||||
this.updateElements();
|
||||
|
||||
if (this._userPreferenceService.areDevFeaturesEnabled) {
|
||||
this.enable([HeaderElements.LOAD_ALL_ANNOTATIONS]);
|
||||
}
|
||||
}
|
||||
|
||||
enable(elements: HeaderElementType[]): void {
|
||||
@ -186,7 +214,7 @@ export class ViewerHeaderService {
|
||||
this._pdf.instance?.UI.setHeaderItems(header => {
|
||||
const enabledItems: IHeaderElement[] = [];
|
||||
const groups: HeaderElementType[][] = [
|
||||
[HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON],
|
||||
[HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON, HeaderElements.LOAD_ALL_ANNOTATIONS],
|
||||
[HeaderElements.TOGGLE_TOOLTIPS],
|
||||
[HeaderElements.SHAPE_TOOL_GROUP_BUTTON],
|
||||
[
|
||||
@ -217,7 +245,7 @@ export class ViewerHeaderService {
|
||||
private _closeCompareMode() {
|
||||
this._pdf.closeCompareMode();
|
||||
const { dossierId, fileId } = this._pdf;
|
||||
const file = this._injector.get(FilesMapService).get(dossierId, fileId);
|
||||
const file = this._filesMapService.get(dossierId, fileId);
|
||||
const filename = file.filename ?? 'document.pdf';
|
||||
|
||||
this._pdf.instance.UI.loadDocument(this.#docBeforeCompare, { filename });
|
||||
|
||||
@ -31,6 +31,10 @@ export const SEARCH_OPTIONS = {
|
||||
ambientString: true, // return ambient string as part of the result
|
||||
};
|
||||
|
||||
export const ViewerEvents = {
|
||||
LOAD_ALL_ANNOTATIONS: 'LOAD_ALL_ANNOTATIONS',
|
||||
} as const;
|
||||
|
||||
export const USELESS_ELEMENTS = [
|
||||
'pageNavOverlay',
|
||||
'menuButton',
|
||||
|
||||
@ -15,3 +15,7 @@ export interface DeleteAnnotationsOptions {
|
||||
}
|
||||
|
||||
export type AnnotationPredicate = (value: Annotation) => boolean;
|
||||
|
||||
export interface ViewerEvent {
|
||||
readonly type: string;
|
||||
}
|
||||
|
||||
@ -15,5 +15,6 @@
|
||||
"RECENT_PERIOD_IN_HOURS": 24,
|
||||
"SELECTION_MODE": "structural",
|
||||
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
|
||||
"RSS_ENABLED": true
|
||||
"RSS_ENABLED": true,
|
||||
"ANNOTATIONS_THRESHOLD": 1000
|
||||
}
|
||||
|
||||
@ -787,7 +787,6 @@
|
||||
},
|
||||
"quick-filters": {
|
||||
"member": "",
|
||||
"my-dossiers": "Meine Dossiers",
|
||||
"owner": ""
|
||||
},
|
||||
"reanalyse": {
|
||||
@ -1314,6 +1313,7 @@
|
||||
"no-data": {
|
||||
"title": "Auf dieser Seite gibt es keine Anmerkungen."
|
||||
},
|
||||
"open-rss-view": "",
|
||||
"quick-nav": {
|
||||
"jump-first": "Zur ersten Seite springen",
|
||||
"jump-last": "Zur letzten Seite springen"
|
||||
@ -1615,6 +1615,7 @@
|
||||
"usage-details": "Nutzungsdetails"
|
||||
},
|
||||
"license-information": "Lizenzinformationen",
|
||||
"load-all-annotations-threshold-exceeded": "",
|
||||
"loading": "",
|
||||
"manual-annotation": {
|
||||
"dialog": {
|
||||
@ -1906,6 +1907,14 @@
|
||||
"red-user-admin": "Benutzer-Admin",
|
||||
"regular": "Regulär"
|
||||
},
|
||||
"rss-dialog": {
|
||||
"actions": {
|
||||
"close": "",
|
||||
"export-json": "",
|
||||
"export-xml": ""
|
||||
},
|
||||
"title": ""
|
||||
},
|
||||
"rules-screen": {
|
||||
"error": {
|
||||
"generic": "Es ist ein Fehler aufgetreten ... Die Regeln konnten nicht aktualisiert werden!"
|
||||
@ -2094,6 +2103,9 @@
|
||||
"view-as": "Ansicht als:",
|
||||
"workflow": "Arbeitsablauf"
|
||||
},
|
||||
"viewer-header": {
|
||||
"load-all-annotations": ""
|
||||
},
|
||||
"watermark-screen": {
|
||||
"action": {
|
||||
"change-success": "Das Wasserzeichen wurde aktualisiert!",
|
||||
|
||||
@ -787,7 +787,6 @@
|
||||
},
|
||||
"quick-filters": {
|
||||
"member": "Dossier Member",
|
||||
"my-dossiers": "My Dossiers",
|
||||
"owner": "Dossier Owner"
|
||||
},
|
||||
"reanalyse": {
|
||||
@ -1295,14 +1294,6 @@
|
||||
},
|
||||
"upload-csv": "Upload File Attributes Configuration"
|
||||
},
|
||||
"rss-dialog": {
|
||||
"title": "Structured Component Management",
|
||||
"actions": {
|
||||
"export-json": "Export JSON",
|
||||
"export-xml": "Export XML",
|
||||
"close": "Close"
|
||||
}
|
||||
},
|
||||
"file-preview": {
|
||||
"assign-me": "Assign to me",
|
||||
"assign-reviewer": "Assign User",
|
||||
@ -1311,7 +1302,6 @@
|
||||
"delta-tooltip": "The Delta View shows the unseen changes since your last visit to the page. This view is only available if there is at least 1 change.",
|
||||
"document-info": "Document Info",
|
||||
"download-original-file": "Download Original File",
|
||||
"open-rss-view": "Open Structured Component Management View",
|
||||
"exclude-pages": "Exclude pages from redaction",
|
||||
"excluded-from-redaction": "excluded",
|
||||
"fullscreen": "Full Screen (F)",
|
||||
@ -1323,6 +1313,7 @@
|
||||
"no-data": {
|
||||
"title": "There have been no changes to this page."
|
||||
},
|
||||
"open-rss-view": "Open Structured Component Management View",
|
||||
"quick-nav": {
|
||||
"jump-first": "Jump to first page",
|
||||
"jump-last": "Jump to last page"
|
||||
@ -1624,6 +1615,7 @@
|
||||
"usage-details": "Usage Details"
|
||||
},
|
||||
"license-information": "License Information",
|
||||
"load-all-annotations-threshold-exceeded": "Caution, document contains more than {threshold} annotations. Drawing all annotations will affect the performance of the app and could even block it.",
|
||||
"loading": "Loading",
|
||||
"manual-annotation": {
|
||||
"dialog": {
|
||||
@ -1915,6 +1907,14 @@
|
||||
"red-user-admin": "Users Admin",
|
||||
"regular": "Regular"
|
||||
},
|
||||
"rss-dialog": {
|
||||
"actions": {
|
||||
"close": "Close",
|
||||
"export-json": "Export JSON",
|
||||
"export-xml": "Export XML"
|
||||
},
|
||||
"title": "Structured Component Management"
|
||||
},
|
||||
"rules-screen": {
|
||||
"error": {
|
||||
"generic": "Something went wrong... Rules update failed!"
|
||||
@ -2103,6 +2103,9 @@
|
||||
"view-as": "View as:",
|
||||
"workflow": "Workflow"
|
||||
},
|
||||
"viewer-header": {
|
||||
"load-all-annotations": "Load all annotations"
|
||||
},
|
||||
"watermark-screen": {
|
||||
"action": {
|
||||
"change-success": "Watermark has been updated!",
|
||||
|
||||
@ -18,6 +18,7 @@ RECENT_PERIOD_IN_HOURS="${RECENT_PERIOD_IN_HOURS:-24}"
|
||||
SELECTION_MODE="${SELECTION_MODE:-structural}"
|
||||
MANUAL_BASE_URL="${MANUAL_BASE_URL:-https://docs.redactmanager.com/preview}"
|
||||
RSS_ENABLED="${RSS_ENABLED:-false}"
|
||||
ANNOTATIONS_THRESHOLD="${ANNOTATIONS_THRESHOLD:-1000}"
|
||||
|
||||
|
||||
|
||||
@ -39,6 +40,7 @@ echo '{
|
||||
"SELECTION_MODE":"'"$SELECTION_MODE"'",
|
||||
"MANUAL_BASE_URL":"'"$MANUAL_BASE_URL"'",
|
||||
"RSS_ENABLED":'"$RSS_ENABLED"'
|
||||
"ANNOTATIONS_THRESHOLD":'"$ANNOTATIONS_THRESHOLD"'
|
||||
}' > /usr/share/nginx/html/ui/assets/config/config.json
|
||||
|
||||
echo 'Env variables: '
|
||||
|
||||
@ -16,4 +16,5 @@ export interface AppConfig {
|
||||
SELECTION_MODE: string;
|
||||
MANUAL_BASE_URL: string;
|
||||
RSS_ENABLED: boolean;
|
||||
ANNOTATIONS_THRESHOLD: number;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user