diff --git a/amd/build/sortvoting.min.js b/amd/build/sortvoting.min.js index e084524..d2f1295 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/issues-list * @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.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.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']"})); //# 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 35d62bc..4aca001 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/issues-list\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.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","allowupdate","style","display","each","index","element","classList","remove","add","fail","Notification","exception","saveVote"],"mappings":";;;;;;;0FAyFQA,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,iBA9ED,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,YACP1B,oBAAoBkB,gBAAgB,aAEpClB,oBAAoB2B,MAAMC,QAAU,2BAC7B,qCAAqCC,MAAK,SAASC,MAAOC,SAC7DA,QAAQC,UAAUC,OAAO,aAAc,aACvCF,QAAQC,UAAUE,IAAI,eACtBH,QAAQb,gBAAgB,aACxBa,QAAQb,gBAAgB,yBAGjCiB,KAAKC,sBAAaC,WAmCbC,CAAStC,sNAvFfG,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/issues-list\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,SACRL,OAAOM,YACf9B,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 diff --git a/amd/src/sortvoting.js b/amd/src/sortvoting.js index 8b1934a..452e635 100644 --- a/amd/src/sortvoting.js +++ b/amd/src/sortvoting.js @@ -69,7 +69,10 @@ const saveVote = function(saveSortVoteElement) { } else { toastAdd(getString('voteerror', 'mod_sortvoting'), {type: 'danger'}); } - if (result.allowupdate) { + if (result.seeresultsupdated) { + // Reload the whole page so the results tab is visible now but wasn't before (or viceversa). + window.location.reload(); + } else if (result.allowupdate) { saveSortVoteElement.removeAttribute('disabled'); } else { saveSortVoteElement.style.display = 'none'; diff --git a/classes/external/save_vote.php b/classes/external/save_vote.php index 21939e6..9aeb1a8 100644 --- a/classes/external/save_vote.php +++ b/classes/external/save_vote.php @@ -79,10 +79,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); - return ['success' => true, 'allowupdate' => (bool) $sortvoting->allowupdate]; + $canseeresultsnew = \mod_sortvoting\permission::can_see_results($sortvoting, $context); + + return [ + 'success' => true, + 'allowupdate' => (bool) $sortvoting->allowupdate, + 'seeresultsupdated' => (bool) $canseeresultsold !== $canseeresultsnew, + ]; } /** @@ -95,6 +102,11 @@ 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( + PARAM_BOOL, + 'Returns true if the user could not see the results and can see them now (or viceversa)', + VALUE_REQUIRED + ), ] ); } diff --git a/classes/permission.php b/classes/permission.php index 8437aef..0922ddb 100644 --- a/classes/permission.php +++ b/classes/permission.php @@ -42,4 +42,42 @@ public static function can_vote(\context_module $context): bool { public static function require_can_vote(\context_module $context) { require_capability('mod/sortvoting:vote', $context); } + + + /** + * User can see results. + * + * @param \stdClass $sortvoting + * @param \context_module $context + * @return bool + */ + public static function can_see_results(\stdClass $sortvoting, \context_module $context): bool { + global $DB, $USER; + + $existingvotes = $DB->get_records_menu( + 'sortvoting_answers', + [ + 'sortvotingid' => $sortvoting->id, + 'userid' => $USER->id, + ], + 'id ASC', + 'optionid, position' + ); + $studenthasvoted = !empty($existingvotes); + $allowstudentsseeresults = $sortvoting->allowstudentsseeresults ?? false; + + return has_capability('mod/sortvoting:readresponses', $context) || ($allowstudentsseeresults && $studenthasvoted); + } + + /** + * Make sure user can see results. + * + * @param \stdClass $sortvoting + * @param \context_module $context + */ + public static function require_can_see_results(\stdClass $sortvoting, \context_module $context) { + if (!self::can_see_results($sortvoting, $context)) { + throw new \moodle_exception('nopermissionstoseeresponses', 'mod_sortvoting'); + } + } } diff --git a/db/install.xml b/db/install.xml index 695622e..ebab4ab 100644 --- a/db/install.xml +++ b/db/install.xml @@ -10,6 +10,7 @@ + diff --git a/db/upgrade.php b/db/upgrade.php index 1fea79e..fd02004 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -39,5 +39,20 @@ function xmldb_sortvoting_upgrade($oldversion) { // You will also have to create the db/install.xml file by using the XMLDB Editor. // Documentation for the XMLDB Editor can be found at {@link https://docs.moodle.org/dev/XMLDB_editor}. + if ($oldversion < 2023101300) { + + // Define field allowstudentsseeresults to be added to sortvoting. + $table = new xmldb_table('sortvoting'); + $field = new xmldb_field('allowstudentsseeresults', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'allowupdate'); + + // Conditionally launch add field allowstudentsseeresults. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Sortvoting savepoint reached. + upgrade_mod_savepoint(true, 2023101300, 'sortvoting'); + } + return true; } diff --git a/lang/en/sortvoting.php b/lang/en/sortvoting.php index 04a1328..a508138 100644 --- a/lang/en/sortvoting.php +++ b/lang/en/sortvoting.php @@ -25,6 +25,8 @@ defined('MOODLE_INTERNAL') || die(); +$string['allowstudentsseeresults'] = 'Allow students to see the results'; +$string['allowstudentsseeresults_help'] = 'If enabled, users will be able to see the results once they have voted.'; $string['allowupdate'] = 'Allow options to be updated'; $string['allowupdate_help'] = 'If enabled, users will be able to update their votes once it is submitted. @@ -38,6 +40,7 @@ $string['instructions'] = 'Change the options below into the desired order, so your preferred choice is at the top and your least favourite choice is at the bottom.'; $string['modulename'] = 'Preference Sort Voting'; $string['modulenameplural'] = 'Preference Sort Votings'; +$string['nopermissionstoseeresponses'] = 'You do not have permissions to see the results'; $string['notenrolledsort'] = 'Sorry, only enrolled users are allowed to vote.'; $string['option'] = 'Option'; $string['optionno'] = 'Option {no}'; diff --git a/lib.php b/lib.php index 0e2aded..f55634d 100644 --- a/lib.php +++ b/lib.php @@ -540,8 +540,7 @@ function sortvoting_view($sortvoting, $course, $cm, $context) { * @return void */ function sortvoting_extend_settings_navigation($settings, $node) { - // TODO: SV-24 -> Check config to allow users see votes. Check if user has voted. - if (has_capability('mod/sortvoting:readresponses', $settings->get_page()->cm->context)) { + if (\mod_sortvoting\permission::can_see_results($settings->get_page()->activityrecord, $settings->get_page()->cm->context)) { // We want to add these new nodes after the Settings node. $keys = $node->get_children_key_list(); $beforekey = null; diff --git a/mod_form.php b/mod_form.php index 4fef22f..1436c42 100644 --- a/mod_form.php +++ b/mod_form.php @@ -70,6 +70,9 @@ public function definition() { $mform->addElement('selectyesno', 'allowupdate', get_string("allowupdate", "sortvoting")); $mform->addHelpButton('allowupdate', 'allowupdate', 'mod_sortvoting'); + $mform->addElement('selectyesno', 'allowstudentsseeresults', get_string("allowstudentsseeresults", "sortvoting")); + $mform->addHelpButton('allowstudentsseeresults', 'allowstudentsseeresults', 'mod_sortvoting'); + $repeatarray = []; $repeatarray[] = $mform->createElement('text', 'option', get_string('optionno', 'sortvoting')); $repeatarray[] = $mform->createElement('hidden', 'optionid', 0); diff --git a/report.php b/report.php index 85fd447..636126a 100644 --- a/report.php +++ b/report.php @@ -34,7 +34,7 @@ $modulecontext = context_module::instance($cm->id); require_login($course, true, $cm); -require_capability('mod/sortvoting:readresponses', $modulecontext); +\mod_sortvoting\permission::require_can_see_results($sortvoting, $modulecontext); $PAGE->set_url('/mod/sortvoting/report.php', ['id' => $cm->id]); $PAGE->set_title(format_string($sortvoting->name)); diff --git a/version.php b/version.php index 8f4cd68..61ae8f2 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ $plugin->component = 'mod_sortvoting'; $plugin->release = '1.0.6'; -$plugin->version = 2023090701; +$plugin->version = 2023101300; $plugin->requires = 2022041908; $plugin->maturity = MATURITY_STABLE; $plugin->dependencies = [];