From 584a6b7bd0b30e94de52bcd88a5cd545fedab9a8 Mon Sep 17 00:00:00 2001 From: Nicoleta Panaghiu Date: Fri, 29 Nov 2024 13:21:47 +0200 Subject: [PATCH] RED-10563: fixed key actions not prevented when input is focused. Also updated config.json with documine stack and properties. --- .../annotations-list.component.ts | 4 ++-- .../file-header/file-header.component.ts | 23 +++++++++++-------- .../file-workload/file-workload.component.ts | 17 ++++++-------- .../services/document-viewer.service.ts | 5 ++-- apps/red-ui/src/app/utils/functions.ts | 10 +++++++- apps/red-ui/src/assets/config/config.json | 10 ++++---- 6 files changed, 39 insertions(+), 30 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts index 7535542c1..ec6e8a67f 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.ts @@ -1,7 +1,6 @@ import { Component, computed, ElementRef, EventEmitter, Input, Output } from '@angular/core'; import { getConfig, HasScrollbarDirective } from '@iqser/common-ui'; import { FilterService } from '@iqser/common-ui/lib/filtering'; -import { IqserEventTarget } from '@iqser/common-ui/lib/utils'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ListItem } from '@models/file/list-item'; import { EarmarkGroup } from '@red/domain'; @@ -15,6 +14,7 @@ import { NgForOf, NgIf } from '@angular/common'; import { HighlightsSeparatorComponent } from '../highlights-separator/highlights-separator.component'; import { AnnotationWrapperComponent } from '../annotation-wrapper/annotation-wrapper.component'; import { AnnotationReferencesListComponent } from '../annotation-references-list/annotation-references-list.component'; +import { isTargetInput } from '@utils/functions'; @Component({ selector: 'redaction-annotations-list', @@ -52,7 +52,7 @@ export class AnnotationsListComponent extends HasScrollbarDirective { console.log('Selected Annotation:', annotation); } - if (($event?.target as IqserEventTarget)?.localName === 'input') { + if (isTargetInput($event)) { return; } diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-header/file-header.component.ts b/apps/red-ui/src/app/modules/file-preview/components/file-header/file-header.component.ts index c62b29a40..bb4076329 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-header/file-header.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/file-header/file-header.component.ts @@ -4,7 +4,6 @@ import { Component, computed, ElementRef, - HostListener, Input, NgZone, OnDestroy, @@ -19,7 +18,6 @@ import { getConfig, HelpModeService, IqserAllowDirective, - IqserDialog, IqserPermissionsService, isIqserDevMode, LoadingService, @@ -51,6 +49,7 @@ import { ALL_HOTKEYS } from '../../utils/constants'; import { AnnotationDrawService } from '../../../pdf-viewer/services/annotation-draw.service'; import { FileManagementService } from '@services/files/file-management.service'; import { MatDialog } from '@angular/material/dialog'; +import { isTargetInput, isTargetTextArea } from '@utils/functions'; @Component({ selector: 'redaction-file-header', @@ -105,6 +104,7 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD ngOnInit() { document.documentElement.addEventListener('fullscreenchange', this.fullscreenListener); + this._pdf.instance.UI.iframeWindow.addEventListener('keyup', this.handleKeyEvent); } ngAfterViewInit() { @@ -116,10 +116,12 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD ngOnDetach() { document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener); + this._pdf.instance.UI.iframeWindow.removeEventListener('keyup', this.handleKeyEvent); } ngOnDestroy() { document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener); + this._pdf.instance.UI.iframeWindow.removeEventListener('keyup', this.handleKeyEvent); } async downloadOriginalFile({ cacheIdentifier, dossierId, fileId, filename }: File) { @@ -177,7 +179,7 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD } } - @HostListener('document:keyup', ['$event']) + @Bind() handleKeyEvent($event: KeyboardEvent) { if (this._router.url.indexOf('/file/') < 0) { return; @@ -208,19 +210,20 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD this._changeRef.markForCheck(); } + if ($event.key === 'F5') { + window.location.reload(); + } + + if (isTargetInput($event) || isTargetTextArea($event)) { + return; + } + if (!$event.ctrlKey && !$event.metaKey && ['f', 'F'].includes($event.key)) { - // if you type in an input, don't toggle full-screen - if ($event.target instanceof HTMLInputElement || $event.target instanceof HTMLTextAreaElement) { - return; - } this.toggleFullScreen(); return; } if (['h', 'H'].includes($event.key)) { - if ($event.target instanceof HTMLInputElement || $event.target instanceof HTMLTextAreaElement) { - return; - } this._ngZone.run(() => { window.focus(); this._helpModeService.activateHelpMode(false); diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts index 6ccf8e4c7..a7e16001d 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts @@ -27,7 +27,7 @@ import { PreventDefaultDirective, } from '@iqser/common-ui'; import { FilterService, INestedFilter, PopupFilterComponent } from '@iqser/common-ui/lib/filtering'; -import { AutoUnsubscribe, Debounce, IqserEventTarget } from '@iqser/common-ui/lib/utils'; +import { AutoUnsubscribe, Debounce } from '@iqser/common-ui/lib/utils'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ListItem } from '@models/file/list-item'; import { TranslateModule } from '@ngx-translate/core'; @@ -57,6 +57,7 @@ import { PageExclusionComponent } from '../page-exclusion/page-exclusion.compone import { PagesComponent } from '../pages/pages.component'; import { ReadonlyBannerComponent } from '../readonly-banner/readonly-banner.component'; import { DocumentInfoComponent } from '../document-info/document-info.component'; +import { isTargetInput } from '@utils/functions'; const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape']; const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; @@ -89,10 +90,7 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; ], }) export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, OnDestroy { - private readonly _annotationsElement = viewChild('annotationsElement'); - private readonly _quickNavigationElement = viewChild('quickNavigation'); readonly multiSelectTemplate = viewChild>('multiSelect'); - readonly #isIqserDevMode = this._userPreferenceService.isIqserDevMode; protected readonly iconButtonTypes = IconButtonTypes; protected readonly circleButtonTypes = CircleButtonTypes; protected readonly displayedAnnotations$: Observable[]>>; @@ -106,6 +104,9 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On protected displayedPages: number[] = []; protected pagesPanelActive = true; protected enabledFilters = []; + private readonly _annotationsElement = viewChild('annotationsElement'); + private readonly _quickNavigationElement = viewChild('quickNavigation'); + readonly #isIqserDevMode = this._userPreferenceService.isIqserDevMode; #displayedPagesChanged = false; constructor( @@ -245,11 +246,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On @HostListener('window:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent): void { - if ( - !ALL_HOTKEY_ARRAY.includes($event.key) || - this._dialog.openDialogs.length || - ($event.target as IqserEventTarget).localName === 'input' - ) { + if (!ALL_HOTKEY_ARRAY.includes($event.key) || this._dialog.openDialogs.length || isTargetInput($event)) { return; } @@ -331,7 +328,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On } preventKeyDefault($event: KeyboardEvent): void { - if (COMMAND_KEY_ARRAY.includes($event.key) && !(($event.target as any).localName === 'input')) { + if (COMMAND_KEY_ARRAY.includes($event.key) && !isTargetInput($event)) { $event.preventDefault(); } } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts index fc85b35ce..a836c6a2f 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts @@ -14,6 +14,7 @@ import { PdfViewer } from './pdf-viewer.service'; import Color = Core.Annotations.Color; import DocumentViewer = Core.DocumentViewer; import Quad = Core.Math.Quad; +import { isTargetInput } from '@utils/functions'; @Injectable() export class REDDocumentViewer { @@ -71,12 +72,12 @@ export class REDDocumentViewer { return fromEvent(this.#document, 'keyUp').pipe( tap(stopAndPreventIfNotAllowed), filter($event => { - if (($event.target as HTMLElement)?.tagName?.toLowerCase() === 'input') { + if (isTargetInput($event)) { if ($event.key === 'Escape') { return true; } } - return ($event.target as HTMLElement)?.tagName?.toLowerCase() !== 'input'; + return isTargetInput($event); }), filter($event => $event.key.startsWith('Arrow') || ['f', 'h', 'H', 'Escape'].includes($event.key)), tap(stopAndPrevent), diff --git a/apps/red-ui/src/app/utils/functions.ts b/apps/red-ui/src/app/utils/functions.ts index 0aca86784..e06f64098 100644 --- a/apps/red-ui/src/app/utils/functions.ts +++ b/apps/red-ui/src/app/utils/functions.ts @@ -1,5 +1,5 @@ import { ITrackable } from '@iqser/common-ui'; -import type { List } from '@iqser/common-ui/lib/utils'; +import type { IqserEventTarget, List } from '@iqser/common-ui/lib/utils'; import type { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { Dayjs } from 'dayjs'; @@ -143,3 +143,11 @@ export function urlFileId() { const fileId = splitUrl[splitUrl.length - 1]; return fileId.split('?')[0]; } + +export function isTargetInput(event: Event) { + return (event?.target as IqserEventTarget)?.localName === 'input'; +} + +export function isTargetTextArea(event: Event) { + return (event?.target as IqserEventTarget)?.localName === 'textarea'; +} diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index 5f6c0ce6e..2ccc6f6d1 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,9 +1,9 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dan2.iqser.cloud", + "API_URL": "https://frontend2.iqser.cloud", "APP_NAME": "RedactManager", - "IS_DOCUMINE": false, + "IS_DOCUMINE": true, "RULE_EDITOR_DEV_ONLY": false, "AUTO_READ_TIME": 3, "BACKEND_APP_VERSION": "4.4.40", @@ -13,13 +13,13 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dan2.iqser.cloud/auth", + "OAUTH_URL": "https://frontend2.iqser.cloud/auth", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview", "ANNOTATIONS_THRESHOLD": 1000, - "THEME": "redact", - "BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/redact/", + "THEME": "scm", + "BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/scm/", "AVAILABLE_NOTIFICATIONS_DAYS": 30, "AVAILABLE_OLD_NOTIFICATIONS_MINUTES": 60, "NOTIFICATIONS_THRESHOLD": 1000,