hakimio / ngx-ui-tour

✈️ UI tour for Angular apps
https://hakimio.github.io/ngx-ui-tour
MIT License
173 stars 26 forks source link

🐞 - [Ionic] tour end button is not working for one of the tour steps #163

Closed NehalCyncly closed 5 months ago

NehalCyncly commented 10 months ago

Which ngx-ui-tour-* package is the source of the bug?

ionic

Please provide a link to a minimal reproduction of the bug

No response

Description

Below is the sample code I am writing to implement a tour . till step 3 tourService.end() is working but once I reached to article step Id end tour is not working when i debug it its returning from the below cases in end() method of tour

 if (this.status === TourState.OFF) {
            return;
        }

TourComponent.js private tourStep: IStepOption[] =[ { anchorId: 'dashboard', stepId:'dashboard', content: 'content', title: 'Dashboard', // route: '/home', isOptional:true }, { anchorId: 'newconfiguration', stepId:'newconfiguration', content: 'New Configuration', title: 'New Configuration', route: '/home', isAsync:true }, { anchorId: 'catalog', stepId:'catalog', content: 'Here you can search for catalog, show models, change the view, filter catalog by next or expired versions, sort the catalog and update the list of catalog.', title: 'All Catalog', isAsync: true, route: '/catalog', delayBeforeStepShow:500 }, { anchorId:'article', stepId:'article', title:'Article', content:'Here you can found the article of choosen catalog', isAsync:true, route:'/article?catalog=BA355473-EB95-8AFA-A4E8-59B2B8DF8F67&serialnumber=1', duplicateAnchorHandling:'registerFirst', delayAfterNavigation:1000, delayBeforeStepShow:500 }, { anchorId: 'chatQuestion', stepId: 'chatQuestion', content: 'Some content', title: 'Chat Question', // route: '#/home', },
{ anchorId: 'mainmenu', stepId:'mainmenu', content: 'Some content', title: 'Main menu', isAsync: true, // route: '/home', duplicateAnchorHandling:'registerFirst', // delayAfterNavigation:5000, delayBeforeStepShow:500 }, { anchorId: 'mainmenuAttachement', stepId:'mainmenuAttachement', content: 'Some content', title: 'Attachment and Documents', isAsync: true,
delayBeforeStepShow:500
}, { anchorId: 'mainmenuAttachementInfo', stepId:'mainmenuAttachementInfo', content: 'Modal content', title: 'Info', delayBeforeStepShow:1000, isOptional:true
}, { anchorId: 'mainmenuAttachementMedia', stepId:'mainmenuAttachementMedia', content: 'Modal content', title: 'Media', delayBeforeStepShow:1000, isOptional:true
}, { anchorId: 'mainmenuAttachementVideo', stepId:'mainmenuAttachementVideo', content: 'Modal content', title: 'Video', delayBeforeStepShow:1000, isOptional:true
}, { anchorId: 'mainmenuAttachementAttachement', stepId:'mainmenuAttachementAttachement', content: 'Modal content', title: 'Attachment', delayBeforeStepShow:500, isOptional:true
},

{
  anchorId: 'setting-general',
  stepId: 'settinggeneral',
  content: 'Other content',
  title: 'General Settings',
  route: '/setting/general',
},
{
  anchorId: 'setting-print',
  stepId: 'settingprint',
  content: 'Other content',
  title: 'Print Settings',
  route: '/setting/print',
},
{
  anchorId: 'setting-language',
  stepId: 'settinglanguage',
  content: 'Other content',
  title: 'Language Settings',
  route: '/setting/language',
},
{
  anchorId: 'setting-view',
  stepId: 'settingview',
  content: 'Other content',
  title: 'View Settings',
  route: '/setting/view',
},
{
  anchorId: 'poolHeader',
  stepId: 'poolHeader',
  content: 'Some content',
  title: 'Plan menu',
  route: '/pool',
},
{
  anchorId: 'poolTable',
  stepId: 'poolTable',
  content: 'Some content',
  title: 'Plan table',
  route: '/pool',
  disableScrollToAnchor:true
},

];

public startTour() { if (this.tourService.getStatus() == 1){ this.tourService.end(); } let tour = this.tourService tour.initialize(this.tourStep, { enableBackdrop: true,
delayAfterNavigation:0, disableScrollToAnchor:true, }); }

endTour(){ this.tourService.end() } Please guide me if I am doing anything wrong

Angular version

16.0.4

Ngx UI Tour version

2.0.5

Which browsers have you used?

Which operating systems have you used?

hakimio commented 10 months ago

Can you create stackblitz reproduction of the issue?

NehalCyncly commented 10 months ago

I am sorry, It cant be possible it's huge project setup . but what i know is like its depends on routes I guess /article?catalog=BA355473-EB95-8AFA-A4E8-59B2B8DF8F67&serialnumber=1

hakimio commented 10 months ago

From your description of the issue, I can't see what's wrong. The tour is set to "end" state when it actually ends, there is an error (error is logged to console) or tour is re-initialized. You have to make a simple reproduction of the issue either on stackblitz or github. Or at least debug the tour service yourself to find out where exactly your tour is set to "end state" while it's still running.

NehalCyncly commented 10 months ago

I am using custom template for displaying tour popup tour.component.html

{{step.title}}

this is the whole code of tour.component.ts

import { Component } from '@angular/core'; import { Subject } from 'rxjs'; import { takeUntil, take, switchMap } from 'rxjs/operators'; import { Router } from '@angular/router'; import { TourService, IStepOption } from 'ngx-ui-tour-ionic' import { ModalController, Platform, LoadingController,PopoverController } from '@ionic/angular'; import { YesnoRevealComponent } from '@reveals/yesno-reveal/yesno-reveal.component'; import { MainmenuPopoverComponent } from '../header/mainmenu-popover/mainmenu-popover.component'; import { Model } from '@models/model.model'; import { ModelVM } from '@models/model-vm.model'; import { MediaInfoRevealComponent, MediaMenuItem } from '@reveals/media-info-reveal/media-info-reveal.component'; import { ModelStoreFacade } from '@core/models/+store/model-store.facade';

import { TranslationService } from '@core/translation/translation.service'; @Component({ selector: 'app-tour', templateUrl: './tour.component.html', styleUrls: ['./tour.component.scss'] }) export class TourComponent { private unsubscribe$ = new Subject(); setActiveTab = new Subject(); mainMenuOpenFlag:Boolean = false private tourStep: IStepOption[] =[ { anchorId: 'dashboard', stepId:'dashboard', content: 'content', title: 'Dashboard', // route: '/home', isOptional:true }, { anchorId: 'newconfiguration', stepId:'newconfiguration', content: 'New Configuration', title: 'New Configuration', route: '/home', isAsync:true }, { anchorId: 'catalog', stepId:'catalog', content: 'Here you can search for catalog, show models, change the view, filter catalog by next or expired versions, sort the catalog and update the list of catalog.', title: 'All Catalog', isAsync: true, route: '/catalog', delayBeforeStepShow:500 }, { anchorId:'article', stepId:'article', title:'Article', content:'Here you can found the article of choosen catalog', isAsync:true, route:'/article', duplicateAnchorHandling:'registerFirst', delayAfterNavigation:1000, delayBeforeStepShow:500 }, { anchorId: 'chatQuestion', stepId: 'chatQuestion', content: 'Some content', title: 'Chat Question', // route: '#/home', },
{ anchorId: 'mainmenu', stepId:'mainmenu', content: 'Some content', title: 'Main menu', isAsync: true, // route: '/home', duplicateAnchorHandling:'registerFirst', // delayAfterNavigation:5000, delayBeforeStepShow:500 }, { anchorId: 'mainmenuAttachement', stepId:'mainmenuAttachement', content: 'Some content', title: 'Attachment and Documents', isAsync: true,
delayBeforeStepShow:500
}, { anchorId: 'mainmenuAttachementInfo', stepId:'mainmenuAttachementInfo', content: 'Modal content', title: 'Info', delayBeforeStepShow:1000, isOptional:true
}, { anchorId: 'mainmenuAttachementMedia', stepId:'mainmenuAttachementMedia', content: 'Modal content', title: 'Media', delayBeforeStepShow:1000, isOptional:true
}, { anchorId: 'mainmenuAttachementVideo', stepId:'mainmenuAttachementVideo', content: 'Modal content', title: 'Video', delayBeforeStepShow:1000, isOptional:true
}, { anchorId: 'mainmenuAttachementAttachement', stepId:'mainmenuAttachementAttachement', content: 'Modal content', title: 'Attachment', delayBeforeStepShow:500, isOptional:true
},

{
  anchorId: 'setting-general',
  stepId: 'settinggeneral',
  content: 'Other content',
  title: 'General Settings',
  route: '/setting/general',
},
{
  anchorId: 'setting-print',
  stepId: 'settingprint',
  content: 'Other content',
  title: 'Print Settings',
  route: '/setting/print',
},
{
  anchorId: 'setting-language',
  stepId: 'settinglanguage',
  content: 'Other content',
  title: 'Language Settings',
  route: '/setting/language',
},
{
  anchorId: 'setting-view',
  stepId: 'settingview',
  content: 'Other content',
  title: 'View Settings',
  route: '/setting/view',
},
{
  anchorId: 'poolHeader',
  stepId: 'poolHeader',
  content: 'Some content',
  title: 'Plan menu',
  route: '/pool',
},
{
  anchorId: 'poolTable',
  stepId: 'poolTable',
  content: 'Some content',
  title: 'Plan table',
  route: '/pool',
  disableScrollToAnchor:true
},

]; public activeModel: ModelVM; constructor( private router: Router, public tourService : TourService, private popoverController: PopoverController, private modelStoreFacade: ModelStoreFacade, private modalController: ModalController, private translationService: TranslationService, ){ this.modelStoreFacade.activeModel$ .pipe(takeUntil(this.unsubscribe$)) .subscribe(value => this.activeModel = value); }

async nextTour(e,step){ console.log(step) if(step?.stepId == "chatQuestion"){ // this.openMainModalPopup(); let onDidDismiss = this.showMainmenuReveal({target:document.getElementById('menuClick')}); onDidDismiss.then(()=>{ console.log("Popover Closed") }) } else if(step?.stepId == "mainmenuAttachement"){ this.dismissMainmenuPopover() this.showModelinfoReveal(this.activeModel, 'attachment') } else if(step?.stepId == "mainmenuAttachementInfo"){ this.setActiveTab?.next('media') } else if(step?.stepId == "mainmenuAttachementMedia"){ this.setActiveTab?.next('video') } else if(step?.stepId == "mainmenuAttachementVideo"){
this.dismissInfoModal(); }

await this.tourService.next();

} async prevTour(e,step){ console.log(step) if(step?.stepId == "mainmenu"){ this.dismissMainmenuPopover(); }else if(step?.stepId == "settinggeneral"){ this.showModelinfoReveal(this.activeModel, 'attachment') } else if(step?.stepId == 'mainmenuAttachementInfo'){ this.dismissInfoModal(); this.showMainmenuReveal({target:document.getElementById('menuClick')});
} await this.tourService.prev() } endTour(){ this.tourService.end() } public startTour() { if (this.tourService.getStatus() == 1){ this.tourService.end(); } let tour = this.tourService tour.initialize(this.tourStep, { enableBackdrop: true,
delayAfterNavigation:0, disableScrollToAnchor:true, });

let path = this.router.url;
if(path?.includes('setting')){
  tour.startAt('settinggeneral');
  const tourSubscribe =()=>{
     let tourSubscribed = tour.stepShow$.subscribe(async(e:any)=>{
        if(e?.step?.anchorId == "setting-view"){
          tourSubscribed.unsubscribe();
          tour.pause();   
          const result = await this.showYesnoReveal({
            // textTranslationKey: 'W4177',
            text: 'Do you want to continue with tour guide?',
            // noLabelTranslationKey: ''
          }).catch(() => false);
          console.log("result",result);      
          if (!result || !result.data || !result.data.confirmed) { this.tourService.end();return; } 
          if(result.data.confirmed){
            tourSubscribe()
           }
        }
    }) 
  }
   tourSubscribe();
}
else{
  tour.start();
}
this.tourService.end$.subscribe(() => {
  if(this.mainMenuOpenFlag) this.dismissMainmenuPopover();
});

} private async showYesnoReveal(params: any): Promise { const modal = await this.modalController.create({ component: YesnoRevealComponent, presentingElement: await this.modalController.getTop(), componentProps: { color: 'danger', titleTranslationKey: 'W1559', ...params }, cssClass: 'auto-height' }); await modal.present(); return await modal.onDidDismiss(); } async showMainmenuReveal(ev: any) { const popover = await this.popoverController.create({ component: MainmenuPopoverComponent, event: ev, cssClass: 'mainmenu-popover dynamicTour', backdropDismiss:true }); await popover.present(); this.mainMenuOpenFlag = true; return await popover.onDidDismiss(); } async dismissMainmenuPopover(){ console.log(await this.popoverController.dismiss()) this.mainMenuOpenFlag = false; await this.popoverController.dismiss() }

async showModelinfoReveal(model: Model, activeView: 'info' | 'media' | 'attachment' = 'info') {
this.translationService.getTranslation$('W1144', { fallback: 'Modellinformation' }).pipe( take(1), switchMap(async (translation) => { const modal = await this.modalController.create({ component: MediaInfoRevealComponent, presentingElement: await this.modalController.getTop(), // Get the top-most ion-modal cssClass: 'auto-height large-width', componentProps: { item: model, activeView:activeView, setActiveTab:this.setActiveTab, title: translation + ': ' + model.visibleLabel, catalogUid: model.catalog, seriesID: model.serialnumber,
stringifyText: (model: ModelVM) => { if (!model) { return ''; } return model.infotexts; }, } }); return await modal.present(); }), takeUntil(this.unsubscribe$) ).subscribe(); } dismissInfoModal(){ this.modalController?.dismiss(); } }

hakimio commented 10 months ago

This is not helpful. As I said before: either create a minimal reproduction of the issue (stackblitz/github repo) or debug the tour service yourself to see why your tour has incorrect state.

hakimio commented 5 months ago

Fixed in v3.0.3.