diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index 640b5dd3e..7b7613640 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -34,7 +34,7 @@ import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationDrawService } from '../pdf-viewer/services/annotation-draw.service'; import { AnnotationProcessingService } from './services/annotation-processing.service'; -import { Dictionary, File, ViewMode, ViewModes } from '@red/domain'; +import { Dictionary, File, ViewModes } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; import { combineLatest, firstValueFrom, from, of, pairwise } from 'rxjs'; import { UserPreferenceService } from '@users/user-preference.service'; @@ -68,6 +68,7 @@ import { PdfProxyService } from './services/pdf-proxy.service'; import { ConfigService } from '@services/config.service'; import { TranslateService } from '@ngx-translate/core'; import Annotation = Core.Annotations.Annotation; +import { ReadableRedactionsService } from '../pdf-viewer/services/readable-redactions.service'; const textActions = [TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE]; @@ -130,6 +131,7 @@ export class FilePreviewScreenComponent private readonly _filesService: FilesService, private readonly _fileManagementService: FileManagementService, private readonly _translateService: TranslateService, + private readonly _readableRedactionsService: ReadableRedactionsService, ) { super(); document.documentElement.addEventListener('fullscreenchange', () => { @@ -238,7 +240,11 @@ export class FilePreviewScreenComponent } case ViewModes.REDACTED: { const nonRedactionEntries = annotations.filter(a => !bool(a.getCustomData('redaction'))); - this._setAnnotationsOpacity(redactions); + if (this._readableRedactionsService.active) { + this._readableRedactionsService.makeRedactionsReadable(redactions); + } else { + this._setAnnotationsOpacity(redactions); + } this._setAnnotationsColor(redactions, 'redactionColor'); this._annotationManager.show(redactions); this._annotationManager.hide(nonRedactionEntries); @@ -630,6 +636,14 @@ export class FilePreviewScreenComponent switchMap(annotations => this.drawChangedAnnotations([], annotations)), ) .subscribe(); + + this.addActiveScreenSubscription = this._readableRedactionsService.active$ + .pipe( + tap(async () => { + await this.updateViewMode(); + }), + ) + .subscribe(); } private _handleDeletedDossier(): void { diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index 12477a62c..d0847e9a3 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -282,6 +282,7 @@ export class PdfProxyService { } this._pdf.enable(TEXT_POPUPS_TO_TOGGLE); this._viewerHeaderService.enable(HEADER_ITEMS_TO_TOGGLE); + this._viewerHeaderService.disable([HeaderElements.TOGGLE_READABLE_REDACTIONS]); if (this._documentViewer.selectedText.length > 2) { this._pdf.enable([TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE]); @@ -304,6 +305,7 @@ export class PdfProxyService { this._pdf.disable(textPopupElementsToDisable); this._viewerHeaderService.disable(headerElementsToDisable); + this._viewerHeaderService.enable([HeaderElements.TOGGLE_READABLE_REDACTIONS]); } private _getManualRedaction(quads: Record, text?: string, convertQuads = false): IManualRedactionEntry { diff --git a/apps/red-ui/src/app/modules/file-preview/utils/constants.ts b/apps/red-ui/src/app/modules/file-preview/utils/constants.ts index 9b1b824c2..bedb27197 100644 --- a/apps/red-ui/src/app/modules/file-preview/utils/constants.ts +++ b/apps/red-ui/src/app/modules/file-preview/utils/constants.ts @@ -22,6 +22,7 @@ export const HeaderElements = { COMPARE_BUTTON: 'COMPARE_BUTTON', CLOSE_COMPARE_BUTTON: 'CLOSE_COMPARE_BUTTON', TOGGLE_TOOLTIPS: 'TOGGLE_TOOLTIPS', + TOGGLE_READABLE_REDACTIONS: 'TOGGLE_READABLE_REDACTIONS', LOAD_ALL_ANNOTATIONS: 'LOAD_ALL_ANNOTATIONS', } as const; diff --git a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts index 73728338f..d49e497f6 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.module.ts @@ -12,6 +12,7 @@ import { MatIconModule } from '@angular/material/icon'; import { AnnotationDrawService } from './services/annotation-draw.service'; import { REDDocumentViewer } from './services/document-viewer.service'; import { WebViewerLoadedGuard } from './services/webviewer-loaded.guard'; +import { ReadableRedactionsService } from './services/readable-redactions.service'; @NgModule({ declarations: [PdfViewerComponent, CompareFileInputComponent, PaginatorComponent], @@ -23,6 +24,7 @@ import { WebViewerLoadedGuard } from './services/webviewer-loaded.guard'; REDAnnotationManager, PageRotationService, TooltipsService, + ReadableRedactionsService, ViewerHeaderService, AnnotationDrawService, WebViewerLoadedGuard, diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts new file mode 100644 index 000000000..0a9ca7f63 --- /dev/null +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts @@ -0,0 +1,60 @@ +import { Inject, Injectable } from '@angular/core'; +import { BASE_HREF_FN, BaseHrefFn } from '@iqser/common-ui'; +import { TranslateService } from '@ngx-translate/core'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { HeaderElements } from '../../file-preview/utils/constants'; +import { PdfViewer } from './pdf-viewer.service'; +import { REDAnnotationManager } from './annotation-manager.service'; +import { AnnotationDrawService } from './annotation-draw.service'; +import { Core } from '@pdftron/webviewer'; +import Annotation = Core.Annotations.Annotation; +import { BehaviorSubject, Observable } from 'rxjs'; + +const READABLE_REDACTION_OPACITY = 0.4; + +@Injectable() +export class ReadableRedactionsService { + readonly #enableIcon = this._convertPath('/assets/icons/general/pdftron-action-enable-tooltips.svg'); + readonly #disableIcon = this._convertPath('/assets/icons/general/pdftron-action-disable-tooltips.svg'); + readonly #active$ = new BehaviorSubject(false); + readonly active$: Observable; + + constructor( + @Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn, + private readonly _pdf: PdfViewer, + private readonly _translateService: TranslateService, + private readonly _annotationManager: REDAnnotationManager, + private readonly _annotationDrawService: AnnotationDrawService, + ) { + this.active$ = this.#active$.asObservable(); + } + + get active() { + return this.#active$.getValue(); + } + + get toggleReadableRedactionsBtnTitle(): string { + return this._translateService.instant(_('pdf-viewer.toggle-readable-redactions'), { + active: this.active, + }); + } + + get toggleReadableRedactionsBtnIcon(): string { + return this.active ? this.#enableIcon : this.#disableIcon; + } + + makeRedactionsReadable(redactions: Annotation[]): void { + redactions.forEach(redaction => { + redaction['Opacity'] = READABLE_REDACTION_OPACITY; + }); + } + + toggleReadableRedactions(): void { + this.#active$.next(!this.active); + + this._pdf.instance.UI.updateElement(HeaderElements.TOGGLE_READABLE_REDACTIONS, { + title: this.toggleReadableRedactionsBtnTitle, + img: this.toggleReadableRedactionsBtnIcon, + }); + } +} diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts index 95c6337e7..f20533488 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts @@ -13,6 +13,7 @@ import { UserPreferenceService } from '@users/user-preference.service'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable, Subject } from 'rxjs'; import { ViewerEvent } from '../utils/types'; +import { ReadableRedactionsService } from './readable-redactions.service'; const divider: IHeaderElement = { type: 'divider', @@ -25,6 +26,7 @@ export class ViewerHeaderService { readonly #config = new Map([ [HeaderElements.SHAPE_TOOL_GROUP_BUTTON, true], [HeaderElements.TOGGLE_TOOLTIPS, true], + [HeaderElements.TOGGLE_READABLE_REDACTIONS, true], [HeaderElements.LOAD_ALL_ANNOTATIONS, false], [HeaderElements.COMPARE_BUTTON, true], [HeaderElements.CLOSE_COMPARE_BUTTON, false], @@ -44,6 +46,7 @@ export class ViewerHeaderService { private readonly _documentViewer: REDDocumentViewer, private readonly _rotationService: PageRotationService, private readonly _tooltipsService: TooltipsService, + private readonly _readableRedactionsService: ReadableRedactionsService, private readonly _userPreferenceService: UserPreferenceService, private readonly _activatedRoute: ActivatedRoute, private readonly _router: Router, @@ -74,6 +77,19 @@ export class ViewerHeaderService { }; } + private get _toggleReadableRedactions(): IHeaderElement { + return { + type: 'actionButton', + element: HeaderElements.TOGGLE_READABLE_REDACTIONS, + dataElement: HeaderElements.TOGGLE_READABLE_REDACTIONS, + title: this._readableRedactionsService.toggleReadableRedactionsBtnTitle, + img: this._readableRedactionsService.toggleReadableRedactionsBtnIcon, + onClick: () => { + this._readableRedactionsService.toggleReadableRedactions(); + }, + }; + } + private get _loadAllAnnotations(): IHeaderElement { return { type: 'actionButton', @@ -192,6 +208,7 @@ export class ViewerHeaderService { [HeaderElements.APPLY_ROTATION, this._applyRotation], [HeaderElements.DISCARD_ROTATION, this._discardRotation], [HeaderElements.TOGGLE_TOOLTIPS, this._toggleTooltips], + [HeaderElements.TOGGLE_READABLE_REDACTIONS, this._toggleReadableRedactions], [HeaderElements.LOAD_ALL_ANNOTATIONS, this._loadAllAnnotations], [HeaderElements.COMPARE_BUTTON, this._compare], [HeaderElements.CLOSE_COMPARE_BUTTON, this._closeCompare], @@ -217,7 +234,7 @@ export class ViewerHeaderService { const enabledItems: IHeaderElement[] = []; const groups: HeaderElementType[][] = [ [HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON, HeaderElements.LOAD_ALL_ANNOTATIONS], - [HeaderElements.TOGGLE_TOOLTIPS], + [HeaderElements.TOGGLE_TOOLTIPS, HeaderElements.TOGGLE_READABLE_REDACTIONS], [HeaderElements.SHAPE_TOOL_GROUP_BUTTON], [ HeaderElements.ROTATE_LEFT_BUTTON, diff --git a/apps/red-ui/src/assets/i18n/de.json b/apps/red-ui/src/assets/i18n/de.json index f97be4b2f..0d86c999a 100644 --- a/apps/red-ui/src/assets/i18n/de.json +++ b/apps/red-ui/src/assets/i18n/de.json @@ -1771,6 +1771,7 @@ "search": "Nach Auswahl suchen" } }, + "toggle-readable-redactions": "", "toggle-tooltips": "{active, select, true{Disable} false{Enable} other{}} Kurzinfos für Anmerkungen" }, "permissions-screen": { diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 8304184e0..9fae51328 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -1771,6 +1771,7 @@ "search": "Search for selection" } }, + "toggle-readable-redactions": "Show redactions as {active, select, true{opaque} false{transparent} other{}}", "toggle-tooltips": "{active, select, true{Disable} false{Enable} other{}} annotation tooltips" }, "permissions-screen": { diff --git a/libs/common-ui b/libs/common-ui index 7272130f7..7367c31d3 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 7272130f7ace18bc4f6b4f5429f000c3eb5b0ef1 +Subproject commit 7367c31d37b19c2e3a73c886cc743b12dcccc71f