diff --git a/admin/tool/usertours/amd/build/usertours.min.js b/admin/tool/usertours/amd/build/usertours.min.js index b5a3ec6f5e9..652ed1d1c90 100644 --- a/admin/tool/usertours/amd/build/usertours.min.js +++ b/admin/tool/usertours/amd/build/usertours.min.js @@ -1,3 +1,3 @@ -define("tool_usertours/usertours",["exports","./tour","core/templates","core/log","core/notification","./repository","core/pending","./events"],(function(_exports,_tour,_templates,_log,_notification,tourRepository,_pending,_events){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.resetTourState=_exports.init=void 0,_tour=_interopRequireDefault(_tour),_templates=_interopRequireDefault(_templates),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),tourRepository=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(tourRepository),_pending=_interopRequireDefault(_pending);var _systemImportTransformerGlobalIdentifier="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}let currentTour=null,tourId=null;_exports.init=async(tourDetails,filters)=>{const requirements=[];filters.forEach((filter=>{requirements.push("function"==typeof _systemImportTransformerGlobalIdentifier.define&&_systemImportTransformerGlobalIdentifier.define.amd?new Promise((function(resolve,reject){_systemImportTransformerGlobalIdentifier.require(["tool_usertours/filter_".concat(filter)],resolve,reject)})):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&_systemImportTransformerGlobalIdentifier.require&&"component"===_systemImportTransformerGlobalIdentifier.require.loader?Promise.resolve(require("tool_usertours/filter_".concat(filter))):Promise.resolve(_systemImportTransformerGlobalIdentifier["tool_usertours/filter_".concat(filter)]))}));const matchingTour=((tourDetails,filters)=>tourDetails.find((tour=>filters.some((filter=>!filter||!filter.filterMatches||filter.filterMatches(tour))))))(tourDetails,await Promise.all(requirements));if(!matchingTour)return;tourId=matchingTour.tourId;let startTour=matchingTour.startTour;void 0===startTour&&(startTour=!0),startTour&&fetchTour(tourId),addResetLink(),document.querySelector("body").addEventListener("click",(e=>{e.target.closest("#resetpagetour")&&(e.preventDefault(),resetTourState(tourId))}))};const fetchTour=async tourId=>{const pendingPromise=new _pending.default("admin_usertour_fetchTour:".concat(tourId));try{const response=await tourRepository.fetchTour(tourId);if(response.hasOwnProperty("tourconfig")){const{html:html}=await _templates.default.renderForPromise("tool_usertours/tourstep",response.tourconfig);startBootstrapTour(tourId,html,response.tourconfig)}pendingPromise.resolve()}catch(error){pendingPromise.resolve(),_notification.default.exception(error)}},addResetLink=()=>{const pendingPromise=new _pending.default("admin_usertour_addResetLink");_templates.default.render("tool_usertours/resettour",{}).then((function(html,js){_templates.default.appendNodeContents((()=>{let location=document.querySelector(".tool_usertours-resettourcontainer");return location||(location=document.querySelector(".logininfo"),location||(location=document.querySelector("footer"),location||document.body))})(),html,js)})).catch().then(pendingPromise.resolve).catch()},startBootstrapTour=(tourId,template,tourConfig)=>(currentTour&¤tTour.tourRunning&&(currentTour.endTour(),currentTour=null),document.addEventListener(_events.eventTypes.tourEnded,markTourComplete),document.addEventListener(_events.eventTypes.stepRenderer,markStepShown),tourConfig.tourName=tourConfig.name,delete tourConfig.name,tourConfig.template=template,tourConfig.steps=tourConfig.steps.map((function(step){return void 0!==step.element&&(step.target=step.element,delete step.element),void 0!==step.reflex&&(step.moveOnClick=!!step.reflex,delete step.reflex),void 0!==step.content&&(step.body=step.content,delete step.content),step})),currentTour=new _tour.default(tourConfig),currentTour.startTour()),markStepShown=e=>{const tour=e.detail.tour,stepConfig=tour.getStepConfig(tour.getCurrentStepNumber());tourRepository.markStepShown(stepConfig.stepid,tourId,tour.getCurrentStepNumber()).catch(_log.default.error)},markTourComplete=e=>{document.removeEventListener(_events.eventTypes.tourEnded,markTourComplete),document.removeEventListener(_events.eventTypes.stepRenderer,markStepShown);const tour=e.detail.tour,stepConfig=tour.getStepConfig(tour.getCurrentStepNumber());tourRepository.markTourComplete(stepConfig.stepid,tourId,tour.getCurrentStepNumber()).catch(_log.default.error)},resetTourState=tourId=>tourRepository.resetTourState(tourId).then((response=>{response.startTour&&fetchTour(response.startTour)})).catch(_notification.default.exception);_exports.resetTourState=resetTourState})); +define("tool_usertours/usertours",["exports","./tour","core/templates","core/log","core/notification","./repository","core/pending","./events"],(function(_exports,_tour,_templates,_log,_notification,tourRepository,_pending,_events){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.resetTourState=_exports.init=void 0,_tour=_interopRequireDefault(_tour),_templates=_interopRequireDefault(_templates),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),tourRepository=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(tourRepository),_pending=_interopRequireDefault(_pending);var _systemImportTransformerGlobalIdentifier="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}let currentTour=null,tourId=null,restartTourAndKeepProgress=!1,currentStepNo=null;_exports.init=async(tourDetails,filters)=>{const requirements=[];filters.forEach((filter=>{requirements.push("function"==typeof _systemImportTransformerGlobalIdentifier.define&&_systemImportTransformerGlobalIdentifier.define.amd?new Promise((function(resolve,reject){_systemImportTransformerGlobalIdentifier.require(["tool_usertours/filter_".concat(filter)],resolve,reject)})):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&_systemImportTransformerGlobalIdentifier.require&&"component"===_systemImportTransformerGlobalIdentifier.require.loader?Promise.resolve(require("tool_usertours/filter_".concat(filter))):Promise.resolve(_systemImportTransformerGlobalIdentifier["tool_usertours/filter_".concat(filter)]))}));const matchingTour=((tourDetails,filters)=>tourDetails.find((tour=>filters.some((filter=>!filter||!filter.filterMatches||filter.filterMatches(tour))))))(tourDetails,await Promise.all(requirements));if(!matchingTour)return;tourId=matchingTour.tourId;let startTour=matchingTour.startTour;void 0===startTour&&(startTour=!0),startTour&&fetchTour(tourId),addResetLink(),document.querySelector("body").addEventListener("click",(e=>{e.target.closest("#resetpagetour")&&(e.preventDefault(),resetTourState(tourId))})),window.addEventListener("resize",(()=>{currentTour&¤tTour.tourRunning&&(clearTimeout(window.resizedFinished),window.resizedFinished=setTimeout((()=>{currentStepNo=currentTour.getCurrentStepNumber(),restartTourAndKeepProgress=!0,resetTourState(tourId)}),250))}))};const fetchTour=async tourId=>{const pendingPromise=new _pending.default("admin_usertour_fetchTour:".concat(tourId));try{const response=await tourRepository.fetchTour(tourId);if(response.hasOwnProperty("tourconfig")){const{html:html}=await _templates.default.renderForPromise("tool_usertours/tourstep",response.tourconfig);startBootstrapTour(tourId,html,response.tourconfig)}pendingPromise.resolve()}catch(error){pendingPromise.resolve(),_notification.default.exception(error)}},addResetLink=()=>{const pendingPromise=new _pending.default("admin_usertour_addResetLink");_templates.default.render("tool_usertours/resettour",{}).then((function(html,js){_templates.default.appendNodeContents((()=>{let location=document.querySelector(".tool_usertours-resettourcontainer");return location||(location=document.querySelector(".logininfo"),location||(location=document.querySelector("footer"),location||document.body))})(),html,js)})).catch().then(pendingPromise.resolve).catch()},startBootstrapTour=(tourId,template,tourConfig)=>{currentTour&¤tTour.tourRunning&&(currentTour.endTour(),currentTour=null),document.addEventListener(_events.eventTypes.tourEnded,markTourComplete),document.addEventListener(_events.eventTypes.stepRenderer,markStepShown),tourConfig.tourName=tourConfig.name,delete tourConfig.name,tourConfig.template=template,tourConfig.steps=tourConfig.steps.map((function(step){return void 0!==step.element&&(step.target=step.element,delete step.element),void 0!==step.reflex&&(step.moveOnClick=!!step.reflex,delete step.reflex),void 0!==step.content&&(step.body=step.content,delete step.content),step})),currentTour=new _tour.default(tourConfig);let startAt=0;return restartTourAndKeepProgress&¤tStepNo&&(startAt=currentStepNo,restartTourAndKeepProgress=!1,currentStepNo=null),currentTour.startTour(startAt)},markStepShown=e=>{const tour=e.detail.tour,stepConfig=tour.getStepConfig(tour.getCurrentStepNumber());tourRepository.markStepShown(stepConfig.stepid,tourId,tour.getCurrentStepNumber()).catch(_log.default.error)},markTourComplete=e=>{document.removeEventListener(_events.eventTypes.tourEnded,markTourComplete),document.removeEventListener(_events.eventTypes.stepRenderer,markStepShown);const tour=e.detail.tour,stepConfig=tour.getStepConfig(tour.getCurrentStepNumber());tourRepository.markTourComplete(stepConfig.stepid,tourId,tour.getCurrentStepNumber()).catch(_log.default.error)},resetTourState=tourId=>tourRepository.resetTourState(tourId).then((response=>{response.startTour&&fetchTour(response.startTour)})).catch(_notification.default.exception);_exports.resetTourState=resetTourState})); //# sourceMappingURL=usertours.min.js.map \ No newline at end of file diff --git a/admin/tool/usertours/amd/build/usertours.min.js.map b/admin/tool/usertours/amd/build/usertours.min.js.map index cef6757938e..8c3fa410513 100644 --- a/admin/tool/usertours/amd/build/usertours.min.js.map +++ b/admin/tool/usertours/amd/build/usertours.min.js.map @@ -1 +1 @@ -{"version":3,"file":"usertours.min.js","sources":["../src/usertours.js"],"sourcesContent":["/**\n * User tour control library.\n *\n * @module tool_usertours/usertours\n * @copyright 2016 Andrew Nicols \n */\nimport BootstrapTour from './tour';\nimport Templates from 'core/templates';\nimport log from 'core/log';\nimport notification from 'core/notification';\nimport * as tourRepository from './repository';\nimport Pending from 'core/pending';\nimport {eventTypes} from './events';\n\nlet currentTour = null;\nlet tourId = null;\n\n/**\n * Find the first matching tour.\n *\n * @param {object[]} tourDetails\n * @param {object[]} filters\n * @returns {null|object}\n */\nconst findMatchingTour = (tourDetails, filters) => {\n return tourDetails.find(tour => filters.some(filter => {\n if (filter && filter.filterMatches) {\n return filter.filterMatches(tour);\n }\n\n return true;\n }));\n};\n\n/**\n * Initialise the user tour for the current page.\n *\n * @method init\n * @param {Array} tourDetails The matching tours for this page.\n * @param {Array} filters The names of all client side filters.\n */\nexport const init = async(tourDetails, filters) => {\n const requirements = [];\n filters.forEach(filter => {\n requirements.push(import(`tool_usertours/filter_${filter}`));\n });\n\n const filterPlugins = await Promise.all(requirements);\n\n const matchingTour = findMatchingTour(tourDetails, filterPlugins);\n if (!matchingTour) {\n return;\n }\n\n // Only one tour per page is allowed.\n tourId = matchingTour.tourId;\n\n let startTour = matchingTour.startTour;\n if (typeof startTour === 'undefined') {\n startTour = true;\n }\n\n if (startTour) {\n // Fetch the tour configuration.\n fetchTour(tourId);\n }\n\n addResetLink();\n\n // Watch for the reset link.\n document.querySelector('body').addEventListener('click', e => {\n const resetLink = e.target.closest('#resetpagetour');\n if (resetLink) {\n e.preventDefault();\n resetTourState(tourId);\n }\n });\n};\n\n/**\n * Fetch the configuration specified tour, and start the tour when it has been fetched.\n *\n * @method fetchTour\n * @param {Number} tourId The ID of the tour to start.\n */\nconst fetchTour = async tourId => {\n const pendingPromise = new Pending(`admin_usertour_fetchTour:${tourId}`);\n\n try {\n // If we don't have any tour config (because it doesn't need showing for the current user), return early.\n const response = await tourRepository.fetchTour(tourId);\n if (response.hasOwnProperty('tourconfig')) {\n const {html} = await Templates.renderForPromise('tool_usertours/tourstep', response.tourconfig);\n startBootstrapTour(tourId, html, response.tourconfig);\n }\n pendingPromise.resolve();\n } catch (error) {\n pendingPromise.resolve();\n notification.exception(error);\n }\n};\n\nconst getPreferredResetLocation = () => {\n let location = document.querySelector('.tool_usertours-resettourcontainer');\n if (location) {\n return location;\n }\n\n location = document.querySelector('.logininfo');\n if (location) {\n return location;\n }\n\n location = document.querySelector('footer');\n if (location) {\n return location;\n }\n\n return document.body;\n};\n\n/**\n * Add a reset link to the page.\n *\n * @method addResetLink\n */\nconst addResetLink = () => {\n const pendingPromise = new Pending('admin_usertour_addResetLink');\n\n Templates.render('tool_usertours/resettour', {})\n .then(function(html, js) {\n // Append the link to the most suitable place on the page with fallback to legacy selectors and finally the body if\n // there is no better place.\n Templates.appendNodeContents(getPreferredResetLocation(), html, js);\n\n return;\n })\n .catch()\n .then(pendingPromise.resolve)\n .catch();\n};\n\n/**\n * Start the specified tour.\n *\n * @method startBootstrapTour\n * @param {Number} tourId The ID of the tour to start.\n * @param {String} template The template to use.\n * @param {Object} tourConfig The tour configuration.\n * @return {Object}\n */\nconst startBootstrapTour = (tourId, template, tourConfig) => {\n if (currentTour && currentTour.tourRunning) {\n // End the current tour.\n currentTour.endTour();\n currentTour = null;\n }\n\n document.addEventListener(eventTypes.tourEnded, markTourComplete);\n document.addEventListener(eventTypes.stepRenderer, markStepShown);\n\n // Sort out the tour name.\n tourConfig.tourName = tourConfig.name;\n delete tourConfig.name;\n\n // Add the template to the configuration.\n // This enables translations of the buttons.\n tourConfig.template = template;\n\n tourConfig.steps = tourConfig.steps.map(function(step) {\n if (typeof step.element !== 'undefined') {\n step.target = step.element;\n delete step.element;\n }\n\n if (typeof step.reflex !== 'undefined') {\n step.moveOnClick = !!step.reflex;\n delete step.reflex;\n }\n\n if (typeof step.content !== 'undefined') {\n step.body = step.content;\n delete step.content;\n }\n\n return step;\n });\n\n currentTour = new BootstrapTour(tourConfig);\n return currentTour.startTour();\n};\n\n/**\n * Mark the specified step as being shownd by the user.\n *\n * @method markStepShown\n * @param {Event} e\n */\nconst markStepShown = e => {\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markStepShown(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Mark the specified tour as being completed by the user.\n *\n * @method markTourComplete\n * @param {Event} e\n * @listens tool_usertours/stepRendered\n */\nconst markTourComplete = e => {\n document.removeEventListener(eventTypes.tourEnded, markTourComplete);\n document.removeEventListener(eventTypes.stepRenderer, markStepShown);\n\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markTourComplete(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Reset the state, and restart the the tour on the current page.\n *\n * @method resetTourState\n * @param {Number} tourId The ID of the tour to start.\n * @returns {Promise}\n */\nexport const resetTourState = tourId => tourRepository.resetTourState(tourId)\n.then(response => {\n if (response.startTour) {\n fetchTour(response.startTour);\n }\n return;\n}).catch(notification.exception);\n"],"names":["currentTour","tourId","async","tourDetails","filters","requirements","forEach","filter","push","matchingTour","find","tour","some","filterMatches","findMatchingTour","Promise","all","startTour","fetchTour","addResetLink","document","querySelector","addEventListener","e","target","closest","preventDefault","resetTourState","pendingPromise","Pending","response","tourRepository","hasOwnProperty","html","Templates","renderForPromise","tourconfig","startBootstrapTour","resolve","error","exception","render","then","js","appendNodeContents","location","body","getPreferredResetLocation","catch","template","tourConfig","tourRunning","endTour","eventTypes","tourEnded","markTourComplete","stepRenderer","markStepShown","tourName","name","steps","map","step","element","reflex","moveOnClick","content","BootstrapTour","detail","stepConfig","getStepConfig","getCurrentStepNumber","stepid","log","removeEventListener","notification"],"mappings":"ssDAcIA,YAAc,KACdC,OAAS,mBA0BOC,MAAMC,YAAaC,iBAC7BC,aAAe,GACrBD,QAAQE,SAAQC,SACZF,aAAaG,qPAAqCD,mUAAAA,mGAAAA,oBAKhDE,aAzBe,EAACN,YAAaC,UAC5BD,YAAYO,MAAKC,MAAQP,QAAQQ,MAAKL,SACrCA,SAAUA,OAAOM,eACVN,OAAOM,cAAcF,UAsBfG,CAAiBX,kBAFVY,QAAQC,IAAIX,mBAGnCI,oBAKLR,OAASQ,aAAaR,WAElBgB,UAAYR,aAAaQ,eACJ,IAAdA,YACPA,WAAY,GAGZA,WAEAC,UAAUjB,QAGdkB,eAGAC,SAASC,cAAc,QAAQC,iBAAiB,SAASC,IACnCA,EAAEC,OAAOC,QAAQ,oBAE/BF,EAAEG,iBACFC,eAAe1B,mBAWrBiB,UAAYhB,MAAAA,eACR0B,eAAiB,IAAIC,oDAAoC5B,mBAIrD6B,eAAiBC,eAAeb,UAAUjB,WAC5C6B,SAASE,eAAe,cAAe,OACjCC,KAACA,YAAcC,mBAAUC,iBAAiB,0BAA2BL,SAASM,YACpFC,mBAAmBpC,OAAQgC,KAAMH,SAASM,YAE9CR,eAAeU,UACjB,MAAOC,OACLX,eAAeU,gCACFE,UAAUD,SA4BzBpB,aAAe,WACXS,eAAiB,IAAIC,iBAAQ,kDAEzBY,OAAO,2BAA4B,IAC5CC,MAAK,SAAST,KAAMU,uBAGPC,mBA/BgB,UAC1BC,SAAWzB,SAASC,cAAc,6CAClCwB,WAIJA,SAAWzB,SAASC,cAAc,cAC9BwB,WAIJA,SAAWzB,SAASC,cAAc,UAC9BwB,UAIGzB,SAAS0B,QAeiBC,GAA6Bd,KAAMU,OAInEK,QACAN,KAAKd,eAAeU,SACpBU,SAYCX,mBAAqB,CAACpC,OAAQgD,SAAUC,cACtClD,aAAeA,YAAYmD,cAE3BnD,YAAYoD,UACZpD,YAAc,MAGlBoB,SAASE,iBAAiB+B,mBAAWC,UAAWC,kBAChDnC,SAASE,iBAAiB+B,mBAAWG,aAAcC,eAGnDP,WAAWQ,SAAWR,WAAWS,YAC1BT,WAAWS,KAIlBT,WAAWD,SAAWA,SAEtBC,WAAWU,MAAQV,WAAWU,MAAMC,KAAI,SAASC,kBACjB,IAAjBA,KAAKC,UACZD,KAAKtC,OAASsC,KAAKC,eACZD,KAAKC,cAGW,IAAhBD,KAAKE,SACZF,KAAKG,cAAgBH,KAAKE,cACnBF,KAAKE,aAGY,IAAjBF,KAAKI,UACZJ,KAAKhB,KAAOgB,KAAKI,eACVJ,KAAKI,SAGTJ,QAGX9D,YAAc,IAAImE,cAAcjB,YACzBlD,YAAYiB,aASjBwC,cAAgBlC,UACZZ,KAAOY,EAAE6C,OAAOzD,KAChB0D,WAAa1D,KAAK2D,cAAc3D,KAAK4D,wBAC3CxC,eAAe0B,cACXY,WAAWG,OACXvE,OACAU,KAAK4D,wBACPvB,MAAMyB,aAAIlC,QAUVgB,iBAAmBhC,IACrBH,SAASsD,oBAAoBrB,mBAAWC,UAAWC,kBACnDnC,SAASsD,oBAAoBrB,mBAAWG,aAAcC,qBAEhD9C,KAAOY,EAAE6C,OAAOzD,KAChB0D,WAAa1D,KAAK2D,cAAc3D,KAAK4D,wBAC3CxC,eAAewB,iBACXc,WAAWG,OACXvE,OACAU,KAAK4D,wBACPvB,MAAMyB,aAAIlC,QAUHZ,eAAiB1B,QAAU8B,eAAeJ,eAAe1B,QACrEyC,MAAKZ,WACEA,SAASb,WACTC,UAAUY,SAASb,cAGxB+B,MAAM2B,sBAAanC"} \ No newline at end of file +{"version":3,"file":"usertours.min.js","sources":["../src/usertours.js"],"sourcesContent":["/**\n * User tour control library.\n *\n * @module tool_usertours/usertours\n * @copyright 2016 Andrew Nicols \n */\nimport BootstrapTour from './tour';\nimport Templates from 'core/templates';\nimport log from 'core/log';\nimport notification from 'core/notification';\nimport * as tourRepository from './repository';\nimport Pending from 'core/pending';\nimport {eventTypes} from './events';\n\nlet currentTour = null;\nlet tourId = null;\nlet restartTourAndKeepProgress = false;\nlet currentStepNo = null;\n\n/**\n * Find the first matching tour.\n *\n * @param {object[]} tourDetails\n * @param {object[]} filters\n * @returns {null|object}\n */\nconst findMatchingTour = (tourDetails, filters) => {\n return tourDetails.find(tour => filters.some(filter => {\n if (filter && filter.filterMatches) {\n return filter.filterMatches(tour);\n }\n\n return true;\n }));\n};\n\n/**\n * Initialise the user tour for the current page.\n *\n * @method init\n * @param {Array} tourDetails The matching tours for this page.\n * @param {Array} filters The names of all client side filters.\n */\nexport const init = async(tourDetails, filters) => {\n const requirements = [];\n filters.forEach(filter => {\n requirements.push(import(`tool_usertours/filter_${filter}`));\n });\n\n const filterPlugins = await Promise.all(requirements);\n\n const matchingTour = findMatchingTour(tourDetails, filterPlugins);\n if (!matchingTour) {\n return;\n }\n\n // Only one tour per page is allowed.\n tourId = matchingTour.tourId;\n\n let startTour = matchingTour.startTour;\n if (typeof startTour === 'undefined') {\n startTour = true;\n }\n\n if (startTour) {\n // Fetch the tour configuration.\n fetchTour(tourId);\n }\n\n addResetLink();\n\n // Watch for the reset link.\n document.querySelector('body').addEventListener('click', e => {\n const resetLink = e.target.closest('#resetpagetour');\n if (resetLink) {\n e.preventDefault();\n resetTourState(tourId);\n }\n });\n\n // Watch for the resize event.\n window.addEventListener(\"resize\", () => {\n // Only listen for the running tour.\n if (currentTour && currentTour.tourRunning) {\n clearTimeout(window.resizedFinished);\n window.resizedFinished = setTimeout(() => {\n // Wait until the resize event has finished.\n currentStepNo = currentTour.getCurrentStepNumber();\n restartTourAndKeepProgress = true;\n resetTourState(tourId);\n }, 250);\n }\n });\n};\n\n/**\n * Fetch the configuration specified tour, and start the tour when it has been fetched.\n *\n * @method fetchTour\n * @param {Number} tourId The ID of the tour to start.\n */\nconst fetchTour = async tourId => {\n const pendingPromise = new Pending(`admin_usertour_fetchTour:${tourId}`);\n\n try {\n // If we don't have any tour config (because it doesn't need showing for the current user), return early.\n const response = await tourRepository.fetchTour(tourId);\n if (response.hasOwnProperty('tourconfig')) {\n const {html} = await Templates.renderForPromise('tool_usertours/tourstep', response.tourconfig);\n startBootstrapTour(tourId, html, response.tourconfig);\n }\n pendingPromise.resolve();\n } catch (error) {\n pendingPromise.resolve();\n notification.exception(error);\n }\n};\n\nconst getPreferredResetLocation = () => {\n let location = document.querySelector('.tool_usertours-resettourcontainer');\n if (location) {\n return location;\n }\n\n location = document.querySelector('.logininfo');\n if (location) {\n return location;\n }\n\n location = document.querySelector('footer');\n if (location) {\n return location;\n }\n\n return document.body;\n};\n\n/**\n * Add a reset link to the page.\n *\n * @method addResetLink\n */\nconst addResetLink = () => {\n const pendingPromise = new Pending('admin_usertour_addResetLink');\n\n Templates.render('tool_usertours/resettour', {})\n .then(function(html, js) {\n // Append the link to the most suitable place on the page with fallback to legacy selectors and finally the body if\n // there is no better place.\n Templates.appendNodeContents(getPreferredResetLocation(), html, js);\n\n return;\n })\n .catch()\n .then(pendingPromise.resolve)\n .catch();\n};\n\n/**\n * Start the specified tour.\n *\n * @method startBootstrapTour\n * @param {Number} tourId The ID of the tour to start.\n * @param {String} template The template to use.\n * @param {Object} tourConfig The tour configuration.\n * @return {Object}\n */\nconst startBootstrapTour = (tourId, template, tourConfig) => {\n if (currentTour && currentTour.tourRunning) {\n // End the current tour.\n currentTour.endTour();\n currentTour = null;\n }\n\n document.addEventListener(eventTypes.tourEnded, markTourComplete);\n document.addEventListener(eventTypes.stepRenderer, markStepShown);\n\n // Sort out the tour name.\n tourConfig.tourName = tourConfig.name;\n delete tourConfig.name;\n\n // Add the template to the configuration.\n // This enables translations of the buttons.\n tourConfig.template = template;\n\n tourConfig.steps = tourConfig.steps.map(function(step) {\n if (typeof step.element !== 'undefined') {\n step.target = step.element;\n delete step.element;\n }\n\n if (typeof step.reflex !== 'undefined') {\n step.moveOnClick = !!step.reflex;\n delete step.reflex;\n }\n\n if (typeof step.content !== 'undefined') {\n step.body = step.content;\n delete step.content;\n }\n\n return step;\n });\n\n currentTour = new BootstrapTour(tourConfig);\n let startAt = 0;\n if (restartTourAndKeepProgress && currentStepNo) {\n startAt = currentStepNo;\n restartTourAndKeepProgress = false;\n currentStepNo = null;\n }\n return currentTour.startTour(startAt);\n};\n\n/**\n * Mark the specified step as being shownd by the user.\n *\n * @method markStepShown\n * @param {Event} e\n */\nconst markStepShown = e => {\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markStepShown(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Mark the specified tour as being completed by the user.\n *\n * @method markTourComplete\n * @param {Event} e\n * @listens tool_usertours/stepRendered\n */\nconst markTourComplete = e => {\n document.removeEventListener(eventTypes.tourEnded, markTourComplete);\n document.removeEventListener(eventTypes.stepRenderer, markStepShown);\n\n const tour = e.detail.tour;\n const stepConfig = tour.getStepConfig(tour.getCurrentStepNumber());\n tourRepository.markTourComplete(\n stepConfig.stepid,\n tourId,\n tour.getCurrentStepNumber()\n ).catch(log.error);\n};\n\n/**\n * Reset the state, and restart the the tour on the current page.\n *\n * @method resetTourState\n * @param {Number} tourId The ID of the tour to start.\n * @returns {Promise}\n */\nexport const resetTourState = tourId => tourRepository.resetTourState(tourId)\n.then(response => {\n if (response.startTour) {\n fetchTour(response.startTour);\n }\n return;\n}).catch(notification.exception);\n"],"names":["currentTour","tourId","restartTourAndKeepProgress","currentStepNo","async","tourDetails","filters","requirements","forEach","filter","push","matchingTour","find","tour","some","filterMatches","findMatchingTour","Promise","all","startTour","fetchTour","addResetLink","document","querySelector","addEventListener","e","target","closest","preventDefault","resetTourState","window","tourRunning","clearTimeout","resizedFinished","setTimeout","getCurrentStepNumber","pendingPromise","Pending","response","tourRepository","hasOwnProperty","html","Templates","renderForPromise","tourconfig","startBootstrapTour","resolve","error","exception","render","then","js","appendNodeContents","location","body","getPreferredResetLocation","catch","template","tourConfig","endTour","eventTypes","tourEnded","markTourComplete","stepRenderer","markStepShown","tourName","name","steps","map","step","element","reflex","moveOnClick","content","BootstrapTour","startAt","detail","stepConfig","getStepConfig","stepid","log","removeEventListener","notification"],"mappings":"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"} \ No newline at end of file diff --git a/admin/tool/usertours/amd/src/usertours.js b/admin/tool/usertours/amd/src/usertours.js index 7439358abc2..8e64e8d68ea 100644 --- a/admin/tool/usertours/amd/src/usertours.js +++ b/admin/tool/usertours/amd/src/usertours.js @@ -14,6 +14,8 @@ import {eventTypes} from './events'; let currentTour = null; let tourId = null; +let restartTourAndKeepProgress = false; +let currentStepNo = null; /** * Find the first matching tour. @@ -75,6 +77,20 @@ export const init = async(tourDetails, filters) => { resetTourState(tourId); } }); + + // Watch for the resize event. + window.addEventListener("resize", () => { + // Only listen for the running tour. + if (currentTour && currentTour.tourRunning) { + clearTimeout(window.resizedFinished); + window.resizedFinished = setTimeout(() => { + // Wait until the resize event has finished. + currentStepNo = currentTour.getCurrentStepNumber(); + restartTourAndKeepProgress = true; + resetTourState(tourId); + }, 250); + } + }); }; /** @@ -187,7 +203,13 @@ const startBootstrapTour = (tourId, template, tourConfig) => { }); currentTour = new BootstrapTour(tourConfig); - return currentTour.startTour(); + let startAt = 0; + if (restartTourAndKeepProgress && currentStepNo) { + startAt = currentStepNo; + restartTourAndKeepProgress = false; + currentStepNo = null; + } + return currentTour.startTour(startAt); }; /**