import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'; import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { TranslateService } from '@ngx-translate/core'; import { BehaviorSubject } from 'rxjs'; import { HelpModeDialogComponent } from './help-mode-dialog/help-mode-dialog.component'; import { HELP_DOCS } from './tokens'; interface Helper { readonly element: HTMLElement; readonly helperElement: HTMLElement; } @Injectable() export class HelpModeService { private readonly _isHelpModeActive$ = new BehaviorSubject(false); readonly isHelpModeActive$ = this._isHelpModeActive$.asObservable(); private readonly _helpModeDialogIsOpened$ = new BehaviorSubject(false); readonly helpModeDialogIsOpened$ = this._helpModeDialogIsOpened$.asObservable(); private readonly _elements: Record = {}; private readonly _renderer: Renderer2; constructor( @Inject(HELP_DOCS) private readonly _docs: Record>, private readonly _dialog: MatDialog, private readonly _rendererFactory: RendererFactory2, private readonly _translateService: TranslateService ) { this._renderer = this._rendererFactory.createRenderer(null, null); } get isHelpModeActive(): boolean { return this._isHelpModeActive$.getValue(); } get helpModeDialogIsOpened(): boolean { return this._helpModeDialogIsOpened$.getValue(); } openHelpModeDialog(): MatDialogRef { this._helpModeDialogIsOpened$.next(true); const ref = this._dialog.open(HelpModeDialogComponent, { width: '600px' }); ref.afterClosed() .toPromise() .then(() => { this._helpModeDialogIsOpened$.next(false); }); return ref; } openDocsFor(elementName: string): void { if (this.isHelpModeActive) { window.open(this._docs[elementName][this._translateService.currentLang]); } } activateHelpMode(): void { this._isHelpModeActive$.next(true); this.openHelpModeDialog(); this._enableHelperElements(); } deactivateHelpMode(): void { this._isHelpModeActive$.next(false); this._disableHelperElements(); } highlightHelperElements(): void { if (!this.isHelpModeActive) return; Object.values(this._elements).forEach(({ helperElement }) => { this._renderer.addClass(helperElement, 'help-highlight'); setTimeout(() => { this._renderer.removeClass(helperElement, 'help-highlight'); }, 500); }); } addElement(elementName: string, element: HTMLElement, helperElement: HTMLElement): void { this._elements[elementName] = { element, helperElement }; } private _enableHelperElements() { Object.values(this._elements).forEach(({ element, helperElement }) => { this._renderer.setStyle(element, 'position', 'relative'); this._renderer.appendChild(element, helperElement); }); } private _disableHelperElements() { Object.values(this._elements).forEach(({ element, helperElement }) => { this._renderer.removeStyle(element, 'position'); this._renderer.removeChild(element, helperElement); }); } }