From f24e17c93eb6f53057db6e89e5c123a751677637 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Thu, 11 May 2017 11:42:53 +0800 Subject: [PATCH 1/2] MDL-58837 course: allow to add multiple sections --- course/amd/build/actions.min.js | 2 +- course/amd/src/actions.js | 46 +++++++++++++++++-- course/changenumsections.php | 8 +++- course/format/renderer.php | 11 +++-- .../format/topics/lang/en/format_topics.php | 2 +- .../tests/behat/edit_delete_sections.feature | 15 ++++++ course/format/weeks/lang/en/format_weeks.php | 2 +- .../tests/behat/edit_delete_sections.feature | 15 ++++++ lang/en/moodle.php | 2 +- lib/amd/build/modal_save_cancel.min.js | 2 +- lib/amd/src/modal_save_cancel.js | 9 ++++ 11 files changed, 99 insertions(+), 15 deletions(-) diff --git a/course/amd/build/actions.min.js b/course/amd/build/actions.min.js index d8e4d3bbd28..ce8c49cf846 100644 --- a/course/amd/build/actions.min.js +++ b/course/amd/build/actions.min.js @@ -1 +1 @@ -define(["jquery","core/ajax","core/templates","core/notification","core/str","core/url","core/yui"],function(a,b,c,d,e,f,g){var h={EDITINPROGRESS:"editinprogress",SECTIONDRAGGABLE:"sectiondraggable",EDITINGMOVE:"editing_move"},i={ACTIVITYLI:"li.activity",ACTIONAREA:".actions",ACTIVITYACTION:"a.cm-edit-action",MENU:".moodle-actionmenu[data-enhance=moodle-core-actionmenu]",TOGGLE:".toggle-display,.dropdown-toggle",SECTIONLI:"li.section",SECTIONACTIONMENU:".section_action_menu"};g.use("moodle-course-coursebase",function(){var a=M.course.format.get_section_selector();a&&(i.SECTIONLI=a)});var j=function(a){var b;return g.use("moodle-course-util",function(c){b=c.Moodle.core_course.util.cm.getId(c.Node(a.get(0)))}),b},k=function(a){var b;return g.use("moodle-course-util",function(c){b=c.Moodle.core_course.util.cm.getName(c.Node(a.get(0)))}),b},l=function(a){a.addClass(h.EDITINPROGRESS);var b=a.find(i.ACTIONAREA).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));return c.show(),c}return null},m=function(a){a.addClass(h.EDITINPROGRESS);var b=a.find(i.SECTIONACTIONMENU).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));return c.show(),c}return null},n=function(a){var b=M.util.add_lightbox(g,g.Node(a.get(0)));return b.show(),b},o=function(a,b,c){window.setTimeout(function(){a.removeClass(h.EDITINPROGRESS),b&&b.hide()},c)},p=function(a,b){a&&window.setTimeout(function(){a.hide()},b)},q=function(a,b){if(g.use("moodle-course-coursebase",function(){M.course.coursebase.invoke_function("setup_for_resource","#"+a)}),M.core.actionmenu&&M.core.actionmenu.newDOMNode&&M.core.actionmenu.newDOMNode(g.one("#"+a)),b){var c=g.one("#"+a+" "+i.MENU).one(i.TOGGLE);c&&c.simulate&&c.simulate("click")}},r=function(b,c){var d=a("#"+b),e="[data-action="+c+"]";"groupsseparate"!==c&&"groupsvisible"!==c&&"groupsnone"!==c||(e="[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]"),d.find(e).is(":visible")?d.find(e).focus():d.find(i.MENU).find(i.TOGGLE).focus()},s=function(b){var c=a("a:visible"),d=!1,e=null;return c.each(function(){if(a.contains(b[0],this))d=!0;else if(d)return e=this,!1}),e},t=function(c,e,f){var g,h=f.attr("data-keepopen"),j=f.attr("data-action"),k=l(c),m=b.call([{methodname:"core_course_edit_module",args:{id:e,action:j,sectionreturn:f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0}}],!0);"duplicate"===j&&(g=n(f.closest(i.SECTIONLI))),a.when.apply(a,m).done(function(b){var d=s(c);c.replaceWith(b),a("
"+b+"
").find(i.ACTIVITYLI).each(function(b){q(a(this).attr("id"),h),0===b&&(r(a(this).attr("id"),j),d=null)}),d&&d.focus(),o(c,k,400),p(g,400),c.trigger(a.Event("coursemoduleedited",{ajaxreturn:b,action:j}))}).fail(function(b){o(c,k),p(g);var e=a.Event("coursemoduleeditfailed",{exception:b,action:j});c.trigger(e),e.isDefaultPrevented()||d.exception(b)})},u=function(c,d,e){var f=l(c),g=b.call([{methodname:"core_course_get_module",args:{id:d,sectionreturn:e}}],!0);a.when.apply(a,g).done(function(a){o(c,f,400),z(a)}).fail(function(){o(c,f)})},v=function(a,b){var c=a.attr("class").match(/modtype_([^\s]*)/)[1],f=k(a);e.get_string("pluginname",c).done(function(a){var c={type:a,name:f};e.get_strings([{key:"confirm"},{key:null===f?"deletechecktype":"deletechecktypename",param:c},{key:"yes"},{key:"no"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],b)})})},w=function(a,b){e.get_strings([{key:"confirm"},{key:"yes"},{key:"no"}]).done(function(c){d.confirm(c[0],a,c[1],c[2],b)})},x=function(a,b,d,f,g,h,i){e.get_string(d,f).done(function(b){a.find("span.menu-action-text").html(b),a.attr("title",b)}),g?e.get_string(g,h).then(function(d){c.renderPix(b,"core",d).then(function(b){a.find(".icon").replaceWith(b)}),a.attr("title",d)}):c.renderPix(b,"core","").then(function(b){a.find(".icon").replaceWith(b)}),a.attr("data-action",i)},y=function(b,c,d,e){var f=c.attr("data-action");if("hide"===f||"show"===f){if("hide"===f?(b.addClass("hidden"),x(c,"i/show","showfromothers","format_"+e,null,null,"show")):(b.removeClass("hidden"),x(c,"i/hide","hidefromothers","format_"+e,null,null,"hide")),void 0!==d.modules)for(var g in d.modules)z(d.modules[g]);void 0!==d.section_availability&&b.find(".section_availability").first().replaceWith(d.section_availability)}else if("setmarker"===f){var h=a(i.SECTIONLI+".current"),j=h.find(i.SECTIONACTIONMENU+" a[data-action=removemarker]");h.removeClass("current"),x(j,"i/marker","highlight","core","markthistopic","core","setmarker"),b.addClass("current"),x(c,"i/marked","highlightoff","core","markedthistopic","core","removemarker")}else"removemarker"===f&&(b.removeClass("current"),x(c,"i/marker","highlight","core","markthistopic","core","setmarker"))},z=function(b){a("
"+b+"
").find(i.ACTIVITYLI).each(function(){var c=a(this).attr("id");a(i.ACTIVITYLI+"#"+c).replaceWith(b),q(c,!1)})},A=function(c,e,f,g){var h=f.attr("data-action"),j=f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0,k=m(c),l=b.call([{methodname:"core_course_edit_section",args:{id:e,action:h,sectionreturn:j}}],!0),q=n(c);a.when.apply(a,l).done(function(b){var d=a.parseJSON(b);o(c,k),p(q),c.find(i.SECTIONACTIONMENU).find(i.TOGGLE).focus();var e=a.Event("coursesectionedited",{ajaxreturn:d,action:h});c.trigger(e),e.isDefaultPrevented()||y(c,f,d,g)}).fail(function(b){o(c,k),p(q);var e=a.Event("coursesectioneditfailed",{exception:b,action:h});c.trigger(e),e.isDefaultPrevented()||d.exception(b)})};return g.use("moodle-course-coursebase",function(){M.course.coursebase.register_module({set_visibility_resource_ui:function(b){var c=a(b.element.getDOMNode()),d=j(c);if(d){var e=c.find("."+h.EDITINGMOVE).attr("data-sectionreturn");u(c,d,e)}}})}),{initCoursePage:function(b){a("body").on("click keypress",i.ACTIVITYLI+" "+i.ACTIVITYACTION+"[data-action]",function(b){if("keypress"!==b.type||13===b.keyCode){var c=a(this),d=c.closest(i.ACTIVITYLI),e=c.attr("data-action"),f=j(d);switch(e){case"moveleft":case"moveright":case"delete":case"duplicate":case"hide":case"stealth":case"show":case"groupsseparate":case"groupsvisible":case"groupsnone":break;default:return}f&&(b.preventDefault(),"delete"===e?v(d,function(){t(d,f,c)}):t(d,f,c))}}),a("body").on("click keypress",i.SECTIONLI+" "+i.SECTIONACTIONMENU+"[data-sectionid] a[data-action]",function(c){if("keypress"!==c.type||13===c.keyCode){var d=a(this),e=d.closest(i.SECTIONLI),f=d.closest(i.SECTIONACTIONMENU).attr("data-sectionid");c.preventDefault(),d.attr("data-confirm")?w(d.attr("data-confirm"),function(){A(e,f,d,b)}):A(e,f,d,b)}})},replaceSectionActionItem:function(a,b,c,d,e,f,g,h){var j=a.find(i.SECTIONACTIONMENU+" "+b);x(j,c,d,e,f,g,h)}}}); \ No newline at end of file +define(["jquery","core/ajax","core/templates","core/notification","core/str","core/url","core/yui","core/modal_factory","core/modal_events","core/key_codes"],function(a,b,c,d,e,f,g,h,i,j){var k={EDITINPROGRESS:"editinprogress",SECTIONDRAGGABLE:"sectiondraggable",EDITINGMOVE:"editing_move"},l={ACTIVITYLI:"li.activity",ACTIONAREA:".actions",ACTIVITYACTION:"a.cm-edit-action",MENU:".moodle-actionmenu[data-enhance=moodle-core-actionmenu]",TOGGLE:".toggle-display,.dropdown-toggle",SECTIONLI:"li.section",SECTIONACTIONMENU:".section_action_menu",ADDSECTIONS:"#changenumsections [data-add-sections]"};g.use("moodle-course-coursebase",function(){var a=M.course.format.get_section_selector();a&&(l.SECTIONLI=a)});var m=function(a){var b;return g.use("moodle-course-util",function(c){b=c.Moodle.core_course.util.cm.getId(c.Node(a.get(0)))}),b},n=function(a){var b;return g.use("moodle-course-util",function(c){b=c.Moodle.core_course.util.cm.getName(c.Node(a.get(0)))}),b},o=function(a){a.addClass(k.EDITINPROGRESS);var b=a.find(l.ACTIONAREA).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));return c.show(),c}return null},p=function(a){a.addClass(k.EDITINPROGRESS);var b=a.find(l.SECTIONACTIONMENU).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));return c.show(),c}return null},q=function(a){var b=M.util.add_lightbox(g,g.Node(a.get(0)));return b.show(),b},r=function(a,b,c){window.setTimeout(function(){a.removeClass(k.EDITINPROGRESS),b&&b.hide()},c)},s=function(a,b){a&&window.setTimeout(function(){a.hide()},b)},t=function(a,b){if(g.use("moodle-course-coursebase",function(){M.course.coursebase.invoke_function("setup_for_resource","#"+a)}),M.core.actionmenu&&M.core.actionmenu.newDOMNode&&M.core.actionmenu.newDOMNode(g.one("#"+a)),b){var c=g.one("#"+a+" "+l.MENU).one(l.TOGGLE);c&&c.simulate&&c.simulate("click")}},u=function(b,c){var d=a("#"+b),e="[data-action="+c+"]";"groupsseparate"!==c&&"groupsvisible"!==c&&"groupsnone"!==c||(e="[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]"),d.find(e).is(":visible")?d.find(e).focus():d.find(l.MENU).find(l.TOGGLE).focus()},v=function(b){var c=a("a:visible"),d=!1,e=null;return c.each(function(){if(a.contains(b[0],this))d=!0;else if(d)return e=this,!1}),e},w=function(c,e,f){var g,h=f.attr("data-keepopen"),i=f.attr("data-action"),j=o(c),k=b.call([{methodname:"core_course_edit_module",args:{id:e,action:i,sectionreturn:f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0}}],!0);"duplicate"===i&&(g=q(f.closest(l.SECTIONLI))),a.when.apply(a,k).done(function(b){var d=v(c);c.replaceWith(b),a("
"+b+"
").find(l.ACTIVITYLI).each(function(b){t(a(this).attr("id"),h),0===b&&(u(a(this).attr("id"),i),d=null)}),d&&d.focus(),r(c,j,400),s(g,400),c.trigger(a.Event("coursemoduleedited",{ajaxreturn:b,action:i}))}).fail(function(b){r(c,j),s(g);var e=a.Event("coursemoduleeditfailed",{exception:b,action:i});c.trigger(e),e.isDefaultPrevented()||d.exception(b)})},x=function(c,d,e){var f=o(c),g=b.call([{methodname:"core_course_get_module",args:{id:d,sectionreturn:e}}],!0);a.when.apply(a,g).done(function(a){r(c,f,400),C(a)}).fail(function(){r(c,f)})},y=function(a,b){var c=a.attr("class").match(/modtype_([^\s]*)/)[1],f=n(a);e.get_string("pluginname",c).done(function(a){var c={type:a,name:f};e.get_strings([{key:"confirm"},{key:null===f?"deletechecktype":"deletechecktypename",param:c},{key:"yes"},{key:"no"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],b)})})},z=function(a,b){e.get_strings([{key:"confirm"},{key:"yes"},{key:"no"}]).done(function(c){d.confirm(c[0],a,c[1],c[2],b)})},A=function(a,b,d,f,g,h,i){e.get_string(d,f).done(function(b){a.find("span.menu-action-text").html(b),a.attr("title",b)}),g?e.get_string(g,h).then(function(d){c.renderPix(b,"core",d).then(function(b){a.find(".icon").replaceWith(b)}),a.attr("title",d)}):c.renderPix(b,"core","").then(function(b){a.find(".icon").replaceWith(b)}),a.attr("data-action",i)},B=function(b,c,d,e){var f=c.attr("data-action");if("hide"===f||"show"===f){if("hide"===f?(b.addClass("hidden"),A(c,"i/show","showfromothers","format_"+e,null,null,"show")):(b.removeClass("hidden"),A(c,"i/hide","hidefromothers","format_"+e,null,null,"hide")),void 0!==d.modules)for(var g in d.modules)C(d.modules[g]);void 0!==d.section_availability&&b.find(".section_availability").first().replaceWith(d.section_availability)}else if("setmarker"===f){var h=a(l.SECTIONLI+".current"),i=h.find(l.SECTIONACTIONMENU+" a[data-action=removemarker]");h.removeClass("current"),A(i,"i/marker","highlight","core","markthistopic","core","setmarker"),b.addClass("current"),A(c,"i/marked","highlightoff","core","markedthistopic","core","removemarker")}else"removemarker"===f&&(b.removeClass("current"),A(c,"i/marker","highlight","core","markthistopic","core","setmarker"))},C=function(b){a("
"+b+"
").find(l.ACTIVITYLI).each(function(){var c=a(this).attr("id");a(l.ACTIVITYLI+"#"+c).replaceWith(b),t(c,!1)})},D=function(c,e,f,g){var h=f.attr("data-action"),i=f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0,j=p(c),k=b.call([{methodname:"core_course_edit_section",args:{id:e,action:h,sectionreturn:i}}],!0),m=q(c);a.when.apply(a,k).done(function(b){var d=a.parseJSON(b);r(c,j),s(m),c.find(l.SECTIONACTIONMENU).find(l.TOGGLE).focus();var e=a.Event("coursesectionedited",{ajaxreturn:d,action:h});c.trigger(e),e.isDefaultPrevented()||B(c,f,d,g)}).fail(function(b){r(c,j),s(m);var e=a.Event("coursesectioneditfailed",{exception:b,action:h});c.trigger(e),e.isDefaultPrevented()||d.exception(b)})};return g.use("moodle-course-coursebase",function(){M.course.coursebase.register_module({set_visibility_resource_ui:function(b){var c=a(b.element.getDOMNode()),d=m(c);if(d){var e=c.find("."+k.EDITINGMOVE).attr("data-sectionreturn");x(c,d,e)}}})}),{initCoursePage:function(b){a("body").on("click keypress",l.ACTIVITYLI+" "+l.ACTIVITYACTION+"[data-action]",function(b){if("keypress"!==b.type||13===b.keyCode){var c=a(this),d=c.closest(l.ACTIVITYLI),e=c.attr("data-action"),f=m(d);switch(e){case"moveleft":case"moveright":case"delete":case"duplicate":case"hide":case"stealth":case"show":case"groupsseparate":case"groupsvisible":case"groupsnone":break;default:return}f&&(b.preventDefault(),"delete"===e?y(d,function(){w(d,f,c)}):w(d,f,c))}}),a("body").on("click keypress",l.SECTIONLI+" "+l.SECTIONACTIONMENU+"[data-sectionid] a[data-action]",function(c){if("keypress"!==c.type||13===c.keyCode){var d=a(this),e=d.closest(l.SECTIONLI),f=d.closest(l.SECTIONACTIONMENU).attr("data-sectionid");c.preventDefault(),d.attr("data-confirm")?z(d.attr("data-confirm"),function(){D(e,f,d,b)}):D(e,f,d,b)}}),e.get_string("numberweeks").done(function(b){var c=a(l.ADDSECTIONS),d=c.attr("data-add-sections"),e=a('
');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/format/renderer.php b/course/format/renderer.php index eeb126f1016..1180f32257b 100644 --- a/course/format/renderer.php +++ b/course/format/renderer.php @@ -991,18 +991,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; }); From 88a7f77525adc22f3bcc3f74705db8149d360016 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Thu, 11 May 2017 11:54:57 +0800 Subject: [PATCH 2/2] MDL-58837 course: do not confirm deleting empty sections --- course/editsection.php | 7 ++++++- course/format/renderer.php | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) 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 1180f32257b..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',