From ef55855b42e47b70ed8c8f856d60131d68f5d864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Thu, 24 Mar 2022 21:42:00 +0200 Subject: [PATCH] Enable/disable buttons through ViewerHeaderConfigService --- .../dossier/utils/compare-mode.utils.ts | 2 - .../pdf-viewer/pdf-viewer.component.ts | 75 ++++-------- .../services/page-rotation.service.ts | 3 + .../services/viewer-header-config.service.ts | 110 +++++++++++++++--- .../modules/file-preview/shared/constants.ts | 31 +++-- apps/red-ui/src/assets/config/config.json | 4 +- 6 files changed, 146 insertions(+), 79 deletions(-) diff --git a/apps/red-ui/src/app/modules/dossier/utils/compare-mode.utils.ts b/apps/red-ui/src/app/modules/dossier/utils/compare-mode.utils.ts index 06876a51b..ff117e3cc 100644 --- a/apps/red-ui/src/app/modules/dossier/utils/compare-mode.utils.ts +++ b/apps/red-ui/src/app/modules/dossier/utils/compare-mode.utils.ts @@ -54,8 +54,6 @@ export const loadCompareDocumentWrapper = async ( instance.UI.loadDocument(mergedDocumentBuffer, { filename: file?.filename ?? 'document.pdf', }); - instance.UI.disableElements(['compareButton']); - instance.UI.enableElements(['closeCompareButton']); navigateToPage(); } catch (e) { diff --git a/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts index 66ad47926..e4950489e 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/pdf-viewer/pdf-viewer.component.ts @@ -152,6 +152,8 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha }, this.instance.Core.PDFNet, ); + this._headerConfigService.disable([HeaderElements.COMPARE_BUTTON]); + this._headerConfigService.enable([HeaderElements.CLOSE_COMPARE_BUTTON]); this._loadingService.stop(); }; @@ -191,8 +193,9 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha const filename = (await this.stateService.file).filename ?? 'document.pdf'; this.instance.UI.loadDocument(currentDocument, { filename }); - this.instance.UI.disableElements([HeaderElements.CLOSE_COMPARE_BUTTON]); - this.instance.UI.enableElements([HeaderElements.COMPARE_BUTTON]); + this._headerConfigService.disable([HeaderElements.CLOSE_COMPARE_BUTTON]); + this._headerConfigService.enable([HeaderElements.COMPARE_BUTTON]); + this.pdf.navigateToPage(1); } @@ -344,45 +347,14 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha 'annotationGroupButton', ]); - const applyRotation: IHeaderElement = this._headerConfigService.applyRotation; - const discardRotation: IHeaderElement = this._headerConfigService.discardRotation; - const compare: IHeaderElement = this._headerConfigService.compare(this.compareFileInput); - const closeCompare: IHeaderElement = this._headerConfigService.closeCompare(async () => { - await this._closeCompareMode(); - }); - const toggleTooltips: IHeaderElement = this._headerConfigService.toggleTooltips(async (title: string, img: string) => { + const toggleTooltipsFn = async (title: string, img: string) => { await this._toggleTooltips(title, img); - }); - const rectangle = this._headerConfigService.rectangle; - const rotateLeft = this._headerConfigService.rotateLeft; - const rotateRight = this._headerConfigService.rotateRight; - const divider = this._headerConfigService.divider; + }; + const closeCompareFn = async () => { + await this._closeCompareMode(); + }; - const headerItems: IHeaderElement[] = [ - divider, - compare, - closeCompare, - divider, - toggleTooltips, - divider, - rectangle, - divider, - rotateLeft, - rotateRight, - applyRotation, - discardRotation, - divider, - ]; - - this.instance.UI.setHeaderItems(header => { - header.getItems().splice(8, 0, ...headerItems); - }); - - this.instance.UI.disableElements([ - HeaderElements.CLOSE_COMPARE_BUTTON, - HeaderElements.APPLY_ROTATION, - HeaderElements.DISCARD_ROTATION, - ]); + this._headerConfigService.initialize(toggleTooltipsFn, this.compareFileInput, closeCompareFn); const dossierTemplateId = this.dossier.dossierTemplateId; @@ -467,10 +439,9 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha } private _cleanUpSelectionAndButtonState() { - const rectangleElements = [HeaderElements.SHAPE_TOOL_GROUP_BUTTON]; this.pdf.deselectAllAnnotations(); - this.instance.UI.disableElements(rectangleElements); - this.instance.UI.enableElements(rectangleElements); + this._headerConfigService.disable([HeaderElements.SHAPE_TOOL_GROUP_BUTTON]); + this._headerConfigService.enable([HeaderElements.SHAPE_TOOL_GROUP_BUTTON]); } private _configureTextPopup() { @@ -538,11 +509,11 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha private async _handleCustomActions() { this.instance.UI.setToolMode('AnnotationEdit'); - const elementsToToggle = [ - TextPopups.ADD_REDACTION, - TextPopups.ADD_RECTANGLE, - TextPopups.ADD_FALSE_POSITIVE, + const textPopupsToToggle = [TextPopups.ADD_REDACTION, TextPopups.ADD_RECTANGLE, TextPopups.ADD_FALSE_POSITIVE]; + const headerItemsToToggle = [ HeaderElements.SHAPE_TOOL_GROUP_BUTTON, + HeaderElements.ROTATE_LEFT_BUTTON, + HeaderElements.ROTATE_RIGHT_BUTTON, HeaderElements.ANNOTATION_POPUP, ]; @@ -554,7 +525,8 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha } catch (e) { // happens } - this.instance.UI.enableElements(elementsToToggle); + this.instance.UI.enableElements(textPopupsToToggle); + this._headerConfigService.enable(headerItemsToToggle); if (this._selectedText.length > 2) { this.instance.UI.enableElements([TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE]); @@ -563,7 +535,8 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha return; } - let elementsToDisable = [...elementsToToggle, TextPopups.ADD_RECTANGLE]; + let textPopupElementsToDisable = [...textPopupsToToggle]; + let headerElementsToDisable = [...headerItemsToToggle]; if (isCurrentPageExcluded) { const allowedActionsWhenPageExcluded: string[] = [ @@ -572,12 +545,14 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha TextPopups.ADD_REDACTION, HeaderElements.SHAPE_TOOL_GROUP_BUTTON, ]; - elementsToDisable = elementsToDisable.filter(element => !allowedActionsWhenPageExcluded.includes(element)); + textPopupElementsToDisable = textPopupElementsToDisable.filter(element => !allowedActionsWhenPageExcluded.includes(element)); + headerElementsToDisable = headerElementsToDisable.filter(element => !allowedActionsWhenPageExcluded.includes(element)); } else { this.instance.UI.disableTools(['AnnotationCreateRectangle']); } - this.instance.UI.disableElements(elementsToDisable); + this.instance.UI.disableElements(textPopupElementsToDisable); + this._headerConfigService.disable(headerElementsToDisable); } private _getManualRedaction( diff --git a/apps/red-ui/src/app/modules/file-preview/services/page-rotation.service.ts b/apps/red-ui/src/app/modules/file-preview/services/page-rotation.service.ts index dec43e358..1ed4f7332 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/page-rotation.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/page-rotation.service.ts @@ -116,6 +116,9 @@ export class PageRotationService { return this.hasRotations() ? this.showConfirmationDialog() : of(ConfirmOptions.DISCARD_CHANGES); } + // TODO: Ideally, enabling/disabling buttons should be done through ViewerHeaderConfigService, not through _pdf.UI, + // but circular dependencies =D + #showActionButtons() { this._pdf.UI.enableElements(actionButtons); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts b/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts index 38bf0ec72..9d62c4056 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts @@ -1,22 +1,40 @@ import { ElementRef, Inject, Injectable } from '@angular/core'; import { IHeaderElement, RotationTypes } from '@red/domain'; -import { HeaderElements } from '../shared/constants'; +import { HeaderElements, HeaderElementType } from '../shared/constants'; import { TranslateService } from '@ngx-translate/core'; import { PageRotationService } from './page-rotation.service'; import { BASE_HREF } from '../../../tokens'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { UserPreferenceService } from '@services/user-preference.service'; +import { PdfViewer } from './pdf-viewer.service'; @Injectable() export class ViewerHeaderConfigService { + private _divider: IHeaderElement = { + type: 'divider', + }; + private _buttons: Map; + private _config: Map = new Map([ + [HeaderElements.SHAPE_TOOL_GROUP_BUTTON, true], + [HeaderElements.ROTATE_LEFT_BUTTON, true], + [HeaderElements.ROTATE_RIGHT_BUTTON, true], + [HeaderElements.APPLY_ROTATION, true], + [HeaderElements.DISCARD_ROTATION, true], + [HeaderElements.TOGGLE_TOOLTIPS, true], + [HeaderElements.ANNOTATION_POPUP, true], + [HeaderElements.COMPARE_BUTTON, true], + [HeaderElements.CLOSE_COMPARE_BUTTON, false], + ]); + constructor( @Inject(BASE_HREF) private readonly _baseHref: string, private readonly _translateService: TranslateService, private readonly _pageRotationService: PageRotationService, private readonly _userPreferenceService: UserPreferenceService, + private readonly _pdfViewer: PdfViewer, ) {} - get applyRotation(): IHeaderElement { + private get _applyRotation(): IHeaderElement { return { type: 'customElement', dataElement: HeaderElements.APPLY_ROTATION, @@ -38,7 +56,7 @@ export class ViewerHeaderConfigService { }; } - get discardRotation(): IHeaderElement { + private get _discardRotation(): IHeaderElement { return { type: 'customElement', dataElement: HeaderElements.DISCARD_ROTATION, @@ -60,13 +78,7 @@ export class ViewerHeaderConfigService { }; } - get divider(): IHeaderElement { - return { - type: 'divider', - }; - } - - get rectangle(): IHeaderElement { + private get _rectangle(): IHeaderElement { return { type: 'toolGroupButton', toolGroup: 'rectangleTools', @@ -76,7 +88,7 @@ export class ViewerHeaderConfigService { }; } - get rotateLeft(): IHeaderElement { + private get _rotateLeft(): IHeaderElement { return { type: 'actionButton', element: 'tooltips', @@ -86,7 +98,7 @@ export class ViewerHeaderConfigService { }; } - get rotateRight(): IHeaderElement { + private get _rotateRight(): IHeaderElement { return { type: 'actionButton', element: 'tooltips', @@ -110,7 +122,39 @@ export class ViewerHeaderConfigService { ); } - toggleTooltips(toggleTooltips: (title: string, img: string) => Promise): IHeaderElement { + initialize( + toggleTooltips: (title: string, img: string) => Promise, + compareFileInput: ElementRef, + closeCompareMode: () => Promise, + ): void { + if (this._buttons) { + console.error('ERROR: ViewerHeaderConfigService can only be initialized once!'); + return; + } + + this._buttons = new Map([ + [HeaderElements.SHAPE_TOOL_GROUP_BUTTON, this._rectangle], + [HeaderElements.ROTATE_LEFT_BUTTON, this._rotateLeft], + [HeaderElements.ROTATE_RIGHT_BUTTON, this._rotateRight], + [HeaderElements.APPLY_ROTATION, this._applyRotation], + [HeaderElements.DISCARD_ROTATION, this._discardRotation], + [HeaderElements.TOGGLE_TOOLTIPS, this._toggleTooltips(toggleTooltips)], + [HeaderElements.COMPARE_BUTTON, this._compare(compareFileInput)], + [HeaderElements.CLOSE_COMPARE_BUTTON, this._closeCompare(closeCompareMode)], + ]); + + this._updateElements(); + } + + enable(elements: HeaderElementType[]): void { + this._updateState(elements, true); + } + + disable(elements: HeaderElementType[]): void { + this._updateState(elements, false); + } + + private _toggleTooltips(toggleTooltips: (title: string, img: string) => Promise): IHeaderElement { return { type: 'actionButton', element: 'tooltips', @@ -123,7 +167,7 @@ export class ViewerHeaderConfigService { }; } - closeCompare(closeCompareMode: () => Promise): IHeaderElement { + private _closeCompare(closeCompareMode: () => Promise): IHeaderElement { return { type: 'actionButton', element: 'closeCompare', @@ -136,7 +180,7 @@ export class ViewerHeaderConfigService { }; } - compare(compareFileInput: ElementRef): IHeaderElement { + private _compare(compareFileInput: ElementRef): IHeaderElement { return { type: 'actionButton', element: 'compare', @@ -147,6 +191,42 @@ export class ViewerHeaderConfigService { }; } + private _pushGroup(items: IHeaderElement[], group: HeaderElementType[]): void { + const enabledItems = group.filter(item => this._isEnabled(item)); + if (enabledItems.length) { + items.push(this._divider); + enabledItems.forEach(item => items.push(this._buttons.get(item))); + } + } + + private _updateElements(): void { + this._pdfViewer.instance.UI.setHeaderItems(header => { + const enabledItems: IHeaderElement[] = []; + const groups: HeaderElementType[][] = [ + [HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON], + [HeaderElements.TOGGLE_TOOLTIPS], + [HeaderElements.SHAPE_TOOL_GROUP_BUTTON], + [ + HeaderElements.ROTATE_LEFT_BUTTON, + HeaderElements.ROTATE_RIGHT_BUTTON, + HeaderElements.APPLY_ROTATION, + HeaderElements.DISCARD_ROTATION, + ], + ]; + groups.forEach(group => this._pushGroup(enabledItems, group)); + header.getItems().splice(8, header.getItems().length - 13, ...enabledItems); + }); + } + + private _updateState(elements: HeaderElementType[], value: boolean): void { + elements.forEach(element => this._config.set(element, value)); + this._updateElements(); + } + + private _isEnabled(key: HeaderElementType): boolean { + return this._config.get(key); + } + private _convertPath(path: string): string { return this._baseHref + path; } diff --git a/apps/red-ui/src/app/modules/file-preview/shared/constants.ts b/apps/red-ui/src/app/modules/file-preview/shared/constants.ts index b1da445d7..2826adb84 100644 --- a/apps/red-ui/src/app/modules/file-preview/shared/constants.ts +++ b/apps/red-ui/src/app/modules/file-preview/shared/constants.ts @@ -2,16 +2,27 @@ export const ALLOWED_KEYBOARD_SHORTCUTS: readonly string[] = ['+', '-', 'p', 'r' export const ALL_HOTKEYS = ['Escape', 'F', 'f', 'ArrowUp', 'ArrowDown']; -export const HeaderElements = { - SHAPE_TOOL_GROUP_BUTTON: 'shapeToolGroupButton', - ROTATE_LEFT_BUTTON: 'rotateLeftButton', - ROTATE_RIGHT_BUTTON: 'rotateRightButton', - APPLY_ROTATION: 'applyRotation', - DISCARD_ROTATION: 'discardRotation', - TOGGLE_TOOLTIPS: 'toggle-tooltips', - ANNOTATION_POPUP: 'annotationPopup', - COMPARE_BUTTON: 'compareButton', - CLOSE_COMPARE_BUTTON: 'closeCompareButton', +export type HeaderElementType = + | 'SHAPE_TOOL_GROUP_BUTTON' + | 'ROTATE_LEFT_BUTTON' + | 'ROTATE_RIGHT_BUTTON' + | 'APPLY_ROTATION' + | 'DISCARD_ROTATION' + | 'TOGGLE_TOOLTIPS' + | 'ANNOTATION_POPUP' + | 'COMPARE_BUTTON' + | 'CLOSE_COMPARE_BUTTON'; + +export const HeaderElements: Record = { + 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', + ANNOTATION_POPUP: 'ANNOTATION_POPUP', + COMPARE_BUTTON: 'COMPARE_BUTTON', + CLOSE_COMPARE_BUTTON: 'CLOSE_COMPARE_BUTTON', } as const; export const TextPopups = { diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index d8966dc0b..684210fa7 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dev-05.iqser.cloud/redaction-gateway-v1", + "API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1", "APP_NAME": "RedactManager", "AUTO_READ_TIME": 3, "BACKEND_APP_VERSION": "4.4.40", @@ -17,7 +17,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dev-05.iqser.cloud/auth/realms/redaction", + "OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview"