@igo2/common
Version:
483 lines (476 loc) • 25.7 kB
JavaScript
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