From 03d29fbfe414e12647ee50215c187fd8208b9f96 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Tue, 4 Apr 2023 15:19:02 +0200 Subject: [PATCH 01/35] setting for multiplemarks added --- db/install.xml | 1 + db/upgrade.php | 17 +++++++++++++++++ lang/en/moodleoverflow.php | 2 ++ mod_form.php | 5 +++++ version.php | 2 +- 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/db/install.xml b/db/install.xml index fb1f1f2b2e..e4651fdc18 100644 --- a/db/install.xml +++ b/db/install.xml @@ -27,6 +27,7 @@ <FIELD NAME="gradecat" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/> <FIELD NAME="anonymous" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="needsreview" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> + <FIELD NAME="allowmultiplemarks" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> </FIELDS> <KEYS> <KEY NAME="primary" TYPE="primary" FIELDS="id"/> diff --git a/db/upgrade.php b/db/upgrade.php index 8c5b7f2356..03e87bb586 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -273,5 +273,22 @@ function xmldb_moodleoverflow_upgrade($oldversion) { // Moodleoverflow savepoint reached. upgrade_mod_savepoint(true, 2023022400, 'moodleoverflow'); } + + if ($oldversion < 2023040400) { + // Define table moodleoverflow to be edited. + $table = new xmldb_table('moodleoverflow'); + + // Define field allowmultiplemarks to be added to moodleoverflow + $field = new xmldb_field('allowmultiplemarks', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'needsreview'); + + //Conditionally launch add field allowmultiplemarks + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Moodleoverflow savepoint reached. + upgrade_mod_savepoint(true, 2023040400, 'moodleoverflow'); + } + return true; } diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index d92b8a37c0..bd13b86e7e 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -326,6 +326,8 @@ $string['attachment'] = 'Attachment'; $string['attachments'] = 'Attachments'; $string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; +$string['allowmultiplemarks'] = 'Multiple marks?'; +$string['allowmultiplemarks_help'] = 'A post can be marked as helpful or solved. Within a discussion, only one post can be marked as helpful/solved. Click the checkbox to mark multiple posts as helpful/solved.'; // Templates. $string['reputation'] = 'Reputation'; diff --git a/mod_form.php b/mod_form.php index 1cb85ae630..8e56aa001e 100644 --- a/mod_form.php +++ b/mod_form.php @@ -224,6 +224,11 @@ public function definition() { $mform->addHelpButton('allownegativereputation', 'allownegativereputation', 'moodleoverflow'); $mform->setDefault('allownegativereputation', MOODLEOVERFLOW_REPUTATION_NEGATIVE); + // Allow multiple marks of helpful/solved + $mform->addElement('checkbox', 'allowmultiplemarks', get_string('allowmultiplemarks', 'moodleoverflow')); + $mform->addHelpButton('allowmultiplemarks', 'allowmultiplemarks', 'moodleoverflow'); + $mform->setDefault('allowmultiplemarks', 0); + // Add standard elements, common to all modules. $this->standard_coursemodule_elements(); diff --git a/version.php b/version.php index d630f8cafc..c600533840 100644 --- a/version.php +++ b/version.php @@ -28,7 +28,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'mod_moodleoverflow'; -$plugin->version = 2023022406; +$plugin->version = 2023040400; $plugin->release = 'v4.1-r1'; $plugin->requires = 2020061500; // Requires Moodle 3.9+. $plugin->maturity = MATURITY_STABLE; From a357fd47851334b0079d02b5b640275cfe6ca99f Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Wed, 5 Apr 2023 16:12:48 +0200 Subject: [PATCH 02/35] 1. feature added, multiple marks are now possible, feature not completed. 2. Code checker errors fixed --- amd/build/rating.min.js | 2 +- amd/build/rating.min.js.map | 2 +- amd/build/reviewing.min.js.map | 2 +- amd/build/warnmodechange.min.js.map | 2 +- amd/src/rating.js | 28 +++++++++++++++++++++++----- db/access.php | 26 +++++++++++++------------- db/upgrade.php | 4 ++-- discussion.php | 5 ++++- externallib.php | 8 ++++---- locallib.php | 8 +++++--- mod_form.php | 2 +- tests/dailymail_test.php | 2 +- view.php | 6 ++++-- 13 files changed, 61 insertions(+), 36 deletions(-) diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index 8683a4e0aa..ce2d7eeadb 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -5,6 +5,6 @@ define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/ * @module mod_moodleoverflow/rating * @copyright 2022 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?20:10,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?2:1,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?4:3,rating=shouldRemove?10*baseRating:baseRating;await sendVote(postid,rating,userid);for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemark){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemark)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 69367bd7e6..25a7285043 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n */\nexport function init(userid) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","setAttribute","title","otherAction","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAoEqBA,0BACRC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,MAAAA,cACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,MAAAA,mBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SA3Dd,GADE,GA4DsEb,QACjFK,cAAcU,aAAa,4BAA6B,cACxDV,cAAcW,YAAc,mBAAU,UAAYP,OAAQ,0BACvD,OACGQ,YAAcJ,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAlErB,EADE,EAmE+Db,QACnEK,cAAcU,aAAa,4BAA6B,iBAClDG,aAAeP,YAAYQ,qDACGF,mBACpCC,aAAaH,aAAa,4BAA6B,cACvDV,cAAcW,YAAc,mBAAU,iBAAmBP,OAAQ,sBACjES,aAAaF,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKG,UAAuB,YAAXX,OACZY,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAeX,YAAYY,UAAUC,SAASH,WAC9CI,WAAaL,UA7EZ,EADD,EA+EAM,OAASJ,aAA4B,GAAbG,WAAkBA,iBAC1CX,SAASF,OAAQc,OAAQ1B,YAC1B,MAAM2B,MAAMzB,KAAK0B,iBAAiB,uBAAyBP,WAC5DM,GAAGJ,UAAUM,OAAOR,WACpBM,GAAGR,qDAA8CV,cAAYqB,kBACnD,iCAAiBrB,QAAU,sBAEpCa,eACDX,YAAYY,UAAUQ,IAAIV,WAC1BhB,cAAcyB,kBAAoB,oCAAoBrB,QAAU,iHArF9EP,KAAO8B,SAASC,eAAe,sCAStBnB,SAASF,OAAQc,OAAQ1B,cAC9BkC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACF1B,OAAQA,OACR2B,SAAUb,WAEd,UACJxB,KAAK0B,gEAAyD5B,cAAYwC,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,mBAE7BxC,KAAK0B,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,mBAE7B1C,KAAK0B,gEAAyDhB,cAAY4B,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,cAEtBX"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAIhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHA9G9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file diff --git a/amd/build/reviewing.min.js.map b/amd/build/reviewing.min.js.map index d5002e736d..13a68e7925 100644 --- a/amd/build/reviewing.min.js.map +++ b/amd/build/reviewing.min.js.map @@ -1 +1 @@ -{"version":3,"file":"reviewing.min.js","sources":["../src/reviewing.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements reviewing functionality\n *\n * @module mod_moodleoverflow/reviewing\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Init function.\n */\nexport function init() {\n Prefetch.prefetchTemplates(['mod_moodleoverflow/reject_post_form', 'mod_moodleoverflow/review_buttons']);\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['post_was_approved', 'jump_to_next_post_needing_review', 'there_are_no_posts_needing_review', 'post_was_rejected']);\n\n const root = document.getElementById('moodleoverflow-posts');\n root.onclick = async(e) => {\n const action = e.target.getAttribute('data-moodleoverflow-action');\n\n if (!action) {\n return;\n }\n\n const post = e.target.closest('*[data-moodleoverflow-postid]');\n const reviewRow = e.target.closest('.reviewrow');\n const postID = post.getAttribute('data-moodleoverflow-postid');\n\n if (action === 'approve') {\n reviewRow.innerHTML = '.';\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_approve_post',\n args: {\n postid: postID,\n }\n }])[0];\n\n let message = await getString('post_was_approved', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n post.classList.remove(\"pendingreview\");\n } else if (action === 'reject') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/reject_post_form', {});\n } else if (action === 'reject-submit') {\n const rejectMessage = post.querySelector('textarea.reject-reason').value.toString().trim();\n reviewRow.innerHTML = '.';\n const args = {\n postid: postID,\n reason: rejectMessage ? rejectMessage : null\n };\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_reject_post',\n args: args\n }])[0];\n\n let message = await getString('post_was_rejected', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n } else if (action === 'reject-cancel') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/review_buttons', {});\n }\n };\n}"],"names":["prefetchTemplates","prefetchStrings","document","getElementById","onclick","async","action","e","target","getAttribute","post","closest","reviewRow","postID","innerHTML","nextPostURL","Ajax","call","methodname","args","postid","message","classList","remove","Templates","render","rejectMessage","querySelector","value","toString","trim","reason"],"mappings":";;;;;;;wGA+BaA,kBAAkB,CAAC,sCAAuC,wDAC1DC,gBAAgB,qBACrB,CAAC,oBAAqB,mCAAoC,oCAAqC,sBAEtFC,SAASC,eAAe,wBAChCC,QAAUC,MAAAA,UACLC,OAASC,EAAEC,OAAOC,aAAa,kCAEhCH,oBAICI,KAAOH,EAAEC,OAAOG,QAAQ,iCACxBC,UAAYL,EAAEC,OAAOG,QAAQ,cAC7BE,OAASH,KAAKD,aAAa,iCAElB,YAAXH,OAAsB,CACtBM,UAAUE,UAAY,UAChBC,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,yCACZC,KAAM,CACFC,OAAQP,WAEZ,OAEAQ,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,QACtBX,KAAKY,UAAUC,OAAO,sBACnB,GAAe,WAAXjB,OACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,sCAAuC,SACjF,GAAe,kBAAXnB,OAA4B,OAC7BoB,cAAgBhB,KAAKiB,cAAc,0BAA0BC,MAAMC,WAAWC,OACpFlB,UAAUE,UAAY,UAChBK,KAAO,CACTC,OAAQP,OACRkB,OAAQL,eAAgC,MAEtCX,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,wCACZC,KAAMA,QACN,OAEAE,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,YACJ,kBAAXf,SACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,oCAAqC"} \ No newline at end of file +{"version":3,"file":"reviewing.min.js","sources":["../src/reviewing.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements reviewing functionality\n *\n * @module mod_moodleoverflow/reviewing\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Init function.\n */\nexport function init() {\n Prefetch.prefetchTemplates(['mod_moodleoverflow/reject_post_form', 'mod_moodleoverflow/review_buttons']);\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['post_was_approved', 'jump_to_next_post_needing_review', 'there_are_no_posts_needing_review', 'post_was_rejected']);\n\n const root = document.getElementById('moodleoverflow-posts');\n root.onclick = async(e) => {\n const action = e.target.getAttribute('data-moodleoverflow-action');\n\n if (!action) {\n return;\n }\n\n const post = e.target.closest('*[data-moodleoverflow-postid]');\n const reviewRow = e.target.closest('.reviewrow');\n const postID = post.getAttribute('data-moodleoverflow-postid');\n\n if (action === 'approve') {\n reviewRow.innerHTML = '.';\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_approve_post',\n args: {\n postid: postID,\n }\n }])[0];\n\n let message = await getString('post_was_approved', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n post.classList.remove(\"pendingreview\");\n } else if (action === 'reject') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/reject_post_form', {});\n } else if (action === 'reject-submit') {\n const rejectMessage = post.querySelector('textarea.reject-reason').value.toString().trim();\n reviewRow.innerHTML = '.';\n const args = {\n postid: postID,\n reason: rejectMessage ? rejectMessage : null\n };\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_reject_post',\n args: args\n }])[0];\n\n let message = await getString('post_was_rejected', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n } else if (action === 'reject-cancel') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/review_buttons', {});\n }\n };\n}"],"names":["prefetchTemplates","prefetchStrings","document","getElementById","onclick","async","action","e","target","getAttribute","post","closest","reviewRow","postID","innerHTML","nextPostURL","Ajax","call","methodname","args","postid","message","classList","remove","Templates","render","rejectMessage","querySelector","value","toString","trim","reason"],"mappings":";;;;;;;wGA+BaA,kBAAkB,CAAC,sCAAuC,wDAC1DC,gBAAgB,qBACrB,CAAC,oBAAqB,mCAAoC,oCAAqC,sBAEtFC,SAASC,eAAe,wBAChCC,QAAUC,gBACLC,OAASC,EAAEC,OAAOC,aAAa,kCAEhCH,oBAICI,KAAOH,EAAEC,OAAOG,QAAQ,iCACxBC,UAAYL,EAAEC,OAAOG,QAAQ,cAC7BE,OAASH,KAAKD,aAAa,iCAElB,YAAXH,OAAsB,CACtBM,UAAUE,UAAY,UAChBC,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,yCACZC,KAAM,CACFC,OAAQP,WAEZ,OAEAQ,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,QACtBX,KAAKY,UAAUC,OAAO,sBACnB,GAAe,WAAXjB,OACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,sCAAuC,SACjF,GAAe,kBAAXnB,OAA4B,OAC7BoB,cAAgBhB,KAAKiB,cAAc,0BAA0BC,MAAMC,WAAWC,OACpFlB,UAAUE,UAAY,UAChBK,KAAO,CACTC,OAAQP,OACRkB,OAAQL,eAAgC,MAEtCX,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,wCACZC,KAAMA,QACN,OAEAE,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,YACJ,kBAAXf,SACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,oCAAqC"} \ No newline at end of file diff --git a/amd/build/warnmodechange.min.js.map b/amd/build/warnmodechange.min.js.map index 70683e5540..b4120395cd 100644 --- a/amd/build/warnmodechange.min.js.map +++ b/amd/build/warnmodechange.min.js.map @@ -1 +1 @@ -{"version":3,"file":"warnmodechange.min.js","sources":["../src/warnmodechange.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Warns on changing the subscription mode.\n *\n * @module mod_moodleoverflow/warnmodechange\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Prefetch from 'core/prefetch';\n\n/**\n * Init function.\n * @param {string} previousSetting\n */\nexport function init(previousSetting) {\n Prefetch.prefetchStrings('mod_moodleoverflow', ['switchtooptional', 'switchtoauto']);\n Prefetch.prefetchStrings('moodle', ['confirm', 'cancel']);\n const form = document.querySelector('form.mform');\n const select = document.getElementById('id_forcesubscribe');\n form.onsubmit = async(e) => {\n const value = select.selectedOptions[0].value;\n if (value == previousSetting || value == 1 || value == 3) {\n return;\n }\n e.preventDefault();\n await Notification.confirm(\n await getString('confirm'),\n await getString(value == 0 ? 'switchtooptional' : 'switchtoauto', 'mod_moodleoverflow'),\n await getString('confirm'),\n await getString('cancel'),\n () => {\n // Prevent this listener from preventing the event again.\n form.onsubmit = undefined;\n form.requestSubmit(e.submitter);\n }, undefined);\n };\n}"],"names":["previousSetting","prefetchStrings","form","document","querySelector","select","getElementById","onsubmit","async","value","selectedOptions","e","preventDefault","Notification","confirm","undefined","requestSubmit","submitter"],"mappings":";;;;;;;oFA8BqBA,mCACRC,gBAAgB,qBAAsB,CAAC,mBAAoB,mCAC3DA,gBAAgB,SAAU,CAAC,UAAW,iBACzCC,KAAOC,SAASC,cAAc,cAC9BC,OAASF,SAASG,eAAe,qBACvCJ,KAAKK,SAAWC,MAAAA,UACNC,MAAQJ,OAAOK,gBAAgB,GAAGD,MACpCA,OAAST,iBAA4B,GAATS,OAAuB,GAATA,QAG9CE,EAAEC,uBACIC,sBAAaC,cACT,mBAAU,iBACV,mBAAmB,GAATL,MAAa,mBAAqB,eAAgB,4BAC5D,mBAAU,iBACV,mBAAU,WAChB,KAEIP,KAAKK,cAAWQ,EAChBb,KAAKc,cAAcL,EAAEM,kBACtBF"} \ No newline at end of file +{"version":3,"file":"warnmodechange.min.js","sources":["../src/warnmodechange.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Warns on changing the subscription mode.\n *\n * @module mod_moodleoverflow/warnmodechange\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Prefetch from 'core/prefetch';\n\n/**\n * Init function.\n * @param {string} previousSetting\n */\nexport function init(previousSetting) {\n Prefetch.prefetchStrings('mod_moodleoverflow', ['switchtooptional', 'switchtoauto']);\n Prefetch.prefetchStrings('moodle', ['confirm', 'cancel']);\n const form = document.querySelector('form.mform');\n const select = document.getElementById('id_forcesubscribe');\n form.onsubmit = async(e) => {\n const value = select.selectedOptions[0].value;\n if (value == previousSetting || value == 1 || value == 3) {\n return;\n }\n e.preventDefault();\n await Notification.confirm(\n await getString('confirm'),\n await getString(value == 0 ? 'switchtooptional' : 'switchtoauto', 'mod_moodleoverflow'),\n await getString('confirm'),\n await getString('cancel'),\n () => {\n // Prevent this listener from preventing the event again.\n form.onsubmit = undefined;\n form.requestSubmit(e.submitter);\n }, undefined);\n };\n}"],"names":["previousSetting","prefetchStrings","form","document","querySelector","select","getElementById","onsubmit","async","value","selectedOptions","e","preventDefault","Notification","confirm","undefined","requestSubmit","submitter"],"mappings":";;;;;;;oFA8BqBA,mCACRC,gBAAgB,qBAAsB,CAAC,mBAAoB,mCAC3DA,gBAAgB,SAAU,CAAC,UAAW,iBACzCC,KAAOC,SAASC,cAAc,cAC9BC,OAASF,SAASG,eAAe,qBACvCJ,KAAKK,SAAWC,gBACNC,MAAQJ,OAAOK,gBAAgB,GAAGD,MACpCA,OAAST,iBAA4B,GAATS,OAAuB,GAATA,QAG9CE,EAAEC,uBACIC,sBAAaC,cACT,mBAAU,iBACV,mBAAmB,GAATL,MAAa,mBAAqB,eAAgB,4BAC5D,mBAAU,iBACV,mBAAU,WAChB,KAEIP,KAAKK,cAAWQ,EAChBb,KAAKc,cAAcL,EAAEM,kBACtBF,GATP"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index 7d504d76c7..7730b52596 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -65,8 +65,10 @@ async function sendVote(postid, rating, userid) { * Init function. * * @param {int} userid + * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed. + * */ -export function init(userid) { +export function init(userid, allowmultiplemark) { Prefetch.prefetchStrings('mod_moodleoverflow', ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful', 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']); @@ -109,11 +111,27 @@ export function init(userid) { const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED; const rating = shouldRemove ? baseRating * 10 : baseRating; await sendVote(postid, rating, userid); - for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) { - el.classList.remove(htmlclass); - el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = - await getString(`mark${action}`, 'mod_moodleoverflow'); + + /* If multiplemarks are not allowed (that is the default mode): delete all marks. + else: only delete the mark if the post is being unmarked. + + then add a mark, if the post is being marked. + */ + if (allowmultiplemark == 0) { + // Delete all marks in the discussion + for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) { + el.classList.remove(htmlclass); + el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = + await getString(`mark${action}`, 'mod_moodleoverflow'); + } + } else { + // Remove only the mark of the unmarked post. + if (shouldRemove) { + postElement.classList.remove(htmlclass); + actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow'); + } } + // If the post is being marked, mark it. if (!shouldRemove) { postElement.classList.add(htmlclass); actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow'); diff --git a/db/access.php b/db/access.php index 6e5fee1b3e..1c5e4b80ff 100644 --- a/db/access.php +++ b/db/access.php @@ -111,11 +111,11 @@ ), 'mod/moodleoverflow:deleteownpost' => array( - 'captype' => 'write', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'student' => CAP_ALLOW, - 'teacher' => CAP_ALLOW, + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ), @@ -123,10 +123,10 @@ ), 'mod/moodleoverflow:deleteanypost' => array( - 'captype' => 'write', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ), @@ -158,10 +158,10 @@ 'mod/moodleoverflow:managesubscriptions' => array( 'riskbitmask' => RISK_SPAM, - 'captype' => 'write', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'teacher' => CAP_ALLOW, + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ), diff --git a/db/upgrade.php b/db/upgrade.php index 03e87bb586..1abb5af03e 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -278,10 +278,10 @@ function xmldb_moodleoverflow_upgrade($oldversion) { // Define table moodleoverflow to be edited. $table = new xmldb_table('moodleoverflow'); - // Define field allowmultiplemarks to be added to moodleoverflow + // Define field allowmultiplemarks to be added to moodleoverflow. $field = new xmldb_field('allowmultiplemarks', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'needsreview'); - //Conditionally launch add field allowmultiplemarks + // Conditionally launch add field allowmultiplemarks. if (!$dbman->field_exists($table, $field)) { $dbman->add_field($table, $field); } diff --git a/discussion.php b/discussion.php index e0af3e24c4..cbc7fee593 100644 --- a/discussion.php +++ b/discussion.php @@ -50,6 +50,9 @@ throw new moodle_exception('invalidcourseid'); } +// Save the allowmultiplemarks setting. +$marksetting = $DB->get_record('moodleoverflow', array('id' => $moodleoverflow->id), 'allowmultiplemarks'); + // Get the related coursemodule and its context. if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) { throw new moodle_exception('invalidcoursemodule'); @@ -128,7 +131,7 @@ $PAGE->requires->js_call_amd('mod_moodleoverflow/reviewing', 'init'); -$PAGE->requires->js_call_amd('mod_moodleoverflow/rating', 'init', [$USER->id]); +$PAGE->requires->js_call_amd('mod_moodleoverflow/rating', 'init', [$USER->id, $marksetting->allowmultiplemarks]); // Initiate the page. $PAGE->set_title($course->shortname . ': ' . format_string($discussion->name)); diff --git a/externallib.php b/externallib.php index 66df2d88b8..a7c29fb75f 100644 --- a/externallib.php +++ b/externallib.php @@ -46,8 +46,8 @@ class mod_moodleoverflow_external extends external_api { public static function record_vote_parameters() { return new external_function_parameters( array( - 'postid' => new external_value(PARAM_INT, 'id of post'), - 'ratingid' => new external_value(PARAM_INT, 'rating') + 'postid' => new external_value(PARAM_INT, 'id of post'), + 'ratingid' => new external_value(PARAM_INT, 'rating') ) ); } @@ -79,8 +79,8 @@ public static function record_vote($postid, $ratingid) { // Parameter validation. $params = self::validate_parameters(self::record_vote_parameters(), array( - 'postid' => $postid, - 'ratingid' => $ratingid, + 'postid' => $postid, + 'ratingid' => $ratingid, )); $transaction = $DB->start_delegated_transaction(); diff --git a/locallib.php b/locallib.php index 64b8589ab0..f7f9294d9f 100644 --- a/locallib.php +++ b/locallib.php @@ -300,7 +300,8 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - } } else { // Get his picture, his name and the link to his profile. - $preparedarray[$i]['picture'] = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course, 'link' => false)); + $preparedarray[$i]['picture'] = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course, + 'link' => false)); $preparedarray[$i]['username'] = fullname($startuser, has_capability('moodle/site:viewfullnames', $context)); $preparedarray[$i]['userlink'] = $CFG->wwwroot . '/user/view.php?id=' . $discussion->userid . '&course=' . $moodleoverflow->course; @@ -1203,7 +1204,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co } // A teacher can mark an answer as solved. - $canmarksolved = (($iscomment != $post->parent) AND !empty($post->parent) AND capabilities::has(capabilities::MARK_SOLVED, $modulecontext)); + $canmarksolved = (($iscomment != $post->parent) && !empty($post->parent) + && capabilities::has(capabilities::MARK_SOLVED, $modulecontext)); if ($canmarksolved) { // When the post is already marked, remove the mark instead. @@ -1268,7 +1270,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $mustachedata->isread = false; $mustachedata->isfirstunread = false; $mustachedata->isfirstpost = false; - $mustachedata->iscomment = (!empty($post->parent) AND ($iscomment == $post->parent)); + $mustachedata->iscomment = (!empty($post->parent) && ($iscomment == $post->parent)); $mustachedata->permalink = $permalink; // Get the ratings. diff --git a/mod_form.php b/mod_form.php index 8e56aa001e..d171d23e83 100644 --- a/mod_form.php +++ b/mod_form.php @@ -224,7 +224,7 @@ public function definition() { $mform->addHelpButton('allownegativereputation', 'allownegativereputation', 'moodleoverflow'); $mform->setDefault('allownegativereputation', MOODLEOVERFLOW_REPUTATION_NEGATIVE); - // Allow multiple marks of helpful/solved + // Allow multiple marks of helpful/solved. $mform->addElement('checkbox', 'allowmultiplemarks', get_string('allowmultiplemarks', 'moodleoverflow')); $mform->addHelpButton('allowmultiplemarks', 'allowmultiplemarks', 'moodleoverflow'); $mform->setDefault('allowmultiplemarks', 0); diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index b6afe4d54e..3064dd674e 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -197,7 +197,7 @@ public function test_mail_not_send() { */ public function test_records_removed() { global $DB; - // create user with maildigest = on. + // Create user with maildigest = on. $this->helper_create_user_and_discussion('1'); // Now send the mails. diff --git a/view.php b/view.php index ad62eca45b..ae87c80bc0 100644 --- a/view.php +++ b/view.php @@ -36,6 +36,7 @@ $page = optional_param('page', 0, PARAM_INT); // Which page to show. $movetopopup = optional_param('movetopopup', 0, PARAM_INT); // Which Topic to move. $linktoforum = optional_param('movetoforum', 0, PARAM_INT); // Forum to which it is moved. + // Set the parameters. $params = array(); if ($id) { @@ -61,7 +62,8 @@ throw new moodle_exception('missingparameter'); } - +// Save the allowmultiplemarks setting. +$marksetting = $DB->get_record('moodleoverflow', array('id' => $moodleoverflow->id), 'allowmultiplemarks'); // Require a login. require_login($course, true, $cm); @@ -87,7 +89,7 @@ $PAGE->set_title(format_string($moodleoverflow->name)); $PAGE->set_heading(format_string($course->fullname)); -$PAGE->requires->js_call_amd('mod_moodleoverflow/rating', 'init', [$USER->id]); +$PAGE->requires->js_call_amd('mod_moodleoverflow/rating', 'init', [$USER->id, $marksetting->allowmultiplemarks]); // Output starts here. echo $OUTPUT->header(); From b98a9de382d2a15fee5d50ca98f30280e083392d Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Thu, 6 Apr 2023 12:35:36 +0200 Subject: [PATCH 03/35] comment added for marks setting in discussion.php --- discussion.php | 4 ++++ lang/en/moodleoverflow.php | 3 +++ locallib.php | 31 ++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/discussion.php b/discussion.php index cbc7fee593..d5c79bfee5 100644 --- a/discussion.php +++ b/discussion.php @@ -142,6 +142,10 @@ // Start the side-output. echo $OUTPUT->header(); + +// Print a text, if multiple marks are allowed. +moodleoverflow_print_multiplemarks_comment($modulecontext, $post); + echo $OUTPUT->heading(format_string($discussion->name), 1, 'discussionname'); // Guests and users can not subscribe to a discussion. diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index bd13b86e7e..a128ed4a37 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -328,6 +328,9 @@ $string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; $string['allowmultiplemarks'] = 'Multiple marks?'; $string['allowmultiplemarks_help'] = 'A post can be marked as helpful or solved. Within a discussion, only one post can be marked as helpful/solved. Click the checkbox to mark multiple posts as helpful/solved.'; +$string['multiplemarkscommentteacherownpost'] = 'Multiple marks are enabled, several posts can be marked as helpful or solved'; +$string['multiplemarkscommentstudentownpost'] = 'Multiple marks are enabled, you can mark several posts as helpful'; +$string['multiplemarkscommentteacher'] = 'Multiple marks are enabled, several posts can be marked as solved'; // Templates. $string['reputation'] = 'Reputation'; diff --git a/locallib.php b/locallib.php index f7f9294d9f..082931d93e 100644 --- a/locallib.php +++ b/locallib.php @@ -876,6 +876,35 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr return !$considerreviewstatus || $posttoreplyto->reviewed == 1; } +/** + * Prints a text, if multiple marks are allowed. + * + * @param stdClass $context The moodleoverflow context. + * @param stdClass $post The post object. + */ +function moodleoverflow_print_multiplemarks_comment($context, $post) { + global $USER; + + // Check if the current user is the starter of the discussion. + $ownpost = (isloggedin() && ($USER->id == $post->userid)); + + // Check if the current user can mark posts as solved. + $canmarksolved = (has_capability('mod/moodleoverflow:marksolved', $context)); + $comment = ''; + + if ($ownpost) { + if ($canmarksolved) { + $comment = get_string('multiplemarkscommentteacherownpost', 'moodleoverflow'); + } else { + $comment = get_string('multiplemarkscommentstudentownpost', 'moodleoverflow'); + } + } + else if ($canmarksolved) { + $comment = get_string('multiplemarkscommentteacher', 'moodleoverflow'); + } + $comment = $comment . '<br>' . '<br>'; + echo $comment; +} /** * Prints a moodleoverflow discussion. * @@ -888,7 +917,7 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post) { global $USER; - // Check if the current is the starter of the discussion. + // Check if the current user is the starter of the discussion. $ownpost = (isloggedin() && ($USER->id == $post->userid)); // Fetch the modulecontext. From d2d9d2c7b676d275e3a62aa2f938d04a33011171 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Thu, 6 Apr 2023 11:32:15 +0200 Subject: [PATCH 04/35] multiplemarks-checkbox bug fixed --- mod_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod_form.php b/mod_form.php index d171d23e83..4df07d8537 100644 --- a/mod_form.php +++ b/mod_form.php @@ -225,7 +225,7 @@ public function definition() { $mform->setDefault('allownegativereputation', MOODLEOVERFLOW_REPUTATION_NEGATIVE); // Allow multiple marks of helpful/solved. - $mform->addElement('checkbox', 'allowmultiplemarks', get_string('allowmultiplemarks', 'moodleoverflow')); + $mform->addElement('advcheckbox', 'allowmultiplemarks', get_string('allowmultiplemarks', 'moodleoverflow')); $mform->addHelpButton('allowmultiplemarks', 'allowmultiplemarks', 'moodleoverflow'); $mform->setDefault('allowmultiplemarks', 0); From 5b04f0e2c1d83daeb51fd166b8f1c290ae125e1e Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 17 Apr 2023 16:04:07 +0200 Subject: [PATCH 05/35] WIP: change button string if posts are marked --- amd/build/rating.min.js.map | 2 +- amd/src/rating.js | 18 +++++ discussion.php | 12 ++- lang/en/moodleoverflow.php | 9 +-- lib.php | 6 ++ locallib.php | 142 +++++++++++++++++++++++++----------- 6 files changed, 135 insertions(+), 54 deletions(-) diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 25a7285043..0df23bfbb9 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAIhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHA9G9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n /*\n // Iterate trough all posts in the discussion and check if there are other marked posts.\n var othermarkedposts = 0;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = 1;\n break;\n }\n }\n // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' .\n // Else: do nothing, because if there is no marked post, the string doesn't change.\n if (othermarkedposts == 1) {\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass)) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n }\n }\n }*/\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAuBhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHAjI9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index 7730b52596..1039a133ce 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -130,6 +130,24 @@ export function init(userid, allowmultiplemark) { postElement.classList.remove(htmlclass); actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow'); } + // Iterate trough all posts in the discussion and check if there are other marked posts. + var othermarkedposts = 0; + for (const el of root.querySelectorAll('.moodleoverflowpost')) { + if (el.classList.contains(htmlclass)) { + othermarkedposts = 1; + break; + } + } + // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' . + // Else: do nothing, because if there is no marked post, the string doesn't change. + if (othermarkedposts == 1) { + for (const el of root.querySelectorAll('.moodleoverflowpost')) { + if (!el.classList.contains(htmlclass)) { + el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = + await getString(`alsomark${action}`, 'mod_moodleoverflow'); + } + } + } } // If the post is being marked, mark it. if (!shouldRemove) { diff --git a/discussion.php b/discussion.php index d5c79bfee5..d751744169 100644 --- a/discussion.php +++ b/discussion.php @@ -143,9 +143,6 @@ // Start the side-output. echo $OUTPUT->header(); -// Print a text, if multiple marks are allowed. -moodleoverflow_print_multiplemarks_comment($modulecontext, $post); - echo $OUTPUT->heading(format_string($discussion->name), 1, 'discussionname'); // Guests and users can not subscribe to a discussion. @@ -157,7 +154,14 @@ echo '<div id="moodleoverflow-posts"><div id="moodleoverflow-root">'; -moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post); +// if multiplemarks are on, then print the discussion considering the markdata, else print the discussion. +if ($marksetting) { + $multiplemarksdata = moodleoverflow_get_discussion_markdata($d); + moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarksdata); +} else { + moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post); +} + echo '</div></div>'; diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index a128ed4a37..cd61080e6c 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -187,9 +187,11 @@ $string['ratingfailed'] = 'Rating failed. Try again.'; $string['rateownpost'] = 'You cannot rate your own post.'; $string['marksolved'] = 'Mark as solution'; +$string['alsomarksolved'] = 'Also mark as solution'; $string['marknotsolved'] = 'Remove solution mark'; -$string['markhelpful'] = 'Mark as Helpful'; -$string['marknothelpful'] = 'Not Helpful'; +$string['markhelpful'] = 'Mark as helpful'; +$string['alsomarkhelpful'] = 'Also mark as helpful'; +$string['marknothelpful'] = 'Not helpful'; $string['answer'] = '{$a} Answer'; $string['answers'] = '{$a} Answers'; @@ -328,9 +330,6 @@ $string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; $string['allowmultiplemarks'] = 'Multiple marks?'; $string['allowmultiplemarks_help'] = 'A post can be marked as helpful or solved. Within a discussion, only one post can be marked as helpful/solved. Click the checkbox to mark multiple posts as helpful/solved.'; -$string['multiplemarkscommentteacherownpost'] = 'Multiple marks are enabled, several posts can be marked as helpful or solved'; -$string['multiplemarkscommentstudentownpost'] = 'Multiple marks are enabled, you can mark several posts as helpful'; -$string['multiplemarkscommentteacher'] = 'Multiple marks are enabled, several posts can be marked as solved'; // Templates. $string['reputation'] = 'Reputation'; diff --git a/lib.php b/lib.php index 980856a25f..01ced85c7c 100644 --- a/lib.php +++ b/lib.php @@ -80,6 +80,12 @@ define('RATING_HELPFUL', 4); define('RATING_REMOVE_HELPFUL', 40); +// Mark constants. +define('MOODLEOVERFLOW_NEITHERHELPFULORSOLVED', 0); +define('MOODLEOVERFLOW_HELPFUL', 1); +define('MOODLEOVERFLOW_SOLVED', 2); +define('MOODLEOVERFLOW_HELPFULANDSOLVED', 3); + /* Moodle core API */ /** diff --git a/locallib.php b/locallib.php index 082931d93e..98e42e3588 100644 --- a/locallib.php +++ b/locallib.php @@ -453,6 +453,42 @@ function moodleoverflow_print_forum_list($course, $cm, $movetopopup) { echo $renderer->render_forum_list($mustachedata); } + +/** + * Get the data about a the marks of a discussion: + * - if a helpful or solved post exists + * - which posts are helpful/solved + * + * Return an object with the data + * + * @param int $discussionid + * @return object + */ +function moodleoverflow_get_discussion_markdata($discussionid) { + $helpful = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussionid, false); + $solved = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussionid, true); + $markdata = new \stdClass(); + $markdata->markstatus = 0; + $markdata->helpfulpostid = false; + $markdata->solvedpostid = false; + if ($helpful) { + if ($solved) { + $markdata->markstatus = 3; + $markdata->helpfulpostid = $helpful->postid; + $markdata->solvedpostid = $solved->postid; + } else { + $markdata->markstatus = 2; + $markdata->helpfulpostid = $helpful->postid; + } + } else { + if ($solved) { + $markdata->markstatus = 1; + $markdata->solvedpostid = $solved->postid; + } + } + + return $markdata; +} /** * Returns an array of counts of replies for each discussion. * @@ -876,35 +912,7 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr return !$considerreviewstatus || $posttoreplyto->reviewed == 1; } -/** - * Prints a text, if multiple marks are allowed. - * - * @param stdClass $context The moodleoverflow context. - * @param stdClass $post The post object. - */ -function moodleoverflow_print_multiplemarks_comment($context, $post) { - global $USER; - - // Check if the current user is the starter of the discussion. - $ownpost = (isloggedin() && ($USER->id == $post->userid)); - - // Check if the current user can mark posts as solved. - $canmarksolved = (has_capability('mod/moodleoverflow:marksolved', $context)); - $comment = ''; - if ($ownpost) { - if ($canmarksolved) { - $comment = get_string('multiplemarkscommentteacherownpost', 'moodleoverflow'); - } else { - $comment = get_string('multiplemarkscommentstudentownpost', 'moodleoverflow'); - } - } - else if ($canmarksolved) { - $comment = get_string('multiplemarkscommentteacher', 'moodleoverflow'); - } - $comment = $comment . '<br>' . '<br>'; - echo $comment; -} /** * Prints a moodleoverflow discussion. * @@ -913,8 +921,9 @@ function moodleoverflow_print_multiplemarks_comment($context, $post) { * @param stdClass $moodleoverflow The moodleoverflow object * @param stdClass $discussion The discussion object * @param stdClass $post The post object + * @param boolean $markdata Object with information about marked posts. Only needed when multiplemarks are allowed */ -function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post) { +function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $markdata = false) { global $USER; // Check if the current user is the starter of the discussion. @@ -966,9 +975,16 @@ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discuss // Check if the post was read. $postread = !empty($post->postread); - // Print the starting post. - echo moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, - $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping); + // Check if there is markdata, if yes, print the starting post considering the markdata. + if ($markdata == false) { + // Print the starting post. + echo moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, + $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping); + } else { + // Print the starting post. + echo moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, + $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping, 0, $markdata); + } // Print answer divider. if ($answercount == 1) { @@ -980,9 +996,16 @@ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discuss echo '<div id="moodleoverflow-posts">'; - // Print the other posts. - echo moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, - null, $usermapping); + // Check if there is markdata, if yes, print the other posts considering the markdata. + if ($markdata == false) { + // Print the other posts. + echo moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, + null, $usermapping); + } else { + // Print the other posts. + echo moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, + null, $usermapping, $markdata); + } echo '</div>'; } @@ -1110,6 +1133,7 @@ function moodleoverflow_get_all_discussion_posts($discussionid, $tracking, $modc * @param bool $iscomment * @param array $usermapping * @param int $level + * @param object $markdata Information about marked posts in a discussion, only needed if multiplemarks are allowed * @return void|null * @throws coding_exception * @throws dml_exception @@ -1119,8 +1143,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $ownpost = false, $link = false, $footer = '', $highlight = '', $postisread = null, $dummyifcantsee = true, $istracked = false, - $iscomment = false, $usermapping = [], $level = 0) { - global $USER, $CFG, $OUTPUT, $PAGE; + $iscomment = false, $usermapping = [], $level = 0, $markdata = false) { + global $USER, $CFG, $OUTPUT, $PAGE, $DB; // Require the filelib. require_once($CFG->libdir . '/filelib.php'); @@ -1176,8 +1200,10 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $str->markread = get_string('markread', 'moodleoverflow'); $str->markunread = get_string('markunread', 'moodleoverflow'); $str->marksolved = get_string('marksolved', 'moodleoverflow'); + $str->alsomarksolved = get_string('alsomarksolved', 'moodleoverflow'); $str->marknotsolved = get_string('marknotsolved', 'moodleoverflow'); $str->markhelpful = get_string('markhelpful', 'moodleoverflow'); + $str->alsomarkhelpful = get_string('alsomarkhelpful', 'moodleoverflow'); $str->marknothelpful = get_string('marknothelpful', 'moodleoverflow'); } @@ -1227,8 +1253,16 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $commands[] = html_writer::tag('a', $str->marknothelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { - $commands[] = html_writer::tag('a', $str->markhelpful, + // If there is markdata: consider it. + // Markdata saves the ID of a marked post in the discussion. + // If multiplemarks are allowed, other posts than the marked post will have another string. + if ($markdata != false && $markdata->helpfulpostid != false && $post->id != $markdata->helpfulpostid) { + $commands[] = html_writer::tag('a', $str->alsomarkhelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); + } else { + $commands[] = html_writer::tag('a', $str->markhelpful, + array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); + } } } @@ -1243,8 +1277,16 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $commands[] = html_writer::tag('a', $str->marknotsolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); } else { - $commands[] = html_writer::tag('a', $str->marksolved, + // If there is markdata: consider it. + // Markdata saves the ID of a marked post in the discussion. + // If multiplemarks are allowed, other posts than the marked post will have another string. + if ($markdata != false && $markdata->solvedpostid != false && $post->id != $markdata->solvedpostid) { + $commands[] = html_writer::tag('a', $str->alsomarksolved, + array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); + } else { + $commands[] = html_writer::tag('a', $str->marksolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); + } } } @@ -1465,13 +1507,14 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co * @param array $posts Array of posts within the discussion * @param bool $iscomment Whether the current post is a comment * @param array $usermapping + * @param object $markdata Information about marked posts in a discussion, only needed if multiplemarks are allowed * @return string * @throws coding_exception * @throws dml_exception * @throws moodle_exception */ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $discussion, $parent, - $istracked, $posts, $iscomment = null, $usermapping = []) { + $istracked, $posts, $iscomment = null, $usermapping = [], $markdata = false) { global $USER; // Prepare the output. @@ -1511,13 +1554,24 @@ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $disc // Determine whether the post has been read by the current user. $postread = !empty($post->postread); - // Print the answer. - $output .= moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, + // Check if there is markdata, if yes print the answer and children considering the markdata. + if ($markdata == false) { + // Print the answer. + $output .= moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, $ownpost, false, '', '', $postread, true, $istracked, $parentid, $usermapping, $level); - // Print its children. - $output .= moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, + // Print its children. + $output .= moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, $parentid, $usermapping); + } else { + // Print the answer. + $output .= moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, + $ownpost, false, '', '', $postread, true, $istracked, $parentid, $usermapping, $level, $markdata); + + // Print its children. + $output .= moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, + $discussion, $post, $istracked, $posts, $parentid, $usermapping, $markdata); + } // End the div. $output .= "</div>\n"; From f08df49d4dd2c3e9bcf76e98ff4cc78e1a69fb82 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Tue, 18 Apr 2023 17:58:12 +0200 Subject: [PATCH 06/35] WIP: change button strings is not working --- amd/build/rating.min.js | 2 +- amd/build/rating.min.js.map | 2 +- amd/src/rating.js | 16 ++++++++++------ classes/ratings.php | 27 +++++++++++++++------------ discussion.php | 5 +++-- locallib.php | 9 +++++++-- 6 files changed, 37 insertions(+), 24 deletions(-) diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index ce2d7eeadb..b88babf908 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -5,6 +5,6 @@ define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/ * @module mod_moodleoverflow/rating * @copyright 2022 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemark){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemark)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemark){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","marknotsolved","markhelpful","alsomarkhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemark)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 0df23bfbb9..b848a3e4d6 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n /*\n // Iterate trough all posts in the discussion and check if there are other marked posts.\n var othermarkedposts = 0;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = 1;\n break;\n }\n }\n // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' .\n // Else: do nothing, because if there is no marked post, the string doesn't change.\n if (othermarkedposts == 1) {\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass)) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n }\n }\n }*/\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAuBhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHAjI9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'marknotsolved', 'markhelpful', 'alsomarkhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n /*// Iterate trough all posts in the discussion and check if there are other marked posts.\n var othermarkedposts = 0;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = 1;\n break;\n }\n }\n // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' .\n // Else: do nothing, because if there is no marked post, the string doesn't change.\n if (othermarkedposts == 1) {\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n\n //el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n //await getString(`alsomark${action}`, 'mod_moodleoverflow');\n }\n else {\n\n }\n }\n }*/\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,gBAAiB,cAAe,kBAAmB,iBAChF,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBA0BhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHApI9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index 1039a133ce..0fb87925b1 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -70,7 +70,7 @@ async function sendVote(postid, rating, userid) { */ export function init(userid, allowmultiplemark) { Prefetch.prefetchStrings('mod_moodleoverflow', - ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful', + ['marksolved', 'alsomarksolved', 'marknotsolved', 'markhelpful', 'alsomarkhelpful', 'marknothelpful', 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']); root.onclick = async(event) => { @@ -130,7 +130,7 @@ export function init(userid, allowmultiplemark) { postElement.classList.remove(htmlclass); actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow'); } - // Iterate trough all posts in the discussion and check if there are other marked posts. + /*// Iterate trough all posts in the discussion and check if there are other marked posts. var othermarkedposts = 0; for (const el of root.querySelectorAll('.moodleoverflowpost')) { if (el.classList.contains(htmlclass)) { @@ -142,12 +142,16 @@ export function init(userid, allowmultiplemark) { // Else: do nothing, because if there is no marked post, the string doesn't change. if (othermarkedposts == 1) { for (const el of root.querySelectorAll('.moodleoverflowpost')) { - if (!el.classList.contains(htmlclass)) { - el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = - await getString(`alsomark${action}`, 'mod_moodleoverflow'); + if (el.classList.contains(htmlclass)) { + + //el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = + //await getString(`alsomark${action}`, 'mod_moodleoverflow'); + } + else { + } } - } + }*/ } // If the post is being marked, mark it. if (!shouldRemove) { diff --git a/classes/ratings.php b/classes/ratings.php index 899755d6d1..94beee681a 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -46,7 +46,7 @@ class ratings { * * @return bool|int */ - public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rating, $cm, $userid = null) { + public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rating, $cm, $userid = null, $allowmultiplemarks = 0) { global $DB, $USER, $SESSION; // Has a user been submitted? @@ -138,20 +138,23 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati throw new moodle_exception('notteacher', 'moodleoverflow'); } - // Get other ratings in the discussion. - $sql = "SELECT * - FROM {moodleoverflow_ratings} - WHERE discussionid = ? AND rating = ?"; - $otherrating = $DB->get_record_sql($sql, [ $discussion->id, $rating ]); + if ($allowmultiplemarks == 0) { + // Get other ratings in the discussion. + $sql = "SELECT * + FROM {moodleoverflow_ratings} + WHERE discussionid = ? AND rating = ?"; + $otherrating = $DB->get_record_sql($sql, [ $discussion->id, $rating ]); - // If there is an old rating, update it. Else create a new rating record. - if ($otherrating) { - return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); - } else { - $mid = $moodleoverflow->id; + // If there is an old rating, update it. Else create a new rating record. + if ($otherrating) { + return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); + } else { + $mid = $moodleoverflow->id; - return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); + return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); + } } + } // Update an rating record. diff --git a/discussion.php b/discussion.php index d751744169..7e81d33195 100644 --- a/discussion.php +++ b/discussion.php @@ -76,7 +76,8 @@ if (in_array($ratingid, array(RATING_SOLVED, RATING_REMOVE_SOLVED, RATING_HELPFUL, RATING_REMOVE_HELPFUL))) { // Rate the post. - if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm)) { + if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm, null, + $marksetting->allowmultiplemarks)) { throw new moodle_exception('ratingfailed', 'moodleoverflow'); } @@ -155,7 +156,7 @@ echo '<div id="moodleoverflow-posts"><div id="moodleoverflow-root">'; // if multiplemarks are on, then print the discussion considering the markdata, else print the discussion. -if ($marksetting) { +if ($marksetting->allowmultiplemarks == 1) { $multiplemarksdata = moodleoverflow_get_discussion_markdata($d); moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarksdata); } else { diff --git a/locallib.php b/locallib.php index 98e42e3588..22e1d96211 100644 --- a/locallib.php +++ b/locallib.php @@ -1242,6 +1242,9 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $permalink = new moodle_url($discussionlink); $permalink->set_anchor('p' . $post->id); + // Save the setting of multiplemarks. + $multiplemarkssetting = $DB->get_record('moodleoverflow', array('id' => $moodleoverflow->id), 'allowmultiplemarks'); + // If the user has started the discussion, he can mark the answer as helpful. $canmarkhelpful = (($USER->id == $discussion->userid) && ($USER->id != $post->userid) && ($iscomment != $post->parent) && !empty($post->parent)); @@ -1256,7 +1259,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co // If there is markdata: consider it. // Markdata saves the ID of a marked post in the discussion. // If multiplemarks are allowed, other posts than the marked post will have another string. - if ($markdata != false && $markdata->helpfulpostid != false && $post->id != $markdata->helpfulpostid) { + if ($multiplemarkssetting->allowmultiplemarks == 1 && $markdata != false && $markdata->helpfulpostid != false + && $post->id != $markdata->helpfulpostid) { $commands[] = html_writer::tag('a', $str->alsomarkhelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { @@ -1280,7 +1284,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co // If there is markdata: consider it. // Markdata saves the ID of a marked post in the discussion. // If multiplemarks are allowed, other posts than the marked post will have another string. - if ($markdata != false && $markdata->solvedpostid != false && $post->id != $markdata->solvedpostid) { + if ($multiplemarkssetting->allowmultiplemarks == 1 && $markdata != false && $markdata->solvedpostid != false + && $post->id != $markdata->solvedpostid) { $commands[] = html_writer::tag('a', $str->alsomarksolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); } else { From 0c6855dff3c509b1148a78672d4728764d08a26e Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 24 Apr 2023 14:36:14 +0200 Subject: [PATCH 07/35] feature problems solved, multiple marks are now really possible --- classes/ratings.php | 162 ++++++++++++++++++++++++++++++++++---------- locallib.php | 1 + 2 files changed, 126 insertions(+), 37 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 899755d6d1..7d26e04aad 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -77,6 +77,12 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati throw new moodle_exception('invalidcourseid'); } + // Are multiple marks allowed? + $markssetting = $DB->get_record('moodleoverflow', array('id' => $moodleoverflow->id), 'allowmultiplemarks'); + $multiplemarks = false; + if ($markssetting->allowmultiplemarks == 1) { + $multiplemarks = true; + } // Retrieve the contexts. $modulecontext = \context_module::instance($cm->id); $coursecontext = \context_course::instance($course->id); @@ -138,20 +144,28 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati throw new moodle_exception('notteacher', 'moodleoverflow'); } - // Get other ratings in the discussion. - $sql = "SELECT * - FROM {moodleoverflow_ratings} - WHERE discussionid = ? AND rating = ?"; - $otherrating = $DB->get_record_sql($sql, [ $discussion->id, $rating ]); - - // If there is an old rating, update it. Else create a new rating record. - if ($otherrating) { - return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); + // Check if multiple marks are not enabled. + if (!$multiplemarks) { + // Get other ratings in the discussion. + $sql = "SELECT * + FROM {moodleoverflow_ratings} + WHERE discussionid = ? AND rating = ?"; + $otherrating = $DB->get_record_sql($sql, [ $discussion->id, $rating ]); + + // If there is an old rating, update it. Else create a new rating record. + if ($otherrating) { + return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); + } else { + $mid = $moodleoverflow->id; + + return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); + } } else { + // If multiplemarks are allowed, only create a new rating. $mid = $moodleoverflow->id; - return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); } + } // Update an rating record. @@ -247,56 +261,96 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { $statusstarter = self::moodleoverflow_discussion_is_solved($discussionid, false); $statusteacher = self::moodleoverflow_discussion_is_solved($discussionid, true); - // The answer that is marked as correct by both is displayed first. + // The answers that are marked as correct by both are displayed first. if ($statusteacher && $statusstarter) { + $markedposts = array(); + foreach ($statusteacher as $solvedposts ) { + foreach ($statusstarter as $helpfulposts) { + // Is the same answer correct for both? + if ($solvedposts->postid == $helpfulposts->postid) { + // Save the post that is marked as solved and helpful and go to the next post. + $markedposts[] = $postscopy[$solvedposts->postid]; + break; + } + } + } + // Now sort the posts by their votes. + self::moodleoverflow_sort_post_by_votes($markedposts); - // Is the same answer correct for both? - if ($statusstarter->postid == $statusteacher->postid) { - + // Iterate trough the marked posts and add it to the new Order. + foreach ($markedposts as $post) { // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $statusstarter->postid; - unset($postscopy[$statusstarter->postid]); - - // Unset the stati to skip the following if-statements. - $statusstarter = false; - $statusteacher = false; + $neworder[] = (int) $post->id; + unset($postscopy[$post->id]); } } // If the answers the teacher marks are preferred, and only // the teacher marked an answer as solved, display it first. if ($preferteacher && $statusteacher) { + // Save the marked posts + $markedposts = array(); + foreach ($statusteacher as $solvedpost) { + if(array_key_exists($solvedpost->postid, $postscopy)) { + $markedposts[] = $postscopy[$solvedpost->postid]; + } + } + // Sort the solved answers. + self::moodleoverflow_sort_post_by_votes($markedposts); - // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $statusteacher->postid; - unset($postscopy[$statusteacher->postid]); - - // Unset the status to skip the following if-statements. - $statusteacher = false; + // Iterate trough the marked posts and add it to the new Order. + foreach ($markedposts as $post) { + // Add the post to the new order and delete it from the posts array. + $neworder[] = (int) $post->id; + unset($postscopy[$post->id]); + } } // If the user who started the discussion has marked // an answer as helpful, display this answer first. if ($statusstarter) { + // Save the marked posts + $markedposts = array(); + foreach ($statusstarter as $helpfulpost) { + if(array_key_exists($helpfulpost->postid, $postscopy)) { + $markedposts[] = $postscopy[$helpfulpost->postid]; + } + } + // Sort the helpful answers. + self::moodleoverflow_sort_post_by_votes($markedposts); - // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $statusstarter->postid; - unset($postscopy[$statusstarter->postid]); + // Iterate trough the marked posts and add it to the new Order. + foreach ($markedposts as $post) { + // Add the post to the new order and delete it from the posts array. + $neworder[] = (int) $post->id; + unset($postscopy[$post->id]); + } } // If a teacher has marked an answer as solved, display it next. if ($statusteacher) { + // Save the marked posts + $markedposts = array(); + foreach ($statusteacher as $solvedpost) { + if(array_key_exists($solvedpost->postid, $postscopy)) { + $markedposts[] = $postscopy[$solvedpost->postid]; + } + } + // Sort the solved answers. + self::moodleoverflow_sort_post_by_votes($markedposts); - // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $statusteacher->postid; - unset($postscopy[$statusteacher->postid]); + // Iterate trough the marked posts and add it to the new Order. + foreach ($markedposts as $post) { + // Add the post to the new order and delete it from the posts array. + $neworder[] = (int) $post->id; + unset($postscopy[$post->id]); + } } // All answers that are not marked by someone should now be left. // Search for all comments. foreach ($postscopy as $postid => $post) { - // Add all comments to the order. // They are independant from the votes. if ($post->parent != $parent->id) { @@ -426,8 +480,8 @@ public static function moodleoverflow_discussion_is_solved($discussionid, $teach // Check if a teacher marked a solution as solved. if ($DB->record_exists('moodleoverflow_ratings', array('discussionid' => $discussionid, 'rating' => 3))) { - // Return the rating record. - return $DB->get_record('moodleoverflow_ratings', array('discussionid' => $discussionid, 'rating' => 3)); + // Return the rating records. + return $DB->get_records('moodleoverflow_ratings', array('discussionid' => $discussionid, 'rating' => 3)); } // The teacher has not marked the discussion as solved. @@ -437,8 +491,8 @@ public static function moodleoverflow_discussion_is_solved($discussionid, $teach // Check if the topic starter marked a solution as helpful. if ($DB->record_exists('moodleoverflow_ratings', array('discussionid' => $discussionid, 'rating' => 4))) { - // Return the rating record. - return $DB->get_record('moodleoverflow_ratings', array('discussionid' => $discussionid, 'rating' => 4)); + // Return the rating records. + return $DB->get_records('moodleoverflow_ratings', array('discussionid' => $discussionid, 'rating' => 4)); } // The topic starter has not marked a solution as helpful. @@ -787,4 +841,38 @@ public static function moodleoverflow_user_can_rate($post, $modulecontext, $user && $post->reviewed == 1; } + private static function moodleoverflow_sort_post_by_votes(array $posts) { + // Function uses quicksort to sort the posts in descending order. + self::moodleoverflow_quicksort_post_by_votes($posts, 0, sizeof($posts) - 1); + + } + + private static function moodleoverflow_quicksort_post_by_votes(array $posts, $low, $high) { + if ($low >= $high) return; + $left = $low; + $right = $high; + $pivot = $posts[ ($low + $high) / 2]->votesdifference; + do { + while ($posts[$left]->votesdifference > $pivot) { + $left++; + } + while ($posts[$right]->votesdifference < $pivot) { + $right--; + } + if ($left <= $right) { + $temp = $posts[$right]; + $post[$right] = $posts[$left]; + $posts[$left] = $temp; + $right--; + $left++; + } + } while ($left <= $right); + if ($low < $right) { + self::moodleoverflow_quicksort_post_by_votes($posts, $low, $right); + } + if ($high > $left ) { + self::moodleoverflow_quicksort_post_by_votes($posts, $left, $high); + } + } + } diff --git a/locallib.php b/locallib.php index f7f9294d9f..a9af33f0d6 100644 --- a/locallib.php +++ b/locallib.php @@ -1022,6 +1022,7 @@ function moodleoverflow_get_all_discussion_posts($discussionid, $tracking, $modc // Assign the ratings to the matching posts. $posts[$postid]->upvotes = $discussionratings[$post->id]->upvotes; $posts[$postid]->downvotes = $discussionratings[$post->id]->downvotes; + $posts[$postid]->votesdifference = $posts[$postid]->upvotes - $posts[$postid]->downvotes; $posts[$postid]->statusstarter = $discussionratings[$post->id]->ishelpful; $posts[$postid]->statusteacher = $discussionratings[$post->id]->issolved; } From 865c60f40fa3452c35f59dcda96d226c5f5802e2 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 24 Apr 2023 14:52:13 +0200 Subject: [PATCH 08/35] revert problems fixed --- amd/build/rating.min.js | 2 +- amd/build/rating.min.js.map | 2 +- amd/src/rating.js | 16 ++++++---------- classes/ratings.php | 1 + discussion.php | 5 ++--- locallib.php | 9 ++------- 6 files changed, 13 insertions(+), 22 deletions(-) diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index b88babf908..ce2d7eeadb 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -5,6 +5,6 @@ define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/ * @module mod_moodleoverflow/rating * @copyright 2022 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemark){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","marknotsolved","markhelpful","alsomarkhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemark)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemark){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemark)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index b848a3e4d6..0df23bfbb9 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'marknotsolved', 'markhelpful', 'alsomarkhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n /*// Iterate trough all posts in the discussion and check if there are other marked posts.\n var othermarkedposts = 0;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = 1;\n break;\n }\n }\n // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' .\n // Else: do nothing, because if there is no marked post, the string doesn't change.\n if (othermarkedposts == 1) {\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n\n //el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n //await getString(`alsomark${action}`, 'mod_moodleoverflow');\n }\n else {\n\n }\n }\n }*/\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,gBAAiB,cAAe,kBAAmB,iBAChF,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBA0BhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHApI9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n /*\n // Iterate trough all posts in the discussion and check if there are other marked posts.\n var othermarkedposts = 0;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = 1;\n break;\n }\n }\n // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' .\n // Else: do nothing, because if there is no marked post, the string doesn't change.\n if (othermarkedposts == 1) {\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass)) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n }\n }\n }*/\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAuBhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHAjI9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index 0fb87925b1..1039a133ce 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -70,7 +70,7 @@ async function sendVote(postid, rating, userid) { */ export function init(userid, allowmultiplemark) { Prefetch.prefetchStrings('mod_moodleoverflow', - ['marksolved', 'alsomarksolved', 'marknotsolved', 'markhelpful', 'alsomarkhelpful', 'marknothelpful', + ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful', 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']); root.onclick = async(event) => { @@ -130,7 +130,7 @@ export function init(userid, allowmultiplemark) { postElement.classList.remove(htmlclass); actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow'); } - /*// Iterate trough all posts in the discussion and check if there are other marked posts. + // Iterate trough all posts in the discussion and check if there are other marked posts. var othermarkedposts = 0; for (const el of root.querySelectorAll('.moodleoverflowpost')) { if (el.classList.contains(htmlclass)) { @@ -142,16 +142,12 @@ export function init(userid, allowmultiplemark) { // Else: do nothing, because if there is no marked post, the string doesn't change. if (othermarkedposts == 1) { for (const el of root.querySelectorAll('.moodleoverflowpost')) { - if (el.classList.contains(htmlclass)) { - - //el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = - //await getString(`alsomark${action}`, 'mod_moodleoverflow'); - } - else { - + if (!el.classList.contains(htmlclass)) { + el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = + await getString(`alsomark${action}`, 'mod_moodleoverflow'); } } - }*/ + } } // If the post is being marked, mark it. if (!shouldRemove) { diff --git a/classes/ratings.php b/classes/ratings.php index 7c97de4df5..be010daf41 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -157,6 +157,7 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati // If there is an old rating, update it. Else create a new rating record. if ($otherrating) { return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); + } else { $mid = $moodleoverflow->id; diff --git a/discussion.php b/discussion.php index 7e81d33195..d751744169 100644 --- a/discussion.php +++ b/discussion.php @@ -76,8 +76,7 @@ if (in_array($ratingid, array(RATING_SOLVED, RATING_REMOVE_SOLVED, RATING_HELPFUL, RATING_REMOVE_HELPFUL))) { // Rate the post. - if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm, null, - $marksetting->allowmultiplemarks)) { + if (!\mod_moodleoverflow\ratings::moodleoverflow_add_rating($moodleoverflow, $ratedpost, $ratingid, $cm)) { throw new moodle_exception('ratingfailed', 'moodleoverflow'); } @@ -156,7 +155,7 @@ echo '<div id="moodleoverflow-posts"><div id="moodleoverflow-root">'; // if multiplemarks are on, then print the discussion considering the markdata, else print the discussion. -if ($marksetting->allowmultiplemarks == 1) { +if ($marksetting) { $multiplemarksdata = moodleoverflow_get_discussion_markdata($d); moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarksdata); } else { diff --git a/locallib.php b/locallib.php index b2e5123b61..2c322b2383 100644 --- a/locallib.php +++ b/locallib.php @@ -1243,9 +1243,6 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $permalink = new moodle_url($discussionlink); $permalink->set_anchor('p' . $post->id); - // Save the setting of multiplemarks. - $multiplemarkssetting = $DB->get_record('moodleoverflow', array('id' => $moodleoverflow->id), 'allowmultiplemarks'); - // If the user has started the discussion, he can mark the answer as helpful. $canmarkhelpful = (($USER->id == $discussion->userid) && ($USER->id != $post->userid) && ($iscomment != $post->parent) && !empty($post->parent)); @@ -1260,8 +1257,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co // If there is markdata: consider it. // Markdata saves the ID of a marked post in the discussion. // If multiplemarks are allowed, other posts than the marked post will have another string. - if ($multiplemarkssetting->allowmultiplemarks == 1 && $markdata != false && $markdata->helpfulpostid != false - && $post->id != $markdata->helpfulpostid) { + if ($markdata != false && $markdata->helpfulpostid != false && $post->id != $markdata->helpfulpostid) { $commands[] = html_writer::tag('a', $str->alsomarkhelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { @@ -1285,8 +1281,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co // If there is markdata: consider it. // Markdata saves the ID of a marked post in the discussion. // If multiplemarks are allowed, other posts than the marked post will have another string. - if ($multiplemarkssetting->allowmultiplemarks == 1 && $markdata != false && $markdata->solvedpostid != false - && $post->id != $markdata->solvedpostid) { + if ($markdata != false && $markdata->solvedpostid != false && $post->id != $markdata->solvedpostid) { $commands[] = html_writer::tag('a', $str->alsomarksolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); } else { From fe52f57403a6c4dfaa71d2f7c93378460f0f0d6f Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 24 Apr 2023 14:52:50 +0200 Subject: [PATCH 09/35] Revert "WIP: change button string if posts are marked" This reverts commit 5b04f0e2c1d83daeb51fd166b8f1c290ae125e1e. --- amd/build/rating.min.js.map | 2 +- amd/src/rating.js | 18 ----- discussion.php | 12 +-- lang/en/moodleoverflow.php | 9 ++- lib.php | 6 -- locallib.php | 142 +++++++++++------------------------- 6 files changed, 54 insertions(+), 135 deletions(-) diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 0df23bfbb9..25a7285043 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n /*\n // Iterate trough all posts in the discussion and check if there are other marked posts.\n var othermarkedposts = 0;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = 1;\n break;\n }\n }\n // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' .\n // Else: do nothing, because if there is no marked post, the string doesn't change.\n if (othermarkedposts == 1) {\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass)) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n }\n }\n }*/\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAuBhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHAjI9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAIhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHA9G9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index 1039a133ce..7730b52596 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -130,24 +130,6 @@ export function init(userid, allowmultiplemark) { postElement.classList.remove(htmlclass); actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow'); } - // Iterate trough all posts in the discussion and check if there are other marked posts. - var othermarkedposts = 0; - for (const el of root.querySelectorAll('.moodleoverflowpost')) { - if (el.classList.contains(htmlclass)) { - othermarkedposts = 1; - break; - } - } - // If there are other marked posts, iterate trough each post and update the string to 'also mark as ...' . - // Else: do nothing, because if there is no marked post, the string doesn't change. - if (othermarkedposts == 1) { - for (const el of root.querySelectorAll('.moodleoverflowpost')) { - if (!el.classList.contains(htmlclass)) { - el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = - await getString(`alsomark${action}`, 'mod_moodleoverflow'); - } - } - } } // If the post is being marked, mark it. if (!shouldRemove) { diff --git a/discussion.php b/discussion.php index d751744169..d5c79bfee5 100644 --- a/discussion.php +++ b/discussion.php @@ -143,6 +143,9 @@ // Start the side-output. echo $OUTPUT->header(); +// Print a text, if multiple marks are allowed. +moodleoverflow_print_multiplemarks_comment($modulecontext, $post); + echo $OUTPUT->heading(format_string($discussion->name), 1, 'discussionname'); // Guests and users can not subscribe to a discussion. @@ -154,14 +157,7 @@ echo '<div id="moodleoverflow-posts"><div id="moodleoverflow-root">'; -// if multiplemarks are on, then print the discussion considering the markdata, else print the discussion. -if ($marksetting) { - $multiplemarksdata = moodleoverflow_get_discussion_markdata($d); - moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarksdata); -} else { - moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post); -} - +moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post); echo '</div></div>'; diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index cd61080e6c..a128ed4a37 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -187,11 +187,9 @@ $string['ratingfailed'] = 'Rating failed. Try again.'; $string['rateownpost'] = 'You cannot rate your own post.'; $string['marksolved'] = 'Mark as solution'; -$string['alsomarksolved'] = 'Also mark as solution'; $string['marknotsolved'] = 'Remove solution mark'; -$string['markhelpful'] = 'Mark as helpful'; -$string['alsomarkhelpful'] = 'Also mark as helpful'; -$string['marknothelpful'] = 'Not helpful'; +$string['markhelpful'] = 'Mark as Helpful'; +$string['marknothelpful'] = 'Not Helpful'; $string['answer'] = '{$a} Answer'; $string['answers'] = '{$a} Answers'; @@ -330,6 +328,9 @@ $string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; $string['allowmultiplemarks'] = 'Multiple marks?'; $string['allowmultiplemarks_help'] = 'A post can be marked as helpful or solved. Within a discussion, only one post can be marked as helpful/solved. Click the checkbox to mark multiple posts as helpful/solved.'; +$string['multiplemarkscommentteacherownpost'] = 'Multiple marks are enabled, several posts can be marked as helpful or solved'; +$string['multiplemarkscommentstudentownpost'] = 'Multiple marks are enabled, you can mark several posts as helpful'; +$string['multiplemarkscommentteacher'] = 'Multiple marks are enabled, several posts can be marked as solved'; // Templates. $string['reputation'] = 'Reputation'; diff --git a/lib.php b/lib.php index 01ced85c7c..980856a25f 100644 --- a/lib.php +++ b/lib.php @@ -80,12 +80,6 @@ define('RATING_HELPFUL', 4); define('RATING_REMOVE_HELPFUL', 40); -// Mark constants. -define('MOODLEOVERFLOW_NEITHERHELPFULORSOLVED', 0); -define('MOODLEOVERFLOW_HELPFUL', 1); -define('MOODLEOVERFLOW_SOLVED', 2); -define('MOODLEOVERFLOW_HELPFULANDSOLVED', 3); - /* Moodle core API */ /** diff --git a/locallib.php b/locallib.php index 2c322b2383..b25af997ff 100644 --- a/locallib.php +++ b/locallib.php @@ -453,42 +453,6 @@ function moodleoverflow_print_forum_list($course, $cm, $movetopopup) { echo $renderer->render_forum_list($mustachedata); } - -/** - * Get the data about a the marks of a discussion: - * - if a helpful or solved post exists - * - which posts are helpful/solved - * - * Return an object with the data - * - * @param int $discussionid - * @return object - */ -function moodleoverflow_get_discussion_markdata($discussionid) { - $helpful = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussionid, false); - $solved = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussionid, true); - $markdata = new \stdClass(); - $markdata->markstatus = 0; - $markdata->helpfulpostid = false; - $markdata->solvedpostid = false; - if ($helpful) { - if ($solved) { - $markdata->markstatus = 3; - $markdata->helpfulpostid = $helpful->postid; - $markdata->solvedpostid = $solved->postid; - } else { - $markdata->markstatus = 2; - $markdata->helpfulpostid = $helpful->postid; - } - } else { - if ($solved) { - $markdata->markstatus = 1; - $markdata->solvedpostid = $solved->postid; - } - } - - return $markdata; -} /** * Returns an array of counts of replies for each discussion. * @@ -912,7 +876,35 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr return !$considerreviewstatus || $posttoreplyto->reviewed == 1; } +/** + * Prints a text, if multiple marks are allowed. + * + * @param stdClass $context The moodleoverflow context. + * @param stdClass $post The post object. + */ +function moodleoverflow_print_multiplemarks_comment($context, $post) { + global $USER; + + // Check if the current user is the starter of the discussion. + $ownpost = (isloggedin() && ($USER->id == $post->userid)); + + // Check if the current user can mark posts as solved. + $canmarksolved = (has_capability('mod/moodleoverflow:marksolved', $context)); + $comment = ''; + if ($ownpost) { + if ($canmarksolved) { + $comment = get_string('multiplemarkscommentteacherownpost', 'moodleoverflow'); + } else { + $comment = get_string('multiplemarkscommentstudentownpost', 'moodleoverflow'); + } + } + else if ($canmarksolved) { + $comment = get_string('multiplemarkscommentteacher', 'moodleoverflow'); + } + $comment = $comment . '<br>' . '<br>'; + echo $comment; +} /** * Prints a moodleoverflow discussion. * @@ -921,9 +913,8 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr * @param stdClass $moodleoverflow The moodleoverflow object * @param stdClass $discussion The discussion object * @param stdClass $post The post object - * @param boolean $markdata Object with information about marked posts. Only needed when multiplemarks are allowed */ -function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $markdata = false) { +function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post) { global $USER; // Check if the current user is the starter of the discussion. @@ -975,16 +966,9 @@ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discuss // Check if the post was read. $postread = !empty($post->postread); - // Check if there is markdata, if yes, print the starting post considering the markdata. - if ($markdata == false) { - // Print the starting post. - echo moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, - $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping); - } else { - // Print the starting post. - echo moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, - $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping, 0, $markdata); - } + // Print the starting post. + echo moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, + $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping); // Print answer divider. if ($answercount == 1) { @@ -996,16 +980,9 @@ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discuss echo '<div id="moodleoverflow-posts">'; - // Check if there is markdata, if yes, print the other posts considering the markdata. - if ($markdata == false) { - // Print the other posts. - echo moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, - null, $usermapping); - } else { - // Print the other posts. - echo moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, - null, $usermapping, $markdata); - } + // Print the other posts. + echo moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, + null, $usermapping); echo '</div>'; } @@ -1134,7 +1111,6 @@ function moodleoverflow_get_all_discussion_posts($discussionid, $tracking, $modc * @param bool $iscomment * @param array $usermapping * @param int $level - * @param object $markdata Information about marked posts in a discussion, only needed if multiplemarks are allowed * @return void|null * @throws coding_exception * @throws dml_exception @@ -1144,8 +1120,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $ownpost = false, $link = false, $footer = '', $highlight = '', $postisread = null, $dummyifcantsee = true, $istracked = false, - $iscomment = false, $usermapping = [], $level = 0, $markdata = false) { - global $USER, $CFG, $OUTPUT, $PAGE, $DB; + $iscomment = false, $usermapping = [], $level = 0) { + global $USER, $CFG, $OUTPUT, $PAGE; // Require the filelib. require_once($CFG->libdir . '/filelib.php'); @@ -1201,10 +1177,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $str->markread = get_string('markread', 'moodleoverflow'); $str->markunread = get_string('markunread', 'moodleoverflow'); $str->marksolved = get_string('marksolved', 'moodleoverflow'); - $str->alsomarksolved = get_string('alsomarksolved', 'moodleoverflow'); $str->marknotsolved = get_string('marknotsolved', 'moodleoverflow'); $str->markhelpful = get_string('markhelpful', 'moodleoverflow'); - $str->alsomarkhelpful = get_string('alsomarkhelpful', 'moodleoverflow'); $str->marknothelpful = get_string('marknothelpful', 'moodleoverflow'); } @@ -1254,16 +1228,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $commands[] = html_writer::tag('a', $str->marknothelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { - // If there is markdata: consider it. - // Markdata saves the ID of a marked post in the discussion. - // If multiplemarks are allowed, other posts than the marked post will have another string. - if ($markdata != false && $markdata->helpfulpostid != false && $post->id != $markdata->helpfulpostid) { - $commands[] = html_writer::tag('a', $str->alsomarkhelpful, + $commands[] = html_writer::tag('a', $str->markhelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); - } else { - $commands[] = html_writer::tag('a', $str->markhelpful, - array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); - } } } @@ -1278,16 +1244,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $commands[] = html_writer::tag('a', $str->marknotsolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); } else { - // If there is markdata: consider it. - // Markdata saves the ID of a marked post in the discussion. - // If multiplemarks are allowed, other posts than the marked post will have another string. - if ($markdata != false && $markdata->solvedpostid != false && $post->id != $markdata->solvedpostid) { - $commands[] = html_writer::tag('a', $str->alsomarksolved, - array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); - } else { - $commands[] = html_writer::tag('a', $str->marksolved, + $commands[] = html_writer::tag('a', $str->marksolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); - } } } @@ -1508,14 +1466,13 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co * @param array $posts Array of posts within the discussion * @param bool $iscomment Whether the current post is a comment * @param array $usermapping - * @param object $markdata Information about marked posts in a discussion, only needed if multiplemarks are allowed * @return string * @throws coding_exception * @throws dml_exception * @throws moodle_exception */ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $discussion, $parent, - $istracked, $posts, $iscomment = null, $usermapping = [], $markdata = false) { + $istracked, $posts, $iscomment = null, $usermapping = []) { global $USER; // Prepare the output. @@ -1555,24 +1512,13 @@ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $disc // Determine whether the post has been read by the current user. $postread = !empty($post->postread); - // Check if there is markdata, if yes print the answer and children considering the markdata. - if ($markdata == false) { - // Print the answer. - $output .= moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, + // Print the answer. + $output .= moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, $ownpost, false, '', '', $postread, true, $istracked, $parentid, $usermapping, $level); - // Print its children. - $output .= moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, + // Print its children. + $output .= moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, $parentid, $usermapping); - } else { - // Print the answer. - $output .= moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, - $ownpost, false, '', '', $postread, true, $istracked, $parentid, $usermapping, $level, $markdata); - - // Print its children. - $output .= moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, - $discussion, $post, $istracked, $posts, $parentid, $usermapping, $markdata); - } // End the div. $output .= "</div>\n"; From 68609d67278af39d3ddfa84ee817e5827a058fe3 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 24 Apr 2023 15:02:02 +0200 Subject: [PATCH 10/35] Revert "comment added for marks setting in discussion.php" This reverts commit b98a9de382d2a15fee5d50ca98f30280e083392d. --- discussion.php | 4 ---- lang/en/moodleoverflow.php | 3 --- locallib.php | 31 +------------------------------ 3 files changed, 1 insertion(+), 37 deletions(-) diff --git a/discussion.php b/discussion.php index d5c79bfee5..cbc7fee593 100644 --- a/discussion.php +++ b/discussion.php @@ -142,10 +142,6 @@ // Start the side-output. echo $OUTPUT->header(); - -// Print a text, if multiple marks are allowed. -moodleoverflow_print_multiplemarks_comment($modulecontext, $post); - echo $OUTPUT->heading(format_string($discussion->name), 1, 'discussionname'); // Guests and users can not subscribe to a discussion. diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index a128ed4a37..bd13b86e7e 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -328,9 +328,6 @@ $string['attachment_help'] = 'You can optionally attach one or more files to a forum post. If you attach an image, it will be displayed after the message.'; $string['allowmultiplemarks'] = 'Multiple marks?'; $string['allowmultiplemarks_help'] = 'A post can be marked as helpful or solved. Within a discussion, only one post can be marked as helpful/solved. Click the checkbox to mark multiple posts as helpful/solved.'; -$string['multiplemarkscommentteacherownpost'] = 'Multiple marks are enabled, several posts can be marked as helpful or solved'; -$string['multiplemarkscommentstudentownpost'] = 'Multiple marks are enabled, you can mark several posts as helpful'; -$string['multiplemarkscommentteacher'] = 'Multiple marks are enabled, several posts can be marked as solved'; // Templates. $string['reputation'] = 'Reputation'; diff --git a/locallib.php b/locallib.php index b25af997ff..a9af33f0d6 100644 --- a/locallib.php +++ b/locallib.php @@ -876,35 +876,6 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr return !$considerreviewstatus || $posttoreplyto->reviewed == 1; } -/** - * Prints a text, if multiple marks are allowed. - * - * @param stdClass $context The moodleoverflow context. - * @param stdClass $post The post object. - */ -function moodleoverflow_print_multiplemarks_comment($context, $post) { - global $USER; - - // Check if the current user is the starter of the discussion. - $ownpost = (isloggedin() && ($USER->id == $post->userid)); - - // Check if the current user can mark posts as solved. - $canmarksolved = (has_capability('mod/moodleoverflow:marksolved', $context)); - $comment = ''; - - if ($ownpost) { - if ($canmarksolved) { - $comment = get_string('multiplemarkscommentteacherownpost', 'moodleoverflow'); - } else { - $comment = get_string('multiplemarkscommentstudentownpost', 'moodleoverflow'); - } - } - else if ($canmarksolved) { - $comment = get_string('multiplemarkscommentteacher', 'moodleoverflow'); - } - $comment = $comment . '<br>' . '<br>'; - echo $comment; -} /** * Prints a moodleoverflow discussion. * @@ -917,7 +888,7 @@ function moodleoverflow_print_multiplemarks_comment($context, $post) { function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post) { global $USER; - // Check if the current user is the starter of the discussion. + // Check if the current is the starter of the discussion. $ownpost = (isloggedin() && ($USER->id == $post->userid)); // Fetch the modulecontext. From a781f29ab6be083c343c17b65c008b4e87239542 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 24 Apr 2023 16:22:40 +0200 Subject: [PATCH 11/35] mark button strings update on reload, only js still needed --- amd/build/rating.min.js | 2 +- amd/build/rating.min.js.map | 2 +- amd/src/rating.js | 6 ++--- discussion.php | 8 +++++-- lang/en/moodleoverflow.php | 4 +++- locallib.php | 47 ++++++++++++++++++++++++++++--------- 6 files changed, 50 insertions(+), 19 deletions(-) diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index ce2d7eeadb..fc1ba94c81 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -5,6 +5,6 @@ define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/ * @module mod_moodleoverflow/rating * @copyright 2022 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemark){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemark)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemarks)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 25a7285043..64007e289e 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemark) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemark == 0) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemark","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,qCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAON,GAArBC,sBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAIhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHA9G9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemarks // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemarks == false) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAOL,GAAtBC,uBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAIhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHA9G9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index 7730b52596..f866b749ff 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -65,10 +65,10 @@ async function sendVote(postid, rating, userid) { * Init function. * * @param {int} userid - * @param {int} allowmultiplemark // 1 means allowed, 0 means not allowed. + * @param {int} allowmultiplemarks // 1 means allowed, 0 means not allowed. * */ -export function init(userid, allowmultiplemark) { +export function init(userid, allowmultiplemarks) { Prefetch.prefetchStrings('mod_moodleoverflow', ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful', 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']); @@ -117,7 +117,7 @@ export function init(userid, allowmultiplemark) { then add a mark, if the post is being marked. */ - if (allowmultiplemark == 0) { + if (allowmultiplemarks == false) { // Delete all marks in the discussion for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) { el.classList.remove(htmlclass); diff --git a/discussion.php b/discussion.php index cbc7fee593..54014664fa 100644 --- a/discussion.php +++ b/discussion.php @@ -52,6 +52,10 @@ // Save the allowmultiplemarks setting. $marksetting = $DB->get_record('moodleoverflow', array('id' => $moodleoverflow->id), 'allowmultiplemarks'); +$multiplemarks = false; +if ($marksetting->allowmultiplemarks == 1) { + $multiplemarks = true; +} // Get the related coursemodule and its context. if (!$cm = get_coursemodule_from_instance('moodleoverflow', $moodleoverflow->id, $course->id)) { @@ -131,7 +135,7 @@ $PAGE->requires->js_call_amd('mod_moodleoverflow/reviewing', 'init'); -$PAGE->requires->js_call_amd('mod_moodleoverflow/rating', 'init', [$USER->id, $marksetting->allowmultiplemarks]); +$PAGE->requires->js_call_amd('mod_moodleoverflow/rating', 'init', [$USER->id, $multiplemarks]); // Initiate the page. $PAGE->set_title($course->shortname . ': ' . format_string($discussion->name)); @@ -153,7 +157,7 @@ echo '<div id="moodleoverflow-posts"><div id="moodleoverflow-root">'; -moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post); +moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarks); echo '</div></div>'; diff --git a/lang/en/moodleoverflow.php b/lang/en/moodleoverflow.php index bd13b86e7e..2f87de27d2 100644 --- a/lang/en/moodleoverflow.php +++ b/lang/en/moodleoverflow.php @@ -187,8 +187,10 @@ $string['ratingfailed'] = 'Rating failed. Try again.'; $string['rateownpost'] = 'You cannot rate your own post.'; $string['marksolved'] = 'Mark as solution'; +$string['alsomarksolved'] = "Also mark as solution"; $string['marknotsolved'] = 'Remove solution mark'; -$string['markhelpful'] = 'Mark as Helpful'; +$string['markhelpful'] = 'Mark as helpful'; +$string['alsomarkhelpful'] = "Also mark as helpful"; $string['marknothelpful'] = 'Not Helpful'; $string['answer'] = '{$a} Answer'; $string['answers'] = '{$a} Answers'; diff --git a/locallib.php b/locallib.php index a9af33f0d6..c9309ac845 100644 --- a/locallib.php +++ b/locallib.php @@ -241,6 +241,8 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - $preparedarray[$i]['starterlink'] = null; if ($statusstarter) { $link = '/mod/moodleoverflow/discussion.php?d='; + $statusstarter = $statusstarter[array_key_first($statusstarter)]; + $preparedarray[$i]['starterlink'] = new moodle_url($link . $statusstarter->discussionid . '#p' . $statusstarter->postid); } @@ -250,6 +252,8 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - $preparedarray[$i]['teacherlink'] = null; if ($statusteacher) { $link = '/mod/moodleoverflow/discussion.php?d='; + $statusteacher = $statusteacher[array_key_first($statusteacher)]; + $preparedarray[$i]['teacherlink'] = new moodle_url($link . $statusteacher->discussionid . '#p' . $statusteacher->postid); } @@ -453,6 +457,7 @@ function moodleoverflow_print_forum_list($course, $cm, $movetopopup) { echo $renderer->render_forum_list($mustachedata); } + /** * Returns an array of counts of replies for each discussion. * @@ -885,9 +890,8 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr * @param stdClass $discussion The discussion object * @param stdClass $post The post object */ -function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post) { +function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarks = false) { global $USER; - // Check if the current is the starter of the discussion. $ownpost = (isloggedin() && ($USER->id == $post->userid)); @@ -939,7 +943,7 @@ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discuss // Print the starting post. echo moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, - $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping); + $ownpost, false, '', '', $postread, true, $istracked, 0, $usermapping, 0, $multiplemarks); // Print answer divider. if ($answercount == 1) { @@ -953,7 +957,7 @@ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discuss // Print the other posts. echo moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, $discussion, $post, $istracked, $posts, - null, $usermapping); + null, $usermapping, $multiplemarks); echo '</div>'; } @@ -1091,7 +1095,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $ownpost = false, $link = false, $footer = '', $highlight = '', $postisread = null, $dummyifcantsee = true, $istracked = false, - $iscomment = false, $usermapping = [], $level = 0) { + $iscomment = false, $usermapping = [], $level = 0, $multiplemarks = false) { global $USER, $CFG, $OUTPUT, $PAGE; // Require the filelib. @@ -1148,8 +1152,10 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $str->markread = get_string('markread', 'moodleoverflow'); $str->markunread = get_string('markunread', 'moodleoverflow'); $str->marksolved = get_string('marksolved', 'moodleoverflow'); + $str->alsomarksolved = get_string('alsomarksolved', 'moodleoverflow'); $str->marknotsolved = get_string('marknotsolved', 'moodleoverflow'); $str->markhelpful = get_string('markhelpful', 'moodleoverflow'); + $str->alsomarkhelpful = get_string('alsomarkhelpful', 'moodleoverflow'); $str->marknothelpful = get_string('marknothelpful', 'moodleoverflow'); } @@ -1188,19 +1194,32 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $permalink = new moodle_url($discussionlink); $permalink->set_anchor('p' . $post->id); + // Check if multiplemarks are allowed, if so, check if there are already marked posts. + $helpfulposts = false; + $solvedposts = false; + if ($multiplemarks) { + $helpfulposts = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->id, false); + $solvedposts = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->id, true); + } + // If the user has started the discussion, he can mark the answer as helpful. $canmarkhelpful = (($USER->id == $discussion->userid) && ($USER->id != $post->userid) && ($iscomment != $post->parent) && !empty($post->parent)); if ($canmarkhelpful) { - // When the post is already marked, remove the mark instead. $link = '/mod/moodleoverflow/discussion.php'; if ($post->statusstarter) { $commands[] = html_writer::tag('a', $str->marknothelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { - $commands[] = html_writer::tag('a', $str->markhelpful, + // If there are already marked posts, change the string of the button. + if($helpfulposts) { + $commands[] = html_writer::tag('a', $str->alsomarkhelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); + } else { + $commands[] = html_writer::tag('a', $str->markhelpful, + array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); + } } } @@ -1215,8 +1234,14 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $commands[] = html_writer::tag('a', $str->marknotsolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); } else { - $commands[] = html_writer::tag('a', $str->marksolved, + // If there are already marked posts, change the string of the button. + if ($solvedposts) { + $commands[] = html_writer::tag('a', $str->alsomarksolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); + } else { + $commands[] = html_writer::tag('a', $str->marksolved, + array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); + } } } @@ -1443,7 +1468,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co * @throws moodle_exception */ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $discussion, $parent, - $istracked, $posts, $iscomment = null, $usermapping = []) { + $istracked, $posts, $iscomment = null, $usermapping = [], $multiplemarks = false) { global $USER; // Prepare the output. @@ -1485,11 +1510,11 @@ function moodleoverflow_print_posts_nested($course, &$cm, $moodleoverflow, $disc // Print the answer. $output .= moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $course, - $ownpost, false, '', '', $postread, true, $istracked, $parentid, $usermapping, $level); + $ownpost, false, '', '', $postread, true, $istracked, $parentid, $usermapping, $level, $multiplemarks); // Print its children. $output .= moodleoverflow_print_posts_nested($course, $cm, $moodleoverflow, - $discussion, $post, $istracked, $posts, $parentid, $usermapping); + $discussion, $post, $istracked, $posts, $parentid, $usermapping, $multiplemarks); // End the div. $output .= "</div>\n"; From 6671a637b9e899346730e495513f83d0519522fc Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Tue, 25 Apr 2023 15:50:11 +0200 Subject: [PATCH 12/35] js added to change action button strings. Feature ready for pull request --- amd/build/rating.min.js | 2 +- amd/build/rating.min.js.map | 2 +- amd/src/rating.js | 41 +++++++++++++++++++++++++++++++++++-- classes/ratings.php | 31 ++++++++++++++-------------- locallib.php | 2 +- 5 files changed, 58 insertions(+), 20 deletions(-) diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index fc1ba94c81..f60ce3513a 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -5,6 +5,6 @@ define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/ * @module mod_moodleoverflow/rating * @copyright 2022 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),0==allowmultiplemarks)for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");else shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"));shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),allowmultiplemarks)shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"),changeStrings(htmlclass,action));else for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"),allowmultiplemarks&&changeStrings(htmlclass,action))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}async function changeStrings(htmlclass,action){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","markhelpful","alsomarkhelpful"]);var othermarkedposts=!1;for(const el of root.querySelectorAll(".moodleoverflowpost"))if(el.classList.contains(htmlclass)){othermarkedposts=!0;break}for(const el of root.querySelectorAll(".moodleoverflowpost"))!el.classList.contains(htmlclass)&&el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]'))&&(el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=othermarkedposts?await(0,_str.get_string)("alsomark".concat(action),"mod_moodleoverflow"):await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"))}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 64007e289e..11f1b470a8 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {int} allowmultiplemarks // 1 means allowed, 0 means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (allowmultiplemarks == false) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n }\n }\n }\n };\n\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","el","querySelectorAll","remove","textContent","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAOL,GAAtBC,uBAEK,MAAMiC,MAAM/B,KAAKgC,iBAAiB,uBAAyBT,WAC5DQ,GAAGN,UAAUQ,OAAOV,WACpBQ,GAAGV,qDAA8Cd,cAAY2B,kBACnD,iCAAiB3B,QAAU,2BAIrCiB,eACAf,YAAYgB,UAAUQ,OAAOV,WAC7BpB,cAAc+B,kBAAoB,iCAAiB3B,QAAU,uBAIhEiB,eACDf,YAAYgB,UAAUU,IAAIZ,WAC1BpB,cAAc+B,kBAAoB,oCAAoB3B,QAAU,iHA9G9EY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOoC,SAASC,eAAe,sCAStBzB,SAASF,OAAQoB,OAAQjC,cAC9ByC,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,UACJ9B,KAAKgC,gEAAyDnC,cAAY+C,SAASC,IAC/EA,EAAEX,YAAcI,SAASQ,eAAzB,IAEJ9C,KAAKgC,gEAAyDM,SAASS,eAAaH,SAASC,IACzFA,EAAEX,YAAcI,SAASU,eAAzB,IAEJhD,KAAKgC,gEAAyDtB,cAAYkC,SAASC,IAC/EA,EAAEX,YAAcI,SAASW,UAAzB,IAEGX"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only usable if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index f866b749ff..41ac768c30 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -65,7 +65,7 @@ async function sendVote(postid, rating, userid) { * Init function. * * @param {int} userid - * @param {int} allowmultiplemarks // 1 means allowed, 0 means not allowed. + * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed. * */ export function init(userid, allowmultiplemarks) { @@ -117,7 +117,7 @@ export function init(userid, allowmultiplemarks) { then add a mark, if the post is being marked. */ - if (allowmultiplemarks == false) { + if (!allowmultiplemarks) { // Delete all marks in the discussion for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) { el.classList.remove(htmlclass); @@ -129,15 +129,52 @@ export function init(userid, allowmultiplemarks) { if (shouldRemove) { postElement.classList.remove(htmlclass); actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow'); + changeStrings(htmlclass, action); } } // If the post is being marked, mark it. if (!shouldRemove) { postElement.classList.add(htmlclass); actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow'); + if (allowmultiplemarks) { + changeStrings(htmlclass, action); + } } + } } }; +} + +/** + * Function to change the String of the post data-action button. + * Only usable if mulitplemarks are allowed. + * @param {string} htmlclass the class where the String is being updated + * @param {string} action helpful or solved mark + */ +async function changeStrings(htmlclass, action) { + Prefetch.prefetchStrings('mod_moodleoverflow', + ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]); + + // 1. Step: Are there other posts in the Discussion, that are solved/helpful? + var othermarkedposts = false; + for (const el of root.querySelectorAll('.moodleoverflowpost')) { + if (el.classList.contains(htmlclass)) { + othermarkedposts = true; + break; + } + } + // 2. Step: Change the strings of the action Button of the unmarked posts. + for (const el of root.querySelectorAll('.moodleoverflowpost')) { + if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action="${action}"]`)) { + if (othermarkedposts) { + el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = + await getString(`alsomark${action}`, 'mod_moodleoverflow'); + } else { + el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent = + await getString(`mark${action}`, 'mod_moodleoverflow'); + } + } + } } \ No newline at end of file diff --git a/classes/ratings.php b/classes/ratings.php index be010daf41..76ea3246fe 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -157,11 +157,12 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati // If there is an old rating, update it. Else create a new rating record. if ($otherrating) { return self::moodleoverflow_update_rating_record($post->id, $rating, $userid, $otherrating->id, $modulecontext); - + } else { $mid = $moodleoverflow->id; - return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); + return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, + $rating, $userid, $modulecontext); } } else { @@ -169,7 +170,6 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati $mid = $moodleoverflow->id; return self::moodleoverflow_add_rating_record($mid, $discussion->id, $post->id, $rating, $userid, $modulecontext); } - } // Update an rating record. @@ -268,9 +268,9 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // The answers that are marked as correct by both are displayed first. if ($statusteacher && $statusstarter) { $markedposts = array(); - foreach ($statusteacher as $solvedposts ) { + foreach ($statusteacher as $solvedposts) { foreach ($statusstarter as $helpfulposts) { - // Is the same answer correct for both? + // Is the same answer correct for both? if ($solvedposts->postid == $helpfulposts->postid) { // Save the post that is marked as solved and helpful and go to the next post. $markedposts[] = $postscopy[$solvedposts->postid]; @@ -292,10 +292,10 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // If the answers the teacher marks are preferred, and only // the teacher marked an answer as solved, display it first. if ($preferteacher && $statusteacher) { - // Save the marked posts + // Save the marked posts. $markedposts = array(); foreach ($statusteacher as $solvedpost) { - if(array_key_exists($solvedpost->postid, $postscopy)) { + if (array_key_exists($solvedpost->postid, $postscopy)) { $markedposts[] = $postscopy[$solvedpost->postid]; } } @@ -313,10 +313,10 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // If the user who started the discussion has marked // an answer as helpful, display this answer first. if ($statusstarter) { - // Save the marked posts + // Save the marked posts. $markedposts = array(); foreach ($statusstarter as $helpfulpost) { - if(array_key_exists($helpfulpost->postid, $postscopy)) { + if (array_key_exists($helpfulpost->postid, $postscopy)) { $markedposts[] = $postscopy[$helpfulpost->postid]; } } @@ -333,10 +333,10 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // If a teacher has marked an answer as solved, display it next. if ($statusteacher) { - // Save the marked posts + // Save the marked posts. $markedposts = array(); foreach ($statusteacher as $solvedpost) { - if(array_key_exists($solvedpost->postid, $postscopy)) { + if (array_key_exists($solvedpost->postid, $postscopy)) { $markedposts[] = $postscopy[$solvedpost->postid]; } } @@ -847,15 +847,16 @@ public static function moodleoverflow_user_can_rate($post, $modulecontext, $user private static function moodleoverflow_sort_post_by_votes(array $posts) { // Function uses quicksort to sort the posts in descending order. - self::moodleoverflow_quicksort_post_by_votes($posts, 0, sizeof($posts) - 1); - + self::moodleoverflow_quicksort_post_by_votes($posts, 0, count($posts) - 1); } private static function moodleoverflow_quicksort_post_by_votes(array $posts, $low, $high) { - if ($low >= $high) return; + if ($low >= $high) { + return; + } $left = $low; $right = $high; - $pivot = $posts[ ($low + $high) / 2]->votesdifference; + $pivot = $posts[($low + $high) / 2]->votesdifference; do { while ($posts[$left]->votesdifference > $pivot) { $left++; diff --git a/locallib.php b/locallib.php index c9309ac845..7a42655ec3 100644 --- a/locallib.php +++ b/locallib.php @@ -1213,7 +1213,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { // If there are already marked posts, change the string of the button. - if($helpfulposts) { + if ($helpfulposts) { $commands[] = html_writer::tag('a', $str->alsomarkhelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { From 5e11d7df92e12ac19b01d535ad68b33988abf980 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 8 May 2023 11:54:16 +0200 Subject: [PATCH 13/35] update 4.2 --- .github/workflows/moodle-ci.yml | 20 ++++++++++++++++---- .github/workflows/moodle-release.yml | 2 +- version.php | 4 ++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index f1fb3f254f..c020ab22d4 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -8,8 +8,8 @@ jobs: strategy: matrix: - php: ['8.0'] - moodle-branch: ['MOODLE_401_STABLE'] + php: ['8.1'] + moodle-branch: ['MOODLE_402_STABLE'] database: ['pgsql'] steps: @@ -110,8 +110,8 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.0'] - moodle-branch: ['MOODLE_311_STABLE', 'MOODLE_400_STABLE', 'MOODLE_401_STABLE'] + php: ['8.0', '8.1'] + moodle-branch: ['MOODLE_401_STABLE', 'MOODLE_402_STABLE'] database: ['mariadb', 'pgsql'] include: - php: '7.4' @@ -120,6 +120,18 @@ jobs: - php: '7.4' moodle-branch: 'MOODLE_39_STABLE' database: 'pgsql' + - php: '8.0' + moodle-branch: 'MOODLE_311_STABLE' + database: 'mariadb' + - php: '8.0' + moodle-branch: 'MOODLE_311_STABLE' + database: 'pgsql' + - php: '8.0' + moodle-branch: 'MOODLE_400_STABLE' + database: 'mariadb' + - php: '8.0' + moodle-branch: 'MOODLE_400_STABLE' + database: 'pgsql' steps: - name: Start MariaDB diff --git a/.github/workflows/moodle-release.yml b/.github/workflows/moodle-release.yml index 97c70a6554..317a7916fa 100644 --- a/.github/workflows/moodle-release.yml +++ b/.github/workflows/moodle-release.yml @@ -44,7 +44,7 @@ jobs: --data-urlencode "altdownloadurl=${ZIPURL}" \ --data-urlencode "releasenotes=${BODY}" \ --data-urlencode "releasenotesformat=4") - echo "::set-output name=response::${RESPONSE}" + echo "response=${RESPONSE}" >> $GITHUB_OUTPUT - name: Evaluate the response id: evaluate-response env: diff --git a/version.php b/version.php index 45384c4fd9..7215a84622 100644 --- a/version.php +++ b/version.php @@ -28,8 +28,8 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'mod_moodleoverflow'; -$plugin->version = 2023050801; -$plugin->release = 'v4.1-r1'; +$plugin->version = 2023050802; +$plugin->release = 'v4.2-r1'; $plugin->requires = 2020061500; // Requires Moodle 3.9+. $plugin->maturity = MATURITY_STABLE; $plugin->dependencies = array(); From 5d3ccadf86ce1ab6b5d0f546cb16380244a1cb99 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 8 May 2023 13:45:34 +0200 Subject: [PATCH 14/35] phpUnit issues fixed for 402 update --- classes/task/send_mails.php | 2 +- lib.php | 4 ++-- tests/review_test.php | 12 +++++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/classes/task/send_mails.php b/classes/task/send_mails.php index 7417ee6a38..0c1d445334 100644 --- a/classes/task/send_mails.php +++ b/classes/task/send_mails.php @@ -128,7 +128,7 @@ public function send_review_notifications() { foreach ($usersto as $userto) { try { - cron_setup_user($userto, $course); + \core\cron::setup_user($userto, $course); $maildata = new moodleoverflow_email( $course, diff --git a/lib.php b/lib.php index 980856a25f..fe78089abb 100644 --- a/lib.php +++ b/lib.php @@ -749,7 +749,7 @@ function moodleoverflow_send_mails() { $userto->markposts = array(); // Cache the capabilities of the user. - cron_setup_user($userto); + \core\cron::setup_user($userto); // Reset the caches. foreach ($coursemodules as $moodleoverflowid => $unused) { @@ -838,7 +838,7 @@ function moodleoverflow_send_mails() { } // Setup roles and languages. - cron_setup_user($userto, $course); + \core\cron::setup_user($userto, $course); // Cache the users capability to view full names. if (!isset($userto->viewfullnames[$moodleoverflow->id])) { diff --git a/tests/review_test.php b/tests/review_test.php index b6e2cb0562..1dfc8cd2d2 100644 --- a/tests/review_test.php +++ b/tests/review_test.php @@ -30,7 +30,6 @@ global $CFG; require_once($CFG->dirroot . '/mod/moodleoverflow/lib.php'); -require_once($CFG->dirroot . '/mod/moodleoverflow/externallib.php'); /** * PHPUnit Tests for testing readtracking. @@ -38,6 +37,7 @@ * @package mod_moodleoverflow * @copyright 2017 Kennet Winter <k_wint10@uni-muenster.de> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * * @group mod_moodleoverflow */ class review_test extends \advanced_testcase { @@ -104,10 +104,13 @@ protected function tearDown(): void { } /** + * @runInSeparateProcess * Test reviews functionality in forums where teachers should review everything. */ public function test_forum_review_everything() { - global $DB; + global $DB, $CFG; + require_once($CFG->dirroot . '/mod/moodleoverflow/externallib.php'); + $options = array('course' => $this->course->id, 'needsreview' => review::EVERYTHING, 'forcesubscribe' => MOODLEOVERFLOW_FORCESUBSCRIBE); $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); @@ -179,10 +182,13 @@ public function test_forum_review_everything() { } /** + * @runInSeparateProcess * Test reviews functionality in forums where teachers should review questions. */ public function test_forum_review_only_questions() { - global $DB; + global $DB, $CFG; + require_once($CFG->dirroot . '/mod/moodleoverflow/externallib.php'); + $options = array('course' => $this->course->id, 'needsreview' => review::QUESTIONS, 'forcesubscribe' => MOODLEOVERFLOW_FORCESUBSCRIBE); $moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $options); From 32e14fbac5bf2bf669950b492809969036026b9b Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 8 May 2023 15:48:41 +0200 Subject: [PATCH 15/35] phpdoc issues fixed --- classes/capabilities.php | 35 ++++++++++++ classes/tables/userstats_table.php | 63 +++++++++++++++++++-- classes/task/send_mails.php | 9 ++- lib.php | 14 ++++- locallib.php | 12 +++- renderer.php | 4 ++ tests/behat/behat_mod_moodleoverflow.php | 4 ++ tests/dailymail_test.php | 13 ++++- tests/review_test.php | 6 +- tests/userstats_test.php | 72 +++++++++++++++++++++--- 10 files changed, 209 insertions(+), 23 deletions(-) diff --git a/classes/capabilities.php b/classes/capabilities.php index be17015033..44dda716d2 100644 --- a/classes/capabilities.php +++ b/classes/capabilities.php @@ -35,22 +35,57 @@ */ class capabilities { + /** capability */ const ADD_INSTANCE = 'mod/moodleoverflow:addinstance'; + + /** capability */ const VIEW_DISCUSSION = 'mod/moodleoverflow:viewdiscussion'; + + /** capability */ const REPLY_POST = 'mod/moodleoverflow:replypost'; + + /** capability */ const START_DISCUSSION = 'mod/moodleoverflow:startdiscussion'; + + /** capability */ const EDIT_ANY_POST = 'mod/moodleoverflow:editanypost'; + + /** capability */ const DELETE_OWN_POST = 'mod/moodleoverflow:deleteownpost'; + + /** capability */ const DELETE_ANY_POST = 'mod/moodleoverflow:deleteanypost'; + + /** capability */ const RATE_POST = 'mod/moodleoverflow:ratepost'; + + /** capability */ const MARK_SOLVED = 'mod/moodleoverflow:marksolved'; + + /** capability */ const MANAGE_SUBSCRIPTIONS = 'mod/moodleoverflow:managesubscriptions'; + + /** capability */ const ALLOW_FORCE_SUBSCRIBE = 'mod/moodleoverflow:allowforcesubscribe'; + + /** capability */ const CREATE_ATTACHMENT = 'mod/moodleoverflow:createattachment'; + + /** capability */ const REVIEW_POST = 'mod/moodleoverflow:reviewpost'; + /** @var array */ private static $cache = []; + /** + * Saves the cache from has_capability. + * + * @param string $capability The capability that is being checked. + * @param context $context The context. + * @param int|null $userid The user ID. + * + * @return bool true or false + */ public static function has(string $capability, context $context, $userid = null): bool { global $USER; if (!$userid) { diff --git a/classes/tables/userstats_table.php b/classes/tables/userstats_table.php index 4883aeb58b..5d040b1990 100644 --- a/classes/tables/userstats_table.php +++ b/classes/tables/userstats_table.php @@ -39,14 +39,26 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class userstats_table extends \flexible_table { - private $courseid; // Course ID. - private $moodleoverflowid; // Moodleoverflow that started the printing of statistics. - private $userstatsdata = array(); // Userstatsdata is a table that will have objects with every user and his statistics. - private $helpactivity; // Help icon for amountofactivity-column. + + /** @var int the Course ID*/ + private $courseid; + + /** @var int Moodleoverflow that started the printing of statistics*/ + private $moodleoverflowid; + + /** @var array table that will have objects with every user and his statistics. */ + private $userstatsdata = array(); + + /** @var \stdClass Help icon for amountofactivity-column.*/ + private $helpactivity; /** * Constructor for workflow_table. + * * @param int $uniqueid Unique id of this table. + * @param int $courseid + * @param int $moodleoverflow ID if the moodleoverflow + * @param string $url The url of the table */ public function __construct($uniqueid, $courseid, $moodleoverflow, $url) { global $PAGE; @@ -87,6 +99,10 @@ public function out() { /** * Method to sort the userstatsdata-table. + * + * @param array $sortorder The sort order array. + * + * @return void */ private function sort_table_data($sortorder) { $key = $sortorder['sortby']; @@ -103,6 +119,13 @@ private function sort_table_data($sortorder) { /** * Sorts userstatsdata with quicksort algorithm. + * + * @param int $low index for quicksort. + * @param int $high index for quicksort. + * @param int $key the column that is being sorted (upvotes, downvotes etc.). + * @param string $order sort in ascending or descending order. + * + * @return void */ private function quick_usertable_sort($low, $high, $key, $order) { if ($low >= $high) { @@ -256,10 +279,21 @@ public function set_helpactivity() { } // Functions that show the data. + + /** + * username column + * @param object $row + * @return string + */ public function col_username($row) { return $row->link; } + /** + * upvotes column + * @param object $row + * @return string + */ public function col_receivedupvotes($row) { if ($row->receivedupvotes > 0) { return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') . @@ -270,6 +304,11 @@ public function col_receivedupvotes($row) { } } + /** + * downvotes column + * @param object $row + * @return string + */ public function col_receiveddownvotes($row) { if ($row->receiveddownvotes > 0) { return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') . @@ -280,6 +319,11 @@ public function col_receiveddownvotes($row) { } } + /** + * activity column + * @param object $row + * @return string + */ public function col_activity($row) { if ($row->activity > 0) { return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') . @@ -290,6 +334,11 @@ public function col_activity($row) { } } + /** + * reputation column + * @param object $row + * @return string + */ public function col_reputation($row) { if ($row->reputation > 0) { return \html_writer::tag('h5', \html_writer::start_span('badge badge-success') . @@ -300,6 +349,12 @@ public function col_reputation($row) { } } + /** + * error handling + * @param object $colname + * @param int $attempt + * @return null + */ public function other_cols($colname, $attempt) { return null; } diff --git a/classes/task/send_mails.php b/classes/task/send_mails.php index 0c1d445334..268774bc29 100644 --- a/classes/task/send_mails.php +++ b/classes/task/send_mails.php @@ -67,7 +67,7 @@ public function execute() { * Sends initial notifications for needed reviews to all users with review capability. */ public function send_review_notifications() { - global $DB, $OUTPUT, $PAGE; + global $DB, $OUTPUT, $PAGE, $CFG; $rendererhtml = $PAGE->get_renderer('mod_moodleoverflow', 'email', 'htmlemail'); $renderertext = $PAGE->get_renderer('mod_moodleoverflow', 'email', 'textemail'); @@ -128,7 +128,12 @@ public function send_review_notifications() { foreach ($usersto as $userto) { try { - \core\cron::setup_user($userto, $course); + // Check for moodle version. Version 401 supported until 8 December 2025. + if ($CFG->branch >= 402) { + \core\cron::setup_user($userto, $course); + } else { + cron_setup_user($userto, $course); + } $maildata = new moodleoverflow_email( $course, diff --git a/lib.php b/lib.php index fe78089abb..5ee67061d7 100644 --- a/lib.php +++ b/lib.php @@ -749,7 +749,12 @@ function moodleoverflow_send_mails() { $userto->markposts = array(); // Cache the capabilities of the user. - \core\cron::setup_user($userto); + // Check for moodle version. Version 401 supported until 8 December 2025. + if ($CFG->branch >= 402) { + \core\cron::setup_user($userto); + } else { + cron_setup_user($userto); + } // Reset the caches. foreach ($coursemodules as $moodleoverflowid => $unused) { @@ -838,7 +843,12 @@ function moodleoverflow_send_mails() { } // Setup roles and languages. - \core\cron::setup_user($userto, $course); + // Check for moodle version. Version 401 supported until 8 December 2025. + if ($CFG->branch >= 402) { + \core\cron::setup_user($userto, $course); + } else { + cron_setup_user($userto, $course); + } // Cache the users capability to view full names. if (!isset($userto->viewfullnames[$moodleoverflow->id])) { diff --git a/locallib.php b/locallib.php index b120deaa22..c138fdfd50 100644 --- a/locallib.php +++ b/locallib.php @@ -328,7 +328,8 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - } } else { // Get his picture, his name and the link to his profile. - $preparedarray[$i]['picture'] = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course, 'link' => false)); + $preparedarray[$i]['picture'] = $OUTPUT->user_picture($startuser, array('courseid' => $moodleoverflow->course, + 'link' => false)); $preparedarray[$i]['username'] = fullname($startuser, has_capability('moodle/site:viewfullnames', $context)); $preparedarray[$i]['userlink'] = $CFG->wwwroot . '/user/view.php?id=' . $discussion->userid . '&course=' . $moodleoverflow->course; @@ -443,6 +444,10 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - /** * Prints a popup with a menu of other moodleoverflow in the course. * Menu to move a topic to another moodleoverflow forum. + * + * @param object $course + * @param object $cm + * @param int $movetopopup forum where forum list is being printed. */ function moodleoverflow_print_forum_list($course, $cm, $movetopopup) { global $CFG, $DB, $PAGE; @@ -1231,7 +1236,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co } // A teacher can mark an answer as solved. - $canmarksolved = (($iscomment != $post->parent) AND !empty($post->parent) AND capabilities::has(capabilities::MARK_SOLVED, $modulecontext)); + $canmarksolved = (($iscomment != $post->parent) && !empty($post->parent) + && capabilities::has(capabilities::MARK_SOLVED, $modulecontext)); if ($canmarksolved) { // When the post is already marked, remove the mark instead. @@ -1296,7 +1302,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $mustachedata->isread = false; $mustachedata->isfirstunread = false; $mustachedata->isfirstpost = false; - $mustachedata->iscomment = (!empty($post->parent) AND ($iscomment == $post->parent)); + $mustachedata->iscomment = (!empty($post->parent) && ($iscomment == $post->parent)); $mustachedata->permalink = $permalink; // Get the ratings. diff --git a/renderer.php b/renderer.php index f6458b547c..905bc3d12d 100644 --- a/renderer.php +++ b/renderer.php @@ -49,6 +49,10 @@ public function render_discussion_list($data) { /** * Display the forum list in the view.php if a discussion needs to be moved to another forum. + * + * @param object $data The prepared variables. + * + * @return string */ public function render_forum_list($data) { return $this->render_from_template('mod_moodleoverflow/forum_list', $data); diff --git a/tests/behat/behat_mod_moodleoverflow.php b/tests/behat/behat_mod_moodleoverflow.php index 7d1375c6c1..709dae2ef6 100644 --- a/tests/behat/behat_mod_moodleoverflow.php +++ b/tests/behat/behat_mod_moodleoverflow.php @@ -113,6 +113,10 @@ protected function add_new_discussion($moodleoverflowname, TableNode $table, $bu $this->execute('behat_general::i_wait_to_be_redirected'); } + /** + * Gets the container node. + * @param string $discussiontitle + */ protected function find_moodleoverflow_discussion_card(string $discussiontitle): \Behat\Mink\Element\Element { return $this->find('xpath', '//*[contains(concat(" ",normalize-space(@class)," ")," moodleoverflowdiscussion ")][.//*[text()="'. diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index b6df80f5d1..c8675b675c 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -41,11 +41,22 @@ */ class dailymail_test extends \advanced_testcase { + /** @var \stdClass */ private $sink; + + /** @var \stdClass */ private $course; + + /** @var \stdClass */ private $user; + + /** @var \stdClass */ private $moodleoverflow; + + /** @var \stdClass */ private $coursemodule; + + /** @var \stdClass */ private $discussion; /** @@ -81,7 +92,7 @@ public function tearDown(): void { /** * Function that creates a new user, which adds a new discussion an post to the moodleoverflow. - * @param $maildigest The maildigest setting: 0 = off , 1 = on + * @param int $maildigest The maildigest setting: 0 = off , 1 = on */ public function helper_create_user_and_discussion($maildigest) { // Create a user enrolled in the course as student. diff --git a/tests/review_test.php b/tests/review_test.php index 1dfc8cd2d2..29aae0090a 100644 --- a/tests/review_test.php +++ b/tests/review_test.php @@ -104,8 +104,9 @@ protected function tearDown(): void { } /** - * @runInSeparateProcess * Test reviews functionality in forums where teachers should review everything. + * + * @runInSeparateProcess */ public function test_forum_review_everything() { global $DB, $CFG; @@ -182,8 +183,9 @@ public function test_forum_review_everything() { } /** - * @runInSeparateProcess * Test reviews functionality in forums where teachers should review questions. + * + * @runInSeparateProcess */ public function test_forum_review_only_questions() { global $DB, $CFG; diff --git a/tests/userstats_test.php b/tests/userstats_test.php index ca657f7d3c..8c0039bbfa 100644 --- a/tests/userstats_test.php +++ b/tests/userstats_test.php @@ -29,22 +29,53 @@ global $CFG; require_once($CFG->dirroot . '/mod/moodleoverflow/lib.php'); + +/** + * PHPUnit Tests for testing userstats. + * + * @package mod_moodleoverflow + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class userstats_test extends \advanced_testcase { + /** @var \stdClass */ private $course; + + /** @var \stdClass */ private $coursemodule; - private $context; + + /** @var \stdClass */ private $moodleoverflow; + + /** @var \stdClass */ private $teacher; + + /** @var \stdClass */ private $user1; + + /** @var \stdClass */ private $user2; - private $discussion1; // Discussion from user1. - private $discussion2; // Discussion from user2. - private $post1; // First post from discussion1. - private $post2; // First post from discussion2. - private $answer1; // Answerpost to discussion1 from user2. - private $answer2; // Answerpost to discussion2 from user1. - private $generator; // Generator for moodleoverflow. + + /** @var \stdClass */ + private $discussion1; + + /** @var \stdClass */ + private $discussion2; + + /** @var \stdClass */ + private $post1; + + /** @var \stdClass */ + private $post2; + + /** @var \stdClass */ + private $answer1; + + /** @var \stdClass */ + private $answer2; + /** @var \mod_moodleoverflow_generator $generator */ + private $generator; /** * Test setUp. @@ -156,7 +187,6 @@ private function helper_course_set_up() { $location = array('course' => $this->course->id); $this->moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $location); $this->coursemodule = get_coursemodule_from_instance('moodleoverflow', $this->moodleoverflow->id); - $this->context = \context_course::instance($this->course->id); // Create a teacher. $this->teacher = $this->getDataGenerator()->create_user(array('firstname' => 'Tamaro', 'lastname' => 'Walter')); @@ -192,6 +222,12 @@ private function create_statstable() { /** * Create a upvote to a post in an existing discussion. + * + * @param object $author // The creator of the rating. + * @param object $discussion // Discussion object. + * @param object $post // Post that is being rated. + * + * @return $rating */ private function create_upvote($author, $discussion, $post) { $record = (object) [ @@ -208,6 +244,12 @@ private function create_upvote($author, $discussion, $post) { /** * Create a downvote to a post in an existing discussion. + * + * @param object $author // The creator of the rating. + * @param object $discussion // Discussion object. + * @param object $post // Post that is being rated. + * + * @return $rating */ private function create_downvote($author, $discussion, $post) { $record = (object) [ @@ -224,6 +266,12 @@ private function create_downvote($author, $discussion, $post) { /** * Create a helpful rating to a post in an existing discussion. + * + * @param object $author // The creator of the rating. + * @param object $discussion // Discussion object. + * @param object $post // Post that is being rated. + * + * @return $rating */ private function create_helpful($author, $discussion, $post) { $record = (object) [ @@ -240,6 +288,12 @@ private function create_helpful($author, $discussion, $post) { /** * Create a solution rating to a post in an existing discussion. + * + * @param object $author // The creator of the rating. + * @param object $discussion // Discussion object. + * @param object $post // Post that is being rated. + * + * @return $rating */ private function create_solution($author, $discussion, $post) { $record = (object) [ From 58fcc2f6267e9f50884a8120b9d8677432208197 Mon Sep 17 00:00:00 2001 From: NinaHerrmann <nina.herrmann@uni-muenster.de> Date: Tue, 9 May 2023 16:49:23 +0200 Subject: [PATCH 16/35] new build --- amd/build/activityhelp.min.js | 2 +- amd/build/activityhelp.min.js.map | 2 +- amd/build/rating.min.js | 9 ++++++++- amd/build/rating.min.js.map | 3 +-- amd/build/reviewing.min.js | 9 ++++++++- amd/build/reviewing.min.js.map | 3 +-- amd/build/warnmodechange.min.js | 9 ++++++++- amd/build/warnmodechange.min.js.map | 3 +-- 8 files changed, 29 insertions(+), 11 deletions(-) diff --git a/amd/build/activityhelp.min.js b/amd/build/activityhelp.min.js index a3dc794e34..a875b70b82 100644 --- a/amd/build/activityhelp.min.js +++ b/amd/build/activityhelp.min.js @@ -6,6 +6,6 @@ define("mod_moodleoverflow/activityhelp",["exports"],(function(_exports){Object. * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var Selectors_actions={showHelpIcon:'[data-action="showhelpicon"]'};_exports.init=function(){document.addEventListener("click",(function(event){event.target.closest(Selectors_actions.showHelpIcon)&&event.preventDefault()}))}})); +const Selectors_actions={showHelpIcon:'[data-action="showhelpicon"]'};_exports.init=()=>{document.addEventListener("click",(event=>{event.target.closest(Selectors_actions.showHelpIcon)&&event.preventDefault()}))}})); //# sourceMappingURL=activityhelp.min.js.map \ No newline at end of file diff --git a/amd/build/activityhelp.min.js.map b/amd/build/activityhelp.min.js.map index 7bae1c7cab..64d79cd463 100644 --- a/amd/build/activityhelp.min.js.map +++ b/amd/build/activityhelp.min.js.map @@ -1 +1 @@ -{"version":3,"file":"activityhelp.min.js","sources":["../src/activityhelp.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Show a help string for the amount of activity column in userstats_table.php\n *\n * @module mod_moodleoverflow/activityhelp\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\n\nconst Selectors = {\n actions: {\n showHelpIcon: '[data-action=\"showhelpicon\"]',\n },\n};\n\n/**\n * Function that shows the help string.\n */\nexport const init = () => {\n document.addEventListener('click', event => {\n if (event.target.closest(Selectors.actions.showHelpIcon)) {\n event.preventDefault();\n }\n });\n};"],"names":["Selectors","showHelpIcon","document","addEventListener","event","target","closest","preventDefault"],"mappings":";;;;;;;;IAyBMA,kBACO,CACLC,aAAc,8CAOF,WAChBC,SAASC,iBAAiB,SAAS,SAAAC,OAC3BA,MAAMC,OAAOC,QAAQN,kBAAkBC,eACvCG,MAAMG"} \ No newline at end of file +{"version":3,"file":"activityhelp.min.js","sources":["../src/activityhelp.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Show a help string for the amount of activity column in userstats_table.php\n *\n * @module mod_moodleoverflow/activityhelp\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\n\nconst Selectors = {\n actions: {\n showHelpIcon: '[data-action=\"showhelpicon\"]',\n },\n};\n\n/**\n * Function that shows the help string.\n */\nexport const init = () => {\n document.addEventListener('click', event => {\n if (event.target.closest(Selectors.actions.showHelpIcon)) {\n event.preventDefault();\n }\n });\n};"],"names":["Selectors","showHelpIcon","document","addEventListener","event","target","closest","preventDefault"],"mappings":";;;;;;;;MAyBMA,kBACO,CACLC,aAAc,8CAOF,KAChBC,SAASC,iBAAiB,SAASC,QAC3BA,MAAMC,OAAOC,QAAQN,kBAAkBC,eACvCG,MAAMG"} \ No newline at end of file diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index 4dc7b4ea4e..f60ce3513a 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -1,3 +1,10 @@ -define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/str"],(function(_exports,_ajax,_prefetch,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _createForOfIteratorHelper(o,allowArrayLike){var it="undefined"!=typeof Symbol&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=function(o,minLen){if(!o)return;if("string"==typeof o)return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);"Object"===n&&o.constructor&&(n=o.constructor.name);if("Map"===n||"Set"===n)return Array.from(o);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}(o))||allowArrayLike&&o&&"number"==typeof o.length){it&&(o=it);var i=0,F=function(){};return{s:F,n:function(){return i>=o.length?{done:!0}:{done:!1,value:o[i++]}},e:function(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var err,normalCompletion=!0,didErr=!1;return{s:function(){it=it.call(o)},n:function(){var step=it.next();return normalCompletion=step.done,step},e:function(_e2){didErr=!0,err=_e2},f:function(){try{normalCompletion||null==it.return||it.return()}finally{if(didErr)throw err}}}}function _arrayLikeToArray(arr,len){(null==len||len>arr.length)&&(len=arr.length);for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg),value=info.value}catch(error){return void reject(error)}info.done?resolve(value):Promise.resolve(value).then(_next,_throw)}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise((function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(void 0)}))}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=(_ref=_asyncToGenerator(regeneratorRuntime.mark((function _callee(event){var actionElement,action,postElement,postid,isupvote,otherAction,otherElement,isHelpful,htmlclass,shouldRemove,baseRating,rating,_iterator,_step,el;return regeneratorRuntime.wrap((function(_context){for(;;)switch(_context.prev=_context.next){case 0:if(actionElement=event.target.closest("[data-moodleoverflow-action]")){_context.next=3;break}return _context.abrupt("return");case 3:action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid"),_context.t0=action,_context.next="upvote"===_context.t0||"downvote"===_context.t0?9:"helpful"===_context.t0||"solved"===_context.t0?32:63;break;case 9:if(isupvote="upvote"===action,"clicked"!==actionElement.getAttribute("data-moodleoverflow-state")){_context.next=19;break}return _context.next=13,sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid);case 13:return actionElement.setAttribute("data-moodleoverflow-state","notclicked"),_context.next=16,(0,_str.get_string)("action_"+action,"mod_moodleoverflow");case 16:actionElement.title=_context.sent,_context.next=31;break;case 19:return otherAction=isupvote?"downvote":"upvote",_context.next=22,sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid);case 22:return actionElement.setAttribute("data-moodleoverflow-state","clicked"),(otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'))).setAttribute("data-moodleoverflow-state","notclicked"),_context.next=27,(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow");case 27:return actionElement.title=_context.sent,_context.next=30,(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow");case 30:otherElement.title=_context.sent;case 31:return _context.abrupt("break",63);case 32:return htmlclass=(isHelpful="helpful"===action)?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating,_context.next=39,sendVote(postid,rating,userid);case 39:_iterator=_createForOfIteratorHelper(root.querySelectorAll(".moodleoverflowpost."+htmlclass)),_context.prev=40,_iterator.s();case 42:if((_step=_iterator.n()).done){_context.next=50;break}return(el=_step.value).classList.remove(htmlclass),_context.next=47,(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");case 47:el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=_context.sent;case 48:_context.next=42;break;case 50:_context.next=55;break;case 52:_context.prev=52,_context.t1=_context.catch(40),_iterator.e(_context.t1);case 55:return _context.prev=55,_iterator.f(),_context.finish(55);case 58:if(shouldRemove){_context.next=63;break}return postElement.classList.add(htmlclass),_context.next=62,(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow");case 62:actionElement.textContent=_context.sent;case 63:case"end":return _context.stop()}}),_callee,null,[[40,52,55,58]])}))),function(_x4){return _ref.apply(this,arguments)});var _ref},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);var RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");function sendVote(_x,_x2,_x3){return _sendVote.apply(this,arguments)}function _sendVote(){return(_sendVote=_asyncToGenerator(regeneratorRuntime.mark((function _callee2(postid,rating,userid){var response;return regeneratorRuntime.wrap((function(_context2){for(;;)switch(_context2.prev=_context2.next){case 0:return _context2.next=2,_ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];case 2:return response=_context2.sent,root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((function(i){i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((function(i){i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((function(i){i.textContent=response.postrating})),_context2.abrupt("return",response);case 7:case"end":return _context2.stop()}}),_callee2)})))).apply(this,arguments)}})); +define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/str"],(function(_exports,_ajax,_prefetch,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +/** + * Implements rating functionality + * + * @module mod_moodleoverflow/rating + * @copyright 2022 Justus Dieckmann WWU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),allowmultiplemarks)shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"),changeStrings(htmlclass,action));else for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"),allowmultiplemarks&&changeStrings(htmlclass,action))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}async function changeStrings(htmlclass,action){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","markhelpful","alsomarkhelpful"]);var othermarkedposts=!1;for(const el of root.querySelectorAll(".moodleoverflowpost"))if(el.classList.contains(htmlclass)){othermarkedposts=!0;break}for(const el of root.querySelectorAll(".moodleoverflowpost"))!el.classList.contains(htmlclass)&&el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]'))&&(el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=othermarkedposts?await(0,_str.get_string)("alsomark".concat(action),"mod_moodleoverflow"):await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"))}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 8243d74e75..11f1b470a8 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1,2 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only usable if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} - +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only usable if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} \ No newline at end of file diff --git a/amd/build/reviewing.min.js b/amd/build/reviewing.min.js index c811cbbdfd..7dc1ac1e4f 100644 --- a/amd/build/reviewing.min.js +++ b/amd/build/reviewing.min.js @@ -1,3 +1,10 @@ -define("mod_moodleoverflow/reviewing",["exports","core/ajax","core/prefetch","core/templates","core/str"],(function(_exports,_ajax,_prefetch,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg),value=info.value}catch(error){return void reject(error)}info.done?resolve(value):Promise.resolve(value).then(_next,_throw)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){_prefetch.default.prefetchTemplates(["mod_moodleoverflow/reject_post_form","mod_moodleoverflow/review_buttons"]),_prefetch.default.prefetchStrings("mod_moodleoverflow",["post_was_approved","jump_to_next_post_needing_review","there_are_no_posts_needing_review","post_was_rejected"]),document.getElementById("moodleoverflow-posts").onclick=(fn=regeneratorRuntime.mark((function _callee(e){var action,post,reviewRow,postID,nextPostURL,message,rejectMessage,args,_nextPostURL,_message;return regeneratorRuntime.wrap((function(_context){for(;;)switch(_context.prev=_context.next){case 0:if(action=e.target.getAttribute("data-moodleoverflow-action")){_context.next=3;break}return _context.abrupt("return");case 3:if(post=e.target.closest("*[data-moodleoverflow-postid]"),reviewRow=e.target.closest(".reviewrow"),postID=post.getAttribute("data-moodleoverflow-postid"),"approve"!==action){_context.next=33;break}return reviewRow.innerHTML=".",_context.next=10,_ajax.default.call([{methodname:"mod_moodleoverflow_review_approve_post",args:{postid:postID}}])[0];case 10:return nextPostURL=_context.sent,_context.next=13,(0,_str.get_string)("post_was_approved","mod_moodleoverflow");case 13:if(_context.t0=_context.sent,message=_context.t0+" ",!nextPostURL){_context.next=25;break}return _context.t1=message,_context.t2='<a href="'.concat(nextPostURL,'">'),_context.next=20,(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow");case 20:_context.t3=_context.sent,_context.t4=_context.t2+_context.t3,message=_context.t1+=_context.t4+"</a>",_context.next=29;break;case 25:return _context.t5=message,_context.next=28,(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow");case 28:message=_context.t5+=_context.sent;case 29:reviewRow.innerHTML=message,post.classList.remove("pendingreview"),_context.next=73;break;case 33:if("reject"!==action){_context.next=40;break}return reviewRow.innerHTML=".",_context.next=37,_templates.default.render("mod_moodleoverflow/reject_post_form",{});case 37:reviewRow.innerHTML=_context.sent,_context.next=73;break;case 40:if("reject-submit"!==action){_context.next=68;break}return rejectMessage=post.querySelector("textarea.reject-reason").value.toString().trim(),reviewRow.innerHTML=".",args={postid:postID,reason:rejectMessage||null},_context.next=46,_ajax.default.call([{methodname:"mod_moodleoverflow_review_reject_post",args:args}])[0];case 46:return _nextPostURL=_context.sent,_context.next=49,(0,_str.get_string)("post_was_rejected","mod_moodleoverflow");case 49:if(_context.t6=_context.sent,_message=_context.t6+" ",!_nextPostURL){_context.next=61;break}return _context.t7=_message,_context.t8='<a href="'.concat(_nextPostURL,'">'),_context.next=56,(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow");case 56:_context.t9=_context.sent,_context.t10=_context.t8+_context.t9,_message=_context.t7+=_context.t10+"</a>",_context.next=65;break;case 61:return _context.t11=_message,_context.next=64,(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow");case 64:_message=_context.t11+=_context.sent;case 65:reviewRow.innerHTML=_message,_context.next=73;break;case 68:if("reject-cancel"!==action){_context.next=73;break}return reviewRow.innerHTML=".",_context.next=72,_templates.default.render("mod_moodleoverflow/review_buttons",{});case 72:reviewRow.innerHTML=_context.sent;case 73:case"end":return _context.stop()}}),_callee)})),_ref=function(){var self=this,args=arguments;return new Promise((function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(void 0)}))},function(_x){return _ref.apply(this,arguments)});var fn,_ref},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch),_templates=_interopRequireDefault(_templates)})); +define("mod_moodleoverflow/reviewing",["exports","core/ajax","core/prefetch","core/templates","core/str"],(function(_exports,_ajax,_prefetch,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +/** + * Implements reviewing functionality + * + * @module mod_moodleoverflow/reviewing + * @copyright 2022 Justus Dieckmann WWU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){_prefetch.default.prefetchTemplates(["mod_moodleoverflow/reject_post_form","mod_moodleoverflow/review_buttons"]),_prefetch.default.prefetchStrings("mod_moodleoverflow",["post_was_approved","jump_to_next_post_needing_review","there_are_no_posts_needing_review","post_was_rejected"]);document.getElementById("moodleoverflow-posts").onclick=async e=>{const action=e.target.getAttribute("data-moodleoverflow-action");if(!action)return;const post=e.target.closest("*[data-moodleoverflow-postid]"),reviewRow=e.target.closest(".reviewrow"),postID=post.getAttribute("data-moodleoverflow-postid");if("approve"===action){reviewRow.innerHTML=".";const nextPostURL=await _ajax.default.call([{methodname:"mod_moodleoverflow_review_approve_post",args:{postid:postID}}])[0];let message=await(0,_str.get_string)("post_was_approved","mod_moodleoverflow")+" ";message+=nextPostURL?'<a href="'.concat(nextPostURL,'">')+await(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow")+"</a>":await(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow"),reviewRow.innerHTML=message,post.classList.remove("pendingreview")}else if("reject"===action)reviewRow.innerHTML=".",reviewRow.innerHTML=await _templates.default.render("mod_moodleoverflow/reject_post_form",{});else if("reject-submit"===action){const rejectMessage=post.querySelector("textarea.reject-reason").value.toString().trim();reviewRow.innerHTML=".";const args={postid:postID,reason:rejectMessage||null},nextPostURL=await _ajax.default.call([{methodname:"mod_moodleoverflow_review_reject_post",args:args}])[0];let message=await(0,_str.get_string)("post_was_rejected","mod_moodleoverflow")+" ";message+=nextPostURL?'<a href="'.concat(nextPostURL,'">')+await(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow")+"</a>":await(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow"),reviewRow.innerHTML=message}else"reject-cancel"===action&&(reviewRow.innerHTML=".",reviewRow.innerHTML=await _templates.default.render("mod_moodleoverflow/review_buttons",{}))}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch),_templates=_interopRequireDefault(_templates)})); //# sourceMappingURL=reviewing.min.js.map \ No newline at end of file diff --git a/amd/build/reviewing.min.js.map b/amd/build/reviewing.min.js.map index 0f8f0c1d6b..13a68e7925 100644 --- a/amd/build/reviewing.min.js.map +++ b/amd/build/reviewing.min.js.map @@ -1,2 +1 @@ -{"version":3,"file":"reviewing.min.js","sources":["../src/reviewing.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements reviewing functionality\n *\n * @module mod_moodleoverflow/reviewing\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Init function.\n */\nexport function init() {\n Prefetch.prefetchTemplates(['mod_moodleoverflow/reject_post_form', 'mod_moodleoverflow/review_buttons']);\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['post_was_approved', 'jump_to_next_post_needing_review', 'there_are_no_posts_needing_review', 'post_was_rejected']);\n\n const root = document.getElementById('moodleoverflow-posts');\n root.onclick = async(e) => {\n const action = e.target.getAttribute('data-moodleoverflow-action');\n\n if (!action) {\n return;\n }\n\n const post = e.target.closest('*[data-moodleoverflow-postid]');\n const reviewRow = e.target.closest('.reviewrow');\n const postID = post.getAttribute('data-moodleoverflow-postid');\n\n if (action === 'approve') {\n reviewRow.innerHTML = '.';\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_approve_post',\n args: {\n postid: postID,\n }\n }])[0];\n\n let message = await getString('post_was_approved', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n post.classList.remove(\"pendingreview\");\n } else if (action === 'reject') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/reject_post_form', {});\n } else if (action === 'reject-submit') {\n const rejectMessage = post.querySelector('textarea.reject-reason').value.toString().trim();\n reviewRow.innerHTML = '.';\n const args = {\n postid: postID,\n reason: rejectMessage ? rejectMessage : null\n };\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_reject_post',\n args: args\n }])[0];\n\n let message = await getString('post_was_rejected', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n } else if (action === 'reject-cancel') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/review_buttons', {});\n }\n };\n}"],"names":["prefetchTemplates","prefetchStrings","document","getElementById","onclick","async","action","e","target","getAttribute","post","closest","reviewRow","postID","innerHTML","nextPostURL","Ajax","call","methodname","args","postid","message","classList","remove","Templates","render","rejectMessage","querySelector","value","toString","trim","reason"],"mappings":";;;;;;;wGA+BaA,kBAAkB,CAAC,sCAAuC,wDAC1DC,gBAAgB,qBACrB,CAAC,oBAAqB,mCAAoC,oCAAqC,sBAEtFC,SAASC,eAAe,wBAChCC,QAAUC,gBACLC,OAASC,EAAEC,OAAOC,aAAa,kCAEhCH,oBAICI,KAAOH,EAAEC,OAAOG,QAAQ,iCACxBC,UAAYL,EAAEC,OAAOG,QAAQ,cAC7BE,OAASH,KAAKD,aAAa,iCAElB,YAAXH,OAAsB,CACtBM,UAAUE,UAAY,UAChBC,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,yCACZC,KAAM,CACFC,OAAQP,WAEZ,OAEAQ,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,QACtBX,KAAKY,UAAUC,OAAO,sBACnB,GAAe,WAAXjB,OACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,sCAAuC,SACjF,GAAe,kBAAXnB,OAA4B,OAC7BoB,cAAgBhB,KAAKiB,cAAc,0BAA0BC,MAAMC,WAAWC,OACpFlB,UAAUE,UAAY,UAChBK,KAAO,CACTC,OAAQP,OACRkB,OAAQL,eAAgC,MAEtCX,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,wCACZC,KAAMA,QACN,OAEAE,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,YACJ,kBAAXf,SACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,oCAAqC"} - +{"version":3,"file":"reviewing.min.js","sources":["../src/reviewing.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements reviewing functionality\n *\n * @module mod_moodleoverflow/reviewing\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Init function.\n */\nexport function init() {\n Prefetch.prefetchTemplates(['mod_moodleoverflow/reject_post_form', 'mod_moodleoverflow/review_buttons']);\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['post_was_approved', 'jump_to_next_post_needing_review', 'there_are_no_posts_needing_review', 'post_was_rejected']);\n\n const root = document.getElementById('moodleoverflow-posts');\n root.onclick = async(e) => {\n const action = e.target.getAttribute('data-moodleoverflow-action');\n\n if (!action) {\n return;\n }\n\n const post = e.target.closest('*[data-moodleoverflow-postid]');\n const reviewRow = e.target.closest('.reviewrow');\n const postID = post.getAttribute('data-moodleoverflow-postid');\n\n if (action === 'approve') {\n reviewRow.innerHTML = '.';\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_approve_post',\n args: {\n postid: postID,\n }\n }])[0];\n\n let message = await getString('post_was_approved', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n post.classList.remove(\"pendingreview\");\n } else if (action === 'reject') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/reject_post_form', {});\n } else if (action === 'reject-submit') {\n const rejectMessage = post.querySelector('textarea.reject-reason').value.toString().trim();\n reviewRow.innerHTML = '.';\n const args = {\n postid: postID,\n reason: rejectMessage ? rejectMessage : null\n };\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_reject_post',\n args: args\n }])[0];\n\n let message = await getString('post_was_rejected', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n } else if (action === 'reject-cancel') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/review_buttons', {});\n }\n };\n}"],"names":["prefetchTemplates","prefetchStrings","document","getElementById","onclick","async","action","e","target","getAttribute","post","closest","reviewRow","postID","innerHTML","nextPostURL","Ajax","call","methodname","args","postid","message","classList","remove","Templates","render","rejectMessage","querySelector","value","toString","trim","reason"],"mappings":";;;;;;;wGA+BaA,kBAAkB,CAAC,sCAAuC,wDAC1DC,gBAAgB,qBACrB,CAAC,oBAAqB,mCAAoC,oCAAqC,sBAEtFC,SAASC,eAAe,wBAChCC,QAAUC,gBACLC,OAASC,EAAEC,OAAOC,aAAa,kCAEhCH,oBAICI,KAAOH,EAAEC,OAAOG,QAAQ,iCACxBC,UAAYL,EAAEC,OAAOG,QAAQ,cAC7BE,OAASH,KAAKD,aAAa,iCAElB,YAAXH,OAAsB,CACtBM,UAAUE,UAAY,UAChBC,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,yCACZC,KAAM,CACFC,OAAQP,WAEZ,OAEAQ,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,QACtBX,KAAKY,UAAUC,OAAO,sBACnB,GAAe,WAAXjB,OACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,sCAAuC,SACjF,GAAe,kBAAXnB,OAA4B,OAC7BoB,cAAgBhB,KAAKiB,cAAc,0BAA0BC,MAAMC,WAAWC,OACpFlB,UAAUE,UAAY,UAChBK,KAAO,CACTC,OAAQP,OACRkB,OAAQL,eAAgC,MAEtCX,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,wCACZC,KAAMA,QACN,OAEAE,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,YACJ,kBAAXf,SACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,oCAAqC"} \ No newline at end of file diff --git a/amd/build/warnmodechange.min.js b/amd/build/warnmodechange.min.js index 370da13a32..5042ba704b 100644 --- a/amd/build/warnmodechange.min.js +++ b/amd/build/warnmodechange.min.js @@ -1,3 +1,10 @@ -define("mod_moodleoverflow/warnmodechange",["exports","core/str","core/notification","core/prefetch"],(function(_exports,_str,_notification,_prefetch){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg),value=info.value}catch(error){return void reject(error)}info.done?resolve(value):Promise.resolve(value).then(_next,_throw)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(previousSetting){_prefetch.default.prefetchStrings("mod_moodleoverflow",["switchtooptional","switchtoauto"]),_prefetch.default.prefetchStrings("moodle",["confirm","cancel"]);var form=document.querySelector("form.mform"),select=document.getElementById("id_forcesubscribe");form.onsubmit=(fn=regeneratorRuntime.mark((function _callee(e){var value;return regeneratorRuntime.wrap((function(_context){for(;;)switch(_context.prev=_context.next){case 0:if((value=select.selectedOptions[0].value)!=previousSetting&&1!=value&&3!=value){_context.next=3;break}return _context.abrupt("return");case 3:return e.preventDefault(),_context.t0=_notification.default,_context.next=7,(0,_str.get_string)("confirm");case 7:return _context.t1=_context.sent,_context.next=10,(0,_str.get_string)(0==value?"switchtooptional":"switchtoauto","mod_moodleoverflow");case 10:return _context.t2=_context.sent,_context.next=13,(0,_str.get_string)("confirm");case 13:return _context.t3=_context.sent,_context.next=16,(0,_str.get_string)("cancel");case 16:return _context.t4=_context.sent,_context.t5=function(){form.onsubmit=void 0,form.requestSubmit(e.submitter)},_context.t6=void 0,_context.next=21,_context.t0.confirm.call(_context.t0,_context.t1,_context.t2,_context.t3,_context.t4,_context.t5,_context.t6);case 21:case"end":return _context.stop()}}),_callee)})),_ref=function(){var self=this,args=arguments;return new Promise((function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(void 0)}))},function(_x){return _ref.apply(this,arguments)});var fn,_ref},_notification=_interopRequireDefault(_notification),_prefetch=_interopRequireDefault(_prefetch)})); +define("mod_moodleoverflow/warnmodechange",["exports","core/str","core/notification","core/prefetch"],(function(_exports,_str,_notification,_prefetch){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +/** + * Warns on changing the subscription mode. + * + * @module mod_moodleoverflow/warnmodechange + * @copyright 2022 Justus Dieckmann WWU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(previousSetting){_prefetch.default.prefetchStrings("mod_moodleoverflow",["switchtooptional","switchtoauto"]),_prefetch.default.prefetchStrings("moodle",["confirm","cancel"]);const form=document.querySelector("form.mform"),select=document.getElementById("id_forcesubscribe");form.onsubmit=async e=>{const value=select.selectedOptions[0].value;value!=previousSetting&&1!=value&&3!=value&&(e.preventDefault(),await _notification.default.confirm(await(0,_str.get_string)("confirm"),await(0,_str.get_string)(0==value?"switchtooptional":"switchtoauto","mod_moodleoverflow"),await(0,_str.get_string)("confirm"),await(0,_str.get_string)("cancel"),(()=>{form.onsubmit=void 0,form.requestSubmit(e.submitter)}),void 0))}},_notification=_interopRequireDefault(_notification),_prefetch=_interopRequireDefault(_prefetch)})); //# sourceMappingURL=warnmodechange.min.js.map \ No newline at end of file diff --git a/amd/build/warnmodechange.min.js.map b/amd/build/warnmodechange.min.js.map index 80beade8a2..b4120395cd 100644 --- a/amd/build/warnmodechange.min.js.map +++ b/amd/build/warnmodechange.min.js.map @@ -1,2 +1 @@ -{"version":3,"file":"warnmodechange.min.js","sources":["../src/warnmodechange.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Warns on changing the subscription mode.\n *\n * @module mod_moodleoverflow/warnmodechange\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Prefetch from 'core/prefetch';\n\n/**\n * Init function.\n * @param {string} previousSetting\n */\nexport function init(previousSetting) {\n Prefetch.prefetchStrings('mod_moodleoverflow', ['switchtooptional', 'switchtoauto']);\n Prefetch.prefetchStrings('moodle', ['confirm', 'cancel']);\n const form = document.querySelector('form.mform');\n const select = document.getElementById('id_forcesubscribe');\n form.onsubmit = async(e) => {\n const value = select.selectedOptions[0].value;\n if (value == previousSetting || value == 1 || value == 3) {\n return;\n }\n e.preventDefault();\n await Notification.confirm(\n await getString('confirm'),\n await getString(value == 0 ? 'switchtooptional' : 'switchtoauto', 'mod_moodleoverflow'),\n await getString('confirm'),\n await getString('cancel'),\n () => {\n // Prevent this listener from preventing the event again.\n form.onsubmit = undefined;\n form.requestSubmit(e.submitter);\n }, undefined);\n };\n}"],"names":["previousSetting","prefetchStrings","form","document","querySelector","select","getElementById","onsubmit","async","value","selectedOptions","e","preventDefault","Notification","confirm","undefined","requestSubmit","submitter"],"mappings":";;;;;;;oFA8BqBA,mCACRC,gBAAgB,qBAAsB,CAAC,mBAAoB,mCAC3DA,gBAAgB,SAAU,CAAC,UAAW,iBACzCC,KAAOC,SAASC,cAAc,cAC9BC,OAASF,SAASG,eAAe,qBACvCJ,KAAKK,SAAWC,gBACNC,MAAQJ,OAAOK,gBAAgB,GAAGD,MACpCA,OAAST,iBAA4B,GAATS,OAAuB,GAATA,QAG9CE,EAAEC,uBACIC,sBAAaC,cACT,mBAAU,iBACV,mBAAmB,GAATL,MAAa,mBAAqB,eAAgB,4BAC5D,mBAAU,iBACV,mBAAU,WAChB,KAEIP,KAAKK,cAAWQ,EAChBb,KAAKc,cAAcL,EAAEM,kBACtBF,GATP"} - +{"version":3,"file":"warnmodechange.min.js","sources":["../src/warnmodechange.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Warns on changing the subscription mode.\n *\n * @module mod_moodleoverflow/warnmodechange\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Prefetch from 'core/prefetch';\n\n/**\n * Init function.\n * @param {string} previousSetting\n */\nexport function init(previousSetting) {\n Prefetch.prefetchStrings('mod_moodleoverflow', ['switchtooptional', 'switchtoauto']);\n Prefetch.prefetchStrings('moodle', ['confirm', 'cancel']);\n const form = document.querySelector('form.mform');\n const select = document.getElementById('id_forcesubscribe');\n form.onsubmit = async(e) => {\n const value = select.selectedOptions[0].value;\n if (value == previousSetting || value == 1 || value == 3) {\n return;\n }\n e.preventDefault();\n await Notification.confirm(\n await getString('confirm'),\n await getString(value == 0 ? 'switchtooptional' : 'switchtoauto', 'mod_moodleoverflow'),\n await getString('confirm'),\n await getString('cancel'),\n () => {\n // Prevent this listener from preventing the event again.\n form.onsubmit = undefined;\n form.requestSubmit(e.submitter);\n }, undefined);\n };\n}"],"names":["previousSetting","prefetchStrings","form","document","querySelector","select","getElementById","onsubmit","async","value","selectedOptions","e","preventDefault","Notification","confirm","undefined","requestSubmit","submitter"],"mappings":";;;;;;;oFA8BqBA,mCACRC,gBAAgB,qBAAsB,CAAC,mBAAoB,mCAC3DA,gBAAgB,SAAU,CAAC,UAAW,iBACzCC,KAAOC,SAASC,cAAc,cAC9BC,OAASF,SAASG,eAAe,qBACvCJ,KAAKK,SAAWC,gBACNC,MAAQJ,OAAOK,gBAAgB,GAAGD,MACpCA,OAAST,iBAA4B,GAATS,OAAuB,GAATA,QAG9CE,EAAEC,uBACIC,sBAAaC,cACT,mBAAU,iBACV,mBAAmB,GAATL,MAAa,mBAAqB,eAAgB,4BAC5D,mBAAU,iBACV,mBAAU,WAChB,KAEIP,KAAKK,cAAWQ,EAChBb,KAAKc,cAAcL,EAAEM,kBACtBF,GATP"} \ No newline at end of file From 3c79050b785715399b9980c14fc592aa85e4c186 Mon Sep 17 00:00:00 2001 From: Nina Herrmann <nina.herrmann@uni-muenster.de> Date: Fri, 12 May 2023 11:58:06 +0200 Subject: [PATCH 17/35] Update capabilities.php --- classes/capabilities.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/classes/capabilities.php b/classes/capabilities.php index 44dda716d2..7a6f72eb3d 100644 --- a/classes/capabilities.php +++ b/classes/capabilities.php @@ -35,46 +35,46 @@ */ class capabilities { - /** capability */ + /** capability add instance */ const ADD_INSTANCE = 'mod/moodleoverflow:addinstance'; - /** capability */ + /** capability view discussions*/ const VIEW_DISCUSSION = 'mod/moodleoverflow:viewdiscussion'; - /** capability */ + /** capability reply in discussions*/ const REPLY_POST = 'mod/moodleoverflow:replypost'; - /** capability */ + /** capability start discussions*/ const START_DISCUSSION = 'mod/moodleoverflow:startdiscussion'; - /** capability */ + /** capability edit post from other course participants*/ const EDIT_ANY_POST = 'mod/moodleoverflow:editanypost'; - /** capability */ + /** capability delete your post*/ const DELETE_OWN_POST = 'mod/moodleoverflow:deleteownpost'; - /** capability */ + /** capability delete post from any course participant*/ const DELETE_ANY_POST = 'mod/moodleoverflow:deleteanypost'; - /** capability */ + /** capability rate a post*/ const RATE_POST = 'mod/moodleoverflow:ratepost'; - /** capability */ + /** capability mark a post as a solution for a questions*/ const MARK_SOLVED = 'mod/moodleoverflow:marksolved'; - /** capability */ + /** capability manage the subscription of a moodleoverflow instance */ const MANAGE_SUBSCRIPTIONS = 'mod/moodleoverflow:managesubscriptions'; - /** capability */ + /** capability force the subscription of participants */ const ALLOW_FORCE_SUBSCRIBE = 'mod/moodleoverflow:allowforcesubscribe'; - /** capability */ + /** capability attach files to posts */ const CREATE_ATTACHMENT = 'mod/moodleoverflow:createattachment'; - /** capability */ + /** capability review post to be published*/ const REVIEW_POST = 'mod/moodleoverflow:reviewpost'; - /** @var array */ + /** @var array cache capabilities*/ private static $cache = []; /** From 723cdcecce00e74b8319fe853f5396e4d777a828 Mon Sep 17 00:00:00 2001 From: Nina Herrmann <nina.herrmann@uni-muenster.de> Date: Fri, 12 May 2023 13:15:05 +0200 Subject: [PATCH 18/35] Update ratings.php short check --- classes/ratings.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 76ea3246fe..e210e6fe65 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -79,10 +79,7 @@ public static function moodleoverflow_add_rating($moodleoverflow, $postid, $rati // Are multiple marks allowed? $markssetting = $DB->get_record('moodleoverflow', array('id' => $moodleoverflow->id), 'allowmultiplemarks'); - $multiplemarks = false; - if ($markssetting->allowmultiplemarks == 1) { - $multiplemarks = true; - } + $multiplemarks = (bool) $markssetting->allowmultiplemarks; // Retrieve the contexts. $modulecontext = \context_module::instance($cm->id); From 656420bb870f26fff33082bffbb5764758abb69a Mon Sep 17 00:00:00 2001 From: Nina Herrmann <nina.herrmann@uni-muenster.de> Date: Fri, 12 May 2023 14:29:39 +0200 Subject: [PATCH 19/35] Update dailymail_test.php --- tests/dailymail_test.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index c8675b675c..3c615730ab 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -41,22 +41,22 @@ */ class dailymail_test extends \advanced_testcase { - /** @var \stdClass */ + /** @var \stdClass collection of messages */ private $sink; - /** @var \stdClass */ + /** @var \stdClass test course */ private $course; - /** @var \stdClass */ + /** @var \stdClass test user*/ private $user; - /** @var \stdClass */ + /** @var \stdClass moodleoverflow instance */ private $moodleoverflow; - /** @var \stdClass */ + /** @var \stdClass coursemodule instance */ private $coursemodule; - /** @var \stdClass */ + /** @var \stdClass discussion instance */ private $discussion; /** From cdf2085590313ade818eef199b9de883d9fe8ab5 Mon Sep 17 00:00:00 2001 From: Nina Herrmann <nina.herrmann@uni-muenster.de> Date: Fri, 12 May 2023 14:37:04 +0200 Subject: [PATCH 20/35] Update userstats_test.php --- tests/userstats_test.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/userstats_test.php b/tests/userstats_test.php index 8c0039bbfa..24ac3ed817 100644 --- a/tests/userstats_test.php +++ b/tests/userstats_test.php @@ -39,40 +39,40 @@ */ class userstats_test extends \advanced_testcase { - /** @var \stdClass */ + /** @var \stdClass test course */ private $course; - /** @var \stdClass */ + /** @var \stdClass coursemodule */ private $coursemodule; - /** @var \stdClass */ + /** @var \stdClass test moodleoverflow */ private $moodleoverflow; - /** @var \stdClass */ + /** @var \stdClass test teacher */ private $teacher; - /** @var \stdClass */ + /** @var \stdClass test user */ private $user1; - /** @var \stdClass */ + /** @var \stdClass another test user */ private $user2; - /** @var \stdClass */ + /** @var \stdClass fake discussion */ private $discussion1; - /** @var \stdClass */ + /** @var \stdClass another faked discussion */ private $discussion2; - /** @var \stdClass */ + /** @var \stdClass a post */ private $post1; - /** @var \stdClass */ + /** @var \stdClass another post */ private $post2; - /** @var \stdClass */ + /** @var \stdClass answer to a post */ private $answer1; - /** @var \stdClass */ + /** @var \stdClass another answer to a post */ private $answer2; /** @var \mod_moodleoverflow_generator $generator */ private $generator; From 565c6dc147e0c9bcf78c3f57e1ab1bfe669a6ed5 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 15 May 2023 14:25:21 +0200 Subject: [PATCH 21/35] post sorting updated1 --- classes/ratings.php | 224 ++++++++++++++++++-------------------------- 1 file changed, 89 insertions(+), 135 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 76ea3246fe..ada282c927 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -230,160 +230,119 @@ public static function moodleoverflow_get_reputation($moodleoverflowid, $userid return self::moodleoverflow_get_reputation_instance($moodleoverflow->id, $userid); } - /** - * Sort a discussion by the ratings of their posts. - * - * @param array $posts - * - * @return array - */ public static function moodleoverflow_sort_answers_by_ratings($posts) { - // Create copies to manipulate. - $parentcopy = $posts; - $postscopy = $posts; - $anothercopy = $posts; - - // Check if teacher ratings are prefered. - $preferteacher = (array_shift($anothercopy)->ratingpreference == 1); - - // Create an array with all the keys of the older array. - $oldorder = array(); - foreach ($postscopy as $postid => $post) { - $oldorder[] = $postid; + // Create a copy that only has the answer posts and save the parent post. + $answerposts = $posts; + $parentpost = array_shift($answerposts); + + // Create an empty array for the sorted posts and add the parent post. + $sortedposts = array(); + $sortedposts[0] = $parentpost; + // Check if solved posts are preferred over helpful posts. + $solutionspreferred = $posts[array_key_first($posts)]->ratingpreference == 1; + + // Sort the answer posts by ratings. + + // Build groups of different types of answers (Solved and helpful, only solved/helpful, other). + // If a group is complete, sort the group. + $index = 1; + $startsolvedandhelpful = 1; + $startsolved = 1; + $starthelpful = 1; + $startother = 1; + // Solved and helpful posts are first. + foreach ($answerposts as $post) { + if ($post->statusteacher == 1 && $post->statusstarter == 1) { + $sortedposts[$index] = $post; + $index++; + } + } + //Update the indices and sort the group by votes. + if ($index > $startsolvedandhelpful) { + $startsolved = $index; + $starthelpful = $index; + $startother = $index; + self::moodleoverflow_quicksort_post_by_votes($sortedposts, $startsolvedandhelpful, $index - 1); } - // Create an array for the new order. - $neworder = array(); + // Check if solutions are preferred. + if ($solutionspreferred) { - // The parent post stays the parent post. - $parent = array_shift($parentcopy); - unset($postscopy[$parent->id]); - $discussionid = $parent->discussion; - $neworder[] = (int) $parent->id; - - // Check if answers has been marked. - $statusstarter = self::moodleoverflow_discussion_is_solved($discussionid, false); - $statusteacher = self::moodleoverflow_discussion_is_solved($discussionid, true); - - // The answers that are marked as correct by both are displayed first. - if ($statusteacher && $statusstarter) { - $markedposts = array(); - foreach ($statusteacher as $solvedposts) { - foreach ($statusstarter as $helpfulposts) { - // Is the same answer correct for both? - if ($solvedposts->postid == $helpfulposts->postid) { - // Save the post that is marked as solved and helpful and go to the next post. - $markedposts[] = $postscopy[$solvedposts->postid]; - break; - } + // Build the group of only solved posts. + foreach ($answerposts as $post) { + if ($post->statusteacher == 1 && $post->statusstarter == 0) { + $sortedposts[$index] = $post; + $index++; } } - // Now sort the posts by their votes. - self::moodleoverflow_sort_post_by_votes($markedposts); - - // Iterate trough the marked posts and add it to the new Order. - foreach ($markedposts as $post) { - // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $post->id; - unset($postscopy[$post->id]); + // Update the indices and sort the group by votes. + if ($index > $startsolved) { + $starthelpful = $index; + $startother = $index; + self::moodleoverflow_quicksort_post_by_votes($sortedposts, $startsolved, $index - 1); } - } - // If the answers the teacher marks are preferred, and only - // the teacher marked an answer as solved, display it first. - if ($preferteacher && $statusteacher) { - // Save the marked posts. - $markedposts = array(); - foreach ($statusteacher as $solvedpost) { - if (array_key_exists($solvedpost->postid, $postscopy)) { - $markedposts[] = $postscopy[$solvedpost->postid]; + // Build the group of only helpful posts. + foreach ($answerposts as $post) { + if ($post->statusteacher == 0 && $post->statusstarter == 1) { + $sortedposts[$index] = $post; + $index++; } } - // Sort the solved answers. - self::moodleoverflow_sort_post_by_votes($markedposts); - - // Iterate trough the marked posts and add it to the new Order. - foreach ($markedposts as $post) { - // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $post->id; - unset($postscopy[$post->id]); + // Update the indices and sort the group by votes. + if ($index > $starthelpful) { + $startother = $index; + self::moodleoverflow_quicksort_post_by_votes($sortedposts, $starthelpful, $index - 1); } - } + } else { - // If the user who started the discussion has marked - // an answer as helpful, display this answer first. - if ($statusstarter) { - // Save the marked posts. - $markedposts = array(); - foreach ($statusstarter as $helpfulpost) { - if (array_key_exists($helpfulpost->postid, $postscopy)) { - $markedposts[] = $postscopy[$helpfulpost->postid]; + // Build the group of only helpful posts. + foreach ($answerposts as $post) { + if ($post->statusteacher == 0 && $post->statusstarter == 1) { + $sortedposts[$index] = $post; + $index++; } } - // Sort the helpful answers. - self::moodleoverflow_sort_post_by_votes($markedposts); - - // Iterate trough the marked posts and add it to the new Order. - foreach ($markedposts as $post) { - // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $post->id; - unset($postscopy[$post->id]); + // Update the indices and sort the group by votes. + if ($index > $starthelpful) { + $startsolved = $index; + $startother = $index; + self::moodleoverflow_quicksort_post_by_votes($sortedposts, $starthelpful, $index - 1); } - } - // If a teacher has marked an answer as solved, display it next. - if ($statusteacher) { - // Save the marked posts. - $markedposts = array(); - foreach ($statusteacher as $solvedpost) { - if (array_key_exists($solvedpost->postid, $postscopy)) { - $markedposts[] = $postscopy[$solvedpost->postid]; + // Build the group of only solved posts. + foreach ($answerposts as $post) { + if ($post->statusteacher == 1 && $post->statusstarter == 0) { + $sortedposts[$index] = $post; + $index++; } } - // Sort the solved answers. - self::moodleoverflow_sort_post_by_votes($markedposts); - - // Iterate trough the marked posts and add it to the new Order. - foreach ($markedposts as $post) { - // Add the post to the new order and delete it from the posts array. - $neworder[] = (int) $post->id; - unset($postscopy[$post->id]); + // Update the indices and sort the group by votes. + if ($index > $startsolved) { + $startother = $index; + self::moodleoverflow_quicksort_post_by_votes($sortedposts, $startsolved, $index - 1); } } - // All answers that are not marked by someone should now be left. - - // Search for all comments. - foreach ($postscopy as $postid => $post) { - // Add all comments to the order. - // They are independant from the votes. - if ($post->parent != $parent->id) { - $neworder[] = $postid; - unset($postscopy[$postid]); + // Now build the group of posts without ratings like helpful/solved. + foreach ($answerposts as $post) { + if ($post->statusteacher == 0 && $post->statusstarter == 0) { + $sortedposts[$index] = $post; + $index++; } } - - // Sort the remaining answers by their total votes. - $votesarray = array(); - foreach ($postscopy as $postid => $post) { - $votesarray[$post->id] = $post->upvotes - $post->downvotes; - } - arsort($votesarray); - - // Add the remaining messages to the new order. - foreach ($votesarray as $postid => $votes) { - $neworder[] = $postid; + // Update the indices and sort the group by votes. + if ($index > $startother) { + self::moodleoverflow_quicksort_post_by_votes($sortedposts, $startother, $index - 1); } - // The new order is determined. - // It has to be applied now. - $sortedposts = array(); - foreach ($neworder as $k) { - $sortedposts[$k] = $posts[$k]; + // Rearrange the indices and return the sorted posts. + $neworder = array(); + foreach ($sortedposts as $post) { + $neworder[$post->id] = $post; } - - // Return the sorted posts. - return $sortedposts; + // return now the sorted posts. + return $neworder; } /** @@ -845,18 +804,13 @@ public static function moodleoverflow_user_can_rate($post, $modulecontext, $user && $post->reviewed == 1; } - private static function moodleoverflow_sort_post_by_votes(array $posts) { - // Function uses quicksort to sort the posts in descending order. - self::moodleoverflow_quicksort_post_by_votes($posts, 0, count($posts) - 1); - } - - private static function moodleoverflow_quicksort_post_by_votes(array $posts, $low, $high) { + private static function moodleoverflow_quicksort_post_by_votes(array &$posts, $low, $high) { if ($low >= $high) { return; } $left = $low; $right = $high; - $pivot = $posts[($low + $high) / 2]->votesdifference; + $pivot = $posts[intval(($low + $high) / 2)]->votesdifference; do { while ($posts[$left]->votesdifference > $pivot) { $left++; From 0951e8d9e8cde68769aba300ec2783a12d81caad Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 15 May 2023 15:58:47 +0200 Subject: [PATCH 22/35] WIP: sort of posts by rating --- classes/ratings.php | 8 ++ tests/ratings_test.php | 224 +++++++++++++++++++++++++++++++++++++++ tests/userstats_test.php | 3 +- 3 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 tests/ratings_test.php diff --git a/classes/ratings.php b/classes/ratings.php index 4aee9c48f5..0c6bb5288c 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -227,6 +227,11 @@ public static function moodleoverflow_get_reputation($moodleoverflowid, $userid return self::moodleoverflow_get_reputation_instance($moodleoverflow->id, $userid); } + /** + * Sort the answers of a discussion by their marks and votes. + * + * @param object $posts all the posts from a discussion. + */ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Create a copy that only has the answer posts and save the parent post. $answerposts = $posts; @@ -235,12 +240,15 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Create an empty array for the sorted posts and add the parent post. $sortedposts = array(); $sortedposts[0] = $parentpost; + // Check if solved posts are preferred over helpful posts. $solutionspreferred = $posts[array_key_first($posts)]->ratingpreference == 1; // Sort the answer posts by ratings. // Build groups of different types of answers (Solved and helpful, only solved/helpful, other). + // statusteacher == 1 means the post is marked as solved. + // statusstarter == 1 means the post is marked as helpful. // If a group is complete, sort the group. $index = 1; $startsolvedandhelpful = 1; diff --git a/tests/ratings_test.php b/tests/ratings_test.php new file mode 100644 index 0000000000..232e34afc3 --- /dev/null +++ b/tests/ratings_test.php @@ -0,0 +1,224 @@ +<?php +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see <http://www.gnu.org/licenses/>. + +/** + * The module moodleoverflow tests. + * + * @package mod_moodleoverflow + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace mod_moodleoverflow; +use mod_moodleoverflow\ratings; + +defined('MOODLE_INTERNAL') || die(); + + +global $CFG; +require_once($CFG->dirroot . '/mod/moodleoverflow/locallib.php'); + +/** + * PHPUnit Tests for testing the ratings.php. + * + * @package mod_moodleoverflow + * @copyright 2023 Tamaro Walter + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class ratings_test extends \advanced_testcase { + /** @var \stdClass test course */ + private $course; + + /** @var \stdClass coursemodule */ + private $coursemodule; + + /** @var \stdClass test moodleoverflow */ + private $moodleoverflow; + + /** @var \stdClass test teacher */ + private $teacher; + + /** @var \stdClass test user */ + private $user1; + + /** @var \stdClass another test user */ + private $user2; + + /** @var \stdClass a discussion */ + private $discussion; + + /** @var \stdClass a post from the teacher*/ + private $post; + + /** @var \stdClass answer from user 1 */ + private $answer1; + + /** @var \stdClass answer from user 1 */ + private $answer2; + + /** @var \stdClass answer from user 1 */ + private $answer3; + + /** @var \stdClass answer from user 2 */ + private $answer4; + + /** @var \stdClass answer from user 2 */ + private $answer5; + + /** @var \stdClass answer from user 2 */ + private $answer6; + + /** @var \mod_moodleoverflow_generator $generator */ + private $generator; + + /** + * Test setUp. + */ + public function setUp(): void { + $this->resetAfterTest(); + $this->helper_course_set_up(); + } + + /** + * Test tearDown. + */ + public function tearDown(): void { + // Clear all caches. + \mod_moodleoverflow\subscriptions::reset_moodleoverflow_cache(); + \mod_moodleoverflow\subscriptions::reset_discussion_cache(); + } + + // Begin of test functions + + /** + * Test, if rating can sort after ever group with ratingpreferences on helpful first. + */ + public function test_everygrouphelpfulon() { + // Create helpful and solved and up and downvotes ratings. + $this->create_everygroup(); + $this->set_ratingpreferences(1); + // Create a array of the posts and sort them. + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + var_dump($sortedposts); + $this->assertEquals(1,1); + } + + // Helper functions + + /** + * This function creates: + * - a course with a moodleoverflow + * - a teacher, who creates a discussion with a post + * - 2 users, which answer to the post from the teacher + */ + private function helper_course_set_up() { + global $DB; + // Create a new course with a moodleoverflow forum. + $this->course = $this->getDataGenerator()->create_course(); + $location = array('course' => $this->course->id); + $this->moodleoverflow = $this->getDataGenerator()->create_module('moodleoverflow', $location); + $this->coursemodule = get_coursemodule_from_instance('moodleoverflow', $this->moodleoverflow->id); + + // Create a teacher. + $this->teacher = $this->getDataGenerator()->create_user(array('firstname' => 'Tamaro', 'lastname' => 'Walter')); + $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, 'student'); + + // Create 2 users. + $this->user1 = $this->getDataGenerator()->create_user(array('firstname' => 'Ava', 'lastname' => 'Davis')); + $this->getDataGenerator()->enrol_user($this->user1->id, $this->course->id, 'student'); + $this->user2 = $this->getDataGenerator()->create_user(array('firstname' => 'Ethan', 'lastname' => 'Brown')); + $this->getDataGenerator()->enrol_user($this->user2->id, $this->course->id, 'student'); + + // Create a discussion, a parent post and six answers + $this->generator = $this->getDataGenerator()->get_plugin_generator('mod_moodleoverflow'); + $this->discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->teacher); + $this->post = $DB->get_record('moodleoverflow_posts', array('id' => $this->discussion[0]->firstpost), '*'); + $this->answer1 = $this->generator->reply_to_post($this->discussion[1], $this->user1, true); + $this->answer2 = $this->generator->reply_to_post($this->discussion[1], $this->user1, true); + $this->answer3 = $this->generator->reply_to_post($this->discussion[1], $this->user1, true); + $this->answer4 = $this->generator->reply_to_post($this->discussion[1], $this->user2, true); + $this->answer5 = $this->generator->reply_to_post($this->discussion[1], $this->user2, true); + $this->answer6 = $this->generator->reply_to_post($this->discussion[1], $this->user2, true); + } + + /** + * creates a rating of every type by adding attributes to the post: + * - post that is solved and helpful + * . post that is only helpful + * - post that is only solved + * - post that is not marked + */ + private function create_everygroup() { + // Answer1. + $this->answer1->upvotes = 0; + $this->answer1->downvotes = 0; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; + $this->answer1->statusstarter = 1; + $this->answer1->statusteacher = 1; + + // Answer2. + $this->answer2->upvotes = 0; + $this->answer2->downvotes = 0; + $this->answer2->votesdifference = $this->answer2->upvotes - $this->answer2->downvotes; + $this->answer2->statusstarter = 0; + $this->answer2->statusteacher = 1; + + // Answer3. + $this->answer3->upvotes = 0; + $this->answer3->downvotes = 0; + $this->answer3->votesdifference = $this->answer3->upvotes - $this->answer3->downvotes; + $this->answer3->statusstarter = 1; + $this->answer3->statusteacher = 0; + + // Answer4. + $this->answer4->upvotes = 1; + $this->answer4->downvotes = 0; + $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; + $this->answer4->statusstarter = 0; + $this->answer4->statusteacher = 0; + + // Answer5. + $this->answer5->upvotes = 0; + $this->answer5->downvotes = 1; + $this->answer5->votesdifference = $this->answer5->upvotes - $this->answer5->downvotes; + $this->answer5->statusstarter = 0; + $this->answer5->statusteacher = 0; + + // Answer6. + $this->answer6->upvotes = 0; + $this->answer6->downvotes = 0; + $this->answer6->votesdifference = $this->answer6->upvotes - $this->answer6->downvotes; + $this->answer6->statusstarter = 0; + $this->answer6->statusteacher = 0; + } + + /** + * sets the ratingpreferences to 1 or 0: + * 1 = solved posts will be shown above helpful posts. + * 0 = helpful posts will be shown above solved posts. + */ + private function set_ratingpreferences($preference) { + if ($preference == 0 || $preference == 1) { + $this->post->ratingpreference = $preference; + $this->answer1->ratingpreference = $preference; + $this->answer2->ratingpreference = $preference; + $this->answer3->ratingpreference = $preference; + $this->answer4->ratingpreference = $preference; + $this->answer5->ratingpreference = $preference; + $this->answer6->ratingpreference = $preference; + } + } +} diff --git a/tests/userstats_test.php b/tests/userstats_test.php index 24ac3ed817..01bb9862fb 100644 --- a/tests/userstats_test.php +++ b/tests/userstats_test.php @@ -57,7 +57,7 @@ class userstats_test extends \advanced_testcase { /** @var \stdClass another test user */ private $user2; - /** @var \stdClass fake discussion */ + /** @var \stdClass a discussion */ private $discussion1; /** @var \stdClass another faked discussion */ @@ -74,6 +74,7 @@ class userstats_test extends \advanced_testcase { /** @var \stdClass another answer to a post */ private $answer2; + /** @var \mod_moodleoverflow_generator $generator */ private $generator; From 82e7ff7409e189ab5f62cc39295edad1318ca7cb Mon Sep 17 00:00:00 2001 From: NinaHerrmann <nina.herrmann@uni-muenster.de> Date: Mon, 15 May 2023 14:41:34 +0200 Subject: [PATCH 23/35] minor changes --- amd/src/rating.js | 8 ++++---- tests/dailymail_test.php | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/amd/src/rating.js b/amd/src/rating.js index 41ac768c30..133eeb71db 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -112,10 +112,10 @@ export function init(userid, allowmultiplemarks) { const rating = shouldRemove ? baseRating * 10 : baseRating; await sendVote(postid, rating, userid); - /* If multiplemarks are not allowed (that is the default mode): delete all marks. - else: only delete the mark if the post is being unmarked. + /* If multiplemarks are not allowed (that is the default mode): delete all marks. + else: only delete the mark if the post is being unmarked. - then add a mark, if the post is being marked. + Add a mark, if the post is being marked. */ if (!allowmultiplemarks) { // Delete all marks in the discussion @@ -149,7 +149,7 @@ export function init(userid, allowmultiplemarks) { /** * Function to change the String of the post data-action button. - * Only usable if mulitplemarks are allowed. + * Only used if mulitplemarks are allowed. * @param {string} htmlclass the class where the String is being updated * @param {string} action helpful or solved mark */ diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index 3c615730ab..29fc74bdce 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -86,8 +86,6 @@ public function tearDown(): void { \mod_moodleoverflow\subscriptions::reset_discussion_cache(); } - - // Helper functions. /** From a161e7ad19b90c890eec204b5a414c9d24d7717a Mon Sep 17 00:00:00 2001 From: NinaHerrmann <nina.herrmann@uni-muenster.de> Date: Mon, 15 May 2023 14:53:50 +0200 Subject: [PATCH 24/35] rename statusteacher and statusstarter in markedhelpful and markedsolution --- amd/build/rating.min.js | 2 +- amd/build/rating.min.js.map | 2 +- amd/src/rating.js | 2 +- classes/ratings.php | 12 ++++---- locallib.php | 44 +++++++++++++++--------------- styles.css | 10 +++---- templates/discussion_list.mustache | 16 +++++------ templates/discussions.mustache | 8 +++--- 8 files changed, 48 insertions(+), 48 deletions(-) diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index f60ce3513a..276685f62e 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -5,6 +5,6 @@ define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/ * @module mod_moodleoverflow/rating * @copyright 2022 Justus Dieckmann WWU * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"statusstarter":"statusteacher",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),allowmultiplemarks)shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"),changeStrings(htmlclass,action));else for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"),allowmultiplemarks&&changeStrings(htmlclass,action))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}async function changeStrings(htmlclass,action){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","markhelpful","alsomarkhelpful"]);var othermarkedposts=!1;for(const el of root.querySelectorAll(".moodleoverflowpost"))if(el.classList.contains(htmlclass)){othermarkedposts=!0;break}for(const el of root.querySelectorAll(".moodleoverflowpost"))!el.classList.contains(htmlclass)&&el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]'))&&(el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=othermarkedposts?await(0,_str.get_string)("alsomark".concat(action),"mod_moodleoverflow"):await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"))}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"markedhelpful":"markedsolution",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),allowmultiplemarks)shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"),changeStrings(htmlclass,action));else for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"),allowmultiplemarks&&changeStrings(htmlclass,action))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}async function changeStrings(htmlclass,action){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","markhelpful","alsomarkhelpful"]);var othermarkedposts=!1;for(const el of root.querySelectorAll(".moodleoverflowpost"))if(el.classList.contains(htmlclass)){othermarkedposts=!0;break}for(const el of root.querySelectorAll(".moodleoverflowpost"))!el.classList.contains(htmlclass)&&el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]'))&&(el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=othermarkedposts?await(0,_str.get_string)("alsomark".concat(action),"mod_moodleoverflow"):await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"))}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index 11f1b470a8..a1fb0b6643 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only usable if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'markedhelpful' : 'markedsolution';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only usable if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} \ No newline at end of file diff --git a/amd/src/rating.js b/amd/src/rating.js index 133eeb71db..0f44f3ba77 100644 --- a/amd/src/rating.js +++ b/amd/src/rating.js @@ -106,7 +106,7 @@ export function init(userid, allowmultiplemarks) { case 'helpful': case 'solved': { const isHelpful = action === 'helpful'; - const htmlclass = isHelpful ? 'statusstarter' : 'statusteacher'; + const htmlclass = isHelpful ? 'markedhelpful' : 'markedsolution'; const shouldRemove = postElement.classList.contains(htmlclass); const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED; const rating = shouldRemove ? baseRating * 10 : baseRating; diff --git a/classes/ratings.php b/classes/ratings.php index 0c6bb5288c..ac05e83a77 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -257,7 +257,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { $startother = 1; // Solved and helpful posts are first. foreach ($answerposts as $post) { - if ($post->statusteacher == 1 && $post->statusstarter == 1) { + if ($post->markedsolution == 1 && $post->markedhelpful == 1) { $sortedposts[$index] = $post; $index++; } @@ -275,7 +275,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only solved posts. foreach ($answerposts as $post) { - if ($post->statusteacher == 1 && $post->statusstarter == 0) { + if ($post->markedsolution == 1 && $post->markedhelpful == 0) { $sortedposts[$index] = $post; $index++; } @@ -289,7 +289,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only helpful posts. foreach ($answerposts as $post) { - if ($post->statusteacher == 0 && $post->statusstarter == 1) { + if ($post->markedsolution == 0 && $post->markedhelpful == 1) { $sortedposts[$index] = $post; $index++; } @@ -303,7 +303,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only helpful posts. foreach ($answerposts as $post) { - if ($post->statusteacher == 0 && $post->statusstarter == 1) { + if ($post->markedsolution == 0 && $post->markedhelpful == 1) { $sortedposts[$index] = $post; $index++; } @@ -317,7 +317,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only solved posts. foreach ($answerposts as $post) { - if ($post->statusteacher == 1 && $post->statusstarter == 0) { + if ($post->markedsolution == 1 && $post->markedhelpful == 0) { $sortedposts[$index] = $post; $index++; } @@ -331,7 +331,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Now build the group of posts without ratings like helpful/solved. foreach ($answerposts as $post) { - if ($post->statusteacher == 0 && $post->statusstarter == 0) { + if ($post->markedsolution == 0 && $post->markedhelpful == 0) { $sortedposts[$index] = $post; $index++; } diff --git a/locallib.php b/locallib.php index de9c882893..71ff6052eb 100644 --- a/locallib.php +++ b/locallib.php @@ -265,31 +265,31 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - } // Check if the question owner marked the question as helpful. - $statusstarter = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, false); + $markedhelpful = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, false); $preparedarray[$i]['starterlink'] = null; - if ($statusstarter) { + if ($markedhelpful) { $link = '/mod/moodleoverflow/discussion.php?d='; - $statusstarter = $statusstarter[array_key_first($statusstarter)]; + $markedhelpful = $markedhelpful[array_key_first($markedhelpful)]; $preparedarray[$i]['starterlink'] = new moodle_url($link . - $statusstarter->discussionid . '#p' . $statusstarter->postid); + $markedhelpful->discussionid . '#p' . $markedhelpful->postid); } // Check if a teacher marked a post as solved. - $statusteacher = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, true); + $markedsolution = \mod_moodleoverflow\ratings::moodleoverflow_discussion_is_solved($discussion->discussion, true); $preparedarray[$i]['teacherlink'] = null; - if ($statusteacher) { + if ($markedsolution) { $link = '/mod/moodleoverflow/discussion.php?d='; - $statusteacher = $statusteacher[array_key_first($statusteacher)]; + $markedsolution = $markedsolution[array_key_first($markedsolution)]; $preparedarray[$i]['teacherlink'] = new moodle_url($link . - $statusteacher->discussionid . '#p' . $statusteacher->postid); + $markedsolution->discussionid . '#p' . $markedsolution->postid); } // Check if a single post was marked by the question owner and a teacher. $statusboth = false; - if ($statusstarter && $statusteacher) { - if ($statusstarter->postid == $statusteacher->postid) { + if ($markedhelpful && $markedsolution) { + if ($markedhelpful->postid == $markedsolution->postid) { $statusboth = true; } } @@ -401,8 +401,8 @@ function moodleoverflow_print_latest_discussions($moodleoverflow, $cm, $page = - $preparedarray[$i]['linktopopup'] = $linktopopup; // Add all created data to an array. - $preparedarray[$i]['statusstarter'] = $statusstarter; - $preparedarray[$i]['statusteacher'] = $statusteacher; + $preparedarray[$i]['markedhelpful'] = $markedhelpful; + $preparedarray[$i]['markedsolution'] = $markedsolution; $preparedarray[$i]['statusboth'] = $statusboth; $preparedarray[$i]['votes'] = $votes; @@ -1059,8 +1059,8 @@ function moodleoverflow_get_all_discussion_posts($discussionid, $tracking, $modc $posts[$postid]->upvotes = $discussionratings[$post->id]->upvotes; $posts[$postid]->downvotes = $discussionratings[$post->id]->downvotes; $posts[$postid]->votesdifference = $posts[$postid]->upvotes - $posts[$postid]->downvotes; - $posts[$postid]->statusstarter = $discussionratings[$post->id]->ishelpful; - $posts[$postid]->statusteacher = $discussionratings[$post->id]->issolved; + $posts[$postid]->markedhelpful = $discussionratings[$post->id]->ishelpful; + $posts[$postid]->markedsolution = $discussionratings[$post->id]->issolved; } // Order the answers by their ratings. @@ -1240,7 +1240,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co if ($canmarkhelpful) { // When the post is already marked, remove the mark instead. $link = '/mod/moodleoverflow/discussion.php'; - if ($post->statusstarter) { + if ($post->markedhelpful) { $commands[] = html_writer::tag('a', $str->marknothelpful, array('class' => 'markhelpful onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'helpful')); } else { @@ -1262,7 +1262,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co // When the post is already marked, remove the mark instead. $link = '/mod/moodleoverflow/discussion.php'; - if ($post->statusteacher) { + if ($post->markedsolution) { $commands[] = html_writer::tag('a', $str->marknotsolved, array('class' => 'marksolved onlyifreviewed', 'role' => 'button', 'data-moodleoverflow-action' => 'solved')); } else { @@ -1335,8 +1335,8 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co $mustachedata->votes = $post->upvotes - $post->downvotes; // Check if the post is marked. - $mustachedata->statusstarter = $post->statusstarter; - $mustachedata->statusteacher = $post->statusteacher; + $mustachedata->markedhelpful = $post->markedhelpful; + $mustachedata->markedsolution = $post->markedsolution; // Did the user rated this post? $rating = \mod_moodleoverflow\ratings::moodleoverflow_user_rated($post->id); @@ -1377,11 +1377,11 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co } } } - if ($post->statusstarter) { - $postclass .= ' statusstarter'; + if ($post->markedhelpful) { + $postclass .= ' markedhelpful'; } - if ($post->statusteacher) { - $postclass .= ' statusteacher'; + if ($post->markedsolution) { + $postclass .= ' markedsolution'; } $mustachedata->postclass = $postclass; diff --git a/styles.css b/styles.css index c6c3c8fbf7..f0c92ff5bf 100644 --- a/styles.css +++ b/styles.css @@ -191,7 +191,7 @@ width: 4px; } -.moodleoverflowpost.statusteacher.statusstarter:before { +.moodleoverflowpost.markedsolution.markedhelpful:before { background: linear-gradient(80deg, rgba(234, 133, 22, 1) 50%, rgba(112, 160, 52, 1) 50%); bottom: -1px; content: ""; @@ -202,7 +202,7 @@ width: 4px; } -.moodleoverflowpost.statusteacher:before { +.moodleoverflowpost.markedsolution:before { background: rgba(112, 160, 52, 1); bottom: -1px; content: ""; @@ -213,7 +213,7 @@ width: 4px; } -.moodleoverflowpost.statusstarter:before { +.moodleoverflowpost.markedhelpful:before { background: rgba(234, 133, 22, 1); bottom: -1px; content: ""; @@ -229,11 +229,11 @@ display: none; } -.moodleoverflowpost.statusstarter .onlyifhelpful { +.moodleoverflowpost.markedhelpful .onlyifhelpful { display: initial; } -.moodleoverflowpost.statusteacher .onlyifsolved { +.moodleoverflowpost.markedsolution .onlyifsolved { display: initial; } diff --git a/templates/discussion_list.mustache b/templates/discussion_list.mustache index 19902f0a78..1cb4a05c76 100644 --- a/templates/discussion_list.mustache +++ b/templates/discussion_list.mustache @@ -119,23 +119,23 @@ {{#pix}}i/duration, moodle, {{#str}}pending_review, mod_moodleoverflow{{/str}}{{/pix}} {{/ questionunderreview }} {{^ questionunderreview }} - {{#statusteacher}} + {{#markedsolution}} <a href="{{teacherlink}}"> {{# pix}} status/c_outline, moodleoverflow, {{#str}}teacherrating, moodleoverflow{{/str}} {{/ pix}} </a> - {{/statusteacher}} - {{^statusteacher}} + {{/markedsolution}} + {{^markedsolution}} {{# pix}} status/c_blank, moodleoverflow, {{#str}}marknotsolved, moodleoverflow{{/str}}{{/ pix}} - {{/statusteacher}} + {{/markedsolution}} - {{#statusstarter}} + {{#markedhelpful}} <a href="{{starterlink}}"> {{# pix}} status/b_outline, moodleoverflow, {{#str}}starterrating, moodleoverflow{{/str}} {{/ pix}} </a> - {{/statusstarter}} - {{^statusstarter}} + {{/markedhelpful}} + {{^markedhelpful}} {{# pix}} status/b_blank, moodleoverflow, {{#str}}marknothelpful, moodleoverflow{{/str}} {{/ pix}} - {{/statusstarter}} + {{/markedhelpful}} {{/ questionunderreview }} </td> diff --git a/templates/discussions.mustache b/templates/discussions.mustache index e8c30202ea..48340589d3 100644 --- a/templates/discussions.mustache +++ b/templates/discussions.mustache @@ -46,16 +46,16 @@ {{#pix}}i/duration, moodle, {{#str}}pending_review, mod_moodleoverflow{{/str}}{{/pix}} {{/ questionunderreview }} {{^ questionunderreview }} - {{#statusteacher}} + {{#markedsolution}} <a href="{{teacherlink}}">{{! avoid whitespace !}}{{# pix}} i/status-solved, moodleoverflow, {{#str}}containsteacherrating, moodleoverflow{{/str}} {{/ pix}}{{! !}}</a> - {{/statusteacher}} - {{#statusstarter}} + {{/markedsolution}} + {{#markedhelpful}} <a href="{{starterlink}}">{{! avoid whitespace !}}{{# pix}} i/status-helpful, moodleoverflow, {{#str}}containsstarterrating, moodleoverflow{{/str}} {{/ pix}}{{! !}}</a> - {{/ statusstarter }} + {{/ markedhelpful }} {{/ questionunderreview }} </div> <div class="d-flex flex-colum flex-wrap justify-content-around"> From f2781289ae65b82f2551b3e1157380813d5ad65f Mon Sep 17 00:00:00 2001 From: NinaHerrmann <nina.herrmann@uni-muenster.de> Date: Mon, 15 May 2023 15:03:44 +0200 Subject: [PATCH 25/35] grunt build --- amd/build/rating.min.js.map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index a1fb0b6643..e0ec5b562e 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'markedhelpful' : 'markedsolution';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n then add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only usable if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,gBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'markedhelpful' : 'markedsolution';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n Add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only used if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,iBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} \ No newline at end of file From 5294e8004aa5e133f0f634d71c8f9215ebe01a29 Mon Sep 17 00:00:00 2001 From: NinaHerrmann <nina.herrmann@uni-muenster.de> Date: Tue, 16 May 2023 14:13:04 +0200 Subject: [PATCH 26/35] WIP - var_dumps to check missing post in ratings.php sorting --- classes/ratings.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/classes/ratings.php b/classes/ratings.php index ac05e83a77..e9c35ac91f 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -243,7 +243,8 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Check if solved posts are preferred over helpful posts. $solutionspreferred = $posts[array_key_first($posts)]->ratingpreference == 1; - + var_dump('start'); + var_dump($posts); // Sort the answer posts by ratings. // Build groups of different types of answers (Solved and helpful, only solved/helpful, other). @@ -342,10 +343,15 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { } // Rearrange the indices and return the sorted posts. + var_dump('sortedpost'); + var_dump($sortedposts); + $neworder = array(); foreach ($sortedposts as $post) { $neworder[$post->id] = $post; } + var_dump('neworder'); + var_dump($neworder); // return now the sorted posts. return $neworder; } From 4145d3c45344e34b2450a6879144bd1782054015 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Tue, 16 May 2023 15:22:59 +0200 Subject: [PATCH 27/35] sorting error fixed in ratings.php --- classes/ratings.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index e9c35ac91f..fbf7be5052 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -242,11 +242,12 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { $sortedposts[0] = $parentpost; // Check if solved posts are preferred over helpful posts. - $solutionspreferred = $posts[array_key_first($posts)]->ratingpreference == 1; - var_dump('start'); - var_dump($posts); - // Sort the answer posts by ratings. + $solutionspreferred = false; + if ($posts[array_key_first($posts)]->ratingpreference == 1) { + $solutionspreferred = true; + } + // Sort the answer posts by ratings. // Build groups of different types of answers (Solved and helpful, only solved/helpful, other). // statusteacher == 1 means the post is marked as solved. // statusstarter == 1 means the post is marked as helpful. @@ -343,15 +344,12 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { } // Rearrange the indices and return the sorted posts. - var_dump('sortedpost'); - var_dump($sortedposts); $neworder = array(); foreach ($sortedposts as $post) { $neworder[$post->id] = $post; } - var_dump('neworder'); - var_dump($neworder); + // return now the sorted posts. return $neworder; } @@ -831,7 +829,7 @@ private static function moodleoverflow_quicksort_post_by_votes(array &$posts, $l } if ($left <= $right) { $temp = $posts[$right]; - $post[$right] = $posts[$left]; + $posts[$right] = $posts[$left]; $posts[$left] = $temp; $right--; $left++; From c76720f3caa50e1d67a9408445d087f6209f1792 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Tue, 16 May 2023 17:40:45 +0200 Subject: [PATCH 28/35] WIP: write test cases for rating.php --- amd/build/activityhelp.min.js | 2 +- amd/build/activityhelp.min.js.map | 2 +- amd/build/rating.min.js | 9 +- amd/build/rating.min.js.map | 2 +- amd/build/reviewing.min.js | 9 +- amd/build/reviewing.min.js.map | 2 +- amd/build/warnmodechange.min.js | 9 +- amd/build/warnmodechange.min.js.map | 2 +- classes/ratings.php | 10 +- tests/ratings_test.php | 154 ++++++++++++++++++++++------ 10 files changed, 133 insertions(+), 68 deletions(-) diff --git a/amd/build/activityhelp.min.js b/amd/build/activityhelp.min.js index a875b70b82..a3dc794e34 100644 --- a/amd/build/activityhelp.min.js +++ b/amd/build/activityhelp.min.js @@ -6,6 +6,6 @@ define("mod_moodleoverflow/activityhelp",["exports"],(function(_exports){Object. * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -const Selectors_actions={showHelpIcon:'[data-action="showhelpicon"]'};_exports.init=()=>{document.addEventListener("click",(event=>{event.target.closest(Selectors_actions.showHelpIcon)&&event.preventDefault()}))}})); +var Selectors_actions={showHelpIcon:'[data-action="showhelpicon"]'};_exports.init=function(){document.addEventListener("click",(function(event){event.target.closest(Selectors_actions.showHelpIcon)&&event.preventDefault()}))}})); //# sourceMappingURL=activityhelp.min.js.map \ No newline at end of file diff --git a/amd/build/activityhelp.min.js.map b/amd/build/activityhelp.min.js.map index 64d79cd463..7bae1c7cab 100644 --- a/amd/build/activityhelp.min.js.map +++ b/amd/build/activityhelp.min.js.map @@ -1 +1 @@ -{"version":3,"file":"activityhelp.min.js","sources":["../src/activityhelp.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Show a help string for the amount of activity column in userstats_table.php\n *\n * @module mod_moodleoverflow/activityhelp\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\n\nconst Selectors = {\n actions: {\n showHelpIcon: '[data-action=\"showhelpicon\"]',\n },\n};\n\n/**\n * Function that shows the help string.\n */\nexport const init = () => {\n document.addEventListener('click', event => {\n if (event.target.closest(Selectors.actions.showHelpIcon)) {\n event.preventDefault();\n }\n });\n};"],"names":["Selectors","showHelpIcon","document","addEventListener","event","target","closest","preventDefault"],"mappings":";;;;;;;;MAyBMA,kBACO,CACLC,aAAc,8CAOF,KAChBC,SAASC,iBAAiB,SAASC,QAC3BA,MAAMC,OAAOC,QAAQN,kBAAkBC,eACvCG,MAAMG"} \ No newline at end of file +{"version":3,"file":"activityhelp.min.js","sources":["../src/activityhelp.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Show a help string for the amount of activity column in userstats_table.php\n *\n * @module mod_moodleoverflow/activityhelp\n * @copyright 2023 Tamaro Walter\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n\n\nconst Selectors = {\n actions: {\n showHelpIcon: '[data-action=\"showhelpicon\"]',\n },\n};\n\n/**\n * Function that shows the help string.\n */\nexport const init = () => {\n document.addEventListener('click', event => {\n if (event.target.closest(Selectors.actions.showHelpIcon)) {\n event.preventDefault();\n }\n });\n};"],"names":["Selectors","showHelpIcon","document","addEventListener","event","target","closest","preventDefault"],"mappings":";;;;;;;;IAyBMA,kBACO,CACLC,aAAc,8CAOF,WAChBC,SAASC,iBAAiB,SAAS,SAAAC,OAC3BA,MAAMC,OAAOC,QAAQN,kBAAkBC,eACvCG,MAAMG"} \ No newline at end of file diff --git a/amd/build/rating.min.js b/amd/build/rating.min.js index 276685f62e..7a148eb2b0 100644 --- a/amd/build/rating.min.js +++ b/amd/build/rating.min.js @@ -1,10 +1,3 @@ -define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/str"],(function(_exports,_ajax,_prefetch,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} -/** - * Implements rating functionality - * - * @module mod_moodleoverflow/rating - * @copyright 2022 Justus Dieckmann WWU - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=async event=>{const actionElement=event.target.closest("[data-moodleoverflow-action]");if(!actionElement)return;const action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid");switch(action){case"upvote":case"downvote":{const isupvote="upvote"===action;if("clicked"===actionElement.getAttribute("data-moodleoverflow-state"))await sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_"+action,"mod_moodleoverflow");else{const otherAction=isupvote?"downvote":"upvote";await sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid),actionElement.setAttribute("data-moodleoverflow-state","clicked");const otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'));otherElement.setAttribute("data-moodleoverflow-state","notclicked"),actionElement.title=await(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow"),otherElement.title=await(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow")}}break;case"helpful":case"solved":{const isHelpful="helpful"===action,htmlclass=isHelpful?"markedhelpful":"markedsolution",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating;if(await sendVote(postid,rating,userid),allowmultiplemarks)shouldRemove&&(postElement.classList.remove(htmlclass),actionElement.textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"),changeStrings(htmlclass,action));else for(const el of root.querySelectorAll(".moodleoverflowpost."+htmlclass))el.classList.remove(htmlclass),el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");shouldRemove||(postElement.classList.add(htmlclass),actionElement.textContent=await(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow"),allowmultiplemarks&&changeStrings(htmlclass,action))}}}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);const RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");async function sendVote(postid,rating,userid){const response=await _ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];return root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((i=>{i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((i=>{i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((i=>{i.textContent=response.postrating})),response}async function changeStrings(htmlclass,action){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","markhelpful","alsomarkhelpful"]);var othermarkedposts=!1;for(const el of root.querySelectorAll(".moodleoverflowpost"))if(el.classList.contains(htmlclass)){othermarkedposts=!0;break}for(const el of root.querySelectorAll(".moodleoverflowpost"))!el.classList.contains(htmlclass)&&el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]'))&&(el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=othermarkedposts?await(0,_str.get_string)("alsomark".concat(action),"mod_moodleoverflow"):await(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow"))}})); +define("mod_moodleoverflow/rating",["exports","core/ajax","core/prefetch","core/str"],(function(_exports,_ajax,_prefetch,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _createForOfIteratorHelper(o,allowArrayLike){var it="undefined"!=typeof Symbol&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=function(o,minLen){if(!o)return;if("string"==typeof o)return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);"Object"===n&&o.constructor&&(n=o.constructor.name);if("Map"===n||"Set"===n)return Array.from(o);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}(o))||allowArrayLike&&o&&"number"==typeof o.length){it&&(o=it);var i=0,F=function(){};return{s:F,n:function(){return i>=o.length?{done:!0}:{done:!1,value:o[i++]}},e:function(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var err,normalCompletion=!0,didErr=!1;return{s:function(){it=it.call(o)},n:function(){var step=it.next();return normalCompletion=step.done,step},e:function(_e2){didErr=!0,err=_e2},f:function(){try{normalCompletion||null==it.return||it.return()}finally{if(didErr)throw err}}}}function _arrayLikeToArray(arr,len){(null==len||len>arr.length)&&(len=arr.length);for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg),value=info.value}catch(error){return void reject(error)}info.done?resolve(value):Promise.resolve(value).then(_next,_throw)}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise((function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(void 0)}))}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(userid,allowmultiplemarks){_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","marknotsolved","markhelpful","marknothelpful","action_remove_upvote","action_upvote","action_remove_downvote","action_downvote"]),root.onclick=(_ref=_asyncToGenerator(regeneratorRuntime.mark((function _callee(event){var actionElement,action,postElement,postid,isupvote,otherAction,otherElement,isHelpful,htmlclass,shouldRemove,baseRating,rating,_iterator,_step,el;return regeneratorRuntime.wrap((function(_context){for(;;)switch(_context.prev=_context.next){case 0:if(actionElement=event.target.closest("[data-moodleoverflow-action]")){_context.next=3;break}return _context.abrupt("return");case 3:action=actionElement.getAttribute("data-moodleoverflow-action"),postElement=actionElement.closest("[data-moodleoverflow-postid]"),postid=null==postElement?void 0:postElement.getAttribute("data-moodleoverflow-postid"),_context.t0=action,_context.next="upvote"===_context.t0||"downvote"===_context.t0?9:"helpful"===_context.t0||"solved"===_context.t0?32:73;break;case 9:if(isupvote="upvote"===action,"clicked"!==actionElement.getAttribute("data-moodleoverflow-state")){_context.next=19;break}return _context.next=13,sendVote(postid,isupvote?RATING_REMOVE_UPVOTE:RATING_REMOVE_DOWNVOTE,userid);case 13:return actionElement.setAttribute("data-moodleoverflow-state","notclicked"),_context.next=16,(0,_str.get_string)("action_"+action,"mod_moodleoverflow");case 16:actionElement.title=_context.sent,_context.next=31;break;case 19:return otherAction=isupvote?"downvote":"upvote",_context.next=22,sendVote(postid,isupvote?RATING_UPVOTE:RATING_DOWNVOTE,userid);case 22:return actionElement.setAttribute("data-moodleoverflow-state","clicked"),(otherElement=postElement.querySelector('[data-moodleoverflow-action="'.concat(otherAction,'"]'))).setAttribute("data-moodleoverflow-state","notclicked"),_context.next=27,(0,_str.get_string)("action_remove_"+action,"mod_moodleoverflow");case 27:return actionElement.title=_context.sent,_context.next=30,(0,_str.get_string)("action_"+otherAction,"mod_moodleoverflow");case 30:otherElement.title=_context.sent;case 31:return _context.abrupt("break",73);case 32:return htmlclass=(isHelpful="helpful"===action)?"markedhelpful":"markedsolution",shouldRemove=postElement.classList.contains(htmlclass),baseRating=isHelpful?RATING_HELPFUL:RATING_SOLVED,rating=shouldRemove?10*baseRating:baseRating,_context.next=39,sendVote(postid,rating,userid);case 39:if(allowmultiplemarks){_context.next=61;break}_iterator=_createForOfIteratorHelper(root.querySelectorAll(".moodleoverflowpost."+htmlclass)),_context.prev=41,_iterator.s();case 43:if((_step=_iterator.n()).done){_context.next=51;break}return(el=_step.value).classList.remove(htmlclass),_context.next=48,(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");case 48:el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=_context.sent;case 49:_context.next=43;break;case 51:_context.next=56;break;case 53:_context.prev=53,_context.t1=_context.catch(41),_iterator.e(_context.t1);case 56:return _context.prev=56,_iterator.f(),_context.finish(56);case 59:_context.next=67;break;case 61:if(!shouldRemove){_context.next=67;break}return postElement.classList.remove(htmlclass),_context.next=65,(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");case 65:actionElement.textContent=_context.sent,changeStrings(htmlclass,action);case 67:if(shouldRemove){_context.next=73;break}return postElement.classList.add(htmlclass),_context.next=71,(0,_str.get_string)("marknot".concat(action),"mod_moodleoverflow");case 71:actionElement.textContent=_context.sent,allowmultiplemarks&&changeStrings(htmlclass,action);case 73:case"end":return _context.stop()}}),_callee,null,[[41,53,56,59]])}))),function(_x4){return _ref.apply(this,arguments)});var _ref},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch);var RATING_DOWNVOTE=1,RATING_UPVOTE=2,RATING_REMOVE_DOWNVOTE=10,RATING_REMOVE_UPVOTE=20,RATING_SOLVED=3,RATING_HELPFUL=4,root=document.getElementById("moodleoverflow-root");function sendVote(_x,_x2,_x3){return _sendVote.apply(this,arguments)}function _sendVote(){return(_sendVote=_asyncToGenerator(regeneratorRuntime.mark((function _callee2(postid,rating,userid){var response;return regeneratorRuntime.wrap((function(_context2){for(;;)switch(_context2.prev=_context2.next){case 0:return _context2.next=2,_ajax.default.call([{methodname:"mod_moodleoverflow_record_vote",args:{postid:postid,ratingid:rating}}])[0];case 2:return response=_context2.sent,root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(userid,'"]')).forEach((function(i){i.textContent=response.raterreputation})),root.querySelectorAll('[data-moodleoverflow-userreputation="'.concat(response.ownerid,'"]')).forEach((function(i){i.textContent=response.ownerreputation})),root.querySelectorAll('[data-moodleoverflow-postreputation="'.concat(postid,'"]')).forEach((function(i){i.textContent=response.postrating})),_context2.abrupt("return",response);case 7:case"end":return _context2.stop()}}),_callee2)})))).apply(this,arguments)}function changeStrings(_x5,_x6){return _changeStrings.apply(this,arguments)}function _changeStrings(){return(_changeStrings=_asyncToGenerator(regeneratorRuntime.mark((function _callee3(htmlclass,action){var othermarkedposts,_iterator2,_step2,_iterator3,_step3,_el;return regeneratorRuntime.wrap((function(_context3){for(;;)switch(_context3.prev=_context3.next){case 0:_prefetch.default.prefetchStrings("mod_moodleoverflow",["marksolved","alsomarksolved","markhelpful","alsomarkhelpful"]),othermarkedposts=!1,_iterator2=_createForOfIteratorHelper(root.querySelectorAll(".moodleoverflowpost")),_context3.prev=3,_iterator2.s();case 5:if((_step2=_iterator2.n()).done){_context3.next=12;break}if(!_step2.value.classList.contains(htmlclass)){_context3.next=10;break}return othermarkedposts=!0,_context3.abrupt("break",12);case 10:_context3.next=5;break;case 12:_context3.next=17;break;case 14:_context3.prev=14,_context3.t0=_context3.catch(3),_iterator2.e(_context3.t0);case 17:return _context3.prev=17,_iterator2.f(),_context3.finish(17);case 20:_iterator3=_createForOfIteratorHelper(root.querySelectorAll(".moodleoverflowpost")),_context3.prev=21,_iterator3.s();case 23:if((_step3=_iterator3.n()).done){_context3.next=37;break}if((_el=_step3.value).classList.contains(htmlclass)||!_el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]'))){_context3.next=35;break}if(!othermarkedposts){_context3.next=32;break}return _context3.next=29,(0,_str.get_string)("alsomark".concat(action),"mod_moodleoverflow");case 29:_el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=_context3.sent,_context3.next=35;break;case 32:return _context3.next=34,(0,_str.get_string)("mark".concat(action),"mod_moodleoverflow");case 34:_el.querySelector('[data-moodleoverflow-action="'.concat(action,'"]')).textContent=_context3.sent;case 35:_context3.next=23;break;case 37:_context3.next=42;break;case 39:_context3.prev=39,_context3.t1=_context3.catch(21),_iterator3.e(_context3.t1);case 42:return _context3.prev=42,_iterator3.f(),_context3.finish(42);case 45:case"end":return _context3.stop()}}),_callee3,null,[[3,14,17,20],[21,39,42,45]])})))).apply(this,arguments)}})); //# sourceMappingURL=rating.min.js.map \ No newline at end of file diff --git a/amd/build/rating.min.js.map b/amd/build/rating.min.js.map index e0ec5b562e..6ca7b5f0bc 100644 --- a/amd/build/rating.min.js.map +++ b/amd/build/rating.min.js.map @@ -1 +1 @@ -{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'markedhelpful' : 'markedsolution';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n Add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only used if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","async","actionElement","event","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","isHelpful","htmlclass","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","remove","textContent","changeStrings","el","querySelectorAll","add","document","getElementById","response","Ajax","call","methodname","args","ratingid","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":";;;;;;;oFAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,QAAUC,oBACLC,cAAgBC,MAAMC,OAAOC,QAAQ,oCACtCH,2BAICI,OAASJ,cAAcK,aAAa,8BACpCC,YAAcN,cAAcG,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,qCAEjCD,YACC,aACA,kBACKI,SAAsB,WAAXJ,UAC+C,YAA5DJ,cAAcK,aAAa,mCACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBjB,QACjFM,cAAcY,aAAa,4BAA6B,cACxDZ,cAAca,YAAc,mBAAU,UAAYT,OAAQ,0BACvD,OACGU,YAAcN,SAAW,WAAa,eACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBtB,QACnEM,cAAcY,aAAa,4BAA6B,iBAClDK,aAAeX,YAAYY,qDACGJ,mBACpCG,aAAaL,aAAa,4BAA6B,cACvDZ,cAAca,YAAc,mBAAU,iBAAmBT,OAAQ,sBACjEa,aAAaJ,YAAc,mBAAU,UAAYC,YAAa,iCAIjE,cACA,gBACKK,UAAuB,YAAXf,OACZgB,UAAYD,UAAY,gBAAkB,iBAC1CE,aAAef,YAAYgB,UAAUC,SAASH,WAC9CI,WAAaL,UAAYM,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,oBAC1Cf,SAASF,OAAQoB,OAAQjC,QAO1BC,mBASG0B,eACAf,YAAYgB,UAAUM,OAAOR,WAC7BpB,cAAc6B,kBAAoB,iCAAiBzB,QAAU,sBAC7D0B,cAAcV,UAAWhB,kBAVxB,MAAM2B,MAAMlC,KAAKmC,iBAAiB,uBAAyBZ,WAC5DW,GAAGT,UAAUM,OAAOR,WACpBW,GAAGb,qDAA8Cd,cAAYyB,kBACnD,iCAAiBzB,QAAU,sBAWxCiB,eACDf,YAAYgB,UAAUW,IAAIb,WAC1BpB,cAAc6B,kBAAoB,oCAAoBzB,QAAU,sBAC5DT,oBACAmC,cAAcV,UAAWhB,mGAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB5B,KAAOqC,SAASC,eAAe,sCAStB1B,SAASF,OAAQoB,OAAQjC,cAC9B0C,eAAiBC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFjC,OAAQA,OACRkC,SAAUd,WAEd,UACJ9B,KAAKmC,gEAAyDtC,cAAYgD,SAASC,IAC/EA,EAAEd,YAAcO,SAASQ,eAAzB,IAEJ/C,KAAKmC,gEAAyDI,SAASS,eAAaH,SAASC,IACzFA,EAAEd,YAAcO,SAASU,eAAzB,IAEJjD,KAAKmC,gEAAyDzB,cAAYmC,SAASC,IAC/EA,EAAEd,YAAcO,SAASW,UAAzB,IAEGX,wBAgGIN,cAAcV,UAAWhB,0BAC3BR,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,wBAGhDoD,kBAAmB,MAClB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,0BAC/BD,GAAGT,UAAUC,SAASH,WAAY,CAClC4B,kBAAmB,YAKtB,MAAMjB,MAAMlC,KAAKmC,iBAAiB,wBAC9BD,GAAGT,UAAUC,SAASH,YAAcW,GAAGb,qDAA8Cd,gBAElF2B,GAAGb,qDAA8Cd,cAAYyB,YAD7DmB,uBAEU,qCAAqB5C,QAAU,4BAG/B,iCAAiBA,QAAU"} \ No newline at end of file +{"version":3,"file":"rating.min.js","sources":["../src/rating.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements rating functionality\n *\n * @module mod_moodleoverflow/rating\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport {get_string as getString} from 'core/str';\n\nconst RATING_DOWNVOTE = 1;\nconst RATING_UPVOTE = 2;\nconst RATING_REMOVE_DOWNVOTE = 10;\nconst RATING_REMOVE_UPVOTE = 20;\nconst RATING_SOLVED = 3;\nconst RATING_HELPFUL = 4;\n\nconst root = document.getElementById('moodleoverflow-root');\n\n/**\n * Send a vote via AJAX, then updates post and user ratings.\n * @param {int} postid\n * @param {int} rating\n * @param {int} userid\n * @returns {Promise<*>}\n */\nasync function sendVote(postid, rating, userid) {\n const response = await Ajax.call([{\n methodname: 'mod_moodleoverflow_record_vote',\n args: {\n postid: postid,\n ratingid: rating\n }\n }])[0];\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${userid}\"]`).forEach((i) => {\n i.textContent = response.raterreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-userreputation=\"${response.ownerid}\"]`).forEach((i) => {\n i.textContent = response.ownerreputation;\n });\n root.querySelectorAll(`[data-moodleoverflow-postreputation=\"${postid}\"]`).forEach((i) => {\n i.textContent = response.postrating;\n });\n return response;\n}\n\n\n/**\n * Init function.\n *\n * @param {int} userid\n * @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.\n *\n */\nexport function init(userid, allowmultiplemarks) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',\n 'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);\n\n root.onclick = async(event) => {\n const actionElement = event.target.closest('[data-moodleoverflow-action]');\n if (!actionElement) {\n return;\n }\n\n const action = actionElement.getAttribute('data-moodleoverflow-action');\n const postElement = actionElement.closest('[data-moodleoverflow-postid]');\n const postid = postElement?.getAttribute('data-moodleoverflow-postid');\n\n switch (action) {\n case 'upvote':\n case 'downvote': {\n const isupvote = action === 'upvote';\n if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {\n await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');\n } else {\n const otherAction = isupvote ? 'downvote' : 'upvote';\n await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);\n actionElement.setAttribute('data-moodleoverflow-state', 'clicked');\n const otherElement = postElement.querySelector(\n `[data-moodleoverflow-action=\"${otherAction}\"]`);\n otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');\n actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');\n otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');\n }\n }\n break;\n case 'helpful':\n case 'solved': {\n const isHelpful = action === 'helpful';\n const htmlclass = isHelpful ? 'markedhelpful' : 'markedsolution';\n const shouldRemove = postElement.classList.contains(htmlclass);\n const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;\n const rating = shouldRemove ? baseRating * 10 : baseRating;\n await sendVote(postid, rating, userid);\n\n /* If multiplemarks are not allowed (that is the default mode): delete all marks.\n else: only delete the mark if the post is being unmarked.\n\n Add a mark, if the post is being marked.\n */\n if (!allowmultiplemarks) {\n // Delete all marks in the discussion\n for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {\n el.classList.remove(htmlclass);\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n } else {\n // Remove only the mark of the unmarked post.\n if (shouldRemove) {\n postElement.classList.remove(htmlclass);\n actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');\n changeStrings(htmlclass, action);\n }\n }\n // If the post is being marked, mark it.\n if (!shouldRemove) {\n postElement.classList.add(htmlclass);\n actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');\n if (allowmultiplemarks) {\n changeStrings(htmlclass, action);\n }\n }\n\n }\n }\n };\n\n}\n\n/**\n * Function to change the String of the post data-action button.\n * Only used if mulitplemarks are allowed.\n * @param {string} htmlclass the class where the String is being updated\n * @param {string} action helpful or solved mark\n */\nasync function changeStrings(htmlclass, action) {\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);\n\n // 1. Step: Are there other posts in the Discussion, that are solved/helpful?\n var othermarkedposts = false;\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (el.classList.contains(htmlclass)) {\n othermarkedposts = true;\n break;\n }\n }\n // 2. Step: Change the strings of the action Button of the unmarked posts.\n for (const el of root.querySelectorAll('.moodleoverflowpost')) {\n if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`)) {\n if (othermarkedposts) {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`alsomark${action}`, 'mod_moodleoverflow');\n } else {\n el.querySelector(`[data-moodleoverflow-action=\"${action}\"]`).textContent =\n await getString(`mark${action}`, 'mod_moodleoverflow');\n }\n }\n }\n}"],"names":["userid","allowmultiplemarks","prefetchStrings","root","onclick","event","actionElement","target","closest","action","getAttribute","postElement","postid","isupvote","sendVote","RATING_REMOVE_UPVOTE","RATING_REMOVE_DOWNVOTE","setAttribute","title","otherAction","RATING_UPVOTE","RATING_DOWNVOTE","otherElement","querySelector","htmlclass","isHelpful","shouldRemove","classList","contains","baseRating","RATING_HELPFUL","RATING_SOLVED","rating","querySelectorAll","el","remove","textContent","changeStrings","add","document","getElementById","Ajax","call","methodname","args","ratingid","response","forEach","i","raterreputation","ownerid","ownerreputation","postrating","othermarkedposts"],"mappings":"8kEAsEqBA,OAAQC,sCAChBC,gBAAgB,qBACrB,CAAC,aAAc,gBAAiB,cAAe,iBAC3C,uBAAwB,gBAAiB,yBAA0B,oBAE3EC,KAAKC,yDAAU,iBAAMC,mQACXC,cAAgBD,MAAME,OAAOC,QAAQ,+FAKrCC,OAASH,cAAcI,aAAa,8BACpCC,YAAcL,cAAcE,QAAQ,gCACpCI,OAASD,yBAAAA,YAAaD,aAAa,0CAEjCD,qBACC,wBACA,2BAkBA,yBACA,6CAlBKI,SAAsB,WAAXJ,OAC+C,YAA5DH,cAAcI,aAAa,6EACrBI,SAASF,OAAQC,SAAWE,qBAAuBC,uBAAwBhB,uBACjFM,cAAcW,aAAa,4BAA6B,gCAC5B,mBAAU,UAAYR,OAAQ,8BAA1DH,cAAcY,0DAERC,YAAcN,SAAW,WAAa,0BACtCC,SAASF,OAAQC,SAAWO,cAAgBC,gBAAiBrB,uBACnEM,cAAcW,aAAa,4BAA6B,YAClDK,aAAeX,YAAYY,qDACGJ,oBACvBF,aAAa,4BAA6B,gCAC3B,mBAAU,iBAAmBR,OAAQ,qCAAjEH,cAAcY,sCACa,mBAAU,UAAYC,YAAa,8BAA9DG,aAAaJ,8EAOXM,WADAC,UAAuB,YAAXhB,QACY,gBAAkB,iBAC1CiB,aAAef,YAAYgB,UAAUC,SAASJ,WAC9CK,WAAaJ,UAAYK,eAAiBC,cAC1CC,OAASN,aAA4B,GAAbG,WAAkBA,4BAC1Cf,SAASF,OAAQoB,OAAQhC,mBAO1BC,gFAEgBE,KAAK8B,iBAAiB,uBAAyBT,gHAArDU,gBACJP,UAAUQ,OAAOX,6BAEV,iCAAiBf,QAAU,8BADrCyB,GAAGX,qDAA8Cd,cAAY2B,sRAK7DV,4CACAf,YAAYgB,UAAUQ,OAAOX,6BACK,iCAAiBf,QAAU,8BAA7DH,cAAc8B,0BACdC,cAAcb,UAAWf,mBAI5BiB,4CACDf,YAAYgB,UAAUW,IAAId,6BACQ,oCAAoBf,QAAU,8BAAhEH,cAAc8B,0BACVnC,oBACAoC,cAAcb,UAAWf,sOAjH3CY,gBAAkB,EAClBD,cAAgB,EAChBJ,uBAAyB,GACzBD,qBAAuB,GACvBgB,cAAgB,EAChBD,eAAiB,EAEjB3B,KAAOoC,SAASC,eAAe,gCAStB1B,6IAAf,kBAAwBF,OAAQoB,OAAQhC,qJACbyC,cAAKC,KAAK,CAAC,CAC9BC,WAAY,iCACZC,KAAM,CACFhC,OAAQA,OACRiC,SAAUb,WAEd,iBANEc,wBAON3C,KAAK8B,gEAAyDjC,cAAY+C,SAAQ,SAACC,GAC/EA,EAAEZ,YAAcU,SAASG,mBAE7B9C,KAAK8B,gEAAyDa,SAASI,eAAaH,SAAQ,SAACC,GACzFA,EAAEZ,YAAcU,SAASK,mBAE7BhD,KAAK8B,gEAAyDrB,cAAYmC,SAAQ,SAACC,GAC/EA,EAAEZ,YAAcU,SAASM,wCAEtBN,oGAgGIT,8JAAf,kBAA6Bb,UAAWf,+LAC3BP,gBAAgB,qBACrB,CAAC,aAAc,iBAAkB,cAAe,oBAGhDmD,kBAAmB,wCACNlD,KAAK8B,iBAAiB,yIAC5BN,UAAUC,SAASJ,2CACtB6B,kBAAmB,sSAKVlD,KAAK8B,iBAAiB,8HAA5BC,kBACCP,UAAUC,SAASJ,aAAcU,IAAGX,qDAA8Cd,2CAClF4C,oEAEU,qCAAqB5C,QAAU,8BADzCyB,IAAGX,qDAA8Cd,cAAY2B,qFAInD,iCAAiB3B,QAAU,8BADrCyB,IAAGX,qDAA8Cd,cAAY2B"} \ No newline at end of file diff --git a/amd/build/reviewing.min.js b/amd/build/reviewing.min.js index 7dc1ac1e4f..c811cbbdfd 100644 --- a/amd/build/reviewing.min.js +++ b/amd/build/reviewing.min.js @@ -1,10 +1,3 @@ -define("mod_moodleoverflow/reviewing",["exports","core/ajax","core/prefetch","core/templates","core/str"],(function(_exports,_ajax,_prefetch,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} -/** - * Implements reviewing functionality - * - * @module mod_moodleoverflow/reviewing - * @copyright 2022 Justus Dieckmann WWU - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){_prefetch.default.prefetchTemplates(["mod_moodleoverflow/reject_post_form","mod_moodleoverflow/review_buttons"]),_prefetch.default.prefetchStrings("mod_moodleoverflow",["post_was_approved","jump_to_next_post_needing_review","there_are_no_posts_needing_review","post_was_rejected"]);document.getElementById("moodleoverflow-posts").onclick=async e=>{const action=e.target.getAttribute("data-moodleoverflow-action");if(!action)return;const post=e.target.closest("*[data-moodleoverflow-postid]"),reviewRow=e.target.closest(".reviewrow"),postID=post.getAttribute("data-moodleoverflow-postid");if("approve"===action){reviewRow.innerHTML=".";const nextPostURL=await _ajax.default.call([{methodname:"mod_moodleoverflow_review_approve_post",args:{postid:postID}}])[0];let message=await(0,_str.get_string)("post_was_approved","mod_moodleoverflow")+" ";message+=nextPostURL?'<a href="'.concat(nextPostURL,'">')+await(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow")+"</a>":await(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow"),reviewRow.innerHTML=message,post.classList.remove("pendingreview")}else if("reject"===action)reviewRow.innerHTML=".",reviewRow.innerHTML=await _templates.default.render("mod_moodleoverflow/reject_post_form",{});else if("reject-submit"===action){const rejectMessage=post.querySelector("textarea.reject-reason").value.toString().trim();reviewRow.innerHTML=".";const args={postid:postID,reason:rejectMessage||null},nextPostURL=await _ajax.default.call([{methodname:"mod_moodleoverflow_review_reject_post",args:args}])[0];let message=await(0,_str.get_string)("post_was_rejected","mod_moodleoverflow")+" ";message+=nextPostURL?'<a href="'.concat(nextPostURL,'">')+await(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow")+"</a>":await(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow"),reviewRow.innerHTML=message}else"reject-cancel"===action&&(reviewRow.innerHTML=".",reviewRow.innerHTML=await _templates.default.render("mod_moodleoverflow/review_buttons",{}))}},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch),_templates=_interopRequireDefault(_templates)})); +define("mod_moodleoverflow/reviewing",["exports","core/ajax","core/prefetch","core/templates","core/str"],(function(_exports,_ajax,_prefetch,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg),value=info.value}catch(error){return void reject(error)}info.done?resolve(value):Promise.resolve(value).then(_next,_throw)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(){_prefetch.default.prefetchTemplates(["mod_moodleoverflow/reject_post_form","mod_moodleoverflow/review_buttons"]),_prefetch.default.prefetchStrings("mod_moodleoverflow",["post_was_approved","jump_to_next_post_needing_review","there_are_no_posts_needing_review","post_was_rejected"]),document.getElementById("moodleoverflow-posts").onclick=(fn=regeneratorRuntime.mark((function _callee(e){var action,post,reviewRow,postID,nextPostURL,message,rejectMessage,args,_nextPostURL,_message;return regeneratorRuntime.wrap((function(_context){for(;;)switch(_context.prev=_context.next){case 0:if(action=e.target.getAttribute("data-moodleoverflow-action")){_context.next=3;break}return _context.abrupt("return");case 3:if(post=e.target.closest("*[data-moodleoverflow-postid]"),reviewRow=e.target.closest(".reviewrow"),postID=post.getAttribute("data-moodleoverflow-postid"),"approve"!==action){_context.next=33;break}return reviewRow.innerHTML=".",_context.next=10,_ajax.default.call([{methodname:"mod_moodleoverflow_review_approve_post",args:{postid:postID}}])[0];case 10:return nextPostURL=_context.sent,_context.next=13,(0,_str.get_string)("post_was_approved","mod_moodleoverflow");case 13:if(_context.t0=_context.sent,message=_context.t0+" ",!nextPostURL){_context.next=25;break}return _context.t1=message,_context.t2='<a href="'.concat(nextPostURL,'">'),_context.next=20,(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow");case 20:_context.t3=_context.sent,_context.t4=_context.t2+_context.t3,message=_context.t1+=_context.t4+"</a>",_context.next=29;break;case 25:return _context.t5=message,_context.next=28,(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow");case 28:message=_context.t5+=_context.sent;case 29:reviewRow.innerHTML=message,post.classList.remove("pendingreview"),_context.next=73;break;case 33:if("reject"!==action){_context.next=40;break}return reviewRow.innerHTML=".",_context.next=37,_templates.default.render("mod_moodleoverflow/reject_post_form",{});case 37:reviewRow.innerHTML=_context.sent,_context.next=73;break;case 40:if("reject-submit"!==action){_context.next=68;break}return rejectMessage=post.querySelector("textarea.reject-reason").value.toString().trim(),reviewRow.innerHTML=".",args={postid:postID,reason:rejectMessage||null},_context.next=46,_ajax.default.call([{methodname:"mod_moodleoverflow_review_reject_post",args:args}])[0];case 46:return _nextPostURL=_context.sent,_context.next=49,(0,_str.get_string)("post_was_rejected","mod_moodleoverflow");case 49:if(_context.t6=_context.sent,_message=_context.t6+" ",!_nextPostURL){_context.next=61;break}return _context.t7=_message,_context.t8='<a href="'.concat(_nextPostURL,'">'),_context.next=56,(0,_str.get_string)("jump_to_next_post_needing_review","mod_moodleoverflow");case 56:_context.t9=_context.sent,_context.t10=_context.t8+_context.t9,_message=_context.t7+=_context.t10+"</a>",_context.next=65;break;case 61:return _context.t11=_message,_context.next=64,(0,_str.get_string)("there_are_no_posts_needing_review","mod_moodleoverflow");case 64:_message=_context.t11+=_context.sent;case 65:reviewRow.innerHTML=_message,_context.next=73;break;case 68:if("reject-cancel"!==action){_context.next=73;break}return reviewRow.innerHTML=".",_context.next=72,_templates.default.render("mod_moodleoverflow/review_buttons",{});case 72:reviewRow.innerHTML=_context.sent;case 73:case"end":return _context.stop()}}),_callee)})),_ref=function(){var self=this,args=arguments;return new Promise((function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(void 0)}))},function(_x){return _ref.apply(this,arguments)});var fn,_ref},_ajax=_interopRequireDefault(_ajax),_prefetch=_interopRequireDefault(_prefetch),_templates=_interopRequireDefault(_templates)})); //# sourceMappingURL=reviewing.min.js.map \ No newline at end of file diff --git a/amd/build/reviewing.min.js.map b/amd/build/reviewing.min.js.map index 13a68e7925..d2b01e0044 100644 --- a/amd/build/reviewing.min.js.map +++ b/amd/build/reviewing.min.js.map @@ -1 +1 @@ -{"version":3,"file":"reviewing.min.js","sources":["../src/reviewing.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements reviewing functionality\n *\n * @module mod_moodleoverflow/reviewing\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Init function.\n */\nexport function init() {\n Prefetch.prefetchTemplates(['mod_moodleoverflow/reject_post_form', 'mod_moodleoverflow/review_buttons']);\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['post_was_approved', 'jump_to_next_post_needing_review', 'there_are_no_posts_needing_review', 'post_was_rejected']);\n\n const root = document.getElementById('moodleoverflow-posts');\n root.onclick = async(e) => {\n const action = e.target.getAttribute('data-moodleoverflow-action');\n\n if (!action) {\n return;\n }\n\n const post = e.target.closest('*[data-moodleoverflow-postid]');\n const reviewRow = e.target.closest('.reviewrow');\n const postID = post.getAttribute('data-moodleoverflow-postid');\n\n if (action === 'approve') {\n reviewRow.innerHTML = '.';\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_approve_post',\n args: {\n postid: postID,\n }\n }])[0];\n\n let message = await getString('post_was_approved', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n post.classList.remove(\"pendingreview\");\n } else if (action === 'reject') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/reject_post_form', {});\n } else if (action === 'reject-submit') {\n const rejectMessage = post.querySelector('textarea.reject-reason').value.toString().trim();\n reviewRow.innerHTML = '.';\n const args = {\n postid: postID,\n reason: rejectMessage ? rejectMessage : null\n };\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_reject_post',\n args: args\n }])[0];\n\n let message = await getString('post_was_rejected', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n } else if (action === 'reject-cancel') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/review_buttons', {});\n }\n };\n}"],"names":["prefetchTemplates","prefetchStrings","document","getElementById","onclick","async","action","e","target","getAttribute","post","closest","reviewRow","postID","innerHTML","nextPostURL","Ajax","call","methodname","args","postid","message","classList","remove","Templates","render","rejectMessage","querySelector","value","toString","trim","reason"],"mappings":";;;;;;;wGA+BaA,kBAAkB,CAAC,sCAAuC,wDAC1DC,gBAAgB,qBACrB,CAAC,oBAAqB,mCAAoC,oCAAqC,sBAEtFC,SAASC,eAAe,wBAChCC,QAAUC,gBACLC,OAASC,EAAEC,OAAOC,aAAa,kCAEhCH,oBAICI,KAAOH,EAAEC,OAAOG,QAAQ,iCACxBC,UAAYL,EAAEC,OAAOG,QAAQ,cAC7BE,OAASH,KAAKD,aAAa,iCAElB,YAAXH,OAAsB,CACtBM,UAAUE,UAAY,UAChBC,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,yCACZC,KAAM,CACFC,OAAQP,WAEZ,OAEAQ,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,QACtBX,KAAKY,UAAUC,OAAO,sBACnB,GAAe,WAAXjB,OACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,sCAAuC,SACjF,GAAe,kBAAXnB,OAA4B,OAC7BoB,cAAgBhB,KAAKiB,cAAc,0BAA0BC,MAAMC,WAAWC,OACpFlB,UAAUE,UAAY,UAChBK,KAAO,CACTC,OAAQP,OACRkB,OAAQL,eAAgC,MAEtCX,kBAAoBC,cAAKC,KAAK,CAAC,CACjCC,WAAY,wCACZC,KAAMA,QACN,OAEAE,cAAgB,mBAAU,oBAAqB,sBAAwB,IAEvEA,SADAN,YACW,mBAAYA,wBACX,mBAAU,mCAAoC,sBACpD,aAEW,mBAAU,oCAAqC,sBAEpEH,UAAUE,UAAYO,YACJ,kBAAXf,SACPM,UAAUE,UAAY,IACtBF,UAAUE,gBAAkBU,mBAAUC,OAAO,oCAAqC"} \ No newline at end of file +{"version":3,"file":"reviewing.min.js","sources":["../src/reviewing.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Implements reviewing functionality\n *\n * @module mod_moodleoverflow/reviewing\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Ajax from 'core/ajax';\nimport Prefetch from 'core/prefetch';\nimport Templates from 'core/templates';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Init function.\n */\nexport function init() {\n Prefetch.prefetchTemplates(['mod_moodleoverflow/reject_post_form', 'mod_moodleoverflow/review_buttons']);\n Prefetch.prefetchStrings('mod_moodleoverflow',\n ['post_was_approved', 'jump_to_next_post_needing_review', 'there_are_no_posts_needing_review', 'post_was_rejected']);\n\n const root = document.getElementById('moodleoverflow-posts');\n root.onclick = async(e) => {\n const action = e.target.getAttribute('data-moodleoverflow-action');\n\n if (!action) {\n return;\n }\n\n const post = e.target.closest('*[data-moodleoverflow-postid]');\n const reviewRow = e.target.closest('.reviewrow');\n const postID = post.getAttribute('data-moodleoverflow-postid');\n\n if (action === 'approve') {\n reviewRow.innerHTML = '.';\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_approve_post',\n args: {\n postid: postID,\n }\n }])[0];\n\n let message = await getString('post_was_approved', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n post.classList.remove(\"pendingreview\");\n } else if (action === 'reject') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/reject_post_form', {});\n } else if (action === 'reject-submit') {\n const rejectMessage = post.querySelector('textarea.reject-reason').value.toString().trim();\n reviewRow.innerHTML = '.';\n const args = {\n postid: postID,\n reason: rejectMessage ? rejectMessage : null\n };\n const nextPostURL = await Ajax.call([{\n methodname: 'mod_moodleoverflow_review_reject_post',\n args: args\n }])[0];\n\n let message = await getString('post_was_rejected', 'mod_moodleoverflow') + ' ';\n if (nextPostURL) {\n message += `<a href=\"${nextPostURL}\">`\n + await getString('jump_to_next_post_needing_review', 'mod_moodleoverflow')\n + \"</a>\";\n } else {\n message += await getString('there_are_no_posts_needing_review', 'mod_moodleoverflow');\n }\n reviewRow.innerHTML = message;\n } else if (action === 'reject-cancel') {\n reviewRow.innerHTML = '.';\n reviewRow.innerHTML = await Templates.render('mod_moodleoverflow/review_buttons', {});\n }\n };\n}"],"names":["prefetchTemplates","prefetchStrings","document","getElementById","onclick","e","action","target","getAttribute","post","closest","reviewRow","postID","innerHTML","Ajax","call","methodname","args","postid","nextPostURL","message","classList","remove","Templates","render","rejectMessage","querySelector","value","toString","trim","reason"],"mappings":"8iBA+BaA,kBAAkB,CAAC,sCAAuC,wDAC1DC,gBAAgB,qBACrB,CAAC,oBAAqB,mCAAoC,oCAAqC,sBAEtFC,SAASC,eAAe,wBAChCC,qCAAU,iBAAMC,yMACXC,OAASD,EAAEE,OAAOC,aAAa,gGAM/BC,KAAOJ,EAAEE,OAAOG,QAAQ,iCACxBC,UAAYN,EAAEE,OAAOG,QAAQ,cAC7BE,OAASH,KAAKD,aAAa,8BAElB,YAAXF,sCACAK,UAAUE,UAAY,qBACIC,cAAKC,KAAK,CAAC,CACjCC,WAAY,yCACZC,KAAM,CACFC,OAAQN,WAEZ,kBALEO,4CAOc,mBAAU,oBAAqB,2DAA/CC,oBAAuE,KACvED,uDACAC,uCAAuBD,oCACX,mBAAU,mCAAoC,4FAD1DC,iCAEM,yDAENA,0BAAiB,mBAAU,oCAAqC,8BAAhEA,2CAEJT,UAAUE,UAAYO,QACtBX,KAAKY,UAAUC,OAAO,mDACJ,WAAXhB,sCACPK,UAAUE,UAAY,qBACMU,mBAAUC,OAAO,sCAAuC,YAApFb,UAAUE,0DACQ,kBAAXP,sCACDmB,cAAgBhB,KAAKiB,cAAc,0BAA0BC,MAAMC,WAAWC,OACpFlB,UAAUE,UAAY,IAChBI,KAAO,CACTC,OAAQN,OACRkB,OAAQL,eAAgC,uBAElBX,cAAKC,KAAK,CAAC,CACjCC,WAAY,wCACZC,KAAMA,QACN,kBAHEE,6CAKc,mBAAU,oBAAqB,2DAA/CC,qBAAuE,KACvED,wDACAC,wCAAuBD,qCACX,mBAAU,mCAAoC,6FAD1DC,mCAEM,0DAENA,2BAAiB,mBAAU,oCAAqC,8BAAhEA,6CAEJT,UAAUE,UAAYO,2CACJ,kBAAXd,sCACPK,UAAUE,UAAY,qBACMU,mBAAUC,OAAO,oCAAqC,YAAlFb,UAAUE"} \ No newline at end of file diff --git a/amd/build/warnmodechange.min.js b/amd/build/warnmodechange.min.js index 5042ba704b..370da13a32 100644 --- a/amd/build/warnmodechange.min.js +++ b/amd/build/warnmodechange.min.js @@ -1,10 +1,3 @@ -define("mod_moodleoverflow/warnmodechange",["exports","core/str","core/notification","core/prefetch"],(function(_exports,_str,_notification,_prefetch){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} -/** - * Warns on changing the subscription mode. - * - * @module mod_moodleoverflow/warnmodechange - * @copyright 2022 Justus Dieckmann WWU - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(previousSetting){_prefetch.default.prefetchStrings("mod_moodleoverflow",["switchtooptional","switchtoauto"]),_prefetch.default.prefetchStrings("moodle",["confirm","cancel"]);const form=document.querySelector("form.mform"),select=document.getElementById("id_forcesubscribe");form.onsubmit=async e=>{const value=select.selectedOptions[0].value;value!=previousSetting&&1!=value&&3!=value&&(e.preventDefault(),await _notification.default.confirm(await(0,_str.get_string)("confirm"),await(0,_str.get_string)(0==value?"switchtooptional":"switchtoauto","mod_moodleoverflow"),await(0,_str.get_string)("confirm"),await(0,_str.get_string)("cancel"),(()=>{form.onsubmit=void 0,form.requestSubmit(e.submitter)}),void 0))}},_notification=_interopRequireDefault(_notification),_prefetch=_interopRequireDefault(_prefetch)})); +define("mod_moodleoverflow/warnmodechange",["exports","core/str","core/notification","core/prefetch"],(function(_exports,_str,_notification,_prefetch){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg),value=info.value}catch(error){return void reject(error)}info.done?resolve(value):Promise.resolve(value).then(_next,_throw)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=function(previousSetting){_prefetch.default.prefetchStrings("mod_moodleoverflow",["switchtooptional","switchtoauto"]),_prefetch.default.prefetchStrings("moodle",["confirm","cancel"]);var form=document.querySelector("form.mform"),select=document.getElementById("id_forcesubscribe");form.onsubmit=(fn=regeneratorRuntime.mark((function _callee(e){var value;return regeneratorRuntime.wrap((function(_context){for(;;)switch(_context.prev=_context.next){case 0:if((value=select.selectedOptions[0].value)!=previousSetting&&1!=value&&3!=value){_context.next=3;break}return _context.abrupt("return");case 3:return e.preventDefault(),_context.t0=_notification.default,_context.next=7,(0,_str.get_string)("confirm");case 7:return _context.t1=_context.sent,_context.next=10,(0,_str.get_string)(0==value?"switchtooptional":"switchtoauto","mod_moodleoverflow");case 10:return _context.t2=_context.sent,_context.next=13,(0,_str.get_string)("confirm");case 13:return _context.t3=_context.sent,_context.next=16,(0,_str.get_string)("cancel");case 16:return _context.t4=_context.sent,_context.t5=function(){form.onsubmit=void 0,form.requestSubmit(e.submitter)},_context.t6=void 0,_context.next=21,_context.t0.confirm.call(_context.t0,_context.t1,_context.t2,_context.t3,_context.t4,_context.t5,_context.t6);case 21:case"end":return _context.stop()}}),_callee)})),_ref=function(){var self=this,args=arguments;return new Promise((function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(void 0)}))},function(_x){return _ref.apply(this,arguments)});var fn,_ref},_notification=_interopRequireDefault(_notification),_prefetch=_interopRequireDefault(_prefetch)})); //# sourceMappingURL=warnmodechange.min.js.map \ No newline at end of file diff --git a/amd/build/warnmodechange.min.js.map b/amd/build/warnmodechange.min.js.map index b4120395cd..f3c76304c1 100644 --- a/amd/build/warnmodechange.min.js.map +++ b/amd/build/warnmodechange.min.js.map @@ -1 +1 @@ -{"version":3,"file":"warnmodechange.min.js","sources":["../src/warnmodechange.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Warns on changing the subscription mode.\n *\n * @module mod_moodleoverflow/warnmodechange\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Prefetch from 'core/prefetch';\n\n/**\n * Init function.\n * @param {string} previousSetting\n */\nexport function init(previousSetting) {\n Prefetch.prefetchStrings('mod_moodleoverflow', ['switchtooptional', 'switchtoauto']);\n Prefetch.prefetchStrings('moodle', ['confirm', 'cancel']);\n const form = document.querySelector('form.mform');\n const select = document.getElementById('id_forcesubscribe');\n form.onsubmit = async(e) => {\n const value = select.selectedOptions[0].value;\n if (value == previousSetting || value == 1 || value == 3) {\n return;\n }\n e.preventDefault();\n await Notification.confirm(\n await getString('confirm'),\n await getString(value == 0 ? 'switchtooptional' : 'switchtoauto', 'mod_moodleoverflow'),\n await getString('confirm'),\n await getString('cancel'),\n () => {\n // Prevent this listener from preventing the event again.\n form.onsubmit = undefined;\n form.requestSubmit(e.submitter);\n }, undefined);\n };\n}"],"names":["previousSetting","prefetchStrings","form","document","querySelector","select","getElementById","onsubmit","async","value","selectedOptions","e","preventDefault","Notification","confirm","undefined","requestSubmit","submitter"],"mappings":";;;;;;;oFA8BqBA,mCACRC,gBAAgB,qBAAsB,CAAC,mBAAoB,mCAC3DA,gBAAgB,SAAU,CAAC,UAAW,iBACzCC,KAAOC,SAASC,cAAc,cAC9BC,OAASF,SAASG,eAAe,qBACvCJ,KAAKK,SAAWC,gBACNC,MAAQJ,OAAOK,gBAAgB,GAAGD,MACpCA,OAAST,iBAA4B,GAATS,OAAuB,GAATA,QAG9CE,EAAEC,uBACIC,sBAAaC,cACT,mBAAU,iBACV,mBAAmB,GAATL,MAAa,mBAAqB,eAAgB,4BAC5D,mBAAU,iBACV,mBAAU,WAChB,KAEIP,KAAKK,cAAWQ,EAChBb,KAAKc,cAAcL,EAAEM,kBACtBF,GATP"} \ No newline at end of file +{"version":3,"file":"warnmodechange.min.js","sources":["../src/warnmodechange.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Warns on changing the subscription mode.\n *\n * @module mod_moodleoverflow/warnmodechange\n * @copyright 2022 Justus Dieckmann WWU\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Prefetch from 'core/prefetch';\n\n/**\n * Init function.\n * @param {string} previousSetting\n */\nexport function init(previousSetting) {\n Prefetch.prefetchStrings('mod_moodleoverflow', ['switchtooptional', 'switchtoauto']);\n Prefetch.prefetchStrings('moodle', ['confirm', 'cancel']);\n const form = document.querySelector('form.mform');\n const select = document.getElementById('id_forcesubscribe');\n form.onsubmit = async(e) => {\n const value = select.selectedOptions[0].value;\n if (value == previousSetting || value == 1 || value == 3) {\n return;\n }\n e.preventDefault();\n await Notification.confirm(\n await getString('confirm'),\n await getString(value == 0 ? 'switchtooptional' : 'switchtoauto', 'mod_moodleoverflow'),\n await getString('confirm'),\n await getString('cancel'),\n () => {\n // Prevent this listener from preventing the event again.\n form.onsubmit = undefined;\n form.requestSubmit(e.submitter);\n }, undefined);\n };\n}"],"names":["previousSetting","prefetchStrings","form","document","querySelector","select","getElementById","onsubmit","e","value","selectedOptions","preventDefault","Notification","undefined","requestSubmit","submitter","confirm"],"mappings":"mhBA8BqBA,mCACRC,gBAAgB,qBAAsB,CAAC,mBAAoB,mCAC3DA,gBAAgB,SAAU,CAAC,UAAW,eACzCC,KAAOC,SAASC,cAAc,cAC9BC,OAASF,SAASG,eAAe,qBACvCJ,KAAKK,sCAAW,iBAAMC,sHACZC,MAAQJ,OAAOK,gBAAgB,GAAGD,QAC3BT,iBAA4B,GAATS,OAAuB,GAATA,4EAG9CD,EAAEG,6BACIC,uCACI,mBAAU,qEACV,mBAAmB,GAATH,MAAa,mBAAqB,eAAgB,iFAC5D,mBAAU,sEACV,mBAAU,+DAChB,WAEIP,KAAKK,cAAWM,EAChBX,KAAKY,cAAcN,EAAEO,6BACtBF,+BATYG"} \ No newline at end of file diff --git a/classes/ratings.php b/classes/ratings.php index fbf7be5052..0c8127394e 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -259,7 +259,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { $startother = 1; // Solved and helpful posts are first. foreach ($answerposts as $post) { - if ($post->markedsolution == 1 && $post->markedhelpful == 1) { + if ($post->markedsolution > 0 && $post->markedhelpful > 0) { $sortedposts[$index] = $post; $index++; } @@ -277,7 +277,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only solved posts. foreach ($answerposts as $post) { - if ($post->markedsolution == 1 && $post->markedhelpful == 0) { + if ($post->markedsolution > 0 && $post->markedhelpful == 0) { $sortedposts[$index] = $post; $index++; } @@ -291,7 +291,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only helpful posts. foreach ($answerposts as $post) { - if ($post->markedsolution == 0 && $post->markedhelpful == 1) { + if ($post->markedsolution == 0 && $post->markedhelpful > 0) { $sortedposts[$index] = $post; $index++; } @@ -305,7 +305,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only helpful posts. foreach ($answerposts as $post) { - if ($post->markedsolution == 0 && $post->markedhelpful == 1) { + if ($post->markedsolution == 0 && $post->markedhelpful > 0) { $sortedposts[$index] = $post; $index++; } @@ -319,7 +319,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Build the group of only solved posts. foreach ($answerposts as $post) { - if ($post->markedsolution == 1 && $post->markedhelpful == 0) { + if ($post->markedsolution > 0 && $post->markedhelpful == 0) { $sortedposts[$index] = $post; $index++; } diff --git a/tests/ratings_test.php b/tests/ratings_test.php index 232e34afc3..c9fdd787e1 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -105,15 +105,69 @@ public function tearDown(): void { /** * Test, if rating can sort after ever group with ratingpreferences on helpful first. */ - public function test_everygrouphelpfulon() { - // Create helpful and solved and up and downvotes ratings. + public function test_sort_answer_by_ratings() { + // Create helpful, solved, up and downvotes ratings. $this->create_everygroup(); - $this->set_ratingpreferences(1); - // Create a array of the posts and sort them. + + // Test with every group if rating + + // Create a array of the posts, save the sorted post and compare them to the order that they should have. $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $this->set_ratingpreferences(0); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer1, $this->answer3, $this->answer2, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Change the rating preference of the teacher and sort again. + $this->set_ratingpreferences(1); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + + // Test without posts that are only marked as solved + $posts = array($this->post, $this->answer1, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $this->set_ratingpreferences(0); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer1, $this->answer3, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + $this->set_ratingpreferences(1); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer1, $this->answer3, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test without posts that are only marked as helpful + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer4, $this->answer5, $this->answer6); + $this->set_ratingpreferences(0); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer1, $this->answer2, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + $this->set_ratingpreferences(1); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer1, $this->answer2, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test without posts that are marked as both helpful and marked + $posts = array($this->post, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $this->set_ratingpreferences(0); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer3, $this->answer2, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + $this->set_ratingpreferences(1); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - var_dump($sortedposts); - $this->assertEquals(1,1); + $rightorderposts = array($this->post, $this->answer2, $this->answer3, $this->answer4, $this->answer6, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); } // Helper functions @@ -154,6 +208,52 @@ private function helper_course_set_up() { $this->answer6 = $this->generator->reply_to_post($this->discussion[1], $this->user2, true); } + + /** + * This function compares 2 arrays with posts and checks if the order is the same. + * + * @param array $sortedposts - The sorted posts + * @param array $rightorderposts - The posts with the order they should have + * The function returns 1 if $sortedposts matches $posts, else 0 + */ + private function postsorderequal($sortedposts, $rightorderposts) { + if (count($sortedposts) != count($rightorderposts)) { + return 0; + } + for ($i = 0; $i < count($sortedposts); $i++) { + // Get the current elements. + $sortedpost = current($sortedposts); + $post = current($rightorderposts); + if ($sortedpost->id == $post->id) { + // Go to the next elements + next($sortedposts); + next($rightorderposts); + } else { + return 0; + } + } + return 1; + } + + /** + * sets the ratingpreferences to 1 or 0: + * 1 = solved posts will be shown above helpful posts. + * 0 = helpful posts will be shown above solved posts. + */ + private function set_ratingpreferences($preference) { + if ($preference == 0 || $preference == 1) { + $this->post->ratingpreference = $preference; + $this->answer1->ratingpreference = $preference; + $this->answer2->ratingpreference = $preference; + $this->answer3->ratingpreference = $preference; + $this->answer4->ratingpreference = $preference; + $this->answer5->ratingpreference = $preference; + $this->answer6->ratingpreference = $preference; + } + } + + // Creation functions, that create different rating situations of the posts in a discussion. + /** * creates a rating of every type by adding attributes to the post: * - post that is solved and helpful @@ -166,59 +266,45 @@ private function create_everygroup() { $this->answer1->upvotes = 0; $this->answer1->downvotes = 0; $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; - $this->answer1->statusstarter = 1; - $this->answer1->statusteacher = 1; + $this->answer1->markedhelpful = 1; + $this->answer1->markedsolution = 1; // Answer2. $this->answer2->upvotes = 0; $this->answer2->downvotes = 0; $this->answer2->votesdifference = $this->answer2->upvotes - $this->answer2->downvotes; - $this->answer2->statusstarter = 0; - $this->answer2->statusteacher = 1; + $this->answer2->markedhelpful = 0; + $this->answer2->markedsolution = 1; // Answer3. $this->answer3->upvotes = 0; $this->answer3->downvotes = 0; $this->answer3->votesdifference = $this->answer3->upvotes - $this->answer3->downvotes; - $this->answer3->statusstarter = 1; - $this->answer3->statusteacher = 0; + $this->answer3->markedhelpful = 1; + $this->answer3->markedsolution = 0; // Answer4. $this->answer4->upvotes = 1; $this->answer4->downvotes = 0; $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; - $this->answer4->statusstarter = 0; - $this->answer4->statusteacher = 0; + $this->answer4->markedhelpful = 0; + $this->answer4->markedsolution = 0; // Answer5. $this->answer5->upvotes = 0; $this->answer5->downvotes = 1; $this->answer5->votesdifference = $this->answer5->upvotes - $this->answer5->downvotes; - $this->answer5->statusstarter = 0; - $this->answer5->statusteacher = 0; + $this->answer5->markedhelpful = 0; + $this->answer5->markedsolution = 0; // Answer6. $this->answer6->upvotes = 0; $this->answer6->downvotes = 0; $this->answer6->votesdifference = $this->answer6->upvotes - $this->answer6->downvotes; - $this->answer6->statusstarter = 0; - $this->answer6->statusteacher = 0; + $this->answer6->markedhelpful = 0; + $this->answer6->markedsolution = 0; } - /** - * sets the ratingpreferences to 1 or 0: - * 1 = solved posts will be shown above helpful posts. - * 0 = helpful posts will be shown above solved posts. - */ - private function set_ratingpreferences($preference) { - if ($preference == 0 || $preference == 1) { - $this->post->ratingpreference = $preference; - $this->answer1->ratingpreference = $preference; - $this->answer2->ratingpreference = $preference; - $this->answer3->ratingpreference = $preference; - $this->answer4->ratingpreference = $preference; - $this->answer5->ratingpreference = $preference; - $this->answer6->ratingpreference = $preference; - } - } + //private function create_groupswithoutsolution + } From bf935755c51335582f4480faa95ed2d0673a6ddc Mon Sep 17 00:00:00 2001 From: NinaHerrmann <nina.herrmann@uni-muenster.de> Date: Tue, 16 May 2023 17:52:02 +0200 Subject: [PATCH 29/35] coding style --- classes/ratings.php | 8 ++++---- tests/ratings_test.php | 17 ++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 0c8127394e..99fb8f2366 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -229,14 +229,14 @@ public static function moodleoverflow_get_reputation($moodleoverflowid, $userid /** * Sort the answers of a discussion by their marks and votes. - * + * * @param object $posts all the posts from a discussion. */ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Create a copy that only has the answer posts and save the parent post. $answerposts = $posts; $parentpost = array_shift($answerposts); - + // Create an empty array for the sorted posts and add the parent post. $sortedposts = array(); $sortedposts[0] = $parentpost; @@ -264,7 +264,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { $index++; } } - //Update the indices and sort the group by votes. + // Update the indices and sort the group by votes. if ($index > $startsolvedandhelpful) { $startsolved = $index; $starthelpful = $index; @@ -349,7 +349,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { foreach ($sortedposts as $post) { $neworder[$post->id] = $post; } - + // return now the sorted posts. return $neworder; } diff --git a/tests/ratings_test.php b/tests/ratings_test.php index c9fdd787e1..8c8250f25e 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -37,7 +37,7 @@ * @copyright 2023 Tamaro Walter * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class ratings_test extends \advanced_testcase { +class ratings_test extends \advanced_testcase { /** @var \stdClass test course */ private $course; @@ -101,7 +101,7 @@ public function tearDown(): void { } // Begin of test functions - + /** * Test, if rating can sort after ever group with ratingpreferences on helpful first. */ @@ -126,7 +126,6 @@ public function test_sort_answer_by_ratings() { $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); - // Test without posts that are only marked as solved $posts = array($this->post, $this->answer1, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $this->set_ratingpreferences(0); @@ -171,7 +170,7 @@ public function test_sort_answer_by_ratings() { } // Helper functions - + /** * This function creates: * - a course with a moodleoverflow @@ -211,7 +210,7 @@ private function helper_course_set_up() { /** * This function compares 2 arrays with posts and checks if the order is the same. - * + * * @param array $sortedposts - The sorted posts * @param array $rightorderposts - The posts with the order they should have * The function returns 1 if $sortedposts matches $posts, else 0 @@ -268,14 +267,14 @@ private function create_everygroup() { $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; $this->answer1->markedhelpful = 1; $this->answer1->markedsolution = 1; - + // Answer2. $this->answer2->upvotes = 0; $this->answer2->downvotes = 0; $this->answer2->votesdifference = $this->answer2->upvotes - $this->answer2->downvotes; $this->answer2->markedhelpful = 0; $this->answer2->markedsolution = 1; - + // Answer3. $this->answer3->upvotes = 0; $this->answer3->downvotes = 0; @@ -305,6 +304,6 @@ private function create_everygroup() { $this->answer6->markedsolution = 0; } - //private function create_groupswithoutsolution - + // private function create_groupswithoutsolution + } From 97f2258698e219f5e77a36bbf6d0331482f2478e Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Tue, 16 May 2023 18:20:35 +0200 Subject: [PATCH 30/35] WIP: write test cases for ratings.php --- tests/ratings_test.php | 76 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/tests/ratings_test.php b/tests/ratings_test.php index 8c8250f25e..8562642b48 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -109,7 +109,7 @@ public function test_sort_answer_by_ratings() { // Create helpful, solved, up and downvotes ratings. $this->create_everygroup(); - // Test with every group if rating + // Test with every group of rating // Create a array of the posts, save the sorted post and compare them to the order that they should have. $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); @@ -167,6 +167,8 @@ public function test_sort_answer_by_ratings() { $rightorderposts = array($this->post, $this->answer2, $this->answer3, $this->answer4, $this->answer6, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); + + // Now test every rating group alone } // Helper functions @@ -304,6 +306,76 @@ private function create_everygroup() { $this->answer6->markedsolution = 0; } - // private function create_groupswithoutsolution + /** + * Creates a rating of one group for every post in the discussion + * Creates up and downvotes + * @param string $group + * A Group can be: + * - both as solution and helpful marked posts (sh) + * - only solution posts (s) + * - only helpful (h) + * - no mark (o) + */ + private function create_onegroup($group) { + + $answers = array($this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + foreach ($answers as $answer) { + switch ($group) { + case 'sh': + $answer->markedhelpful = 1; + $answer->markedsolution = 1; + break; + case 's': + $answer->markedhelpful = 0; + $answer->markedsolution = 1; + break; + case 'h': + $answer->markedhelpful = 1; + $answer->markedsolution = 0; + break; + case 'o': + $answer->markedhelpful = 0; + $answer->markedsolution = 0; + break; + default: + $answer->markedhelpful = 0; + $answer->markedsolution = 0; + break; + } + } + + // Votes for the answerposts + // Answer1. + $this->answer1->upvotes = 4; + $this->answer1->downvotes = -4; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 0. + + // Answer2. + $this->answer1->upvotes = 1; + $this->answer1->downvotes = 2; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = -1. + + // Answer3. + $this->answer1->upvotes = 3; + $this->answer1->downvotes = 2; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 1. + + // Answer4. + $this->answer1->upvotes = 5; + $this->answer1->downvotes = 0; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 5 + + // Answer5. + $this->answer1->upvotes = 0; + $this->answer1->downvotes = 2; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = -2. + + // Answer6. + $this->answer1->upvotes = 4; + $this->answer1->downvotes = 2; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 2. + + // Rightorder = answer4 , answer6, answer3, answer1, answer2, answer5. + } } From cac514bef42c3f32bc56345398870ee2e225ffde Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 22 May 2023 11:08:02 +0200 Subject: [PATCH 31/35] test cases completed for ratings.php --- tests/ratings_test.php | 293 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 269 insertions(+), 24 deletions(-) diff --git a/tests/ratings_test.php b/tests/ratings_test.php index 8562642b48..062c538dd5 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -103,9 +103,10 @@ public function tearDown(): void { // Begin of test functions /** - * Test, if rating can sort after ever group with ratingpreferences on helpful first. + * Tests function ratings::moodleoverflow_sort_answer_by_ratings + * Test case: Every group of rating exists (helful and solved posts, only helpful/solved and none) */ - public function test_sort_answer_by_ratings() { + public function test_answersorting_everygroup() { // Create helpful, solved, up and downvotes ratings. $this->create_everygroup(); @@ -125,6 +126,15 @@ public function test_sort_answer_by_ratings() { $rightorderposts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer6, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); + } + + /** + * Tests function ratings::moodleoverflow_sort_answer_by_ratings + * Test case: One group of rating does not exist + */ + public function test_answersorting_threegroups() { + // Create helpful, solved, up and downvotes ratings. + $this->create_everygroup(); // Test without posts that are only marked as solved $posts = array($this->post, $this->answer1, $this->answer3, $this->answer4, $this->answer5, $this->answer6); @@ -167,8 +177,134 @@ public function test_sort_answer_by_ratings() { $rightorderposts = array($this->post, $this->answer2, $this->answer3, $this->answer4, $this->answer6, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); + } + + /** + * Tests function ratings::moodleoverflow_sort_answer_by_ratings + * Test case: two groups of rating do not exist + */ + public function test_answersorting_twogroups() { + $this->set_ratingpreferences(0); + + // Test case 1: helpful and solved post, only solved posts. + $group1 = 'sh'; + $group2 = 's'; + $this->create_twogroups($group1, $group2); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 2: helpful and solved post, only helpful posts. + $group1 = 'sh'; + $group2 = 'h'; + $this->create_twogroups($group1, $group2); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 3: helpful and solved post, not-marked posts. + $group1 = 'sh'; + $group2 = 'o'; + $this->create_twogroups($group1, $group2); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); - // Now test every rating group alone + // Test case 4: only solved posts and only helpful posts with ratingpreferences = 0. + $group1 = 's'; + $group2 = 'h'; + $this->set_ratingpreferences(0); + $this->create_twogroups($group1, $group2); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer6, $this->answer5, $this->answer4, $this->answer2, $this->answer1, $this->answer3); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 5: only solved posts and only helpful posts with ratingpreferences = 1. + $group1 = 's'; + $group2 = 'h'; + $this->set_ratingpreferences(1); + $this->create_twogroups($group1, $group2); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 6: only solved posts and not-marked posts. + $group1 = 's'; + $group2 = 'o'; + $this->create_twogroups($group1, $group2); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 6: only helpful posts and not-marked posts. + $group1 = 'h'; + $group2 = 'o'; + $this->create_twogroups($group1, $group2); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + } + + /** + * Tests function ratings::moodleoverflow_sort_answer_by_ratings + * Test case: Only one group of rating exists, so only: + * - helpful and solved posts, or + * - helpful, or + * - solved, or + * - not marked + */ + public function test_answersorting_onegroup() { + $this->set_ratingpreferences(0); + + // Test case 1: only solved and helpful posts. + $group = 'sh'; + $this->create_onegroup($group); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 1: only solvedposts. + $group = 's'; + $this->create_onegroup($group); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 1: only helpful posts. + $group = 'h'; + $this->create_onegroup($group); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); + + // Test case 1: only not marked posts. + $group = 'o'; + $this->create_onegroup($group); + $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); + $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $result = $this->postsorderequal($sortedposts, $rightorderposts); + $this->assertEquals(1, $result); } // Helper functions @@ -317,7 +453,6 @@ private function create_everygroup() { * - no mark (o) */ private function create_onegroup($group) { - $answers = array($this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); foreach ($answers as $answer) { switch ($group) { @@ -337,45 +472,155 @@ private function create_onegroup($group) { $answer->markedhelpful = 0; $answer->markedsolution = 0; break; - default: - $answer->markedhelpful = 0; - $answer->markedsolution = 0; - break; } } // Votes for the answerposts // Answer1. $this->answer1->upvotes = 4; - $this->answer1->downvotes = -4; + $this->answer1->downvotes = 4; $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 0. // Answer2. - $this->answer1->upvotes = 1; - $this->answer1->downvotes = 2; - $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = -1. + $this->answer2->upvotes = 1; + $this->answer2->downvotes = 2; + $this->answer2->votesdifference = $this->answer2->upvotes - $this->answer2->downvotes; // Vd = -1. // Answer3. - $this->answer1->upvotes = 3; - $this->answer1->downvotes = 2; - $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 1. + $this->answer3->upvotes = 3; + $this->answer3->downvotes = 2; + $this->answer3->votesdifference = $this->answer3->upvotes - $this->answer3->downvotes; // Vd = 1. // Answer4. - $this->answer1->upvotes = 5; - $this->answer1->downvotes = 0; - $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 5 + $this->answer4->upvotes = 5; + $this->answer4->downvotes = 0; + $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; // Vd = 5 // Answer5. - $this->answer1->upvotes = 0; - $this->answer1->downvotes = 2; - $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = -2. + $this->answer5->upvotes = 0; + $this->answer5->downvotes = 2; + $this->answer5->votesdifference = $this->answer5->upvotes - $this->answer5->downvotes; // Vd = -2. // Answer6. - $this->answer1->upvotes = 4; - $this->answer1->downvotes = 2; - $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = 2. + $this->answer6->upvotes = 4; + $this->answer6->downvotes = 2; + $this->answer6->votesdifference = $this->answer6->upvotes - $this->answer6->downvotes; // Vd = 2. // Rightorder = answer4 , answer6, answer3, answer1, answer2, answer5. } + private function create_twogroups($group1, $group2) { + // Set the first 3 answers to the first group of rating. + switch ($group1) { + case 'sh': + $this->answer1->markedhelpful = 1; + $this->answer1->markedsolution = 1; + $this->answer2->markedhelpful = 1; + $this->answer2->markedsolution = 1; + $this->answer3->markedhelpful = 1; + $this->answer3->markedsolution = 1; + break; + case 's': + $this->answer1->markedhelpful = 0; + $this->answer1->markedsolution = 1; + $this->answer2->markedhelpful = 0; + $this->answer2->markedsolution = 1; + $this->answer3->markedhelpful = 0; + $this->answer3->markedsolution = 1; + break; + case 'h': + $this->answer1->markedhelpful = 1; + $this->answer1->markedsolution = 0; + $this->answer2->markedhelpful = 1; + $this->answer2->markedsolution = 0; + $this->answer3->markedhelpful = 1; + $this->answer3->markedsolution = 0; + break; + case 'o': + $this->answer1->markedhelpful = 0; + $this->answer1->markedsolution = 0; + $this->answer2->markedhelpful = 0; + $this->answer2->markedsolution = 0; + $this->answer3->markedhelpful = 0; + $this->answer3->markedsolution = 0; + break; + } + + switch ($group2) { + case 'sh': + $this->answer4->markedhelpful = 1; + $this->answer4->markedsolution = 1; + $this->answer5->markedhelpful = 1; + $this->answer5->markedsolution = 1; + $this->answer6->markedhelpful = 1; + $this->answer6->markedsolution = 1; + break; + case 's': + $this->answer4->markedhelpful = 0; + $this->answer4->markedsolution = 1; + $this->answer5->markedhelpful = 0; + $this->answer5->markedsolution = 1; + $this->answer6->markedhelpful = 0; + $this->answer6->markedsolution = 1; + break; + case 'h': + $this->answer4->markedhelpful = 1; + $this->answer4->markedsolution = 0; + $this->answer5->markedhelpful = 1; + $this->answer5->markedsolution = 0; + $this->answer6->markedhelpful = 1; + $this->answer6->markedsolution = 0; + break; + case 'o': + $this->answer4->markedhelpful = 0; + $this->answer4->markedsolution = 0; + $this->answer5->markedhelpful = 0; + $this->answer5->markedsolution = 0; + $this->answer6->markedhelpful = 0; + $this->answer6->markedsolution = 0; + break; + } + + // Now set the up and downvotes for every answer. + // Answer1. + $this->answer1->upvotes = 3; + $this->answer1->downvotes = 4; + $this->answer1->votesdifference = $this->answer1->upvotes - $this->answer1->downvotes; // Vd = -1. + + // Answer2. + $this->answer2->upvotes = 4; + $this->answer2->downvotes = 1; + $this->answer2->votesdifference = $this->answer2->upvotes - $this->answer2->downvotes; // Vd = 3. + + // Answer3. + $this->answer3->upvotes = 0; + $this->answer3->downvotes = 2; + $this->answer3->votesdifference = $this->answer3->upvotes - $this->answer3->downvotes; // Vd = -2. + + // Answer4. + $this->answer4->upvotes = 5; + $this->answer4->downvotes = 5; + $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; // Vd = 0 + + // Answer5. + $this->answer5->upvotes = 6; + $this->answer5->downvotes = 5; + $this->answer5->votesdifference = $this->answer5->upvotes - $this->answer5->downvotes; // Vd = 1. + + // Answer6. + $this->answer6->upvotes = 4; + $this->answer6->downvotes = 2; + $this->answer6->votesdifference = $this->answer6->upvotes - $this->answer6->downvotes; // Vd = 2. + + + // The Rightorder depends now on the group parameter. + // Rightorder (sh,s) = answer2, answer1, answer3, answer6, answer5, answer4. + // Rightorder (sh,h) = answer2, answer1, answer3, answer6, answer5, answer4. + // Rightorder (sh,o) = answer2, answer1, answer3, answer6, answer5, answer4. + // Rightorder (s,h) = answer6, answer5, answer4, answer2, answer1, answer3. with ratingpreference = 0. + // Rightorder (s,h) = answer2, answer1, answer3, answer6, answer5, answer4. with ratingpreference = 1 + // Rightorder (s,o) = answer2, answer1, answer3, answer6, answer5, answer4. + // Rightorder (h,o) = answer2, answer1, answer3, answer6, answer5, answer4. + + } } From 30036238ea82f589f64de85f154e6eec5ae54f82 Mon Sep 17 00:00:00 2001 From: NinaHerrmann <nina.herrmann@uni-muenster.de> Date: Mon, 22 May 2023 11:37:51 +0200 Subject: [PATCH 32/35] force encoding to ENT_COMPAT (default in php < 8.1) --- classes/output/moodleoverflow_email.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/classes/output/moodleoverflow_email.php b/classes/output/moodleoverflow_email.php index fc83e1cf5c..b52d653be9 100644 --- a/classes/output/moodleoverflow_email.php +++ b/classes/output/moodleoverflow_email.php @@ -155,15 +155,15 @@ public function export_for_template(\renderer_base $renderer, $plaintext = false protected function export_for_template_text(\mod_moodleoverflow_renderer $renderer) { return array( - 'id' => html_entity_decode($this->post->id), - 'coursename' => html_entity_decode($this->get_coursename()), - 'courselink' => html_entity_decode($this->get_courselink()), - 'moodleoverflowname' => html_entity_decode($this->get_moodleoverflowname()), - 'showdiscussionname' => html_entity_decode($this->has_showdiscussionname()), - 'discussionname' => html_entity_decode($this->get_discussionname()), - 'subject' => html_entity_decode($this->get_subject()), - 'authorfullname' => html_entity_decode($this->get_author_fullname()), - 'postdate' => html_entity_decode($this->get_postdate()), + 'id' => html_entity_decode($this->post->id, ENT_COMPAT), + 'coursename' => html_entity_decode($this->get_coursename(), ENT_COMPAT), + 'courselink' => html_entity_decode($this->get_courselink(), ENT_COMPAT), + 'moodleoverflowname' => html_entity_decode($this->get_moodleoverflowname(), ENT_COMPAT), + 'showdiscussionname' => html_entity_decode($this->has_showdiscussionname(), ENT_COMPAT), + 'discussionname' => html_entity_decode($this->get_discussionname(), ENT_COMPAT), + 'subject' => html_entity_decode($this->get_subject(), ENT_COMPAT), + 'authorfullname' => html_entity_decode($this->get_author_fullname(), ENT_COMPAT), + 'postdate' => html_entity_decode($this->get_postdate(), ENT_COMPAT), 'firstpost' => $this->is_firstpost(), 'canreply' => $this->canreply, 'permalink' => $this->get_permalink(), @@ -179,7 +179,7 @@ protected function export_for_template_text(\mod_moodleoverflow_renderer $render 'grouppicture' => $this->get_group_picture(), // Format some components according to the renderer. - 'message' => html_entity_decode($renderer->format_message_text($this->cm, $this->post)), + 'message' => html_entity_decode($renderer->format_message_text($this->cm, $this->post), ENT_COMPAT), ); } From fdfec0e64c0d9b66f58c1298250c274096f2d405 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 22 May 2023 12:43:54 +0200 Subject: [PATCH 33/35] code checking and cleaning --- classes/ratings.php | 8 ++- classes/task/send_daily_mail.php | 1 - locallib.php | 3 + tests/behat/behat_mod_moodleoverflow.php | 9 ++- tests/dailymail_test.php | 4 ++ tests/ratings_test.php | 82 ++++++++++++++++-------- tests/userstats_test.php | 4 ++ 7 files changed, 79 insertions(+), 32 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 99fb8f2366..568489514a 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -350,7 +350,7 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { $neworder[$post->id] = $post; } - // return now the sorted posts. + // Return now the sorted posts. return $neworder; } @@ -813,6 +813,12 @@ public static function moodleoverflow_user_can_rate($post, $modulecontext, $user && $post->reviewed == 1; } + /** + * Sorts answerposts of a discussion with quicksort algorithm + * @param array $posts the posts that are being sorted + * @param int $low the index from where the sorting begins + * @param int $high the index until the array is being sorted + */ private static function moodleoverflow_quicksort_post_by_votes(array &$posts, $low, $high) { if ($low >= $high) { return; diff --git a/classes/task/send_daily_mail.php b/classes/task/send_daily_mail.php index e2c57a57e2..7c2fa1cda9 100644 --- a/classes/task/send_daily_mail.php +++ b/classes/task/send_daily_mail.php @@ -23,7 +23,6 @@ */ namespace mod_moodleoverflow\task; -defined('MOODLE_INTERNAL') || die(); /** * This task sends a daily mail of unread posts */ diff --git a/locallib.php b/locallib.php index 71ff6052eb..ef1ec7a7b9 100644 --- a/locallib.php +++ b/locallib.php @@ -921,6 +921,7 @@ function moodleoverflow_user_can_post($modulecontext, $posttoreplyto, $considerr * @param stdClass $moodleoverflow The moodleoverflow object * @param stdClass $discussion The discussion object * @param stdClass $post The post object + * @param bool $multiplemarks The setting of multiplemarks (default: multiplemarks are not allowed) */ function moodleoverflow_print_discussion($course, $cm, $moodleoverflow, $discussion, $post, $multiplemarks = false) { global $USER; @@ -1118,6 +1119,7 @@ function moodleoverflow_get_all_discussion_posts($discussionid, $tracking, $modc * @param bool $iscomment * @param array $usermapping * @param int $level + * @param bool $multiplemarks setting of multiplemarks * @return void|null * @throws coding_exception * @throws dml_exception @@ -1494,6 +1496,7 @@ function moodleoverflow_print_post($post, $discussion, $moodleoverflow, $cm, $co * @param array $posts Array of posts within the discussion * @param bool $iscomment Whether the current post is a comment * @param array $usermapping + * @param bool $multiplemarks * @return string * @throws coding_exception * @throws dml_exception diff --git a/tests/behat/behat_mod_moodleoverflow.php b/tests/behat/behat_mod_moodleoverflow.php index 709dae2ef6..56983731d4 100644 --- a/tests/behat/behat_mod_moodleoverflow.php +++ b/tests/behat/behat_mod_moodleoverflow.php @@ -128,7 +128,8 @@ protected function find_moodleoverflow_discussion_card(string $discussiontitle): * * This step is for advanced users, use it if you don't find anything else suitable for what you need. * - * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should exist in the "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ + * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should exist in the + * "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ * @throws ElementNotFoundException Thrown by behat_base::find * @param string $element The locator of the specified selector * @param string $selectortype The selector type @@ -149,7 +150,8 @@ public function should_exist_in_the_moodleoverflow_discussion_card($element, $se /** * Click on the element of the specified type which is located inside the second element. * - * @When /^I click on "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" in the "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ + * @When /^I click on "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" in the + * "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ * @param string $element Element we look for * @param string $selectortype The type of what we look for * @param string $discussiontitle The discussion title @@ -173,7 +175,8 @@ public function i_click_on_in_the_moodleoverflow_discussion_card($element, $sele * * This step is for advanced users, use it if you don't find anything else suitable for what you need. * - * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should not exist in the "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ + * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should not exist in the + * "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ * @throws ExpectationException * @param string $element The locator of the specified selector * @param string $selectortype The selector type diff --git a/tests/dailymail_test.php b/tests/dailymail_test.php index 29fc74bdce..26447424b1 100644 --- a/tests/dailymail_test.php +++ b/tests/dailymail_test.php @@ -134,6 +134,7 @@ private function helper_run_send_mails() { /** * Test if the task send_daily_mail sends a mail to the user. + * @covers \send_daily_mail::execute */ public function test_mail_delivery() { @@ -151,6 +152,7 @@ public function test_mail_delivery() { /** * Test if the content of the mail matches the supposed content. + * @covers \send_daily_mail::execute */ public function test_content_of_mail_delivery() { @@ -185,6 +187,7 @@ public function test_content_of_mail_delivery() { /** * Test if the task does not send a mail when maildigest = 0 + * @covers \send_daily_mail::execute */ public function test_mail_not_send() { // Creat user with daily_mail = off. @@ -200,6 +203,7 @@ public function test_mail_not_send() { /** * Test if database is updated after sending a mail + * @covers \send_daily_mail::execute */ public function test_records_removed() { global $DB; diff --git a/tests/ratings_test.php b/tests/ratings_test.php index 062c538dd5..31de91a2fe 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -100,30 +100,33 @@ public function tearDown(): void { \mod_moodleoverflow\subscriptions::reset_discussion_cache(); } - // Begin of test functions + // Begin of test functions. /** - * Tests function ratings::moodleoverflow_sort_answer_by_ratings + * Tests function ratings::moodleoverflow_sort_answer_by_ratings * Test case: Every group of rating exists (helful and solved posts, only helpful/solved and none) + * @covers \ratings::moodleoverflow_sort_answer_by_ratings() */ public function test_answersorting_everygroup() { // Create helpful, solved, up and downvotes ratings. $this->create_everygroup(); - // Test with every group of rating + // Test with every group of rating. // Create a array of the posts, save the sorted post and compare them to the order that they should have. $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $this->set_ratingpreferences(0); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer1, $this->answer3, $this->answer2, $this->answer4, $this->answer6, $this->answer5); + $rightorderposts = array($this->post, $this->answer1, $this->answer3, $this->answer2, + $this->answer4, $this->answer6, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); // Change the rating preference of the teacher and sort again. $this->set_ratingpreferences(1); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer6, $this->answer5); + $rightorderposts = array($this->post, $this->answer1, $this->answer2, $this->answer3, + $this->answer4, $this->answer6, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); } @@ -131,12 +134,13 @@ public function test_answersorting_everygroup() { /** * Tests function ratings::moodleoverflow_sort_answer_by_ratings * Test case: One group of rating does not exist + * @covers \ratings::moodleoverflow_sort_answer_by_ratings() */ public function test_answersorting_threegroups() { // Create helpful, solved, up and downvotes ratings. $this->create_everygroup(); - // Test without posts that are only marked as solved + // Test without posts that are only marked as solved. $posts = array($this->post, $this->answer1, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $this->set_ratingpreferences(0); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); @@ -150,7 +154,7 @@ public function test_answersorting_threegroups() { $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); - // Test without posts that are only marked as helpful + // Test without posts that are only marked as helpful. $posts = array($this->post, $this->answer1, $this->answer2, $this->answer4, $this->answer5, $this->answer6); $this->set_ratingpreferences(0); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); @@ -164,7 +168,7 @@ public function test_answersorting_threegroups() { $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); - // Test without posts that are marked as both helpful and marked + // Test without posts that are marked as both helpful and marked. $posts = array($this->post, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $this->set_ratingpreferences(0); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); @@ -182,6 +186,7 @@ public function test_answersorting_threegroups() { /** * Tests function ratings::moodleoverflow_sort_answer_by_ratings * Test case: two groups of rating do not exist + * @covers \ratings::moodleoverflow_sort_answer_by_ratings() */ public function test_answersorting_twogroups() { $this->set_ratingpreferences(0); @@ -192,7 +197,8 @@ public function test_answersorting_twogroups() { $this->create_twogroups($group1, $group2); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, + $this->answer6, $this->answer5, $this->answer4); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -202,7 +208,8 @@ public function test_answersorting_twogroups() { $this->create_twogroups($group1, $group2); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, + $this->answer6, $this->answer5, $this->answer4); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -212,7 +219,8 @@ public function test_answersorting_twogroups() { $this->create_twogroups($group1, $group2); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, + $this->answer6, $this->answer5, $this->answer4); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -223,7 +231,8 @@ public function test_answersorting_twogroups() { $this->create_twogroups($group1, $group2); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer6, $this->answer5, $this->answer4, $this->answer2, $this->answer1, $this->answer3); + $rightorderposts = array($this->post, $this->answer6, $this->answer5, $this->answer4, + $this->answer2, $this->answer1, $this->answer3); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -234,7 +243,8 @@ public function test_answersorting_twogroups() { $this->create_twogroups($group1, $group2); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, + $this->answer6, $this->answer5, $this->answer4); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -244,7 +254,8 @@ public function test_answersorting_twogroups() { $this->create_twogroups($group1, $group2); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, + $this->answer6, $this->answer5, $this->answer4); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -254,7 +265,8 @@ public function test_answersorting_twogroups() { $this->create_twogroups($group1, $group2); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, $this->answer6, $this->answer5, $this->answer4); + $rightorderposts = array($this->post, $this->answer2, $this->answer1, $this->answer3, + $this->answer6, $this->answer5, $this->answer4); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); } @@ -266,6 +278,7 @@ public function test_answersorting_twogroups() { * - helpful, or * - solved, or * - not marked + * @covers \ratings::moodleoverflow_sort_answer_by_ratings() */ public function test_answersorting_onegroup() { $this->set_ratingpreferences(0); @@ -275,7 +288,8 @@ public function test_answersorting_onegroup() { $this->create_onegroup($group); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, + $this->answer1, $this->answer2, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -284,7 +298,8 @@ public function test_answersorting_onegroup() { $this->create_onegroup($group); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, + $this->answer1, $this->answer2, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -293,7 +308,8 @@ public function test_answersorting_onegroup() { $this->create_onegroup($group); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, + $this->answer1, $this->answer2, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); @@ -302,12 +318,13 @@ public function test_answersorting_onegroup() { $this->create_onegroup($group); $posts = array($this->post, $this->answer1, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); - $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, $this->answer1, $this->answer2, $this->answer5); + $rightorderposts = array($this->post, $this->answer4, $this->answer6, $this->answer3, + $this->answer1, $this->answer2, $this->answer5); $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); } - // Helper functions + // Helper functions. /** * This function creates: @@ -333,7 +350,7 @@ private function helper_course_set_up() { $this->user2 = $this->getDataGenerator()->create_user(array('firstname' => 'Ethan', 'lastname' => 'Brown')); $this->getDataGenerator()->enrol_user($this->user2->id, $this->course->id, 'student'); - // Create a discussion, a parent post and six answers + // Create a discussion, a parent post and six answers. $this->generator = $this->getDataGenerator()->get_plugin_generator('mod_moodleoverflow'); $this->discussion = $this->generator->post_to_forum($this->moodleoverflow, $this->teacher); $this->post = $DB->get_record('moodleoverflow_posts', array('id' => $this->discussion[0]->firstpost), '*'); @@ -362,7 +379,7 @@ private function postsorderequal($sortedposts, $rightorderposts) { $sortedpost = current($sortedposts); $post = current($rightorderposts); if ($sortedpost->id == $post->id) { - // Go to the next elements + // Go to the next elements. next($sortedposts); next($rightorderposts); } else { @@ -376,6 +393,7 @@ private function postsorderequal($sortedposts, $rightorderposts) { * sets the ratingpreferences to 1 or 0: * 1 = solved posts will be shown above helpful posts. * 0 = helpful posts will be shown above solved posts. + * @param int $preference the rating preference */ private function set_ratingpreferences($preference) { if ($preference == 0 || $preference == 1) { @@ -494,7 +512,7 @@ private function create_onegroup($group) { // Answer4. $this->answer4->upvotes = 5; $this->answer4->downvotes = 0; - $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; // Vd = 5 + $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; // Vd = 5. // Answer5. $this->answer5->upvotes = 0; @@ -509,7 +527,18 @@ private function create_onegroup($group) { // Rightorder = answer4 , answer6, answer3, answer1, answer2, answer5. } - private function create_twogroups($group1, $group2) { + /** + * Creates ratings of the posts of the assigned groups in the discussion. + * Creates up and downvotes + * @param string $group1 + * @param string $group2 + * A Group can be: + * - both as solution and helpful marked posts (sh) + * - only solution posts (s) + * - only helpful (h) + * - no mark (o) + */ + private function create_twogroups($group1, $group2) { // Set the first 3 answers to the first group of rating. switch ($group1) { case 'sh': @@ -600,7 +629,7 @@ private function create_twogroups($group1, $group2) { // Answer4. $this->answer4->upvotes = 5; $this->answer4->downvotes = 5; - $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; // Vd = 0 + $this->answer4->votesdifference = $this->answer4->upvotes - $this->answer4->downvotes; // Vd = 0. // Answer5. $this->answer5->upvotes = 6; @@ -612,7 +641,6 @@ private function create_twogroups($group1, $group2) { $this->answer6->downvotes = 2; $this->answer6->votesdifference = $this->answer6->upvotes - $this->answer6->downvotes; // Vd = 2. - // The Rightorder depends now on the group parameter. // Rightorder (sh,s) = answer2, answer1, answer3, answer6, answer5, answer4. // Rightorder (sh,h) = answer2, answer1, answer3, answer6, answer5, answer4. @@ -620,7 +648,7 @@ private function create_twogroups($group1, $group2) { // Rightorder (s,h) = answer6, answer5, answer4, answer2, answer1, answer3. with ratingpreference = 0. // Rightorder (s,h) = answer2, answer1, answer3, answer6, answer5, answer4. with ratingpreference = 1 // Rightorder (s,o) = answer2, answer1, answer3, answer6, answer5, answer4. - // Rightorder (h,o) = answer2, answer1, answer3, answer6, answer5, answer4. + // Rightorder (h,o) = answer2, answer1, answer3, answer6, answer5, answer4. } } diff --git a/tests/userstats_test.php b/tests/userstats_test.php index 01bb9862fb..9b26db5e56 100644 --- a/tests/userstats_test.php +++ b/tests/userstats_test.php @@ -99,6 +99,7 @@ public function tearDown(): void { /** * Test, if a upvote is being counted. + * @covers \userstats_table */ public function test_upvote() { // Teacher upvotes the discussion and the answer of user2. @@ -116,6 +117,7 @@ public function test_upvote() { /** * Test, if a downvote is being counted. + * @covers \userstats_table */ public function test_downvote() { // Teacher downvotes the discussion and the answer of user1. @@ -133,6 +135,7 @@ public function test_downvote() { /** * Test, if the activity is calculated correctly. + * @covers \userstats_table */ public function test_activity() { // User1 will rates 3 times. @@ -153,6 +156,7 @@ public function test_activity() { } /** * Test, if the reputation is calculated correctly. + * @covers \userstats_table */ public function test_reputation() { // User1 creates some ratings for user2, Teacher creates some ratings for user2. From d7cb0d8dd580b691fa1fd9aac2d3b46808c6be63 Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 22 May 2023 13:17:59 +0200 Subject: [PATCH 34/35] last changes on version number for release --- classes/ratings.php | 4 ++-- tests/ratings_test.php | 2 +- version.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/classes/ratings.php b/classes/ratings.php index 568489514a..b9da34156e 100644 --- a/classes/ratings.php +++ b/classes/ratings.php @@ -249,8 +249,8 @@ public static function moodleoverflow_sort_answers_by_ratings($posts) { // Sort the answer posts by ratings. // Build groups of different types of answers (Solved and helpful, only solved/helpful, other). - // statusteacher == 1 means the post is marked as solved. - // statusstarter == 1 means the post is marked as helpful. + // markedsolved == 1 means the post is marked as solved. + // markedhelpful == 1 means the post is marked as helpful. // If a group is complete, sort the group. $index = 1; $startsolvedandhelpful = 1; diff --git a/tests/ratings_test.php b/tests/ratings_test.php index 31de91a2fe..c7fb701f6e 100644 --- a/tests/ratings_test.php +++ b/tests/ratings_test.php @@ -168,7 +168,7 @@ public function test_answersorting_threegroups() { $result = $this->postsorderequal($sortedposts, $rightorderposts); $this->assertEquals(1, $result); - // Test without posts that are marked as both helpful and marked. + // Test without posts that are marked as both helpful and solved. $posts = array($this->post, $this->answer2, $this->answer3, $this->answer4, $this->answer5, $this->answer6); $this->set_ratingpreferences(0); $sortedposts = ratings::moodleoverflow_sort_answers_by_ratings($posts); diff --git a/version.php b/version.php index 7215a84622..b70eabf999 100644 --- a/version.php +++ b/version.php @@ -28,7 +28,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'mod_moodleoverflow'; -$plugin->version = 2023050802; +$plugin->version = 2023052200; $plugin->release = 'v4.2-r1'; $plugin->requires = 2020061500; // Requires Moodle 3.9+. $plugin->maturity = MATURITY_STABLE; From 8e761b39cb0984d6b5ed7261b2d0d733fd9c1c1a Mon Sep 17 00:00:00 2001 From: TamaroWalter <tamarowalter@yahoo.de> Date: Mon, 22 May 2023 13:23:40 +0200 Subject: [PATCH 35/35] behat problems fixed --- tests/behat/behat_mod_moodleoverflow.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/behat/behat_mod_moodleoverflow.php b/tests/behat/behat_mod_moodleoverflow.php index 56983731d4..709dae2ef6 100644 --- a/tests/behat/behat_mod_moodleoverflow.php +++ b/tests/behat/behat_mod_moodleoverflow.php @@ -128,8 +128,7 @@ protected function find_moodleoverflow_discussion_card(string $discussiontitle): * * This step is for advanced users, use it if you don't find anything else suitable for what you need. * - * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should exist in the - * "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ + * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should exist in the "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ * @throws ElementNotFoundException Thrown by behat_base::find * @param string $element The locator of the specified selector * @param string $selectortype The selector type @@ -150,8 +149,7 @@ public function should_exist_in_the_moodleoverflow_discussion_card($element, $se /** * Click on the element of the specified type which is located inside the second element. * - * @When /^I click on "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" in the - * "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ + * @When /^I click on "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" in the "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ * @param string $element Element we look for * @param string $selectortype The type of what we look for * @param string $discussiontitle The discussion title @@ -175,8 +173,7 @@ public function i_click_on_in_the_moodleoverflow_discussion_card($element, $sele * * This step is for advanced users, use it if you don't find anything else suitable for what you need. * - * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should not exist in the - * "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ + * @Then /^"(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)" should not exist in the "(?P<element2_string>(?:[^"]|\\")*)" moodleoverflow discussion card$/ * @throws ExpectationException * @param string $element The locator of the specified selector * @param string $selectortype The selector type