From fef6b463086b93d903074afa3583ad0fc62f3ba3 Mon Sep 17 00:00:00 2001
From: Alex ORLUC <alex.orluc@maarch.org>
Date: Thu, 9 Jul 2020 16:51:56 +0200
Subject: [PATCH] FEAT #14324 TIME 3:15 feature tour

---
 ...notification-administration.component.html |   2 +-
 ...otifications-administration.component.html |   6 +-
 .../notifications-administration.component.ts | 134 ++++++++++--------
 src/frontend/app/home/home.component.html     |   2 +-
 src/frontend/app/home/home.component.ts       |   7 +-
 src/frontend/assets/admin_button.png          | Bin 0 -> 2953 bytes
 src/frontend/lang/lang-en.ts                  |   6 +-
 src/frontend/lang/lang-fr.ts                  |  16 ++-
 src/frontend/lang/lang-nl.ts                  |   6 +-
 src/frontend/service/featureTour.service.ts   | 105 ++++++++------
 10 files changed, 161 insertions(+), 123 deletions(-)
 create mode 100644 src/frontend/assets/admin_button.png

diff --git a/src/frontend/app/administration/notification/notification-administration.component.html b/src/frontend/app/administration/notification/notification-administration.component.html
index dc18f3c53be..29b6ca33041 100755
--- a/src/frontend/app/administration/notification/notification-administration.component.html
+++ b/src/frontend/app/administration/notification/notification-administration.component.html
@@ -2,7 +2,7 @@
     <ng-template #adminMenuTemplate>
         <mat-nav-list>
             <h3 mat-subheader *ngIf="!creationMode">{{lang.actions}}</h3>
-            <a mat-list-item (click)="createScript()" *ngIf="!creationMode && !loading && !notification.scriptcreated">
+            <a mat-list-item (click)="createScript()" *ngIf="!creationMode && !loading && !notification.scriptcreated" joyrideStep="createScriptTour" (next)="createScript()">
                 <mat-icon color="primary" mat-list-icon class="fa fa-terminal"></mat-icon>
                 <p mat-line>
                     {{lang.createScriptNotification}}
diff --git a/src/frontend/app/administration/notification/notifications-administration.component.html b/src/frontend/app/administration/notification/notifications-administration.component.html
index d59bfb7d980..07aea70801f 100755
--- a/src/frontend/app/administration/notification/notifications-administration.component.html
+++ b/src/frontend/app/administration/notification/notifications-administration.component.html
@@ -8,7 +8,7 @@
                     {{lang.add}}
                 </p>
             </a>
-            <a mat-list-item (click)="loadCron();snav2.toggle();" (next)="loadCron();snav2.toggle()" joyrideStep="notifTour" [text]="'Cliquez ici pour plannifier une tâche éxistante. Plannifions <b>Notification de bannettes</b>'">
+            <a mat-list-item (click)="loadCron();snav2.toggle();" (next)="snav2.open();paramCron();" joyrideStep="notifTour">
                 <mat-icon color="primary" mat-list-icon class="fa fa-clock"></mat-icon>
                 <p mat-line>
                     {{lang.toSchedule}}
@@ -84,7 +84,7 @@
                         <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
                         <mat-row *matRowDef="let row; columns: displayedColumns;"
                             routerLink="/administration/notifications/{{row.notification_sid}}" style="cursor:pointer;"
-                            matTooltip="{{lang.view}}"></mat-row>
+                            matTooltip="{{lang.view}}" [joyrideStep]="row.notification_id + '_Tour'"></mat-row>
                     </mat-table>
                     <div class="mat-paginator"
                         style="min-height:48px;min-height: 48px;display: flex;justify-content: end;align-items: center;padding-right: 20px;">
@@ -94,7 +94,7 @@
         </div>
     </mat-sidenav-content>
     <mat-sidenav #snav2 [mode]="appService.getViewMode() ? 'over' : 'side'" [fixedInViewport]="appService.getViewMode()"
-        fixedTopGap="56" position='end' [opened]="appService.getViewMode() ? false : false"  (next)="paramCron()" stepPosition="center" joyrideStep="notifTour2">
+        fixedTopGap="56" position='end' [opened]="appService.getViewMode() ? false : false"  (next)="paramCron()">
         <mat-list  (next)="saveCron()" joyrideStep="notifTour3">
             <h3 mat-subheader>{{lang.notificationSchedule}}</h3>
             <form class="form-horizontal" #notifForm="ngForm" style="overflow:hidden;">
diff --git a/src/frontend/app/administration/notification/notifications-administration.component.ts b/src/frontend/app/administration/notification/notifications-administration.component.ts
index 48333b916d2..793b8c06d93 100755
--- a/src/frontend/app/administration/notification/notifications-administration.component.ts
+++ b/src/frontend/app/administration/notification/notifications-administration.component.ts
@@ -9,6 +9,10 @@ import { NotificationService } from '../../../service/notification/notification.
 import { HeaderService } from '../../../service/header.service';
 import { AppService } from '../../../service/app.service';
 import { FunctionsService } from '../../../service/functions.service';
+import { tap } from 'rxjs/internal/operators/tap';
+import { catchError } from 'rxjs/internal/operators/catchError';
+import { of } from 'rxjs/internal/observable/of';
+import { finalize } from 'rxjs/operators';
 
 @Component({
     templateUrl: 'notifications-administration.component.html'
@@ -110,68 +114,71 @@ export class NotificationsAdministrationComponent implements OnInit {
     }
 
     loadCron() {
-
-        this.hours = [{ label: this.lang.eachHour, value: '*' }];
-        this.minutes = [{ label: this.lang.eachMinute, value: '*' }];
-
-        this.months = [
-            { label: this.lang.eachMonth, value: '*' },
-            { label: this.lang.january, value: '1' },
-            { label: this.lang.february, value: '2' },
-            { label: this.lang.march, value: '3' },
-            { label: this.lang.april, value: '4' },
-            { label: this.lang.may, value: '5' },
-            { label: this.lang.june, value: '6' },
-            { label: this.lang.july, value: '7' },
-            { label: this.lang.august, value: '8' },
-            { label: this.lang.september, value: '9' },
-            { label: this.lang.october, value: '10' },
-            { label: this.lang.november, value: '11' },
-            { label: this.lang.december, value: '12' }
-        ];
-
-        this.dom = [{ label: this.lang.notUsed, value: '*' }];
-
-        this.dow = [
-            { label: this.lang.eachDay, value: '*' },
-            { label: this.lang.monday, value: '1' },
-            { label: this.lang.tuesday, value: '2' },
-            { label: this.lang.wednesday, value: '3' },
-            { label: this.lang.thursday, value: '4' },
-            { label: this.lang.friday, value: '5' },
-            { label: this.lang.saturday, value: '6' },
-            { label: this.lang.sunday, value: '7' }
-        ];
-
-        this.newCron = {
-            'm': '',
-            'h': '',
-            'dom': '',
-            'mon': '',
-            'cmd': '',
-            'state': 'normal'
-        };
-
-        for (let it = 0; it <= 23; it++) {
-            this.hours.push({ label: it, value: String(it) });
-        }
-
-        for (let it = 0; it <= 59; it++) {
-            this.minutes.push({ label: it, value: String(it) });
-        }
-
-        for (let it = 1; it <= 31; it++) {
-            this.dom.push({ label: it, value: String(it) });
-        }
-
-        this.http.get('../rest/notifications/schedule')
-            .subscribe((data: any) => {
-                this.crontab = data.crontab;
-                this.authorizedNotification = data.authorizedNotification;
-            }, (err) => {
-                this.notify.error(err.error.errors);
-            });
-
+        return new Promise((resolve) => {
+            this.hours = [{ label: this.lang.eachHour, value: '*' }];
+            this.minutes = [{ label: this.lang.eachMinute, value: '*' }];
+
+            this.months = [
+                { label: this.lang.eachMonth, value: '*' },
+                { label: this.lang.january, value: '1' },
+                { label: this.lang.february, value: '2' },
+                { label: this.lang.march, value: '3' },
+                { label: this.lang.april, value: '4' },
+                { label: this.lang.may, value: '5' },
+                { label: this.lang.june, value: '6' },
+                { label: this.lang.july, value: '7' },
+                { label: this.lang.august, value: '8' },
+                { label: this.lang.september, value: '9' },
+                { label: this.lang.october, value: '10' },
+                { label: this.lang.november, value: '11' },
+                { label: this.lang.december, value: '12' }
+            ];
+
+            this.dom = [{ label: this.lang.notUsed, value: '*' }];
+
+            this.dow = [
+                { label: this.lang.eachDay, value: '*' },
+                { label: this.lang.monday, value: '1' },
+                { label: this.lang.tuesday, value: '2' },
+                { label: this.lang.wednesday, value: '3' },
+                { label: this.lang.thursday, value: '4' },
+                { label: this.lang.friday, value: '5' },
+                { label: this.lang.saturday, value: '6' },
+                { label: this.lang.sunday, value: '7' }
+            ];
+
+            this.newCron = {
+                'm': '',
+                'h': '',
+                'dom': '',
+                'mon': '',
+                'cmd': '',
+                'state': 'normal'
+            };
+
+            for (let it = 0; it <= 23; it++) {
+                this.hours.push({ label: it, value: String(it) });
+            }
+
+            for (let it = 0; it <= 59; it++) {
+                this.minutes.push({ label: it, value: String(it) });
+            }
+
+            for (let it = 1; it <= 31; it++) {
+                this.dom.push({ label: it, value: String(it) });
+            }
+            this.http.get('../rest/notifications/schedule').pipe(
+                tap((data: any) => {
+                    this.crontab = data.crontab;
+                    this.authorizedNotification = data.authorizedNotification;
+                }),
+                finalize(() => resolve(true)),
+                catchError((err: any) => {
+                    this.notify.handleSoftErrors(err);
+                    return of(false);
+                })
+            ).subscribe();
+        });
     }
 
     saveCron() {
@@ -215,7 +222,8 @@ export class NotificationsAdministrationComponent implements OnInit {
         return false;
     }
 
-    paramCron() {
+    async paramCron() {
+        await this.loadCron();
         const notifBasket = this.authorizedNotification.filter((notif: any) => notif.path.indexOf('_BASKETS.sh') > -1)[0];
         this.newCron = {
             'm': '0',
diff --git a/src/frontend/app/home/home.component.html b/src/frontend/app/home/home.component.html
index e7e72a734a0..49b76380a1c 100644
--- a/src/frontend/app/home/home.component.html
+++ b/src/frontend/app/home/home.component.html
@@ -1,4 +1,4 @@
-<mat-sidenav-container autosize class="maarch-container">
+<mat-sidenav-container autosize class="maarch-container" joyrideStep="welcome" stepPosition="center">
     <mat-sidenav-content>
         <mat-card id="viewThumbnail" style="display:none;position: fixed;z-index: 2;margin-left: 1px;"><img
                 style="max-height: 100vh;" [src]="thumbnailUrl | secureUrl | async" />
diff --git a/src/frontend/app/home/home.component.ts b/src/frontend/app/home/home.component.ts
index 960c5c4e021..d1db0b1984d 100644
--- a/src/frontend/app/home/home.component.ts
+++ b/src/frontend/app/home/home.component.ts
@@ -12,6 +12,7 @@ import { Router } from '@angular/router';
 import { tap } from 'rxjs/internal/operators/tap';
 import { catchError } from 'rxjs/internal/operators/catchError';
 import { of } from 'rxjs/internal/observable/of';
+import { FeatureTourService } from '../../service/featureTour.service';
 
 declare var $: any;
 
@@ -45,7 +46,8 @@ export class HomeComponent implements OnInit, AfterViewInit {
         private notify: NotificationService,
         private headerService: HeaderService,
         public appService: AppService,
-        private router: Router
+        private router: Router,
+        private featureTourService: FeatureTourService
     ) {
         (<any>window).pdfWorkerSrc = '../node_modules/pdfjs-dist/build/pdf.worker.min.js';
     }
@@ -70,6 +72,9 @@ export class HomeComponent implements OnInit, AfterViewInit {
     }
 
     ngAfterViewInit(): void {
+        if (this.headerService.user.userId === 'superadmin') {
+            this.featureTourService.init();
+        }
         this.http.get('../rest/home/lastRessources')
             .subscribe((data: any) => {
                 setTimeout(() => {
diff --git a/src/frontend/assets/admin_button.png b/src/frontend/assets/admin_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..d33f14c642e4b93efb0e87459ec94e6a40aa2f76
GIT binary patch
literal 2953
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

literal 0
HcmV?d00001

diff --git a/src/frontend/lang/lang-en.ts b/src/frontend/lang/lang-en.ts
index 2b9e602319d..b8363cce200 100755
--- a/src/frontend/lang/lang-en.ts
+++ b/src/frontend/lang/lang-en.ts
@@ -1855,5 +1855,9 @@ export const LANG_EN = {
     "notifTour3Title": "Task period",
     "notifTour3Description": "You can choose different periods to configure your task.",
     "notifTour4Title": "To do-list",
-    "notifTour4Description": "The list of your active tasks appears here."
+    "notifTour4Description": "The list of your active tasks appears here.",
+    "welcomeTourTitle": "welcome",
+    "welcomeTourDescription": "We will show you some configuration points : <ul><li>Configure a <b color=\"primary\">mail server</b></li><li>Configure your first <b color=\"primary\">notification</b></li></ul><br/>To begin, click on <img style=\"width: 32px;\" src=\"assets/admin_button.png\" />",
+    "createScriptTourTitle": "Create the script",
+    "createScriptTourDescription": "Before scheduling the task, we need to create the script."
 };
\ No newline at end of file
diff --git a/src/frontend/lang/lang-fr.ts b/src/frontend/lang/lang-fr.ts
index 187a0b18fef..59a710b97dc 100755
--- a/src/frontend/lang/lang-fr.ts
+++ b/src/frontend/lang/lang-fr.ts
@@ -1833,8 +1833,8 @@ export const LANG_FR = {
     "collaboraOnlineEditDenied2": "ne peut pas être édité avec Collabora Online",
     "documentEditor_collaboraonline": "Ouvre la suite Collabora Online directement dans l'application Maarch Courrier",
     "canUpdateResourcesInSignatureBook": "Pouvoir modifier les documents intégrés au parapheur",
-    "admin_email_serverTour": "Vous devez paramétrer un serveur de mail afin de pouvoir créer des utilisateurs ou d'activer les notifications.",
-    "admin_notifTour": "Nous vous conseillons de paramétrer les notifications de bannettes",
+    "admin_email_serverTour": "Vous devez paramétrer un serveur de mail afin de pouvoir <b color=\"primary\">créer des utilisateurs</b> ou d'<b color=\"primary\">activer les notifications</b>.",
+    "admin_notifTour": "Nous allons paramétrer votre première notification",
     "includeFolderPerimeter": "Consulter les courriers hors périmètre dans les dossiers et courriers suivis",
     "getIt": "J'ai compris",
     "admin_email_serverTitle": "Paramétrer un serveur de mail",    
@@ -1844,11 +1844,15 @@ export const LANG_FR = {
     "emailTour2Description": "Il est fortement recommandé de tester les informations renseignées afin de s'assurer que la connexion soit effective.",
     "admin_notifTitle": "Gérer les notifications",
     "notifTourTitle": "Planifier",
-    "notifTourDescription": "Vous pouvez planifier vos notifications de manière précise",
+    "notifTourDescription": "Ensuite, nous allons <b color=\"primary\">planifier</b> la tâche.",
     "notifTour2Title": "Notification de bannettes",
-    "notifTour2Description": "Nous allons planifier la <b color=\"primary\">notification de bannettes</b> pour <b color=\"primary\">chaque jour à 8h00<b>.<br/><br/>Cela avertira les utilisateurs de nouveaux contenus dans leur bannettes.",
+    "notifTour2Description": "Nous allons configurer la <b color=\"primary\">notification de bannettes</b> pour avertir les utilisateurs de nouveaux contenus dans leur bannettes.",
     "notifTour3Title": "Période de la tâche",
-    "notifTour3Description": "Vous pouvez choisir différentes périodes pour paramétrer votre tâche",
+    "notifTour3Description": "Vous pouvez choisir différentes périodes pour paramétrer votre tâche.<br/></br/>Ici nous allons la paramétrer <b color=\"primary\">chaque jour à 8h00<b> ",
     "notifTour4Title": "Liste des tâches",
-    "notifTour4Description": "La liste de vos tâches actives apparaît ici"
+    "notifTour4Description": "La liste de vos <b color=\"primary\">tâches actives</b> apparaît ici",
+    "welcomeTourTitle": "Bienvenue",
+    "welcomeTourDescription": "Nous allons vous montrer certains points de configuration : <ul><li>Paraméter un <b color=\"primary\">serveur de mail</b></li><li>Configurer votre première <b color=\"primary\">notification</b></li></ul><br/>Pour commencer, cliquez sur <img style=\"width:32px;\" src=\"assets/admin_button.png\"/>",
+    "createScriptTourTitle": "Créer le script",
+    "createScriptTourDescription": "Avant de planifier la tâche, nous devons créer le script.",
 };
diff --git a/src/frontend/lang/lang-nl.ts b/src/frontend/lang/lang-nl.ts
index ba1adb0c073..2929933e1a1 100755
--- a/src/frontend/lang/lang-nl.ts
+++ b/src/frontend/lang/lang-nl.ts
@@ -1867,5 +1867,9 @@ export const LANG_NL = {
     "notifTour3Description": "Vous pouvez choisir différentes périodes pour paramétrer votre tâche__TO_TRANSLATE",
     "notifTour4Title": "Liste des tâches__TO_TRANSLATE",
     "notifTour4Description": "La liste de vos tâches actives apparaissent ici__TO_TRANSLATE",
-    "documentsOutOfPerimeter": "Certains documents sont en dehors de votre périmètre__TO_TRANSLATE"
+    "documentsOutOfPerimeter": "Certains documents sont en dehors de votre périmètre__TO_TRANSLATE",
+    "welcomeTourTitle": "Bienvenue__TO_TRANSLATE",
+    "welcomeTourDescription": "Nous allons vous montrer certains points de configuration : <ul><li>Paraméter un <b color=\"primary\">serveur de mail</b></li><li>Configurer votre première <b color=\"primary\">notification</b></li></ul><br/>Pour commencer, cliquez sur <img style=\"width:32px;\" src=\"assets/admin_button.png\"/>__TO_TRANSLATE",
+    "createScriptTourTitle": "Créer le script__TO_TRANSLATE",
+    "createScriptTourDescription": "Avant de planifier la tâche, nous devons créer le script.__TO_TRANSLATE"
 };
\ No newline at end of file
diff --git a/src/frontend/service/featureTour.service.ts b/src/frontend/service/featureTour.service.ts
index 5d35725b238..ba7f2326ba5 100644
--- a/src/frontend/service/featureTour.service.ts
+++ b/src/frontend/service/featureTour.service.ts
@@ -18,61 +18,75 @@ export class FeatureTourService {
     currentTour: any = null;
 
     tour: any[] = [
+        {
+            type: 'welcome',
+            stepId: 'welcome',
+            title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.welcomeTourTitle}</b>`,
+            description: this.lang.welcomeTourDescription,
+            redirectToAdmin: false,
+        },
         {
             type: 'email',
-            stepId: 'admin_email_server',
+            stepId: 'admin_email_server@administration',
             title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.admin_email_serverTitle}</b>`,
             description: this.lang.admin_email_serverTour,
-            redirectToAdmin : false,
+            redirectToAdmin: false,
         },
         {
             type: 'email',
             stepId: 'emailTour@administration/sendmail',
             title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.emailTourTitle}</b>`,
             description: this.lang.emailTourDescription,
-            redirectToAdmin : false,
+            redirectToAdmin: false,
         },
         {
             type: 'email',
             stepId: 'emailTour2@administration/sendmail',
             title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.emailTour2Title}</b>`,
             description: this.lang.emailTour2Description,
-            redirectToAdmin : false,
+            redirectToAdmin: false,
         },
         {
             type: 'notification',
-            stepId: 'admin_notif',
+            stepId: 'admin_notif@administration',
             title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.admin_notifTitle}</b>`,
             description: this.lang.admin_notifTour,
-            redirectToAdmin : false,
+            redirectToAdmin: false,
         },
         {
             type: 'notification',
-            stepId: 'notifTour@administration/notifications',
-            title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.notifTourTitle}</b>`,
-            description: this.lang.notifTourDescription,
-            redirectToAdmin : false,
+            stepId: 'BASKETS_Tour@administration/notifications',
+            title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.notifTour2Title}</b>`,
+            description: this.lang.notifTour2Description,
+            redirectToAdmin: false,
         },
         {
             type: 'notification',
-            stepId: 'notifTour2@administration/notifications',
-            title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.notifTour2Title}</b>`,
-            description: this.lang.notifTour2Description,
-            redirectToAdmin : false,
+            stepId: 'createScriptTour@administration/notifications/4',
+            title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.createScriptTourTitle}</b>`,
+            description: this.lang.createScriptTourDescription,
+            redirectToAdmin: false,
+        },
+        {
+            type: 'notification',
+            stepId: 'notifTour@administration/notifications',
+            title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.notifTourTitle}</b>`,
+            description: this.lang.notifTourDescription,
+            redirectToAdmin: false,
         },
         {
             type: 'notification',
             stepId: 'notifTour3@administration/notifications',
             title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.notifTour3Title}</b>`,
             description: this.lang.notifTour3Description,
-            redirectToAdmin : false,
+            redirectToAdmin: false,
         },
         {
             type: 'notification',
             stepId: 'notifTour4@administration/notifications',
             title: `<i class="far fa-question-circle" color="primary"></i>&nbsp;<b color="primary">${this.lang.notifTour4Title}</b>`,
             description: this.lang.notifTour4Description,
-            redirectToAdmin : true,
+            redirectToAdmin: true,
         },
     ];
 
@@ -90,38 +104,37 @@ export class FeatureTourService {
 
     init() {
         if (!this.functionService.empty(this.currentStepType)) {
-            setTimeout(() => {
-                const steps = this.tour.filter(step => step.type === this.currentStepType).map(step => step.stepId);
-                this.joyrideService.startTour(
-                    {
-                        customTexts: {
-                            next: '>>',
-                            prev: '<<',
-                            done: this.lang.getIt
-                        },
-                        steps: steps
-                    }
-                ).subscribe(
-                    step => {
-                        /*Do something*/
-                        this.currentTour = this.tour.filter((item: any) => item.stepId.split('@')[0] === step.name)[0];
-                        const containerElement = document.getElementsByClassName('joyride-step__container') as HTMLCollectionOf<HTMLElement> 
-                        containerElement[0].style.width = 'auto';
-                        containerElement[0].style.height = 'auto';
-                        document.getElementsByClassName('joyride-step__header')[0].innerHTML = `${this.currentTour.title}`;
-                        document.getElementsByClassName('joyride-step__body')[0].innerHTML = `${this.currentTour.description}`;
-                    },
-                    error => {
-                        /*handle error*/
+            const steps = this.tour.filter(step => step.type === this.currentStepType).map(step => step.stepId);
+            this.joyrideService.startTour(
+                {
+                    customTexts: {
+                        next: '>>',
+                        prev: '<<',
+                        done: this.lang.getIt
                     },
-                    () => {
-                        if (this.currentTour.redirectToAdmin) {
-                            this.router.navigate(['/administration']);
-                        }
-                        this.endTour();
+                    steps: steps,
+                    waitingTime: 500
+                }
+            ).subscribe(
+                step => {
+                    /*Do something*/
+                    this.currentTour = this.tour.filter((item: any) => item.stepId.split('@')[0] === step.name)[0];
+                    const containerElement = document.getElementsByClassName('joyride-step__container') as HTMLCollectionOf<HTMLElement>
+                    containerElement[0].style.width = 'auto';
+                    containerElement[0].style.height = 'auto';
+                    document.getElementsByClassName('joyride-step__header')[0].innerHTML = `${this.currentTour.title}`;
+                    document.getElementsByClassName('joyride-step__body')[0].innerHTML = `${this.currentTour.description}`;
+                },
+                error => {
+                    /*handle error*/
+                },
+                () => {
+                    if (this.currentTour.redirectToAdmin) {
+                        this.router.navigate(['/administration']);
                     }
-                );
-            }, 500);
+                    this.endTour();
+                }
+            );
         }
     }
 
-- 
GitLab