diff --git a/mod/data/amd/build/importmappingdialogue.min.js b/mod/data/amd/build/importmappingdialogue.min.js new file mode 100644 index 00000000000..20e603ce9c9 --- /dev/null +++ b/mod/data/amd/build/importmappingdialogue.min.js @@ -0,0 +1,10 @@ +define("mod_data/importmappingdialogue",["exports","core/notification","core/ajax","core/url","core/templates","core/modal_factory","core/prefetch","core/str"],(function(_exports,_notification,_ajax,_url,_templates,_modal_factory,_prefetch,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +/** + * Javascript module for deleting a database as a preset. + * + * @module mod_data/importmappingdialogue + * @copyright 2022 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax),_url=_interopRequireDefault(_url),_templates=_interopRequireDefault(_templates),_modal_factory=_interopRequireDefault(_modal_factory),(0,_prefetch.prefetchStrings)("mod_data",["mapping:dialogtitle:usepreset"]);const selectors_selectPresetButton='input[name="selectpreset"]';_exports.init=()=>{registerEventListeners()};const registerEventListeners=()=>{document.addEventListener("click",(event=>{const usepreset=event.target.closest(selectors_selectPresetButton);usepreset&&(event.preventDefault(),showMappingDialogue(usepreset))}))},showMappingDialogue=usepreset=>{const presetName=usepreset.dataset.presetname,cmId=usepreset.dataset.cmid;getMappingInformation(cmId,presetName).then((result=>(result.data&&result.data.needsmapping?buildModal({title:(0,_str.get_string)("mapping:dialogtitle:usepreset","mod_data",result.data.presetname),body:_templates.default.render("mod_data/fields_mapping_body",result.data),footer:_templates.default.render("mod_data/fields_mapping_footer",getMappingButtons(cmId,presetName)),large:!0}):window.location.href=_url.default.relativeUrl("mod/data/field.php",{id:cmId,mode:"usepreset",fullname:presetName},!1),!0))).catch(_notification.default.exception)},buildModal=params=>_modal_factory.default.create({...params,type:_modal_factory.default.types.DEFAULT}).then((modal=>(modal.show(),modal.showFooter(),modal.registerCloseOnCancel(),modal))).catch(_notification.default.exception),getMappingButtons=(cmId,presetName)=>{const data={};return data.mapfieldsbutton=_url.default.relativeUrl("mod/data/field.php",{id:cmId,fullname:presetName,mode:"usepreset",action:"select"},!1),data.applybutton=_url.default.relativeUrl("mod/data/field.php",{id:cmId,fullname:presetName,mode:"usepreset",action:"notmapping"},!1),data},getMappingInformation=(cmId,presetName)=>{const request={methodname:"mod_data_get_mapping_information",args:{cmid:cmId,importedpreset:presetName}};return _ajax.default.call([request])[0]}})); + +//# sourceMappingURL=importmappingdialogue.min.js.map \ No newline at end of file diff --git a/mod/data/amd/build/importmappingdialogue.min.js.map b/mod/data/amd/build/importmappingdialogue.min.js.map new file mode 100644 index 00000000000..e728d110fa0 --- /dev/null +++ b/mod/data/amd/build/importmappingdialogue.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"importmappingdialogue.min.js","sources":["../src/importmappingdialogue.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 * Javascript module for deleting a database as a preset.\n *\n * @module mod_data/importmappingdialogue\n * @copyright 2022 Amaia Anabitarte \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Notification from 'core/notification';\nimport Ajax from 'core/ajax';\nimport Url from 'core/url';\nimport Templates from 'core/templates';\nimport ModalFactory from 'core/modal_factory';\nimport {prefetchStrings} from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\n// Load global strings.\nprefetchStrings('mod_data', ['mapping:dialogtitle:usepreset']);\n\nconst selectors = {\n selectPresetButton: 'input[name=\"selectpreset\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n registerEventListeners();\n};\n\n/**\n * Register events.\n */\nconst registerEventListeners = () => {\n document.addEventListener('click', (event) => {\n const usepreset = event.target.closest(selectors.selectPresetButton);\n if (usepreset) {\n event.preventDefault();\n showMappingDialogue(usepreset);\n }\n });\n};\n\n/**\n * Show the confirmation modal for uploading a preset.\n *\n * @param {HTMLElement} usepreset the preset to import.\n */\nconst showMappingDialogue = (usepreset) => {\n const presetName = usepreset.dataset.presetname;\n const cmId = usepreset.dataset.cmid;\n\n getMappingInformation(cmId, presetName).then((result) => {\n if (result.data && result.data.needsmapping) {\n buildModal({\n title: getString('mapping:dialogtitle:usepreset', 'mod_data', result.data.presetname),\n body: Templates.render('mod_data/fields_mapping_body', result.data),\n footer: Templates.render('mod_data/fields_mapping_footer', getMappingButtons(cmId, presetName)),\n large: true,\n });\n } else {\n window.location.href = Url.relativeUrl(\n 'mod/data/field.php',\n {\n id: cmId,\n mode: 'usepreset',\n fullname: presetName,\n },\n false\n );\n }\n return true;\n }).catch(Notification.exception);\n};\n\n/**\n * Given an object we want to build a modal ready to show\n *\n * @method buildModal\n * @param {Object} params the modal params\n * @param {Promise} params.title\n * @param {Promise} params.body\n * @param {Promise} params.footer\n * @return {Object} The modal ready to display immediately and render body in later.\n */\nconst buildModal = (params) => {\n return ModalFactory.create({\n ...params,\n type: ModalFactory.types.DEFAULT,\n }).then(modal => {\n modal.show();\n modal.showFooter();\n modal.registerCloseOnCancel();\n return modal;\n }).catch(Notification.exception);\n};\n\n/**\n * Add buttons to render on mapping modal.\n *\n * @param {int} cmId The id of the current database activity.\n * @param {string} presetName The preset name to delete.\n * @return {array} Same data with buttons.\n */\nconst getMappingButtons = (cmId, presetName) => {\n const data = {};\n\n data.mapfieldsbutton = Url.relativeUrl(\n 'mod/data/field.php',\n {\n id: cmId,\n fullname: presetName,\n mode: 'usepreset',\n action: 'select',\n },\n false\n );\n\n data.applybutton = Url.relativeUrl(\n 'mod/data/field.php',\n {\n id: cmId,\n fullname: presetName,\n mode: 'usepreset',\n action: 'notmapping'\n },\n false\n );\n\n return data;\n};\n\n/**\n * Check whether we should show the mapping dialogue or not.\n *\n * @param {int} cmId The id of the current database activity.\n * @param {string} presetName The preset name to delete.\n * @return {promise} Resolved with the result and warnings of deleting a preset.\n */\nconst getMappingInformation = (cmId, presetName) => {\n const request = {\n methodname: 'mod_data_get_mapping_information',\n args: {\n cmid: cmId,\n importedpreset: presetName,\n }\n };\n return Ajax.call([request])[0];\n};\n"],"names":["selectors","registerEventListeners","document","addEventListener","event","usepreset","target","closest","preventDefault","showMappingDialogue","presetName","dataset","presetname","cmId","cmid","getMappingInformation","then","result","data","needsmapping","buildModal","title","body","Templates","render","footer","getMappingButtons","large","window","location","href","Url","relativeUrl","id","mode","fullname","catch","Notification","exception","params","ModalFactory","create","type","types","DEFAULT","modal","show","showFooter","registerCloseOnCancel","mapfieldsbutton","action","applybutton","request","methodname","args","importedpreset","Ajax","call"],"mappings":";;;;;;;8UAgCgB,WAAY,CAAC,wCAEvBA,6BACkB,2CAMJ,KAChBC,gCAMEA,uBAAyB,KAC3BC,SAASC,iBAAiB,SAAUC,cAC1BC,UAAYD,MAAME,OAAOC,QAAQP,8BACnCK,YACAD,MAAMI,iBACNC,oBAAoBJ,gBAU1BI,oBAAuBJ,kBACnBK,WAAaL,UAAUM,QAAQC,WAC/BC,KAAOR,UAAUM,QAAQG,KAE/BC,sBAAsBF,KAAMH,YAAYM,MAAMC,SACtCA,OAAOC,MAAQD,OAAOC,KAAKC,aAC3BC,WAAW,CACPC,OAAO,mBAAU,gCAAiC,WAAYJ,OAAOC,KAAKN,YAC1EU,KAAMC,mBAAUC,OAAO,+BAAgCP,OAAOC,MAC9DO,OAAQF,mBAAUC,OAAO,iCAAkCE,kBAAkBb,KAAMH,aACnFiB,OAAO,IAGXC,OAAOC,SAASC,KAAOC,aAAIC,YACvB,qBACA,CACIC,GAAIpB,KACJqB,KAAM,YACNC,SAAUzB,aAEd,IAGD,KACR0B,MAAMC,sBAAaC,YAapBlB,WAAcmB,QACTC,uBAAaC,OAAO,IACpBF,OACHG,KAAMF,uBAAaG,MAAMC,UAC1B5B,MAAK6B,QACJA,MAAMC,OACND,MAAME,aACNF,MAAMG,wBACCH,SACRT,MAAMC,sBAAaC,WAUpBZ,kBAAoB,CAACb,KAAMH,oBACvBQ,KAAO,UAEbA,KAAK+B,gBAAkBlB,aAAIC,YACvB,qBACA,CACIC,GAAIpB,KACJsB,SAAUzB,WACVwB,KAAM,YACNgB,OAAQ,WAEZ,GAGJhC,KAAKiC,YAAcpB,aAAIC,YACnB,qBACA,CACIC,GAAIpB,KACJsB,SAAUzB,WACVwB,KAAM,YACNgB,OAAQ,eAEZ,GAGGhC,MAULH,sBAAwB,CAACF,KAAMH,oBAC3B0C,QAAU,CACZC,WAAY,mCACZC,KAAM,CACFxC,KAAMD,KACN0C,eAAgB7C,oBAGjB8C,cAAKC,KAAK,CAACL,UAAU"} \ No newline at end of file diff --git a/mod/data/amd/build/selectpreset.min.js b/mod/data/amd/build/selectpreset.min.js index 9e64d02194d..46e992f9533 100644 --- a/mod/data/amd/build/selectpreset.min.js +++ b/mod/data/amd/build/selectpreset.min.js @@ -6,6 +6,6 @@ define("mod_data/selectpreset",["exports"],(function(_exports){Object.defineProp * @copyright 2021 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const selectors_presetRadioButton='input[name="fullname"]',selectors_selectPresetButton='input[name="selectpreset"]',selectors_selectedPresetRadioButton='input[name="fullname"]:checked';_exports.init=()=>{const radioButton=document.querySelectorAll(selectors_presetRadioButton);disableUsePresetButton(),radioButton.forEach((elem=>{elem.addEventListener("change",(function(event){event.preventDefault(),disableUsePresetButton()}))}))};const disableUsePresetButton=()=>{let selectPresetButton=document.querySelector(selectors_selectPresetButton);document.querySelectorAll(selectors_selectedPresetRadioButton).length>0?(selectPresetButton.removeAttribute("disabled"),selectPresetButton.classList.remove("btn-secondary"),selectPresetButton.classList.add("btn-primary")):(selectPresetButton.setAttribute("disabled",!0),selectPresetButton.classList.remove("btn-primary"),selectPresetButton.classList.add("btn-secondary"))}})); +const selectors_presetRadioButton='input[name="fullname"]',selectors_selectPresetButton='input[name="selectpreset"]',selectors_selectedPresetRadioButton='input[name="fullname"]:checked';_exports.init=()=>{const radioButton=document.querySelectorAll(selectors_presetRadioButton);disableUsePresetButton(),radioButton.forEach((elem=>{elem.addEventListener("change",(function(event){event.preventDefault(),disableUsePresetButton()}))}))};const disableUsePresetButton=()=>{let selectPresetButton=document.querySelector(selectors_selectPresetButton);const selectedRadioButton=document.querySelector(selectors_selectedPresetRadioButton);selectedRadioButton?(selectPresetButton.removeAttribute("disabled"),selectPresetButton.classList.remove("btn-secondary"),selectPresetButton.classList.add("btn-primary"),selectPresetButton.setAttribute("data-presetname",selectedRadioButton.getAttribute("value")),selectPresetButton.setAttribute("data-cmid",selectedRadioButton.getAttribute("data-cmid"))):(selectPresetButton.setAttribute("disabled",!0),selectPresetButton.classList.remove("btn-primary"),selectPresetButton.classList.add("btn-secondary"),selectPresetButton.removeAttribute("data-presetname"),selectPresetButton.removeAttribute("data-cmid"))}})); //# sourceMappingURL=selectpreset.min.js.map \ No newline at end of file diff --git a/mod/data/amd/build/selectpreset.min.js.map b/mod/data/amd/build/selectpreset.min.js.map index e7ee516bd6d..97239a2842b 100644 --- a/mod/data/amd/build/selectpreset.min.js.map +++ b/mod/data/amd/build/selectpreset.min.js.map @@ -1 +1 @@ -{"version":3,"file":"selectpreset.min.js","sources":["../src/selectpreset.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 * Javascript module to control the form responsible for selecting a preset.\n *\n * @module mod_data/selectpreset\n * @copyright 2021 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst selectors = {\n presetRadioButton: 'input[name=\"fullname\"]',\n selectPresetButton: 'input[name=\"selectpreset\"]',\n selectedPresetRadioButton: 'input[name=\"fullname\"]:checked',\n};\n\n/**\n * Initialize module.\n */\nexport const init = () => {\n const radioButton = document.querySelectorAll(selectors.presetRadioButton);\n\n // Initialize the \"Use a preset\" button properly.\n disableUsePresetButton();\n\n radioButton.forEach((elem) => {\n elem.addEventListener('change', function(event) {\n event.preventDefault();\n // Enable the \"Use a preset\" button when any of the radio buttons in the presets list is checked.\n disableUsePresetButton();\n });\n });\n\n};\n\n/**\n * Decide whether to disable or not the \"Use a preset\" button.\n * When there is no preset selected, the button should be displayed disabled; otherwise, it will appear enabled as a primary button.\n *\n * @method\n * @private\n */\nconst disableUsePresetButton = () => {\n let selectPresetButton = document.querySelector(selectors.selectPresetButton);\n const selectedRadioButton = document.querySelectorAll(selectors.selectedPresetRadioButton);\n\n if (selectedRadioButton.length > 0) {\n // There is one preset selected, so the button should be enabled.\n selectPresetButton.removeAttribute('disabled');\n selectPresetButton.classList.remove('btn-secondary');\n selectPresetButton.classList.add('btn-primary');\n } else {\n // There is no any preset selected, so the button should be disabled.\n selectPresetButton.setAttribute('disabled', true);\n selectPresetButton.classList.remove('btn-primary');\n selectPresetButton.classList.add('btn-secondary');\n }\n};\n"],"names":["selectors","radioButton","document","querySelectorAll","disableUsePresetButton","forEach","elem","addEventListener","event","preventDefault","selectPresetButton","querySelector","length","removeAttribute","classList","remove","add","setAttribute"],"mappings":";;;;;;;;MAuBMA,4BACiB,yBADjBA,6BAEkB,6BAFlBA,oCAGyB,+CAMX,WACVC,YAAcC,SAASC,iBAAiBH,6BAG9CI,yBAEAH,YAAYI,SAASC,OACjBA,KAAKC,iBAAiB,UAAU,SAASC,OACrCA,MAAMC,iBAENL,sCAaNA,uBAAyB,SACvBM,mBAAqBR,SAASS,cAAcX,8BACpBE,SAASC,iBAAiBH,qCAE9BY,OAAS,GAE7BF,mBAAmBG,gBAAgB,YACnCH,mBAAmBI,UAAUC,OAAO,iBACpCL,mBAAmBI,UAAUE,IAAI,iBAGjCN,mBAAmBO,aAAa,YAAY,GAC5CP,mBAAmBI,UAAUC,OAAO,eACpCL,mBAAmBI,UAAUE,IAAI"} \ No newline at end of file +{"version":3,"file":"selectpreset.min.js","sources":["../src/selectpreset.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 * Javascript module to control the form responsible for selecting a preset.\n *\n * @module mod_data/selectpreset\n * @copyright 2021 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst selectors = {\n presetRadioButton: 'input[name=\"fullname\"]',\n selectPresetButton: 'input[name=\"selectpreset\"]',\n selectedPresetRadioButton: 'input[name=\"fullname\"]:checked',\n};\n\n/**\n * Initialize module.\n */\nexport const init = () => {\n const radioButton = document.querySelectorAll(selectors.presetRadioButton);\n\n // Initialize the \"Use a preset\" button properly.\n disableUsePresetButton();\n\n radioButton.forEach((elem) => {\n elem.addEventListener('change', function(event) {\n event.preventDefault();\n // Enable the \"Use a preset\" button when any of the radio buttons in the presets list is checked.\n disableUsePresetButton();\n });\n });\n\n};\n\n/**\n * Decide whether to disable or not the \"Use a preset\" button.\n * When there is no preset selected, the button should be displayed disabled; otherwise, it will appear enabled as a primary button.\n *\n * @method\n * @private\n */\nconst disableUsePresetButton = () => {\n let selectPresetButton = document.querySelector(selectors.selectPresetButton);\n const selectedRadioButton = document.querySelector(selectors.selectedPresetRadioButton);\n\n if (selectedRadioButton) {\n // There is one preset selected, so the button should be enabled.\n selectPresetButton.removeAttribute('disabled');\n selectPresetButton.classList.remove('btn-secondary');\n selectPresetButton.classList.add('btn-primary');\n selectPresetButton.setAttribute('data-presetname', selectedRadioButton.getAttribute('value'));\n selectPresetButton.setAttribute('data-cmid', selectedRadioButton.getAttribute('data-cmid'));\n } else {\n // There is no any preset selected, so the button should be disabled.\n selectPresetButton.setAttribute('disabled', true);\n selectPresetButton.classList.remove('btn-primary');\n selectPresetButton.classList.add('btn-secondary');\n selectPresetButton.removeAttribute('data-presetname');\n selectPresetButton.removeAttribute('data-cmid');\n }\n};\n"],"names":["selectors","radioButton","document","querySelectorAll","disableUsePresetButton","forEach","elem","addEventListener","event","preventDefault","selectPresetButton","querySelector","selectedRadioButton","removeAttribute","classList","remove","add","setAttribute","getAttribute"],"mappings":";;;;;;;;MAuBMA,4BACiB,yBADjBA,6BAEkB,6BAFlBA,oCAGyB,+CAMX,WACVC,YAAcC,SAASC,iBAAiBH,6BAG9CI,yBAEAH,YAAYI,SAASC,OACjBA,KAAKC,iBAAiB,UAAU,SAASC,OACrCA,MAAMC,iBAENL,sCAaNA,uBAAyB,SACvBM,mBAAqBR,SAASS,cAAcX,oCAC1CY,oBAAsBV,SAASS,cAAcX,qCAE/CY,qBAEAF,mBAAmBG,gBAAgB,YACnCH,mBAAmBI,UAAUC,OAAO,iBACpCL,mBAAmBI,UAAUE,IAAI,eACjCN,mBAAmBO,aAAa,kBAAmBL,oBAAoBM,aAAa,UACpFR,mBAAmBO,aAAa,YAAaL,oBAAoBM,aAAa,gBAG9ER,mBAAmBO,aAAa,YAAY,GAC5CP,mBAAmBI,UAAUC,OAAO,eACpCL,mBAAmBI,UAAUE,IAAI,iBACjCN,mBAAmBG,gBAAgB,mBACnCH,mBAAmBG,gBAAgB"} \ No newline at end of file diff --git a/mod/data/amd/src/importmappingdialogue.js b/mod/data/amd/src/importmappingdialogue.js new file mode 100644 index 00000000000..a1112a6b48e --- /dev/null +++ b/mod/data/amd/src/importmappingdialogue.js @@ -0,0 +1,164 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Javascript module for deleting a database as a preset. + * + * @module mod_data/importmappingdialogue + * @copyright 2022 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Notification from 'core/notification'; +import Ajax from 'core/ajax'; +import Url from 'core/url'; +import Templates from 'core/templates'; +import ModalFactory from 'core/modal_factory'; +import {prefetchStrings} from 'core/prefetch'; +import {get_string as getString} from 'core/str'; + +// Load global strings. +prefetchStrings('mod_data', ['mapping:dialogtitle:usepreset']); + +const selectors = { + selectPresetButton: 'input[name="selectpreset"]', +}; + +/** + * Initialize module + */ +export const init = () => { + registerEventListeners(); +}; + +/** + * Register events. + */ +const registerEventListeners = () => { + document.addEventListener('click', (event) => { + const usepreset = event.target.closest(selectors.selectPresetButton); + if (usepreset) { + event.preventDefault(); + showMappingDialogue(usepreset); + } + }); +}; + +/** + * Show the confirmation modal for uploading a preset. + * + * @param {HTMLElement} usepreset the preset to import. + */ +const showMappingDialogue = (usepreset) => { + const presetName = usepreset.dataset.presetname; + const cmId = usepreset.dataset.cmid; + + getMappingInformation(cmId, presetName).then((result) => { + if (result.data && result.data.needsmapping) { + buildModal({ + title: getString('mapping:dialogtitle:usepreset', 'mod_data', result.data.presetname), + body: Templates.render('mod_data/fields_mapping_body', result.data), + footer: Templates.render('mod_data/fields_mapping_footer', getMappingButtons(cmId, presetName)), + large: true, + }); + } else { + window.location.href = Url.relativeUrl( + 'mod/data/field.php', + { + id: cmId, + mode: 'usepreset', + fullname: presetName, + }, + false + ); + } + return true; + }).catch(Notification.exception); +}; + +/** + * Given an object we want to build a modal ready to show + * + * @method buildModal + * @param {Object} params the modal params + * @param {Promise} params.title + * @param {Promise} params.body + * @param {Promise} params.footer + * @return {Object} The modal ready to display immediately and render body in later. + */ +const buildModal = (params) => { + return ModalFactory.create({ + ...params, + type: ModalFactory.types.DEFAULT, + }).then(modal => { + modal.show(); + modal.showFooter(); + modal.registerCloseOnCancel(); + return modal; + }).catch(Notification.exception); +}; + +/** + * Add buttons to render on mapping modal. + * + * @param {int} cmId The id of the current database activity. + * @param {string} presetName The preset name to delete. + * @return {array} Same data with buttons. + */ +const getMappingButtons = (cmId, presetName) => { + const data = {}; + + data.mapfieldsbutton = Url.relativeUrl( + 'mod/data/field.php', + { + id: cmId, + fullname: presetName, + mode: 'usepreset', + action: 'select', + }, + false + ); + + data.applybutton = Url.relativeUrl( + 'mod/data/field.php', + { + id: cmId, + fullname: presetName, + mode: 'usepreset', + action: 'notmapping' + }, + false + ); + + return data; +}; + +/** + * Check whether we should show the mapping dialogue or not. + * + * @param {int} cmId The id of the current database activity. + * @param {string} presetName The preset name to delete. + * @return {promise} Resolved with the result and warnings of deleting a preset. + */ +const getMappingInformation = (cmId, presetName) => { + const request = { + methodname: 'mod_data_get_mapping_information', + args: { + cmid: cmId, + importedpreset: presetName, + } + }; + return Ajax.call([request])[0]; +}; diff --git a/mod/data/amd/src/selectpreset.js b/mod/data/amd/src/selectpreset.js index 6fd881c2957..9dbe7d8a769 100644 --- a/mod/data/amd/src/selectpreset.js +++ b/mod/data/amd/src/selectpreset.js @@ -55,17 +55,21 @@ export const init = () => { */ const disableUsePresetButton = () => { let selectPresetButton = document.querySelector(selectors.selectPresetButton); - const selectedRadioButton = document.querySelectorAll(selectors.selectedPresetRadioButton); + const selectedRadioButton = document.querySelector(selectors.selectedPresetRadioButton); - if (selectedRadioButton.length > 0) { + if (selectedRadioButton) { // There is one preset selected, so the button should be enabled. selectPresetButton.removeAttribute('disabled'); selectPresetButton.classList.remove('btn-secondary'); selectPresetButton.classList.add('btn-primary'); + selectPresetButton.setAttribute('data-presetname', selectedRadioButton.getAttribute('value')); + selectPresetButton.setAttribute('data-cmid', selectedRadioButton.getAttribute('data-cmid')); } else { // There is no any preset selected, so the button should be disabled. selectPresetButton.setAttribute('disabled', true); selectPresetButton.classList.remove('btn-primary'); selectPresetButton.classList.add('btn-secondary'); + selectPresetButton.removeAttribute('data-presetname'); + selectPresetButton.removeAttribute('data-cmid'); } }; diff --git a/mod/data/classes/external/get_mapping_information.php b/mod/data/classes/external/get_mapping_information.php new file mode 100644 index 00000000000..0051456d760 --- /dev/null +++ b/mod/data/classes/external/get_mapping_information.php @@ -0,0 +1,97 @@ +. + +namespace mod_data\external; + +use core\notification; +use mod_data\local\importer\preset_importer; +use mod_data\manager; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/externallib.php'); + +/** + * This is the external method for deleting a saved preset. + * + * @package mod_data + * @since Moodle 4.1 + * @copyright 2022 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class get_mapping_information extends \external_api { + /** + * Parameters. + * + * @return \external_function_parameters + */ + public static function execute_parameters(): \external_function_parameters { + return new \external_function_parameters([ + 'cmid' => new \external_value(PARAM_INT, 'Id of the data activity', VALUE_REQUIRED), + 'importedpreset' => new \external_value(PARAM_TEXT, 'Preset to be imported'), + ]); + } + + /** + * Get importing information for the given database course module. + * + * @param int $cmid Id of the course module where to import the preset. + * @param string $importedpreset Plugin or saved preset to be imported. + * @return array Information needed to decide whether to show the dialogue or not. + */ + public static function execute(int $cmid, string $importedpreset): array { + + $params = self::validate_parameters( + self::execute_parameters(), + ['cmid' => $cmid, 'importedpreset' => $importedpreset] + ); + + try { + // Let's get the manager. + list($course, $cm) = get_course_and_cm_from_cmid($params['cmid'], manager::MODULE); + $manager = manager::create_from_coursemodule($cm); + + $importer = preset_importer::create_from_plugin_or_directory($manager, $params['importedpreset']); + $result['data'] = $importer->get_mapping_information(); + } catch (\moodle_exception $e) { + $result['warnings'][] = [ + 'item' => $importedpreset, + 'warningcode' => 'exception', + 'message' => $e->getMessage() + ]; + notification::error($e->getMessage()); + } + return $result; + } + + /** + * Return. + * + * @return \external_single_structure + */ + public static function execute_returns(): \external_single_structure { + return new \external_single_structure([ + 'data' => new \external_single_structure([ + 'needsmapping' => new \external_value(PARAM_BOOL, 'Whether the importing needs mapping or not'), + 'presetname' => new \external_value(PARAM_TEXT, 'Name of the applied preset'), + 'fieldstocreate' => new \external_value(PARAM_TEXT, 'List of field names to create'), + 'fieldstoremove' => new \external_value(PARAM_TEXT, 'List of field names to remove'), + ], 'Information to import if everything went fine', VALUE_OPTIONAL), + 'warnings' => new \external_warnings(), + ]); + } +} diff --git a/mod/data/classes/local/importer/preset_importer.php b/mod/data/classes/local/importer/preset_importer.php index 12a9b7c1729..0394330d9fb 100644 --- a/mod/data/classes/local/importer/preset_importer.php +++ b/mod/data/classes/local/importer/preset_importer.php @@ -16,6 +16,7 @@ namespace mod_data\local\importer; +use core\notification; use mod_data\manager; use mod_data\preset; use stdClass; @@ -36,6 +37,18 @@ abstract class preset_importer { /** @var string directory where to find the preset. */ protected $directory; + /** @var array fields to remove. */ + public $fieldstoremove; + + /** @var array fields to update. */ + public $fieldstoupdate; + + /** @var array fields to create. */ + public $fieldstocreate; + + /** @var array settings to be imported. */ + public $settings; + /** * Constructor * @@ -45,6 +58,9 @@ abstract class preset_importer { public function __construct(manager $manager, string $directory) { $this->manager = $manager; $this->directory = $directory; + + // Read the preset and saved result. + $this->settings = $this->get_preset_settings(); } /** @@ -176,22 +192,33 @@ abstract class preset_importer { } // Now work out fields to user friendly array. - $fieldsarray = $parsedxml['preset']['#']['field']; - foreach ($fieldsarray as $field) { - if (!is_array($field)) { - continue; - } - $fieldstoimport = new StdClass(); - foreach ($field['#'] as $param => $value) { - if (!is_array($value)) { + if ( + array_key_exists('preset', $parsedxml) && + array_key_exists('#', $parsedxml['preset']) && + array_key_exists('field', $parsedxml['preset']['#'])) { + $fieldsarray = $parsedxml['preset']['#']['field']; + foreach ($fieldsarray as $field) { + if (!is_array($field)) { continue; } - $fieldstoimport->$param = $value[0]['#']; + $fieldstoimport = new StdClass(); + foreach ($field['#'] as $param => $value) { + if (!is_array($value)) { + continue; + } + $fieldstoimport->$param = $value[0]['#']; + } + $fieldstoimport->dataid = $module->id; + $fieldstoimport->type = clean_param($fieldstoimport->type, PARAM_ALPHA); + $result->importfields[] = $fieldstoimport; } - $fieldstoimport->dataid = $module->id; - $fieldstoimport->type = clean_param($fieldstoimport->type, PARAM_ALPHA); - $result->importfields[] = $fieldstoimport; } + + // Calculate default mapping. + if (is_null($this->fieldstoremove) && is_null($this->fieldstocreate) && is_null($this->fieldstoupdate)) { + $this->set_affected_fields($result->importfields, $result->currentfields); + } + // Now add the HTML templates to the settings array so we can update d. foreach (manager::TEMPLATES_LIST as $templatename => $templatefile) { $result->settings->$templatename = $this->get_file_contents( @@ -215,63 +242,44 @@ abstract class preset_importer { public function import(bool $overwritesettings): bool { global $DB, $OUTPUT; - $params = $this->get_preset_settings(); - $settings = $params->settings; - $newfields = $params->importfields; - $currentfields = $params->currentfields; - $preservedfields = []; + $settings = $this->settings->settings; + $currentfields = $this->settings->currentfields; + $missingfieldtypes = []; $module = $this->manager->get_instance(); - // Maps fields and makes new ones. - if (!empty($newfields)) { - // We require an injective mapping, and need to know what to protect. - foreach ($newfields as $newid => $newfield) { - $cid = optional_param("field_$newid", -1, PARAM_INT); - if ($cid == -1) { - continue; - } - if (array_key_exists($cid, $preservedfields)) { - throw new \moodle_exception('notinjectivemap', 'data'); - } else { - $preservedfields[$cid] = true; - } - } - - foreach ($newfields as $newid => $newfield) { - $cid = optional_param("field_$newid", -1, PARAM_INT); - - /* A mapping. Just need to change field params. Data kept. */ - if ($cid != -1 && isset($currentfields[$cid])) { - $fieldobject = data_get_field_from_id($currentfields[$cid]->id, $module); - foreach ($newfield as $param => $value) { - if ($param != "id") { - $fieldobject->field->$param = $value; - } + foreach ($this->fieldstoupdate as $currentid => $updatable) { + if ($currentid != -1 && isset($currentfields[$currentid])) { + $fieldobject = data_get_field_from_id($currentfields[$currentid]->id, $module); + foreach ($updatable as $param => $value) { + if ($param != "id") { + $fieldobject->field->$param = $value; } - unset($fieldobject->field->similarfield); - $fieldobject->update_field(); - unset($fieldobject); - } else { - /* Make a new field */ - $filepath = "field/$newfield->type/field.class.php"; - if (!file_exists($filepath)) { - $missingfieldtypes[] = $newfield->name; - continue; - } - include_once($filepath); - - if (!isset($newfield->description)) { - $newfield->description = ''; - } - $classname = 'data_field_'.$newfield->type; - $fieldclass = new $classname($newfield, $module); - $fieldclass->insert_field(); - unset($fieldclass); } + unset($fieldobject->field->similarfield); + $fieldobject->update_field(); + unset($fieldobject); } - if (!empty($missingfieldtypes)) { - echo $OUTPUT->notification(get_string('missingfieldtypeimport', 'data') . html_writer::alist($missingfieldtypes)); + } + + foreach ($this->fieldstocreate as $newfield) { + /* Make a new field */ + $filepath = "field/$newfield->type/field.class.php"; + if (!file_exists($filepath)) { + $missingfieldtypes[] = $newfield->name; + continue; } + include_once($filepath); + + if (!isset($newfield->description)) { + $newfield->description = ''; + } + $classname = 'data_field_' . $newfield->type; + $fieldclass = new $classname($newfield, $module); + $fieldclass->insert_field(); + unset($fieldclass); + } + if (!empty($missingfieldtypes)) { + echo $OUTPUT->notification(get_string('missingfieldtypeimport', 'data') . html_writer::alist($missingfieldtypes)); } // Get rid of all old unused data. @@ -328,6 +336,59 @@ abstract class preset_importer { return $this->cleanup(); } + /** + * Returns information about the fields needs to be removed, updated or created. + * + * @param array $newfields Array of new fields to be applied. + * @param array $currentfields Array of current fields on database activity. + * @return void + */ + public function set_affected_fields(array $newfields = [], array $currentfields = []): void { + $fieldstoremove = []; + $fieldstocreate = []; + $preservedfields = []; + + // Maps fields and makes new ones. + if (!empty($newfields)) { + // We require an injective mapping, and need to know what to protect. + foreach ($newfields as $newid => $newfield) { + $preservedfieldid = optional_param("field_$newid", -1, PARAM_INT); + + if (array_key_exists($preservedfieldid, $preservedfields)) { + throw new \moodle_exception('notinjectivemap', 'data'); + } + + if ($preservedfieldid == -1) { + // Let's check if there is any field with same type and name that we could map to. + foreach ($currentfields as $currentid => $currentfield) { + if (($currentfield->type == $newfield->type) && + ($currentfield->name == $newfield->name) && !array_key_exists($currentid, $preservedfields)) { + // We found a possible default map. + $preservedfieldid = $currentid; + $preservedfields[$currentid] = $newfield; + } + } + } + if ($preservedfieldid == -1) { + // We need to create a new field. + $fieldstocreate[] = $newfield; + } else { + $preservedfields[$preservedfieldid] = $newfield; + } + } + } + + foreach ($currentfields as $currentid => $currentfield) { + if (!array_key_exists($currentid, $preservedfields)) { + $fieldstoremove[] = $currentfield; + } + } + + $this->fieldstocreate = $fieldstocreate; + $this->fieldstoremove = $fieldstoremove; + $this->fieldstoupdate = $preservedfields; + } + /** * Any clean up routines should go here * @@ -343,7 +404,10 @@ abstract class preset_importer { * @return bool True if the current database needs to map the fields imported. */ public function needs_mapping(): bool { - return $this->manager->has_fields(); + if (!$this->manager->has_fields()) { + return false; + } + return (!empty($this->fieldstocreate) || !empty($this->fieldstoremove)); } /** @@ -365,16 +429,14 @@ abstract class preset_importer { * @return void */ public function finish_import_process(bool $overwritesettings, stdClass $instance): void { - global $DB; - $this->import($overwritesettings); - $strimportsuccess = get_string('importsuccess', 'data'); - $straddentries = get_string('addentries', 'data'); - $strtodatabase = get_string('todatabase', 'data'); - if (!$DB->get_records('data_records', ['dataid' => $instance->id])) { - \core\notification::success("$strimportsuccess $straddentries $strtodatabase"); + $result = $this->import($overwritesettings); + if ($result) { + notification::success(get_string('importsuccess', 'mod_data')); } else { - \core\notification::success($strimportsuccess); + notification::error(get_string('cannotapplypreset', 'mod_data')); } + $backurl = new \moodle_url('/mod/data/field.php', ['d' => $instance->id]); + redirect($backurl); } /** @@ -385,17 +447,64 @@ abstract class preset_importer { * @throws \moodle_exception when the file provided as parameter (POST or GET) does not exist */ public static function create_from_parameters(manager $manager): preset_importer { - global $CFG; + $fullname = optional_param('fullname', '', PARAM_PATH); // Directory the preset is in. if (!$fullname) { - $presetdir = $CFG->tempdir . '/forms/' . required_param('directory', PARAM_FILE); - if (!file_exists($presetdir) || !is_dir($presetdir)) { - throw new \moodle_exception('cannotimport'); - } - $importer = new preset_upload_importer($manager, $presetdir); - } else { - $importer = new preset_existing_importer($manager, $fullname); + $fullname = required_param('directory', PARAM_FILE); } - return $importer; + + return self::create_from_plugin_or_directory($manager, $fullname); + } + + /** + * Get the right importer instance from the provided parameters (POST or GET) + * + * @param manager $manager the current database manager + * @param string $pluginordirectory The plugin name or directory to create the importer from. + * @return preset_importer the relevant preset_importer instance + */ + public static function create_from_plugin_or_directory(manager $manager, string $pluginordirectory): preset_importer { + global $CFG; + + if (!$pluginordirectory) { + throw new \moodle_exception('emptypresetname', 'mod_data'); + } + try { + $presetdir = $CFG->tempdir . '/forms/' . $pluginordirectory; + if (file_exists($presetdir) && is_dir($presetdir)) { + return new preset_upload_importer($manager, $presetdir); + } else { + return new preset_existing_importer($manager, $pluginordirectory); + } + } catch (\moodle_exception $e) { + throw new \moodle_exception('errorpresetnotfound', 'mod_data', '', $pluginordirectory); + } + } + + /** + * Get the information needed to decide the modal + * + * @return array An array with all the information to decide the mapping + */ + public function get_mapping_information(): array { + return [ + 'needsmapping' => $this->needs_mapping(), + 'presetname' => preset::get_name_from_plugin($this->get_directory()), + 'fieldstocreate' => $this->get_field_names($this->fieldstocreate), + 'fieldstoremove' => $this->get_field_names($this->fieldstoremove), + ]; + } + + /** + * Returns a list of the fields + * + * @param array $fields Array of fields to get name from. + * @return string A string listing the names of the fields. + */ + public function get_field_names(array $fields): string { + $fieldnames = array_map(function($field) { + return $field->name; + }, $fields); + return implode(', ', $fieldnames); } } diff --git a/mod/data/classes/output/action_bar.php b/mod/data/classes/output/action_bar.php index 7db843fb6a1..483a0cde78a 100644 --- a/mod/data/classes/output/action_bar.php +++ b/mod/data/classes/output/action_bar.php @@ -82,6 +82,21 @@ class action_bar { return $renderer->render_fields_action_bar($fieldsactionbar); } + /** + * Generate the output for the action bar in the field mappings page. + * + * @return string The HTML code for the action bar. + */ + public function get_fields_mapping_action_bar(): string { + global $PAGE; + + $renderer = $PAGE->get_renderer('mod_data'); + $fieldsactionbar = new fields_mappings_action_bar($this->id); + + $data = $fieldsactionbar->export_for_template($renderer); + return $renderer->render_from_template('mod_data/fields_action_bar', $data); + } + /** * Generate the output for the create a new field action menu. * diff --git a/mod/data/classes/output/fields_action_bar.php b/mod/data/classes/output/fields_action_bar.php index 31634d52484..e0dec7f201b 100644 --- a/mod/data/classes/output/fields_action_bar.php +++ b/mod/data/classes/output/fields_action_bar.php @@ -66,6 +66,7 @@ class fields_action_bar implements templatable, renderable { $data = [ 'd' => $this->id, + 'tertiarytitle' => get_string('managefields', 'mod_data'), ]; if ($this->fieldselect) { diff --git a/mod/data/classes/output/fields_mappings_action_bar.php b/mod/data/classes/output/fields_mappings_action_bar.php new file mode 100644 index 00000000000..f7d33619b6b --- /dev/null +++ b/mod/data/classes/output/fields_mappings_action_bar.php @@ -0,0 +1,57 @@ +. + +namespace mod_data\output; + +use templatable; +use renderable; + +/** + * Renderable class for the action bar elements in the fields mapping page in the database activity. + * + * @package mod_data + * @copyright 2022 Amaia Anabitarte + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class fields_mappings_action_bar implements templatable, renderable { + + /** @var int $id The database module id. */ + private $id; + + /** + * The class constructor. + * + * @param int $id The database module id + */ + public function __construct(int $id) { + $this->id = $id; + } + + /** + * Export the data for the mustache template. + * + * @param \renderer_base $output The renderer to be used to render the action bar elements. + * @return array + */ + public function export_for_template(\renderer_base $output): array { + return [ + 'tertiarytitle' => get_string('fieldmappings', 'mod_data'), + 'hasback' => true, + 'backtitle' => get_string('back'), + 'backurl' => new \moodle_url('/mod/data/preset.php', ['d' => $this->id]), + ]; + } +} diff --git a/mod/data/classes/output/preset_preview.php b/mod/data/classes/output/preset_preview.php index a0f85a285c1..f35c10fd9e5 100644 --- a/mod/data/classes/output/preset_preview.php +++ b/mod/data/classes/output/preset_preview.php @@ -83,7 +83,7 @@ class preset_preview implements templatable, renderable { * @return array */ public function export_for_template(\renderer_base $output): array { - $instance = $this->manager->get_instance(); + $coursemodule = $this->manager->get_coursemodule(); $preset = $this->preset; // Get fields for preview. @@ -107,7 +107,7 @@ class preset_preview implements templatable, renderable { } return [ - 'd' => $instance->id, + 'cmid' => $coursemodule->id, 'description' => $preset->description ?? '', 'preview' => $content, 'formactionurl' => $useurl->out(), diff --git a/mod/data/classes/output/presets.php b/mod/data/classes/output/presets.php index d001fe82687..db55ad1b1ec 100644 --- a/mod/data/classes/output/presets.php +++ b/mod/data/classes/output/presets.php @@ -102,6 +102,7 @@ class presets implements templatable, renderable { $fullname = $preset->get_fullname(); $id = $this->manager->get_instance()->id; + $cmid = $this->manager->get_coursemodule()->id; $previewurl = new moodle_url( '/mod/data/preset.php', ['d' => $id, 'fullname' => $fullname, 'action' => 'preview'] @@ -109,6 +110,7 @@ class presets implements templatable, renderable { $presets[] = [ 'id' => $id, + 'cmid' => $cmid, 'name' => $preset->name, 'url' => $previewurl->out(), 'shortname' => $preset->shortname, diff --git a/mod/data/classes/preset.php b/mod/data/classes/preset.php index fdad67ef147..da69c5365c5 100644 --- a/mod/data/classes/preset.php +++ b/mod/data/classes/preset.php @@ -576,7 +576,8 @@ class preset { * @return string The plugin preset name to display. */ public static function get_name_from_plugin(string $pluginname): string { - if ($pos = strpos($pluginname, '/')) { + $pos = strpos($pluginname, '/'); + if ($pos !== false) { $pluginname = substr($pluginname, $pos + 1); } if (!strpos(trim($pluginname), ' ') && get_string_manager()->string_exists('modulename', 'datapreset_'.$pluginname)) { diff --git a/mod/data/db/services.php b/mod/data/db/services.php index e2784e62a2f..ac6ef13ef2a 100644 --- a/mod/data/db/services.php +++ b/mod/data/db/services.php @@ -122,4 +122,11 @@ $functions = array( 'ajax' => true, 'capabilities' => 'mod/data:manageuserpresets', ), + 'mod_data_get_mapping_information' => array( + 'classname' => 'mod_data\external\get_mapping_information', + 'description' => 'Get importing information', + 'type' => 'read', + 'ajax' => true, + 'capabilities' => 'mod/data:managetemplates', + ), ); diff --git a/mod/data/field.php b/mod/data/field.php index 008baf4de6b..9917410aa25 100644 --- a/mod/data/field.php +++ b/mod/data/field.php @@ -108,13 +108,9 @@ $data->instance = $cm->instance; $renderer = $manager->get_renderer(); if ($action == 'finishimport' && confirm_sesskey()) { - data_print_header($course, $cm, $data, false); $overwritesettings = optional_param('overwritesettings', false, PARAM_BOOL); $importer = preset_importer::create_from_parameters($manager); $importer->finish_import_process($overwritesettings, $data); - echo $OUTPUT->continue_button(new moodle_url('/mod/data/field.php', ['d' => $data->id])); - echo $OUTPUT->footer(); - exit; } switch ($mode) { @@ -255,19 +251,18 @@ switch ($mode) { case 'usepreset': $importer = preset_importer::create_from_parameters($manager); - if (!$importer->needs_mapping()) { + if (!$importer->needs_mapping() || $action == 'notmapping') { $backurl = new moodle_url('/mod/data/field.php', ['id' => $cm->id]); if ($importer->import(false)) { notification::success(get_string('importsuccess', 'mod_data')); } else { - notification::error(get_string('presetapplied', 'mod_data')); + notification::error(get_string('cannotapplypreset', 'mod_data')); } redirect($backurl); } $PAGE->navbar->add(get_string('usestandard', 'data')); - $fieldactionbar = $actionbar->get_fields_action_bar(); + $fieldactionbar = $actionbar->get_fields_mapping_action_bar(); data_print_header($course, $cm, $data, false, $fieldactionbar); - echo $OUTPUT->heading(get_string('usestandard', 'data'), 2, 'mb-4'); $importer = new preset_existing_importer($manager, $fullname); echo $renderer->importing_preset($data, $importer); echo $OUTPUT->footer(); diff --git a/mod/data/lang/en/data.php b/mod/data/lang/en/data.php index 331768a8a8e..b26e6a8b758 100644 --- a/mod/data/lang/en/data.php +++ b/mod/data/lang/en/data.php @@ -27,7 +27,6 @@ $string['action'] = 'Action'; $string['actionsmenu'] = 'Actions menu'; $string['add'] = 'Add entry'; $string['addcomment'] = 'Add comment'; -$string['addentries'] = 'Add entries'; $string['addtemplate'] = 'Add entry template'; $string['advancedsearch'] = 'Advanced search'; $string['allowcomments'] = 'Allow comments on entries'; @@ -61,6 +60,7 @@ $string['cannotadd'] = 'Can not add entries!'; $string['cannotdeletepreset'] = 'Error deleting a preset!'; $string['cannotoverwritepreset'] = 'Error overwriting preset'; $string['cannotunziptopreset'] = 'Cannot unzip to the preset directory'; +$string['cannotapplypreset'] = 'Error applying the preset.'; $string['closebeforeopen'] = 'You have specified an end date before the start date.'; $string['columns'] = 'columns'; $string['comment'] = 'Comment'; @@ -146,6 +146,7 @@ $string['eventrecordupdated'] = 'Record updated'; $string['eventtemplateupdated'] = 'Template updated'; $string['eventtemplateviewed'] = 'Templates viewed'; $string['fileencoding'] = 'Encoding'; +$string['emptypresetname'] = 'Preset name or file cannot be empty'; $string['entries'] = 'Entries'; $string['entrieslefttoadd'] = 'You must add {$a->entriesleft} more entry/entries in order to complete this activity'; $string['entrieslefttoaddtoview'] = 'You must add {$a->entrieslefttoview} more entry/entries before you can view other participants\' entries.'; @@ -155,6 +156,7 @@ $string['errormustbeteacher'] = 'You need to be a teacher to use this page!'; $string['errorpresetexists'] = 'A preset with this name already exists.'; $string['errorpresetexistsbutnotoverwrite'] = 'A preset with this name already exists. Choose a different name.'; $string['errormustsupplyvalue'] = 'You must supply a value here.'; +$string['errorpresetnotfound'] = 'Preset with name {$a} not found.'; $string['example'] = 'Database module example'; $string['excel'] = 'Excel'; $string['export'] = 'Export'; @@ -177,7 +179,7 @@ $string['fieldheight'] = 'Height'; $string['fieldheightlistview'] = 'Height in list view'; $string['fieldheightsingleview'] = 'Height in single view'; $string['fieldids'] = 'Field ids'; -$string['fieldmappings'] = 'Field mappings'; +$string['fieldmappings'] = 'Fields mappings'; $string['fieldmappings_help'] = 'This menu allows you to keep the data from the existing database. To preserve the data in a field, you must map it to a new field, where the data will appear. Any field can also be left blank, with no information copied into it. Any old field not mapped to a new one will be lost and all its data removed. You can only map fields of the same type, so each drop-down menu will have different fields in it. Also, you must be careful not to try and map one old field to more than one new field.'; $string['fieldname'] = 'Field name'; @@ -219,7 +221,7 @@ $string['expired'] = 'Sorry, this activity closed on {$a} and is no longer avail $string['importentries'] = 'Import entries'; $string['importpreset'] = 'Import preset'; $string['importapreset'] = 'Import a preset'; -$string['importsuccess'] = 'The preset has been successfully applied.'; +$string['importsuccess'] = 'Preset applied.'; $string['importpresetmissingcapability'] = 'You don\'t have permission to import a preset.'; $string['includeapproval'] = 'Include approval status'; $string['includetags'] = 'Include tags'; @@ -266,11 +268,18 @@ $string['listview'] = 'List view'; $string['listtemplate'] = 'List view template'; $string['longitude'] = 'Longitude'; $string['manageapproved'] = 'Allow editing of approved entries'; -$string['managefields'] = 'Manage fields'; $string['manageapproved_help'] = 'If disabled, approved entries are no longer editable or deletable by the user who added them. This setting has no effect unless \'Approval required\' is enabled.'; +$string['managefields'] = 'Manage fields'; $string['mapexistingfield'] = 'Map to {$a}'; $string['mapnewfield'] = 'Create a new field'; $string['mappingwarning'] = 'All old fields not mapped to a new field will be lost and all data in that field will be removed.'; +$string['mapping:fieldstocreate'] = 'Fields to be created: {$a}'; +$string['mapping:fieldstodelete'] = 'Existing fields to be deleted: {$a}'; +$string['mapping:warningmessagedeleteandcreate'] = 'If fields to be deleted are of the same type as fields to be created, you may be able to map them in Map fields.'; +$string['mapping:warningmessagedelete'] = 'If fields to be deleted are of the same type as new fields in the preset you\'re applying, you may be able to map them in Map fields.'; +$string['mapping:mapfields'] = 'Map fields'; +$string['mapping:applypresets'] = 'Apply preset'; +$string['mapping:dialogtitle:usepreset'] = 'Apply preset {$a}?'; $string['maxentries'] = 'Maximum number of entries'; $string['maxentries_help'] = 'The maximum number of entries a student is allowed to submit for this activity.'; $string['maxsize'] = 'Maximum size'; @@ -330,7 +339,7 @@ $string['optionalfilename'] = 'Filename (optional)'; $string['other'] = 'Other'; $string['overwrite'] = 'Overwrite'; $string['overrwritedesc'] = 'Replace existing preset with this name and overwrite its contents'; -$string['overwritesettings'] = 'Overwrite current settings'; +$string['overwritesettings'] = 'Overwrite current settings such as comments, ratings, etc.'; $string['page-mod-data-x'] = 'Any database activity module page'; $string['pagesize'] = 'Entries per page'; $string['participants'] = 'Participants'; @@ -434,7 +443,6 @@ $string['text'] = 'Text'; $string['textarea'] = 'Text area'; $string['timeadded'] = 'Time added'; $string['timemodified'] = 'Time modified'; -$string['todatabase'] = 'to this database.'; $string['type'] = 'Field type'; $string['undefinedprocessactionmethod'] = 'No action method defined in Data_Preset to handle action "{$a}".'; $string['unsupportedfields'] = 'Unsupported fields'; @@ -474,3 +482,5 @@ $string['pleaseaddsome'] = 'Please create some below or choose a $string['blank'] = 'Blank'; $string['savetemplate'] = 'Save template'; $string['addedby'] = 'Added by'; +$string['addentries'] = 'Add entries'; +$string['todatabase'] = 'to this database.'; diff --git a/mod/data/lang/en/deprecated.txt b/mod/data/lang/en/deprecated.txt index 6c7fa3037cb..3cda6949bec 100644 --- a/mod/data/lang/en/deprecated.txt +++ b/mod/data/lang/en/deprecated.txt @@ -6,3 +6,6 @@ pleaseaddsome,mod_data blank,mod_data savetemplate,mod_data addedby,mod_data +addentries,mod_data +todatabase,mod_data + diff --git a/mod/data/preset.php b/mod/data/preset.php index aea1e24f964..1ce4e2446d6 100644 --- a/mod/data/preset.php +++ b/mod/data/preset.php @@ -119,7 +119,7 @@ if ($action == 'importzip') { $importer = new preset_upload_importer($manager, $CFG->tempdir . $filepath); if ($importer->needs_mapping()) { echo $OUTPUT->header(); - echo $OUTPUT->heading(get_string('importpreset', 'data'), 2, 'mb-4'); + echo $OUTPUT->heading(get_string('fieldmappings', 'data'), 2, 'mb-4'); echo $renderer->importing_preset($data, $importer); echo $OUTPUT->footer(); exit(0); @@ -151,8 +151,6 @@ if ($action === 'preview') { exit(0); } -echo $OUTPUT->header(); - if ($action === 'finishimport') { if (!confirm_sesskey()) { throw new moodle_exception('invalidsesskey'); @@ -160,12 +158,10 @@ if ($action === 'finishimport') { $overwritesettings = optional_param('overwritesettings', false, PARAM_BOOL); $importer = preset_importer::create_from_parameters($manager); $importer->finish_import_process($overwritesettings, $data); - - echo $OUTPUT->continue_button(new moodle_url('/mod/data/preset.php', ['d' => $data->id])); - echo $OUTPUT->footer(); - exit(0); } +echo $OUTPUT->header(); + $actionbar = new \mod_data\output\action_bar($data->id, $url); echo $actionbar->get_presets_action_bar(); $presets = new \mod_data\output\presets($manager, $presets, new \moodle_url('/mod/data/field.php'), true); diff --git a/mod/data/renderer.php b/mod/data/renderer.php index 9ea5431982a..aad4bbf20ad 100644 --- a/mod/data/renderer.php +++ b/mod/data/renderer.php @@ -57,9 +57,8 @@ class mod_data_renderer extends plugin_renderer_base { public function importing_preset(stdClass $datamodule, \mod_data\local\importer\preset_importer $importer): string { $strwarning = get_string('mappingwarning', 'data'); - $strfieldmappings = get_string('fieldmappings', 'data'); - $params = $importer->get_preset_settings(); + $params = $importer->settings; $newfields = $params->importfields; $currentfields = $params->currentfields; @@ -77,8 +76,6 @@ class mod_data_renderer extends plugin_renderer_base { ); if (!empty($newfields)) { - $html .= $this->output->heading_with_help($strfieldmappings, 'fieldmappings', 'data', '', '', 3); - $table = new html_table(); $table->data = array(); @@ -94,10 +91,18 @@ class mod_data_renderer extends plugin_renderer_base { continue; } if ($currentfield->name == $newfield->name) { - $row[1] .= html_writer::tag('option', get_string('mapexistingfield', 'data', $currentfield->name), array('value'=>$cid, 'selected'=>'selected')); - $selected=true; + $row[1] .= html_writer::tag( + 'option', + get_string('mapexistingfield', 'data', $currentfield->name), + ['value' => $cid, 'selected' => 'selected'] + ); + $selected = true; } else { - $row[1] .= html_writer::tag('option', get_string('mapexistingfield', 'data', $currentfield->name), array('value'=>$cid)); + $row[1] .= html_writer::tag( + 'option', + get_string('mapexistingfield', 'data', $currentfield->name), + ['value' => $cid] + ); } } @@ -117,13 +122,13 @@ class mod_data_renderer extends plugin_renderer_base { } $html .= html_writer::start_tag('div', array('class'=>'overwritesettings')); - $html .= html_writer::tag('label', get_string('overwritesettings', 'data'), array('for' => 'overwritesettings')); - $attrs = array('type' => 'checkbox', 'name' => 'overwritesettings', 'id' => 'overwritesettings', 'class' => 'ml-1'); + $attrs = ['type' => 'checkbox', 'name' => 'overwritesettings', 'id' => 'overwritesettings', 'class' => 'mr-2']; $html .= html_writer::empty_tag('input', $attrs); + $html .= html_writer::tag('label', get_string('overwritesettings', 'data'), ['for' => 'overwritesettings']); $html .= html_writer::end_tag('div'); $actionbuttons = html_writer::start_div(); - $cancelurl = new moodle_url('/mod/data/preset.php', ['d' => $datamodule->id]); + $cancelurl = new moodle_url('/mod/data/field.php', ['d' => $datamodule->id]); $actionbuttons .= html_writer::tag('a', get_string('cancel') , [ 'href' => $cancelurl->out(false), 'class' => 'btn btn-secondary mr-2', diff --git a/mod/data/styles.css b/mod/data/styles.css index 3102d3d21c7..4640028ec66 100644 --- a/mod/data/styles.css +++ b/mod/data/styles.css @@ -198,6 +198,7 @@ .entriesactions .dropdown-toggle:hover, .entriesactions .show > .btn-secondary.dropdown-toggle, #page-mod-data-view .whitebutton .btn-secondary, +#page-mod-data-preset .whitebutton .btn-secondary, #page-mod-data-field- .whitebutton .btn-secondary, #page-mod-data-templates .whitebutton .btn-secondary { background: white; diff --git a/mod/data/templates/fields_action_bar.mustache b/mod/data/templates/fields_action_bar.mustache index 3e5dde9fa4f..24a110b2e1d 100644 --- a/mod/data/templates/fields_action_bar.mustache +++ b/mod/data/templates/fields_action_bar.mustache @@ -22,7 +22,7 @@ Example context (json): { - "d": 1, + "tertiarytitle": "Manage fields", "fieldselect": { "id": "single_select_test", "name": "fieldselector", @@ -43,15 +43,34 @@ ], "disabled": false, "title": null - } + }, + "hasback" : true, + "backurl": "https://moodlesite.com/mod/data/preset.php", + "backtitle": "Back" } }}
-
-

{{#str}}managefields, mod_data{{/str}}

+
+ {{#hasback}} + + {{/hasback}} + {{#urlselect}} + + {{/urlselect}} + {{#tertiarytitle}} + + {{/tertiarytitle}}
-
+
{{#fieldselect}}