UNPKG

@igo2/common

Version:
483 lines (476 loc) 25.7 kB
import * as i0 from '@angular/core'; import { Injectable, Input, ViewEncapsulation, Component, NgModule } from '@angular/core'; import { NgIf, NgClass, AsyncPipe } from '@angular/common'; import * as i4 from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button'; import * as i6 from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon'; import * as i5$1 from '@angular/material/tooltip'; import { MatTooltipModule } from '@angular/material/tooltip'; import * as i3$1 from '@igo2/common/icon'; import { PRESENTATION_PLAY_ICON, IgoIconComponent } from '@igo2/common/icon'; import * as i2$2 from '@igo2/common/tool'; import * as i3 from '@igo2/core/language'; import { IgoLanguageModule } from '@igo2/core/language'; import { of } from 'rxjs'; import * as i2 from '@igo2/core/config'; import * as i2$1 from '@igo2/core/media'; import { autoPlacement, offset } from '@floating-ui/dom'; import * as i5 from 'angular-shepherd'; import * as i1 from '@angular/common/http'; import { catchError } from 'rxjs/operators'; import * as i7 from '@ngx-translate/core'; class InteractiveTourLoader { http; configService; jsonURL; allToursOptions; constructor(http, configService) { this.http = http; this.configService = configService; this.jsonURL = this.getPathToConfigFile(); } loadConfigTour() { this.getJSON().subscribe((data) => { this.allToursOptions = data; }, () => { throw new Error(`Problem with Interactive tour configuration file: interactiveTour.json not find. Check if the file and is path is set correctly.`); }); } getPathToConfigFile() { return (this.configService.getConfig('interactiveTour.pathToConfigFile') || './config/interactiveTour.json'); } getJSON() { return this.http.get(this.jsonURL).pipe(catchError((e) => { e.error.caught = true; throw e; })); } getTourOptionData(toolName) { if (this.allToursOptions === undefined) { return undefined; } let nameInConfigFile = toolName; nameInConfigFile = nameInConfigFile.replace(/\s/g, ''); return this.allToursOptions[nameInConfigFile]; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourLoader, deps: [{ token: i1.HttpClient }, { token: i2.ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourLoader }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourLoader, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.HttpClient }, { type: i2.ConfigService }] }); class InteractiveTourService { configService; mediaService; languageService; interactiveTourLoader; shepherdService; previousStep; constructor(configService, mediaService, languageService, interactiveTourLoader, shepherdService) { this.configService = configService; this.mediaService = mediaService; this.languageService = languageService; this.interactiveTourLoader = interactiveTourLoader; this.shepherdService = shepherdService; if (this.isAppHaveTour()) { this.interactiveTourLoader.loadConfigTour(); } } isAppHaveTour() { const haveTour = this.configService.getConfig('interactiveTour.activateInteractiveTour'); if (haveTour === undefined) { return true; } else { return haveTour; } } isToolHaveTourConfig(toolName) { const checkTourActiveOptions = this.interactiveTourLoader.getTourOptionData(toolName); if (checkTourActiveOptions === undefined) { return false; } else { return true; } } disabledTourButton(toolName) { const stepConfig = this.interactiveTourLoader.getTourOptionData(toolName); if (stepConfig?.conditions) { for (const condition of stepConfig.conditions) { if (document.querySelector(condition) === null) { return true; } } } return false; } isMobile() { return this.mediaService.isMobile(); } isTourDisplayInMobile() { const showInMobile = this.configService.getConfig('interactiveTour.tourInMobile'); return showInMobile === undefined ? true : showInMobile; } getButtons(buttonKind) { if (buttonKind === 'noBackButton') { return [ { classes: 'shepherd-button-primary', text: this.languageService.translate.instant('igo.common.interactiveTour.nextButton'), type: 'next' } ]; } if (buttonKind === 'first') { return [ { classes: 'shepherd-button-secondary', text: this.languageService.translate.instant('igo.common.interactiveTour.exitButton'), type: 'cancel' }, { classes: 'shepherd-button-primary', text: this.languageService.translate.instant('igo.common.interactiveTour.nextButton'), type: 'next' } ]; } if (buttonKind === 'last') { return [ { classes: 'shepherd-button-secondary', text: this.languageService.translate.instant('igo.common.interactiveTour.backButton'), type: 'back' }, { classes: 'shepherd-button-primary', text: this.languageService.translate.instant('igo.common.interactiveTour.exitButton'), type: 'cancel' } ]; } return [ { classes: 'shepherd-button-secondary', text: this.languageService.translate.instant('igo.common.interactiveTour.backButton'), type: 'back' }, { classes: 'shepherd-button-primary', text: this.languageService.translate.instant('igo.common.interactiveTour.nextButton'), type: 'next' } ]; } getAction(actionName) { const action = { click: 'click' }; return action[actionName.toLowerCase()]; } addProgress() { const self = this; let nbTry = 0; const maxTry = 21; const checkExist = setInterval(() => { if (self.getCurrentStep()) { if (self.getCurrentStep().options.attachTo.element && !document.querySelector(self.getCurrentStep().options.attachTo.element)) { self.cancel(); clearInterval(checkExist); return; } else { const currentStepElement = self.getCurrentStep().getElement(); const header = currentStepElement ? currentStepElement.querySelector('.shepherd-header') : undefined; nbTry++; if (header || nbTry > maxTry) { clearInterval(checkExist); } if (header) { const stepsArray = self.steps; const progress = document.createElement('span'); progress.className = 'shepherd-progress'; progress.innerText = `${stepsArray.indexOf(self.getCurrentStep()) + 1}/${stepsArray.length}`; header.insertBefore(progress, currentStepElement.querySelector('.shepherd-cancel-icon')); } } } }, 100); } checkNext(index, tour) { if (tour.getCurrentStep()) { if (tour.getCurrentStep().options.attachTo.element && document.querySelector(tour.getCurrentStep().options.attachTo.element)) { tour.complete(); return; } if (index.index === tour.steps.length - 1) { tour.complete(); return; } tour.steps.splice(index.index, 1); const nextStep = tour.steps[index.index]; if (nextStep.options.attachTo.element && !document.querySelector(nextStep.options.attachTo.element)) { index.index = index.index + 1; this.checkNext(index, tour); } else { tour._setupModal(); tour.show(nextStep.id); } } } executeAction(step, actionConfig) { if (!actionConfig) { return; } if (actionConfig.condition && ((actionConfig.condition.charAt(0) === '!' && document.querySelector(actionConfig.condition.slice(1))) || (actionConfig.condition.charAt(0) !== '!' && !document.querySelector(actionConfig.condition)))) { return; } const element = document.querySelector(actionConfig.element || step.element); const action = this.getAction(actionConfig.action); if (element && action) { element[action](); } } executeActionPromise(step, actionConfig) { return new Promise((resolve) => { this.executeAction(step, actionConfig); if (!actionConfig || !actionConfig.waitFor) { resolve(); return; } let nbTry = 0; const maxTry = actionConfig.maxWait ? actionConfig.maxWait / 100 : 20; const checkExist = setInterval(() => { nbTry++; if (nbTry > maxTry || document.querySelector(actionConfig.waitFor)) { clearInterval(checkExist); resolve(); } }, 100); }); } getShepherdSteps(tourConfig) { const shepherdSteps = []; let i = 0; for (const step of tourConfig.steps) { const position = step.position ?? tourConfig.position; shepherdSteps.push({ attachTo: { element: step.element, on: position // PopperPlacement }, floatingUIOptions: { middleware: [ position === 'auto' && autoPlacement(), offset({ mainAxis: 15 }) ].filter(Boolean) }, beforeShowPromise: () => { return Promise.all([ this.executeActionPromise(this.previousStep, this.previousStep ? this.previousStep.beforeChange : undefined), this.executeActionPromise(step, step.beforeShow) ]); }, buttons: this.getButtons(i === 0 ? 'first' : i + 1 === tourConfig.steps.length ? 'last' : tourConfig.steps[i].noBackButton ? 'noBackButton' : undefined), classes: step.class, highlightClass: step.highlightClass, scrollTo: step.scrollToElement || tourConfig.scrollToElement || true, canClickTarget: step.disableInteraction ? !step.disableInteraction : undefined, title: this.languageService.translate.instant(step.title || tourConfig.title), text: [this.languageService.translate.instant(step.text)], when: { show: () => { this.executeAction(step, step.onShow); }, hide: () => { this.previousStep = step; this.executeAction(step, step.onHide); } } }); i++; } return shepherdSteps; } startTour(toolName) { const stepConfig = this.interactiveTourLoader.getTourOptionData(toolName); this.shepherdService.defaultStepOptions = { classes: stepConfig.class, highlightClass: stepConfig.highlightClass, canClickTarget: stepConfig.disableInteraction ? !stepConfig.disableInteraction : true, cancelIcon: { enabled: true } }; const shepherdSteps = this.getShepherdSteps(stepConfig); this.shepherdService.modal = true; this.shepherdService.confirmCancel = false; this.shepherdService.addSteps(shepherdSteps); this.shepherdService.tourObject.on('show', this.addProgress); this.shepherdService.tourObject.on('cancel', (index) => { this.checkNext(index, this.shepherdService.tourObject); }); this.shepherdService.start(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourService, deps: [{ token: i2.ConfigService }, { token: i2$1.MediaService }, { token: i3.LanguageService }, { token: InteractiveTourLoader }, { token: i5.ShepherdService }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i2.ConfigService }, { type: i2$1.MediaService }, { type: i3.LanguageService }, { type: InteractiveTourLoader }, { type: i5.ShepherdService }] }); class InteractiveTourComponent { interactiveTourService; toolService; iconService; presentationIcon = PRESENTATION_PLAY_ICON; /** * Toolbox that holds main tools */ tourToStart = ''; styleButton; discoverTitleInLocale$ = of('IGO'); getClass() { return { 'tour-button-tool-icon': this.styleButton === 'icon', 'tour-button-tool': this.styleButton === 'raised' }; } get toolbox() { return this.toolService.toolbox; } getTourToStart() { if (this.tourToStart) { return this.tourToStart; } else { return this.activeToolName; } } get activeToolName() { if (this.toolbox) { if (this.isActiveTool) { return this.toolbox.activeTool$.getValue().name; } else { return 'global'; } } else { return undefined; } } get isActiveTool() { if (this.toolbox) { return this.toolbox.activeTool$.getValue() !== undefined; } else { return undefined; } } get isToolHaveTour() { if (this.activeToolName === 'about' && !this.tourToStart) { return false; } return this.interactiveTourService.isToolHaveTourConfig(this.getTourToStart()); } get showTourButton() { // 2 conditions to show: have Tour on tool in Config file and if we are in mobile displayInMobile= true if (this.isToolHaveTour === false) { return false; } let inMobileAndShow; if (this.interactiveTourService.isMobile()) { inMobileAndShow = this.isTourDisplayInMobile; if (inMobileAndShow === false) { return false; } } return true; } get isTourDisplayInMobile() { return this.interactiveTourService.isTourDisplayInMobile(); } get disabledTourButton() { return this.interactiveTourService.disabledTourButton(this.activeToolName); } constructor(interactiveTourService, toolService, iconService) { this.interactiveTourService = interactiveTourService; this.toolService = toolService; this.iconService = iconService; this.iconService.registerSvg(this.presentationIcon); } startInteractiveTour() { const tour = this.getTourToStart(); if (tour) { this.interactiveTourService.startTour(tour); } else { return; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourComponent, deps: [{ token: InteractiveTourService }, { token: i2$2.ToolService }, { token: i3$1.IconService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: InteractiveTourComponent, isStandalone: true, selector: "igo-interactive-tour", inputs: { tourToStart: "tourToStart", styleButton: "styleButton", discoverTitleInLocale$: "discoverTitleInLocale$" }, ngImport: i0, template: "<ng-container *ngIf=\"showTourButton\">\n <button\n *ngIf=\"styleButton === 'icon'; else raisedButton\"\n (click)=\"startInteractiveTour()\"\n [ngClass]=\"getClass()\"\n color=\"primary\"\n mat-icon-button\n tooltip-position=\"below\"\n matTooltipShowDelay=\"500\"\n [matTooltip]=\"\n disabledTourButton\n ? ('igo.common.interactiveTour.disaledTooltipTourToolButton'\n | translate)\n : ('igo.common.interactiveTour.tooltipTourToolButton' | translate)\n \"\n [disabled]=\"disabledTourButton\"\n >\n <igo-icon [icon]=\"presentationIcon\" iconPositionEnd />\n </button>\n\n <ng-template #raisedButton>\n <button\n (click)=\"startInteractiveTour()\"\n [ngClass]=\"getClass()\"\n color=\"primary\"\n mat-raised-button\n tooltip-position=\"below\"\n matTooltipShowDelay=\"500\"\n [disabled]=\"disabledTourButton\"\n >\n {{ 'igo.common.interactiveTour.buttonTitle' | translate }}\n {{ discoverTitleInLocale$ | async | translate }}\n <mat-icon\n [svgIcon]=\"presentationIcon.name\"\n iconPositionEnd\n [matTooltip]=\"\n disabledTourButton\n ? ('igo.common.interactiveTour.disaledTooltipTourToolButton'\n | translate)\n : ('igo.common.interactiveTour.tooltipTourToolButton' | translate)\n \"\n >\n </mat-icon>\n </button>\n </ng-template>\n</ng-container>\n", styles: [":host ::ng-deep button.tour-button-tool-icon{color:var(--mat-sys-primary-container)}:host ::ng-deep button.tour-button-tool-icon:hover{background-color:var(--mat-sys-secondary-container);color:var(--mat-sys-on-secondary-container)}:host ::ng-deep .mat-primary .mat-mdc-icon-button{color:#fff}:host>button.mat-mdc-raised-button.tour-button-tool-icon{box-shadow:none}.shepherd-has-title .shepherd-content .shepherd-header{padding:.5em .75em}.shepherd-has-title .shepherd-content .shepherd-header h3{font-size:14px}.shepherd-title{margin:0!important;font-weight:revert!important}.shepherd-progress{margin-right:15px;color:#737373}.shepherd-element{border:1px solid;border-color:#474747;box-shadow:4px 5px #65656599}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "ngmodule", type: IgoLanguageModule }, { kind: "pipe", type: i7.TranslatePipe, name: "translate" }, { kind: "component", type: IgoIconComponent, selector: "igo-icon", inputs: ["color", "icon"] }], encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: InteractiveTourComponent, decorators: [{ type: Component, args: [{ selector: 'igo-interactive-tour', encapsulation: ViewEncapsulation.None, imports: [ NgIf, MatButtonModule, NgClass, MatTooltipModule, MatIconModule, AsyncPipe, IgoLanguageModule, IgoIconComponent ], template: "<ng-container *ngIf=\"showTourButton\">\n <button\n *ngIf=\"styleButton === 'icon'; else raisedButton\"\n (click)=\"startInteractiveTour()\"\n [ngClass]=\"getClass()\"\n color=\"primary\"\n mat-icon-button\n tooltip-position=\"below\"\n matTooltipShowDelay=\"500\"\n [matTooltip]=\"\n disabledTourButton\n ? ('igo.common.interactiveTour.disaledTooltipTourToolButton'\n | translate)\n : ('igo.common.interactiveTour.tooltipTourToolButton' | translate)\n \"\n [disabled]=\"disabledTourButton\"\n >\n <igo-icon [icon]=\"presentationIcon\" iconPositionEnd />\n </button>\n\n <ng-template #raisedButton>\n <button\n (click)=\"startInteractiveTour()\"\n [ngClass]=\"getClass()\"\n color=\"primary\"\n mat-raised-button\n tooltip-position=\"below\"\n matTooltipShowDelay=\"500\"\n [disabled]=\"disabledTourButton\"\n >\n {{ 'igo.common.interactiveTour.buttonTitle' | translate }}\n {{ discoverTitleInLocale$ | async | translate }}\n <mat-icon\n [svgIcon]=\"presentationIcon.name\"\n iconPositionEnd\n [matTooltip]=\"\n disabledTourButton\n ? ('igo.common.interactiveTour.disaledTooltipTourToolButton'\n | translate)\n : ('igo.common.interactiveTour.tooltipTourToolButton' | translate)\n \"\n >\n </mat-icon>\n </button>\n </ng-template>\n</ng-container>\n", styles: [":host ::ng-deep button.tour-button-tool-icon{color:var(--mat-sys-primary-container)}:host ::ng-deep button.tour-button-tool-icon:hover{background-color:var(--mat-sys-secondary-container);color:var(--mat-sys-on-secondary-container)}:host ::ng-deep .mat-primary .mat-mdc-icon-button{color:#fff}:host>button.mat-mdc-raised-button.tour-button-tool-icon{box-shadow:none}.shepherd-has-title .shepherd-content .shepherd-header{padding:.5em .75em}.shepherd-has-title .shepherd-content .shepherd-header h3{font-size:14px}.shepherd-title{margin:0!important;font-weight:revert!important}.shepherd-progress{margin-right:15px;color:#737373}.shepherd-element{border:1px solid;border-color:#474747;box-shadow:4px 5px #65656599}\n"] }] }], ctorParameters: () => [{ type: InteractiveTourService }, { type: i2$2.ToolService }, { type: i3$1.IconService }], propDecorators: { tourToStart: [{ type: Input }], styleButton: [{ type: Input }], discoverTitleInLocale$: [{ type: Input }] } }); class IgoInteractiveTourModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoInteractiveTourModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.15", ngImport: i0, type: IgoInteractiveTourModule, imports: [InteractiveTourComponent], exports: [InteractiveTourComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoInteractiveTourModule, providers: [InteractiveTourService, InteractiveTourLoader], imports: [InteractiveTourComponent] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoInteractiveTourModule, decorators: [{ type: NgModule, args: [{ imports: [InteractiveTourComponent], exports: [InteractiveTourComponent], providers: [InteractiveTourService, InteractiveTourLoader] }] }] }); /** * Generated bundle index. Do not edit. */ export { IgoInteractiveTourModule, InteractiveTourComponent, InteractiveTourLoader, InteractiveTourService }; //# sourceMappingURL=igo2-common-interactive-tour.mjs.map