From be87af01477ef705491833fbbade5278af7fa4fe Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Tue, 6 Dec 2022 00:56:08 +0200 Subject: [PATCH] RED-5673 - Help mode links overlay the open user menu --- src/lib/help-mode/help-mode.directive.ts | 5 ++- src/lib/help-mode/help-mode.service.ts | 43 +++++++++++++++---- .../page-header/models/action-config.model.ts | 2 + .../page-header/page-header.component.html | 3 ++ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/lib/help-mode/help-mode.directive.ts b/src/lib/help-mode/help-mode.directive.ts index f8f7291..8274e22 100644 --- a/src/lib/help-mode/help-mode.directive.ts +++ b/src/lib/help-mode/help-mode.directive.ts @@ -1,5 +1,5 @@ import { Directive, ElementRef, Input, OnInit, Optional, Renderer2 } from '@angular/core'; -import { HelpModeService, ScrollableParentView } from './help-mode.service'; +import { HelpModeService, OverlappingElement, ScrollableParentView } from './help-mode.service'; @Directive({ selector: '[iqserHelpMode]', @@ -8,6 +8,7 @@ import { HelpModeService, ScrollableParentView } from './help-mode.service'; export class HelpModeDirective implements OnInit { @Input('iqserHelpMode') elementName!: string; @Input() scrollableParentView!: ScrollableParentView; + @Input() overlappingElement!: OverlappingElement; @Input() dialogElement = false; constructor( @@ -31,7 +32,7 @@ export class HelpModeDirective implements OnInit { this._renderer.setAttribute(helperElement, 'target', '_blank'); this._renderer.addClass(helperElement, 'help-mode'); - this._helpModeService.addElement(helperElementName, element, helperElement, this.scrollableParentView, this.dialogElement); + this._helpModeService.addElement(helperElementName, element, helperElement, this.scrollableParentView, this.overlappingElement, this.dialogElement); } private _generateId(): string { diff --git a/src/lib/help-mode/help-mode.service.ts b/src/lib/help-mode/help-mode.service.ts index 3606244..39edb1f 100644 --- a/src/lib/help-mode/help-mode.service.ts +++ b/src/lib/help-mode/help-mode.service.ts @@ -8,6 +8,7 @@ import { HelpDocs } from './help-docs'; const VIRTUAL_SCROLL_ID = 'virtual-scroll'; const ANNOTATIONS_LIST_ID = 'annotations-list'; +const USER_MENU_ID = 'user-menu-items'; const SCROLL_BUTTONS_IDS = ['scroll-up', 'scroll-down']; export const ScrollableParentViews = { @@ -17,11 +18,18 @@ export const ScrollableParentViews = { export type ScrollableParentView = keyof typeof ScrollableParentViews; +export const OverlappingElements = { + USER_MENU: 'USER_MENU' +} as const; + +export type OverlappingElement = keyof typeof OverlappingElements; + interface Helper { readonly element: HTMLElement; readonly helperElement: HTMLElement; readonly scrollableParentView: ScrollableParentView; - readonly dialogElement: boolean; + readonly overlappingElement: OverlappingElement; + readonly dialogElement?: boolean; } @Injectable() @@ -104,18 +112,19 @@ export class HelpModeService { element: HTMLElement, helperElement: HTMLElement, scrollableParentView: ScrollableParentView, + overlappingElement: OverlappingElement, dialogElement: boolean, ): void { - this._helperElements[helperElementName] = { element, helperElement, scrollableParentView, dialogElement }; + this._helperElements[helperElementName] = { element, helperElement, scrollableParentView, overlappingElement, dialogElement }; } updateHelperElements() { - Object.values(this._helperElements).forEach(({ element, helperElement, scrollableParentView }) => { - this._updateHelperElement(element, helperElement, scrollableParentView); + Object.values(this._helperElements).forEach(({ element, helperElement, scrollableParentView, overlappingElement }) => { + this._updateHelperElement(element, helperElement, scrollableParentView, overlappingElement); }); } - private _isElementVisible(element: HTMLElement, scrollableParentView: ScrollableParentView): boolean { + private _isElementVisible(element: HTMLElement, scrollableParentView: ScrollableParentView, overlappingElementName: OverlappingElement): boolean { let elementRect: DOMRect = element.getBoundingClientRect(); if (elementRect.top === 0 && elementRect.left === 0 && elementRect.bottom === 0 && elementRect.bottom === 0) { return false; @@ -162,11 +171,27 @@ export class HelpModeService { } } + if (overlappingElementName) { + const overlappingElement = document.getElementById(USER_MENU_ID); + + if (!overlappingElement) { + return true; + } + + const overlappingElementRect = overlappingElement.getBoundingClientRect(); + + return !( + Math.max(elementRect.left, overlappingElementRect.left) < Math.min(elementRect.right, overlappingElementRect.right) && + Math.max(elementRect.top, overlappingElementRect.top) < Math.min(elementRect.bottom, overlappingElementRect.bottom) + ); + + } + return true; } - private _updateHelperElement(element: HTMLElement, helperElement: HTMLElement, scrollableParentView: ScrollableParentView) { - if (this._isElementVisible(element, scrollableParentView)) { + private _updateHelperElement(element: HTMLElement, helperElement: HTMLElement, scrollableParentView: ScrollableParentView, overlappingElement: OverlappingElement) { + if (this._isElementVisible(element, scrollableParentView, overlappingElement)) { const dimensions = this._getElementDimensions(element); helperElement.style.cssText = ` top:${dimensions.y}px; @@ -181,10 +206,10 @@ export class HelpModeService { } private _enableHelperElements() { - Object.values(this._helperElements).forEach(({ element, helperElement, scrollableParentView, dialogElement }) => { + Object.values(this._helperElements).forEach(({ element, helperElement, scrollableParentView,overlappingElement, dialogElement }) => { if (this._dialogMode === dialogElement) { document.body.appendChild(helperElement); - this._updateHelperElement(element, helperElement, scrollableParentView); + this._updateHelperElement(element, helperElement, scrollableParentView, overlappingElement); } }); } diff --git a/src/lib/listing/page-header/models/action-config.model.ts b/src/lib/listing/page-header/models/action-config.model.ts index 96f869b..1f3b6d5 100644 --- a/src/lib/listing/page-header/models/action-config.model.ts +++ b/src/lib/listing/page-header/models/action-config.model.ts @@ -1,8 +1,10 @@ import { BaseHeaderConfig } from './base-config.model'; import { Observable } from 'rxjs'; +import { OverlappingElement } from '../../../help-mode'; export interface ActionConfig extends BaseHeaderConfig { readonly action: ($event: MouseEvent) => void; readonly helpModeKey?: string; + readonly overlappingElement?: OverlappingElement; readonly disabled$?: Observable; } diff --git a/src/lib/listing/page-header/page-header.component.html b/src/lib/listing/page-header/page-header.component.html index 942a874..318fa76 100644 --- a/src/lib/listing/page-header/page-header.component.html +++ b/src/lib/listing/page-header/page-header.component.html @@ -47,6 +47,7 @@ [icon]="config.icon" [id]="config.label.replace('.', '-')" [iqserHelpMode]="config.helpModeKey" + [overlappingElement]="config.overlappingElement" [label]="config.label | translate" [type]="config.type" > @@ -61,6 +62,7 @@ [icon]="config.icon" [id]="config.id" [iqserHelpMode]="config.helpModeKey" + [overlappingElement]="config.overlappingElement" [tooltipPosition]="'below'" [tooltip]="config.label" > @@ -75,6 +77,7 @@ [class.ml-6]="actionConfigs" [icon]="'iqser:close'" [iqserHelpMode]="'edit_dossier_in_dossier'" + [overlappingElement]="'USER_MENU'" [tooltipPosition]="'below'" [tooltip]="'common.close' | translate" >