');e.find("label").html(b),h.create({title:d,type:h.types.SAVE_CANCEL,body:e.html()},c).done(function(b){var e=a(b.getBody()).find("#add_section_numsections"),f=function(){""+parseInt(e.val())===e.val()&&parseInt(e.val())>=1&&(document.location=c.attr("href")+"&numsections="+parseInt(e.val()))};b.setSaveButtonText(d),b.getRoot().on(i.shown,function(){e.focus().select().on("keydown",function(a){a.keyCode===j.enter&&f()})}),b.getRoot().on(i.save,function(a){a.preventDefault(),f()})})})},replaceSectionActionItem:function(a,b,c,d,e,f,g,h){var i=a.find(l.SECTIONACTIONMENU+" "+b);A(i,c,d,e,f,g,h)}}});
\ No newline at end of file
diff --git a/course/amd/src/actions.js b/course/amd/src/actions.js
index da812407b67..a804b45cf17 100644
--- a/course/amd/src/actions.js
+++ b/course/amd/src/actions.js
@@ -22,8 +22,9 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.3
*/
-define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/url', 'core/yui'],
- function($, ajax, templates, notification, str, url, Y) {
+define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/url', 'core/yui',
+ 'core/modal_factory', 'core/modal_events', 'core/key_codes'],
+ function($, ajax, templates, notification, str, url, Y, ModalFactory, ModalEvents, KeyCodes) {
var CSS = {
EDITINPROGRESS: 'editinprogress',
SECTIONDRAGGABLE: 'sectiondraggable',
@@ -36,7 +37,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
MENU: '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',
TOGGLE: '.toggle-display,.dropdown-toggle',
SECTIONLI: 'li.section',
- SECTIONACTIONMENU: '.section_action_menu'
+ SECTIONACTIONMENU: '.section_action_menu',
+ ADDSECTIONS: '#changenumsections [data-add-sections]'
};
Y.use('moodle-course-coursebase', function() {
@@ -576,6 +578,44 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
editSection(sectionElement, sectionId, actionItem, courseformat);
}
});
+
+ // Add a handler for "Add sections" link to ask for a number of sections to add.
+ str.get_string('numberweeks').done(function(strNumberSections) {
+ var trigger = $(SELECTOR.ADDSECTIONS),
+ modalTitle = trigger.attr('data-add-sections');
+ var modalBody = $('
' +
+ '
');
+ modalBody.find('label').html(strNumberSections);
+ ModalFactory.create({
+ title: modalTitle,
+ type: ModalFactory.types.SAVE_CANCEL,
+ body: modalBody.html()
+ }, trigger)
+ .done(function(modal) {
+ var numSections = $(modal.getBody()).find('#add_section_numsections'),
+ addSections = function() {
+ // Check if value of the "Number of sections" is a valid positive integer and redirect
+ // to adding a section script.
+ if ('' + parseInt(numSections.val()) === numSections.val() && parseInt(numSections.val()) >= 1) {
+ document.location = trigger.attr('href') + '&numsections=' + parseInt(numSections.val());
+ }
+ };
+ modal.setSaveButtonText(modalTitle);
+ modal.getRoot().on(ModalEvents.shown, function() {
+ // When modal is shown focus and select the input and add a listener to keypress of "Enter".
+ numSections.focus().select().on('keydown', function(e) {
+ if (e.keyCode === KeyCodes.enter) {
+ addSections();
+ }
+ });
+ });
+ modal.getRoot().on(ModalEvents.save, function(e) {
+ // When modal "Add" button is pressed.
+ e.preventDefault();
+ addSections();
+ });
+ });
+ });
},
/**
diff --git a/course/changenumsections.php b/course/changenumsections.php
index a7b9495b76b..c3d2a55f394 100644
--- a/course/changenumsections.php
+++ b/course/changenumsections.php
@@ -31,6 +31,7 @@ require_once($CFG->dirroot.'/course/lib.php');
$courseid = required_param('courseid', PARAM_INT);
$increase = optional_param('increase', null, PARAM_BOOL);
$insertsection = optional_param('insertsection', null, PARAM_INT); // Insert section at position; 0 means at the end.
+$numsections = optional_param('numsections', 1, PARAM_INT); // Number of sections to insert.
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL); // Where to return to after the action.
$sectionreturn = optional_param('sectionreturn', null, PARAM_INT); // Section to return to, ignored if $returnurl is specified.
@@ -70,9 +71,12 @@ if (isset($courseformatoptions['numsections']) && $increase !== null) {
// Inserting sections at any position except in the very end requires capability to move sections.
require_capability('moodle/course:movesections', context_course::instance($course->id));
}
- $section = course_create_section($course, $insertsection);
+ $sections = [];
+ for ($i = 0; $i < max($numsections, 1); $i ++) {
+ $sections[] = course_create_section($course, $insertsection);
+ }
if (!$returnurl) {
- $returnurl = course_get_url($course, $section->section,
+ $returnurl = course_get_url($course, $sections[0]->section,
($sectionreturn !== null) ? ['sr' => $sectionreturn] : []);
}
}
diff --git a/course/editsection.php b/course/editsection.php
index 231935f31be..b04440bf8fe 100644
--- a/course/editsection.php
+++ b/course/editsection.php
@@ -49,9 +49,14 @@ if ($deletesection) {
$cancelurl = course_get_url($course, $sectioninfo, array('sr' => $sectionreturn));
if (course_can_delete_section($course, $sectioninfo)) {
$confirm = optional_param('confirm', false, PARAM_BOOL) && confirm_sesskey();
+ if (!$confirm && optional_param('sesskey', null, PARAM_RAW) !== null &&
+ empty($sectioninfo->summary) && empty($sectioninfo->sequence) && confirm_sesskey()) {
+ // Do not ask for confirmation if section is empty and sesskey is already provided.
+ $confirm = true;
+ }
if ($confirm) {
course_delete_section($course, $sectioninfo, true, true);
- $courseurl = course_get_url($course, 0, array('sr' => $sectionreturn));
+ $courseurl = course_get_url($course, $sectioninfo->section - 1, array('sr' => $sectionreturn));
redirect($courseurl);
} else {
if (get_string_manager()->string_exists('deletesection', 'format_' . $course->format)) {
diff --git a/course/format/renderer.php b/course/format/renderer.php
index eeb126f1016..f16bdd61ca3 100644
--- a/course/format/renderer.php
+++ b/course/format/renderer.php
@@ -394,7 +394,8 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
$url = new moodle_url('/course/editsection.php', array(
'id' => $section->id,
'sr' => $sectionreturn,
- 'delete' => 1));
+ 'delete' => 1,
+ 'sesskey' => sesskey()));
$controls['delete'] = array(
'url' => $url,
'icon' => 'i/delete',
@@ -991,18 +992,19 @@ abstract class format_section_renderer_base extends plugin_renderer_base {
// capabilities 'moodle/course:update' and 'moodle/course:movesections'.
echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right'));
- if (get_string_manager()->string_exists('addsection', 'format_'.$course->format)) {
- $straddsection = get_string('addsection', 'format_'.$course->format);
+ if (get_string_manager()->string_exists('addsections', 'format_'.$course->format)) {
+ $straddsections = get_string('addsections', 'format_'.$course->format);
} else {
- $straddsection = get_string('addsection');
+ $straddsections = get_string('addsections');
}
$url = new moodle_url('/course/changenumsections.php',
['courseid' => $course->id, 'insertsection' => 0, 'sesskey' => sesskey()]);
if ($sectionreturn !== null) {
$url->param('sectionreturn', $sectionreturn);
}
- $icon = $this->output->pix_icon('t/add', $straddsection);
- echo html_writer::link($url, $icon . $straddsection, array('class' => 'add-section'));
+ $icon = $this->output->pix_icon('t/add', $straddsections);
+ echo html_writer::link($url, $icon . $straddsections,
+ array('class' => 'add-sections', 'data-add-sections' => $straddsections));
echo html_writer::end_tag('div');
}
}
diff --git a/course/format/topics/lang/en/format_topics.php b/course/format/topics/lang/en/format_topics.php
index 38991849d52..d9d9a15d478 100644
--- a/course/format/topics/lang/en/format_topics.php
+++ b/course/format/topics/lang/en/format_topics.php
@@ -23,7 +23,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-$string['addsection'] = 'Add topic';
+$string['addsections'] = 'Add topics';
$string['currentsection'] = 'This topic';
$string['editsection'] = 'Edit topic';
$string['editsectionname'] = 'Edit topic name';
diff --git a/course/format/topics/tests/behat/edit_delete_sections.feature b/course/format/topics/tests/behat/edit_delete_sections.feature
index 87ca326d63b..bdb48f3888f 100644
--- a/course/format/topics/tests/behat/edit_delete_sections.feature
+++ b/course/format/topics/tests/behat/edit_delete_sections.feature
@@ -79,3 +79,18 @@ Feature: Sections can be edited and deleted in topics format
And I should not see "Test chat name"
And I should see "Test choice name" in the "li#section-4" "css_element"
And I should see "Topic 4"
+
+ @javascript
+ Scenario: Adding sections in topics format
+ When I follow "Add topics"
+ Then the field "Number of sections" matches value "1"
+ And I press "Add topics"
+ And I should see "Topic 6" in the "li#section-6" "css_element"
+ And "li#section-7" "css_element" should not exist
+ And I follow "Add topics"
+ And I set the field "Number of sections" to "3"
+ And I press "Add topics"
+ And I should see "Topic 7" in the "li#section-7" "css_element"
+ And I should see "Topic 8" in the "li#section-8" "css_element"
+ And I should see "Topic 9" in the "li#section-9" "css_element"
+ And "li#section-10" "css_element" should not exist
diff --git a/course/format/weeks/lang/en/format_weeks.php b/course/format/weeks/lang/en/format_weeks.php
index 7a1ff4db776..4f1eaa9c858 100644
--- a/course/format/weeks/lang/en/format_weeks.php
+++ b/course/format/weeks/lang/en/format_weeks.php
@@ -23,7 +23,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-$string['addsection'] = 'Add week';
+$string['addsections'] = 'Add weeks';
$string['currentsection'] = 'This week';
$string['editsection'] = 'Edit week';
$string['editsectionname'] = 'Edit week name';
diff --git a/course/format/weeks/tests/behat/edit_delete_sections.feature b/course/format/weeks/tests/behat/edit_delete_sections.feature
index db7cacd8283..7e1d1758859 100644
--- a/course/format/weeks/tests/behat/edit_delete_sections.feature
+++ b/course/format/weeks/tests/behat/edit_delete_sections.feature
@@ -86,3 +86,18 @@ Feature: Sections can be edited and deleted in weeks format
And I should not see "Test chat name"
And I should see "Test choice name" in the "li#section-4" "css_element"
And I should see "22 May - 28 May"
+
+ @javascript
+ Scenario: Adding sections in weeks format
+ When I follow "Add weeks"
+ Then the field "Number of sections" matches value "1"
+ And I press "Add weeks"
+ And I should see "5 June - 11 June" in the "li#section-6" "css_element"
+ And "li#section-7" "css_element" should not exist
+ And I follow "Add weeks"
+ And I set the field "Number of sections" to "3"
+ And I press "Add weeks"
+ And I should see "12 June - 18 June" in the "li#section-7" "css_element"
+ And I should see "19 June - 25 June" in the "li#section-8" "css_element"
+ And I should see "26 June - 2 July" in the "li#section-9" "css_element"
+ And "li#section-10" "css_element" should not exist
diff --git a/lang/en/moodle.php b/lang/en/moodle.php
index 9a317cff6c4..196ebde7e8f 100644
--- a/lang/en/moodle.php
+++ b/lang/en/moodle.php
@@ -71,7 +71,7 @@ $string['addresource'] = 'Add a resource...';
$string['addresourceoractivity'] = 'Add an activity or resource';
$string['addresourcetosection'] = 'Add a resource to section \'{$a}\'';
$string['address'] = 'Address';
-$string['addsection'] = 'Add section';
+$string['addsections'] = 'Add sections';
$string['addstudent'] = 'Add student';
$string['addsubcategory'] = 'Add a subcategory';
$string['addteacher'] = 'Add teacher';
diff --git a/lib/amd/build/modal_save_cancel.min.js b/lib/amd/build/modal_save_cancel.min.js
index 0bdfe30ae00..96737e88ad3 100644
--- a/lib/amd/build/modal_save_cancel.min.js
+++ b/lib/amd/build/modal_save_cancel.min.js
@@ -1 +1 @@
-define(["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events"],function(a,b,c,d,e){var f={SAVE_BUTTON:'[data-action="save"]',CANCEL_BUTTON:'[data-action="cancel"]'},g=function(a){d.call(this,a),this.getFooter().find(f.SAVE_BUTTON).length||b.exception({message:"No save button found"}),this.getFooter().find(f.CANCEL_BUTTON).length||b.exception({message:"No cancel button found"})};return g.prototype=Object.create(d.prototype),g.prototype.constructor=g,g.prototype.setFooter=function(){b.exception({message:"Can not change the footer of a save cancel modal"})},g.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this),this.getModal().on(c.events.activate,f.SAVE_BUTTON,function(b,c){var d=a.Event(e.save);this.getRoot().trigger(d,this),d.isDefaultPrevented()||(this.hide(),c.originalEvent.preventDefault())}.bind(this)),this.getModal().on(c.events.activate,f.CANCEL_BUTTON,function(b,c){var d=a.Event(e.cancel);this.getRoot().trigger(d,this),d.isDefaultPrevented()||(this.hide(),c.originalEvent.preventDefault())}.bind(this))},g});
\ No newline at end of file
+define(["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_events"],function(a,b,c,d,e){var f={SAVE_BUTTON:'[data-action="save"]',CANCEL_BUTTON:'[data-action="cancel"]'},g=function(a){d.call(this,a),this.getFooter().find(f.SAVE_BUTTON).length||b.exception({message:"No save button found"}),this.getFooter().find(f.CANCEL_BUTTON).length||b.exception({message:"No cancel button found"})};return g.prototype=Object.create(d.prototype),g.prototype.constructor=g,g.prototype.setFooter=function(){b.exception({message:"Can not change the footer of a save cancel modal"})},g.prototype.registerEventListeners=function(){d.prototype.registerEventListeners.call(this),this.getModal().on(c.events.activate,f.SAVE_BUTTON,function(b,c){var d=a.Event(e.save);this.getRoot().trigger(d,this),d.isDefaultPrevented()||(this.hide(),c.originalEvent.preventDefault())}.bind(this)),this.getModal().on(c.events.activate,f.CANCEL_BUTTON,function(b,c){var d=a.Event(e.cancel);this.getRoot().trigger(d,this),d.isDefaultPrevented()||(this.hide(),c.originalEvent.preventDefault())}.bind(this))},g.prototype.setSaveButtonText=function(a){this.getFooter().find(f.SAVE_BUTTON).text(a)},g});
\ No newline at end of file
diff --git a/lib/amd/src/modal_save_cancel.js b/lib/amd/src/modal_save_cancel.js
index 6aa133c80dc..c80d485b0a1 100644
--- a/lib/amd/src/modal_save_cancel.js
+++ b/lib/amd/src/modal_save_cancel.js
@@ -88,5 +88,14 @@ define(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/m
}.bind(this));
};
+ /**
+ * Allows to overwrite the text of "Save changes" button.
+ *
+ * @param String text
+ */
+ ModalSaveCancel.prototype.setSaveButtonText = function(text) {
+ this.getFooter().find(SELECTORS.SAVE_BUTTON).text(text);
+ };
+
return ModalSaveCancel;
});