diff --git a/src/assets/styles/common-dialogs.scss b/src/assets/styles/common-dialogs.scss index 1d6746c..7550eb8 100644 --- a/src/assets/styles/common-dialogs.scss +++ b/src/assets/styles/common-dialogs.scss @@ -34,8 +34,12 @@ display: flex; - > * { + > *:not(iqser-help-button) { margin-right: 16px; } } + + .dialog-actions iqser-help-button{ + margin-left: auto; + } } diff --git a/src/assets/styles/common-help-mode.scss b/src/assets/styles/common-help-mode.scss index 9f7a7b8..95b824f 100644 --- a/src/assets/styles/common-help-mode.scss +++ b/src/assets/styles/common-help-mode.scss @@ -1,5 +1,5 @@ .help-mode { - z-index: 10; + z-index: 1100; position: absolute; transition: all 0.25s; } diff --git a/src/lib/buttons/buttons.module.ts b/src/lib/buttons/buttons.module.ts index 1e71c60..3a0ed3f 100644 --- a/src/lib/buttons/buttons.module.ts +++ b/src/lib/buttons/buttons.module.ts @@ -7,9 +7,10 @@ import { ChevronButtonComponent } from './chevron-button/chevron-button.componen import { CircleButtonComponent } from './circle-button/circle-button.component'; import { IconButtonComponent } from './icon-button/icon-button.component'; import { IqserIconsModule } from '../icons'; +import { HelpButtonComponent } from './help-button/help-button.component'; const matModules = [MatButtonModule, MatTooltipModule]; -const components = [ChevronButtonComponent, CircleButtonComponent, IconButtonComponent]; +const components = [ChevronButtonComponent, CircleButtonComponent, IconButtonComponent, HelpButtonComponent]; @NgModule({ declarations: [...components], diff --git a/src/lib/buttons/help-button/help-button.component.html b/src/lib/buttons/help-button/help-button.component.html new file mode 100644 index 0000000..d0b79a1 --- /dev/null +++ b/src/lib/buttons/help-button/help-button.component.html @@ -0,0 +1,14 @@ + + diff --git a/src/lib/buttons/help-button/help-button.component.scss b/src/lib/buttons/help-button/help-button.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/lib/buttons/help-button/help-button.component.ts b/src/lib/buttons/help-button/help-button.component.ts new file mode 100644 index 0000000..55ab46f --- /dev/null +++ b/src/lib/buttons/help-button/help-button.component.ts @@ -0,0 +1,13 @@ +import { Component, Input } from '@angular/core'; +import { HelpModeService } from '@iqser/common-ui'; + +@Component({ + selector: 'iqser-help-button', + templateUrl: './help-button.component.html', + styleUrls: ['./help-button.component.scss'], +}) +export class HelpButtonComponent { + @Input() dialogButton = true; + + constructor(readonly helpModeService: HelpModeService) {} +} diff --git a/src/lib/buttons/icon-button/icon-button.component.html b/src/lib/buttons/icon-button/icon-button.component.html index 56a12c5..cc09847 100644 --- a/src/lib/buttons/icon-button/icon-button.component.html +++ b/src/lib/buttons/icon-button/icon-button.component.html @@ -4,6 +4,7 @@ [class.overlay]="showDot" [class.primary]="type === iconButtonTypes.primary" [class.show-bg]="type === iconButtonTypes.dark" + [class.help]="type === iconButtonTypes.help" [disabled]="disabled" mat-button type="button" diff --git a/src/lib/buttons/types/icon-button.type.ts b/src/lib/buttons/types/icon-button.type.ts index fb3b62d..f2af12d 100644 --- a/src/lib/buttons/types/icon-button.type.ts +++ b/src/lib/buttons/types/icon-button.type.ts @@ -2,6 +2,7 @@ export const IconButtonTypes = { default: 'default', dark: 'dark', primary: 'primary', + help: 'help', } as const; export type IconButtonType = keyof typeof IconButtonTypes; diff --git a/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.scss b/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.scss index 17dd08c..d0953d1 100644 --- a/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.scss +++ b/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.scss @@ -1,16 +1,16 @@ -section { + section { background: #ecedf0; display: flex; justify-content: center; -} -.content { - width: 440px; - display: flex; - flex-direction: column; - align-items: center; - text-align: center; - padding-top: 20px; - padding-bottom: 30px; - line-height: 18px; -} + .content { + width: 440px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding-top: 20px; + padding-bottom: 30px; + line-height: 18px; + } + } diff --git a/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.ts b/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.ts index a4aee63..92bd84c 100644 --- a/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.ts +++ b/src/lib/help-mode/help-mode-dialog/help-mode-dialog.component.ts @@ -1,8 +1,27 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; + +const HIGHER_CDK_OVERLAY_CONTAINER_ZINDEX = '1200'; +const DEFAULT_CDK_OVERLAY_CONTAINER_ZINDEX = '800'; @Component({ templateUrl: './help-mode-dialog.component.html', styleUrls: ['./help-mode-dialog.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class HelpModeDialogComponent {} +export class HelpModeDialogComponent implements OnInit, OnDestroy { + + ngOnInit(): void { + this._setCdkOverlayContainerZindex(HIGHER_CDK_OVERLAY_CONTAINER_ZINDEX); + } + + ngOnDestroy(): void { + this._setCdkOverlayContainerZindex(DEFAULT_CDK_OVERLAY_CONTAINER_ZINDEX); + } + + private _setCdkOverlayContainerZindex(zIndex: string): void { + const cdkOverlayContainer = document.querySelector('.cdk-overlay-container'); + if (cdkOverlayContainer) { + cdkOverlayContainer.style.zIndex = zIndex; + } + } +} diff --git a/src/lib/help-mode/help-mode.directive.ts b/src/lib/help-mode/help-mode.directive.ts index af3f122..10fc2d6 100644 --- a/src/lib/help-mode/help-mode.directive.ts +++ b/src/lib/help-mode/help-mode.directive.ts @@ -9,6 +9,7 @@ import { Router } from '@angular/router'; export class HelpModeDirective implements OnInit { @Input('iqserHelpMode') elementName!: string; @Input() scrollableParentView!: ScrollableParentView; + @Input() dialogElement = false; private _path: string; constructor( @@ -35,7 +36,8 @@ export class HelpModeDirective implements OnInit { this._renderer.setAttribute(helperElement, 'href', this._helpModeService.getDocsLink(this.elementName)); this._renderer.setAttribute(helperElement, 'target', '_blank'); this._renderer.addClass(helperElement, 'help-mode'); - this._helpModeService.addElement(helperElementName, element, helperElement, this.scrollableParentView); + + this._helpModeService.addElement(helperElementName, element, helperElement, this.scrollableParentView, 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 8172914..ba8304c 100644 --- a/src/lib/help-mode/help-mode.service.ts +++ b/src/lib/help-mode/help-mode.service.ts @@ -11,7 +11,7 @@ const SCROLL_BUTTONS_IDS = ['scroll-up', 'scroll-down']; export const ScrollableParentViews = { VIRTUAL_SCROLL: 'VIRTUAL_SCROLL', - ANNOTATIONS_LIST: 'ANNOTATIONS_LIST' + ANNOTATIONS_LIST: 'ANNOTATIONS_LIST', } as const; export type ScrollableParentView = keyof typeof ScrollableParentViews; @@ -20,6 +20,7 @@ interface Helper { readonly element: HTMLElement; readonly helperElement: HTMLElement; readonly scrollableParentView: ScrollableParentView; + readonly dialogElement: boolean; } @Injectable({ @@ -34,6 +35,8 @@ export class HelpModeService { private readonly _helperElements: Record = {}; private readonly _renderer: Renderer2; + private _dialogMode = false; + constructor( @Inject(HELP_DOCS) private readonly _docs: Record>, @Inject(MANUAL_BASE_URL) private readonly _manualBaseURL: string, @@ -69,11 +72,12 @@ export class HelpModeService { return this._docs[elementName] ? `${this._manualBaseURL}${this._docs[elementName][this._translateService.currentLang]}` : ''; } - activateHelpMode(): void { + activateHelpMode(dialogMode: boolean = false): void { if (!this.isHelpModeActive) { document.body.style.setProperty('overflow', 'hidden'); this._isHelpModeActive$.next(true); this.openHelpModeDialog(); + this._dialogMode = dialogMode; setTimeout(() => { this._enableHelperElements(); }); @@ -97,26 +101,32 @@ export class HelpModeService { }); } - addElement(helperElementName: string, element: HTMLElement, helperElement: HTMLElement, scrollableParentView: ScrollableParentView): void { - this._helperElements[helperElementName] = { element, helperElement, scrollableParentView }; + addElement( + helperElementName: string, + element: HTMLElement, + helperElement: HTMLElement, + scrollableParentView: ScrollableParentView, + dialogElement: boolean, + ): void { + this._helperElements[helperElementName] = { element, helperElement, scrollableParentView, dialogElement }; } updateHelperElements() { - Object.values(this._helperElements).forEach(({element, helperElement, scrollableParentView }) => { + Object.values(this._helperElements).forEach(({ element, helperElement, scrollableParentView }) => { this._updateHelperElement(element, helperElement, scrollableParentView); }); } private _isElementVisible(element: HTMLElement, scrollableParentView: ScrollableParentView): boolean { - const elementRect = element.getBoundingClientRect(); + let elementRect: DOMRect = element.getBoundingClientRect(); if (elementRect.top === 0 && elementRect.left === 0 && elementRect.bottom === 0 && elementRect.bottom === 0) { return false; } if (scrollableParentView) { const scrollableElementId = scrollableParentView === ScrollableParentViews.VIRTUAL_SCROLL ? VIRTUAL_SCROLL_ID : ANNOTATIONS_LIST_ID; - const scrollableElement: any = document.getElementById(scrollableElementId); + const scrollableElement: HTMLElement = document.getElementById(scrollableElementId); if (!scrollableElement) { return false; @@ -133,16 +143,16 @@ export class HelpModeService { if (scrollableParentView === ScrollableParentViews.VIRTUAL_SCROLL) { for (const id of SCROLL_BUTTONS_IDS) { - const scroll: any = document.getElementById(id); + const scroll: HTMLElement = document.getElementById(id); - const elementRect = element.getBoundingClientRect(); - const scrollRect = scroll.getBoundingClientRect(); + elementRect = element.getBoundingClientRect(); + const scrollRect = scroll?.getBoundingClientRect(); - if(elementRect.top + elementRect.height > scrollRect.top + if (elementRect.top + elementRect.height > scrollRect.top && elementRect.left + elementRect.width > scrollRect.left && elementRect.bottom - elementRect.height < scrollRect.bottom && elementRect.right - elementRect.width < scrollRect.right) { - return false + return false; } } } @@ -160,17 +170,19 @@ export class HelpModeService { width:${dimensions.width}px; height:${dimensions.height}px; `; - helperElement.classList.add('help-mode') + helperElement.classList.add('help-mode'); } else { - helperElement.classList.remove('help-mode') + helperElement.classList.remove('help-mode'); } } private _enableHelperElements() { - Object.values(this._helperElements).forEach(({ element, helperElement, scrollableParentView }) => { - document.body.appendChild(helperElement) - this._updateHelperElement(element, helperElement, scrollableParentView); + Object.values(this._helperElements).forEach(({ element, helperElement, scrollableParentView, dialogElement }) => { + if (this._dialogMode === dialogElement ) { + document.body.appendChild(helperElement); + this._updateHelperElement(element, helperElement, scrollableParentView); + } }); } diff --git a/src/lib/help-mode/help-mode/help-mode.component.html b/src/lib/help-mode/help-mode/help-mode.component.html index 8cbab9b..0c15be4 100644 --- a/src/lib/help-mode/help-mode/help-mode.component.html +++ b/src/lib/help-mode/help-mode/help-mode.component.html @@ -1,12 +1,12 @@ - {{ 'help-mode.text' | translate }} + {{ 'help-mode.bottom-text' | translate }} {{ 'help-mode.instructions' | translate }} (esc) - + diff --git a/src/lib/help-mode/help-mode/help-mode.component.scss b/src/lib/help-mode/help-mode/help-mode.component.scss index 421d474..e73a56b 100644 --- a/src/lib/help-mode/help-mode/help-mode.component.scss +++ b/src/lib/help-mode/help-mode/help-mode.component.scss @@ -42,7 +42,7 @@ border-right: 8px solid var(--iqser-helpmode-primary); border-top: 8px solid var(--iqser-helpmode-primary); border-bottom: 60px solid var(--iqser-helpmode-primary); - z-index: 5; + z-index: 1000; position: absolute; display: flex; justify-content: center; diff --git a/src/lib/help-mode/help-mode/help-mode.component.ts b/src/lib/help-mode/help-mode/help-mode.component.ts index c9a189a..1fcd619 100644 --- a/src/lib/help-mode/help-mode/help-mode.component.ts +++ b/src/lib/help-mode/help-mode/help-mode.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core'; import { HelpModeService } from '../help-mode.service'; import { IqserEventTarget } from '../../utils'; +import { MatDialog } from '@angular/material/dialog'; @Component({ selector: 'iqser-help-mode', @@ -9,10 +10,11 @@ import { IqserEventTarget } from '../../utils'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class HelpModeComponent { - constructor(readonly helpModeService: HelpModeService) {} + constructor(private readonly _dialog: MatDialog, readonly helpModeService: HelpModeService) {} - @HostListener('document:keydown.escape') onEscKeydownHandler(): void { - if (!this.helpModeService.helpModeDialogIsOpened) { + @HostListener('document:keydown.escape', ['$event']) onEscKeydownHandler(event: KeyboardEvent): void { + if (!this.helpModeService.helpModeDialogIsOpened && this.helpModeService.isHelpModeActive) { + event?.stopPropagation(); this.helpModeService.deactivateHelpMode(); } } @@ -20,7 +22,8 @@ export class HelpModeComponent { @HostListener('document:keydown.h', ['$event']) onHKeydownHandler(event: KeyboardEvent): void { const node = (event.target as IqserEventTarget).localName; if (!this.helpModeService.isHelpModeActive && node !== 'input' && node !== 'textarea') { - this.helpModeService.activateHelpMode(); + const dialogMode = !!this._dialog.openDialogs.length; + this.helpModeService.activateHelpMode(dialogMode); } }
{{ 'help-mode.text' | translate }}
{{ 'help-mode.bottom-text' | translate }}