MDL-84487 mod_quiz: Use modal form for editing random questions
Creating and editing random questions were using 2 different forms - one dynamic form in a modal, and the other a regular form on a standalone page. The "Switch bank" UI only works in a modal, so while it was displayed on the edit page, it didn't function. This combines the editing functionality with the existing modal form, so the same UI can be used for both operations, and the "Switch bank" functionality works.
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -40,7 +40,9 @@ const SELECTORS = {
|
||||
ADD_ON_PAGE_FORM_ELEMENT: '[name="addonpage"]',
|
||||
ADD_RANDOM_BUTTON: 'input[type="submit"][name="addrandom"]',
|
||||
ADD_NEW_CATEGORY_BUTTON: 'input[type="submit"][name="newcategory"]',
|
||||
SUBMIT_BUTTON_ELEMENT: 'input[type="submit"][name="addrandom"], input[type="submit"][name="newcategory"]',
|
||||
SUBMIT_BUTTON_ELEMENT: 'input[type="submit"][name="addrandom"], '
|
||||
+ 'input[type="submit"][name="newcategory"], '
|
||||
+ 'input[type="submit"][name="update"]',
|
||||
FORM_HEADER: 'legend',
|
||||
SELECT_NUMBER_TO_ADD: '#menurandomcount',
|
||||
NEW_CATEGORY_ELEMENT: '#categoryname',
|
||||
@@ -52,6 +54,7 @@ const SELECTORS = {
|
||||
NEW_BANKMOD_ID: 'data-newmodid',
|
||||
BANK_SEARCH: '#searchbanks',
|
||||
GO_BACK_BUTTON: 'button[data-action="go-back"]',
|
||||
UPDATE_FILTER_BUTTON: 'input[type="submit"][name="update"]',
|
||||
};
|
||||
|
||||
export default class ModalAddRandomQuestion extends Modal {
|
||||
@@ -76,7 +79,7 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
quizCmId,
|
||||
showNewCategory = true
|
||||
) {
|
||||
const selector = '.menu [data-action="addarandomquestion"]';
|
||||
const selector = '.menu [data-action="addarandomquestion"], [data-action="editrandomquestion"]';
|
||||
document.addEventListener('click', (e) => {
|
||||
const trigger = e.target.closest(selector);
|
||||
if (!trigger) {
|
||||
@@ -84,6 +87,10 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
if (trigger.dataset.slotid) {
|
||||
showNewCategory = false;
|
||||
}
|
||||
|
||||
ModalAddRandomQuestion.create({
|
||||
contextId,
|
||||
bankCmId,
|
||||
@@ -93,7 +100,7 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
showNewCategory,
|
||||
title: trigger.dataset.header,
|
||||
addOnPage: trigger.dataset.addonpage,
|
||||
|
||||
slotId: trigger.dataset.slotid,
|
||||
templateContext: {
|
||||
hidden: showNewCategory,
|
||||
},
|
||||
@@ -112,6 +119,8 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
this.returnUrl = null;
|
||||
this.quizCmId = null;
|
||||
this.loadedForm = false;
|
||||
this.slotId = 0;
|
||||
this.savedFilterCondition = null;
|
||||
}
|
||||
|
||||
configure(modalConfig) {
|
||||
@@ -120,6 +129,8 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
this.setCategory(modalConfig.category);
|
||||
this.setReturnUrl(modalConfig.returnUrl);
|
||||
this.showNewCategory = modalConfig.showNewCategory;
|
||||
this.setSlotId(modalConfig.slotId ?? 0);
|
||||
this.setSavedFilterCondition(modalConfig.savedFilterCondition ?? null);
|
||||
|
||||
super.configure(modalConfig);
|
||||
}
|
||||
@@ -177,6 +188,42 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
return this.returnUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ID of the quiz slot, if we are editing an existing random question.
|
||||
*
|
||||
* @param {Number} slotId
|
||||
*/
|
||||
setSlotId(slotId) {
|
||||
this.slotId = slotId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current slot ID.
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
getSlotId() {
|
||||
return this.slotId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the current filterCondition JSON string.
|
||||
*
|
||||
* @param {String} filterCondition
|
||||
*/
|
||||
setSavedFilterCondition(filterCondition) {
|
||||
this.savedFilterCondition = filterCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the saved filterCondition JSON string.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
getSavedFilterCondition() {
|
||||
return this.savedFilterCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a given form element inside (a child of) a given tab element.
|
||||
*
|
||||
@@ -239,29 +286,35 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
const returnurl = this.getReturnUrl();
|
||||
const quizcmid = this.quizCmId;
|
||||
const bankcmid = this.bankCmId;
|
||||
const savedfiltercondition = this.getSavedFilterCondition();
|
||||
this.setSavedFilterCondition(null);
|
||||
|
||||
return Fragment.loadFragment(
|
||||
'mod_quiz',
|
||||
'add_random_question_form',
|
||||
this.getContextId(),
|
||||
{
|
||||
addonpage,
|
||||
addonpage: addonpage ?? null,
|
||||
returnurl,
|
||||
quizcmid,
|
||||
bankcmid,
|
||||
slotid: this.getSlotId(),
|
||||
savedfiltercondition,
|
||||
}
|
||||
)
|
||||
.then((html, js) => {
|
||||
const form = $(html);
|
||||
const existingCategoryTabContent = form.find(SELECTORS.EXISTING_CATEGORY_TAB);
|
||||
const existingCategoryTab = this.getBody().find(SELECTORS.EXISTING_CATEGORY_CONTAINER);
|
||||
const newCategoryTabContent = form.find(SELECTORS.NEW_CATEGORY_TAB);
|
||||
const newCategoryTab = this.getBody().find(SELECTORS.NEW_CATEGORY_CONTAINER);
|
||||
if (!this.getSlotId()) {
|
||||
const existingCategoryTabContent = form.find(SELECTORS.EXISTING_CATEGORY_TAB);
|
||||
const existingCategoryTab = this.getBody().find(SELECTORS.EXISTING_CATEGORY_CONTAINER);
|
||||
const newCategoryTabContent = form.find(SELECTORS.NEW_CATEGORY_TAB);
|
||||
const newCategoryTab = this.getBody().find(SELECTORS.NEW_CATEGORY_CONTAINER);
|
||||
|
||||
// Transform the form into tabs for better rendering in the modal.
|
||||
this.moveContentIntoTab(existingCategoryTabContent, existingCategoryTab);
|
||||
this.moveContentIntoTab(newCategoryTabContent, newCategoryTab);
|
||||
this.moveTabsIntoTabContent(form);
|
||||
// Transform the form into tabs for better rendering in the modal.
|
||||
this.moveContentIntoTab(existingCategoryTabContent, existingCategoryTab);
|
||||
this.moveContentIntoTab(newCategoryTabContent, newCategoryTab);
|
||||
this.moveTabsIntoTabContent(form);
|
||||
}
|
||||
|
||||
Templates.replaceNode(this.getBody().find(SELECTORS.TAB_CONTENT), form, js);
|
||||
return;
|
||||
@@ -291,6 +344,13 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
this.addQuestions(quizcmid, addonpage, randomcount, filtercondition, '', '');
|
||||
return;
|
||||
}
|
||||
// Update the filter condition for the slot if the update button was clicked.
|
||||
const updateFilterButton = e.target.closest(SELECTORS.UPDATE_FILTER_BUTTON);
|
||||
if (updateFilterButton) {
|
||||
const filtercondition = document.querySelector(SELECTORS.FILTER_CONDITION_ELEMENT).dataset?.filtercondition;
|
||||
this.updateFilterCondition(quizcmid, this.getSlotId(), filtercondition);
|
||||
return;
|
||||
}
|
||||
// Add new category if the add category button was clicked.
|
||||
const addCategoryButton = e.target.closest(SELECTORS.ADD_NEW_CATEGORY_BUTTON);
|
||||
if (addCategoryButton) {
|
||||
@@ -307,6 +367,9 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
});
|
||||
|
||||
this.getModal().on('click', SELECTORS.SWITCH_TO_OTHER_BANK, () => {
|
||||
this.setSavedFilterCondition(
|
||||
document.querySelector(SELECTORS.FILTER_CONDITION_ELEMENT).dataset?.filtercondition
|
||||
);
|
||||
this.handleSwitchBankContentReload(SELECTORS.BANK_SEARCH)
|
||||
.then(function(ModalQuizQuestionBank) {
|
||||
$(SELECTORS.BANK_SEARCH)?.on('change', (e) => {
|
||||
@@ -323,6 +386,7 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
'addOnPage': ModalQuizQuestionBank.getAddOnPageId(),
|
||||
'templateContext': {hidden: ModalQuizQuestionBank.showNewCategory},
|
||||
'showNewCategory': ModalQuizQuestionBank.showNewCategory,
|
||||
'slotId': ModalQuizQuestionBank.getSlotId(),
|
||||
})
|
||||
.then(ModalQuizQuestionBank.destroy())
|
||||
.catch(Notification.exception);
|
||||
@@ -345,6 +409,8 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
'addOnPage': this.getAddOnPageId(),
|
||||
'templateContext': {hidden: this.showNewCategory},
|
||||
'showNewCategory': this.showNewCategory,
|
||||
'savedFilterCondition': this.getSavedFilterCondition(),
|
||||
'slotId': this.getSlotId(),
|
||||
}).then(this.destroy()).catch(Notification.exception);
|
||||
});
|
||||
|
||||
@@ -362,6 +428,7 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
'addOnPage': this.getAddOnPageId(),
|
||||
'templateContext': {hidden: this.showNewCategory},
|
||||
'showNewCategory': this.showNewCategory,
|
||||
'slotId': this.getSlotId(),
|
||||
}).then(this.destroy()).catch(Notification.exception);
|
||||
}
|
||||
});
|
||||
@@ -411,6 +478,39 @@ export default class ModalAddRandomQuestion extends Modal {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call web service function to update the filter condition for an existing slot.
|
||||
*
|
||||
* @param {number} quizcmid the course module id of the quiz.
|
||||
* @param {number} slotid The slot the random question is in.
|
||||
* @param {string} filtercondition The new filter condition.
|
||||
*/
|
||||
async updateFilterCondition(
|
||||
quizcmid,
|
||||
slotid,
|
||||
filtercondition,
|
||||
) {
|
||||
// We do not need to resolve this Pending because the form submission will result in a page redirect.
|
||||
new Pending('mod-quiz/modal_add_random_questions');
|
||||
const call = {
|
||||
methodname: 'mod_quiz_update_filter_condition',
|
||||
args: {
|
||||
cmid: quizcmid,
|
||||
slotid,
|
||||
filtercondition,
|
||||
}
|
||||
};
|
||||
try {
|
||||
const response = await fetchMany([call])[0];
|
||||
const form = document.querySelector(SELECTORS.FORM_ELEMENT);
|
||||
const messageInput = form.querySelector(SELECTORS.MESSAGE_INPUT);
|
||||
messageInput.value = response.message;
|
||||
form.submit();
|
||||
} catch (e) {
|
||||
Notification.exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the modal show function to load the form when this modal is first
|
||||
* shown.
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Defines the editing form for random questions.
|
||||
*
|
||||
* @package mod_quiz
|
||||
* @copyright 2018 Shamim Rezaie <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace mod_quiz\form;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot.'/lib/formslib.php');
|
||||
|
||||
/**
|
||||
* Class randomquestion_form
|
||||
*
|
||||
* @package mod_quiz
|
||||
* @copyright 2018 Shamim Rezaie <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class randomquestion_form extends \moodleform {
|
||||
|
||||
/**
|
||||
* Form definiton.
|
||||
*/
|
||||
public function definition() {
|
||||
$mform = $this->_form;
|
||||
|
||||
$contexts = $this->_customdata['contexts'];
|
||||
$usablecontexts = $contexts->having_cap('moodle/question:useall');
|
||||
|
||||
// Standard fields at the start of the form.
|
||||
$mform->addElement('header', 'generalheader', get_string("general", 'form'));
|
||||
|
||||
$mform->addElement('questioncategory', 'category', get_string('category', 'question'),
|
||||
['contexts' => $usablecontexts, 'top' => true]);
|
||||
|
||||
$mform->addElement('advcheckbox', 'includesubcategories', get_string('recurse', 'quiz'), null, null, [0, 1]);
|
||||
|
||||
$tops = question_get_top_categories_for_contexts(array_column($contexts->all(), 'id'));
|
||||
$mform->hideIf('includesubcategories', 'category', 'in', $tops);
|
||||
|
||||
$tags = \core_tag_tag::get_tags_by_area_in_contexts('core_question', 'question', $usablecontexts);
|
||||
$tagstrings = [];
|
||||
foreach ($tags as $tag) {
|
||||
$tagstrings["{$tag->id},{$tag->name}"] = $tag->name;
|
||||
}
|
||||
$options = [
|
||||
'multiple' => true,
|
||||
'noselectionstring' => get_string('anytags', 'quiz'),
|
||||
];
|
||||
$mform->addElement('autocomplete', 'fromtags', get_string('randomquestiontags', 'mod_quiz'), $tagstrings, $options);
|
||||
$mform->addHelpButton('fromtags', 'randomquestiontags', 'mod_quiz');
|
||||
|
||||
$mform->addElement('hidden', 'slotid');
|
||||
$mform->setType('slotid', PARAM_INT);
|
||||
|
||||
$mform->addElement('hidden', 'returnurl');
|
||||
$mform->setType('returnurl', PARAM_LOCALURL);
|
||||
|
||||
$buttonarray = [];
|
||||
$buttonarray[] = $mform->createElement('submit', 'submitbutton', get_string('savechanges'));
|
||||
$buttonarray[] = $mform->createElement('cancel');
|
||||
$mform->addGroup($buttonarray, 'buttonar', '', [' '], false);
|
||||
$mform->closeHeaderBefore('buttonar');
|
||||
}
|
||||
|
||||
public function set_data($defaultvalues) {
|
||||
$mform = $this->_form;
|
||||
|
||||
if ($defaultvalues->fromtags) {
|
||||
$fromtagselement = $mform->getElement('fromtags');
|
||||
foreach ($defaultvalues->fromtags as $fromtag) {
|
||||
if (!$fromtagselement->optionExists($fromtag)) {
|
||||
$optionname = get_string('randomfromunavailabletag', 'mod_quiz', explode(',', $fromtag)[1]);
|
||||
$fromtagselement->addOption($optionname, $fromtag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent::set_data($defaultvalues);
|
||||
}
|
||||
}
|
||||
@@ -1104,10 +1104,7 @@ class edit_renderer extends \plugin_renderer_base {
|
||||
*/
|
||||
public function random_question(structure $structure, $slotnumber, $pageurl) {
|
||||
$question = $structure->get_question_in_slot($slotnumber);
|
||||
$bankcontext = \context::instance_by_id($question->contextid);
|
||||
$slot = $structure->get_slot_by_number($slotnumber);
|
||||
$editurl = new \moodle_url('/mod/quiz/editrandom.php',
|
||||
['returnurl' => $pageurl->out_as_local_url(), 'slotid' => $slot->id, 'bankcmid' => $bankcontext->instanceid]);
|
||||
|
||||
$temp = clone($question);
|
||||
$temp->questiontext = '';
|
||||
@@ -1138,8 +1135,17 @@ class edit_renderer extends \plugin_renderer_base {
|
||||
$qbanklink = ' ' . \html_writer::link($qbankurl,
|
||||
get_string('seequestions', 'quiz'), ['class' => 'mod_quiz_random_qbank_link']);
|
||||
|
||||
return html_writer::link($editurl, $icon . $editicon, ['title' => $configuretitle]) .
|
||||
' ' . $instancename . ' ' . $qbanklink;
|
||||
$editlink = html_writer::link(
|
||||
$pageurl->out(),
|
||||
$icon . $editicon,
|
||||
[
|
||||
'title' => $configuretitle,
|
||||
'data-action' => 'editrandomquestion',
|
||||
'data-slotid' => $slot->id,
|
||||
'data-header' => get_string('randomediting', 'mod_quiz'),
|
||||
],
|
||||
);
|
||||
return $editlink . ' ' . $instancename . ' ' . $qbanklink;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Page for editing random questions.
|
||||
*
|
||||
* @package mod_quiz
|
||||
* @copyright 2018 Shamim Rezaie <[email protected]>
|
||||
* @author 2021 Safat Shahin <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
use core_question\local\bank\filter_condition_manager;
|
||||
use core_question\question_reference_manager;
|
||||
use mod_quiz\quiz_settings;
|
||||
use mod_quiz\question\bank\random_question_view;
|
||||
|
||||
require_once(__DIR__ . '/../../config.php');
|
||||
require_once($CFG->dirroot . '/mod/quiz/locallib.php');
|
||||
require_once($CFG->dirroot . '/mod/quiz/lib.php');
|
||||
|
||||
$slotid = required_param('slotid', PARAM_INT);
|
||||
$bankcmid = required_param('bankcmid', PARAM_INT);
|
||||
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
|
||||
|
||||
// Get the quiz slot.
|
||||
$slot = $DB->get_record('quiz_slots', ['id' => $slotid], '*', MUST_EXIST);
|
||||
$quizobj = quiz_settings::create($slot->quizid);
|
||||
$quiz = $quizobj->get_quiz();
|
||||
$cm = $quizobj->get_cm();
|
||||
$course = $quizobj->get_course();
|
||||
|
||||
require_login($course, false, $cm);
|
||||
|
||||
if ($returnurl) {
|
||||
$returnurl = new moodle_url($returnurl);
|
||||
} else {
|
||||
$returnurl = new moodle_url('/mod/quiz/edit.php', ['cmid' => $cm->id]);
|
||||
}
|
||||
|
||||
$url = new moodle_url('/mod/quiz/editrandom.php', ['slotid' => $slotid]);
|
||||
$PAGE->set_url($url);
|
||||
$PAGE->set_pagelayout('admin');
|
||||
$PAGE->add_body_class('limitedwidth');
|
||||
|
||||
$setreference = $DB->get_record('question_set_references',
|
||||
['itemid' => $slot->id, 'component' => 'mod_quiz', 'questionarea' => 'slot']);
|
||||
$filterconditions = json_decode($setreference->filtercondition, true);
|
||||
$filterconditions = question_reference_manager::convert_legacy_set_reference_filter_condition($filterconditions);
|
||||
$filterconditions = filter_condition_manager::filter_invalid_values($filterconditions);
|
||||
|
||||
$params = $filterconditions;
|
||||
$params['cmid'] = $cm->id;
|
||||
$extraparams['view'] = random_question_view::class;
|
||||
$extraparams['requirebankswitch'] = false;
|
||||
$extraparams['quizcmid'] = $quizobj->get_cm()->id;
|
||||
|
||||
// Build required parameters.
|
||||
[$contexts, $thispageurl, $cm, $pagevars, $extraparams] = build_required_parameters_for_custom_view($params, $extraparams);
|
||||
|
||||
$thiscontext = context_module::instance($bankcmid);
|
||||
$contexts = new core_question\local\bank\question_edit_contexts($thiscontext);
|
||||
|
||||
// Create the editing form.
|
||||
$mform = new mod_quiz\form\randomquestion_form(new moodle_url('/mod/quiz/editrandom.php'), ['contexts' => $contexts]);
|
||||
|
||||
// Set the form data.
|
||||
$toform = new stdClass();
|
||||
$toform->category = $filterconditions['filter']['category']['values'][0];
|
||||
$includesubcategories = false;
|
||||
if (!empty($filterconditions['filter']['category']['filteroptions']['includesubcategories'])) {
|
||||
$includesubcategories = true;
|
||||
}
|
||||
$toform->includesubcategories = $includesubcategories;
|
||||
$toform->fromtags = [];
|
||||
if (isset($filterconditions['tags'])) {
|
||||
$currentslottags = $filterconditions['tags'];
|
||||
foreach ($currentslottags as $slottag) {
|
||||
$toform->fromtags[] = $slottag;
|
||||
}
|
||||
}
|
||||
|
||||
$toform->returnurl = $returnurl;
|
||||
$toform->slotid = $slot->id;
|
||||
if ($cm !== null) {
|
||||
$toform->cmid = $cm->id;
|
||||
$toform->courseid = $cm->course;
|
||||
} else {
|
||||
$toform->courseid = $COURSE->id;
|
||||
}
|
||||
|
||||
$mform->set_data($toform);
|
||||
|
||||
if ($mform->is_cancelled()) {
|
||||
redirect($returnurl);
|
||||
} else if ($fromform = $mform->get_data()) {
|
||||
list($newcatid, $newcontextid) = explode(',', $fromform->category);
|
||||
if ($newcatid != $category->id) {
|
||||
$contextid = $newcontextid;
|
||||
} else {
|
||||
$contextid = $category->contextid;
|
||||
}
|
||||
$setreference->questionscontextid = $contextid;
|
||||
|
||||
// Set the filter conditions.
|
||||
$filtercondition = new stdClass();
|
||||
$filtercondition->questioncategoryid = $newcatid;
|
||||
$filtercondition->includingsubcategories = $fromform->includesubcategories;
|
||||
|
||||
if (isset($fromform->fromtags)) {
|
||||
$tags = [];
|
||||
foreach ($fromform->fromtags as $tagstring) {
|
||||
list($tagid, $tagname) = explode(',', $tagstring);
|
||||
$tags[] = "{$tagid},{$tagname}";
|
||||
}
|
||||
if (!empty($tags)) {
|
||||
$filtercondition->tags = $tags;
|
||||
}
|
||||
}
|
||||
|
||||
$setreference->filtercondition = json_encode($filtercondition);
|
||||
$DB->update_record('question_set_references', $setreference);
|
||||
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
$heading = get_string('randomediting', 'mod_quiz');
|
||||
$PAGE->set_title($heading);
|
||||
$PAGE->set_heading($COURSE->fullname);
|
||||
$PAGE->navbar->add($heading);
|
||||
|
||||
// Custom View.
|
||||
$questionbank = new random_question_view($contexts, $thispageurl, $course, $cm, $params, $extraparams);
|
||||
|
||||
// Output.
|
||||
$renderer = $PAGE->get_renderer('mod_quiz', 'edit');
|
||||
$data = new \stdClass();
|
||||
$data->questionbank = $renderer->question_bank_contents($questionbank, $params);
|
||||
$data->cmid = $cm->id;
|
||||
$data->slotid = $slot->id;
|
||||
$data->returnurl = $returnurl;
|
||||
$updateform = $OUTPUT->render_from_template('mod_quiz/update_filter_condition_form', $data);
|
||||
$PAGE->requires->js_call_amd('mod_quiz/update_random_question_filter_condition', 'init');
|
||||
|
||||
// Display a heading, question editing form.
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading_with_help($heading, 'randomquestion', 'mod_quiz');
|
||||
echo $updateform;
|
||||
echo $OUTPUT->footer();
|
||||
+24
-2
@@ -2386,7 +2386,26 @@ function mod_quiz_output_fragment_switch_question_bank($args): string {
|
||||
* @return string The rendered mform fragment.
|
||||
*/
|
||||
function mod_quiz_output_fragment_add_random_question_form($args) {
|
||||
global $PAGE, $OUTPUT;
|
||||
global $PAGE, $OUTPUT, $DB;
|
||||
|
||||
$slotid = clean_param($args['slotid'] ?? 0, PARAM_INT);
|
||||
if (empty($slotid)) {
|
||||
$params = $args;
|
||||
} else {
|
||||
// Load the stored filters for the current slot.
|
||||
$setreference = $DB->get_record('question_set_references',
|
||||
['itemid' => $slotid, 'component' => 'mod_quiz', 'questionarea' => 'slot']);
|
||||
$filterconditions = json_decode($setreference->filtercondition, true);
|
||||
$filterconditions = \core_question\question_reference_manager::convert_legacy_set_reference_filter_condition(
|
||||
$filterconditions,
|
||||
);
|
||||
$params = \core_question\local\bank\filter_condition_manager::filter_invalid_values($filterconditions);
|
||||
}
|
||||
|
||||
if (!empty($args['savedfiltercondition'])) {
|
||||
$filtercondition = json_decode($args['savedfiltercondition'], true);
|
||||
$params['filter'] = $filtercondition['filter'];
|
||||
}
|
||||
|
||||
$extraparams = [];
|
||||
$extraparams['quizcmid'] = clean_param($args['quizcmid'], PARAM_INT);
|
||||
@@ -2394,7 +2413,7 @@ function mod_quiz_output_fragment_add_random_question_form($args) {
|
||||
|
||||
// Build required parameters.
|
||||
[$contexts, $thispageurl, $cm, $pagevars, $extraparams] =
|
||||
build_required_parameters_for_custom_view($args, $extraparams);
|
||||
build_required_parameters_for_custom_view($params, $extraparams);
|
||||
|
||||
// Additional param to differentiate with other question bank view.
|
||||
$extraparams['view'] = mod_quiz\question\bank\random_question_view::class;
|
||||
@@ -2432,6 +2451,9 @@ function mod_quiz_output_fragment_add_random_question_form($args) {
|
||||
'randomoptions' => $randomcount,
|
||||
'questioncategoryoptions' => $catoptions,
|
||||
];
|
||||
if (!empty($slotid)) {
|
||||
$data['slotid'] = $slotid;
|
||||
}
|
||||
|
||||
$helpicon = new \help_icon('parentcategory', 'question');
|
||||
$data['questioncategoryhelp'] = $helpicon->export_for_template($renderer);
|
||||
|
||||
@@ -52,11 +52,14 @@
|
||||
<div class="mt-2 position-relative" data-region="add_random_question_form-container">
|
||||
<form action="{{returnurl}}" method="POST" id="add_random_question_form" class="mform">
|
||||
<fieldset id="id_existingcategoryheader">
|
||||
{{^slotid}}
|
||||
<legend>{{#str}} randomfromexistingcategory, mod_quiz {{/str}}</legend>
|
||||
{{/slotid}}
|
||||
<!-- Question bank -->
|
||||
{{{questionbank}}}
|
||||
|
||||
<!-- Select number of random question -->
|
||||
{{^slotid}}
|
||||
<label>
|
||||
{{#str}}randomnumber, mod_quiz{{/str}}
|
||||
<select id="menurandomcount" name="randomcount" class="form-control form-select">
|
||||
@@ -65,16 +68,24 @@
|
||||
{{/randomoptions}}
|
||||
</select>
|
||||
</label>
|
||||
{{/slotid}}
|
||||
|
||||
<!-- Buttons -->
|
||||
<!-- Buttons -->
|
||||
<div class="modal-footer mt-1" data-region="footer">
|
||||
<input type="hidden" name="message" value="">
|
||||
<input type="submit" class="btn btn-primary" name="addrandom" value="{{#str}} addrandomquestion, mod_quiz {{/str}}">
|
||||
{{#slotid}}
|
||||
<input name="slotid" type="hidden" value="{{slotid}}"/>
|
||||
<input type="submit" class="btn btn-primary" name="update" value="{{#str}} updatefilterconditon, mod_quiz {{/str}}">
|
||||
{{/slotid}}
|
||||
{{^slotid}}
|
||||
<input type="submit" class="btn btn-primary" name="addrandom" value="{{#str}} addrandomquestion, mod_quiz {{/str}}">
|
||||
{{/slotid}}
|
||||
<input type="submit" class="btn btn-secondary" name="cancel" value="{{#str}} cancel {{/str}}">
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
||||
{{^slotid}}
|
||||
<fieldset id="id_newcategoryheader">
|
||||
<legend>{{#str}} randomquestionusinganewcategory, mod_quiz {{/str}}</legend>
|
||||
<!-- New categoryname -->
|
||||
@@ -114,5 +125,6 @@
|
||||
<input type="submit" class="btn btn-secondary" name="cancel" value="{{#str}} cancel {{/str}}">
|
||||
</div>
|
||||
</fieldset>
|
||||
{{/slotid}}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -102,6 +102,7 @@ Feature: Adding random questions to a quiz based on category and tags
|
||||
And I should see "foo"
|
||||
And I should see "question 1 name"
|
||||
And I should see "\"listen\" & \"answer\""
|
||||
And I click on "Cancel" "button" in the "Editing a random question" "dialogue"
|
||||
# Include subcategories.
|
||||
And I navigate to "Questions" in current page administration
|
||||
And I open the "Page 1" add to quiz menu
|
||||
|
||||
@@ -15,22 +15,26 @@ Feature: Editing random questions already in a quiz based on category and tags
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "activities" exist:
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 for testing the Add random question form | C1 | quiz1 |
|
||||
| activity | name | intro | course | idnumber |
|
||||
| quiz | Quiz 1 | Quiz 1 for testing the Add random question form | C1 | quiz1 |
|
||||
| qbank | Qbank 1 | Qbank 1 for testing the Edit random question form | C1 | qbank1 |
|
||||
And the following "question categories" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | quiz1 | Questions Category 1|
|
||||
| Activity module | quiz1 | Questions Category 2|
|
||||
| Activity module | qbank1 | Questions Category 3|
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | user | questiontext |
|
||||
| Questions Category 1 | essay | question 1 name | admin | Question 1 text |
|
||||
| Questions Category 1 | essay | question 2 name | teacher1 | Question 2 text |
|
||||
| Questions Category 3 | essay | question 3 name | teacher1 | Question 3 text |
|
||||
And the following "core_question > Tags" exist:
|
||||
| question | tag |
|
||||
| question 1 name | easy |
|
||||
| question 1 name | essay |
|
||||
| question 2 name | hard |
|
||||
| question 2 name | essay |
|
||||
| question 3 name | essay |
|
||||
|
||||
Scenario: Editing tags on one slot does not delete the rest
|
||||
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
|
||||
@@ -52,3 +56,32 @@ Feature: Editing random questions already in a quiz based on category and tags
|
||||
And I should see "Random (Questions Category 1) based on filter condition with tags: hard" on quiz page "2"
|
||||
And I click on "Configure question" "link" in the "Random (Questions Category 1) based on filter condition with tags: hard" "list_item"
|
||||
And "hard" "autocomplete_selection" should be visible
|
||||
|
||||
Scenario: Switch banks when editing a random question
|
||||
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
|
||||
And I open the "last" add to quiz menu
|
||||
And I follow "a random question"
|
||||
And I apply question bank filter "Tag" with value "essay"
|
||||
And I press "Add random question"
|
||||
When I click on "Configure question" "link" in the "Random (Questions Category 1) based on filter condition with tags: essay" "list_item"
|
||||
And I press "Switch bank"
|
||||
And I click on "Qbank 1" "link" in the "Select question bank" "dialogue"
|
||||
And the field "filter-value-qtagids" matches value "essay"
|
||||
And I apply question bank filter "Category" with value "Questions Category 3 (1)"
|
||||
And I should see "question 3 name"
|
||||
And I press "Update filter conditions"
|
||||
Then I should see "Random (Questions Category 3) based on filter condition with tags: essay" on quiz page "1"
|
||||
|
||||
Scenario: "Go back" from bank switcher keeps existing filter values.
|
||||
Given I am on the "Quiz 1" "mod_quiz > Edit" page logged in as "teacher1"
|
||||
And I open the "last" add to quiz menu
|
||||
And I follow "a random question"
|
||||
And I apply question bank filter "Tag" with value "essay"
|
||||
And I press "Add random question"
|
||||
When I click on "Configure question" "link" in the "Random (Questions Category 1) based on filter condition with tags: essay" "list_item"
|
||||
And the field "filter-value-category" matches value " Questions Category 1 (2)"
|
||||
And the field "filter-value-qtagids" matches value "essay"
|
||||
And I press "Switch bank"
|
||||
And I press "Go back"
|
||||
Then the field "filter-value-category" matches value " Questions Category 1 (2)"
|
||||
And the field "filter-value-qtagids" matches value "essay"
|
||||
|
||||
Reference in New Issue
Block a user