Skip to content

Commit

Permalink
MDL-65399 mod_quiz: UI should prevent deleting the last slot of section
Browse files Browse the repository at this point in the history
  • Loading branch information
rezaies committed May 6, 2019
1 parent 2b9c3f1 commit fe3d98f
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 16 deletions.
2 changes: 2 additions & 0 deletions mod/quiz/classes/output/edit_renderer.php
Expand Up @@ -1150,6 +1150,8 @@ protected function initialise_editing_javascript(structure $structure,

$this->page->requires->strings_for_js(array(
'addpagebreak',
'cannotremoveallsectionslots',
'cannotremoveslots',
'confirmremovesectionheading',
'confirmremovequestion',
'dragtoafter',
Expand Down
2 changes: 2 additions & 0 deletions mod/quiz/lang/en/quiz.php
Expand Up @@ -137,6 +137,8 @@
$string['cannotloadquestion'] = 'Could not load question options';
$string['cannotloadtypeinfo'] = 'Unable to load questiontype specific question information';
$string['cannotopen'] = 'Cannot open export file ({$a})';
$string['cannotremoveallsectionslots'] = 'You have selected all questions of the \'{$a}\' section heading. It is not allowed to remove all questions under a section heading.';
$string['cannotremoveslots'] = 'Can not remove questions';
$string['cannotrestore'] = 'Could not restore question sessions';
$string['cannotreviewopen'] = 'You cannot review this attempt, it is still open.';
$string['cannotsavelayout'] = 'Could not save layout';
Expand Down
6 changes: 2 additions & 4 deletions mod/quiz/styles.css
Expand Up @@ -1190,11 +1190,9 @@ table#categoryquestions {
display: none;
}

#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading a,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading form,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading .instancesectioncontainer,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading .instanceshufflequestions,
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading .instancesectioncontainer h3 {
#page-mod-quiz-edit.select-multiple .mod-quiz-edit-content .section-heading .instanceshufflequestions {
display: none;
}

Expand Down
71 changes: 71 additions & 0 deletions mod/quiz/tests/behat/editing_remove_multiple_questions.feature
Expand Up @@ -167,3 +167,74 @@ Feature: Edit quiz page - remove multiple questions

When I click on "Deselect all" "link"
Then the field "selectquestion-3" matches value "0"

@javascript
Scenario: Delete multiple questions from sections
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | Question A | First question |
| Test questions | truefalse | Question B | Second question |
| Test questions | truefalse | Question C | Third question |
| Test questions | truefalse | Question D | Fourth question |
| Test questions | truefalse | Question E | Fifth question |
| Test questions | truefalse | Question F | Sixth question |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Question A | 1 |
| Question B | 2 |
| Question C | 3 |
| Question D | 4 |
| Question E | 5 |
| Question F | 6 |
And quiz "Quiz 1" contains the following sections:
| heading | firstslot | shuffle |
| Section 1 | 1 | 0 |
| Section 2 | 2 | 0 |
| Section 3 | 4 | 0 |
And I navigate to "Edit quiz" in current page administration

When I click on "Select multiple items" "button"
And I click on "selectquestion-3" "checkbox"
And I click on "selectquestion-5" "checkbox"
And I click on "selectquestion-6" "checkbox"
And I click on "Delete selected" "button"
And I click on "Yes" "button" in the "Confirm" "dialogue"

Then I should see "Question A" on quiz page "1"
And I should see "Question B" on quiz page "2"
And I should see "Question D" on quiz page "3"
And I should not see "Question C"
And I should not see "Question E"
And I should not see "Question F"

@javascript
Scenario: Attempting to delete all questions of a sections
Given the following "questions" exist:
| questioncategory | qtype | name | questiontext |
| Test questions | truefalse | Question A | First question |
| Test questions | truefalse | Question B | Second question |
| Test questions | truefalse | Question C | Third question |
| Test questions | truefalse | Question D | Fourth question |
| Test questions | truefalse | Question E | Fifth question |
| Test questions | truefalse | Question F | Sixth question |
And quiz "Quiz 1" contains the following questions:
| question | page |
| Question A | 1 |
| Question B | 2 |
| Question C | 3 |
| Question D | 4 |
| Question E | 5 |
| Question F | 6 |
And quiz "Quiz 1" contains the following sections:
| heading | firstslot | shuffle |
| Section 1 | 1 | 0 |
| Section 2 | 2 | 0 |
| Section 3 | 4 | 0 |
And I navigate to "Edit quiz" in current page administration

When I click on "Select multiple items" "button"
And I click on "selectquestion-2" "checkbox"
And I click on "selectquestion-3" "checkbox"
And I click on "Delete selected" "button"

Then I should see "Can not remove questions"
Expand Up @@ -64,6 +64,7 @@ var CSS = {
NUMQUESTIONS: '.numberofquestions',
PAGECONTENT: 'div#page-content',
PAGELI: 'li.page',
SECTIONLI: 'li.section',
SECTIONUL: 'ul.section',
SECTIONFORM: '.instancesectioncontainer form',
SECTIONINPUT: 'input[name=section]',
Expand Down Expand Up @@ -337,7 +338,7 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
Y.one(SELECTOR.SELECTMULTIPLEDELETEBUTTON).setAttribute('disabled', 'disabled');

// Assign the delete method to the delete multiple button.
Y.delegate('click', this.delete_multiple_with_confirmation, BODY, SELECTOR.SELECTMULTIPLEDELETEBUTTON, this);
Y.delegate('click', this.delete_multiple_action, BODY, SELECTOR.SELECTMULTIPLEDELETEBUTTON, this);

// Enable the delete all button only when at least one slot is selected.
Y.delegate('click', this.toggle_select_all_buttons_enabled, BODY, SELECTOR.SELECTMULTIPLECHECKBOX, this);
Expand Down Expand Up @@ -439,7 +440,6 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
* @param {EventFacade} ev The event that was fired.
* @param {Node} button The button that triggered this action.
* @param {Node} activity The activity node that this action will be performed on.
* @chainable
*/
delete_with_confirmation: function(ev, button, activity) {
// Prevent the default button action.
Expand Down Expand Up @@ -481,13 +481,62 @@ Y.extend(RESOURCETOOLBOX, TOOLBOX, {
}, this);
},

/**
* Finds the section that would become empty if we remove the selected slots.
*
* @protected
* @method find_sections_that_would_become_empty
* @returns {String} The name of the first section found
*/
find_sections_that_would_become_empty: function() {
var section;
var sectionnodes = Y.all(SELECTOR.SECTIONLI);

if (sectionnodes.size() > 1) {
sectionnodes.some(function(node) {
var sectionname = node.one(SELECTOR.INSTANCESECTION).getContent();
var checked = node.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':checked');
var unchecked = node.all(SELECTOR.SELECTMULTIPLECHECKBOX + ':not(:checked)');

if (!checked.isEmpty() && unchecked.isEmpty()) {
section = sectionname;
}

return section;
});
}

return section;
},

/**
* Takes care of what needs to happen when the user clicks on the delete multiple button.
*
* @protected
* @method delete_multiple_action
* @param {EventFacade} ev The event that was fired.
*/
delete_multiple_action: function(ev) {
var problemsection = this.find_sections_that_would_become_empty();

if (problemsection) {
var alert = new M.core.alert({
title: M.util.get_string('cannotremoveslots', 'quiz'),
message: M.util.get_string('cannotremoveallsectionslots', 'quiz', problemsection)
});

alert.show();
} else {
this.delete_multiple_with_confirmation(ev);
}
},

/**
* Deletes the given activities or resources after confirmation.
*
* @protected
* @method delete_multiple_with_confirmation
* @param {EventFacade} ev The event that was fired.
* @chainable
*/
delete_multiple_with_confirmation: function(ev) {
ev.preventDefault();
Expand Down

0 comments on commit fe3d98f

Please sign in to comment.