From 9a03bf7e9bfd8f5d61c4170501e70ff0c5658d9a Mon Sep 17 00:00:00 2001 From: Odei Alba Date: Fri, 19 Apr 2024 17:43:24 +0200 Subject: [PATCH] SV-60 Change behaviour so once the student has voted, they are taken automatically to the results screen --- amd/build/sortvoting.min.js | 2 +- amd/build/sortvoting.min.js.map | 2 +- amd/src/sortvoting.js | 6 +++--- classes/external/save_vote.php | 17 ++++++++++++----- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/amd/build/sortvoting.min.js b/amd/build/sortvoting.min.js index f45ccd8..2f30dd6 100644 --- a/amd/build/sortvoting.min.js +++ b/amd/build/sortvoting.min.js @@ -5,6 +5,6 @@ define("mod_sortvoting/sortvoting",["exports","core/notification","core/ajax","c * @module mod_sortvoting/sortvoting * @copyright 2023 Odei Alba * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){new _sortable_list.default("#sortvotinglist",{moveHandlerSelector:".optionitem"}),(0,_jquery.default)("ul#sortvotinglist > *").on(_sortable_list.default.EVENTS.DROP,(function(evt,info){if(info.positionChanged)for(var lis=info.sourceList[0].getElementsByTagName("li"),i=0;i{const saveSortVoteElement=event.target.closest(SELECTORS_SAVEVOTE);saveSortVoteElement&&(event.preventDefault(),function(saveSortVoteElement){saveSortVoteElement.setAttribute("disabled",!0);var sortvotingid=document.getElementsByName("sortvotingid")[0].value,options=document.getElementsByName("option[]"),votes=[],positions=[];if(options.forEach((function(option){positions.push(option.value),votes.push({position:option.value,optionid:option.getAttribute("data-optionid")})})),new Set(positions).size!==positions.length)return(0,_toast.add)((0,_str.get_string)("errorduplicatedposition","mod_sortvoting"),{type:"danger"}),void saveSortVoteElement.removeAttribute("disabled");_ajax.default.call([{methodname:"mod_sortvoting_save_vote",args:{sortvotingid:sortvotingid,votes:votes}}])[0].done((function(result){result.success?(0,_toast.add)((0,_str.get_string)("votesuccess","mod_sortvoting"),{type:"success"}):(0,_toast.add)((0,_str.get_string)("voteerror","mod_sortvoting"),{type:"danger"}),result.seeresultsupdated?window.location.reload():result.allowupdate?saveSortVoteElement.removeAttribute("disabled"):(saveSortVoteElement.style.display="none",(0,_jquery.default)("ul#sortvotinglist > li.optionitem").each((function(index,element){element.classList.remove("optionitem","draggable"),element.classList.add("bg-gray-100"),element.removeAttribute("draggable"),element.removeAttribute("data-drag-type")})))})).fail(_notification.default.exception)}(saveSortVoteElement))}))},_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax),_sortable_list=_interopRequireDefault(_sortable_list),_jquery=_interopRequireDefault(_jquery);const SELECTORS_SAVEVOTE="[data-action='savevote']"})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){new _sortable_list.default("#sortvotinglist",{moveHandlerSelector:".optionitem"}),(0,_jquery.default)("ul#sortvotinglist > *").on(_sortable_list.default.EVENTS.DROP,(function(evt,info){if(info.positionChanged)for(var lis=info.sourceList[0].getElementsByTagName("li"),i=0;i{const saveSortVoteElement=event.target.closest(SELECTORS_SAVEVOTE);saveSortVoteElement&&(event.preventDefault(),function(saveSortVoteElement){saveSortVoteElement.setAttribute("disabled",!0);var sortvotingid=document.getElementsByName("sortvotingid")[0].value,options=document.getElementsByName("option[]"),votes=[],positions=[];if(options.forEach((function(option){positions.push(option.value),votes.push({position:option.value,optionid:option.getAttribute("data-optionid")})})),new Set(positions).size!==positions.length)return(0,_toast.add)((0,_str.get_string)("errorduplicatedposition","mod_sortvoting"),{type:"danger"}),void saveSortVoteElement.removeAttribute("disabled");_ajax.default.call([{methodname:"mod_sortvoting_save_vote",args:{sortvotingid:sortvotingid,votes:votes}}])[0].done((function(result){result.success?(0,_toast.add)((0,_str.get_string)("votesuccess","mod_sortvoting"),{type:"success"}):(0,_toast.add)((0,_str.get_string)("voteerror","mod_sortvoting"),{type:"danger"}),result.canseeresults?window.location.href=result.redirecturl:result.allowupdate?saveSortVoteElement.removeAttribute("disabled"):(saveSortVoteElement.style.display="none",(0,_jquery.default)("ul#sortvotinglist > li.optionitem").each((function(index,element){element.classList.remove("optionitem","draggable"),element.classList.add("bg-gray-100"),element.removeAttribute("draggable"),element.removeAttribute("data-drag-type")})))})).fail(_notification.default.exception)}(saveSortVoteElement))}))},_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax),_sortable_list=_interopRequireDefault(_sortable_list),_jquery=_interopRequireDefault(_jquery);const SELECTORS_SAVEVOTE="[data-action='savevote']"})); //# sourceMappingURL=sortvoting.min.js.map \ No newline at end of file diff --git a/amd/build/sortvoting.min.js.map b/amd/build/sortvoting.min.js.map index 549464a..125e196 100644 --- a/amd/build/sortvoting.min.js.map +++ b/amd/build/sortvoting.min.js.map @@ -1 +1 @@ -{"version":3,"file":"sortvoting.min.js","sources":["../src/sortvoting.js"],"sourcesContent":["// This file is part of the mod_sortvoting plugin for 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 * AMD module used when saving a new sort voting.\n *\n * @module mod_sortvoting/sortvoting\n * @copyright 2023 Odei Alba \n * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Notification from 'core/notification';\nimport Ajax from 'core/ajax';\nimport SortableList from 'core/sortable_list';\nimport {add as toastAdd} from 'core/toast';\nimport jQuery from 'jquery';\nimport {get_string as getString} from 'core/str';\n\nconst SELECTORS = {\n SAVEVOTE: \"[data-action='savevote']\"\n};\n\n/**\n * Save sort vote.\n * @param {Element} saveSortVoteElement\n */\nconst saveVote = function(saveSortVoteElement) {\n saveSortVoteElement.setAttribute('disabled', true);\n var sortvotingid = document.getElementsByName('sortvotingid')[0].value;\n var options = document.getElementsByName('option[]');\n\n // Build votes and positions arrays for later processing.\n var votes = [];\n var positions = [];\n options.forEach(function(option) {\n positions.push(option.value);\n votes.push({\n 'position': option.value,\n 'optionid': option.getAttribute('data-optionid')\n });\n });\n\n // Check if all elements of the positions array are unique.\n if (new Set(positions).size !== positions.length) {\n toastAdd(getString('errorduplicatedposition', 'mod_sortvoting'), {type: 'danger'});\n saveSortVoteElement.removeAttribute('disabled');\n return;\n }\n\n // Save vote.\n var promises = Ajax.call([\n {methodname: 'mod_sortvoting_save_vote', args: {sortvotingid: sortvotingid, votes: votes}}\n ]);\n promises[0].done(function(result) {\n if (result.success) {\n toastAdd(getString('votesuccess', 'mod_sortvoting'), {type: 'success'});\n } else {\n toastAdd(getString('voteerror', 'mod_sortvoting'), {type: 'danger'});\n }\n if (result.seeresultsupdated) {\n // Reload the whole page so the results tab is visible now but wasn't before (or viceversa).\n window.location.reload();\n } else if (result.allowupdate) {\n saveSortVoteElement.removeAttribute('disabled');\n } else {\n saveSortVoteElement.style.display = 'none';\n jQuery('ul#sortvotinglist > li.optionitem').each(function(index, element) {\n element.classList.remove('optionitem', 'draggable');\n element.classList.add('bg-gray-100');\n element.removeAttribute('draggable');\n element.removeAttribute('data-drag-type');\n });\n }\n }).fail(Notification.exception);\n};\n\n/**\n * Sets up sortable list in the column sort order page.\n */\nconst setupSortableLists = () => {\n new SortableList('#sortvotinglist', {\n moveHandlerSelector: '.optionitem',\n });\n // Listen to the events when element is dragged.\n jQuery('ul#sortvotinglist > *').on(SortableList.EVENTS.DROP, function(evt, info) {\n if (info.positionChanged) {\n // Get the ul element and loop into the li elements.\n var list = info.sourceList[0];\n var lis = list.getElementsByTagName('li');\n for (var i = 0; i < lis.length; i++) {\n // Set the value of the input to the position of the li element.\n lis[i].getElementsByTagName('input')[0].value = i + 1;\n }\n }\n });\n};\n\n/**\n * Init page\n */\nexport function init() {\n setupSortableLists();\n document.addEventListener('click', event => {\n\n // Save sort vote.\n const saveSortVoteElement = event.target.closest(SELECTORS.SAVEVOTE);\n if (saveSortVoteElement) {\n event.preventDefault();\n saveVote(saveSortVoteElement);\n }\n });\n}\n"],"names":["SortableList","moveHandlerSelector","on","EVENTS","DROP","evt","info","positionChanged","lis","sourceList","getElementsByTagName","i","length","value","document","addEventListener","event","saveSortVoteElement","target","closest","SELECTORS","preventDefault","setAttribute","sortvotingid","getElementsByName","options","votes","positions","forEach","option","push","getAttribute","Set","size","type","removeAttribute","Ajax","call","methodname","args","done","result","success","seeresultsupdated","window","location","reload","allowupdate","style","display","each","index","element","classList","remove","add","fail","Notification","exception","saveVote"],"mappings":";;;;;;;0FA4FQA,uBAAa,kBAAmB,CAChCC,oBAAqB,oCAGlB,yBAAyBC,GAAGF,uBAAaG,OAAOC,MAAM,SAASC,IAAKC,SACnEA,KAAKC,wBAGDC,IADOF,KAAKG,WAAW,GACZC,qBAAqB,MAC3BC,EAAI,EAAGA,EAAIH,IAAII,OAAQD,IAE5BH,IAAIG,GAAGD,qBAAqB,SAAS,GAAGG,MAAQF,EAAI,KAWhEG,SAASC,iBAAiB,SAASC,cAGzBC,oBAAsBD,MAAME,OAAOC,QAAQC,oBAC7CH,sBACAD,MAAMK,iBAjFD,SAASJ,qBACtBA,oBAAoBK,aAAa,YAAY,OACzCC,aAAeT,SAASU,kBAAkB,gBAAgB,GAAGX,MAC7DY,QAAUX,SAASU,kBAAkB,YAGrCE,MAAQ,GACRC,UAAY,MAChBF,QAAQG,SAAQ,SAASC,QACrBF,UAAUG,KAAKD,OAAOhB,OACtBa,MAAMI,KAAK,UACKD,OAAOhB,eACPgB,OAAOE,aAAa,sBAKpC,IAAIC,IAAIL,WAAWM,OAASN,UAAUf,6BAC7B,mBAAU,0BAA2B,kBAAmB,CAACsB,KAAM,gBACxEjB,oBAAoBkB,gBAAgB,YAKzBC,cAAKC,KAAK,CACrB,CAACC,WAAY,2BAA4BC,KAAM,CAAChB,aAAcA,aAAcG,MAAOA,UAE9E,GAAGc,MAAK,SAASC,QAClBA,OAAOC,wBACE,mBAAU,cAAe,kBAAmB,CAACR,KAAM,4BAEnD,mBAAU,YAAa,kBAAmB,CAACA,KAAM,WAE1DO,OAAOE,kBAEPC,OAAOC,SAASC,SACTL,OAAOM,YACd9B,oBAAoBkB,gBAAgB,aAEpClB,oBAAoB+B,MAAMC,QAAU,2BAC7B,qCAAqCC,MAAK,SAASC,MAAOC,SAC7DA,QAAQC,UAAUC,OAAO,aAAc,aACvCF,QAAQC,UAAUE,IAAI,eACtBH,QAAQjB,gBAAgB,aACxBiB,QAAQjB,gBAAgB,yBAGjCqB,KAAKC,sBAAaC,WAmCbC,CAAS1C,sNA1FfG,mBACQ"} \ No newline at end of file +{"version":3,"file":"sortvoting.min.js","sources":["../src/sortvoting.js"],"sourcesContent":["// This file is part of the mod_sortvoting plugin for 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 * AMD module used when saving a new sort voting.\n *\n * @module mod_sortvoting/sortvoting\n * @copyright 2023 Odei Alba \n * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Notification from 'core/notification';\nimport Ajax from 'core/ajax';\nimport SortableList from 'core/sortable_list';\nimport {add as toastAdd} from 'core/toast';\nimport jQuery from 'jquery';\nimport {get_string as getString} from 'core/str';\n\nconst SELECTORS = {\n SAVEVOTE: \"[data-action='savevote']\"\n};\n\n/**\n * Save sort vote.\n * @param {Element} saveSortVoteElement\n */\nconst saveVote = function(saveSortVoteElement) {\n saveSortVoteElement.setAttribute('disabled', true);\n var sortvotingid = document.getElementsByName('sortvotingid')[0].value;\n var options = document.getElementsByName('option[]');\n\n // Build votes and positions arrays for later processing.\n var votes = [];\n var positions = [];\n options.forEach(function(option) {\n positions.push(option.value);\n votes.push({\n 'position': option.value,\n 'optionid': option.getAttribute('data-optionid')\n });\n });\n\n // Check if all elements of the positions array are unique.\n if (new Set(positions).size !== positions.length) {\n toastAdd(getString('errorduplicatedposition', 'mod_sortvoting'), {type: 'danger'});\n saveSortVoteElement.removeAttribute('disabled');\n return;\n }\n\n // Save vote.\n var promises = Ajax.call([\n {methodname: 'mod_sortvoting_save_vote', args: {sortvotingid: sortvotingid, votes: votes}}\n ]);\n promises[0].done(function(result) {\n if (result.success) {\n toastAdd(getString('votesuccess', 'mod_sortvoting'), {type: 'success'});\n } else {\n toastAdd(getString('voteerror', 'mod_sortvoting'), {type: 'danger'});\n }\n if (result.canseeresults) {\n // If the user can see the results, redirect to the results page. Otherwise, reload the page.\n window.location.href = result.redirecturl;\n } else if (result.allowupdate) {\n saveSortVoteElement.removeAttribute('disabled');\n } else {\n saveSortVoteElement.style.display = 'none';\n jQuery('ul#sortvotinglist > li.optionitem').each(function(index, element) {\n element.classList.remove('optionitem', 'draggable');\n element.classList.add('bg-gray-100');\n element.removeAttribute('draggable');\n element.removeAttribute('data-drag-type');\n });\n }\n }).fail(Notification.exception);\n};\n\n/**\n * Sets up sortable list in the column sort order page.\n */\nconst setupSortableLists = () => {\n new SortableList('#sortvotinglist', {\n moveHandlerSelector: '.optionitem',\n });\n // Listen to the events when element is dragged.\n jQuery('ul#sortvotinglist > *').on(SortableList.EVENTS.DROP, function(evt, info) {\n if (info.positionChanged) {\n // Get the ul element and loop into the li elements.\n var list = info.sourceList[0];\n var lis = list.getElementsByTagName('li');\n for (var i = 0; i < lis.length; i++) {\n // Set the value of the input to the position of the li element.\n lis[i].getElementsByTagName('input')[0].value = i + 1;\n }\n }\n });\n};\n\n/**\n * Init page\n */\nexport function init() {\n setupSortableLists();\n document.addEventListener('click', event => {\n\n // Save sort vote.\n const saveSortVoteElement = event.target.closest(SELECTORS.SAVEVOTE);\n if (saveSortVoteElement) {\n event.preventDefault();\n saveVote(saveSortVoteElement);\n }\n });\n}\n"],"names":["SortableList","moveHandlerSelector","on","EVENTS","DROP","evt","info","positionChanged","lis","sourceList","getElementsByTagName","i","length","value","document","addEventListener","event","saveSortVoteElement","target","closest","SELECTORS","preventDefault","setAttribute","sortvotingid","getElementsByName","options","votes","positions","forEach","option","push","getAttribute","Set","size","type","removeAttribute","Ajax","call","methodname","args","done","result","success","canseeresults","window","location","href","redirecturl","allowupdate","style","display","each","index","element","classList","remove","add","fail","Notification","exception","saveVote"],"mappings":";;;;;;;0FA4FQA,uBAAa,kBAAmB,CAChCC,oBAAqB,oCAGlB,yBAAyBC,GAAGF,uBAAaG,OAAOC,MAAM,SAASC,IAAKC,SACnEA,KAAKC,wBAGDC,IADOF,KAAKG,WAAW,GACZC,qBAAqB,MAC3BC,EAAI,EAAGA,EAAIH,IAAII,OAAQD,IAE5BH,IAAIG,GAAGD,qBAAqB,SAAS,GAAGG,MAAQF,EAAI,KAWhEG,SAASC,iBAAiB,SAASC,cAGzBC,oBAAsBD,MAAME,OAAOC,QAAQC,oBAC7CH,sBACAD,MAAMK,iBAjFD,SAASJ,qBACtBA,oBAAoBK,aAAa,YAAY,OACzCC,aAAeT,SAASU,kBAAkB,gBAAgB,GAAGX,MAC7DY,QAAUX,SAASU,kBAAkB,YAGrCE,MAAQ,GACRC,UAAY,MAChBF,QAAQG,SAAQ,SAASC,QACrBF,UAAUG,KAAKD,OAAOhB,OACtBa,MAAMI,KAAK,UACKD,OAAOhB,eACPgB,OAAOE,aAAa,sBAKpC,IAAIC,IAAIL,WAAWM,OAASN,UAAUf,6BAC7B,mBAAU,0BAA2B,kBAAmB,CAACsB,KAAM,gBACxEjB,oBAAoBkB,gBAAgB,YAKzBC,cAAKC,KAAK,CACrB,CAACC,WAAY,2BAA4BC,KAAM,CAAChB,aAAcA,aAAcG,MAAOA,UAE9E,GAAGc,MAAK,SAASC,QAClBA,OAAOC,wBACE,mBAAU,cAAe,kBAAmB,CAACR,KAAM,4BAEnD,mBAAU,YAAa,kBAAmB,CAACA,KAAM,WAE1DO,OAAOE,cAEPC,OAAOC,SAASC,KAAOL,OAAOM,YACvBN,OAAOO,YACd/B,oBAAoBkB,gBAAgB,aAEpClB,oBAAoBgC,MAAMC,QAAU,2BAC7B,qCAAqCC,MAAK,SAASC,MAAOC,SAC7DA,QAAQC,UAAUC,OAAO,aAAc,aACvCF,QAAQC,UAAUE,IAAI,eACtBH,QAAQlB,gBAAgB,aACxBkB,QAAQlB,gBAAgB,yBAGjCsB,KAAKC,sBAAaC,WAmCbC,CAAS3C,sNA1FfG,mBACQ"} \ No newline at end of file diff --git a/amd/src/sortvoting.js b/amd/src/sortvoting.js index 046b860..1ee9180 100644 --- a/amd/src/sortvoting.js +++ b/amd/src/sortvoting.js @@ -69,9 +69,9 @@ const saveVote = function(saveSortVoteElement) { } else { toastAdd(getString('voteerror', 'mod_sortvoting'), {type: 'danger'}); } - if (result.seeresultsupdated) { - // Reload the whole page so the results tab is visible now but wasn't before (or viceversa). - window.location.reload(); + if (result.canseeresults) { + // If the user can see the results, redirect to the results page. Otherwise, reload the page. + window.location.href = result.redirecturl; } else if (result.allowupdate) { saveSortVoteElement.removeAttribute('disabled'); } else { diff --git a/classes/external/save_vote.php b/classes/external/save_vote.php index 9aeb1a8..5bcc547 100644 --- a/classes/external/save_vote.php +++ b/classes/external/save_vote.php @@ -23,6 +23,7 @@ use external_single_structure; use external_value; use moodle_exception; +use moodle_url; defined('MOODLE_INTERNAL') || die; require_once($CFG->dirroot . '/mod/sortvoting/lib.php'); @@ -79,16 +80,17 @@ public static function execute($sortvotingid, $votes) { $context = \context_module::instance($cm->id); self::validate_context($context); \mod_sortvoting\permission::require_can_vote($context); - $canseeresultsold = \mod_sortvoting\permission::can_see_results($sortvoting, $context); sortvoting_user_submit_response($sortvoting, $params['votes'], $course, $cm); - $canseeresultsnew = \mod_sortvoting\permission::can_see_results($sortvoting, $context); + $canseeresults = \mod_sortvoting\permission::can_see_results($sortvoting, $context); + $redirecturl = $canseeresults ? '/mod/sortvoting/report.php' : '/mod/sortvoting/view.php'; return [ 'success' => true, 'allowupdate' => (bool) $sortvoting->allowupdate, - 'seeresultsupdated' => (bool) $canseeresultsold !== $canseeresultsnew, + 'canseeresults' => (bool) $canseeresults, + 'redirecturl' => (new moodle_url($redirecturl, ['id' => $cm->id]))->out(), ]; } @@ -102,9 +104,14 @@ public static function execute_returns() { [ 'success' => new external_value(PARAM_BOOL, 'Returns true on successful vote submision or throws an error'), 'allowupdate' => new external_value(PARAM_BOOL, 'Returns true if vote can be updated', VALUE_REQUIRED), - 'seeresultsupdated' => new external_value( + 'canseeresults' => new external_value( PARAM_BOOL, - 'Returns true if the user could not see the results and can see them now (or viceversa)', + 'Returns true if the user can see the results of the vote', + VALUE_REQUIRED + ), + 'redirecturl' => new external_value( + PARAM_URL, + 'Redirect URL to the results or the vote page', VALUE_REQUIRED ), ]