From 8af6eb31afd237416bc2ccaa84a81b5f1ae790d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Thu, 24 Mar 2022 18:03:38 +0200 Subject: [PATCH 1/2] Viewer header config service initial --- .../pdf-viewer/pdf-viewer.component.ts | 147 ++++------------- .../file-preview/file-preview-providers.ts | 2 + .../services/viewer-header-config.service.ts | 153 ++++++++++++++++++ 3 files changed, 184 insertions(+), 118 deletions(-) create mode 100644 apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts 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 757c15cdb..66ad47926 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 @@ -11,7 +11,7 @@ import { SimpleChanges, ViewChild, } from '@angular/core'; -import { Dossier, File, IHeaderElement, IManualRedactionEntry, RotationTypes } from '@red/domain'; +import { Dossier, File, IHeaderElement, IManualRedactionEntry } from '@red/domain'; import { Core, WebViewerInstance } from '@pdftron/webviewer'; import { TranslateService } from '@ngx-translate/core'; import { @@ -43,17 +43,11 @@ import { FilePreviewDialogService } from '../../services/file-preview-dialog.ser import { loadCompareDocumentWrapper } from '../../../dossier/utils/compare-mode.utils'; import { from, fromEvent } from 'rxjs'; import { FileDataService } from '../../services/file-data.service'; +import { ViewerHeaderConfigService } from '../../services/viewer-header-config.service'; import Tools = Core.Tools; import TextTool = Tools.TextTool; import Annotation = Core.Annotations.Annotation; -function getDivider(hiddenOn?: readonly ('desktop' | 'mobile' | 'tablet')[]) { - return { - type: 'divider', - hidden: hiddenOn, - }; -} - @Component({ selector: 'redaction-pdf-viewer', templateUrl: './pdf-viewer.component.html', @@ -89,6 +83,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha private readonly _fileManagementService: FileManagementService, private readonly _pageRotationService: PageRotationService, private readonly _fileDataService: FileDataService, + private readonly _headerConfigService: ViewerHeaderConfigService, readonly stateService: FilePreviewStateService, readonly viewModeService: ViewModeService, readonly multiSelectService: MultiSelectService, @@ -97,20 +92,6 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha super(); } - private get _toggleTooltipsBtnTitle(): string { - return this._translateService.instant(_('pdf-viewer.toggle-tooltips'), { - active: this._userPreferenceService.getFilePreviewTooltipsPreference(), - }); - } - - private get _toggleTooltipsIcon(): string { - return this._convertPath( - this._userPreferenceService.getFilePreviewTooltipsPreference() - ? '/assets/icons/general/pdftron-action-enable-tooltips.svg' - : '/assets/icons/general/pdftron-action-disable-tooltips.svg', - ); - } - async ngOnInit() { this._setReadyAndInitialState = this._setReadyAndInitialState.bind(this); await this._loadViewer(); @@ -200,7 +181,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha fileReader.readAsArrayBuffer(fileToCompare); } - async closeCompareMode() { + private async _closeCompareMode() { this.viewModeService.compareMode = false; const pdfNet = this.instance.Core.PDFNet; await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null); @@ -333,6 +314,12 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha } } + private async _toggleTooltips(title: string, img: string): Promise { + await this._userPreferenceService.toggleFilePreviewTooltipsPreference(); + this._updateTooltipsVisibility(); + this.instance.UI.updateElement(HeaderElements.TOGGLE_TOOLTIPS, { title, img }); + } + private _configureElements() { this.instance.UI.disableElements([ 'pageNavOverlay', @@ -357,107 +344,31 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha 'annotationGroupButton', ]); - const applyRotation: IHeaderElement = { - type: 'customElement', - dataElement: HeaderElements.APPLY_ROTATION, - render: () => { - const paragraph = document.createElement('p'); - paragraph.innerText = this._translateService.instant('page-rotation.apply'); - paragraph.style.cssText = ` - font-size: 11px; - font-weight: 600; - color: #DD4D50; - cursor: pointer; - margin: 0 12px; - `; - paragraph.addEventListener('click', async () => { - await this._pageRotationService.applyRotation(); - }); - return paragraph; - }, - }; - const discardRotation: IHeaderElement = { - type: 'customElement', - dataElement: HeaderElements.DISCARD_ROTATION, - render: () => { - const paragraph = document.createElement('p'); - paragraph.innerText = this._translateService.instant('page-rotation.discard'); - paragraph.style.cssText = ` - font-size: 11px; - font-weight: 600; - color: #283241; - cursor: pointer; - opacity: 0.7; - `; - paragraph.addEventListener('click', () => { - this._pageRotationService.discardRotation(); - }); - return paragraph; - }, - }; + 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) => { + 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 divider = getDivider(); const headerItems: IHeaderElement[] = [ divider, - { - type: 'actionButton', - element: 'compare', - dataElement: HeaderElements.COMPARE_BUTTON, - img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'), - title: 'Compare', - onClick: () => { - this.compareFileInput.nativeElement.click(); - }, - }, - { - type: 'actionButton', - element: 'closeCompare', - dataElement: HeaderElements.CLOSE_COMPARE_BUTTON, - img: this._convertPath('/assets/icons/general/pdftron-action-close-compare.svg'), - title: 'Leave Compare Mode', - onClick: async () => { - await this.closeCompareMode(); - }, - }, + compare, + closeCompare, divider, - { - type: 'actionButton', - element: 'tooltips', - dataElement: HeaderElements.TOGGLE_TOOLTIPS, - img: this._toggleTooltipsIcon, - title: this._toggleTooltipsBtnTitle, - onClick: async () => { - await this._userPreferenceService.toggleFilePreviewTooltipsPreference(); - this._updateTooltipsVisibility(); - this.instance.UI.updateElement(HeaderElements.TOGGLE_TOOLTIPS, { - title: this._toggleTooltipsBtnTitle, - img: this._toggleTooltipsIcon, - }); - }, - }, + toggleTooltips, divider, - { - type: 'toolGroupButton', - toolGroup: 'rectangleTools', - dataElement: HeaderElements.SHAPE_TOOL_GROUP_BUTTON, - img: this._convertPath('/assets/icons/general/rectangle.svg'), - title: 'annotation.rectangle', - }, + rectangle, divider, - { - type: 'actionButton', - element: 'tooltips', - dataElement: HeaderElements.ROTATE_LEFT_BUTTON, - img: this._convertPath('/assets/icons/general/rotate-left.svg'), - onClick: () => this._pageRotationService.addRotation(RotationTypes.LEFT), - }, - { - type: 'actionButton', - element: 'tooltips', - dataElement: HeaderElements.ROTATE_RIGHT_BUTTON, - img: this._convertPath('/assets/icons/general/rotate-right.svg'), - onClick: () => this._pageRotationService.addRotation(RotationTypes.RIGHT), - }, + rotateLeft, + rotateRight, applyRotation, discardRotation, divider, diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts index 98c44dc3e..cc630ae8a 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts @@ -14,6 +14,7 @@ import { dossiersServiceProvider } from '@services/entity-services/dossiers.serv import { PageRotationService } from './services/page-rotation.service'; import { PdfViewer } from './services/pdf-viewer.service'; import { FileDataService } from './services/file-data.service'; +import { ViewerHeaderConfigService } from './services/viewer-header-config.service'; export const filePreviewScreenProviders = [ FilterService, @@ -32,4 +33,5 @@ export const filePreviewScreenProviders = [ AnnotationProcessingService, FileDataService, dossiersServiceProvider, + ViewerHeaderConfigService, ]; 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 new file mode 100644 index 000000000..38bf0ec72 --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/services/viewer-header-config.service.ts @@ -0,0 +1,153 @@ +import { ElementRef, Inject, Injectable } from '@angular/core'; +import { IHeaderElement, RotationTypes } from '@red/domain'; +import { HeaderElements } 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'; + +@Injectable() +export class ViewerHeaderConfigService { + constructor( + @Inject(BASE_HREF) private readonly _baseHref: string, + private readonly _translateService: TranslateService, + private readonly _pageRotationService: PageRotationService, + private readonly _userPreferenceService: UserPreferenceService, + ) {} + + get applyRotation(): IHeaderElement { + return { + type: 'customElement', + dataElement: HeaderElements.APPLY_ROTATION, + render: () => { + const paragraph = document.createElement('p'); + paragraph.innerText = this._translateService.instant('page-rotation.apply'); + paragraph.style.cssText = ` + font-size: 11px; + font-weight: 600; + color: #DD4D50; + cursor: pointer; + margin: 0 12px; + `; + paragraph.addEventListener('click', async () => { + await this._pageRotationService.applyRotation(); + }); + return paragraph; + }, + }; + } + + get discardRotation(): IHeaderElement { + return { + type: 'customElement', + dataElement: HeaderElements.DISCARD_ROTATION, + render: () => { + const paragraph = document.createElement('p'); + paragraph.innerText = this._translateService.instant('page-rotation.discard'); + paragraph.style.cssText = ` + font-size: 11px; + font-weight: 600; + color: #283241; + cursor: pointer; + opacity: 0.7; + `; + paragraph.addEventListener('click', () => { + this._pageRotationService.discardRotation(); + }); + return paragraph; + }, + }; + } + + get divider(): IHeaderElement { + return { + type: 'divider', + }; + } + + get rectangle(): IHeaderElement { + return { + type: 'toolGroupButton', + toolGroup: 'rectangleTools', + dataElement: HeaderElements.SHAPE_TOOL_GROUP_BUTTON, + img: this._convertPath('/assets/icons/general/rectangle.svg'), + title: 'annotation.rectangle', + }; + } + + get rotateLeft(): IHeaderElement { + return { + type: 'actionButton', + element: 'tooltips', + dataElement: HeaderElements.ROTATE_LEFT_BUTTON, + img: this._convertPath('/assets/icons/general/rotate-left.svg'), + onClick: () => this._pageRotationService.addRotation(RotationTypes.LEFT), + }; + } + + get rotateRight(): IHeaderElement { + return { + type: 'actionButton', + element: 'tooltips', + dataElement: HeaderElements.ROTATE_RIGHT_BUTTON, + img: this._convertPath('/assets/icons/general/rotate-right.svg'), + onClick: () => this._pageRotationService.addRotation(RotationTypes.RIGHT), + }; + } + + private get _toggleTooltipsBtnTitle(): string { + return this._translateService.instant(_('pdf-viewer.toggle-tooltips'), { + active: this._userPreferenceService.getFilePreviewTooltipsPreference(), + }); + } + + private get _toggleTooltipsBtnIcon(): string { + return this._convertPath( + this._userPreferenceService.getFilePreviewTooltipsPreference() + ? '/assets/icons/general/pdftron-action-enable-tooltips.svg' + : '/assets/icons/general/pdftron-action-disable-tooltips.svg', + ); + } + + toggleTooltips(toggleTooltips: (title: string, img: string) => Promise): IHeaderElement { + return { + type: 'actionButton', + element: 'tooltips', + dataElement: HeaderElements.TOGGLE_TOOLTIPS, + img: this._toggleTooltipsBtnIcon, + title: this._toggleTooltipsBtnTitle, + onClick: async () => { + await toggleTooltips(this._toggleTooltipsBtnTitle, this._toggleTooltipsBtnIcon); + }, + }; + } + + closeCompare(closeCompareMode: () => Promise): IHeaderElement { + return { + type: 'actionButton', + element: 'closeCompare', + dataElement: HeaderElements.CLOSE_COMPARE_BUTTON, + img: this._convertPath('/assets/icons/general/pdftron-action-close-compare.svg'), + title: 'Leave Compare Mode', + onClick: async () => { + await closeCompareMode(); + }, + }; + } + + compare(compareFileInput: ElementRef): IHeaderElement { + return { + type: 'actionButton', + element: 'compare', + dataElement: HeaderElements.COMPARE_BUTTON, + img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'), + title: 'Compare', + onClick: () => compareFileInput.nativeElement.click(), + }; + } + + private _convertPath(path: string): string { + return this._baseHref + path; + } +} 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 2/2] 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"