From 48eec50590579b4fd935554109813b5740eac26c Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 5 Jul 2024 16:59:55 +0100 Subject: [PATCH] MDL-82401 quiz: editing modals must be removed on close --- mod/quiz/amd/build/add_question_modal.min.js | 2 +- .../amd/build/add_question_modal.min.js.map | 2 +- .../build/modal_add_random_question.min.js | 2 +- .../modal_add_random_question.min.js.map | 2 +- mod/quiz/amd/src/add_question_modal.js | 1 + mod/quiz/amd/src/modal_add_random_question.js | 2 ++ .../editing_add_from_question_bank.feature | 20 +++++++++++++++++++ .../tests/behat/editing_add_random.feature | 12 +++++++++++ 8 files changed, 39 insertions(+), 4 deletions(-) diff --git a/mod/quiz/amd/build/add_question_modal.min.js b/mod/quiz/amd/build/add_question_modal.min.js index 57e67301cd2..c565b06c23a 100644 --- a/mod/quiz/amd/build/add_question_modal.min.js +++ b/mod/quiz/amd/build/add_question_modal.min.js @@ -5,6 +5,6 @@ define("mod_quiz/add_question_modal",["exports","core/modal"],(function(_exports * @module mod_quiz/add_question_modal * @copyright 2023 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal=(obj=_modal)&&obj.__esModule?obj:{default:obj};class AddQuestionModal extends _modal.default{configure(modalConfig){modalConfig.large=!0,modalConfig.show=!0,this.setContextId(modalConfig.contextId),this.setAddOnPageId(modalConfig.addOnPage),super.configure(modalConfig)}constructor(root){super(root),this.contextId=null,this.addOnPageId=null}setContextId(id){this.contextId=id}getContextId(){return this.contextId}setAddOnPageId(id){this.addOnPageId=id}getAddOnPageId(){return this.addOnPageId}}return _exports.default=AddQuestionModal,_exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal=(obj=_modal)&&obj.__esModule?obj:{default:obj};class AddQuestionModal extends _modal.default{configure(modalConfig){modalConfig.large=!0,modalConfig.show=!0,modalConfig.removeOnClose=!0,this.setContextId(modalConfig.contextId),this.setAddOnPageId(modalConfig.addOnPage),super.configure(modalConfig)}constructor(root){super(root),this.contextId=null,this.addOnPageId=null}setContextId(id){this.contextId=id}getContextId(){return this.contextId}setAddOnPageId(id){this.addOnPageId=id}getAddOnPageId(){return this.addOnPageId}}return _exports.default=AddQuestionModal,_exports.default})); //# sourceMappingURL=add_question_modal.min.js.map \ No newline at end of file diff --git a/mod/quiz/amd/build/add_question_modal.min.js.map b/mod/quiz/amd/build/add_question_modal.min.js.map index 8f2082971fd..a907164be0e 100644 --- a/mod/quiz/amd/build/add_question_modal.min.js.map +++ b/mod/quiz/amd/build/add_question_modal.min.js.map @@ -1 +1 @@ -{"version":3,"file":"add_question_modal.min.js","sources":["../src/add_question_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 add random question modal.\n *\n * @module mod_quiz/add_question_modal\n * @copyright 2023 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\n\nexport default class AddQuestionModal extends Modal {\n configure(modalConfig) {\n // Add question modals are always large.\n modalConfig.large = true;\n\n // Always show on creation.\n modalConfig.show = true;\n\n // Apply question modal configuration.\n this.setContextId(modalConfig.contextId);\n this.setAddOnPageId(modalConfig.addOnPage);\n\n // Apply standard configuration.\n super.configure(modalConfig);\n }\n\n constructor(root) {\n super(root);\n\n this.contextId = null;\n this.addOnPageId = null;\n }\n\n /**\n * Save the Moodle context id that the question bank is being\n * rendered in.\n *\n * @method setContextId\n * @param {Number} id\n */\n setContextId(id) {\n this.contextId = id;\n }\n\n /**\n * Retrieve the saved Moodle context id.\n *\n * @method getContextId\n * @return {Number}\n */\n getContextId() {\n return this.contextId;\n }\n\n /**\n * Set the id of the page that the question should be added to\n * when the user clicks the add to quiz link.\n *\n * @method setAddOnPageId\n * @param {Number} id\n */\n setAddOnPageId(id) {\n this.addOnPageId = id;\n }\n\n /**\n * Returns the saved page id for the question to be added to.\n *\n * @method getAddOnPageId\n * @return {Number}\n */\n getAddOnPageId() {\n return this.addOnPageId;\n }\n\n}\n"],"names":["AddQuestionModal","Modal","configure","modalConfig","large","show","setContextId","contextId","setAddOnPageId","addOnPage","constructor","root","addOnPageId","id","getContextId","this","getAddOnPageId"],"mappings":";;;;;;;iJAyBqBA,yBAAyBC,eAC1CC,UAAUC,aAENA,YAAYC,OAAQ,EAGpBD,YAAYE,MAAO,OAGdC,aAAaH,YAAYI,gBACzBC,eAAeL,YAAYM,iBAG1BP,UAAUC,aAGpBO,YAAYC,YACFA,WAEDJ,UAAY,UACZK,YAAc,KAUvBN,aAAaO,SACJN,UAAYM,GASrBC,sBACWC,KAAKR,UAUhBC,eAAeK,SACND,YAAcC,GASvBG,wBACWD,KAAKH"} \ No newline at end of file +{"version":3,"file":"add_question_modal.min.js","sources":["../src/add_question_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 add random question modal.\n *\n * @module mod_quiz/add_question_modal\n * @copyright 2023 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\n\nexport default class AddQuestionModal extends Modal {\n configure(modalConfig) {\n // Add question modals are always large.\n modalConfig.large = true;\n\n // Always show on creation.\n modalConfig.show = true;\n modalConfig.removeOnClose = true;\n\n // Apply question modal configuration.\n this.setContextId(modalConfig.contextId);\n this.setAddOnPageId(modalConfig.addOnPage);\n\n // Apply standard configuration.\n super.configure(modalConfig);\n }\n\n constructor(root) {\n super(root);\n\n this.contextId = null;\n this.addOnPageId = null;\n }\n\n /**\n * Save the Moodle context id that the question bank is being\n * rendered in.\n *\n * @method setContextId\n * @param {Number} id\n */\n setContextId(id) {\n this.contextId = id;\n }\n\n /**\n * Retrieve the saved Moodle context id.\n *\n * @method getContextId\n * @return {Number}\n */\n getContextId() {\n return this.contextId;\n }\n\n /**\n * Set the id of the page that the question should be added to\n * when the user clicks the add to quiz link.\n *\n * @method setAddOnPageId\n * @param {Number} id\n */\n setAddOnPageId(id) {\n this.addOnPageId = id;\n }\n\n /**\n * Returns the saved page id for the question to be added to.\n *\n * @method getAddOnPageId\n * @return {Number}\n */\n getAddOnPageId() {\n return this.addOnPageId;\n }\n\n}\n"],"names":["AddQuestionModal","Modal","configure","modalConfig","large","show","removeOnClose","setContextId","contextId","setAddOnPageId","addOnPage","constructor","root","addOnPageId","id","getContextId","this","getAddOnPageId"],"mappings":";;;;;;;iJAyBqBA,yBAAyBC,eAC1CC,UAAUC,aAENA,YAAYC,OAAQ,EAGpBD,YAAYE,MAAO,EACnBF,YAAYG,eAAgB,OAGvBC,aAAaJ,YAAYK,gBACzBC,eAAeN,YAAYO,iBAG1BR,UAAUC,aAGpBQ,YAAYC,YACFA,WAEDJ,UAAY,UACZK,YAAc,KAUvBN,aAAaO,SACJN,UAAYM,GASrBC,sBACWC,KAAKR,UAUhBC,eAAeK,SACND,YAAcC,GASvBG,wBACWD,KAAKH"} \ No newline at end of file diff --git a/mod/quiz/amd/build/modal_add_random_question.min.js b/mod/quiz/amd/build/modal_add_random_question.min.js index af4c41fad09..2a96535c730 100644 --- a/mod/quiz/amd/build/modal_add_random_question.min.js +++ b/mod/quiz/amd/build/modal_add_random_question.min.js @@ -1,3 +1,3 @@ -define("mod_quiz/modal_add_random_question",["exports","jquery","./add_question_modal","core/notification","core/fragment","core/templates","core_form/changechecker","core/ajax","core/pending"],(function(_exports,_jquery,_add_question_modal,Notification,Fragment,Templates,FormChangeChecker,_ajax,_pending){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),_add_question_modal=_interopRequireDefault(_add_question_modal),Notification=_interopRequireWildcard(Notification),Fragment=_interopRequireWildcard(Fragment),Templates=_interopRequireWildcard(Templates),FormChangeChecker=_interopRequireWildcard(FormChangeChecker),_pending=_interopRequireDefault(_pending);const SELECTORS={EXISTING_CATEGORY_CONTAINER:'[data-region="existing-category-container"]',EXISTING_CATEGORY_TAB:"#id_existingcategoryheader",NEW_CATEGORY_CONTAINER:'[data-region="new-category-container"]',NEW_CATEGORY_TAB:"#id_newcategoryheader",TAB_CONTENT:'[data-region="tab-content"]',ADD_ON_PAGE_FORM_ELEMENT:'[name="addonpage"]',ADD_RANDOM_BUTTON:'input[type="submit"][name="addrandom"]',ADD_NEW_CATEGORY_BUTTON:'input[type="submit"][name="newcategory"]',SUBMIT_BUTTON_ELEMENT:'input[type="submit"][name="addrandom"], input[type="submit"][name="newcategory"]',FORM_HEADER:"legend",SELECT_NUMBER_TO_ADD:"#menurandomcount",NEW_CATEGORY_ELEMENT:"#categoryname",PARENT_CATEGORY_ELEMENT:"#parentcategory",FILTER_CONDITION_ELEMENT:"[data-filtercondition]",FORM_ELEMENT:"#add_random_question_form",MESSAGE_INPUT:'[name="message"]'};class ModalAddRandomQuestion extends _add_question_modal.default{static init(contextId,category,returnUrl,cmid){let showNewCategory=!(arguments.length>4&&void 0!==arguments[4])||arguments[4];document.addEventListener("click",(e=>{const trigger=e.target.closest('.menu [data-action="addarandomquestion"]');trigger&&(e.preventDefault(),ModalAddRandomQuestion.create({contextId:contextId,category:category,returnUrl:returnUrl,cmid:cmid,title:trigger.dataset.header,addOnPage:trigger.dataset.addonpage,templateContext:{hidden:showNewCategory}}))}))}constructor(root){super(root),this.category=null,this.returnUrl=null,this.cmid=null,this.loadedForm=!1}configure(modalConfig){this.setCategory(modalConfig.category),this.setReturnUrl(modalConfig.returnUrl),this.setCMID(modalConfig.cmid),super.configure(modalConfig)}setAddOnPageId(id){super.setAddOnPageId(id),this.getBody().find(SELECTORS.ADD_ON_PAGE_FORM_ELEMENT).val(id)}setCategory(category){this.category=category}getCategory(){return this.category}setReturnUrl(url){this.returnUrl=url}getReturnUrl(){return this.returnUrl}setCMID(id){this.cmid=id}getCMID(){return this.cmid}moveContentIntoTab(tabContent,tabElement){tabContent.find(SELECTORS.FORM_HEADER).addClass("hidden"),tabContent.wrap(tabElement)}moveTabsIntoTabContent(form){const tabContent=this.getBody().find(SELECTORS.TAB_CONTENT).empty();form.find('[role="tabpanel"]').wrapAll(tabContent)}moveCancelButtonToTabs(form){const cancelButton=form.find(SELECTORS.CANCEL_BUTTON_ELEMENT).addClass("ml-1"),tabFooters=form.find('[data-region="footer"]');cancelButton.closest(SELECTORS.BUTTON_CONTAINER).remove(),cancelButton.clone().appendTo(tabFooters)}loadForm(){const cmid=this.getCMID(),cat=this.getCategory(),addonpage=this.getAddOnPageId(),returnurl=this.getReturnUrl();return Fragment.loadFragment("mod_quiz","add_random_question_form",this.getContextId(),{addonpage:addonpage,cat:cat,returnurl:returnurl,cmid:cmid}).then(((html,js)=>{const form=(0,_jquery.default)(html),existingCategoryTabContent=form.find(SELECTORS.EXISTING_CATEGORY_TAB),existingCategoryTab=this.getBody().find(SELECTORS.EXISTING_CATEGORY_CONTAINER),newCategoryTabContent=form.find(SELECTORS.NEW_CATEGORY_TAB),newCategoryTab=this.getBody().find(SELECTORS.NEW_CATEGORY_CONTAINER);this.moveContentIntoTab(existingCategoryTabContent,existingCategoryTab),this.moveContentIntoTab(newCategoryTabContent,newCategoryTab),this.moveTabsIntoTabContent(form),Templates.replaceNode(this.getBody().find(SELECTORS.TAB_CONTENT),form,js)})).then((()=>{FormChangeChecker.disableAllChecks(),this.getBody()[0].addEventListener("click",(e=>{if(!e.target.closest(SELECTORS.SUBMIT_BUTTON_ELEMENT))return;e.preventDefault();if(e.target.closest(SELECTORS.ADD_RANDOM_BUTTON)){var _document$querySelect;const randomcount=document.querySelector(SELECTORS.SELECT_NUMBER_TO_ADD).value,filtercondition=null===(_document$querySelect=document.querySelector(SELECTORS.FILTER_CONDITION_ELEMENT).dataset)||void 0===_document$querySelect?void 0:_document$querySelect.filtercondition;return void this.addQuestions(cmid,addonpage,randomcount,filtercondition,"","")}e.target.closest(SELECTORS.ADD_NEW_CATEGORY_BUTTON)&&this.addQuestions(cmid,addonpage,1,"",document.querySelector(SELECTORS.NEW_CATEGORY_ELEMENT).value,document.querySelector(SELECTORS.PARENT_CATEGORY_ELEMENT).value)}))})).catch(Notification.exception)}async addQuestions(cmid,addonpage,randomcount,filtercondition,newcategory,parentcategory){new _pending.default("mod-quiz/modal_add_random_questions");const call={methodname:"mod_quiz_add_random_questions",args:{cmid:cmid,addonpage:addonpage,randomcount:randomcount,filtercondition:filtercondition,newcategory:newcategory,parentcategory:parentcategory}};try{const response=await(0,_ajax.call)([call])[0],form=document.querySelector(SELECTORS.FORM_ELEMENT);form.querySelector(SELECTORS.MESSAGE_INPUT).value=response.message,form.submit()}catch(e){Notification.exception(e)}}show(){super.show(this),this.loadedForm||(this.loadForm(window.location.search),this.loadedForm=!0)}}return _exports.default=ModalAddRandomQuestion,_defineProperty(ModalAddRandomQuestion,"TYPE","mod_quiz-quiz-add-random-question"),_defineProperty(ModalAddRandomQuestion,"TEMPLATE","mod_quiz/modal_add_random_question"),ModalAddRandomQuestion.registerModalType(),_exports.default})); +define("mod_quiz/modal_add_random_question",["exports","jquery","./add_question_modal","core/notification","core/fragment","core/templates","core_form/changechecker","core/ajax","core/pending"],(function(_exports,_jquery,_add_question_modal,Notification,Fragment,Templates,FormChangeChecker,_ajax,_pending){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),_add_question_modal=_interopRequireDefault(_add_question_modal),Notification=_interopRequireWildcard(Notification),Fragment=_interopRequireWildcard(Fragment),Templates=_interopRequireWildcard(Templates),FormChangeChecker=_interopRequireWildcard(FormChangeChecker),_pending=_interopRequireDefault(_pending);const SELECTORS={EXISTING_CATEGORY_CONTAINER:'[data-region="existing-category-container"]',EXISTING_CATEGORY_TAB:"#id_existingcategoryheader",NEW_CATEGORY_CONTAINER:'[data-region="new-category-container"]',NEW_CATEGORY_TAB:"#id_newcategoryheader",TAB_CONTENT:'[data-region="tab-content"]',ADD_ON_PAGE_FORM_ELEMENT:'[name="addonpage"]',ADD_RANDOM_BUTTON:'input[type="submit"][name="addrandom"]',ADD_NEW_CATEGORY_BUTTON:'input[type="submit"][name="newcategory"]',SUBMIT_BUTTON_ELEMENT:'input[type="submit"][name="addrandom"], input[type="submit"][name="newcategory"]',FORM_HEADER:"legend",SELECT_NUMBER_TO_ADD:"#menurandomcount",NEW_CATEGORY_ELEMENT:"#categoryname",PARENT_CATEGORY_ELEMENT:"#parentcategory",FILTER_CONDITION_ELEMENT:"[data-filtercondition]",FORM_ELEMENT:"#add_random_question_form",MESSAGE_INPUT:'[name="message"]'};class ModalAddRandomQuestion extends _add_question_modal.default{static init(contextId,category,returnUrl,cmid){let showNewCategory=!(arguments.length>4&&void 0!==arguments[4])||arguments[4];document.addEventListener("click",(e=>{const trigger=e.target.closest('.menu [data-action="addarandomquestion"]');trigger&&(e.preventDefault(),ModalAddRandomQuestion.create({contextId:contextId,category:category,returnUrl:returnUrl,cmid:cmid,title:trigger.dataset.header,addOnPage:trigger.dataset.addonpage,templateContext:{hidden:showNewCategory}}))}))}constructor(root){super(root),this.category=null,this.returnUrl=null,this.cmid=null,this.loadedForm=!1}configure(modalConfig){modalConfig.removeOnClose=!0,this.setCategory(modalConfig.category),this.setReturnUrl(modalConfig.returnUrl),this.setCMID(modalConfig.cmid),super.configure(modalConfig)}setAddOnPageId(id){super.setAddOnPageId(id),this.getBody().find(SELECTORS.ADD_ON_PAGE_FORM_ELEMENT).val(id)}setCategory(category){this.category=category}getCategory(){return this.category}setReturnUrl(url){this.returnUrl=url}getReturnUrl(){return this.returnUrl}setCMID(id){this.cmid=id}getCMID(){return this.cmid}moveContentIntoTab(tabContent,tabElement){tabContent.find(SELECTORS.FORM_HEADER).addClass("hidden"),tabContent.wrap(tabElement)}moveTabsIntoTabContent(form){const tabContent=this.getBody().find(SELECTORS.TAB_CONTENT).empty();form.find('[role="tabpanel"]').wrapAll(tabContent)}moveCancelButtonToTabs(form){const cancelButton=form.find(SELECTORS.CANCEL_BUTTON_ELEMENT).addClass("ml-1"),tabFooters=form.find('[data-region="footer"]');cancelButton.closest(SELECTORS.BUTTON_CONTAINER).remove(),cancelButton.clone().appendTo(tabFooters)}loadForm(){const cmid=this.getCMID(),cat=this.getCategory(),addonpage=this.getAddOnPageId(),returnurl=this.getReturnUrl();return Fragment.loadFragment("mod_quiz","add_random_question_form",this.getContextId(),{addonpage:addonpage,cat:cat,returnurl:returnurl,cmid:cmid}).then(((html,js)=>{const form=(0,_jquery.default)(html),existingCategoryTabContent=form.find(SELECTORS.EXISTING_CATEGORY_TAB),existingCategoryTab=this.getBody().find(SELECTORS.EXISTING_CATEGORY_CONTAINER),newCategoryTabContent=form.find(SELECTORS.NEW_CATEGORY_TAB),newCategoryTab=this.getBody().find(SELECTORS.NEW_CATEGORY_CONTAINER);this.moveContentIntoTab(existingCategoryTabContent,existingCategoryTab),this.moveContentIntoTab(newCategoryTabContent,newCategoryTab),this.moveTabsIntoTabContent(form),Templates.replaceNode(this.getBody().find(SELECTORS.TAB_CONTENT),form,js)})).then((()=>{FormChangeChecker.disableAllChecks(),this.getBody()[0].addEventListener("click",(e=>{if(!e.target.closest(SELECTORS.SUBMIT_BUTTON_ELEMENT))return;e.preventDefault();if(e.target.closest(SELECTORS.ADD_RANDOM_BUTTON)){var _document$querySelect;const randomcount=document.querySelector(SELECTORS.SELECT_NUMBER_TO_ADD).value,filtercondition=null===(_document$querySelect=document.querySelector(SELECTORS.FILTER_CONDITION_ELEMENT).dataset)||void 0===_document$querySelect?void 0:_document$querySelect.filtercondition;return void this.addQuestions(cmid,addonpage,randomcount,filtercondition,"","")}e.target.closest(SELECTORS.ADD_NEW_CATEGORY_BUTTON)&&this.addQuestions(cmid,addonpage,1,"",document.querySelector(SELECTORS.NEW_CATEGORY_ELEMENT).value,document.querySelector(SELECTORS.PARENT_CATEGORY_ELEMENT).value)}))})).catch(Notification.exception)}async addQuestions(cmid,addonpage,randomcount,filtercondition,newcategory,parentcategory){new _pending.default("mod-quiz/modal_add_random_questions");const call={methodname:"mod_quiz_add_random_questions",args:{cmid:cmid,addonpage:addonpage,randomcount:randomcount,filtercondition:filtercondition,newcategory:newcategory,parentcategory:parentcategory}};try{const response=await(0,_ajax.call)([call])[0],form=document.querySelector(SELECTORS.FORM_ELEMENT);form.querySelector(SELECTORS.MESSAGE_INPUT).value=response.message,form.submit()}catch(e){Notification.exception(e)}}show(){super.show(this),this.loadedForm||(this.loadForm(window.location.search),this.loadedForm=!0)}}return _exports.default=ModalAddRandomQuestion,_defineProperty(ModalAddRandomQuestion,"TYPE","mod_quiz-quiz-add-random-question"),_defineProperty(ModalAddRandomQuestion,"TEMPLATE","mod_quiz/modal_add_random_question"),ModalAddRandomQuestion.registerModalType(),_exports.default})); //# sourceMappingURL=modal_add_random_question.min.js.map \ No newline at end of file diff --git a/mod/quiz/amd/build/modal_add_random_question.min.js.map b/mod/quiz/amd/build/modal_add_random_question.min.js.map index 6d26ea8047f..4158d4c8226 100644 --- a/mod/quiz/amd/build/modal_add_random_question.min.js.map +++ b/mod/quiz/amd/build/modal_add_random_question.min.js.map @@ -1 +1 @@ -{"version":3,"file":"modal_add_random_question.min.js","sources":["../src/modal_add_random_question.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 add random question modal.\n *\n * @module mod_quiz/modal_add_random_question\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Modal from './add_question_modal';\nimport * as Notification from 'core/notification';\nimport * as Fragment from 'core/fragment';\nimport * as Templates from 'core/templates';\nimport * as FormChangeChecker from 'core_form/changechecker';\nimport {call as fetchMany} from 'core/ajax';\nimport Pending from 'core/pending';\n\nconst SELECTORS = {\n EXISTING_CATEGORY_CONTAINER: '[data-region=\"existing-category-container\"]',\n EXISTING_CATEGORY_TAB: '#id_existingcategoryheader',\n NEW_CATEGORY_CONTAINER: '[data-region=\"new-category-container\"]',\n NEW_CATEGORY_TAB: '#id_newcategoryheader',\n TAB_CONTENT: '[data-region=\"tab-content\"]',\n ADD_ON_PAGE_FORM_ELEMENT: '[name=\"addonpage\"]',\n ADD_RANDOM_BUTTON: 'input[type=\"submit\"][name=\"addrandom\"]',\n ADD_NEW_CATEGORY_BUTTON: 'input[type=\"submit\"][name=\"newcategory\"]',\n SUBMIT_BUTTON_ELEMENT: 'input[type=\"submit\"][name=\"addrandom\"], input[type=\"submit\"][name=\"newcategory\"]',\n FORM_HEADER: 'legend',\n SELECT_NUMBER_TO_ADD: '#menurandomcount',\n NEW_CATEGORY_ELEMENT: '#categoryname',\n PARENT_CATEGORY_ELEMENT: '#parentcategory',\n FILTER_CONDITION_ELEMENT: '[data-filtercondition]',\n FORM_ELEMENT: '#add_random_question_form',\n MESSAGE_INPUT: '[name=\"message\"]',\n};\n\nexport default class ModalAddRandomQuestion extends Modal {\n static TYPE = 'mod_quiz-quiz-add-random-question';\n static TEMPLATE = 'mod_quiz/modal_add_random_question';\n\n /**\n * Create the add random question modal.\n *\n * @param {Number} contextId Current context id.\n * @param {string} category Category id and category context id comma separated.\n * @param {string} returnUrl URL to return to after form submission.\n * @param {Number} cmid Current course module id.\n * @param {boolean} showNewCategory Display the New category tab when selecting random questions.\n */\n static init(contextId, category, returnUrl, cmid, showNewCategory = true) {\n const selector = '.menu [data-action=\"addarandomquestion\"]';\n document.addEventListener('click', (e) => {\n const trigger = e.target.closest(selector);\n if (!trigger) {\n return;\n }\n e.preventDefault();\n\n ModalAddRandomQuestion.create({\n contextId,\n category,\n returnUrl,\n cmid,\n\n title: trigger.dataset.header,\n addOnPage: trigger.dataset.addonpage,\n\n templateContext: {\n hidden: showNewCategory,\n },\n });\n });\n }\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n constructor(root) {\n super(root);\n this.category = null;\n this.returnUrl = null;\n this.cmid = null;\n this.loadedForm = false;\n }\n\n configure(modalConfig) {\n this.setCategory(modalConfig.category);\n this.setReturnUrl(modalConfig.returnUrl);\n this.setCMID(modalConfig.cmid);\n\n super.configure(modalConfig);\n }\n\n /**\n * Set the id of the page that the question should be added to\n * when the user clicks the add to quiz link.\n *\n * @method setAddOnPageId\n * @param {int} id\n */\n setAddOnPageId(id) {\n super.setAddOnPageId(id);\n this.getBody().find(SELECTORS.ADD_ON_PAGE_FORM_ELEMENT).val(id);\n }\n\n /**\n * Set the category for this form. The category is a comma separated\n * category id and category context id.\n *\n * @method setCategory\n * @param {string} category\n */\n setCategory(category) {\n this.category = category;\n }\n\n /**\n * Returns the saved category.\n *\n * @method getCategory\n * @return {string}\n */\n getCategory() {\n return this.category;\n }\n\n /**\n * Set the return URL for the form.\n *\n * @method setReturnUrl\n * @param {string} url\n */\n setReturnUrl(url) {\n this.returnUrl = url;\n }\n\n /**\n * Returns the return URL for the form.\n *\n * @method getReturnUrl\n * @return {string}\n */\n getReturnUrl() {\n return this.returnUrl;\n }\n\n /**\n * Set the course module id for the form.\n *\n * @method setCMID\n * @param {Number} id\n */\n setCMID(id) {\n this.cmid = id;\n }\n\n /**\n * Returns the course module id for the form.\n *\n * @method getCMID\n * @return {Number}\n */\n getCMID() {\n return this.cmid;\n }\n\n /**\n * Moves a given form element inside (a child of) a given tab element.\n *\n * Hides the 'legend' (e.g. header) element of the form element because the\n * tab has the name.\n *\n * Moves the submit button into a footer element at the bottom of the form\n * element for styling purposes.\n *\n * @method moveContentIntoTab\n * @param {jquery} tabContent The form element to move into the tab.\n * @param {jquey} tabElement The tab element for the form element to move into.\n */\n moveContentIntoTab(tabContent, tabElement) {\n // Hide the header because the tabs show us which part of the form we're\n // looking at.\n tabContent.find(SELECTORS.FORM_HEADER).addClass('hidden');\n // Move the element inside a tab.\n tabContent.wrap(tabElement);\n }\n\n /**\n * Empty the tab content container and move all tabs from the form into the\n * tab container element.\n *\n * @method moveTabsIntoTabContent\n * @param {jquery} form The form element.\n */\n moveTabsIntoTabContent(form) {\n // Empty it to remove the loading icon.\n const tabContent = this.getBody().find(SELECTORS.TAB_CONTENT).empty();\n // Make sure all tabs are inside the tab content element.\n form.find('[role=\"tabpanel\"]').wrapAll(tabContent);\n }\n\n /**\n * Make sure all of the tabs have a cancel button in their fotter to sit along\n * side the submit button.\n *\n * @method moveCancelButtonToTabs\n * @param {jquey} form The form element.\n */\n moveCancelButtonToTabs(form) {\n const cancelButton = form.find(SELECTORS.CANCEL_BUTTON_ELEMENT).addClass('ml-1');\n const tabFooters = form.find('[data-region=\"footer\"]');\n // Remove the buttons container element.\n cancelButton.closest(SELECTORS.BUTTON_CONTAINER).remove();\n cancelButton.clone().appendTo(tabFooters);\n }\n\n /**\n * Load the add random question form in a fragement and perform some transformation\n * on the HTML to convert it into tabs for rendering in the modal.\n *\n * @method loadForm\n * @return {promise} Resolved with form HTML and JS.\n */\n loadForm() {\n const cmid = this.getCMID();\n const cat = this.getCategory();\n const addonpage = this.getAddOnPageId();\n const returnurl = this.getReturnUrl();\n\n return Fragment.loadFragment(\n 'mod_quiz',\n 'add_random_question_form',\n this.getContextId(),\n {\n addonpage,\n cat,\n returnurl,\n cmid,\n }\n )\n .then((html, js) =>{\n const form = $(html);\n const existingCategoryTabContent = form.find(SELECTORS.EXISTING_CATEGORY_TAB);\n const existingCategoryTab = this.getBody().find(SELECTORS.EXISTING_CATEGORY_CONTAINER);\n const newCategoryTabContent = form.find(SELECTORS.NEW_CATEGORY_TAB);\n const newCategoryTab = this.getBody().find(SELECTORS.NEW_CATEGORY_CONTAINER);\n\n // Transform the form into tabs for better rendering in the modal.\n this.moveContentIntoTab(existingCategoryTabContent, existingCategoryTab);\n this.moveContentIntoTab(newCategoryTabContent, newCategoryTab);\n this.moveTabsIntoTabContent(form);\n\n Templates.replaceNode(this.getBody().find(SELECTORS.TAB_CONTENT), form, js);\n return;\n })\n .then(() => {\n // Make sure the form change checker is disabled otherwise it'll stop the user from navigating away from the\n // page once the modal is hidden.\n FormChangeChecker.disableAllChecks();\n\n // Add question to quiz.\n this.getBody()[0].addEventListener('click', (e) => {\n const button = e.target.closest(SELECTORS.SUBMIT_BUTTON_ELEMENT);\n if (!button) {\n return;\n }\n e.preventDefault();\n\n // Add Random questions if the add random button was clicked.\n const addRandomButton = e.target.closest(SELECTORS.ADD_RANDOM_BUTTON);\n if (addRandomButton) {\n const randomcount = document.querySelector(SELECTORS.SELECT_NUMBER_TO_ADD).value;\n const filtercondition = document.querySelector(SELECTORS.FILTER_CONDITION_ELEMENT).dataset?.filtercondition;\n\n this.addQuestions(cmid, addonpage, randomcount, filtercondition, '', '');\n return;\n }\n // Add new category if the add category button was clicked.\n const addCategoryButton = e.target.closest(SELECTORS.ADD_NEW_CATEGORY_BUTTON);\n if (addCategoryButton) {\n this.addQuestions(\n cmid,\n addonpage,\n 1,\n '',\n document.querySelector(SELECTORS.NEW_CATEGORY_ELEMENT).value,\n document.querySelector(SELECTORS.PARENT_CATEGORY_ELEMENT).value\n );\n return;\n }\n });\n })\n .catch(Notification.exception);\n }\n\n /**\n * Call web service function to add random questions\n *\n * @param {number} cmid course module id\n * @param {number} addonpage the page where random questions will be added to\n * @param {number} randomcount Number of random questions\n * @param {string} filtercondition Filter condition\n * @param {string} newcategory add new category\n * @param {string} parentcategory parent category of new category\n */\n async addQuestions(\n cmid,\n addonpage,\n randomcount,\n filtercondition,\n newcategory,\n parentcategory\n ) {\n // We do not need to resolve this Pending because the form submission will result in a page redirect.\n new Pending('mod-quiz/modal_add_random_questions');\n const call = {\n methodname: 'mod_quiz_add_random_questions',\n args: {\n cmid,\n addonpage,\n randomcount,\n filtercondition,\n newcategory,\n parentcategory,\n }\n };\n try {\n const response = await fetchMany([call])[0];\n const form = document.querySelector(SELECTORS.FORM_ELEMENT);\n const messageInput = form.querySelector(SELECTORS.MESSAGE_INPUT);\n messageInput.value = response.message;\n form.submit();\n } catch (e) {\n Notification.exception(e);\n }\n }\n\n /**\n * Override the modal show function to load the form when this modal is first\n * shown.\n *\n * @method show\n */\n show() {\n super.show(this);\n\n if (!this.loadedForm) {\n this.loadForm(window.location.search);\n this.loadedForm = true;\n }\n }\n}\n\nModalAddRandomQuestion.registerModalType();\n"],"names":["SELECTORS","EXISTING_CATEGORY_CONTAINER","EXISTING_CATEGORY_TAB","NEW_CATEGORY_CONTAINER","NEW_CATEGORY_TAB","TAB_CONTENT","ADD_ON_PAGE_FORM_ELEMENT","ADD_RANDOM_BUTTON","ADD_NEW_CATEGORY_BUTTON","SUBMIT_BUTTON_ELEMENT","FORM_HEADER","SELECT_NUMBER_TO_ADD","NEW_CATEGORY_ELEMENT","PARENT_CATEGORY_ELEMENT","FILTER_CONDITION_ELEMENT","FORM_ELEMENT","MESSAGE_INPUT","ModalAddRandomQuestion","Modal","contextId","category","returnUrl","cmid","showNewCategory","document","addEventListener","e","trigger","target","closest","preventDefault","create","title","dataset","header","addOnPage","addonpage","templateContext","hidden","constructor","root","loadedForm","configure","modalConfig","setCategory","setReturnUrl","setCMID","setAddOnPageId","id","getBody","find","val","getCategory","this","url","getReturnUrl","getCMID","moveContentIntoTab","tabContent","tabElement","addClass","wrap","moveTabsIntoTabContent","form","empty","wrapAll","moveCancelButtonToTabs","cancelButton","CANCEL_BUTTON_ELEMENT","tabFooters","BUTTON_CONTAINER","remove","clone","appendTo","loadForm","cat","getAddOnPageId","returnurl","Fragment","loadFragment","getContextId","then","html","js","existingCategoryTabContent","existingCategoryTab","newCategoryTabContent","newCategoryTab","Templates","replaceNode","FormChangeChecker","disableAllChecks","randomcount","querySelector","value","filtercondition","_document$querySelect","addQuestions","catch","Notification","exception","newcategory","parentcategory","Pending","call","methodname","args","response","message","submit","show","window","location","search","registerModalType"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"modal_add_random_question.min.js","sources":["../src/modal_add_random_question.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 add random question modal.\n *\n * @module mod_quiz/modal_add_random_question\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Modal from './add_question_modal';\nimport * as Notification from 'core/notification';\nimport * as Fragment from 'core/fragment';\nimport * as Templates from 'core/templates';\nimport * as FormChangeChecker from 'core_form/changechecker';\nimport {call as fetchMany} from 'core/ajax';\nimport Pending from 'core/pending';\n\nconst SELECTORS = {\n EXISTING_CATEGORY_CONTAINER: '[data-region=\"existing-category-container\"]',\n EXISTING_CATEGORY_TAB: '#id_existingcategoryheader',\n NEW_CATEGORY_CONTAINER: '[data-region=\"new-category-container\"]',\n NEW_CATEGORY_TAB: '#id_newcategoryheader',\n TAB_CONTENT: '[data-region=\"tab-content\"]',\n ADD_ON_PAGE_FORM_ELEMENT: '[name=\"addonpage\"]',\n ADD_RANDOM_BUTTON: 'input[type=\"submit\"][name=\"addrandom\"]',\n ADD_NEW_CATEGORY_BUTTON: 'input[type=\"submit\"][name=\"newcategory\"]',\n SUBMIT_BUTTON_ELEMENT: 'input[type=\"submit\"][name=\"addrandom\"], input[type=\"submit\"][name=\"newcategory\"]',\n FORM_HEADER: 'legend',\n SELECT_NUMBER_TO_ADD: '#menurandomcount',\n NEW_CATEGORY_ELEMENT: '#categoryname',\n PARENT_CATEGORY_ELEMENT: '#parentcategory',\n FILTER_CONDITION_ELEMENT: '[data-filtercondition]',\n FORM_ELEMENT: '#add_random_question_form',\n MESSAGE_INPUT: '[name=\"message\"]',\n};\n\nexport default class ModalAddRandomQuestion extends Modal {\n static TYPE = 'mod_quiz-quiz-add-random-question';\n static TEMPLATE = 'mod_quiz/modal_add_random_question';\n\n /**\n * Create the add random question modal.\n *\n * @param {Number} contextId Current context id.\n * @param {string} category Category id and category context id comma separated.\n * @param {string} returnUrl URL to return to after form submission.\n * @param {Number} cmid Current course module id.\n * @param {boolean} showNewCategory Display the New category tab when selecting random questions.\n */\n static init(contextId, category, returnUrl, cmid, showNewCategory = true) {\n const selector = '.menu [data-action=\"addarandomquestion\"]';\n document.addEventListener('click', (e) => {\n const trigger = e.target.closest(selector);\n if (!trigger) {\n return;\n }\n e.preventDefault();\n\n ModalAddRandomQuestion.create({\n contextId,\n category,\n returnUrl,\n cmid,\n\n title: trigger.dataset.header,\n addOnPage: trigger.dataset.addonpage,\n\n templateContext: {\n hidden: showNewCategory,\n },\n });\n });\n }\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n constructor(root) {\n super(root);\n this.category = null;\n this.returnUrl = null;\n this.cmid = null;\n this.loadedForm = false;\n }\n\n configure(modalConfig) {\n modalConfig.removeOnClose = true;\n\n this.setCategory(modalConfig.category);\n this.setReturnUrl(modalConfig.returnUrl);\n this.setCMID(modalConfig.cmid);\n\n super.configure(modalConfig);\n }\n\n /**\n * Set the id of the page that the question should be added to\n * when the user clicks the add to quiz link.\n *\n * @method setAddOnPageId\n * @param {int} id\n */\n setAddOnPageId(id) {\n super.setAddOnPageId(id);\n this.getBody().find(SELECTORS.ADD_ON_PAGE_FORM_ELEMENT).val(id);\n }\n\n /**\n * Set the category for this form. The category is a comma separated\n * category id and category context id.\n *\n * @method setCategory\n * @param {string} category\n */\n setCategory(category) {\n this.category = category;\n }\n\n /**\n * Returns the saved category.\n *\n * @method getCategory\n * @return {string}\n */\n getCategory() {\n return this.category;\n }\n\n /**\n * Set the return URL for the form.\n *\n * @method setReturnUrl\n * @param {string} url\n */\n setReturnUrl(url) {\n this.returnUrl = url;\n }\n\n /**\n * Returns the return URL for the form.\n *\n * @method getReturnUrl\n * @return {string}\n */\n getReturnUrl() {\n return this.returnUrl;\n }\n\n /**\n * Set the course module id for the form.\n *\n * @method setCMID\n * @param {Number} id\n */\n setCMID(id) {\n this.cmid = id;\n }\n\n /**\n * Returns the course module id for the form.\n *\n * @method getCMID\n * @return {Number}\n */\n getCMID() {\n return this.cmid;\n }\n\n /**\n * Moves a given form element inside (a child of) a given tab element.\n *\n * Hides the 'legend' (e.g. header) element of the form element because the\n * tab has the name.\n *\n * Moves the submit button into a footer element at the bottom of the form\n * element for styling purposes.\n *\n * @method moveContentIntoTab\n * @param {jquery} tabContent The form element to move into the tab.\n * @param {jquey} tabElement The tab element for the form element to move into.\n */\n moveContentIntoTab(tabContent, tabElement) {\n // Hide the header because the tabs show us which part of the form we're\n // looking at.\n tabContent.find(SELECTORS.FORM_HEADER).addClass('hidden');\n // Move the element inside a tab.\n tabContent.wrap(tabElement);\n }\n\n /**\n * Empty the tab content container and move all tabs from the form into the\n * tab container element.\n *\n * @method moveTabsIntoTabContent\n * @param {jquery} form The form element.\n */\n moveTabsIntoTabContent(form) {\n // Empty it to remove the loading icon.\n const tabContent = this.getBody().find(SELECTORS.TAB_CONTENT).empty();\n // Make sure all tabs are inside the tab content element.\n form.find('[role=\"tabpanel\"]').wrapAll(tabContent);\n }\n\n /**\n * Make sure all of the tabs have a cancel button in their fotter to sit along\n * side the submit button.\n *\n * @method moveCancelButtonToTabs\n * @param {jquey} form The form element.\n */\n moveCancelButtonToTabs(form) {\n const cancelButton = form.find(SELECTORS.CANCEL_BUTTON_ELEMENT).addClass('ml-1');\n const tabFooters = form.find('[data-region=\"footer\"]');\n // Remove the buttons container element.\n cancelButton.closest(SELECTORS.BUTTON_CONTAINER).remove();\n cancelButton.clone().appendTo(tabFooters);\n }\n\n /**\n * Load the add random question form in a fragement and perform some transformation\n * on the HTML to convert it into tabs for rendering in the modal.\n *\n * @method loadForm\n * @return {promise} Resolved with form HTML and JS.\n */\n loadForm() {\n const cmid = this.getCMID();\n const cat = this.getCategory();\n const addonpage = this.getAddOnPageId();\n const returnurl = this.getReturnUrl();\n\n return Fragment.loadFragment(\n 'mod_quiz',\n 'add_random_question_form',\n this.getContextId(),\n {\n addonpage,\n cat,\n returnurl,\n cmid,\n }\n )\n .then((html, js) =>{\n const form = $(html);\n const existingCategoryTabContent = form.find(SELECTORS.EXISTING_CATEGORY_TAB);\n const existingCategoryTab = this.getBody().find(SELECTORS.EXISTING_CATEGORY_CONTAINER);\n const newCategoryTabContent = form.find(SELECTORS.NEW_CATEGORY_TAB);\n const newCategoryTab = this.getBody().find(SELECTORS.NEW_CATEGORY_CONTAINER);\n\n // Transform the form into tabs for better rendering in the modal.\n this.moveContentIntoTab(existingCategoryTabContent, existingCategoryTab);\n this.moveContentIntoTab(newCategoryTabContent, newCategoryTab);\n this.moveTabsIntoTabContent(form);\n\n Templates.replaceNode(this.getBody().find(SELECTORS.TAB_CONTENT), form, js);\n return;\n })\n .then(() => {\n // Make sure the form change checker is disabled otherwise it'll stop the user from navigating away from the\n // page once the modal is hidden.\n FormChangeChecker.disableAllChecks();\n\n // Add question to quiz.\n this.getBody()[0].addEventListener('click', (e) => {\n const button = e.target.closest(SELECTORS.SUBMIT_BUTTON_ELEMENT);\n if (!button) {\n return;\n }\n e.preventDefault();\n\n // Add Random questions if the add random button was clicked.\n const addRandomButton = e.target.closest(SELECTORS.ADD_RANDOM_BUTTON);\n if (addRandomButton) {\n const randomcount = document.querySelector(SELECTORS.SELECT_NUMBER_TO_ADD).value;\n const filtercondition = document.querySelector(SELECTORS.FILTER_CONDITION_ELEMENT).dataset?.filtercondition;\n\n this.addQuestions(cmid, addonpage, randomcount, filtercondition, '', '');\n return;\n }\n // Add new category if the add category button was clicked.\n const addCategoryButton = e.target.closest(SELECTORS.ADD_NEW_CATEGORY_BUTTON);\n if (addCategoryButton) {\n this.addQuestions(\n cmid,\n addonpage,\n 1,\n '',\n document.querySelector(SELECTORS.NEW_CATEGORY_ELEMENT).value,\n document.querySelector(SELECTORS.PARENT_CATEGORY_ELEMENT).value\n );\n return;\n }\n });\n })\n .catch(Notification.exception);\n }\n\n /**\n * Call web service function to add random questions\n *\n * @param {number} cmid course module id\n * @param {number} addonpage the page where random questions will be added to\n * @param {number} randomcount Number of random questions\n * @param {string} filtercondition Filter condition\n * @param {string} newcategory add new category\n * @param {string} parentcategory parent category of new category\n */\n async addQuestions(\n cmid,\n addonpage,\n randomcount,\n filtercondition,\n newcategory,\n parentcategory\n ) {\n // We do not need to resolve this Pending because the form submission will result in a page redirect.\n new Pending('mod-quiz/modal_add_random_questions');\n const call = {\n methodname: 'mod_quiz_add_random_questions',\n args: {\n cmid,\n addonpage,\n randomcount,\n filtercondition,\n newcategory,\n parentcategory,\n }\n };\n try {\n const response = await fetchMany([call])[0];\n const form = document.querySelector(SELECTORS.FORM_ELEMENT);\n const messageInput = form.querySelector(SELECTORS.MESSAGE_INPUT);\n messageInput.value = response.message;\n form.submit();\n } catch (e) {\n Notification.exception(e);\n }\n }\n\n /**\n * Override the modal show function to load the form when this modal is first\n * shown.\n *\n * @method show\n */\n show() {\n super.show(this);\n\n if (!this.loadedForm) {\n this.loadForm(window.location.search);\n this.loadedForm = true;\n }\n }\n}\n\nModalAddRandomQuestion.registerModalType();\n"],"names":["SELECTORS","EXISTING_CATEGORY_CONTAINER","EXISTING_CATEGORY_TAB","NEW_CATEGORY_CONTAINER","NEW_CATEGORY_TAB","TAB_CONTENT","ADD_ON_PAGE_FORM_ELEMENT","ADD_RANDOM_BUTTON","ADD_NEW_CATEGORY_BUTTON","SUBMIT_BUTTON_ELEMENT","FORM_HEADER","SELECT_NUMBER_TO_ADD","NEW_CATEGORY_ELEMENT","PARENT_CATEGORY_ELEMENT","FILTER_CONDITION_ELEMENT","FORM_ELEMENT","MESSAGE_INPUT","ModalAddRandomQuestion","Modal","contextId","category","returnUrl","cmid","showNewCategory","document","addEventListener","e","trigger","target","closest","preventDefault","create","title","dataset","header","addOnPage","addonpage","templateContext","hidden","constructor","root","loadedForm","configure","modalConfig","removeOnClose","setCategory","setReturnUrl","setCMID","setAddOnPageId","id","getBody","find","val","getCategory","this","url","getReturnUrl","getCMID","moveContentIntoTab","tabContent","tabElement","addClass","wrap","moveTabsIntoTabContent","form","empty","wrapAll","moveCancelButtonToTabs","cancelButton","CANCEL_BUTTON_ELEMENT","tabFooters","BUTTON_CONTAINER","remove","clone","appendTo","loadForm","cat","getAddOnPageId","returnurl","Fragment","loadFragment","getContextId","then","html","js","existingCategoryTabContent","existingCategoryTab","newCategoryTabContent","newCategoryTab","Templates","replaceNode","FormChangeChecker","disableAllChecks","randomcount","querySelector","value","filtercondition","_document$querySelect","addQuestions","catch","Notification","exception","newcategory","parentcategory","Pending","call","methodname","args","response","message","submit","show","window","location","search","registerModalType"],"mappings":"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"} \ No newline at end of file diff --git a/mod/quiz/amd/src/add_question_modal.js b/mod/quiz/amd/src/add_question_modal.js index 2947d7cf9dd..466883dcbd4 100644 --- a/mod/quiz/amd/src/add_question_modal.js +++ b/mod/quiz/amd/src/add_question_modal.js @@ -30,6 +30,7 @@ export default class AddQuestionModal extends Modal { // Always show on creation. modalConfig.show = true; + modalConfig.removeOnClose = true; // Apply question modal configuration. this.setContextId(modalConfig.contextId); diff --git a/mod/quiz/amd/src/modal_add_random_question.js b/mod/quiz/amd/src/modal_add_random_question.js index 151e81316d6..2f8e8ea250f 100644 --- a/mod/quiz/amd/src/modal_add_random_question.js +++ b/mod/quiz/amd/src/modal_add_random_question.js @@ -101,6 +101,8 @@ export default class ModalAddRandomQuestion extends Modal { } configure(modalConfig) { + modalConfig.removeOnClose = true; + this.setCategory(modalConfig.category); this.setReturnUrl(modalConfig.returnUrl); this.setCMID(modalConfig.cmid); diff --git a/mod/quiz/tests/behat/editing_add_from_question_bank.feature b/mod/quiz/tests/behat/editing_add_from_question_bank.feature index 096f30995f2..e5671404278 100644 --- a/mod/quiz/tests/behat/editing_add_from_question_bank.feature +++ b/mod/quiz/tests/behat/editing_add_from_question_bank.feature @@ -81,6 +81,26 @@ Feature: Adding questions to a quiz from the question bank And I should see "Feature question 5" And I should see "Feature question 9" + Scenario: After closing and reopening the modal, it still works + Given the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | My collection | + And the following "question" exists: + | questioncategory | My collection | + | qtype | essay | + | name | Feature question | + | questiontext | Write about topic | + | user | teacher1 | + When I am on the "Quiz 1" "mod_quiz > Edit" page logged in as teacher1 + And I open the "last" add to quiz menu + And I follow "from question bank" + And I click on "Close" "button" in the "Add from the question bank at the end" "dialogue" + And I open the "last" add to quiz menu + And I follow "from question bank" + And I set the field "Category" to "My collection" + And I press "Apply filters" + Then I should see "Feature question" + Scenario: Questions are added in the right place with multiple sections Given the following "questions" exist: | questioncategory | qtype | name | questiontext | diff --git a/mod/quiz/tests/behat/editing_add_random.feature b/mod/quiz/tests/behat/editing_add_random.feature index f62410480f5..7dc16b6dcb4 100644 --- a/mod/quiz/tests/behat/editing_add_random.feature +++ b/mod/quiz/tests/behat/editing_add_random.feature @@ -84,6 +84,18 @@ Feature: Adding random questions to a quiz based on category and tags And I should see "question 1 name" And I should see "\"listen\" & \"answer\"" + Scenario: After closing and reopening the modal, it still works + When I am on the "Quiz 1" "mod_quiz > Edit" page logged in as teacher1 + And I open the "last" add to quiz menu + And I follow "a random question" + And I click on "Close" "button" in the "Add a random question at the end" "dialogue" + And I open the "last" add to quiz menu + And I follow "a random question" + And I should not see "question 3 name" + And I set the field "Category" to "Subcategory" + And I press "Apply filters" + Then I should see "question 3 name" + Scenario: Teacher without moodle/question:useall should not see the add a random question menu item Given the following "permission overrides" exist: | capability | permission | role | contextlevel | reference |