RED-6510 - WIP on "Lazy load help mode elements"

This commit is contained in:
Valentin Mihai 2023-04-06 14:59:24 +03:00
parent 6c63f851cf
commit 8a61630a37
13 changed files with 74 additions and 89 deletions

View File

@ -19,7 +19,7 @@
*ngIf="showButton"
[buttonId]="buttonId"
[icon]="buttonIcon"
[iqserHelpMode]="helpModeKey"
[attr.help-mode-key]="helpModeKey"
[label]="buttonLabel"
[type]="iconButtonTypes.primary"
></iqser-icon-button>

View File

@ -5,7 +5,7 @@
[class.active]="filter.checked"
[class.disabled]="filter.disabled"
class="quick-filter"
[iqserHelpMode]="filter.helpModeKey"
[attr.help-mode-key]="filter.helpModeKey"
>
{{ filter.label }}
</div>

View File

@ -22,7 +22,8 @@ export class HelpButtonComponent implements OnInit, OnDestroy {
activateHelpMode(): void {
if (this.helpButtonKey) {
const url = this._helpModeService.getDocsLink(this.helpButtonKey);
// const url = this._helpModeService.getDocsLink(this.helpButtonKey);
const url = '';
window.open(url, '_blank');
return;
}

View File

@ -1 +0,0 @@
export type HelpDocs = Record<string, Record<string, string>>;

View File

@ -1,50 +0,0 @@
import { Directive, ElementRef, Input, OnInit, Optional, Renderer2 } from '@angular/core';
import { HELP_MODE_CLASS, OverlappingElement, ScrollableParentView } from './utils/constants';
import { Helper, HelpModeService } from './help-mode.service';
@Directive({
selector: '[iqserHelpMode]',
exportAs: 'iqserHelpMode',
})
export class HelpModeDirective implements OnInit {
@Input('iqserHelpMode') helpModeKey!: string;
@Input() scrollableParentView!: ScrollableParentView;
@Input() overlappingElements: OverlappingElement[] = [];
@Input() dialogElement = false;
constructor(
private readonly _elementRef: ElementRef,
private readonly _renderer: Renderer2,
@Optional() private readonly _helpModeService: HelpModeService,
) {}
ngOnInit(): void {
if (this.helpModeKey && this._helpModeService) {
this._createHelperElement();
}
}
private _createHelperElement() {
const element = this._elementRef.nativeElement as HTMLElement;
const helperKey = `${this.helpModeKey}-${this._generateId()}`;
const helperElement = this._renderer.createElement('a') as HTMLElement;
this._renderer.setAttribute(helperElement, 'href', this._helpModeService.getDocsLink(this.helpModeKey));
this._renderer.setAttribute(helperElement, 'target', '_blank');
this._renderer.addClass(helperElement, HELP_MODE_CLASS);
const helper: Helper = {
element,
helperElement,
scrollableParentView: this.scrollableParentView,
overlappingElements: this.overlappingElements,
dialogElement: this.dialogElement,
};
this._helpModeService.addHelper(helperKey, helper);
}
private _generateId(): string {
return Math.random().toString(36).substring(2, 9);
}
}

View File

@ -3,15 +3,13 @@ import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { HelpModeDialogComponent } from './help-mode-dialog/help-mode-dialog.component';
import { HelpModeComponent } from './help-mode/help-mode.component';
import { HelpModeDirective } from './help-mode.directive';
import { HelpButtonComponent } from './help-button/help-button.component';
import { HelpModeService } from './help-mode.service';
import { HelpDocs } from './help-docs';
import { HELP_DOCS } from './tokens';
import { DocsKey, HelpModeService } from './help-mode.service';
import { MatDialogModule } from '@angular/material/dialog';
import { CircleButtonComponent } from '../buttons';
import { HELP_MODE_KEYS } from './tokens';
const components = [HelpModeComponent, HelpModeDialogComponent, HelpModeDirective, HelpButtonComponent];
const components = [HelpModeComponent, HelpModeDialogComponent, HelpButtonComponent];
@NgModule({
declarations: [...components],
@ -19,10 +17,10 @@ const components = [HelpModeComponent, HelpModeDialogComponent, HelpModeDirectiv
exports: [...components],
})
export class IqserHelpModeModule {
static forRoot(helpDocs: HelpDocs): ModuleWithProviders<IqserHelpModeModule> {
static forRoot(helpDocs: DocsKey): ModuleWithProviders<IqserHelpModeModule> {
return {
ngModule: IqserHelpModeModule,
providers: [{ provide: HELP_DOCS, useValue: helpDocs }, HelpModeService],
providers: [{ provide: HELP_MODE_KEYS, useValue: helpDocs }, HelpModeService],
};
}
}

View File

@ -3,8 +3,7 @@ import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, firstValueFrom } from 'rxjs';
import { HelpModeDialogComponent } from './help-mode-dialog/help-mode-dialog.component';
import { HELP_DOCS, MANUAL_BASE_URL } from './tokens';
import { HelpDocs } from './help-docs';
import { HELP_MODE_KEYS, MANUAL_BASE_URL } from './tokens';
import {
ANNOTATIONS_LIST_ID,
HELP_HIGHLIGHT_CLASS,
@ -28,6 +27,13 @@ export interface Helper {
readonly iframeElement?: boolean;
}
export interface DocsKey {
readonly key: string;
readonly scrollableParentView?: ScrollableParentView;
readonly overlappingElements?: OverlappingElement[];
readonly dialogElement?: boolean;
}
@Injectable()
export class HelpModeService {
helpButtonKey: string | undefined;
@ -40,7 +46,7 @@ export class HelpModeService {
#dialogMode = false;
constructor(
@Inject(HELP_DOCS) private readonly _docs: HelpDocs,
@Inject(HELP_MODE_KEYS) private readonly _keys: DocsKey[],
@Inject(MANUAL_BASE_URL) private readonly _manualBaseURL: string,
private readonly _dialog: MatDialog,
private readonly _rendererFactory: RendererFactory2,
@ -70,20 +76,23 @@ export class HelpModeService {
return ref;
}
getDocsLink(elementName: string): string {
return this._docs[elementName] ? `${this._manualBaseURL}${this._docs[elementName][this._translateService.currentLang]}` : '';
}
activateHelpMode(dialogMode: boolean = false): void {
if (!this.isHelpModeActive) {
document.body.style.setProperty('overflow', 'unset');
this.#isHelpModeActive$.next(true);
this.openHelpModeDialog();
this.#dialogMode = dialogMode;
setTimeout(() => {
this.#createWebViewerHelpers();
this.#enableHelperElements();
}, 500);
// setTimeout(() => {
// this.#createWebViewerHelpers();
// this.#enableHelperElements();
// }, 500);
for (const key in this._keys) {
this.#createHelperElement(this._keys[key]);
}
this.#createWebViewerHelpers();
this.#enableHelperElements();
}
}
@ -95,6 +104,35 @@ export class HelpModeService {
}
}
#createHelperElement(key: DocsKey) {
const element = document.querySelectorAll(`[help-mode-key='${key.key}']`)[0] as HTMLElement;
if (element) {
const helperKey = `${key.key}-${this.#generateId()}`;
const helperElement = this.#renderer.createElement('a') as HTMLElement;
this.#renderer.setAttribute(helperElement, 'href', this.#generateDocsLink(key.key));
this.#renderer.setAttribute(helperElement, 'target', '_blank');
this.#renderer.addClass(helperElement, HELP_MODE_CLASS);
this.#helpers[helperKey] = {
element,
helperElement,
scrollableParentView: key.scrollableParentView,
overlappingElements: key.overlappingElements,
dialogElement: !!key.dialogElement,
};
}
}
#generateId(): string {
return Math.random().toString(36).substring(2, 9);
}
#generateDocsLink(key: string) {
const currentLang = this._translateService.currentLang;
return `${this._manualBaseURL}/${currentLang}/index-${currentLang}.html?contextId=${key}`;
}
highlightHelperElements(): void {
Object.values(this.#helpers).forEach(helper => {
this.#renderer.addClass(helper.helperElement, HELP_HIGHLIGHT_CLASS);
@ -111,7 +149,7 @@ export class HelpModeService {
const element: HTMLElement = iframe.contentWindow?.document.querySelector(e.querySelector) as HTMLElement;
const helperElement: HTMLElement = this.#renderer.createElement('a') as HTMLElement;
this.#renderer.setAttribute(helperElement, 'href', this.getDocsLink(e.helpModeKey));
this.#renderer.setAttribute(helperElement, 'href', this.#generateDocsLink(e.helpModeKey));
this.#renderer.setAttribute(helperElement, 'target', '_blank');
this.#renderer.addClass(helperElement, HELP_MODE_CLASS);
@ -230,6 +268,9 @@ export class HelpModeService {
#enableHelperElements() {
Object.values(this.#helpers).forEach(helper => {
console.log('-----------------------');
console.log('this.#dialogMode: ', this.#dialogMode);
console.log('helper.dialogElement: ', helper.dialogElement);
if (this.#dialogMode === helper.dialogElement) {
document.body.appendChild(helper.helperElement);
this.#updateHelperElement(helper);

View File

@ -25,7 +25,8 @@ export class HelpModeComponent {
const node = (event.target as IqserEventTarget).localName;
if (!this.helpModeService.isHelpModeActive && node !== 'input' && node !== 'textarea') {
if (this.helpModeService.helpButtonKey) {
const url = this.helpModeService.getDocsLink(this.helpModeService.helpButtonKey);
// const url = this.helpModeService.getDocsLink(this.helpModeService.helpButtonKey);
const url = '';
window.open(url, '_blank');
return;
}

View File

@ -1,8 +1,6 @@
export * from './tokens';
export * from './help-docs';
export * from './help-mode.module';
export * from './help-mode.service';
export * from './help-mode.directive';
export * from './help-mode/help-mode.component';
export * from './help-button/help-button.component';
export * from './help-mode-dialog/help-mode-dialog.component';

View File

@ -1,8 +1,8 @@
import { inject, InjectionToken } from '@angular/core';
import { IqserConfigService } from '../services';
import { HelpDocs } from './help-docs';
import { DocsKey } from './help-mode.service';
export const HELP_DOCS = new InjectionToken<HelpDocs>('Links to user manual or help docs');
export const HELP_MODE_KEYS = new InjectionToken<DocsKey>('Help mode keys');
export const MANUAL_BASE_URL = new InjectionToken<string>('Base manual URL', {
factory: () => inject(IqserConfigService).values.MANUAL_BASE_URL,
});

View File

@ -15,8 +15,8 @@
<ng-container *ngFor="let filter of filters; trackBy: trackByLabel">
<iqser-popup-filter
*ngIf="!filter.hide"
[iqserHelpMode]="filterHelpModeKey"
[primaryFiltersSlug]="filter.slug"
[attr.help-mode-key]="filterHelpModeKey"
></iqser-popup-filter>
</ng-container>
@ -29,7 +29,7 @@
<div
(click)="resetFilters()"
*ngIf="!hideResetButton && (showResetFilters$ | async) === true"
[iqserHelpMode]="'filter_' + helpModeKey + '_list'"
[attr.help-mode-key]="'filter_' + helpModeKey + '_list'"
class="reset-filters"
translate="reset-filters"
></div>
@ -46,10 +46,9 @@
*ngIf="!config.hide"
[buttonId]="config.label.replace('.', '-')"
[icon]="config.icon"
[iqserHelpMode]="config.helpModeKey"
[label]="config.label | translate"
[overlappingElements]="config.overlappingElements"
[type]="config.type"
[attr.help-mode-key]="config.helpModeKey"
></iqser-icon-button>
</ng-container>
@ -61,9 +60,8 @@
[buttonId]="config.id"
[disabled]="config.disabled$ && (config.disabled$ | async)"
[icon]="config.icon"
[iqserHelpMode]="config.helpModeKey"
[overlappingElements]="config.overlappingElements"
[tooltip]="config.label"
[attr.help-mode-key]="config.helpModeKey"
></iqser-circle-button>
</ng-container>
@ -76,8 +74,7 @@
*ngIf="showCloseButton"
[class.ml-6]="actionConfigs"
[icon]="'iqser:close'"
[iqserHelpMode]="'edit_dossier_in_dossier'"
[overlappingElements]="['USER_MENU']"
[attr.help-mode-key]="'edit_dossier_in_dossier'"
[tooltip]="'common.close' | translate"
></iqser-circle-button>
</div>

View File

@ -1,7 +1,7 @@
<button
(click)="scroll(buttonType.top)"
[hidden]="(showScrollUp$ | async) === false"
[iqserHelpMode]="helpModeKey + '_list'"
[attr.help-mode-key]="helpModeKey + '_list'"
class="scroll-button top pointer"
id="scroll-up"
>
@ -11,7 +11,7 @@
<button
(click)="scroll(buttonType.bottom)"
[hidden]="(showScrollDown$ | async) === false"
[iqserHelpMode]="helpModeKey + '_list'"
[attr.help-mode-key]="helpModeKey + '_list'"
class="scroll-button bottom pointer"
id="scroll-down"
>

View File

@ -1,5 +1,5 @@
<div [class.selection-enabled]="selectionEnabled" class="header-item">
<div [iqserHelpMode]="helpModeKey" class="header-title">
<div [attr.help-mode-key]="helpModeKey" class="header-title">
<iqser-round-checkbox
id="select-all-entities-toggle"
(click)="listingService.selectAll()"