From fbb842e5966592a3e25a0aee5c187a2485b07024 Mon Sep 17 00:00:00 2001 From: FelixDiLenarda <92793568+FelixDiLenarda@users.noreply.github.com> Date: Tue, 16 May 2023 20:13:18 +0200 Subject: [PATCH 1/7] Resized the monologo.svg and png to 24x24 px (#477) --- pix/monologo.png | Bin 5359 -> 719 bytes pix/monologo.svg | 135 +++++++++++++---------------------------------- 2 files changed, 38 insertions(+), 97 deletions(-) diff --git a/pix/monologo.png b/pix/monologo.png index 5fe031496fcd4f8ba00f30bfb09fba9d332e94e2..15e1f3e806f0b53091f2a397564864a5d794ec77 100644 GIT binary patch literal 719 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 diff --git a/pix/monologo.svg b/pix/monologo.svg index dcf41261..004ad0f2 100644 --- a/pix/monologo.svg +++ b/pix/monologo.svg @@ -1,97 +1,38 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - + + + +Created with Fabric.js 4.6.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 458cedcf261dff282cece8a1f632b9aaca1e7fcc Mon Sep 17 00:00:00 2001 From: Mike Churchward Date: Tue, 16 May 2023 14:43:27 -0400 Subject: [PATCH 2/7] Fixing issues from plugins database checks (#483) * Removing illegal console commands. Script may not be needed. * Fixing illegal line length. * Fixing docblocks and unused variables. * Fixing css spaces. * Adding a true return. * Fixing JSON context. --- appjs/uncheckother.js | 5 -- db/upgrade.php | 2 +- javascript/mobile.js | 7 ++- module.js | 50 ++++++++++++++----- styles_app.css | 2 +- .../mobile/ionic3/select_question.mustache | 2 + .../mobile/ionic3/slider_question.mustache | 16 +++--- 7 files changed, 53 insertions(+), 31 deletions(-) diff --git a/appjs/uncheckother.js b/appjs/uncheckother.js index dd06d8b4..c76a4df6 100644 --- a/appjs/uncheckother.js +++ b/appjs/uncheckother.js @@ -1,9 +1,4 @@ (function(t) { t.toggleRatebox = function($event, $fieldkey) { - console.log($fieldkey); - console.log($event); - console.log($event.value); - console.log(this.CONTENT_OTHERDATA[$fieldkey]); -// this.CONTENT_OTHERDATA[$fieldkey] = "4"; } })(this); \ No newline at end of file diff --git a/db/upgrade.php b/db/upgrade.php index 3861f365..fe91ab16 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -997,7 +997,7 @@ function xmldb_questionnaire_upgrade($oldversion=0) { upgrade_mod_savepoint(true, 2022092200, 'questionnaire'); } - return $result; + return true; } /** diff --git a/javascript/mobile.js b/javascript/mobile.js index 1291f57a..e46928da 100644 --- a/javascript/mobile.js +++ b/javascript/mobile.js @@ -23,8 +23,11 @@ this.questionsFormErrors = {}; for (const fieldkey in this.CONTENT_OTHERDATA.fields) { questionsFormFields[fieldkey] = []; questionsFormFields[fieldkey][0] = ''; - for (const itemid in this.CONTENT_OTHERDATA.questions[this.CONTENT_OTHERDATA.pagenum][this.CONTENT_OTHERDATA.fields[fieldkey].id]) { - questionsFormFields[fieldkey][0] = this.CONTENT_OTHERDATA.questions[this.CONTENT_OTHERDATA.pagenum][this.CONTENT_OTHERDATA.fields[fieldkey].id][itemid].value; + for (const itemid in + this.CONTENT_OTHERDATA.questions[this.CONTENT_OTHERDATA.pagenum][this.CONTENT_OTHERDATA.fields[fieldkey].id]) { + questionsFormFields[fieldkey][0] = + this.CONTENT_OTHERDATA.questions[this.CONTENT_OTHERDATA.pagenum][this.CONTENT_OTHERDATA.fields[fieldkey].id] + [itemid].value; } if (this.CONTENT_OTHERDATA.fields[fieldkey].required === 'y') { questionsFormFields[fieldkey][1] = this.Validators.required; diff --git a/module.js b/module.js index f3eb8d60..9eb3e93d 100644 --- a/module.js +++ b/module.js @@ -27,13 +27,21 @@ * http://stackoverflow.com/questions/6787383/what-is-the-solution-to-remove-add-a-class-in-pure-javascript. * */ -function addClass(el, aclass){ +/** + * @param {HTMLElement} el + * @param {string} aclass + */ +function addClass(el, aclass) { el.className += ' ' + aclass; } -function removeClass(el, aclass){ +/** + * @param {HTMLElement} el + * @param {string} aclass + */ +function removeClass(el, aclass) { var elClass = ' ' + el.className + ' '; - while(elClass.indexOf(' ' + aclass + ' ') != - 1) { + while (elClass.indexOf(' ' + aclass + ' ') != -1) { elClass = elClass.replace(' ' + aclass + ' ', ''); } el.className = elClass; @@ -44,7 +52,6 @@ function removeClass(el, aclass){ * Javascript for hiding/displaying children questions on preview page of * questionnaire with conditional branching. */ - function depend(children, choices) { children = children.split(','); choices = choices.split(','); @@ -82,7 +89,7 @@ function depend(children, choices) { droplist.disabled = false; } delete children[i]; - } else if (children[i]){ + } else if (children[i]) { if (typeof document !== "undefined" && ("classList" in document.createElement("a"))) { q.classList.remove('qn-container'); q.classList.add('hidedependquestion'); @@ -114,6 +121,10 @@ function depend(children, choices) { /* exported dependdrop */ +/** + * @param {string} qId + * @param {*} children + */ function dependdrop(qId, children) { var e = document.getElementById(qId); var choice = e.options[e.selectedIndex].value; @@ -124,9 +135,12 @@ function dependdrop(qId, children) { // When respondent enters text in !other field, corresponding // radio button OR check box is automatically checked. /* exported other_check */ +/** + * @param {string | void} name + */ function other_check(name) { var other = name.split("_"); - var other = name.slice(name.indexOf("o")+1); + var other = name.slice(name.indexOf("o") + 1); if (other.indexOf("]") != -1) { other = other.slice(0, other.indexOf("]")); } @@ -141,6 +155,9 @@ function other_check(name) { // Automatically empty an !other text input field if another Radio button is clicked. /* exported other_check_empty */ +/** + * @param {string} name + */ function other_check_empty(name, value) { var f = document.getElementById("phpesp_response"); var i; @@ -149,7 +166,7 @@ function other_check_empty(name, value) { f.elements[i].checked = true; var otherid = f.elements[i].name + "_" + f.elements[i].value.substring(6); var other = document.getElementsByName(otherid); - if (value.substr(0,6) != "other_") { + if (value.substr(0, 6) != "other_") { other[0].value = ""; } else { other[0].focus(); @@ -169,6 +186,10 @@ function other_check_empty(name, value) { // In a Rate question type of sub-type Order : automatically uncheck a Radio button // when another radio button in the same column is clicked. /* exported other_rate_uncheck */ +/** + * @param {string} name + * @param {string} value + */ function other_rate_uncheck(name, value) { var col_name = name.substr(0, name.indexOf("_")); var inputbuttons = document.getElementsByTagName("input"); @@ -183,6 +204,9 @@ function other_rate_uncheck(name, value) { // Empty an !other text input when corresponding Check Box is clicked (supposedly to empty it). /* exported checkbox_empty */ +/** + * @param {string} name + */ function checkbox_empty(name) { var actualbuttons = document.getElementsByName(name); for (var i = 0; i <= actualbuttons.length; i++) { @@ -204,24 +228,24 @@ M.mod_questionnaire = M.mod_questionnaire || {}; /* exported Y */ /* exported e */ -M.mod_questionnaire.init_attempt_form = function(Y) { +M.mod_questionnaire.init_attempt_form = function() { M.core_formchangechecker.init({formid: 'phpesp_response'}); }; M.mod_questionnaire.init_sendmessage = function(Y) { - Y.on('click', function(e) { + Y.on('click', function() { Y.all('input.usercheckbox').each(function() { this.set('checked', 'checked'); }); }, '#checkall'); - Y.on('click', function(e) { + Y.on('click', function() { Y.all('input.usercheckbox').each(function() { this.set('checked', ''); }); }, '#checknone'); - Y.on('click', function(e) { + Y.on('click', function() { Y.all('input.usercheckbox').each(function() { if (this.get('alt') == 0) { this.set('checked', 'checked'); @@ -231,7 +255,7 @@ M.mod_questionnaire.init_sendmessage = function(Y) { }); }, '#checknotstarted'); - Y.on('click', function(e) { + Y.on('click', function() { Y.all('input.usercheckbox').each(function() { if (this.get('alt') == 1) { this.set('checked', 'checked'); @@ -242,7 +266,7 @@ M.mod_questionnaire.init_sendmessage = function(Y) { }, '#checkstarted'); }; -M.mod_questionnaire.init_slider = function(Y) { +M.mod_questionnaire.init_slider = function() { const allRanges = document.querySelectorAll(".slider"); allRanges.forEach(wrap => { const range = wrap.querySelector("input.questionnaire-slider"); diff --git a/styles_app.css b/styles_app.css index e1b368db..e752eca3 100644 --- a/styles_app.css +++ b/styles_app.css @@ -7,7 +7,7 @@ span.mobileratequestion { -webkit-transform: translate3d(0, 0, 0) scale(1); transform: translate3d(0, 0, 0) scale(1); } -.mod_questionnaire_slider .range-has-pin::part(pin){ +.mod_questionnaire_slider .range-has-pin::part(pin) { -webkit-transform: translate3d(0, -24px, 0) scale(1); transform: translate3d(0, -24px, 0) scale(1); } diff --git a/templates/local/mobile/ionic3/select_question.mustache b/templates/local/mobile/ionic3/select_question.mustache index 30777db4..cf41de04 100644 --- a/templates/local/mobile/ionic3/select_question.mustache +++ b/templates/local/mobile/ionic3/select_question.mustache @@ -28,11 +28,13 @@ "fieldkey": 985, "choices": [ { + "id": 200, "content": "Red", "completed": 0, "value": 1 }, { + "id": 201, "content": "Blue", "completed": 0, "value": 0 diff --git a/templates/local/mobile/ionic3/slider_question.mustache b/templates/local/mobile/ionic3/slider_question.mustache index 64aef335..27ccb7c2 100644 --- a/templates/local/mobile/ionic3/slider_question.mustache +++ b/templates/local/mobile/ionic3/slider_question.mustache @@ -27,18 +27,16 @@ { "fieldkey": 985, "extradata": { - "minrange" : 1 - "maxrange" : 10 - "startingvalue" : 5 - "stepvalue" : 1 - "leftlabel" : "left label" - "rightlabel" : "right label" + "minrange" : 1, + "maxrange" : 10, + "startingvalue" : 5, + "stepvalue" : 1, + "leftlabel" : "left label", + "rightlabel" : "right label", "centerlabel": "center label" }, - completed: 0 - + "completed": 0 } - }} {{=<% %>=}} <%#extradata%> From 81ad1e19f85e6de1ab0ef77a72d531474dfe0fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joseph=20R=C3=A9zeau?= Date: Fri, 23 Jun 2023 15:05:27 +0200 Subject: [PATCH 3/7] New attempt at restoring the radar chart_type to questionnaire feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Joseph Rézeau --- classes/feedback_form.php | 31 +++++++++++++------------------ feedback.php | 2 -- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/classes/feedback_form.php b/classes/feedback_form.php index 25260847..62a7471a 100644 --- a/classes/feedback_form.php +++ b/classes/feedback_form.php @@ -36,7 +36,13 @@ class feedback_form extends \moodleform { */ public function definition() { global $questionnaire; - + // We need to get the number of current feedbacksections to allow the radar chart type or not. + global $DB; + $sid = $questionnaire->survey->id; + $sql = 'SELECT COUNT(*) ' . + 'FROM {questionnaire_fb_sections} ' . + 'WHERE surveyid = '.$sid; + $numfeedbacksections = $DB->count_records_sql($sql, [$sid]); $mform =& $this->_form; // Questionnaire Feedback Sections and Messages. @@ -71,30 +77,19 @@ public function definition() { $charttypes = [null => get_string('none'), 'bipolar' => get_string('chart:bipolar', 'questionnaire'), - 'hbar' => get_string('chart:hbar', 'questionnaire'), - 'rose' => get_string('chart:rose', 'questionnaire')]; - $chartgroup[] = $mform->createElement('select', 'chart_type_two_sections', - get_string('chart:type', 'questionnaire') . ' (' . - get_string('feedbackbysection', 'questionnaire') . ')', $charttypes); - if ($questionnaire->survey->feedbacksections > 1) { - $mform->setDefault('chart_type_two_sections', $questionnaire->survey->chart_type); + 'hbar' => get_string('chart:hbar', 'questionnaire')]; + // The rose and radar charttypes are only available if there are at least 3 feedback sections. + if ($numfeedbacksections > 2) { + $charttypes['rose'] = get_string('chart:rose', 'questionnaire'); + $charttypes['radar'] = get_string('chart:radar', 'questionnaire'); } - $mform->disabledIf('chart_type_two_sections', 'feedbacksections', 'neq', 2); - - $charttypes = [null => get_string('none'), - 'bipolar' => get_string('chart:bipolar', 'questionnaire'), - 'hbar' => get_string('chart:hbar', 'questionnaire'), - 'radar' => get_string('chart:radar', 'questionnaire'), - 'rose' => get_string('chart:rose', 'questionnaire')]; $chartgroup[] = $mform->createElement('select', 'chart_type_sections', get_string('chart:type', 'questionnaire') . ' (' . get_string('feedbackbysection', 'questionnaire') . ')', $charttypes); if ($questionnaire->survey->feedbacksections > 1) { $mform->setDefault('chart_type_sections', $questionnaire->survey->chart_type); } - $mform->disabledIf('chart_type_sections', 'feedbacksections', 'eq', 0); - $mform->disabledIf('chart_type_sections', 'feedbacksections', 'eq', 1); - $mform->disabledIf('chart_type_sections', 'feedbacksections', 'eq', 2); + $mform->disabledIf('chart_type_sections', 'feedbacksections', 'neq', 2); $mform->addGroup($chartgroup, 'chartgroup', get_string('chart:type', 'questionnaire'), null, false); diff --git a/feedback.php b/feedback.php index cf6c2f50..c1612892 100644 --- a/feedback.php +++ b/feedback.php @@ -115,8 +115,6 @@ if ($settings->feedbacksections == 1) { $sdata->chart_type = $settings->chart_type_global; } else if ($settings->feedbacksections == 2) { - $sdata->chart_type = $settings->chart_type_two_sections; - } else if ($settings->feedbacksections > 2) { $sdata->chart_type = $settings->chart_type_sections; } } From 5c480fb33ec9b5368b99b4234854023322103a78 Mon Sep 17 00:00:00 2001 From: emanoylov <80328987+emanoylov@users.noreply.github.com> Date: Tue, 4 Jul 2023 20:38:27 +0100 Subject: [PATCH 4/7] Questionnaire: More meaningful error than nopermissions (#488) Co-authored-by: Emanoil Manoylov --- lang/en/questionnaire.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lang/en/questionnaire.php b/lang/en/questionnaire.php index dce6e767..636e0d6c 100644 --- a/lang/en/questionnaire.php +++ b/lang/en/questionnaire.php @@ -672,3 +672,4 @@ $string['yourresponse'] = 'View your response(s)'; $string['yourresponses'] = 'View your response(s)'; $string['crontask'] = 'Questionnaire cleanup job'; +$string['nopermissions'] = 'Sorry, but you do not currently have permissions to view this page or perform this action.'; From d02ed3eabf93e7d2f277139af146f070be8915b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joseph=20R=C3=A9zeau?= Date: Thu, 6 Jul 2023 18:04:29 +0200 Subject: [PATCH 5/7] Revision 01 of PR #490 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Joseph Rézeau --- classes/feedback_form.php | 41 +++++++++++++++++++++++++------ classes/feedback_section_form.php | 7 ++++-- fbsections.php | 13 ++++++---- feedback.php | 2 ++ 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/classes/feedback_form.php b/classes/feedback_form.php index 62a7471a..2f2f6deb 100644 --- a/classes/feedback_form.php +++ b/classes/feedback_form.php @@ -36,13 +36,22 @@ class feedback_form extends \moodleform { */ public function definition() { global $questionnaire; - // We need to get the number of current feedbacksections to allow the radar chart type or not. + // We need to get the number of current feedbacksections to allow the rose and radar chart types or not. global $DB; $sid = $questionnaire->survey->id; $sql = 'SELECT COUNT(*) ' . 'FROM {questionnaire_fb_sections} ' . 'WHERE surveyid = '.$sid; $numfeedbacksections = $DB->count_records_sql($sql, [$sid]); + + // Get all questions that are valid feedback questions. + $nbvalidquestions = 0; + foreach ($questionnaire->questions as $question) { + if ($question->valid_feedback()) { + $nbvalidquestions++; + } + } + $mform =& $this->_form; // Questionnaire Feedback Sections and Messages. @@ -50,7 +59,9 @@ public function definition() { $feedbackoptions = []; $feedbackoptions[0] = get_string('feedbacknone', 'questionnaire'); $feedbackoptions[1] = get_string('feedbackglobal', 'questionnaire'); - $feedbackoptions[2] = get_string('feedbacksections', 'questionnaire'); + if ($nbvalidquestions > 1) { + $feedbackoptions[2] = get_string('feedbacksections', 'questionnaire'); + } $mform->addElement('select', 'feedbacksections', get_string('feedbackoptions', 'questionnaire'), $feedbackoptions); $mform->setDefault('feedbacksections', $questionnaire->survey->feedbacksections); @@ -62,6 +73,7 @@ public function definition() { // Is the RGraph library enabled at level site? if (get_config('questionnaire', 'usergraph')) { + /* First set up a Chart type group for the Global Feedback option. */ $chartgroup = []; $charttypes = [null => get_string('none'), 'bipolar' => get_string('chart:bipolar', 'questionnaire'), @@ -69,16 +81,21 @@ public function definition() { $chartgroup[] = $mform->createElement('select', 'chart_type_global', get_string('chart:type', 'questionnaire') . ' (' . get_string('feedbackglobal', 'questionnaire') . ')', $charttypes); + + // If we are editing an already saved questionnaire, and 'Feedback options' + // is set to 'Global Feedback', set default to its charttype. if ($questionnaire->survey->feedbacksections == 1) { $mform->setDefault('chart_type_global', $questionnaire->survey->chart_type); } - $mform->disabledIf('chart_type_global', 'feedbacksections', 'eq', 0); - $mform->disabledIf('chart_type_global', 'feedbacksections', 'neq', 1); + /* If 'Feedback options' is set to 'No Feedback messages' then hide the Global Feedback Chart type group. */ + $mform->hideIf('chart_type_global', 'feedbacksections', 'eq', 0); + + /* Now set up a Chart type group for the Feedback sections option. */ $charttypes = [null => get_string('none'), 'bipolar' => get_string('chart:bipolar', 'questionnaire'), 'hbar' => get_string('chart:hbar', 'questionnaire')]; - // The rose and radar charttypes are only available if there are at least 3 feedback sections. + /* If there are at least 3 feedback sections, make the rose and radar charttypes available. */ if ($numfeedbacksections > 2) { $charttypes['rose'] = get_string('chart:rose', 'questionnaire'); $charttypes['radar'] = get_string('chart:radar', 'questionnaire'); @@ -86,14 +103,23 @@ public function definition() { $chartgroup[] = $mform->createElement('select', 'chart_type_sections', get_string('chart:type', 'questionnaire') . ' (' . get_string('feedbackbysection', 'questionnaire') . ')', $charttypes); + + // If we are editing an already saved questionnaire, and 'Feedback options' + // is set to 'Feedback sections', set default to its charttype. if ($questionnaire->survey->feedbacksections > 1) { $mform->setDefault('chart_type_sections', $questionnaire->survey->chart_type); } - $mform->disabledIf('chart_type_sections', 'feedbacksections', 'neq', 2); + + /* If 'Feedback options' is NOT set to 'Feedback sections' then hide the 'Feedback sections' Chart type group. */ + $mform->hideIf('chart_type_sections', 'feedbacksections', 'neq', 2); + /* If 'Feedback options' is set to 'Feedback sections' then hide the Global Feedback Chart type group. */ + $mform->hideIf('chart_type_global', 'feedbacksections', 'eq', 2); $mform->addGroup($chartgroup, 'chartgroup', get_string('chart:type', 'questionnaire'), null, false); $mform->addHelpButton('chartgroup', 'chart:type', 'questionnaire'); + /* If 'Feedback options' is set to 'No Feedback messages' then completely hide the chartgroup group. */ + $mform->hideIf('chartgroup', 'feedbacksections', 'eq', 0); } $editoroptions = ['maxfiles' => EDITOR_UNLIMITED_FILES, 'trusttext' => true]; $mform->addElement('editor', 'feedbacknotes', get_string('feedbacknotes', 'questionnaire'), null, $editoroptions); @@ -109,8 +135,9 @@ public function definition() { $mform->setType('courseid', PARAM_RAW); // Can't seem to disable or hide one button in the group, so create two different button sets and hide one. + $submitlabel = get_string('savechangesanddisplay'); $buttongroup = []; - $buttongroup[] = $mform->createElement('submit', 'feedbacksettingsbutton1', get_string('savesettings', 'questionnaire')); + $buttongroup[] = $mform->createElement('submit', 'submitbutton', $submitlabel); $buttongroup[] = $mform->createElement('submit', 'feedbackeditbutton', get_string('feedbackeditsections', 'questionnaire')); $mform->addGroup($buttongroup, 'buttongroup'); if (moodle_major_version() == '3.3') { diff --git a/classes/feedback_section_form.php b/classes/feedback_section_form.php index 740d5604..e052fadf 100644 --- a/classes/feedback_section_form.php +++ b/classes/feedback_section_form.php @@ -170,10 +170,13 @@ public function definition() { $mform->setType('sectionid', PARAM_INT); // Buttons. + $submitlabelsaveanddisplay = get_string('savechangesanddisplay'); + $submitlabelreturntofeedbackoptions = get_string('feedbackoptions', 'questionnaire'); $buttonarray = []; - $buttonarray[] = $mform->createElement('submit', 'submitbutton', get_string('savechanges')); $buttonarray[] = $mform->createElement('submit', 'confirmdeletesection', get_string('deletesection', 'questionnaire')); - $buttonarray[] = $mform->createElement('cancel'); + $buttonarray[] = $mform->createElement('submit', 'submitbutton', get_string('savechanges')); + $buttonarray[] = $mform->createElement('submit', 'submitbutton1', $submitlabelreturntofeedbackoptions); + $buttonarray[] = $mform->createElement('submit', 'submitbutton2', $submitlabelsaveanddisplay); $mform->addGroup($buttonarray, 'buttonar', '', ' ', false); $mform->closeHeaderBefore('buttonar'); } diff --git a/fbsections.php b/fbsections.php index 13f3a8e7..c1146b6c 100644 --- a/fbsections.php +++ b/fbsections.php @@ -131,10 +131,6 @@ $feedbackform->set_data($sdata); -if ($feedbackform->is_cancelled()) { - redirect(new moodle_url('/mod/questionnaire/feedback.php', ['id' => $cm->id])); -} - if ($settings = $feedbackform->get_data()) { // Because formslib doesn't support 'numeric' or 'image' inputs, the results won't show up in the $feedbackform object. $fullform = data_submitted(); @@ -177,7 +173,7 @@ // Update the section with question weights. $feedbacksection->set_new_scorecalculation($scorecalculation); - } else if (isset($settings->submitbutton)) { + } else if (isset($settings->submitbutton ) || isset($settings->submitbutton1) || isset($settings->submitbutton2)) { if (isset($fullform->weight)) { $feedbacksection->scorecalculation = $fullform->weight; } else { @@ -238,7 +234,14 @@ // Update all feedback data. $feedbacksection->update(); + if (isset($settings->submitbutton1)) { + redirect(new moodle_url('/mod/questionnaire/feedback.php', ['id' => $cm->id])); + } + if (isset($settings->submitbutton2)) { + redirect(new moodle_url('/mod/questionnaire/view.php', ['id' => $cm->id])); + } } + $feedbackform = new \mod_questionnaire\feedback_section_form('fbsections.php', $customdata); } diff --git a/feedback.php b/feedback.php index c1612892..96516efa 100644 --- a/feedback.php +++ b/feedback.php @@ -142,6 +142,8 @@ $feedbacksection = mod_questionnaire\feedback\section::new_section($questionnaire->sid, $sectionlabel); } redirect(new moodle_url('/mod/questionnaire/fbsections.php', ['id' => $cm->id, 'section' => $firstsection])); + } else { + redirect('view.php?id='.$cm->id); } } From fdd4e40980984792b8aa82dc19ca3aac9339259d Mon Sep 17 00:00:00 2001 From: rezeau Date: Mon, 25 Sep 2023 12:03:21 +0200 Subject: [PATCH 6/7] fixed module.js (for MOODLE_STABLE_401) Signed-off-by: rezeau --- module.js | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/module.js b/module.js index 9eb3e93d..1c8d0070 100644 --- a/module.js +++ b/module.js @@ -267,15 +267,22 @@ M.mod_questionnaire.init_sendmessage = function(Y) { }; M.mod_questionnaire.init_slider = function() { - const allRanges = document.querySelectorAll(".slider"); + const allRanges = document.querySelectorAll(".question-slider"); allRanges.forEach(wrap => { const range = wrap.querySelector("input.questionnaire-slider"); const bubble = wrap.querySelector(".bubble"); + const labels = { + leftlabel: wrap.querySelector(".left-side-label"), + middlelabel: wrap.querySelector(".middle-side-label"), + rightlabel: wrap.querySelector(".right-side-label") + }; range.addEventListener("input", () => { setBubble(range, bubble); + createAccessibilityHeading(range, bubble, labels); }); setBubble(range, bubble); + createAccessibilityHeading(range, bubble, labels); }); function setBubble(range, bubble) { @@ -296,4 +303,85 @@ M.mod_questionnaire.init_slider = function() { // Sorta magic numbers based on size of the native UI thumb bubble.style.left = `calc(${newVal}% + (${8 - newVal * 0.15}px))`; } + + /** + * Adds accessibility support by generating an h2 element with relevant text. + * @param {HTMLElement} range - The range input element. + * @param {HTMLElement} bubble - The bubble element. + * @param {Object} labels - The object containing label elements. + */ + function createAccessibilityHeading(range, bubble, labels) { + const min = range.min ? range.min : 0; + const max = range.max ? range.max : 100; + const step = range.step ? range.step : 1; + const centerValues = calculateCenterValues(range); + + const accesshideElement = document.createElement('h2'); + accesshideElement.classList.add('accesshide'); + + const a = { + min, + max, + leftlabel: labels.leftlabel.innerHTML, + rightlabel: labels.rightlabel.innerHTML, + middlelabel: labels.middlelabel.innerHTML, + centreval: centerValues[0], + centreval1: centerValues[0], + centreval2: centerValues[1], + }; + + const rangeNum = max - min; + const numSteps = rangeNum / step; + + const middleLabel = (numSteps % 2 !== 0) + ? (labels.middlelabel.innerHTML + ? M.util.get_string('middlepartwithtwovalues', 'questionnaire', a) + : M.util.get_string('middlepartwithtwovaluesdefault', 'questionnaire', a)) + : (labels.middlelabel.innerHTML + ? M.util.get_string('middlepart', 'questionnaire', a) + : M.util.get_string('middlepartdefault', 'questionnaire', a)); + + const leftPart = labels.leftlabel.innerHTML ? M.util.get_string('leftpart', 'questionnaire', a) + : M.util.get_string('leftpartdefault', 'questionnaire', a); + + const middlePart = middleLabel ? middleLabel : ''; + + const rightPart = labels.rightlabel.innerHTML + ? M.util.get_string('rightpart', 'questionnaire', a) : M.util.get_string('rightpartdefault', 'questionnaire', a); + + // Include a whitespace to accommodate a setting of the NVDA screen reader. + const whitespace = '\xa0'; + accesshideElement.textContent = whitespace + M.util.get_string('where', 'questionnaire', a) + leftPart + middlePart + rightPart; + bubble.appendChild(accesshideElement); + } + + /** + * Calculates the center value(s) based on the given range. + * @param {Object} range - The range object containing properties: min, max, step. + * @returns {Array} - An array containing the center value(s). + */ + function calculateCenterValues(range) { + const min = parseInt(range.min); + const max = parseInt(range.max); + const step = parseInt(range.step); + const rangeNum = max - min; + + // Calculate the number of steps. + const numSteps = rangeNum / step; + + // Calculate the center value(s). + const centerValues = []; + if (numSteps % 2 === 0) { + // Even number of steps, return single center value. + const center = (min + max) / 2; + centerValues.push(center); + } else { + // Odd number of steps, calculate lower and upper center values. + const lowerCenter = min + Math.floor(numSteps / 2) * step; + const upperCenter = lowerCenter + step; + centerValues.push(lowerCenter, upperCenter); + } + + return centerValues; + } }; From 2f49bee2ec440d4884190c93b5032a694e3c6b53 Mon Sep 17 00:00:00 2001 From: rezeau Date: Mon, 25 Sep 2023 16:10:12 +0200 Subject: [PATCH 7/7] rebased to to MOODLE_401_STABLE Signed-off-by: rezeau