From 15c340660799a4e24cd6fed2f93361375f6c9a39 Mon Sep 17 00:00:00 2001
From: Andreas Fernandez <a.fernandez@scripting-base.de>
Date: Wed, 16 Nov 2022 08:26:53 +0100
Subject: [PATCH] [TASK] Make backdrop of wizards static
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Multi-step wizards may contain a lot of different steps (e.g. in
localization or form management) and accidentally closing the wizard by
clicking the backdrop may lead to frustration.

To prevent this issue, the backdrop of such wizards is now static.

Resolves: #99102
Releases: main
Change-Id: I7e7adf6a8e30cc067fbadd73016cf01ec9bdf4d2
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/76639
Tested-by: core-ci <typo3@b13.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Frank Nägler <frank.naegler@typo3.com>
Reviewed-by: Frank Nägler <frank.naegler@typo3.com>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
---
 Build/Sources/TypeScript/backend/multi-step-wizard.ts           | 1 +
 Build/Sources/TypeScript/backend/wizard.ts                      | 1 +
 .../backend/Resources/Public/JavaScript/multi-step-wizard.js    | 2 +-
 typo3/sysext/backend/Resources/Public/JavaScript/wizard.js      | 2 +-
 4 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/Build/Sources/TypeScript/backend/multi-step-wizard.ts b/Build/Sources/TypeScript/backend/multi-step-wizard.ts
index 757da7616ce6..bb0acf68a1e1 100644
--- a/Build/Sources/TypeScript/backend/multi-step-wizard.ts
+++ b/Build/Sources/TypeScript/backend/multi-step-wizard.ts
@@ -134,6 +134,7 @@ class MultiStepWizard {
       title: firstSlide.title,
       content: $slides,
       severity: firstSlide.severity,
+      staticBackdrop: true,
       buttons: [{
         text: top.TYPO3.lang['wizard.button.cancel'],
         active: true,
diff --git a/Build/Sources/TypeScript/backend/wizard.ts b/Build/Sources/TypeScript/backend/wizard.ts
index 1279bb475396..52fffde31dee 100644
--- a/Build/Sources/TypeScript/backend/wizard.ts
+++ b/Build/Sources/TypeScript/backend/wizard.ts
@@ -104,6 +104,7 @@ class Wizard {
       title: firstSlide.title,
       content: $slides,
       severity: firstSlide.severity,
+      staticBackdrop: true,
       buttons: [{
         text: top.TYPO3.lang['wizard.button.cancel'],
         active: true,
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/multi-step-wizard.js b/typo3/sysext/backend/Resources/Public/JavaScript/multi-step-wizard.js
index d64a68004164..1490f23de708 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/multi-step-wizard.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/multi-step-wizard.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-import{SeverityEnum}from"@typo3/backend/enum/severity.js";import $ from"jquery";import Modal from"@typo3/backend/modal.js";import Severity from"@typo3/backend/severity.js";import Icons from"@typo3/backend/icons.js";class MultiStepWizard{constructor(){this.setup={slides:[],settings:{},forceSelection:!0,$carousel:null},this.originalSetup=$.extend(!0,{},this.setup)}set(e,t){return this.setup.settings[e]=t,this}addSlide(e,t,s="",i=SeverityEnum.info,r,a){const l={identifier:e,title:t,content:s,severity:i,progressBarTitle:r,callback:a};return this.setup.slides.push(l),this}addFinalProcessingSlide(e){return e||(e=()=>{this.dismiss()}),Icons.getIcon("spinner-circle",Icons.sizes.default,null,null).then((t=>{let s=$("<div />",{class:"text-center"}).append(t);this.addSlide("final-processing-slide",top.TYPO3.lang["wizard.processing.title"],s[0].outerHTML,Severity.info,null,e)}))}show(){let e=this.generateSlides(),t=this.setup.slides[0];Modal.advanced({title:t.title,content:e,severity:t.severity,buttons:[{text:top.TYPO3.lang["wizard.button.cancel"],active:!0,btnClass:"btn-default float-start",name:"cancel",trigger:()=>{this.getComponent().trigger("wizard-dismiss")}},{text:top.TYPO3.lang["wizard.button.prev"],btnClass:"btn-"+Severity.getCssClass(t.severity),name:"prev"},{text:top.TYPO3.lang["wizard.button.next"],btnClass:"btn-"+Severity.getCssClass(t.severity),name:"next"}],additionalCssClasses:["modal-multi-step-wizard"],callback:()=>{this.addButtonContainer(),this.addProgressBar(),this.initializeEvents()}});this.getComponent().on("wizard-visible",(()=>{this.runSlideCallback(t,this.setup.$carousel.find(".carousel-item").first())})).on("wizard-dismissed",(()=>{this.setup=$.extend(!0,{},this.originalSetup)}))}getComponent(){return null===this.setup.$carousel&&this.generateSlides(),this.setup.$carousel}dismiss(){Modal.dismiss()}lockNextStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!0),e}unlockNextStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!1),e}lockPrevStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="prev"]');return e.prop("disabled",!0),e}unlockPrevStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="prev"]');return e.prop("disabled",!1),e}triggerStepButton(e){let t=this.setup.$carousel.closest(".modal").find('button[name="'+e+'"]');return t.length>0&&!0!==t.prop("disabled")&&t.trigger("click"),t}blurCancelStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="cancel"]');return e.trigger("blur"),e}initializeEvents(){let e=this.setup.$carousel.closest(".modal");this.initializeSlideNextEvent(e),this.initializeSlidePrevEvent(e),this.setup.$carousel.on("slide.bs.carousel",(t=>{"left"===t.direction?this.nextSlideChanges(e):this.prevSlideChanges(e)})).on("slid.bs.carousel",(e=>{let t=this.setup.$carousel.data("currentIndex"),s=this.setup.slides[t];this.runSlideCallback(s,$(e.relatedTarget)),this.setup.forceSelection&&this.lockNextStep()}));let t=this.getComponent();t.on("wizard-dismiss",this.dismiss),Modal.currentModal.addEventListener("typo3-modal-hidden",(()=>{t.trigger("wizard-dismissed")})),Modal.currentModal.addEventListener("typo3-modal-shown",(()=>{t.trigger("wizard-visible")}))}initializeSlideNextEvent(e){e.find(".modal-footer").find('button[name="next"]').off().on("click",(()=>{this.setup.$carousel.carousel("next")}))}initializeSlidePrevEvent(e){e.find(".modal-footer").find('button[name="prev"]').off().on("click",(()=>{this.setup.$carousel.carousel("prev")}))}nextSlideChanges(e){this.initializeSlideNextEvent(e);const t=e.find(".modal-title"),s=e.find(".modal-footer"),i=this.setup.$carousel.data("currentSlide")+1,r=this.setup.$carousel.data("currentIndex"),a=r+1;t.text(this.setup.slides[a].title),this.setup.$carousel.data("currentSlide",i),this.setup.$carousel.data("currentIndex",a);const l=s.find(".progress-bar");l.eq(r).width("0%"),l.eq(a).width(this.setup.$carousel.data("initialStep")*i+"%").removeClass("inactive"),this.updateCurrentSeverity(e,r,a)}prevSlideChanges(e){this.initializeSlidePrevEvent(e);const t=e.find(".modal-title"),s=e.find(".modal-footer"),i=s.find('button[name="next"]'),r=this.setup.$carousel.data("currentSlide")-1,a=this.setup.$carousel.data("currentIndex"),l=a-1;this.setup.$carousel.data("currentSlide",r),this.setup.$carousel.data("currentIndex",l),t.text(this.setup.slides[l].title),s.find(".progress-bar.last-step").width(this.setup.$carousel.data("initialStep")+"%").text(this.getProgressBarTitle(this.setup.$carousel.data("slideCount")-1)),i.text(top.TYPO3.lang["wizard.button.next"]);const n=s.find(".progress-bar");n.eq(a).width(this.setup.$carousel.data("initialStep")+"%").addClass("inactive"),n.eq(l).width(this.setup.$carousel.data("initialStep")*r+"%").removeClass("inactive"),this.updateCurrentSeverity(e,a,l)}updateCurrentSeverity(e,t,s){e.find(".modal-footer").find('button[name="next"]').removeClass("btn-"+Severity.getCssClass(this.setup.slides[t].severity)).addClass("btn-"+Severity.getCssClass(this.setup.slides[s].severity)),e.removeClass("modal-severity-"+Severity.getCssClass(this.setup.slides[t].severity)).addClass("modal-severity-"+Severity.getCssClass(this.setup.slides[s].severity))}getProgressBarTitle(e){let t;return t=null===this.setup.slides[e].progressBarTitle?0===e?top.TYPO3.lang["wizard.progressStep.start"]:e>=this.setup.$carousel.data("slideCount")-1?top.TYPO3.lang["wizard.progressStep.finish"]:top.TYPO3.lang["wizard.progressStep"]+String(e+1):this.setup.slides[e].progressBarTitle,t}runSlideCallback(e,t){"function"==typeof e.callback&&e.callback(t,this.setup.settings,e.identifier)}addProgressBar(){let e,t=this.setup.$carousel.find(".carousel-item").length,s=Math.max(1,t),i=this.setup.$carousel.closest(".modal").find(".modal-footer");if(e=Math.round(100/s),this.setup.$carousel.data("initialStep",e).data("slideCount",s).data("realSlideCount",t).data("currentIndex",0).data("currentSlide",1),s>1){i.prepend($("<div />",{class:"progress"}));for(let t=0;t<this.setup.slides.length;++t){let s;s=0===t?"progress-bar first-step":t===this.setup.$carousel.data("slideCount")-1?"progress-bar last-step inactive":"progress-bar step inactive",i.find(".progress").append($("<div />",{role:"progressbar",class:s,"aria-valuemin":0,"aria-valuenow":e,"aria-valuemax":100}).width(e+"%").text(this.getProgressBarTitle(t)))}}}addButtonContainer(){this.setup.$carousel.closest(".modal").find(".modal-footer .btn").wrapAll('<div class="modal-btn-group" />')}generateSlides(){if(null!==this.setup.$carousel)return this.setup.$carousel;let e='<div class="carousel slide" data-bs-ride="false"><div class="carousel-inner" role="listbox">';for(let t=0;t<this.setup.slides.length;++t){let s=this.setup.slides[t],i=s.content;"object"==typeof i&&(i=i.html()),e+='<div class="carousel-item" data-bs-slide="'+s.identifier+'" data-step="'+t+'">'+i+"</div>"}return e+="</div></div>",this.setup.$carousel=$(e),this.setup.$carousel.find(".carousel-item").first().addClass("active"),this.setup.$carousel}}let multistepWizardObject;try{window.opener&&window.opener.TYPO3&&window.opener.TYPO3.MultiStepWizard&&(multistepWizardObject=window.opener.TYPO3.MultiStepWizard),parent&&parent.window.TYPO3&&parent.window.TYPO3.MultiStepWizard&&(multistepWizardObject=parent.window.TYPO3.MultiStepWizard),top&&top.TYPO3&&top.TYPO3.MultiStepWizard&&(multistepWizardObject=top.TYPO3.MultiStepWizard)}catch(e){}multistepWizardObject||(multistepWizardObject=new MultiStepWizard,"undefined"!=typeof TYPO3&&(TYPO3.MultiStepWizard=multistepWizardObject));export default multistepWizardObject;
\ No newline at end of file
+import{SeverityEnum}from"@typo3/backend/enum/severity.js";import $ from"jquery";import Modal from"@typo3/backend/modal.js";import Severity from"@typo3/backend/severity.js";import Icons from"@typo3/backend/icons.js";class MultiStepWizard{constructor(){this.setup={slides:[],settings:{},forceSelection:!0,$carousel:null},this.originalSetup=$.extend(!0,{},this.setup)}set(t,e){return this.setup.settings[t]=e,this}addSlide(t,e,s="",i=SeverityEnum.info,r,a){const l={identifier:t,title:e,content:s,severity:i,progressBarTitle:r,callback:a};return this.setup.slides.push(l),this}addFinalProcessingSlide(t){return t||(t=()=>{this.dismiss()}),Icons.getIcon("spinner-circle",Icons.sizes.default,null,null).then((e=>{let s=$("<div />",{class:"text-center"}).append(e);this.addSlide("final-processing-slide",top.TYPO3.lang["wizard.processing.title"],s[0].outerHTML,Severity.info,null,t)}))}show(){let t=this.generateSlides(),e=this.setup.slides[0];Modal.advanced({title:e.title,content:t,severity:e.severity,staticBackdrop:!0,buttons:[{text:top.TYPO3.lang["wizard.button.cancel"],active:!0,btnClass:"btn-default float-start",name:"cancel",trigger:()=>{this.getComponent().trigger("wizard-dismiss")}},{text:top.TYPO3.lang["wizard.button.prev"],btnClass:"btn-"+Severity.getCssClass(e.severity),name:"prev"},{text:top.TYPO3.lang["wizard.button.next"],btnClass:"btn-"+Severity.getCssClass(e.severity),name:"next"}],additionalCssClasses:["modal-multi-step-wizard"],callback:()=>{this.addButtonContainer(),this.addProgressBar(),this.initializeEvents()}});this.getComponent().on("wizard-visible",(()=>{this.runSlideCallback(e,this.setup.$carousel.find(".carousel-item").first())})).on("wizard-dismissed",(()=>{this.setup=$.extend(!0,{},this.originalSetup)}))}getComponent(){return null===this.setup.$carousel&&this.generateSlides(),this.setup.$carousel}dismiss(){Modal.dismiss()}lockNextStep(){let t=this.setup.$carousel.closest(".modal").find('button[name="next"]');return t.prop("disabled",!0),t}unlockNextStep(){let t=this.setup.$carousel.closest(".modal").find('button[name="next"]');return t.prop("disabled",!1),t}lockPrevStep(){let t=this.setup.$carousel.closest(".modal").find('button[name="prev"]');return t.prop("disabled",!0),t}unlockPrevStep(){let t=this.setup.$carousel.closest(".modal").find('button[name="prev"]');return t.prop("disabled",!1),t}triggerStepButton(t){let e=this.setup.$carousel.closest(".modal").find('button[name="'+t+'"]');return e.length>0&&!0!==e.prop("disabled")&&e.trigger("click"),e}blurCancelStep(){let t=this.setup.$carousel.closest(".modal").find('button[name="cancel"]');return t.trigger("blur"),t}initializeEvents(){let t=this.setup.$carousel.closest(".modal");this.initializeSlideNextEvent(t),this.initializeSlidePrevEvent(t),this.setup.$carousel.on("slide.bs.carousel",(e=>{"left"===e.direction?this.nextSlideChanges(t):this.prevSlideChanges(t)})).on("slid.bs.carousel",(t=>{let e=this.setup.$carousel.data("currentIndex"),s=this.setup.slides[e];this.runSlideCallback(s,$(t.relatedTarget)),this.setup.forceSelection&&this.lockNextStep()}));let e=this.getComponent();e.on("wizard-dismiss",this.dismiss),Modal.currentModal.addEventListener("typo3-modal-hidden",(()=>{e.trigger("wizard-dismissed")})),Modal.currentModal.addEventListener("typo3-modal-shown",(()=>{e.trigger("wizard-visible")}))}initializeSlideNextEvent(t){t.find(".modal-footer").find('button[name="next"]').off().on("click",(()=>{this.setup.$carousel.carousel("next")}))}initializeSlidePrevEvent(t){t.find(".modal-footer").find('button[name="prev"]').off().on("click",(()=>{this.setup.$carousel.carousel("prev")}))}nextSlideChanges(t){this.initializeSlideNextEvent(t);const e=t.find(".modal-title"),s=t.find(".modal-footer"),i=this.setup.$carousel.data("currentSlide")+1,r=this.setup.$carousel.data("currentIndex"),a=r+1;e.text(this.setup.slides[a].title),this.setup.$carousel.data("currentSlide",i),this.setup.$carousel.data("currentIndex",a);const l=s.find(".progress-bar");l.eq(r).width("0%"),l.eq(a).width(this.setup.$carousel.data("initialStep")*i+"%").removeClass("inactive"),this.updateCurrentSeverity(t,r,a)}prevSlideChanges(t){this.initializeSlidePrevEvent(t);const e=t.find(".modal-title"),s=t.find(".modal-footer"),i=s.find('button[name="next"]'),r=this.setup.$carousel.data("currentSlide")-1,a=this.setup.$carousel.data("currentIndex"),l=a-1;this.setup.$carousel.data("currentSlide",r),this.setup.$carousel.data("currentIndex",l),e.text(this.setup.slides[l].title),s.find(".progress-bar.last-step").width(this.setup.$carousel.data("initialStep")+"%").text(this.getProgressBarTitle(this.setup.$carousel.data("slideCount")-1)),i.text(top.TYPO3.lang["wizard.button.next"]);const n=s.find(".progress-bar");n.eq(a).width(this.setup.$carousel.data("initialStep")+"%").addClass("inactive"),n.eq(l).width(this.setup.$carousel.data("initialStep")*r+"%").removeClass("inactive"),this.updateCurrentSeverity(t,a,l)}updateCurrentSeverity(t,e,s){t.find(".modal-footer").find('button[name="next"]').removeClass("btn-"+Severity.getCssClass(this.setup.slides[e].severity)).addClass("btn-"+Severity.getCssClass(this.setup.slides[s].severity)),t.removeClass("modal-severity-"+Severity.getCssClass(this.setup.slides[e].severity)).addClass("modal-severity-"+Severity.getCssClass(this.setup.slides[s].severity))}getProgressBarTitle(t){let e;return e=null===this.setup.slides[t].progressBarTitle?0===t?top.TYPO3.lang["wizard.progressStep.start"]:t>=this.setup.$carousel.data("slideCount")-1?top.TYPO3.lang["wizard.progressStep.finish"]:top.TYPO3.lang["wizard.progressStep"]+String(t+1):this.setup.slides[t].progressBarTitle,e}runSlideCallback(t,e){"function"==typeof t.callback&&t.callback(e,this.setup.settings,t.identifier)}addProgressBar(){let t,e=this.setup.$carousel.find(".carousel-item").length,s=Math.max(1,e),i=this.setup.$carousel.closest(".modal").find(".modal-footer");if(t=Math.round(100/s),this.setup.$carousel.data("initialStep",t).data("slideCount",s).data("realSlideCount",e).data("currentIndex",0).data("currentSlide",1),s>1){i.prepend($("<div />",{class:"progress"}));for(let e=0;e<this.setup.slides.length;++e){let s;s=0===e?"progress-bar first-step":e===this.setup.$carousel.data("slideCount")-1?"progress-bar last-step inactive":"progress-bar step inactive",i.find(".progress").append($("<div />",{role:"progressbar",class:s,"aria-valuemin":0,"aria-valuenow":t,"aria-valuemax":100}).width(t+"%").text(this.getProgressBarTitle(e)))}}}addButtonContainer(){this.setup.$carousel.closest(".modal").find(".modal-footer .btn").wrapAll('<div class="modal-btn-group" />')}generateSlides(){if(null!==this.setup.$carousel)return this.setup.$carousel;let t='<div class="carousel slide" data-bs-ride="false"><div class="carousel-inner" role="listbox">';for(let e=0;e<this.setup.slides.length;++e){let s=this.setup.slides[e],i=s.content;"object"==typeof i&&(i=i.html()),t+='<div class="carousel-item" data-bs-slide="'+s.identifier+'" data-step="'+e+'">'+i+"</div>"}return t+="</div></div>",this.setup.$carousel=$(t),this.setup.$carousel.find(".carousel-item").first().addClass("active"),this.setup.$carousel}}let multistepWizardObject;try{window.opener&&window.opener.TYPO3&&window.opener.TYPO3.MultiStepWizard&&(multistepWizardObject=window.opener.TYPO3.MultiStepWizard),parent&&parent.window.TYPO3&&parent.window.TYPO3.MultiStepWizard&&(multistepWizardObject=parent.window.TYPO3.MultiStepWizard),top&&top.TYPO3&&top.TYPO3.MultiStepWizard&&(multistepWizardObject=top.TYPO3.MultiStepWizard)}catch(t){}multistepWizardObject||(multistepWizardObject=new MultiStepWizard,"undefined"!=typeof TYPO3&&(TYPO3.MultiStepWizard=multistepWizardObject));export default multistepWizardObject;
\ No newline at end of file
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/wizard.js b/typo3/sysext/backend/Resources/Public/JavaScript/wizard.js
index c479dc267795..c332c24e3f37 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/wizard.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/wizard.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-import{SeverityEnum}from"@typo3/backend/enum/severity.js";import $ from"jquery";import{default as Modal}from"@typo3/backend/modal.js";import Severity from"@typo3/backend/severity.js";import Icons from"@typo3/backend/icons.js";class Wizard{constructor(){this.setup={slides:[],settings:{},forceSelection:!0,$carousel:null},this.originalSetup=$.extend(!0,{},this.setup)}set(e,t){return this.setup.settings[e]=t,this}addSlide(e,t,s="",i=SeverityEnum.info,a){const r={identifier:e,title:t,content:s,severity:i,callback:a};return this.setup.slides.push(r),this}addFinalProcessingSlide(e){return e||(e=()=>{this.dismiss()}),Icons.getIcon("spinner-circle-dark",Icons.sizes.large,null,null).then((t=>{let s=$("<div />",{class:"text-center"}).append(t);this.addSlide("final-processing-slide",top.TYPO3.lang["wizard.processing.title"],s[0].outerHTML,Severity.info,e)}))}show(){let e=this.generateSlides(),t=this.setup.slides[0];const s=Modal.advanced({title:t.title,content:e,severity:t.severity,buttons:[{text:top.TYPO3.lang["wizard.button.cancel"],active:!0,btnClass:"btn-default",name:"cancel",trigger:()=>{this.getComponent().trigger("wizard-dismiss")}},{text:top.TYPO3.lang["wizard.button.next"],btnClass:"btn-"+Severity.getCssClass(t.severity),name:"next"}],callback:()=>{this.addProgressBar(),this.initializeEvents(s)}});this.setup.forceSelection&&this.lockNextStep(),this.getComponent().on("wizard-visible",(()=>{this.runSlideCallback(t,this.setup.$carousel.find(".carousel-item").first())})).on("wizard-dismissed",(()=>{this.setup=$.extend(!0,{},this.originalSetup)}))}getComponent(){return null===this.setup.$carousel&&this.generateSlides(),this.setup.$carousel}dismiss(){Modal.dismiss()}lockNextStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!0),e}unlockNextStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!1),e}setForceSelection(e){this.setup.forceSelection=e}initializeEvents(e){let t=this.setup.$carousel.closest(".modal"),s=t.find(".modal-title"),i=t.find(".modal-footer"),a=i.find('button[name="next"]');a.on("click",(()=>{this.setup.$carousel.carousel("next")})),this.setup.$carousel.on("slide.bs.carousel",(()=>{let e=this.setup.$carousel.data("currentSlide")+1,r=this.setup.$carousel.data("currentIndex")+1;s.text(this.setup.slides[r].title),this.setup.$carousel.data("currentSlide",e),this.setup.$carousel.data("currentIndex",r),e>=this.setup.$carousel.data("realSlideCount")?(t.find(".modal-header .close").remove(),i.slideUp()):i.find(".progress-bar").width(this.setup.$carousel.data("initialStep")*e+"%").text(top.TYPO3.lang["wizard.progress"].replace("{0}",e).replace("{1}",this.setup.$carousel.data("slideCount"))),a.removeClass("btn-"+Severity.getCssClass(this.setup.slides[r-1].severity)).addClass("btn-"+Severity.getCssClass(this.setup.slides[r].severity)),t.removeClass("modal-severity-"+Severity.getCssClass(this.setup.slides[r-1].severity)).addClass("modal-severity-"+Severity.getCssClass(this.setup.slides[r].severity))})).on("slid.bs.carousel",(e=>{let t=this.setup.$carousel.data("currentIndex"),s=this.setup.slides[t];this.runSlideCallback(s,$(e.relatedTarget)),this.setup.forceSelection&&this.lockNextStep()}));let r=this.getComponent();r.on("wizard-dismiss",this.dismiss),e.addEventListener("typo3-modal-hidden",(()=>{r.trigger("wizard-dismissed")})),e.addEventListener("typo3-modal-shown",(()=>{r.trigger("wizard-visible")}))}runSlideCallback(e,t){"function"==typeof e.callback&&e.callback(t,this.setup.settings,e.identifier)}addProgressBar(){let e,t=this.setup.$carousel.find(".carousel-item").length,s=Math.max(1,t),i=this.setup.$carousel.closest(".modal").find(".modal-footer");e=Math.round(100/s),this.setup.$carousel.data("initialStep",e).data("slideCount",s).data("realSlideCount",t).data("currentIndex",0).data("currentSlide",1),s>1&&i.prepend($("<div />",{class:"progress"}).append($("<div />",{role:"progressbar",class:"progress-bar","aria-valuemin":0,"aria-valuenow":e,"aria-valuemax":100}).width(e+"%").text(top.TYPO3.lang["wizard.progress"].replace("{0}","1").replace("{1}",s))))}generateSlides(){if(null!==this.setup.$carousel)return this.setup.$carousel;let e='<div class="carousel slide" data-bs-ride="false"><div class="carousel-inner" role="listbox">';for(let t of Object.values(this.setup.slides)){let s=t.content;"object"==typeof s&&(s=s.html()),e+='<div class="carousel-item" data-bs-slide="'+t.identifier+'">'+s+"</div>"}return e+="</div></div>",this.setup.$carousel=$(e),this.setup.$carousel.find(".carousel-item").first().addClass("active"),this.setup.$carousel}}let wizardObject;try{window.opener&&window.opener.TYPO3&&window.opener.TYPO3.Wizard&&(wizardObject=window.opener.TYPO3.Wizard),parent&&parent.window.TYPO3&&parent.window.TYPO3.Wizard&&(wizardObject=parent.window.TYPO3.Wizard),top&&top.TYPO3&&top.TYPO3.Wizard&&(wizardObject=top.TYPO3.Wizard)}catch{}wizardObject||(wizardObject=new Wizard,"undefined"!=typeof TYPO3&&(TYPO3.Wizard=wizardObject));export default wizardObject;
\ No newline at end of file
+import{SeverityEnum}from"@typo3/backend/enum/severity.js";import $ from"jquery";import{default as Modal}from"@typo3/backend/modal.js";import Severity from"@typo3/backend/severity.js";import Icons from"@typo3/backend/icons.js";class Wizard{constructor(){this.setup={slides:[],settings:{},forceSelection:!0,$carousel:null},this.originalSetup=$.extend(!0,{},this.setup)}set(e,t){return this.setup.settings[e]=t,this}addSlide(e,t,s="",i=SeverityEnum.info,a){const r={identifier:e,title:t,content:s,severity:i,callback:a};return this.setup.slides.push(r),this}addFinalProcessingSlide(e){return e||(e=()=>{this.dismiss()}),Icons.getIcon("spinner-circle-dark",Icons.sizes.large,null,null).then((t=>{let s=$("<div />",{class:"text-center"}).append(t);this.addSlide("final-processing-slide",top.TYPO3.lang["wizard.processing.title"],s[0].outerHTML,Severity.info,e)}))}show(){let e=this.generateSlides(),t=this.setup.slides[0];const s=Modal.advanced({title:t.title,content:e,severity:t.severity,staticBackdrop:!0,buttons:[{text:top.TYPO3.lang["wizard.button.cancel"],active:!0,btnClass:"btn-default",name:"cancel",trigger:()=>{this.getComponent().trigger("wizard-dismiss")}},{text:top.TYPO3.lang["wizard.button.next"],btnClass:"btn-"+Severity.getCssClass(t.severity),name:"next"}],callback:()=>{this.addProgressBar(),this.initializeEvents(s)}});this.setup.forceSelection&&this.lockNextStep(),this.getComponent().on("wizard-visible",(()=>{this.runSlideCallback(t,this.setup.$carousel.find(".carousel-item").first())})).on("wizard-dismissed",(()=>{this.setup=$.extend(!0,{},this.originalSetup)}))}getComponent(){return null===this.setup.$carousel&&this.generateSlides(),this.setup.$carousel}dismiss(){Modal.dismiss()}lockNextStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!0),e}unlockNextStep(){let e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!1),e}setForceSelection(e){this.setup.forceSelection=e}initializeEvents(e){let t=this.setup.$carousel.closest(".modal"),s=t.find(".modal-title"),i=t.find(".modal-footer"),a=i.find('button[name="next"]');a.on("click",(()=>{this.setup.$carousel.carousel("next")})),this.setup.$carousel.on("slide.bs.carousel",(()=>{let e=this.setup.$carousel.data("currentSlide")+1,r=this.setup.$carousel.data("currentIndex")+1;s.text(this.setup.slides[r].title),this.setup.$carousel.data("currentSlide",e),this.setup.$carousel.data("currentIndex",r),e>=this.setup.$carousel.data("realSlideCount")?(t.find(".modal-header .close").remove(),i.slideUp()):i.find(".progress-bar").width(this.setup.$carousel.data("initialStep")*e+"%").text(top.TYPO3.lang["wizard.progress"].replace("{0}",e).replace("{1}",this.setup.$carousel.data("slideCount"))),a.removeClass("btn-"+Severity.getCssClass(this.setup.slides[r-1].severity)).addClass("btn-"+Severity.getCssClass(this.setup.slides[r].severity)),t.removeClass("modal-severity-"+Severity.getCssClass(this.setup.slides[r-1].severity)).addClass("modal-severity-"+Severity.getCssClass(this.setup.slides[r].severity))})).on("slid.bs.carousel",(e=>{let t=this.setup.$carousel.data("currentIndex"),s=this.setup.slides[t];this.runSlideCallback(s,$(e.relatedTarget)),this.setup.forceSelection&&this.lockNextStep()}));let r=this.getComponent();r.on("wizard-dismiss",this.dismiss),e.addEventListener("typo3-modal-hidden",(()=>{r.trigger("wizard-dismissed")})),e.addEventListener("typo3-modal-shown",(()=>{r.trigger("wizard-visible")}))}runSlideCallback(e,t){"function"==typeof e.callback&&e.callback(t,this.setup.settings,e.identifier)}addProgressBar(){let e,t=this.setup.$carousel.find(".carousel-item").length,s=Math.max(1,t),i=this.setup.$carousel.closest(".modal").find(".modal-footer");e=Math.round(100/s),this.setup.$carousel.data("initialStep",e).data("slideCount",s).data("realSlideCount",t).data("currentIndex",0).data("currentSlide",1),s>1&&i.prepend($("<div />",{class:"progress"}).append($("<div />",{role:"progressbar",class:"progress-bar","aria-valuemin":0,"aria-valuenow":e,"aria-valuemax":100}).width(e+"%").text(top.TYPO3.lang["wizard.progress"].replace("{0}","1").replace("{1}",s))))}generateSlides(){if(null!==this.setup.$carousel)return this.setup.$carousel;let e='<div class="carousel slide" data-bs-ride="false"><div class="carousel-inner" role="listbox">';for(let t of Object.values(this.setup.slides)){let s=t.content;"object"==typeof s&&(s=s.html()),e+='<div class="carousel-item" data-bs-slide="'+t.identifier+'">'+s+"</div>"}return e+="</div></div>",this.setup.$carousel=$(e),this.setup.$carousel.find(".carousel-item").first().addClass("active"),this.setup.$carousel}}let wizardObject;try{window.opener&&window.opener.TYPO3&&window.opener.TYPO3.Wizard&&(wizardObject=window.opener.TYPO3.Wizard),parent&&parent.window.TYPO3&&parent.window.TYPO3.Wizard&&(wizardObject=parent.window.TYPO3.Wizard),top&&top.TYPO3&&top.TYPO3.Wizard&&(wizardObject=top.TYPO3.Wizard)}catch{}wizardObject||(wizardObject=new Wizard,"undefined"!=typeof TYPO3&&(TYPO3.Wizard=wizardObject));export default wizardObject;
\ No newline at end of file
-- 
GitLab