Merge branch 'MDL-80386_404' of https://github.com/timhunt/moodle into MOODLE_404_STABLE

This commit is contained in:
Jun Pataleta
2025-03-13 12:32:38 +08:00
8 changed files with 134 additions and 11 deletions
+6 -2
View File
@@ -36,7 +36,8 @@
}
]
}
]
],
"showallbutton": false
}
}}
@@ -52,7 +53,10 @@
<button type="button" class="btn btn-link text-reset" data-filteraction="add">
{{#pix}}t/add{{/pix}}<span class="pl-3">{{#str}}addcondition{{/str}}</span>
</button>
<button data-filteraction="reset" type="button" class="btn btn-secondary ml-auto mr-2">{{#str}}clearfilters{{/str}}</button>
{{#showallbutton}}
<button data-filteraction="showall" data-perpage="{{ perpage }}" data-status="0" type="button" class="btn btn-light ml-auto mr-2">{{#str}}showall{{/str}}</button>
{{/showallbutton}}
<button data-filteraction="reset" type="button" class="btn btn-secondary {{^showallbutton}}ml-auto{{/showallbutton}} mr-2">{{#str}}clearfilters{{/str}}</button>
<button data-filteraction="apply" type="button" class="btn btn-primary">{{#str}}applyfilters{{/str}}</button>
</div>
@@ -83,10 +83,10 @@ class custom_view extends \core_question\local\bank\view {
}
$this->init_columns($this->wanted_columns(), $this->heading_column());
$this->pagesize = self::DEFAULT_PAGE_SIZE;
parent::__construct($contexts, $pageurl, $course, $cm, $params, $extraparams);
[$this->quiz, ] = get_module_from_cmid($cm->id);
$this->set_quiz_has_attempts(quiz_has_attempts($this->quiz->id));
$this->pagesize = self::DEFAULT_PAGE_SIZE;
}
/**
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+37 -2
View File
@@ -27,6 +27,9 @@ import Selectors from 'core/datafilter/selectors';
import Templates from 'core/templates';
import Fragment from 'core/fragment';
import {get_strings as getStrings} from 'core/str';
import {getString} from 'core/str';
import {addIconToContainerRemoveOnCompletion} from 'core/loadingicon';
/**
* Initialise the question bank filter on the element with the given id.
*
@@ -42,7 +45,7 @@ import {get_strings as getStrings} from 'core/str';
* @param {Object} pagevars JSON-encoded parameters from passed from the view, including filters and jointype.
* @param {Object} extraparams JSON-encoded additional parameters specific to this view class, used for re-rendering the view.
*/
export const init = (
export const init = async(
filterRegionId,
defaultcourseid,
defaultcategoryid,
@@ -68,10 +71,19 @@ export const init = (
EDIT_SWITCH_URL: '.editmode-switch-form input[name=pageurl]',
CATEGORY_VALIDATION_INPUT: 'div[data-filter-type="category"] div.form-autocomplete-input input',
QUESTION_BANK_WINDOW: '.questionbankwindow',
SHOW_ALL_LINK: '[data-filteraction="showall"]',
};
const filterSet = document.querySelector(`#${filterRegionId}`);
const [
showAllText,
showPerPageText,
] = await Promise.all([
getString('showall', 'core', ''),
getString('showperpage', 'core', extraparams.defaultqperpage),
]);
const viewData = {
extraparams: JSON.stringify(extraparams),
cmid,
@@ -138,10 +150,15 @@ export const init = (
// Load questions for first page.
viewData.filter = JSON.stringify(filterdata);
viewData.sortdata = JSON.stringify(sortData);
const questionscontainer = document.querySelector(SELECTORS.QUESTION_CONTAINER_ID);
// Clear the contents of the element, then append the loading icon.
questionscontainer.innerHTML = '';
addIconToContainerRemoveOnCompletion(questionscontainer, pendingPromise);
Fragment.loadFragment(component, callback, contextId, viewData)
// Render questions for first page and pagination.
.then((questionhtml, jsfooter) => {
const questionscontainer = document.querySelector(SELECTORS.QUESTION_CONTAINER_ID);
if (questionhtml === undefined) {
questionhtml = '';
}
@@ -207,6 +224,7 @@ export const init = (
const sortableLink = e.target.closest(SELECTORS.SORT_LINK);
const paginationLink = e.target.closest(SELECTORS.PAGINATION_LINK);
const clearLink = e.target.closest(Selectors.filterset.actions.resetFilters);
const showallLink = e.target.closest(SELECTORS.SHOW_ALL_LINK);
if (sortableLink) {
e.preventDefault();
const oldSort = sortData;
@@ -232,6 +250,23 @@ export const init = (
if (clearLink) {
cleanUrlParams();
}
if (showallLink) {
e.preventDefault();
// Toggle between showing all and going back to the original qperpage.
if (Number(showallLink.dataset.status) === 0) {
viewData.qperpage = extraparams.maxqperpage;
showallLink.dataset.status = 1;
showallLink.innerText = showPerPageText;
} else {
viewData.qperpage = extraparams.defaultqperpage;
showallLink.dataset.status = 0;
showallLink.innerText = showAllText;
}
viewData.qpage = 0;
coreFilter.updateTableFromFilter();
}
});
// Run apply filter at page load.
+11 -3
View File
@@ -235,6 +235,10 @@ class view {
$this->cm = $cm;
$this->extraparams = $extraparams;
// Add the default qperpage to extra params array so we can switch back and forth between it and "all".
$this->extraparams['defaultqperpage'] = $this->pagesize;
$this->extraparams['maxqperpage'] = MAXIMUM_QUESTIONS_PER_PAGE;
// Default filter condition.
if (!isset($params['filter']) && isset($params['cat'])) {
$params['filter'] = [];
@@ -811,15 +815,18 @@ class view {
*/
protected function load_page_questions(): \moodle_recordset {
global $DB;
// Load the questions based on the page we are on.
$questions = $DB->get_recordset_sql($this->loadsql, $this->sqlparams,
(int)$this->pagevars['qpage'] * (int)$this->pagevars['qperpage'], $this->pagevars['qperpage']);
(int)$this->pagevars['qpage'] * (int)$this->pagevars['qperpage'], (int)$this->pagevars['qperpage']);
if (!$questions->valid()) {
$questions->close();
// No questions on this page. Reset to the nearest page that contains questions.
$this->pagevars['qpage'] = max(0,
ceil($this->totalcount / $this->pagevars['qperpage']) - 1);
ceil($this->totalcount / (int)$this->pagevars['qperpage']) - 1);
$questions = $DB->get_recordset_sql($this->loadsql, $this->sqlparams,
$this->pagevars['qpage'] * (int) $this->pagevars['qperpage'], $this->pagevars['qperpage']);
(int)$this->pagevars['qpage'] * (int)$this->pagevars['qperpage'], (int)$this->pagevars['qperpage']);
}
return $questions;
}
@@ -1155,6 +1162,7 @@ class view {
// We probably do not want to raise it to unlimited, so randomly picking 5 minutes.
// Note: We do not call this in the loop because quiz ob_ captures this function (see raise() PHP doc).
\core_php_time_limit::raise(300);
raise_memory_limit(MEMORY_EXTRA);
[$categoryid, $contextid] = category_condition::validate_category_param($this->pagevars['cat']);
$catcontext = \context::instance_by_id($contextid);
@@ -137,6 +137,7 @@ class question_bank_filter_ui extends datafilter {
'cmid' => $this->cmid ?? 0,
'pagevars' => json_encode($this->pagevars),
'extraparams' => json_encode($this->extraparams),
'showallbutton' => true,
];
}
}
@@ -0,0 +1,75 @@
@core @core_question @qbank_filter @javascript
Feature: A teacher can show all of the questions on the question bank and override pagination
In order to see all the questions in the question bank
As a teacher
I must be able to toggle between show all and show paginated
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
And the following "activities" exist:
| activity | name | course | idnumber |
| quiz | Test quiz | C1 | quiz1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And the following "question categories" exist:
| contextlevel | reference | questioncategory | name |
| Course | C1 | Top | Test Category |
Given 201 "questions" exist with the following data:
| questioncategory | Test Category |
| qtype | truefalse |
| name | Question #[count] |
| questiontext | True or false? |
Scenario: Use "Show All" button on the question bank when there are no questions
Given I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When I apply question bank filter "Category" with value "Default for C1"
Then I should not see "Question #"
And I click on "Show all" "button"
Then I should not see "Question #"
And I click on "Show 100 per page" "button"
Then I should not see "Question #"
Scenario: Question bank shows paginated questions by default
Given I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When I apply question bank filter "Category" with value "Top for Course 1"
Then I should see "100" occurrences of "Question #" in the "div#questionscontainer" "css_element"
And I should see "1" in the ".pagination" "css_element"
And I should see "2" in the ".pagination" "css_element"
And I should see "3" in the ".pagination" "css_element"
Scenario: Toggle "Show all" shows all questions
Given I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When I apply question bank filter "Category" with value "Top for Course 1"
And I click on "Show all" "button"
Then I should see "201" occurrences of "Question #" in the "div#questionscontainer" "css_element"
And ".pagination" "css_element" should not exist
And I should see "Show 100 per page"
Scenario: Toggle "Show all" back to paginated shows paginated questions
Given I am on the "Course 1" "core_question > course question bank" page logged in as "teacher1"
When I apply question bank filter "Category" with value "Top for Course 1"
And I click on "Show all" "button"
And I click on "Show 100 per page" "button"
Then I should see "100" occurrences of "Question #" in the "div#questionscontainer" "css_element"
And I should see "1" in the ".pagination" "css_element"
And I should see "2" in the ".pagination" "css_element"
And I should see "3" in the ".pagination" "css_element"
And I should see "Show all"
Scenario: Show all questions on the question bank when adding questions to a quiz
Given I am on the "Test quiz" "mod_quiz > Edit" page logged in as "teacher1"
When I open the "last" add to quiz menu
And I follow "from question bank"
And I apply question bank filter "Category" with value "Top for Course 1"
Then I should see "20" occurrences of "Question #" in the "div#questionscontainer" "css_element"
When I click on "Show all" "button"
Then I should see "201" occurrences of "Question #" in the "div#questionscontainer" "css_element"
When I click on "Select all" "checkbox"
And I click on "Add selected questions to the quiz" "button"
Then I should see "Questions: 201"