From e76650c1f148e83601ad010e9010f03e7244e5fe Mon Sep 17 00:00:00 2001 From: "jacob.viertel@wunderbyte.at" Date: Fri, 7 Feb 2025 13:44:52 +0100 Subject: [PATCH] Improvement: strings localized, mandatory icon --- amd/build/cashier_modal.min.js | 2 +- amd/build/cashier_modal.min.js.map | 2 +- amd/build/checkout_manager.min.js | 4 +- amd/build/checkout_manager.min.js.map | 2 +- .../checkout_process/checkout_manager.php | 1 + lang/de/local_shopping_cart.php | 3 + lang/en/local_shopping_cart.php | 1 + .../checkout_manager_form_buttons.mustache | 3 +- ...heckout_manager_form_progress_bar.mustache | 7 ++ templates/checkout_payment_checkout.mustache | 83 ++++++++++++------- 10 files changed, 69 insertions(+), 39 deletions(-) diff --git a/amd/build/cashier_modal.min.js b/amd/build/cashier_modal.min.js index dca4df90..b7b5d36f 100644 --- a/amd/build/cashier_modal.min.js +++ b/amd/build/cashier_modal.min.js @@ -5,6 +5,6 @@ define("local_shopping_cart/cashier_modal",["exports","core/modal_factory","core * @module core_payment/gateways_modal * @copyright Wunderbyte GmbH * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const show=async function(rootNode){let{focusOnClose:focusOnClose=null}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const modal=await _modal_factory.default.create({type:_modal_gateways.default.TYPE,title:await(0,_str.get_string)("selectpaymenttype","core_payment"),body:await _templates.default.render("core_payment/gateways_modal",{})});console.log("initt23432532532tt");const rootElement=modal.getRoot()[0];(0,_toast.addToastRegion)(rootElement),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(()=>{modal.destroy();try{focusOnClose.focus()}catch(e){console.log("error: ",e)}})),modal.getRoot().on(_events.default.proceed,(e=>{const gateway=(rootElement.querySelector(_selectors.default.values.gateway)||{value:""}).value;gateway?processPayment(gateway,rootNode.dataset.component,rootNode.dataset.paymentarea,rootNode.dataset.itemid,rootNode.dataset.description).then((message=>(modal.hide(),(0,_notifications.showNotification)(message,"success"),location.href=rootNode.dataset.successurl,message))).catch((message=>_notification.default.alert("",message))):(0,_str.get_string)("nogatewayselected","core_payment").then((message=>(0,_toast.add)(message,{type:"warning"}))),e.preventDefault()})),rootElement.addEventListener("change",(e=>{e.target.matches(_selectors.default.elements.gateways)&&updateCostRegion(rootElement,rootNode.dataset.cost)}));const context={gateways:await(0,_repository.getAvailableGateways)(rootNode.dataset.component,rootNode.dataset.paymentarea,rootNode.dataset.itemid)},{html:html,js:js}=await _templates.default.renderForPromise("core_payment/gateways",context);_templates.default.replaceNodeContents(rootElement.querySelector(_selectors.default.regions.gatewaysContainer),html,js),selectSingleGateway(rootElement),await updateCostRegion(rootElement,rootNode.dataset.cost)},selectSingleGateway=root=>{const gateways=root.querySelectorAll(_selectors.default.elements.gateways);1==gateways.length&&(gateways[0].checked=!0)},updateCostRegion=async function(root){let defaultCost=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const gatewayElement=root.querySelector(_selectors.default.values.gateway),surcharge=parseInt((gatewayElement||{dataset:{surcharge:0}}).dataset.surcharge),cost=(gatewayElement||{dataset:{cost:defaultCost}}).dataset.cost,{html:html,js:js}=await _templates.default.renderForPromise("core_payment/fee_breakdown",{fee:cost,surcharge:surcharge});_templates.default.replaceNodeContents(root.querySelector(_selectors.default.regions.costContainer),html,js)},processPayment=async(gateway,component,paymentArea,itemId,description)=>{console.log("initt23432532532tt");return(await("function"==typeof _systemImportTransformerGlobalIdentifier.define&&_systemImportTransformerGlobalIdentifier.define.amd?new Promise((function(resolve,reject){_systemImportTransformerGlobalIdentifier.require([`paygw_${gateway}/gateways_modal`],resolve,reject)})):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&_systemImportTransformerGlobalIdentifier.require&&"component"===_systemImportTransformerGlobalIdentifier.require.loader?Promise.resolve(require(`paygw_${gateway}/gateways_modal`)):Promise.resolve(_systemImportTransformerGlobalIdentifier[`paygw_${gateway}/gateways_modal`]))).process(component,paymentArea,itemId,description)},init=()=>{console.log("initt23432532532tt"),init.initialised||(init.initialised=!0,document.addEventListener("click",(e=>{const gatewayTrigger=e.target.closest('[data-action="core_payment/triggerPayment"]');gatewayTrigger&&(e.preventDefault(),show(gatewayTrigger,{focusOnClose:e.target}))})))};_exports.init=init,init.initialised=!1})); + */function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const show=async function(rootNode){let{focusOnClose:focusOnClose=null}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const modal=await _modal_factory.default.create({type:_modal_gateways.default.TYPE,title:await(0,_str.get_string)("selectpaymenttype","core_payment"),body:await _templates.default.render("core_payment/gateways_modal",{})}),rootElement=modal.getRoot()[0];(0,_toast.addToastRegion)(rootElement),modal.show(),modal.getRoot().on(_modal_events.default.hidden,(()=>{modal.destroy();try{focusOnClose.focus()}catch(e){console.log("error: ",e)}})),modal.getRoot().on(_events.default.proceed,(e=>{const gateway=(rootElement.querySelector(_selectors.default.values.gateway)||{value:""}).value;gateway?processPayment(gateway,rootNode.dataset.component,rootNode.dataset.paymentarea,rootNode.dataset.itemid,rootNode.dataset.description).then((message=>(modal.hide(),(0,_notifications.showNotification)(message,"success"),location.href=rootNode.dataset.successurl,message))).catch((message=>_notification.default.alert("",message))):(0,_str.get_string)("nogatewayselected","core_payment").then((message=>(0,_toast.add)(message,{type:"warning"}))),e.preventDefault()})),rootElement.addEventListener("change",(e=>{e.target.matches(_selectors.default.elements.gateways)&&updateCostRegion(rootElement,rootNode.dataset.cost)}));const context={gateways:await(0,_repository.getAvailableGateways)(rootNode.dataset.component,rootNode.dataset.paymentarea,rootNode.dataset.itemid)},{html:html,js:js}=await _templates.default.renderForPromise("core_payment/gateways",context);_templates.default.replaceNodeContents(rootElement.querySelector(_selectors.default.regions.gatewaysContainer),html,js),selectSingleGateway(rootElement),await updateCostRegion(rootElement,rootNode.dataset.cost)},selectSingleGateway=root=>{const gateways=root.querySelectorAll(_selectors.default.elements.gateways);1==gateways.length&&(gateways[0].checked=!0)},updateCostRegion=async function(root){let defaultCost=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const gatewayElement=root.querySelector(_selectors.default.values.gateway),surcharge=parseInt((gatewayElement||{dataset:{surcharge:0}}).dataset.surcharge),cost=(gatewayElement||{dataset:{cost:defaultCost}}).dataset.cost,{html:html,js:js}=await _templates.default.renderForPromise("core_payment/fee_breakdown",{fee:cost,surcharge:surcharge});_templates.default.replaceNodeContents(root.querySelector(_selectors.default.regions.costContainer),html,js)},processPayment=async(gateway,component,paymentArea,itemId,description)=>(await("function"==typeof _systemImportTransformerGlobalIdentifier.define&&_systemImportTransformerGlobalIdentifier.define.amd?new Promise((function(resolve,reject){_systemImportTransformerGlobalIdentifier.require([`paygw_${gateway}/gateways_modal`],resolve,reject)})):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&_systemImportTransformerGlobalIdentifier.require&&"component"===_systemImportTransformerGlobalIdentifier.require.loader?Promise.resolve(require(`paygw_${gateway}/gateways_modal`)):Promise.resolve(_systemImportTransformerGlobalIdentifier[`paygw_${gateway}/gateways_modal`]))).process(component,paymentArea,itemId,description),init=()=>{init.initialised||(init.initialised=!0,document.addEventListener("click",(e=>{const gatewayTrigger=e.target.closest('[data-action="core_payment/triggerPayment"]');gatewayTrigger&&(e.preventDefault(),show(gatewayTrigger,{focusOnClose:e.target}))})))};_exports.init=init,init.initialised=!1})); //# sourceMappingURL=cashier_modal.min.js.map \ No newline at end of file diff --git a/amd/build/cashier_modal.min.js.map b/amd/build/cashier_modal.min.js.map index 89b13965..6f287d81 100644 --- a/amd/build/cashier_modal.min.js.map +++ b/amd/build/cashier_modal.min.js.map @@ -1 +1 @@ -{"version":3,"file":"cashier_modal.min.js","sources":["../src/cashier_modal.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Contain the logic for the gateways modal.\n *\n * @module core_payment/gateways_modal\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalFactory from 'core/modal_factory';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\nimport {getAvailableGateways} from './repository';\nimport Selectors from './selectors';\nimport ModalEvents from 'core/modal_events';\nimport PaymentEvents from 'core_payment/events';\nimport {add as addToast, addToastRegion} from 'core/toast';\nimport {showNotification} from 'local_shopping_cart/notifications';\nimport ModalGateways from './modal_gateways';\nimport Notification from 'core/notification';\n\n/**\n * Register event listeners for the module.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', e => {\n const gatewayTrigger = e.target.closest('[data-action=\"core_payment/triggerPayment\"]');\n if (gatewayTrigger) {\n e.preventDefault();\n\n show(gatewayTrigger, {focusOnClose: e.target});\n }\n });\n};\n\n/**\n * Shows the gateway selector modal.\n *\n * @param {HTMLElement} rootNode\n * @param {Object} options - Additional options\n * @param {HTMLElement} options.focusOnClose The element to focus on when the modal is closed.\n */\nconst show = async(rootNode, {\n focusOnClose = null,\n} = {}) => {\n const modal = await ModalFactory.create({\n type: ModalGateways.TYPE,\n title: await getString('selectpaymenttype', 'core_payment'),\n body: await Templates.render('core_payment/gateways_modal', {}),\n });\n // eslint-disable-next-line no-console\n console.log('initt23432532532tt');\n\n const rootElement = modal.getRoot()[0];\n addToastRegion(rootElement);\n\n modal.show();\n\n modal.getRoot().on(ModalEvents.hidden, () => {\n // Destroy when hidden.\n modal.destroy();\n try {\n focusOnClose.focus();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.log('error: ', e);\n }\n });\n\n modal.getRoot().on(PaymentEvents.proceed, (e) => {\n const gateway = (rootElement.querySelector(Selectors.values.gateway) || {value: ''}).value;\n\n if (gateway) {\n processPayment(\n gateway,\n rootNode.dataset.component,\n rootNode.dataset.paymentarea,\n rootNode.dataset.itemid,\n rootNode.dataset.description\n )\n .then(message => {\n modal.hide();\n showNotification(message, 'success');\n\n location.href = rootNode.dataset.successurl;\n\n // The following return statement is never reached. It is put here just to make eslint happy.\n return message;\n })\n .catch(message => Notification.alert('', message));\n } else {\n // We cannot use await in the following line.\n // The reason is that we are preventing the default action of the save event being triggered,\n // therefore we cannot define the event handler function asynchronous.\n // eslint-disable-next-line promise/catch-or-return\n getString('nogatewayselected', 'core_payment').then(message => addToast(message, {type: 'warning'}));\n }\n\n e.preventDefault();\n });\n\n // Re-calculate the cost when gateway is changed.\n rootElement.addEventListener('change', e => {\n if (e.target.matches(Selectors.elements.gateways)) {\n updateCostRegion(rootElement, rootNode.dataset.cost);\n }\n });\n\n const gateways = await getAvailableGateways(rootNode.dataset.component, rootNode.dataset.paymentarea, rootNode.dataset.itemid);\n const context = {\n gateways\n };\n\n const {html, js} = await Templates.renderForPromise('core_payment/gateways', context);\n Templates.replaceNodeContents(rootElement.querySelector(Selectors.regions.gatewaysContainer), html, js);\n selectSingleGateway(rootElement);\n await updateCostRegion(rootElement, rootNode.dataset.cost);\n};\n\n/**\n * Auto-select the gateway if there is only one gateway.\n *\n * @param {HTMLElement} root An HTMLElement that contains the cost region\n */\nconst selectSingleGateway = root => {\n const gateways = root.querySelectorAll(Selectors.elements.gateways);\n\n if (gateways.length == 1) {\n gateways[0].checked = true;\n }\n};\n\n/**\n * Shows the cost of the item the user is purchasing in the cost region.\n *\n * @param {HTMLElement} root An HTMLElement that contains the cost region\n * @param {string} defaultCost The default cost that is going to be displayed if no gateway is selected\n * @returns {Promise}\n */\nconst updateCostRegion = async(root, defaultCost = '') => {\n const gatewayElement = root.querySelector(Selectors.values.gateway);\n const surcharge = parseInt((gatewayElement || {dataset: {surcharge: 0}}).dataset.surcharge);\n const cost = (gatewayElement || {dataset: {cost: defaultCost}}).dataset.cost;\n\n const {html, js} = await Templates.renderForPromise('core_payment/fee_breakdown', {fee: cost, surcharge});\n Templates.replaceNodeContents(root.querySelector(Selectors.regions.costContainer), html, js);\n};\n\n/**\n * Process payment using the selected gateway.\n *\n * @param {string} gateway The gateway to be used for payment\n * @param {string} component Name of the component that the itemId belongs to\n * @param {string} paymentArea Name of the area in the component that the itemId belongs to\n * @param {number} itemId An internal identifier that is used by the component\n * @param {string} description Description of the payment\n * @returns {Promise}\n */\nconst processPayment = async(gateway, component, paymentArea, itemId, description) => {\n // eslint-disable-next-line no-console\n console.log('initt23432532532tt');\n const paymentMethod = await import(`paygw_${gateway}/gateways_modal`);\n return paymentMethod.process(component, paymentArea, itemId, description);\n};\n\n/**\n * Set up the payment actions.\n */\nexport const init = () => {\n // eslint-disable-next-line no-console\n console.log('initt23432532532tt');\n if (!init.initialised) {\n // Event listeners should only be registered once.\n init.initialised = true;\n registerEventListeners();\n }\n};\n\n/**\n * Whether the init function was called before.\n *\n * @static\n * @type {boolean}\n */\ninit.initialised = false;\n"],"names":["_modal_factory","_interopRequireDefault","_templates","_selectors","_modal_events","_events","_modal_gateways","_notification","_systemImportTransformerGlobalIdentifier","window","self","global","e","__esModule","default","show","async","rootNode","focusOnClose","arguments","length","undefined","modal","ModalFactory","create","type","ModalGateways","TYPE","title","getString","body","Templates","render","console","log","rootElement","getRoot","addToastRegion","on","ModalEvents","hidden","destroy","focus","PaymentEvents","proceed","gateway","querySelector","Selectors","values","value","processPayment","dataset","component","paymentarea","itemid","description","then","message","hide","showNotification","location","href","successurl","catch","Notification","alert","get_string","addToast","add","preventDefault","addEventListener","target","matches","elements","gateways","updateCostRegion","cost","context","getAvailableGateways","html","js","renderForPromise","replaceNodeContents","regions","gatewaysContainer","selectSingleGateway","root","querySelectorAll","checked","defaultCost","gatewayElement","surcharge","parseInt","fee","costContainer","paymentArea","itemId","define","amd","Promise","resolve","reject","require","module","exports","loader","process","init","initialised","document","gatewayTrigger","closest","_exports"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"cashier_modal.min.js","sources":["../src/cashier_modal.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Contain the logic for the gateways modal.\n *\n * @module core_payment/gateways_modal\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalFactory from 'core/modal_factory';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\nimport {getAvailableGateways} from './repository';\nimport Selectors from './selectors';\nimport ModalEvents from 'core/modal_events';\nimport PaymentEvents from 'core_payment/events';\nimport {add as addToast, addToastRegion} from 'core/toast';\nimport {showNotification} from 'local_shopping_cart/notifications';\nimport ModalGateways from './modal_gateways';\nimport Notification from 'core/notification';\n\n/**\n * Register event listeners for the module.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', e => {\n const gatewayTrigger = e.target.closest('[data-action=\"core_payment/triggerPayment\"]');\n if (gatewayTrigger) {\n e.preventDefault();\n\n show(gatewayTrigger, {focusOnClose: e.target});\n }\n });\n};\n\n/**\n * Shows the gateway selector modal.\n *\n * @param {HTMLElement} rootNode\n * @param {Object} options - Additional options\n * @param {HTMLElement} options.focusOnClose The element to focus on when the modal is closed.\n */\nconst show = async(rootNode, {\n focusOnClose = null,\n} = {}) => {\n const modal = await ModalFactory.create({\n type: ModalGateways.TYPE,\n title: await getString('selectpaymenttype', 'core_payment'),\n body: await Templates.render('core_payment/gateways_modal', {}),\n });\n\n const rootElement = modal.getRoot()[0];\n addToastRegion(rootElement);\n\n modal.show();\n\n modal.getRoot().on(ModalEvents.hidden, () => {\n // Destroy when hidden.\n modal.destroy();\n try {\n focusOnClose.focus();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.log('error: ', e);\n }\n });\n\n modal.getRoot().on(PaymentEvents.proceed, (e) => {\n const gateway = (rootElement.querySelector(Selectors.values.gateway) || {value: ''}).value;\n\n if (gateway) {\n processPayment(\n gateway,\n rootNode.dataset.component,\n rootNode.dataset.paymentarea,\n rootNode.dataset.itemid,\n rootNode.dataset.description\n )\n .then(message => {\n modal.hide();\n showNotification(message, 'success');\n\n location.href = rootNode.dataset.successurl;\n\n // The following return statement is never reached. It is put here just to make eslint happy.\n return message;\n })\n .catch(message => Notification.alert('', message));\n } else {\n // We cannot use await in the following line.\n // The reason is that we are preventing the default action of the save event being triggered,\n // therefore we cannot define the event handler function asynchronous.\n // eslint-disable-next-line promise/catch-or-return\n getString('nogatewayselected', 'core_payment').then(message => addToast(message, {type: 'warning'}));\n }\n\n e.preventDefault();\n });\n\n // Re-calculate the cost when gateway is changed.\n rootElement.addEventListener('change', e => {\n if (e.target.matches(Selectors.elements.gateways)) {\n updateCostRegion(rootElement, rootNode.dataset.cost);\n }\n });\n\n const gateways = await getAvailableGateways(rootNode.dataset.component, rootNode.dataset.paymentarea, rootNode.dataset.itemid);\n const context = {\n gateways\n };\n\n const {html, js} = await Templates.renderForPromise('core_payment/gateways', context);\n Templates.replaceNodeContents(rootElement.querySelector(Selectors.regions.gatewaysContainer), html, js);\n selectSingleGateway(rootElement);\n await updateCostRegion(rootElement, rootNode.dataset.cost);\n};\n\n/**\n * Auto-select the gateway if there is only one gateway.\n *\n * @param {HTMLElement} root An HTMLElement that contains the cost region\n */\nconst selectSingleGateway = root => {\n const gateways = root.querySelectorAll(Selectors.elements.gateways);\n\n if (gateways.length == 1) {\n gateways[0].checked = true;\n }\n};\n\n/**\n * Shows the cost of the item the user is purchasing in the cost region.\n *\n * @param {HTMLElement} root An HTMLElement that contains the cost region\n * @param {string} defaultCost The default cost that is going to be displayed if no gateway is selected\n * @returns {Promise}\n */\nconst updateCostRegion = async(root, defaultCost = '') => {\n const gatewayElement = root.querySelector(Selectors.values.gateway);\n const surcharge = parseInt((gatewayElement || {dataset: {surcharge: 0}}).dataset.surcharge);\n const cost = (gatewayElement || {dataset: {cost: defaultCost}}).dataset.cost;\n\n const {html, js} = await Templates.renderForPromise('core_payment/fee_breakdown', {fee: cost, surcharge});\n Templates.replaceNodeContents(root.querySelector(Selectors.regions.costContainer), html, js);\n};\n\n/**\n * Process payment using the selected gateway.\n *\n * @param {string} gateway The gateway to be used for payment\n * @param {string} component Name of the component that the itemId belongs to\n * @param {string} paymentArea Name of the area in the component that the itemId belongs to\n * @param {number} itemId An internal identifier that is used by the component\n * @param {string} description Description of the payment\n * @returns {Promise}\n */\nconst processPayment = async(gateway, component, paymentArea, itemId, description) => {\n const paymentMethod = await import(`paygw_${gateway}/gateways_modal`);\n return paymentMethod.process(component, paymentArea, itemId, description);\n};\n\n/**\n * Set up the payment actions.\n */\nexport const init = () => {\n if (!init.initialised) {\n // Event listeners should only be registered once.\n init.initialised = true;\n registerEventListeners();\n }\n};\n\n/**\n * Whether the init function was called before.\n *\n * @static\n * @type {boolean}\n */\ninit.initialised = false;\n"],"names":["_modal_factory","_interopRequireDefault","_templates","_selectors","_modal_events","_events","_modal_gateways","_notification","_systemImportTransformerGlobalIdentifier","window","self","global","e","__esModule","default","show","async","rootNode","focusOnClose","arguments","length","undefined","modal","ModalFactory","create","type","ModalGateways","TYPE","title","getString","body","Templates","render","rootElement","getRoot","addToastRegion","on","ModalEvents","hidden","destroy","focus","console","log","PaymentEvents","proceed","gateway","querySelector","Selectors","values","value","processPayment","dataset","component","paymentarea","itemid","description","then","message","hide","showNotification","location","href","successurl","catch","Notification","alert","get_string","addToast","add","preventDefault","addEventListener","target","matches","elements","gateways","updateCostRegion","cost","context","getAvailableGateways","html","js","renderForPromise","replaceNodeContents","regions","gatewaysContainer","selectSingleGateway","root","querySelectorAll","checked","defaultCost","gatewayElement","surcharge","parseInt","fee","costContainer","paymentArea","itemId","define","amd","Promise","resolve","reject","require","module","exports","loader","process","init","initialised","document","gatewayTrigger","closest","_exports"],"mappings":"weAuBAA,eAAAC,uBAAAD,gBACAE,WAAAD,uBAAAC,YAGAC,WAAAF,uBAAAE,YACAC,cAAAH,uBAAAG,eACAC,QAAAJ,uBAAAI,SAGAC,gBAAAL,uBAAAK,iBACAC,cAAAN,uBAAAM,eAA6C,IAAAC,yCAAA,oBAAAC,OAAAA,OAAA,oBAAAC,KAAAA,KAAA,oBAAAC,OAAAA,OAAA,CAAA;;;;;;;KAlB7C,SAAAV,uBAAAW,GAAAA,OAAAA,GAAAA,EAAAC,WAAAD,EAAAE,CAAAA,QAAAF,EAAA,CAuBA,MAkBMG,KAAOC,eAAMC,UAER,IAFkBC,aACzBA,aAAe,MAClBC,UAAAC,OAAAD,QAAAE,IAAAF,UAAAE,GAAAF,UAAG,GAAA,GACA,MAAMG,YAAcC,eAAYT,QAACU,OAAO,CACpCC,KAAMC,gBAAaZ,QAACa,KACpBC,YAAa,EAAAC,KAAAA,YAAU,oBAAqB,gBAC5CC,WAAYC,WAASjB,QAACkB,OAAO,8BAA+B,CAAA,KAG1DC,YAAcX,MAAMY,UAAU,IACpC,EAAAC,OAAAA,gBAAeF,aAEfX,MAAMP,OAENO,MAAMY,UAAUE,GAAGC,cAAWvB,QAACwB,QAAQ,KAEnChB,MAAMiB,UACN,IACIrB,aAAasB,OAChB,CAAC,MAAO5B,GAEL6B,QAAQC,IAAI,UAAW9B,EAC3B,KAGJU,MAAMY,UAAUE,GAAGO,QAAAA,QAAcC,SAAUhC,IACvC,MAAMiC,SAAWZ,YAAYa,cAAcC,WAAAA,QAAUC,OAAOH,UAAY,CAACI,MAAO,KAAKA,MAEjFJ,QACAK,eACIL,QACA5B,SAASkC,QAAQC,UACjBnC,SAASkC,QAAQE,YACjBpC,SAASkC,QAAQG,OACjBrC,SAASkC,QAAQI,aAEpBC,MAAKC,UACFnC,MAAMoC,QACN,EAAAC,eAAgBA,kBAACF,QAAS,WAE1BG,SAASC,KAAO5C,SAASkC,QAAQW,WAG1BL,WAEVM,OAAMN,SAAWO,cAAAA,QAAaC,MAAM,GAAIR,YAMzC,EAAA5B,KAASqC,YAAC,oBAAqB,gBAAgBV,MAAKC,UAAW,EAAAU,OAAQC,KAACX,QAAS,CAAChC,KAAM,cAG5Fb,EAAEyD,gBAAgB,IAItBpC,YAAYqC,iBAAiB,UAAU1D,IAC/BA,EAAE2D,OAAOC,QAAQzB,WAASjC,QAAC2D,SAASC,WACpCC,iBAAiB1C,YAAahB,SAASkC,QAAQyB,KACnD,IAGJ,MACMC,QAAU,CACZH,eAFmB,EAAAI,kCAAqB7D,SAASkC,QAAQC,UAAWnC,SAASkC,QAAQE,YAAapC,SAASkC,QAAQG,UAKjHyB,KAACA,KAAIC,GAAEA,UAAYjD,WAASjB,QAACmE,iBAAiB,wBAAyBJ,SAC7E9C,WAAAA,QAAUmD,oBAAoBjD,YAAYa,cAAcC,WAAAA,QAAUoC,QAAQC,mBAAoBL,KAAMC,IACpGK,oBAAoBpD,mBACd0C,iBAAiB1C,YAAahB,SAASkC,QAAQyB,OAQnDS,oBAAsBC,OACxB,MAAMZ,SAAWY,KAAKC,iBAAiBxC,WAAAA,QAAU0B,SAASC,UAEnC,GAAnBA,SAAStD,SACTsD,SAAS,GAAGc,SAAU,EAC1B,EAUEb,iBAAmB3D,eAAMsE,MAA2B,IAArBG,YAAWtE,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAG,GAC/C,MAAMuE,eAAiBJ,KAAKxC,cAAcC,WAAAA,QAAUC,OAAOH,SACrD8C,UAAYC,UAAUF,gBAAkB,CAACvC,QAAS,CAACwC,UAAW,KAAKxC,QAAQwC,WAC3Ef,MAAQc,gBAAkB,CAACvC,QAAS,CAACyB,KAAMa,eAAetC,QAAQyB,MAElEG,KAACA,KAAIC,GAAEA,UAAYjD,WAAAA,QAAUkD,iBAAiB,6BAA8B,CAACY,IAAKjB,KAAMe,sBAC9F5D,WAAAA,QAAUmD,oBAAoBI,KAAKxC,cAAcC,WAAAA,QAAUoC,QAAQW,eAAgBf,KAAMC,KAavF9B,eAAiBlC,MAAM6B,QAASO,UAAW2C,YAAaC,OAAQzC,qBAC5C/C,mBAAAA,yCAAAyF,QAAAzF,yCAAAyF,OAAAC,IAAA,IAAAC,SAAAC,SAAAA,QAAAC,QAAA7F,yCAAA8F,QAAa,CAAA,SAASzD,0BAAwBuD,QAAAC,OAAA,IAAAE,oBAAAA,QAAAA,OAAAC,SAAAD,oBAAAD,6BAAAC,QAAAA,OAAAnD,WAAA5C,yCAAA8F,SAAA,cAAA9F,yCAAA8F,QAAAG,OAAAN,QAAAC,QAAAE,QAAA,SAAxBzD,2BAAwBsD,QAAAC,QAAA5F,yCAAjC,SAASqC,6BACvB6D,QAAQtD,UAAW2C,YAAaC,OAAQzC,aAMpDoD,KAAOA,KACXA,KAAKC,cAEND,KAAKC,aAAc,EA9IvBC,SAASvC,iBAAiB,SAAS1D,IAC/B,MAAMkG,eAAiBlG,EAAE2D,OAAOwC,QAAQ,+CACpCD,iBACAlG,EAAEyD,iBAEFtD,KAAK+F,eAAgB,CAAC5F,aAAcN,EAAE2D,SAC1C,IA0IJ,EACFyC,SAAAL,KAAAA,KAQFA,KAAKC,aAAc,CAAM"} \ No newline at end of file diff --git a/amd/build/checkout_manager.min.js b/amd/build/checkout_manager.min.js index bab9eeb6..a95e3506 100644 --- a/amd/build/checkout_manager.min.js +++ b/amd/build/checkout_manager.min.js @@ -1,9 +1,9 @@ -define("local_shopping_cart/checkout_manager",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){initControlListener(),function(){const formBody=document.querySelector(SELECTORS.CHECKBOXITEMBODY);formBody&&formBody.addEventListener("change",(function(event){const target=event.target;if(["INPUT","SELECT","TEXTAREA"].includes(target.tagName)){const processElements=document.querySelectorAll('[data-shopping-cart-process-data="true"]'),changedInputs=Array.from(processElements).map((element=>{const value="checkbox"===element.type?element.checked:element.value;return"radio"==element.type?element.checked?{name:element.name||"unnamed",value:value}:null:{name:element.name||"unnamed",value:value}})).filter((item=>null!==item));if(target.hasAttribute("data-skip-webservice"))return;"checkbox"==target.type&&(target.value=target.checked),triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:formBody.dataset.action,currentstep:formBody.dataset.currentstep,identifier:formBody.dataset.identifier,changedinput:JSON.stringify(changedInputs)})}}))}(),function(){const vatNumber=document.getElementById("shopping-cart-checkout-manager-verify-vat");if(vatNumber){const formBody=document.querySelector(SELECTORS.CHECKBOXITEMBODY);vatNumber.addEventListener("click",(function(){const countryCode=document.getElementById("shopping-cart-checkout-manager-country-select").value,vatNumber=document.getElementById("shopping-cart-checkout-manager-vat-number").value;if(!countryCode||!vatNumber)return void alert("Please select a country and enter a valid VAT number.");const changedInput={vatCodeCountry:`${countryCode},${vatNumber}`};triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:formBody.dataset.action,currentstep:formBody.dataset.currentstep,identifier:formBody.dataset.identifier,changedinput:JSON.stringify(changedInput)})}))}}(),document.addEventListener(EVENTSLISTENING.ADDRESSREDRAWN,(function(){!function(){const formBody=document.querySelector(SELECTORS.CHECKBOXITEMBODY),currentstep=formBody?formBody.dataset.currentstep:null;null!==currentstep&&triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:"",currentstep:currentstep})}()}))}; +define("local_shopping_cart/checkout_manager",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getChangedInputs=getChangedInputs,_exports.getDatasetValue=getDatasetValue,_exports.init=function(){(function(formBody){initControlListener(),null!=formBody&&(function(){const formBody=document.querySelector(SELECTORS.CHECKBOXITEMBODY);formBody.addEventListener("change",(event=>function(event,formBody){const target=event.target;if(["INPUT","SELECT","TEXTAREA"].includes(target.tagName)){const changedInputs=getChangedInputs();if(target.hasAttribute("data-skip-webservice"))return;"checkbox"==target.type&&(target.value=target.checked),triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:getDatasetValue(formBody,"action"),currentstep:getDatasetValue(formBody,"currentstep"),identifier:getDatasetValue(formBody,"identifier"),changedinput:JSON.stringify(changedInputs)})}}(event,formBody)))}(),function(){const vatNumber=document.getElementById(IDS.VERIFYVAT);vatNumber&&vatNumber.addEventListener("click",vatNumberVerifyCallback)}())})(document.querySelector(SELECTORS.CHECKBOXITEMBODY)),document.addEventListener(EVENTSLISTENING.ADDRESSREDRAWN,getNewAddress)}; /* * @package local_shopping_cart * @copyright Wunderbyte GmbH * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const SELECTORS={CHECKOUTMANAGERFORMID:"#shopping-cart-checkout-manager-form",CHECKOUTMANAGERFORMTEMPLATE:"local_shopping_cart/checkout_manager_form",CHECKOUTMANAGERBUTTONSTEMPLATE:"local_shopping_cart/checkout_manager_form_buttons",CHECKOUTMANAGERBUTTONSID:"shopping-cart-checkout-manager-buttons",CHECKOUTMANAGERPROGRESSBARTEMPLATE:"local_shopping_cart/checkout_manager_form_progress_bar",CHECKOUTMANAGERPROGRESSBARID:"shopping-cart-checkout-manager-status-bar",BUTTONS:".shopping-cart-checkout-manager-buttons button",PROGRESSBUTTONS:".shopping-cart-checkout-manager-status-bar button",CHECKBOXITEMBODY:"#shopping-cart-checkout-manager-form-body",NEWADDRESSBUTTON:".shopping-cart-new-address",FEEDBACKMESSAGE:".shopping-cart-checkout-manager-alert-container"},WEBSERVICE={CHECKOUTPROCESS:"local_shopping_cart_control_checkout_process"},EVENTSLISTENING={ADDRESSREDRAWN:"local_shopping_cart/addressesRedrawn"};function initControlListener(){[SELECTORS.BUTTONS,SELECTORS.PROGRESSBUTTONS].forEach((selector=>{document.querySelectorAll(selector).forEach((button=>{button.addEventListener("click",(function(){const action=this.getAttribute("data-action"),currentstep=this.getAttribute("data-currentstep");null!=action&&null!=currentstep&&triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:action,currentstep:currentstep})}))}))}))}function triggerButtonControlWebService(serviceName,params){require(["core/ajax"],(function(Ajax){Ajax.call([{methodname:serviceName,args:params}])[0].done((function(response){var data;(data=response).data=JSON.parse(data.data),data.reloadbody?require(["core/templates"],(function(templates){templates.render(SELECTORS.CHECKOUTMANAGERFORMTEMPLATE,data.data).then((function(html,js){return templates.replaceNodeContents(document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID),html,js)})).then((function(){if(data.jsscript){const scriptContent=data.jsscript.replace(/]*>|<\/script>/gi,"");try{templates.appendNodeContents(document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID),"",scriptContent)}catch(err){console.error("Error executing script:",err)}}})).catch((function(err){console.error("Error rendering body: ",err)}))})):require(["core/templates"],(function(templates){const controlButtons=document.getElementById(SELECTORS.CHECKOUTMANAGERBUTTONSID),progressBar=document.getElementById(SELECTORS.CHECKOUTMANAGERPROGRESSBARID),feedbackMessageContainer=document.querySelector(SELECTORS.FEEDBACKMESSAGE);if(!controlButtons)return void console.error("Target div not found in the DOM.");const renderButtonTemplate=templates.render(SELECTORS.CHECKOUTMANAGERBUTTONSTEMPLATE,data.data).then((function(html){controlButtons.innerHTML=html})).catch((function(err){console.error("Error updating the specific div:",err)}));console.log("updating the specific div:",data);const progressBarTemplate=templates.render(SELECTORS.CHECKOUTMANAGERPROGRESSBARTEMPLATE,data.data).then((function(html){progressBar.innerHTML=html})).catch((function(err){console.error("Error updating the specific div:",err)}));if(feedbackMessageContainer){const datafeedback=JSON.parse(data.managerdata);feedbackMessageContainer&&null!=datafeedback.feedback&&templates.render("local_shopping_cart/checkout_manager_feedback",datafeedback.feedback).then((function(html){feedbackMessageContainer.innerHTML=html})).catch((function(err){console.error("Error updating feedback message:",err)}))}Promise.all([renderButtonTemplate,progressBarTemplate]).then((function(){console.log("Both templates have been updated."),initControlListener()})).catch((function(err){console.error("Render problem:",err)}))}))})).fail((function(err){console.error("Failed to complete action. Error: ",err)}))}))}})); +const SELECTORS={CHECKOUTMANAGERFORMID:"#shopping-cart-checkout-manager-form",CHECKOUTMANAGERFORMTEMPLATE:"local_shopping_cart/checkout_manager_form",CHECKOUTMANAGERBUTTONSTEMPLATE:"local_shopping_cart/checkout_manager_form_buttons",CHECKOUTMANAGERBUTTONSID:"shopping-cart-checkout-manager-buttons",CHECKOUTMANAGERPROGRESSBARTEMPLATE:"local_shopping_cart/checkout_manager_form_progress_bar",CHECKOUTMANAGERPROGRESSBARID:"shopping-cart-checkout-manager-status-bar",BUTTONS:".shopping-cart-checkout-manager-buttons button",PROGRESSBUTTONS:".shopping-cart-checkout-manager-status-bar button",CHECKBOXITEMBODY:"#shopping-cart-checkout-manager-form-body",NEWADDRESSBUTTON:".shopping-cart-new-address",FEEDBACKMESSAGE:".shopping-cart-checkout-manager-alert-container"},WEBSERVICE={CHECKOUTPROCESS:"local_shopping_cart_control_checkout_process"},EVENTSLISTENING={ADDRESSREDRAWN:"local_shopping_cart/addressesRedrawn"},IDS={VATNUMBER:"shopping-cart-checkout-manager-vat-number",VERIFYVAT:"shopping-cart-checkout-manager-verify-vat",COUNTRYSELECT:"shopping-cart-checkout-manager-country-select"};function getNewAddress(){const currentstep=getDatasetValue(document.querySelector(SELECTORS.CHECKBOXITEMBODY),"currentstep");null!==currentstep&&triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:"",currentstep:currentstep})}function vatNumberVerifyCallback(){const formBody=document.querySelector(SELECTORS.CHECKBOXITEMBODY),countryCode=document.getElementById(IDS.COUNTRYSELECT)?.value,vatNumber=document.getElementById(IDS.VATNUMBER)?.value;countryCode&&vatNumber?triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:getDatasetValue(formBody,"action"),currentstep:getDatasetValue(formBody,"currentstep"),identifier:getDatasetValue(formBody,"identifier"),changedinput:JSON.stringify({vatCodeCountry:`${countryCode},${vatNumber}`})}):alert("alert")}function initControlListener(){const selectors=`${SELECTORS.BUTTONS}, ${SELECTORS.PROGRESSBUTTONS}`;document.querySelectorAll(selectors).forEach((button=>{button.addEventListener("click",controlCallback)}))}function controlCallback(){const action=this.getAttribute("data-action"),currentstep=this.getAttribute("data-currentstep");action&¤tstep&&triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS,{action:action,currentstep:currentstep})}function getChangedInputs(){const processElements=document.querySelectorAll('[data-shopping-cart-process-data="true"]');return Array.from(processElements).map((element=>{const value="checkbox"===element.type?element.checked:element.value;return"radio"===element.type?element.checked?{name:element.name||"unnamed",value:value}:[]:{name:element.name||"unnamed",value:value}})).filter((item=>null!==item))}function triggerButtonControlWebService(serviceName,params){require(["core/ajax"],(function(Ajax){Ajax.call([{methodname:serviceName,args:params}])[0].done((function(response){var data;(data=response).data=JSON.parse(data.data),require(["core/templates"],(function(templates){data.reloadbody?function(templates,data){templates.render(SELECTORS.CHECKOUTMANAGERFORMTEMPLATE,data.data).then((function(html,js){return templates.replaceNodeContents(document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID),html,js)})).then((function(){if(data.jsscript){const scriptContent=data.jsscript.replace(/]*>|<\/script>/gi,"");try{templates.appendNodeContents(document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID),"",scriptContent)}catch(err){console.error("fail script",err)}}})).catch((function(err){console.error("fail script",err)}))}(templates,data):function(templates,data){const controlButtons=document.getElementById(SELECTORS.CHECKOUTMANAGERBUTTONSID),progressBar=document.getElementById(SELECTORS.CHECKOUTMANAGERPROGRESSBARID),feedbackMessageContainer=document.querySelector(SELECTORS.FEEDBACKMESSAGE);if(!controlButtons)return void console.error("controlButtons");const renderButtonTemplate=templates.render(SELECTORS.CHECKOUTMANAGERBUTTONSTEMPLATE,data.data).then((function(html){controlButtons.innerHTML=html})).catch((function(err){console.error("fail render button",err)})),progressBarTemplate=templates.render(SELECTORS.CHECKOUTMANAGERPROGRESSBARTEMPLATE,data.data).then((function(html){progressBar.innerHTML=html})).catch((function(err){console.error("fail render button",err)}));if(feedbackMessageContainer){const datafeedback=JSON.parse(data.managerdata);feedbackMessageContainer&&null!=datafeedback.feedback&&templates.render("local_shopping_cart/checkout_manager_feedback",datafeedback.feedback).then((function(html){feedbackMessageContainer.innerHTML=html})).catch((function(err){console.error("fail render feedback",err)}))}Promise.all([renderButtonTemplate,progressBarTemplate]).then((function(){initControlListener()})).catch((function(err){console.error("fail init listener",err)}))}(templates,data)}))})).fail((function(err){console.error("fail button trigger",err)}))}))}function getDatasetValue(element,key){return element?.dataset[key]||""}})); //# sourceMappingURL=checkout_manager.min.js.map \ No newline at end of file diff --git a/amd/build/checkout_manager.min.js.map b/amd/build/checkout_manager.min.js.map index 658fd57c..995f93ee 100644 --- a/amd/build/checkout_manager.min.js.map +++ b/amd/build/checkout_manager.min.js.map @@ -1 +1 @@ -{"version":3,"file":"checkout_manager.min.js","sources":["../src/checkout_manager.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/*\n * @package local_shopping_cart\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst SELECTORS = {\n CHECKOUTMANAGERFORMID: '#shopping-cart-checkout-manager-form',\n CHECKOUTMANAGERFORMTEMPLATE: 'local_shopping_cart/checkout_manager_form',\n CHECKOUTMANAGERBUTTONSTEMPLATE: 'local_shopping_cart/checkout_manager_form_buttons',\n CHECKOUTMANAGERBUTTONSID: 'shopping-cart-checkout-manager-buttons',\n CHECKOUTMANAGERPROGRESSBARTEMPLATE: 'local_shopping_cart/checkout_manager_form_progress_bar',\n CHECKOUTMANAGERPROGRESSBARID: 'shopping-cart-checkout-manager-status-bar',\n BUTTONS: '.shopping-cart-checkout-manager-buttons button',\n PROGRESSBUTTONS: '.shopping-cart-checkout-manager-status-bar button',\n CHECKBOXITEMBODY: '#shopping-cart-checkout-manager-form-body',\n NEWADDRESSBUTTON: '.shopping-cart-new-address',\n FEEDBACKMESSAGE: '.shopping-cart-checkout-manager-alert-container'\n};\n\nconst WEBSERVICE = {\n CHECKOUTPROCESS: 'local_shopping_cart_control_checkout_process',\n};\n\nconst EVENTSLISTENING = {\n ADDRESSREDRAWN: 'local_shopping_cart/addressesRedrawn',\n};\n/**\n * Initializes the checkout manager functionality.\n */\nfunction init() {\n initControlListener();\n initChangeListener();\n initVatNumberVerifyListener();\n document.addEventListener(EVENTSLISTENING.ADDRESSREDRAWN, function() {\n getNewAddress();\n });\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction getNewAddress() {\n const formBody = document.querySelector(SELECTORS.CHECKBOXITEMBODY);\n const currentstep = formBody ? formBody.dataset.currentstep : null;\n if (currentstep !== null) {\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: '',\n currentstep: currentstep,\n });\n }\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction initVatNumberVerifyListener() {\n const vatNumber = document.getElementById('shopping-cart-checkout-manager-verify-vat');\n if (vatNumber) {\n const formBody = document.querySelector(SELECTORS.CHECKBOXITEMBODY);\n vatNumber.addEventListener('click', function() {\n const countrySelect = document.getElementById('shopping-cart-checkout-manager-country-select');\n const countryCode = countrySelect.value;\n\n const vatNumberInput = document.getElementById('shopping-cart-checkout-manager-vat-number');\n const vatNumber = vatNumberInput.value;\n\n if (!countryCode || !vatNumber) {\n alert('Please select a country and enter a valid VAT number.');\n return;\n }\n const vatCountryCodeNumber = `${countryCode},${vatNumber}`;\n const changedInput = {\n 'vatCodeCountry': vatCountryCodeNumber,\n };\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: formBody.dataset.action,\n currentstep: formBody.dataset.currentstep,\n identifier: formBody.dataset.identifier,\n changedinput: JSON.stringify(changedInput)\n });\n });\n }\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction initControlListener() {\n const buttonSelectors = [SELECTORS.BUTTONS, SELECTORS.PROGRESSBUTTONS];\n buttonSelectors.forEach(selector => {\n const buttons = document.querySelectorAll(selector);\n buttons.forEach(button => {\n button.addEventListener('click', function() {\n const action = this.getAttribute('data-action');\n const currentstep = this.getAttribute('data-currentstep');\n if (\n action != undefined &&\n currentstep != undefined\n ) {\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: action,\n currentstep: currentstep,\n });\n }\n });\n });\n });\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction initChangeListener() {\n const formBody = document.querySelector(SELECTORS.CHECKBOXITEMBODY);\n if (formBody) {\n formBody.addEventListener('change', function(event) {\n const target = event.target;\n if (['INPUT', 'SELECT', 'TEXTAREA'].includes(target.tagName)) {\n const processElements = document.querySelectorAll('[data-shopping-cart-process-data=\"true\"]');\n const changedInputs = Array.from(processElements).map(element => {\n const value = element.type === 'checkbox' ? element.checked : element.value;\n if (\n element.type == 'radio'\n ) {\n if (element.checked) {\n return {\n name: element.name || 'unnamed',\n value: value,\n };\n }\n return null;\n } else {\n return {\n name: element.name || 'unnamed',\n value: value,\n };\n }\n })\n .filter(item => item !== null);\n if (\n target.hasAttribute('data-skip-webservice')\n ) {\n return;\n }\n if (target.type == 'checkbox') {\n target.value = target.checked;\n }\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: formBody.dataset.action,\n currentstep: formBody.dataset.currentstep,\n identifier: formBody.dataset.identifier,\n changedinput: JSON.stringify(changedInputs)\n });\n }\n });\n }\n}\n\n/**\n * Handles button control for the checkout process.\n * @param {string} serviceName - The name of the web service.\n * @param {Object} params - The parameters for the web service call.\n */\nfunction triggerButtonControlWebService(serviceName, params) {\n require(['core/ajax'], function (Ajax) {\n const requests = Ajax.call([{\n methodname: serviceName,\n args: params,\n }]);\n requests[0].done(function(response) {\n updateCheckoutManagerPartials(response);\n }).fail(function(err) {\n // eslint-disable-next-line no-console\n console.error('Failed to complete action. Error: ', err);\n return;\n });\n });\n}\n\n/**\n * Updates specific Mustache partials dynamically based on the web service response.\n * @param {Object} data - The data returned from the web service.\n */\nfunction updateCheckoutManagerPartials(data) {\n data.data = JSON.parse(data.data);\n if (data.reloadbody) {\n require(['core/templates'], function(templates) {\n templates.render(SELECTORS.CHECKOUTMANAGERFORMTEMPLATE, data.data)\n .then(function(html, js) {\n return templates.replaceNodeContents(document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID), html, js);\n })\n .then(function() {\n if (data.jsscript) {\n const scriptContent = data.jsscript.replace(/]*>|<\\/script>/gi, '');\n try {\n templates.appendNodeContents(\n document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID),\n '',\n scriptContent\n );\n\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('Error executing script:', err);\n }\n }\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('Error rendering body: ', err);\n return;\n });\n });\n } else {\n require(['core/templates'], function(templates) {\n const controlButtons = document.getElementById(SELECTORS.CHECKOUTMANAGERBUTTONSID);\n const progressBar = document.getElementById(SELECTORS.CHECKOUTMANAGERPROGRESSBARID);\n const feedbackMessageContainer = document.querySelector(SELECTORS.FEEDBACKMESSAGE);\n\n if (!controlButtons) {\n // eslint-disable-next-line no-console\n console.error('Target div not found in the DOM.');\n return;\n }\n // Render new content for the div\n const renderButtonTemplate = templates.render(SELECTORS.CHECKOUTMANAGERBUTTONSTEMPLATE, data.data)\n .then(function(html) {\n controlButtons.innerHTML = html;\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('Error updating the specific div:', err);\n });\n // eslint-disable-next-line no-console\n console.log('updating the specific div:', data);\n const progressBarTemplate = templates.render(SELECTORS.CHECKOUTMANAGERPROGRESSBARTEMPLATE, data.data)\n .then(function(html) {\n progressBar.innerHTML = html;\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('Error updating the specific div:', err);\n });\n if (feedbackMessageContainer) {\n const datafeedback = JSON.parse(data.managerdata);\n if (\n feedbackMessageContainer &&\n datafeedback.feedback != undefined\n ) {\n templates.render('local_shopping_cart/checkout_manager_feedback', datafeedback.feedback)\n .then(function(html) {\n feedbackMessageContainer.innerHTML = html;\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('Error updating feedback message:', err);\n });\n }\n }\n Promise.all([renderButtonTemplate, progressBarTemplate]).then(function() {\n // eslint-disable-next-line no-console\n console.log('Both templates have been updated.');\n\n initControlListener();\n return;\n }).catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('Render problem:', err);\n });\n });\n\n }\n}\n\nexport {init};"],"names":["initControlListener","formBody","document","querySelector","SELECTORS","CHECKBOXITEMBODY","addEventListener","event","target","includes","tagName","processElements","querySelectorAll","changedInputs","Array","from","map","element","value","type","checked","name","filter","item","hasAttribute","triggerButtonControlWebService","WEBSERVICE","CHECKOUTPROCESS","action","dataset","currentstep","identifier","changedinput","JSON","stringify","initChangeListener","vatNumber","getElementById","countryCode","alert","changedInput","vatCodeCountry","initVatNumberVerifyListener","EVENTSLISTENING","ADDRESSREDRAWN","getNewAddress","CHECKOUTMANAGERFORMID","CHECKOUTMANAGERFORMTEMPLATE","CHECKOUTMANAGERBUTTONSTEMPLATE","CHECKOUTMANAGERBUTTONSID","CHECKOUTMANAGERPROGRESSBARTEMPLATE","CHECKOUTMANAGERPROGRESSBARID","BUTTONS","PROGRESSBUTTONS","NEWADDRESSBUTTON","FEEDBACKMESSAGE","forEach","selector","button","this","getAttribute","undefined","serviceName","params","require","Ajax","call","methodname","args","done","response","data","parse","reloadbody","templates","render","then","html","js","replaceNodeContents","jsscript","scriptContent","replace","appendNodeContents","err","console","error","catch","controlButtons","progressBar","feedbackMessageContainer","renderButtonTemplate","innerHTML","log","progressBarTemplate","datafeedback","managerdata","feedback","Promise","all","fail"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"checkout_manager.min.js","sources":["../src/checkout_manager.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/*\n * @package local_shopping_cart\n * @copyright Wunderbyte GmbH \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst SELECTORS = {\n CHECKOUTMANAGERFORMID: '#shopping-cart-checkout-manager-form',\n CHECKOUTMANAGERFORMTEMPLATE: 'local_shopping_cart/checkout_manager_form',\n CHECKOUTMANAGERBUTTONSTEMPLATE: 'local_shopping_cart/checkout_manager_form_buttons',\n CHECKOUTMANAGERBUTTONSID: 'shopping-cart-checkout-manager-buttons',\n CHECKOUTMANAGERPROGRESSBARTEMPLATE: 'local_shopping_cart/checkout_manager_form_progress_bar',\n CHECKOUTMANAGERPROGRESSBARID: 'shopping-cart-checkout-manager-status-bar',\n BUTTONS: '.shopping-cart-checkout-manager-buttons button',\n PROGRESSBUTTONS: '.shopping-cart-checkout-manager-status-bar button',\n CHECKBOXITEMBODY: '#shopping-cart-checkout-manager-form-body',\n NEWADDRESSBUTTON: '.shopping-cart-new-address',\n FEEDBACKMESSAGE: '.shopping-cart-checkout-manager-alert-container'\n};\n\nconst WEBSERVICE = {\n CHECKOUTPROCESS: 'local_shopping_cart_control_checkout_process',\n};\n\nconst EVENTSLISTENING = {\n ADDRESSREDRAWN: 'local_shopping_cart/addressesRedrawn',\n};\n\nconst IDS = {\n VATNUMBER: 'shopping-cart-checkout-manager-vat-number',\n VERIFYVAT: 'shopping-cart-checkout-manager-verify-vat',\n COUNTRYSELECT: 'shopping-cart-checkout-manager-country-select',\n};\n\n/**\n * Initializes the checkout manager functionality.\n */\nfunction init() {\n const formBody = document.querySelector(SELECTORS.CHECKBOXITEMBODY);\n initListeners(formBody);\n document.addEventListener(EVENTSLISTENING.ADDRESSREDRAWN, getNewAddress);\n}\n\n/**\n * Initializes the checkout manager functionality.\n * @param {HTMLElement} formBody - The name of the web service.\n */\nfunction initListeners(formBody) {\n initControlListener();\n if (formBody != undefined) {\n initChangeListener();\n initVatNumberVerifyListener(formBody);\n }\n\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction getNewAddress() {\n const formBody = document.querySelector(SELECTORS.CHECKBOXITEMBODY);\n const currentstep = getDatasetValue(formBody, 'currentstep');\n if (currentstep !== null) {\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: '',\n currentstep: currentstep,\n });\n }\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction initVatNumberVerifyListener() {\n const vatNumber = document.getElementById(IDS.VERIFYVAT);\n if (vatNumber) {\n vatNumber.addEventListener('click', vatNumberVerifyCallback);\n }\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction vatNumberVerifyCallback() {\n const formBody = document.querySelector(SELECTORS.CHECKBOXITEMBODY);\n const countryCode = document.getElementById(IDS.COUNTRYSELECT)?.value;\n const vatNumber = document.getElementById(IDS.VATNUMBER)?.value;\n\n if (!countryCode || !vatNumber) {\n alert('alert');\n return;\n }\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: getDatasetValue(formBody, 'action'),\n currentstep: getDatasetValue(formBody, 'currentstep'),\n identifier: getDatasetValue(formBody, 'identifier'),\n changedinput: JSON.stringify({\n 'vatCodeCountry': `${countryCode},${vatNumber}`,\n }),\n });\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction initControlListener() {\n const selectors = `${SELECTORS.BUTTONS}, ${SELECTORS.PROGRESSBUTTONS}`;\n document.querySelectorAll(selectors).forEach(button => {\n button.addEventListener('click', controlCallback);\n });\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction controlCallback() {\n const action = this.getAttribute('data-action');\n const currentstep = this.getAttribute('data-currentstep');\n if (action && currentstep) {\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: action,\n currentstep: currentstep,\n });\n }\n}\n\n/**\n * Initializes the change listener for the form body.\n */\nfunction initChangeListener() {\n const formBody = document.querySelector(SELECTORS.CHECKBOXITEMBODY);\n formBody.addEventListener('change', event => changeCallback(event, formBody));\n}\n\n/**\n * Initializes the change listener for the form body.\n * @param {Object} event - The name of the web service.\n * @param {HTMLElement} formBody - The parameters for the web service call.\n */\nfunction changeCallback(event, formBody) {\n const target = event.target;\n if (['INPUT', 'SELECT', 'TEXTAREA'].includes(target.tagName)) {\n const changedInputs = getChangedInputs();\n if (\n target.hasAttribute('data-skip-webservice')\n ) {\n return;\n }\n if (target.type == 'checkbox') {\n target.value = target.checked;\n }\n\n triggerButtonControlWebService(WEBSERVICE.CHECKOUTPROCESS, {\n action: getDatasetValue(formBody, 'action'),\n currentstep: getDatasetValue(formBody, 'currentstep'),\n identifier: getDatasetValue(formBody, 'identifier'),\n changedinput: JSON.stringify(changedInputs)\n });\n }\n}\n\n/**\n * Handles button control for the checkout process.\n */\nfunction getChangedInputs() {\n const processElements = document.querySelectorAll('[data-shopping-cart-process-data=\"true\"]');\n return Array.from(processElements).map(element => {\n const value = element.type === 'checkbox' ? element.checked : element.value;\n if (element.type === 'radio') {\n return element.checked\n ? {name: element.name || 'unnamed', value: value}\n : [];\n }\n\n return {\n name: element.name || 'unnamed',\n value: value,\n };\n })\n .filter(item => item !== null);\n}\n\n\n/**\n * Handles button control for the checkout process.\n * @param {string} serviceName - The name of the web service.\n * @param {Object} params - The parameters for the web service call.\n */\nfunction triggerButtonControlWebService(serviceName, params) {\n require(['core/ajax'], function (Ajax) {\n const requests = Ajax.call([{\n methodname: serviceName,\n args: params,\n }]);\n requests[0].done(function(response) {\n updateCheckoutManagerPartials(response);\n }).fail(function(err) {\n // eslint-disable-next-line no-console\n console.error('fail button trigger', err);\n return;\n });\n });\n}\n\n/**\n * Updates specific Mustache partials dynamically based on the web service response.\n * @param {Object} data - The data returned from the web service.\n */\nfunction updateCheckoutManagerPartials(data) {\n data.data = JSON.parse(data.data);\n require(['core/templates'], function(templates) {\n if (data.reloadbody) {\n staticReloadBody(templates, data);\n } else {\n newReloadBody(templates, data);\n }\n });\n}\n\n/**\n * Utility to get dataset values safely.\n * @param {Object} templates - The element with the dataset.\n * @param {Array} data - The element with the dataset.\n */\nfunction newReloadBody(templates, data) {\n const controlButtons = document.getElementById(SELECTORS.CHECKOUTMANAGERBUTTONSID);\n const progressBar = document.getElementById(SELECTORS.CHECKOUTMANAGERPROGRESSBARID);\n const feedbackMessageContainer = document.querySelector(SELECTORS.FEEDBACKMESSAGE);\n\n if (!controlButtons) {\n // eslint-disable-next-line no-console\n console.error('controlButtons');\n return;\n }\n // Render new content for the div\n const renderButtonTemplate = templates.render(SELECTORS.CHECKOUTMANAGERBUTTONSTEMPLATE, data.data)\n .then(function(html) {\n controlButtons.innerHTML = html;\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('fail render button', err);\n });\n const progressBarTemplate = templates.render(SELECTORS.CHECKOUTMANAGERPROGRESSBARTEMPLATE, data.data)\n .then(function(html) {\n progressBar.innerHTML = html;\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('fail render button', err);\n });\n if (feedbackMessageContainer) {\n const datafeedback = JSON.parse(data.managerdata);\n if (\n feedbackMessageContainer &&\n datafeedback.feedback != undefined\n ) {\n templates.render('local_shopping_cart/checkout_manager_feedback', datafeedback.feedback)\n .then(function(html) {\n feedbackMessageContainer.innerHTML = html;\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('fail render feedback', err);\n });\n }\n }\n Promise.all([renderButtonTemplate, progressBarTemplate]).then(function() {\n initControlListener();\n return;\n }).catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('fail init listener', err);\n });\n}\n\n/**\n * Utility to get dataset values safely.\n * @param {Object} templates - The element with the dataset.\n * @param {Array} data - The element with the dataset.\n */\nfunction staticReloadBody(templates, data) {\n templates.render(SELECTORS.CHECKOUTMANAGERFORMTEMPLATE, data.data)\n .then(function(html, js) {\n return templates.replaceNodeContents(document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID), html, js);\n })\n .then(function() {\n if (data.jsscript) {\n const scriptContent = data.jsscript.replace(/]*>|<\\/script>/gi, '');\n try {\n templates.appendNodeContents(\n document.querySelector(SELECTORS.CHECKOUTMANAGERFORMID),\n '',\n scriptContent\n );\n\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error('fail script', err);\n }\n }\n return;\n })\n .catch(function(err) {\n // eslint-disable-next-line no-console\n console.error('fail script', err);\n return;\n });\n}\n\n/**\n * Utility to get dataset values safely.\n * @param {HTMLElement} element - The element with the dataset.\n * @param {string} key - The dataset key.\n * @returns {string|null} - The value or null if not found.\n */\nfunction getDatasetValue(element, key) {\n return element?.dataset[key] || '';\n}\n\nexport {\n init,\n getDatasetValue,\n getChangedInputs\n};"],"names":["formBody","initControlListener","undefined","document","querySelector","SELECTORS","CHECKBOXITEMBODY","addEventListener","event","target","includes","tagName","changedInputs","getChangedInputs","hasAttribute","type","value","checked","triggerButtonControlWebService","WEBSERVICE","CHECKOUTPROCESS","action","getDatasetValue","currentstep","identifier","changedinput","JSON","stringify","changeCallback","initChangeListener","vatNumber","getElementById","IDS","VERIFYVAT","vatNumberVerifyCallback","initVatNumberVerifyListener","initListeners","EVENTSLISTENING","ADDRESSREDRAWN","getNewAddress","CHECKOUTMANAGERFORMID","CHECKOUTMANAGERFORMTEMPLATE","CHECKOUTMANAGERBUTTONSTEMPLATE","CHECKOUTMANAGERBUTTONSID","CHECKOUTMANAGERPROGRESSBARTEMPLATE","CHECKOUTMANAGERPROGRESSBARID","BUTTONS","PROGRESSBUTTONS","NEWADDRESSBUTTON","FEEDBACKMESSAGE","VATNUMBER","COUNTRYSELECT","countryCode","vatCodeCountry","alert","selectors","querySelectorAll","forEach","button","controlCallback","this","getAttribute","processElements","Array","from","map","element","name","filter","item","serviceName","params","require","Ajax","call","methodname","args","done","response","data","parse","templates","reloadbody","render","then","html","js","replaceNodeContents","jsscript","scriptContent","replace","appendNodeContents","err","console","error","catch","staticReloadBody","controlButtons","progressBar","feedbackMessageContainer","renderButtonTemplate","innerHTML","progressBarTemplate","datafeedback","managerdata","feedback","Promise","all","newReloadBody","fail","key","dataset"],"mappings":"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"} \ No newline at end of file diff --git a/classes/local/checkout_process/checkout_manager.php b/classes/local/checkout_process/checkout_manager.php index 069a412c..d1639a4a 100644 --- a/classes/local/checkout_process/checkout_manager.php +++ b/classes/local/checkout_process/checkout_manager.php @@ -119,6 +119,7 @@ public function set_manager_data(&$checkoutmanager, $currentstep) { 'item' => $iteminstance->get_icon_progress_bar(), 'status' => 'inactive', 'valid' => self::is_step_valid($classname), + 'mandatory' => $iteminstance->is_mandatory(), 'classname' => $classname, ]; } diff --git a/lang/de/local_shopping_cart.php b/lang/de/local_shopping_cart.php index 2f9cf9a6..9f99593d 100644 --- a/lang/de/local_shopping_cart.php +++ b/lang/de/local_shopping_cart.php @@ -188,6 +188,7 @@ $string['choosehighertimestamp'] = 'Wählen Sie einen späteren Zeipunkt'; $string['chooseplatform'] = 'Plattform wählen'; $string['chooseplatformdesc'] = 'Wählen Sie Ihre Rechnungsplattform aus.'; +$string['completeshoppingcartprecheckout'] = 'Füllen Sie zunächst alle Pflichtfelder aus, um den Einkauf abzuschließen.'; $string['confirmadditionalconditions'] = "Zusätzliche Konditionen akzeptieren"; $string['confirmcancelallbody'] = 'Möchten Sie den Kauf für alle aktuellen Käufer:innen wirklich stornieren? Folgende Nutzer:innen erhalten den Kaufpreis zurück: @@ -422,6 +423,7 @@ $string['modulename'] = 'Warenkorb'; $string['mt'] = "Malta"; $string['mycart'] = 'Mein Warenkorb'; +$string['nextbutton'] = "Nächster Schritt"; $string['nl'] = "Niederlande"; $string['nocostcenter'] = 'Keine Kostenstelle'; $string['nofixedpercentage'] = 'Kein fixer Prozentsatz'; @@ -505,6 +507,7 @@ $string['placeholderlabelitemname'] = ""; $string['placeholderlabelprice'] = " "; $string['pluginname'] = 'Warenkorb'; +$string['previousbutton'] = 'Vorheriger Schritt'; $string['previouspurchases'] = 'Bisherige Käufe'; $string['price'] = 'Preis'; $string['print'] = 'Drucken'; diff --git a/lang/en/local_shopping_cart.php b/lang/en/local_shopping_cart.php index 241cfc98..9a5189c9 100644 --- a/lang/en/local_shopping_cart.php +++ b/lang/en/local_shopping_cart.php @@ -187,6 +187,7 @@ $string['choosehighertimestamp'] = 'Choose a later time'; $string['chooseplatform'] = 'Choose Platform'; $string['chooseplatformdesc'] = 'Select your invoicing platform.'; +$string['completeshoppingcartprecheckout'] = 'Submit all mandatory fields, before continuing with the payment process..'; $string['confirmadditionalconditions'] = "I accept the additional conditions"; $string['confirmcancelallbody'] = 'Do you really want to cancel this purchase for all users? The following users will get their money back as credit: diff --git a/templates/checkout_manager_form_buttons.mustache b/templates/checkout_manager_form_buttons.mustache index 12bd8519..121a6752 100644 --- a/templates/checkout_manager_form_buttons.mustache +++ b/templates/checkout_manager_form_buttons.mustache @@ -64,13 +64,12 @@ {{/checkout_manager_body.buttons.next_button}} - {{#checkout_manager_body.buttons.checkout_button}} +
{{> local_shopping_cart/checkout_payment_checkout}}
- {{/checkout_manager_body.buttons.checkout_button}}