diff --git a/course/amd/build/actions.min.js b/course/amd/build/actions.min.js index 20369231437..b8206bb69df 100644 --- a/course/amd/build/actions.min.js +++ b/course/amd/build/actions.min.js @@ -1,2 +1,2 @@ -function _defineProperty(a,b,c){if(b in a){Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0})}else{a[b]=c}return a}define ("core_course/actions",["jquery","core/ajax","core/templates","core/notification","core/str","core/url","core/yui","core/modal_factory","core/modal_events","core/key_codes","core/log","core_courseformat/courseeditor","core/event_dispatcher","core_course/events"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){var o=["moveSection","moveCm","addSection","deleteSection"],p=l.getCurrentCourseEditor(),q,r={EDITINPROGRESS:"editinprogress",SECTIONDRAGGABLE:"sectiondraggable",EDITINGMOVE:"editing_move"},s={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]",SECTIONBADGES:"[data-region=\"sectionbadges\"]"};g.use("moodle-course-coursebase",function(){var a=M.course.format.get_section_selector();if(a){s.SECTIONLI=a}});var t=function(a,b,c,d){if(!(c instanceof Element)&&c.get!==void 0){c=c.get(0)}return m.dispatchEvent(a,b,c,d)},u=function(a){var b=a.get(0);if(b.dataset.id){return b.dataset.id}var c;g.use("moodle-course-util",function(a){c=a.Moodle.core_course.util.cm.getId(a.Node(b))});return c},v=function(a){var b;g.use("moodle-course-util",function(c){b=c.Moodle.core_course.util.cm.getName(c.Node(a.get(0)))});var c=p.state,d=u(a);if(!b&&c&&d){var e;b=null===(e=c.cm.get(d))||void 0===e?void 0:e.name}return b},w=function(a){a.addClass(r.EDITINPROGRESS);var b=a.find(s.ACTIONAREA).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));c.show();if(a.data("id")!==void 0){p.dispatch("cmLock",[a.data("id")],!0)}return c}return null},x=function(a){a.addClass(r.EDITINPROGRESS);var b=a.find(s.SECTIONACTIONMENU).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));c.show();if(a.data("id")!==void 0){p.dispatch("sectionLock",[a.data("id")],!0)}return c}return null},y=function(a){var b=a.get(0),c=M.util.add_lightbox(g,g.Node(b));if("section"==b.dataset.for&&b.dataset.id){p.dispatch("sectionLock",[b.dataset.id],!0);c.setAttribute("data-state","section");c.setAttribute("data-state-id",b.dataset.id)}c.show();return c},z=function(a,b,c){window.setTimeout(function(){a.removeClass(r.EDITINPROGRESS);if(b){b.hide()}if(a.data("id")!==void 0){var c="section"===a.data("for")?"sectionLock":"cmLock";p.dispatch(c,[a.data("id")],!1)}},c)},A=function(a,b){if(a){window.setTimeout(function(){a.hide();if(a.getAttribute("data-state")){p.dispatch("".concat(a.getAttribute("data-state"),"Lock"),[a.getAttribute("data-state-id")],!1)}},b)}},B=function(a){g.use("moodle-course-coursebase",function(){M.course.coursebase.invoke_function("setup_for_resource","#"+a)});if(M.core.actionmenu&&M.core.actionmenu.newDOMNode){M.core.actionmenu.newDOMNode(g.one("#"+a))}},C=function(b,c){var d=a("#"+b),e="[data-action="+c+"]";if("groupsseparate"===c||"groupsvisible"===c||"groupsnone"===c){e="[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]"}if(d.find(e).is(":visible")){d.find(e).focus()}else{d.find(s.MENU).find(s.TOGGLE).focus()}},D=function(b){var c=a("a:visible"),d=!1,e=null;c.each(function(){if(a.contains(b[0],this)){d=!0}else if(d){e=this;return!1}return!0});return e},E=function(c,e,f){var g=f.attr("data-action"),h=w(c),i=b.call([{methodname:"core_course_edit_module",args:{id:e,action:g,sectionreturn:f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0}}],!0),j;if("duplicate"===g){j=y(f.closest(s.SECTIONLI))}a.when.apply(a,i).done(function(b){var d=D(c);c.replaceWith(b);var f=[];a("
"+b+"
").find(s.ACTIVITYLI).each(function(b){B(a(this).attr("id"));if(0===b){C(a(this).attr("id"),g);d=null}f.push(u(a(this)))});if(d){d.focus()}z(c,h,400);A(j,400);c.trigger(a.Event("coursemoduleedited",{ajaxreturn:b,action:g}));p.dispatch("legacyActivityAction",g,e,f)}).fail(function(b){z(c,h);A(j);var f=a.Event("coursemoduleeditfailed",{exception:b,action:g});c.trigger(f);if(!f.isDefaultPrevented()){d.exception(b)}})},F=function(c,d,e){if(e===void 0){e=p.sectionReturn}var f=a(c),g=w(f),h=b.call([{methodname:"core_course_get_module",args:{id:d,sectionreturn:e}}],!0);return new Promise(function(b,c){a.when.apply(a,h).done(function(a){z(f,g,400);L(a);b(a)}).fail(function(){z(f,g);c()})})},G=function(a,b){var c=a.attr("class").match(/modtype_([^\s]*)/)[1],f=v(a);e.get_string("pluginname",c).done(function(a){e.get_strings([{key:"confirm",component:"core"},{key:null===f?"deletechecktype":"deletechecktypename",param:{type:a,name:f}},{key:"yes"},{key:"no"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],b)})})},H=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)})},I=function(a,b,f,g,h){return e.get_strings([{key:f,component:g}]).then(function(d){a.find("span.menu-action-text").html(d[0]);return c.renderPix(b,"core")}).then(function(b){a.find(".icon").replaceWith(b);a.attr("data-action",h)}).catch(d.exception)},J=function(b,c,d,e,f){var g=c.attr("data-action");if("hide"===g||"show"===g){if("hide"===g){b.addClass("hidden");O(b[0],"hiddenfromstudents",!0);I(c,"i/show","showfromothers","format_"+e,"show")}else{O(b[0],"hiddenfromstudents",!1);b.removeClass("hidden");I(c,"i/hide","hidefromothers","format_"+e,"hide")}if(d.modules!==void 0){for(var h in d.modules){L(d.modules[h])}}if(d.section_availability!==void 0){b.find(".section_availability").first().replaceWith(d.section_availability)}var k=p.state.section.get(f);if(k!==void 0){p.dispatch("sectionState",[f])}}else if("setmarker"===g){var i=a(s.SECTIONLI+".current"),j=i.find(s.SECTIONACTIONMENU+" a[data-action=removemarker]");i.removeClass("current");I(j,"i/marker","highlight","core","setmarker");b.addClass("current");I(c,"i/marked","highlightoff","core","removemarker");p.dispatch("legacySectionAction",g,f);O(b[0],"highlighted",!0)}else if("removemarker"===g){b.removeClass("current");I(c,"i/marker","highlight","core","setmarker");p.dispatch("legacySectionAction",g,f);O(b[0],"highlighted",!1)}},K=function(a){var b=document.getElementById(a);if(!b||!b.contains(document.activeElement)){return}if(b.querySelector(s.ACTIONAREA).contains(document.activeElement)){return"".concat(s.ACTIONAREA," [tabindex=\"0\"]")}if(document.activeElement.id){return"#".concat(document.activeElement.id)}},L=function(b){a("
"+b+"
").find(s.ACTIVITYLI).each(function(){var c=a(this).attr("id"),d=K(c);a(s.ACTIVITYLI+"#"+c).replaceWith(b);B(c);if(d){var e,f=document.getElementById(c);null===(e=f.querySelector(d))||void 0===e?void 0:e.focus()}})},N=function(c,e,f,g){var h=f.attr("data-action"),i=f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0;if(p.supportComponents&&o.includes(h)){return!1}var j=x(c),k=b.call([{methodname:"core_course_edit_section",args:{id:e,action:h,sectionreturn:i}}],!0),l=y(c);a.when.apply(a,k).done(function(b){var d=a.parseJSON(b);z(c,j);A(l);c.find(s.SECTIONACTIONMENU).find(s.TOGGLE).focus();var i=a.Event("coursesectionedited",{ajaxreturn:d,action:h});c.trigger(i);if(!i.isDefaultPrevented()){J(c,f,d,g,e)}}).fail(function(b){z(c,j);A(l);var f=a.Event("coursesectioneditfailed",{exception:b,action:h});c.trigger(f);if(!f.isDefaultPrevented()){d.exception(b)}});return!0},O=function(a,b,e){var f=a.querySelector(s.SECTIONBADGES);if(!f){return}if(e){c.render("core_courseformat/local/content/section/badges",_defineProperty({},b,1)).then(function(a,b){c.prependNodeContents(f,a,b);return!0}).catch(d.exception)}else{var g=f.querySelector("[data-type=\""+b+"\"]");g.remove()}};g.use("moodle-course-coursebase",function(){M.course.coursebase.register_module({set_visibility_resource_ui:function set_visibility_resource_ui(b){var c=a(b.element.getDOMNode()),d=u(c);if(d){var e=c.find("."+r.EDITINGMOVE).attr("data-sectionreturn");F(c,d,e)}},updateMovedCmState:function updateMovedCmState(a){var b=p.state,c=b.cm.get(a.cmid);if(c!==void 0){p.dispatch("sectionState",[c.sectionid])}p.dispatch("cmState",[a.cmid])},updateMovedSectionState:function updateMovedSectionState(){p.dispatch("courseState")}})});p.addMutations({legacyActivityAction:function legacyActivityAction(a,b,c,d){var e=a.state,f=e.cm.get(c);if(f===void 0){return}var g=e.section.get(f.sectionid);if(g===void 0){return}p.dispatch("cmLock",[f.id],!0);a.setReadOnly(!1);f.locked=!1;switch(b){case"delete":g.cmlist=g.cmlist.reduce(function(a,b){if(b!=c){a.push(b)}return a},[]);e.cm.delete(c);break;case"hide":case"show":f.visible="show"===b?!0:!1;break;case"duplicate":p.dispatch("cmState",d);break;}a.setReadOnly(!0)},legacySectionAction:function legacySectionAction(a,b,c){var d=a.state,e=d.section.get(c);if(e===void 0){return}a.setReadOnly(!1);e.locked=!0;a.setReadOnly(!0);a.setReadOnly(!1);e.locked=!1;switch(b){case"setmarker":d.section.forEach(function(a){if(a.id!=c){a.current=!1}});e.current=!0;break;case"removemarker":e.current=!1;break;}a.setReadOnly(!0)}});return{initCoursePage:function initCoursePage(b){q=b;a("body").on("click keypress",s.ACTIVITYLI+" "+s.ACTIVITYACTION+"[data-action]",function(b){if("keypress"===b.type&&13!==b.keyCode){return}var c=a(this),d=c.closest(s.ACTIVITYLI),e=c.attr("data-action"),f=u(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;}if(!f){return}b.preventDefault();if("delete"===e){G(d,function(){E(d,f,c)})}else{E(d,f,c)}});a("body").on("click keypress",s.SECTIONLI+" "+s.SECTIONACTIONMENU+"[data-sectionid] a[data-action]",function(c){if("keypress"===c.type&&13!==c.keyCode){return}var d=a(this),e=d.closest(s.SECTIONLI),f=d.closest(s.SECTIONACTIONMENU).attr("data-sectionid"),g=!0;if(d.attr("data-confirm")){H(d.attr("data-confirm"),function(){g=N(e,f,d,b)})}else{g=N(e,f,d,b)}if(g){c.preventDefault()}});a("body").on("updated","".concat(s.SECTIONLI," [data-inplaceeditable]"),function(a){if(a.ajaxreturn&&a.ajaxreturn.itemid){var b=p.state,c=b.section.get(a.ajaxreturn.itemid);if(c!==void 0){p.dispatch("sectionState",[a.ajaxreturn.itemid])}}});a("body").on("updated","".concat(s.ACTIVITYLI," [data-inplaceeditable]"),function(a){if(a.ajaxreturn&&a.ajaxreturn.itemid){p.dispatch("cmState",[a.ajaxreturn.itemid])}});if(p.supportComponents&&o.includes("addSection")){return}e.get_string("numberweeks").done(function(b){var c=a(s.ADDSECTIONS),d=c.attr("data-add-sections"),e=c.attr("data-new-sections"),f=a("
");f.find("label").html(b);h.create({title:d,type:h.types.SAVE_CANCEL,body:f.html()},c).done(function(b){var e=a(b.getBody()).find("#add_section_numsections"),f=function(){if(""+parseInt(e.val())===e.val()&&1<=parseInt(e.val())){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){if(a.keyCode===j.enter){f()}})});b.getRoot().on(i.save,function(a){a.preventDefault();f()})})})},replaceSectionActionItem:function replaceSectionActionItem(a,b,c,d,e,f){k.debug("replaceSectionActionItem() is deprecated and will be removed.");var g=a.find(s.SECTIONACTIONMENU+" "+b);I(g,c,d,e,f)},refreshModule:F,refreshSection:function refreshSection(c,e,f){if(f===void 0){f=p.sectionReturn}var g=a(c),h="refresh",i=b.call([{methodname:"core_course_edit_section",args:{id:e,action:h,sectionreturn:f}}],!0),j=x(g);return new Promise(function(b,c){a.when.apply(a,i).done(function(c){z(g,j);var d=a.parseJSON(c),f=a(d.content);g.replaceWith(f);a("".concat(s.SECTIONLI,"#").concat(e," ").concat(s.ACTIVITYLI)).each(function(a,b){B(b.data("id"))});var i=t(n.sectionRefreshed,{ajaxreturn:d,action:h,newSectionElement:f.get(0)},f);if(!i.defaultPrevented){J(f,a(s.SECTIONLI+"#"+e),d,q,e)}b(d)}).fail(function(a){var b=t("coursesectionrefreshfailed",{exception:a,action:h},g);if(!b.defaultPrevented){d.exception(a)}c()})})}}}); +function _defineProperty(a,b,c){if(b in a){Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0})}else{a[b]=c}return a}define ("core_course/actions",["jquery","core/ajax","core/templates","core/notification","core/str","core/url","core/yui","core/modal_factory","core/modal_events","core/key_codes","core/log","core_courseformat/courseeditor","core/event_dispatcher","core_course/events"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n){var o=["moveSection","moveCm","addSection","deleteSection"],p=l.getCurrentCourseEditor(),q,r={EDITINPROGRESS:"editinprogress",SECTIONDRAGGABLE:"sectiondraggable",EDITINGMOVE:"editing_move"},s={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]",SECTIONBADGES:"[data-region=\"sectionbadges\"]"};g.use("moodle-course-coursebase",function(){var a=M.course.format.get_section_selector();if(a){s.SECTIONLI=a}});var t=function(a,b,c,d){if(!(c instanceof Element)&&c.get!==void 0){c=c.get(0)}return m.dispatchEvent(a,b,c,d)},u=function(a){var b=a.get(0);if(b.dataset.id){return b.dataset.id}var c;g.use("moodle-course-util",function(a){c=a.Moodle.core_course.util.cm.getId(a.Node(b))});return c},v=function(a){var b;g.use("moodle-course-util",function(c){b=c.Moodle.core_course.util.cm.getName(c.Node(a.get(0)))});var c=p.state,d=u(a);if(!b&&c&&d){var e;b=null===(e=c.cm.get(d))||void 0===e?void 0:e.name}return b},w=function(a){a.addClass(r.EDITINPROGRESS);var b=a.find(s.ACTIONAREA).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));c.show();if(a.data("id")!==void 0){p.dispatch("cmLock",[a.data("id")],!0)}return c}return null},x=function(a){a.addClass(r.EDITINPROGRESS);var b=a.find(s.SECTIONACTIONMENU).get(0);if(b){var c=M.util.add_spinner(g,g.Node(b));c.show();if(a.data("id")!==void 0){p.dispatch("sectionLock",[a.data("id")],!0)}return c}return null},y=function(a){var b=a.get(0),c=M.util.add_lightbox(g,g.Node(b));if("section"==b.dataset.for&&b.dataset.id){p.dispatch("sectionLock",[b.dataset.id],!0);c.setAttribute("data-state","section");c.setAttribute("data-state-id",b.dataset.id)}c.show();return c},z=function(a,b,c){window.setTimeout(function(){a.removeClass(r.EDITINPROGRESS);if(b){b.hide()}if(a.data("id")!==void 0){var c="section"===a.data("for")?"sectionLock":"cmLock";p.dispatch(c,[a.data("id")],!1)}},c)},A=function(a,b){if(a){window.setTimeout(function(){a.hide();if(a.getAttribute("data-state")){p.dispatch("".concat(a.getAttribute("data-state"),"Lock"),[a.getAttribute("data-state-id")],!1)}},b)}},B=function(a){g.use("moodle-course-coursebase",function(){M.course.coursebase.invoke_function("setup_for_resource","#"+a)});if(M.core.actionmenu&&M.core.actionmenu.newDOMNode){M.core.actionmenu.newDOMNode(g.one("#"+a))}},C=function(b,c){var d=a("#"+b),e="[data-action="+c+"]";if("groupsseparate"===c||"groupsvisible"===c||"groupsnone"===c){e="[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]"}if(d.find(e).is(":visible")){d.find(e).focus()}else{d.find(s.MENU).find(s.TOGGLE).focus()}},D=function(b){var c=a("a:visible"),d=!1,e=null;c.each(function(){if(a.contains(b[0],this)){d=!0}else if(d){e=this;return!1}return!0});return e},E=function(c,e,f){var g=f.attr("data-action"),h=w(c),i=b.call([{methodname:"core_course_edit_module",args:{id:e,action:g,sectionreturn:f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0}}],!0),j;if("duplicate"===g){j=y(f.closest(s.SECTIONLI))}a.when.apply(a,i).done(function(b){var d=D(c);c.replaceWith(b);var f=[];a("
"+b+"
").find(s.ACTIVITYLI).each(function(b){B(a(this).attr("id"));if(0===b){C(a(this).attr("id"),g);d=null}f.push(u(a(this)))});if(d){d.focus()}z(c,h,400);A(j,400);c.trigger(a.Event("coursemoduleedited",{ajaxreturn:b,action:g}));p.dispatch("legacyActivityAction",g,e,f)}).fail(function(b){z(c,h);A(j);var f=a.Event("coursemoduleeditfailed",{exception:b,action:g});c.trigger(f);if(!f.isDefaultPrevented()){d.exception(b)}})},F=function(c,d,e){if(e===void 0){e=p.sectionReturn}var f=a(c),g=w(f),h=b.call([{methodname:"core_course_get_module",args:{id:d,sectionreturn:e}}],!0);return new Promise(function(b,c){a.when.apply(a,h).done(function(a){z(f,g,400);L(a);b(a)}).fail(function(){z(f,g);c()})})},G=function(a,b){var c=a.attr("class").match(/modtype_([^\s]*)/)[1],f=v(a);e.get_string("pluginname",c).done(function(a){e.get_strings([{key:"confirm",component:"core"},{key:null===f?"deletechecktype":"deletechecktypename",param:{type:a,name:f}},{key:"yes"},{key:"no"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],b)})})},H=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)})},I=function(a,b,f,g,h){return e.get_strings([{key:f,component:g}]).then(function(d){a.find("span.menu-action-text").html(d[0]);return c.renderPix(b,"core")}).then(function(b){a.find(".icon").replaceWith(b);a.attr("data-action",h)}).catch(d.exception)},J=function(b,c,d,e,f){var g=c.attr("data-action");if("hide"===g||"show"===g){if("hide"===g){b.addClass("hidden");O(b[0],"hiddenfromstudents",!0);I(c,"i/show","showfromothers","format_"+e,"show")}else{O(b[0],"hiddenfromstudents",!1);b.removeClass("hidden");I(c,"i/hide","hidefromothers","format_"+e,"hide")}if(d.modules!==void 0){for(var h in d.modules){L(d.modules[h])}}if(d.section_availability!==void 0){b.find(".section_availability").first().replaceWith(d.section_availability)}var k=p.state.section.get(f);if(k!==void 0){p.dispatch("sectionState",[f])}}else if("setmarker"===g){var i=a(s.SECTIONLI+".current"),j=i.find(s.SECTIONACTIONMENU+" a[data-action=removemarker]");i.removeClass("current");I(j,"i/marker","highlight","core","setmarker");b.addClass("current");I(c,"i/marked","highlightoff","core","removemarker");p.dispatch("legacySectionAction",g,f);O(b[0],"highlighted",!0)}else if("removemarker"===g){b.removeClass("current");I(c,"i/marker","highlight","core","setmarker");p.dispatch("legacySectionAction",g,f);O(b[0],"highlighted",!1)}},K=function(a){var b=document.getElementById(a);if(!b||!b.contains(document.activeElement)){return}if(b.querySelector(s.ACTIONAREA).contains(document.activeElement)){return"".concat(s.ACTIONAREA," [tabindex=\"0\"]")}if(document.activeElement.id){return"#".concat(document.activeElement.id)}},L=function(b){a("
"+b+"
").find(s.ACTIVITYLI).each(function(){var c=a(this).attr("id"),d=K(c);a(s.ACTIVITYLI+"#"+c).replaceWith(b);B(c);if(d){var e,f=document.getElementById(c);null===(e=f.querySelector(d))||void 0===e?void 0:e.focus()}})},N=function(c,e,f,g){var h=f.attr("data-action"),i=f.attr("data-sectionreturn")?f.attr("data-sectionreturn"):0;if(p.supportComponents&&o.includes(h)){return!1}var j=x(c),k=b.call([{methodname:"core_course_edit_section",args:{id:e,action:h,sectionreturn:i}}],!0),l=y(c);a.when.apply(a,k).done(function(b){var d=a.parseJSON(b);z(c,j);A(l);c.find(s.SECTIONACTIONMENU).find(s.TOGGLE).focus();var i=a.Event("coursesectionedited",{ajaxreturn:d,action:h});c.trigger(i);if(!i.isDefaultPrevented()){J(c,f,d,g,e)}}).fail(function(b){z(c,j);A(l);var f=a.Event("coursesectioneditfailed",{exception:b,action:h});c.trigger(f);if(!f.isDefaultPrevented()){d.exception(b)}});return!0},O=function(a,b,e){var f=a.querySelector(s.SECTIONBADGES);if(!f){return}if(e){c.render("core_courseformat/local/content/section/badges",_defineProperty({},b,1)).then(function(a,b){c.prependNodeContents(f,a,b);return!0}).catch(d.exception)}else{var g=f.querySelector("[data-type=\""+b+"\"]");g.remove()}};g.use("moodle-course-coursebase",function(){M.course.coursebase.register_module({set_visibility_resource_ui:function set_visibility_resource_ui(b){var c=a(b.element.getDOMNode()),d=u(c);if(d){var e=c.find("."+r.EDITINGMOVE).attr("data-sectionreturn");F(c,d,e)}},updateMovedCmState:function updateMovedCmState(a){var b=p.state,c=b.cm.get(a.cmid);if(c!==void 0){p.dispatch("sectionState",[c.sectionid])}p.dispatch("cmState",[a.cmid])},updateMovedSectionState:function updateMovedSectionState(){p.dispatch("courseState")}})});p.addMutations({legacyActivityAction:function legacyActivityAction(a,b,c,d){var e=a.state,f=e.cm.get(c);if(f===void 0){return}var g=e.section.get(f.sectionid);if(g===void 0){return}p.dispatch("cmLock",[f.id],!0);a.setReadOnly(!1);f.locked=!1;switch(b){case"delete":g.cmlist=g.cmlist.reduce(function(a,b){if(b!=c){a.push(b)}return a},[]);e.cm.delete(c);break;case"hide":case"show":case"duplicate":p.dispatch("cmState",d);break;}a.setReadOnly(!0)},legacySectionAction:function legacySectionAction(a,b,c){var d=a.state,e=d.section.get(c);if(e===void 0){return}a.setReadOnly(!1);e.locked=!0;a.setReadOnly(!0);a.setReadOnly(!1);e.locked=!1;switch(b){case"setmarker":d.section.forEach(function(a){if(a.id!=c){a.current=!1}});e.current=!0;break;case"removemarker":e.current=!1;break;}a.setReadOnly(!0)}});return{initCoursePage:function initCoursePage(b){q=b;a("body").on("click keypress",s.ACTIVITYLI+" "+s.ACTIVITYACTION+"[data-action]",function(b){if("keypress"===b.type&&13!==b.keyCode){return}var c=a(this),d=c.closest(s.ACTIVITYLI),e=c.attr("data-action"),f=u(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;}if(!f){return}b.preventDefault();if("delete"===e){G(d,function(){E(d,f,c)})}else{E(d,f,c)}});a("body").on("click keypress",s.SECTIONLI+" "+s.SECTIONACTIONMENU+"[data-sectionid] a[data-action]",function(c){if("keypress"===c.type&&13!==c.keyCode){return}var d=a(this),e=d.closest(s.SECTIONLI),f=d.closest(s.SECTIONACTIONMENU).attr("data-sectionid"),g=!0;if(d.attr("data-confirm")){H(d.attr("data-confirm"),function(){g=N(e,f,d,b)})}else{g=N(e,f,d,b)}if(g){c.preventDefault()}});a("body").on("updated","".concat(s.SECTIONLI," [data-inplaceeditable]"),function(a){if(a.ajaxreturn&&a.ajaxreturn.itemid){var b=p.state,c=b.section.get(a.ajaxreturn.itemid);if(c!==void 0){p.dispatch("sectionState",[a.ajaxreturn.itemid])}}});a("body").on("updated","".concat(s.ACTIVITYLI," [data-inplaceeditable]"),function(a){if(a.ajaxreturn&&a.ajaxreturn.itemid){p.dispatch("cmState",[a.ajaxreturn.itemid])}});if(p.supportComponents&&o.includes("addSection")){return}e.get_string("numberweeks").done(function(b){var c=a(s.ADDSECTIONS),d=c.attr("data-add-sections"),e=c.attr("data-new-sections"),f=a("
");f.find("label").html(b);h.create({title:d,type:h.types.SAVE_CANCEL,body:f.html()},c).done(function(b){var e=a(b.getBody()).find("#add_section_numsections"),f=function(){if(""+parseInt(e.val())===e.val()&&1<=parseInt(e.val())){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){if(a.keyCode===j.enter){f()}})});b.getRoot().on(i.save,function(a){a.preventDefault();f()})})})},replaceSectionActionItem:function replaceSectionActionItem(a,b,c,d,e,f){k.debug("replaceSectionActionItem() is deprecated and will be removed.");var g=a.find(s.SECTIONACTIONMENU+" "+b);I(g,c,d,e,f)},refreshModule:F,refreshSection:function refreshSection(c,e,f){if(f===void 0){f=p.sectionReturn}var g=a(c),h="refresh",i=b.call([{methodname:"core_course_edit_section",args:{id:e,action:h,sectionreturn:f}}],!0),j=x(g);return new Promise(function(b,c){a.when.apply(a,i).done(function(c){z(g,j);var d=a.parseJSON(c),f=a(d.content);g.replaceWith(f);a("".concat(s.SECTIONLI,"#").concat(e," ").concat(s.ACTIVITYLI)).each(function(a,b){B(b.data("id"))});var i=t(n.sectionRefreshed,{ajaxreturn:d,action:h,newSectionElement:f.get(0)},f);if(!i.defaultPrevented){J(f,a(s.SECTIONLI+"#"+e),d,q,e)}b(d)}).fail(function(a){var b=t("coursesectionrefreshfailed",{exception:a,action:h},g);if(!b.defaultPrevented){d.exception(a)}c()})})}}}); //# sourceMappingURL=actions.min.js.map diff --git a/course/amd/build/actions.min.js.map b/course/amd/build/actions.min.js.map index 21d88e03ced..bab3b1c0b20 100644 --- a/course/amd/build/actions.min.js.map +++ b/course/amd/build/actions.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/actions.js"],"names":["define","$","ajax","templates","notification","str","url","Y","ModalFactory","ModalEvents","KeyCodes","log","editor","EventDispatcher","CourseEvents","componentActions","courseeditor","getCurrentCourseEditor","formatname","CSS","EDITINPROGRESS","SECTIONDRAGGABLE","EDITINGMOVE","SELECTOR","ACTIVITYLI","ACTIONAREA","ACTIVITYACTION","MENU","TOGGLE","SECTIONLI","SECTIONACTIONMENU","ADDSECTIONS","SECTIONBADGES","use","courseformatselector","M","course","format","get_section_selector","dispatchEvent","eventName","detail","container","options","Element","get","getModuleId","element","item","dataset","id","Moodle","core_course","util","cm","getId","Node","getModuleName","name","getName","state","cmid","addActivitySpinner","activity","addClass","actionarea","find","spinner","add_spinner","show","data","dispatch","addSectionSpinner","sectionelement","addSectionLightbox","lightbox","add_lightbox","for","setAttribute","removeSpinner","delay","window","setTimeout","removeClass","hide","mutation","removeLightbox","getAttribute","initActionMenu","elementid","coursebase","invoke_function","core","actionmenu","newDOMNode","one","focusActionItem","elementId","action","mainelement","selector","is","focus","findNextFocusable","mainElement","tabables","isInside","foundElement","each","contains","editModule","moduleElement","target","attr","promises","call","methodname","args","sectionreturn","closest","when","apply","done","elementToFocus","replaceWith","affectedids","index","push","trigger","Event","ajaxreturn","fail","ex","e","exception","isDefaultPrevented","refreshModule","sectionReturn","activityElement","Promise","resolve","reject","replaceActivityHtmlWith","confirmDeleteModule","onconfirm","modtypename","match","modulename","get_string","pluginname","get_strings","key","component","param","type","s","confirm","confirmEditSection","message","replaceActionItem","actionitem","image","stringname","stringcomponent","newaction","then","strings","html","renderPix","pixhtml","catch","defaultEditSectionHandler","sectionElement","actionItem","courseformat","sectionid","setSectionBadge","modules","i","section_availability","first","section","oldmarker","oldActionItem","getActivityFocusedElement","document","getElementById","activeElement","querySelector","activityHTML","focusedPath","newItem","editSection","supportComponents","includes","dataencoded","parseJSON","badgetype","add","sectionbadges","render","js","prependNodeContents","badge","remove","register_module","set_visibility_resource_ui","getDOMNode","updateMovedCmState","params","updateMovedSectionState","addMutations","legacyActivityAction","statemanager","setReadOnly","locked","cmlist","reduce","current","delete","visible","legacySectionAction","forEach","initCoursePage","on","keyCode","moduleId","preventDefault","sectionId","isExecuted","itemid","strNumberSections","modalTitle","newSections","modalBody","create","title","types","SAVE_CANCEL","body","modal","numSections","getBody","addSections","parseInt","val","location","setSaveButtonText","getRoot","shown","select","enter","save","replaceSectionActionItem","debug","refreshSection","newSectionElement","content","event","sectionRefreshed","defaultPrevented"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Various actions on modules and sections in the editing mode - hiding, duplicating, deleting, etc.\n *\n * @module core_course/actions\n * @copyright 2016 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.3\n */\ndefine(\n [\n 'jquery',\n 'core/ajax',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/url',\n 'core/yui',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/key_codes',\n 'core/log',\n 'core_courseformat/courseeditor',\n 'core/event_dispatcher',\n 'core_course/events'\n ],\n function(\n $,\n ajax,\n templates,\n notification,\n str,\n url,\n Y,\n ModalFactory,\n ModalEvents,\n KeyCodes,\n log,\n editor,\n EventDispatcher,\n CourseEvents\n ) {\n\n // Eventually, core_courseformat/local/content/actions will handle all actions for\n // component compatible formats and the default actions.js won't be necessary anymore.\n // Meanwhile, we filter the migrated actions.\n const componentActions = ['moveSection', 'moveCm', 'addSection', 'deleteSection'];\n\n // The course reactive instance.\n const courseeditor = editor.getCurrentCourseEditor();\n\n // The current course format name (loaded on init).\n let formatname;\n\n var CSS = {\n EDITINPROGRESS: 'editinprogress',\n SECTIONDRAGGABLE: 'sectiondraggable',\n EDITINGMOVE: 'editing_move'\n };\n var SELECTOR = {\n ACTIVITYLI: 'li.activity',\n ACTIONAREA: '.actions',\n ACTIVITYACTION: 'a.cm-edit-action',\n MENU: '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',\n TOGGLE: '.toggle-display,.dropdown-toggle',\n SECTIONLI: 'li.section',\n SECTIONACTIONMENU: '.section_action_menu',\n ADDSECTIONS: '.changenumsections [data-add-sections]',\n SECTIONBADGES: '[data-region=\"sectionbadges\"]',\n };\n\n Y.use('moodle-course-coursebase', function() {\n var courseformatselector = M.course.format.get_section_selector();\n if (courseformatselector) {\n SELECTOR.SECTIONLI = courseformatselector;\n }\n });\n\n /**\n * Dispatch event wrapper.\n *\n * Old jQuery events will be replaced by native events gradually.\n *\n * @method dispatchEvent\n * @param {String} eventName The name of the event\n * @param {Object} detail Any additional details to pass into the eveent\n * @param {Node|HTMLElement} container The point at which to dispatch the event\n * @param {Object} options\n * @param {Boolean} options.bubbles Whether to bubble up the DOM\n * @param {Boolean} options.cancelable Whether preventDefault() can be called\n * @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM boundary\n * @returns {CustomEvent}\n */\n const dispatchEvent = function(eventName, detail, container, options) {\n // Most actions still uses jQuery node instead of regular HTMLElement.\n if (!(container instanceof Element) && container.get !== undefined) {\n container = container.get(0);\n }\n return EventDispatcher.dispatchEvent(eventName, detail, container, options);\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getId\n *\n * @param {JQuery} element\n * @returns {Integer}\n */\n var getModuleId = function(element) {\n // Check if we have a data-id first.\n const item = element.get(0);\n if (item.dataset.id) {\n return item.dataset.id;\n }\n // Use YUI way if data-id is not present.\n let id;\n Y.use('moodle-course-util', function(Y) {\n id = Y.Moodle.core_course.util.cm.getId(Y.Node(item));\n });\n return id;\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getName\n *\n * @param {JQuery} element\n * @returns {String}\n */\n var getModuleName = function(element) {\n var name;\n Y.use('moodle-course-util', function(Y) {\n name = Y.Moodle.core_course.util.cm.getName(Y.Node(element.get(0)));\n });\n // Check if we have the name in the course state.\n const state = courseeditor.state;\n const cmid = getModuleId(element);\n if (!name && state && cmid) {\n name = state.cm.get(cmid)?.name;\n }\n return name;\n };\n\n /**\n * Wrapper for M.util.add_spinner for an activity\n *\n * @param {JQuery} activity\n * @returns {Node}\n */\n var addActivitySpinner = function(activity) {\n activity.addClass(CSS.EDITINPROGRESS);\n var actionarea = activity.find(SELECTOR.ACTIONAREA).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the activity state element.\n if (activity.data('id') !== undefined) {\n courseeditor.dispatch('cmLock', [activity.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_spinner for a section\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionSpinner = function(sectionelement) {\n sectionelement.addClass(CSS.EDITINPROGRESS);\n var actionarea = sectionelement.find(SELECTOR.SECTIONACTIONMENU).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the section state element.\n if (sectionelement.data('id') !== undefined) {\n courseeditor.dispatch('sectionLock', [sectionelement.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_lightbox\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionLightbox = function(sectionelement) {\n const item = sectionelement.get(0);\n var lightbox = M.util.add_lightbox(Y, Y.Node(item));\n if (item.dataset.for == 'section' && item.dataset.id) {\n courseeditor.dispatch('sectionLock', [item.dataset.id], true);\n lightbox.setAttribute('data-state', 'section');\n lightbox.setAttribute('data-state-id', item.dataset.id);\n }\n lightbox.show();\n return lightbox;\n };\n\n /**\n * Removes the spinner element\n *\n * @param {JQuery} element\n * @param {Node} spinner\n * @param {Number} delay\n */\n var removeSpinner = function(element, spinner, delay) {\n window.setTimeout(function() {\n element.removeClass(CSS.EDITINPROGRESS);\n if (spinner) {\n spinner.hide();\n }\n // Unlock the state element.\n if (element.data('id') !== undefined) {\n const mutation = (element.data('for') === 'section') ? 'sectionLock' : 'cmLock';\n courseeditor.dispatch(mutation, [element.data('id')], false);\n }\n }, delay);\n };\n\n /**\n * Removes the lightbox element\n *\n * @param {Node} lightbox lighbox YUI element returned by addSectionLightbox\n * @param {Number} delay\n */\n var removeLightbox = function(lightbox, delay) {\n if (lightbox) {\n window.setTimeout(function() {\n lightbox.hide();\n // Unlock state if necessary.\n if (lightbox.getAttribute('data-state')) {\n courseeditor.dispatch(\n `${lightbox.getAttribute('data-state')}Lock`,\n [lightbox.getAttribute('data-state-id')],\n false\n );\n }\n }, delay);\n }\n };\n\n /**\n * Initialise action menu for the element (section or module)\n *\n * @param {String} elementid CSS id attribute of the element\n */\n var initActionMenu = function(elementid) {\n // Initialise action menu in the new activity.\n Y.use('moodle-course-coursebase', function() {\n M.course.coursebase.invoke_function('setup_for_resource', '#' + elementid);\n });\n if (M.core.actionmenu && M.core.actionmenu.newDOMNode) {\n M.core.actionmenu.newDOMNode(Y.one('#' + elementid));\n }\n };\n\n /**\n * Returns focus to the element that was clicked or \"Edit\" link if element is no longer visible.\n *\n * @param {String} elementId CSS id attribute of the element\n * @param {String} action data-action property of the element that was clicked\n */\n var focusActionItem = function(elementId, action) {\n var mainelement = $('#' + elementId);\n var selector = '[data-action=' + action + ']';\n if (action === 'groupsseparate' || action === 'groupsvisible' || action === 'groupsnone') {\n // New element will have different data-action.\n selector = '[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]';\n }\n if (mainelement.find(selector).is(':visible')) {\n mainelement.find(selector).focus();\n } else {\n // Element not visible, focus the \"Edit\" link.\n mainelement.find(SELECTOR.MENU).find(SELECTOR.TOGGLE).focus();\n }\n };\n\n /**\n * Find next after the element\n *\n * @param {JQuery} mainElement element that is about to be deleted\n * @returns {JQuery}\n */\n var findNextFocusable = function(mainElement) {\n var tabables = $(\"a:visible\");\n var isInside = false;\n var foundElement = null;\n tabables.each(function() {\n if ($.contains(mainElement[0], this)) {\n isInside = true;\n } else if (isInside) {\n foundElement = this;\n return false; // Returning false in .each() is equivalent to \"break;\" inside the loop in php.\n }\n return true;\n });\n return foundElement;\n };\n\n /**\n * Performs an action on a module (moving, deleting, duplicating, hiding, etc.)\n *\n * @param {JQuery} moduleElement activity element we perform action on\n * @param {Number} cmid\n * @param {JQuery} target the element (menu item) that was clicked\n */\n var editModule = function(moduleElement, cmid, target) {\n var action = target.attr('data-action');\n var spinner = addActivitySpinner(moduleElement);\n var promises = ajax.call([{\n methodname: 'core_course_edit_module',\n args: {id: cmid,\n action: action,\n sectionreturn: target.attr('data-sectionreturn') ? target.attr('data-sectionreturn') : 0\n }\n }], true);\n\n var lightbox;\n if (action === 'duplicate') {\n lightbox = addSectionLightbox(target.closest(SELECTOR.SECTIONLI));\n }\n $.when.apply($, promises)\n .done(function(data) {\n var elementToFocus = findNextFocusable(moduleElement);\n moduleElement.replaceWith(data);\n let affectedids = [];\n // Initialise action menu for activity(ies) added as a result of this.\n $('
' + data + '
').find(SELECTOR.ACTIVITYLI).each(function(index) {\n initActionMenu($(this).attr('id'));\n if (index === 0) {\n focusActionItem($(this).attr('id'), action);\n elementToFocus = null;\n }\n // Save any activity id in cmids.\n affectedids.push(getModuleId($(this)));\n });\n // In case of activity deletion focus the next focusable element.\n if (elementToFocus) {\n elementToFocus.focus();\n }\n // Remove spinner and lightbox with a delay.\n removeSpinner(moduleElement, spinner, 400);\n removeLightbox(lightbox, 400);\n // Trigger event that can be observed by course formats.\n moduleElement.trigger($.Event('coursemoduleedited', {ajaxreturn: data, action: action}));\n\n // Modify cm state.\n courseeditor.dispatch('legacyActivityAction', action, cmid, affectedids);\n\n }).fail(function(ex) {\n // Remove spinner and lightbox.\n removeSpinner(moduleElement, spinner);\n removeLightbox(lightbox);\n // Trigger event that can be observed by course formats.\n var e = $.Event('coursemoduleeditfailed', {exception: ex, action: action});\n moduleElement.trigger(e);\n if (!e.isDefaultPrevented()) {\n notification.exception(ex);\n }\n });\n };\n\n /**\n * Requests html for the module via WS core_course_get_module and updates the module on the course page\n *\n * Used after d&d of the module to another section\n *\n * @param {JQuery|Element} element\n * @param {Number} cmid\n * @param {Number} sectionreturn\n * @return {Promise} the refresh promise\n */\n var refreshModule = function(element, cmid, sectionreturn) {\n\n if (sectionreturn === undefined) {\n sectionreturn = courseeditor.sectionReturn;\n }\n\n const activityElement = $(element);\n var spinner = addActivitySpinner(activityElement);\n var promises = ajax.call([{\n methodname: 'core_course_get_module',\n args: {id: cmid, sectionreturn: sectionreturn}\n }], true);\n\n return new Promise((resolve, reject) => {\n $.when.apply($, promises)\n .done(function(data) {\n removeSpinner(activityElement, spinner, 400);\n replaceActivityHtmlWith(data);\n resolve(data);\n }).fail(function() {\n removeSpinner(activityElement, spinner);\n reject();\n });\n });\n };\n\n /**\n * Requests html for the section via WS core_course_edit_section and updates the section on the course page\n *\n * @param {JQuery|Element} element\n * @param {Number} sectionid\n * @param {Number} sectionreturn\n * @return {Promise} the refresh promise\n */\n var refreshSection = function(element, sectionid, sectionreturn) {\n\n if (sectionreturn === undefined) {\n sectionreturn = courseeditor.sectionReturn;\n }\n\n const sectionElement = $(element);\n const action = 'refresh';\n const promises = ajax.call([{\n methodname: 'core_course_edit_section',\n args: {id: sectionid, action, sectionreturn},\n }], true);\n\n var spinner = addSectionSpinner(sectionElement);\n return new Promise((resolve, reject) => {\n $.when.apply($, promises)\n .done(dataencoded => {\n\n removeSpinner(sectionElement, spinner);\n const data = $.parseJSON(dataencoded);\n\n const newSectionElement = $(data.content);\n sectionElement.replaceWith(newSectionElement);\n\n // Init modules menus.\n $(`${SELECTOR.SECTIONLI}#${sectionid} ${SELECTOR.ACTIVITYLI}`).each(\n (index, activity) => {\n initActionMenu(activity.data('id'));\n }\n );\n\n // Trigger event that can be observed by course formats.\n const event = dispatchEvent(\n CourseEvents.sectionRefreshed,\n {\n ajaxreturn: data,\n action: action,\n newSectionElement: newSectionElement.get(0),\n },\n newSectionElement\n );\n\n if (!event.defaultPrevented) {\n defaultEditSectionHandler(\n newSectionElement, $(SELECTOR.SECTIONLI + '#' + sectionid),\n data,\n formatname,\n sectionid\n );\n }\n resolve(data);\n }).fail(ex => {\n // Trigger event that can be observed by course formats.\n const event = dispatchEvent(\n 'coursesectionrefreshfailed',\n {exception: ex, action: action},\n sectionElement\n );\n if (!event.defaultPrevented) {\n notification.exception(ex);\n }\n reject();\n });\n });\n };\n\n /**\n * Displays the delete confirmation to delete a module\n *\n * @param {JQuery} mainelement activity element we perform action on\n * @param {function} onconfirm function to execute on confirm\n */\n var confirmDeleteModule = function(mainelement, onconfirm) {\n var modtypename = mainelement.attr('class').match(/modtype_([^\\s]*)/)[1];\n var modulename = getModuleName(mainelement);\n\n str.get_string('pluginname', modtypename).done(function(pluginname) {\n var plugindata = {\n type: pluginname,\n name: modulename\n };\n str.get_strings([\n {key: 'confirm', component: 'core'},\n {key: modulename === null ? 'deletechecktype' : 'deletechecktypename', param: plugindata},\n {key: 'yes'},\n {key: 'no'}\n ]).done(function(s) {\n notification.confirm(s[0], s[1], s[2], s[3], onconfirm);\n }\n );\n });\n };\n\n /**\n * Displays the delete confirmation to delete a section\n *\n * @param {String} message confirmation message\n * @param {function} onconfirm function to execute on confirm\n */\n var confirmEditSection = function(message, onconfirm) {\n str.get_strings([\n {key: 'confirm'}, // TODO link text\n {key: 'yes'},\n {key: 'no'}\n ]).done(function(s) {\n notification.confirm(s[0], message, s[1], s[2], onconfirm);\n }\n );\n };\n\n /**\n * Replaces an action menu item with another one (for example Show->Hide, Set marker->Remove marker)\n *\n * @param {JQuery} actionitem\n * @param {String} image new image name (\"i/show\", \"i/hide\", etc.)\n * @param {String} stringname new string for the action menu item\n * @param {String} stringcomponent\n * @param {String} newaction new value for data-action attribute of the link\n * @return {Promise} promise which is resolved when the replacement has completed\n */\n var replaceActionItem = function(actionitem, image, stringname,\n stringcomponent, newaction) {\n\n var stringRequests = [{key: stringname, component: stringcomponent}];\n // Do not provide an icon with duplicate, different text to the menu item.\n\n return str.get_strings(stringRequests).then(function(strings) {\n actionitem.find('span.menu-action-text').html(strings[0]);\n\n return templates.renderPix(image, 'core');\n }).then(function(pixhtml) {\n actionitem.find('.icon').replaceWith(pixhtml);\n actionitem.attr('data-action', newaction);\n return;\n }).catch(notification.exception);\n };\n\n /**\n * Default post-processing for section AJAX edit actions.\n *\n * This can be overridden in course formats by listening to event coursesectionedited:\n *\n * $('body').on('coursesectionedited', 'li.section', function(e) {\n * var action = e.action,\n * sectionElement = $(e.target),\n * data = e.ajaxreturn;\n * // ... Do some processing here.\n * e.preventDefault(); // Prevent default handler.\n * });\n *\n * @param {JQuery} sectionElement\n * @param {JQuery} actionItem\n * @param {Object} data\n * @param {String} courseformat\n * @param {Number} sectionid\n */\n var defaultEditSectionHandler = function(sectionElement, actionItem, data, courseformat, sectionid) {\n var action = actionItem.attr('data-action');\n if (action === 'hide' || action === 'show') {\n if (action === 'hide') {\n sectionElement.addClass('hidden');\n setSectionBadge(sectionElement[0], 'hiddenfromstudents', true);\n replaceActionItem(actionItem, 'i/show',\n 'showfromothers', 'format_' + courseformat, 'show');\n } else {\n setSectionBadge(sectionElement[0], 'hiddenfromstudents', false);\n sectionElement.removeClass('hidden');\n replaceActionItem(actionItem, 'i/hide',\n 'hidefromothers', 'format_' + courseformat, 'hide');\n }\n // Replace the modules with new html (that indicates that they are now hidden or not hidden).\n if (data.modules !== undefined) {\n for (var i in data.modules) {\n replaceActivityHtmlWith(data.modules[i]);\n }\n }\n // Replace the section availability information.\n if (data.section_availability !== undefined) {\n sectionElement.find('.section_availability').first().replaceWith(data.section_availability);\n }\n // Modify course state.\n const section = courseeditor.state.section.get(sectionid);\n if (section !== undefined) {\n courseeditor.dispatch('sectionState', [sectionid]);\n }\n } else if (action === 'setmarker') {\n var oldmarker = $(SELECTOR.SECTIONLI + '.current'),\n oldActionItem = oldmarker.find(SELECTOR.SECTIONACTIONMENU + ' ' + 'a[data-action=removemarker]');\n oldmarker.removeClass('current');\n replaceActionItem(oldActionItem, 'i/marker',\n 'highlight', 'core', 'setmarker');\n sectionElement.addClass('current');\n replaceActionItem(actionItem, 'i/marked',\n 'highlightoff', 'core', 'removemarker');\n courseeditor.dispatch('legacySectionAction', action, sectionid);\n setSectionBadge(sectionElement[0], 'highlighted', true);\n } else if (action === 'removemarker') {\n sectionElement.removeClass('current');\n replaceActionItem(actionItem, 'i/marker',\n 'highlight', 'core', 'setmarker');\n courseeditor.dispatch('legacySectionAction', action, sectionid);\n setSectionBadge(sectionElement[0], 'highlighted', false);\n }\n };\n\n /**\n * Get the focused element path in an activity if any.\n *\n * This method is used to restore focus when the activity HTML is refreshed.\n * Only the main course editor elements can be refocused as they are always present\n * even if the activity content changes.\n *\n * @param {String} id the element id the activity element\n * @return {String|undefined} the inner path of the focused element or undefined\n */\n const getActivityFocusedElement = function(id) {\n const element = document.getElementById(id);\n if (!element || !element.contains(document.activeElement)) {\n return undefined;\n }\n // Check if the actions menu toggler is focused.\n if (element.querySelector(SELECTOR.ACTIONAREA).contains(document.activeElement)) {\n return `${SELECTOR.ACTIONAREA} [tabindex=\"0\"]`;\n }\n // Return the current element id if any.\n if (document.activeElement.id) {\n return `#${document.activeElement.id}`;\n }\n return undefined;\n };\n\n /**\n * Replaces the course module with the new html (used to update module after it was edited or its visibility was changed).\n *\n * @param {String} activityHTML\n */\n var replaceActivityHtmlWith = function(activityHTML) {\n $('
' + activityHTML + '
').find(SELECTOR.ACTIVITYLI).each(function() {\n // Extract id from the new activity html.\n var id = $(this).attr('id');\n // Check if the current focused element is inside the activity.\n let focusedPath = getActivityFocusedElement(id);\n // Find the existing element with the same id and replace its contents with new html.\n $(SELECTOR.ACTIVITYLI + '#' + id).replaceWith(activityHTML);\n // Initialise action menu.\n initActionMenu(id);\n // Re-focus the previous elements.\n if (focusedPath) {\n const newItem = document.getElementById(id);\n newItem.querySelector(focusedPath)?.focus();\n }\n\n });\n };\n\n /**\n * Performs an action on a module (moving, deleting, duplicating, hiding, etc.)\n *\n * @param {JQuery} sectionElement section element we perform action on\n * @param {Nunmber} sectionid\n * @param {JQuery} target the element (menu item) that was clicked\n * @param {String} courseformat\n * @return {boolean} true the action call is sent to the server or false if it is ignored.\n */\n var editSection = function(sectionElement, sectionid, target, courseformat) {\n var action = target.attr('data-action'),\n sectionreturn = target.attr('data-sectionreturn') ? target.attr('data-sectionreturn') : 0;\n\n // Filter direct component handled actions.\n if (courseeditor.supportComponents && componentActions.includes(action)) {\n return false;\n }\n\n var spinner = addSectionSpinner(sectionElement);\n var promises = ajax.call([{\n methodname: 'core_course_edit_section',\n args: {id: sectionid, action: action, sectionreturn: sectionreturn}\n }], true);\n\n var lightbox = addSectionLightbox(sectionElement);\n $.when.apply($, promises)\n .done(function(dataencoded) {\n var data = $.parseJSON(dataencoded);\n removeSpinner(sectionElement, spinner);\n removeLightbox(lightbox);\n sectionElement.find(SELECTOR.SECTIONACTIONMENU).find(SELECTOR.TOGGLE).focus();\n // Trigger event that can be observed by course formats.\n var e = $.Event('coursesectionedited', {ajaxreturn: data, action: action});\n sectionElement.trigger(e);\n if (!e.isDefaultPrevented()) {\n defaultEditSectionHandler(sectionElement, target, data, courseformat, sectionid);\n }\n }).fail(function(ex) {\n // Remove spinner and lightbox.\n removeSpinner(sectionElement, spinner);\n removeLightbox(lightbox);\n // Trigger event that can be observed by course formats.\n var e = $.Event('coursesectioneditfailed', {exception: ex, action: action});\n sectionElement.trigger(e);\n if (!e.isDefaultPrevented()) {\n notification.exception(ex);\n }\n });\n return true;\n };\n\n /**\n * Sets the section badge in the section header.\n *\n * @param {JQuery} sectionElement section element we perform action on\n * @param {String} badgetype the type of badge this is for\n * @param {bool} add true to add, false to remove\n */\n var setSectionBadge = function(sectionElement, badgetype, add) {\n const sectionbadges = sectionElement.querySelector(SELECTOR.SECTIONBADGES);\n if (!sectionbadges) {\n return;\n }\n if (add) {\n templates.render('core_courseformat/local/content/section/badges', {[badgetype]: 1})\n .then(function(html, js) {\n templates.prependNodeContents(sectionbadges, html, js);\n return true;\n }).catch(notification.exception);\n } else {\n const badge = sectionbadges.querySelector('[data-type=\"' + badgetype + '\"]');\n badge.remove();\n }\n };\n\n // Register a function to be executed after D&D of an activity.\n Y.use('moodle-course-coursebase', function() {\n M.course.coursebase.register_module({\n // Ignore camelcase eslint rule for the next line because it is an expected name of the callback.\n // eslint-disable-next-line camelcase\n set_visibility_resource_ui: function(args) {\n var mainelement = $(args.element.getDOMNode());\n var cmid = getModuleId(mainelement);\n if (cmid) {\n var sectionreturn = mainelement.find('.' + CSS.EDITINGMOVE).attr('data-sectionreturn');\n refreshModule(mainelement, cmid, sectionreturn);\n }\n },\n /**\n * Update the course state when some cm is moved via YUI.\n * @param {*} params\n */\n updateMovedCmState: (params) => {\n const state = courseeditor.state;\n\n // Update old section.\n const cm = state.cm.get(params.cmid);\n if (cm !== undefined) {\n courseeditor.dispatch('sectionState', [cm.sectionid]);\n }\n // Update cm state.\n courseeditor.dispatch('cmState', [params.cmid]);\n },\n /**\n * Update the course state when some section is moved via YUI.\n */\n updateMovedSectionState: () => {\n courseeditor.dispatch('courseState');\n },\n });\n });\n\n // From Moodle 4.0 all edit actions are being re-implemented as state mutation.\n // This means all method from this \"actions\" module will be deprecated when all the course\n // interface is migrated to reactive components.\n // Most legacy actions did not provide enough information to regenarate the course so they\n // use the mutations courseState, sectionState and cmState to get the updated state from\n // the server. However, some activity actions where we can prevent an extra webservice\n // call by implementing an adhoc mutation.\n courseeditor.addMutations({\n /**\n * Compatibility function to update Moodle 4.0 course state using legacy actions.\n *\n * This method only updates some actions which does not require to use cmState mutation\n * to get updated data form the server.\n *\n * @param {Object} statemanager the current state in read write mode\n * @param {String} action the performed action\n * @param {Number} cmid the affected course module id\n * @param {Array} affectedids all affected cm ids (for duplicate action)\n */\n legacyActivityAction: function(statemanager, action, cmid, affectedids) {\n\n const state = statemanager.state;\n const cm = state.cm.get(cmid);\n if (cm === undefined) {\n return;\n }\n const section = state.section.get(cm.sectionid);\n if (section === undefined) {\n return;\n }\n\n // Send the element is locked.\n courseeditor.dispatch('cmLock', [cm.id], true);\n\n // Now we do the real mutation.\n statemanager.setReadOnly(false);\n\n // This unlocked will take effect when the read only is restored.\n cm.locked = false;\n\n switch (action) {\n case 'delete':\n // Remove from section.\n section.cmlist = section.cmlist.reduce(\n (cmlist, current) => {\n if (current != cmid) {\n cmlist.push(current);\n }\n return cmlist;\n },\n []\n );\n // Delete form list.\n state.cm.delete(cmid);\n break;\n\n case 'hide':\n case 'show':\n cm.visible = (action === 'show') ? true : false;\n break;\n\n case 'duplicate':\n // Duplicate requires to get extra data from the server.\n courseeditor.dispatch('cmState', affectedids);\n break;\n }\n statemanager.setReadOnly(true);\n },\n legacySectionAction: function(statemanager, action, sectionid) {\n\n const state = statemanager.state;\n const section = state.section.get(sectionid);\n if (section === undefined) {\n return;\n }\n\n // Send the element is locked. Reactive events are only triggered when the state\n // read only mode is restored. We want to notify the interface the element is\n // locked so we need to do a quick lock operation before performing the rest\n // of the mutation.\n statemanager.setReadOnly(false);\n section.locked = true;\n statemanager.setReadOnly(true);\n\n // Now we do the real mutation.\n statemanager.setReadOnly(false);\n\n // This locked will take effect when the read only is restored.\n section.locked = false;\n\n switch (action) {\n case 'setmarker':\n // Remove previous marker.\n state.section.forEach((current) => {\n if (current.id != sectionid) {\n current.current = false;\n }\n });\n section.current = true;\n break;\n\n case 'removemarker':\n section.current = false;\n break;\n }\n statemanager.setReadOnly(true);\n },\n });\n\n return /** @alias module:core_course/actions */ {\n\n /**\n * Initialises course page\n *\n * @method init\n * @param {String} courseformat name of the current course format (for fetching strings)\n */\n initCoursePage: function(courseformat) {\n\n formatname = courseformat;\n\n // Add a handler for course module actions.\n $('body').on('click keypress', SELECTOR.ACTIVITYLI + ' ' +\n SELECTOR.ACTIVITYACTION + '[data-action]', function(e) {\n if (e.type === 'keypress' && e.keyCode !== 13) {\n return;\n }\n var actionItem = $(this),\n moduleElement = actionItem.closest(SELECTOR.ACTIVITYLI),\n action = actionItem.attr('data-action'),\n moduleId = getModuleId(moduleElement);\n switch (action) {\n case 'moveleft':\n case 'moveright':\n case 'delete':\n case 'duplicate':\n case 'hide':\n case 'stealth':\n case 'show':\n case 'groupsseparate':\n case 'groupsvisible':\n case 'groupsnone':\n break;\n default:\n // Nothing to do here!\n return;\n }\n if (!moduleId) {\n return;\n }\n e.preventDefault();\n if (action === 'delete') {\n // Deleting requires confirmation.\n confirmDeleteModule(moduleElement, function() {\n editModule(moduleElement, moduleId, actionItem);\n });\n } else {\n editModule(moduleElement, moduleId, actionItem);\n }\n });\n\n // Add a handler for section show/hide actions.\n $('body').on('click keypress', SELECTOR.SECTIONLI + ' ' +\n SELECTOR.SECTIONACTIONMENU + '[data-sectionid] ' +\n 'a[data-action]', function(e) {\n if (e.type === 'keypress' && e.keyCode !== 13) {\n return;\n }\n var actionItem = $(this),\n sectionElement = actionItem.closest(SELECTOR.SECTIONLI),\n sectionId = actionItem.closest(SELECTOR.SECTIONACTIONMENU).attr('data-sectionid');\n\n let isExecuted = true;\n if (actionItem.attr('data-confirm')) {\n // Action requires confirmation.\n confirmEditSection(actionItem.attr('data-confirm'), function() {\n isExecuted = editSection(sectionElement, sectionId, actionItem, courseformat);\n });\n } else {\n isExecuted = editSection(sectionElement, sectionId, actionItem, courseformat);\n }\n // Prevent any other module from capturing the action if it is already in execution.\n if (isExecuted) {\n e.preventDefault();\n }\n });\n\n // The section and activity names are edited using inplace editable.\n // The \"update\" jQuery event must be captured in order to update the course state.\n $('body').on('updated', `${SELECTOR.SECTIONLI} [data-inplaceeditable]`, function(e) {\n if (e.ajaxreturn && e.ajaxreturn.itemid) {\n const state = courseeditor.state;\n const section = state.section.get(e.ajaxreturn.itemid);\n if (section !== undefined) {\n courseeditor.dispatch('sectionState', [e.ajaxreturn.itemid]);\n }\n }\n });\n $('body').on('updated', `${SELECTOR.ACTIVITYLI} [data-inplaceeditable]`, function(e) {\n if (e.ajaxreturn && e.ajaxreturn.itemid) {\n courseeditor.dispatch('cmState', [e.ajaxreturn.itemid]);\n }\n });\n\n // Component-based formats don't use modals to create sections.\n if (courseeditor.supportComponents && componentActions.includes('addSection')) {\n return;\n }\n\n // Add a handler for \"Add sections\" link to ask for a number of sections to add.\n str.get_string('numberweeks').done(function(strNumberSections) {\n var trigger = $(SELECTOR.ADDSECTIONS),\n modalTitle = trigger.attr('data-add-sections'),\n newSections = trigger.attr('data-new-sections');\n var modalBody = $('
' +\n '
');\n modalBody.find('label').html(strNumberSections);\n ModalFactory.create({\n title: modalTitle,\n type: ModalFactory.types.SAVE_CANCEL,\n body: modalBody.html()\n }, trigger)\n .done(function(modal) {\n var numSections = $(modal.getBody()).find('#add_section_numsections'),\n addSections = function() {\n // Check if value of the \"Number of sections\" is a valid positive integer and redirect\n // to adding a section script.\n if ('' + parseInt(numSections.val()) === numSections.val() && parseInt(numSections.val()) >= 1) {\n document.location = trigger.attr('href') + '&numsections=' + parseInt(numSections.val());\n }\n };\n modal.setSaveButtonText(modalTitle);\n modal.getRoot().on(ModalEvents.shown, function() {\n // When modal is shown focus and select the input and add a listener to keypress of \"Enter\".\n numSections.focus().select().on('keydown', function(e) {\n if (e.keyCode === KeyCodes.enter) {\n addSections();\n }\n });\n });\n modal.getRoot().on(ModalEvents.save, function(e) {\n // When modal \"Add\" button is pressed.\n e.preventDefault();\n addSections();\n });\n });\n });\n },\n\n /**\n * Replaces a section action menu item with another one (for example Show->Hide, Set marker->Remove marker)\n *\n * This method can be used by course formats in their listener to the coursesectionedited event\n *\n * @deprecated since Moodle 3.9\n * @param {JQuery} sectionelement\n * @param {String} selector CSS selector inside the section element, for example \"a[data-action=show]\"\n * @param {String} image new image name (\"i/show\", \"i/hide\", etc.)\n * @param {String} stringname new string for the action menu item\n * @param {String} stringcomponent\n * @param {String} newaction new value for data-action attribute of the link\n */\n replaceSectionActionItem: function(sectionelement, selector, image, stringname,\n stringcomponent, newaction) {\n log.debug('replaceSectionActionItem() is deprecated and will be removed.');\n var actionitem = sectionelement.find(SELECTOR.SECTIONACTIONMENU + ' ' + selector);\n replaceActionItem(actionitem, image, stringname, stringcomponent, newaction);\n },\n // Method to refresh a module.\n refreshModule,\n refreshSection,\n };\n });\n"],"file":"actions.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/actions.js"],"names":["define","$","ajax","templates","notification","str","url","Y","ModalFactory","ModalEvents","KeyCodes","log","editor","EventDispatcher","CourseEvents","componentActions","courseeditor","getCurrentCourseEditor","formatname","CSS","EDITINPROGRESS","SECTIONDRAGGABLE","EDITINGMOVE","SELECTOR","ACTIVITYLI","ACTIONAREA","ACTIVITYACTION","MENU","TOGGLE","SECTIONLI","SECTIONACTIONMENU","ADDSECTIONS","SECTIONBADGES","use","courseformatselector","M","course","format","get_section_selector","dispatchEvent","eventName","detail","container","options","Element","get","getModuleId","element","item","dataset","id","Moodle","core_course","util","cm","getId","Node","getModuleName","name","getName","state","cmid","addActivitySpinner","activity","addClass","actionarea","find","spinner","add_spinner","show","data","dispatch","addSectionSpinner","sectionelement","addSectionLightbox","lightbox","add_lightbox","for","setAttribute","removeSpinner","delay","window","setTimeout","removeClass","hide","mutation","removeLightbox","getAttribute","initActionMenu","elementid","coursebase","invoke_function","core","actionmenu","newDOMNode","one","focusActionItem","elementId","action","mainelement","selector","is","focus","findNextFocusable","mainElement","tabables","isInside","foundElement","each","contains","editModule","moduleElement","target","attr","promises","call","methodname","args","sectionreturn","closest","when","apply","done","elementToFocus","replaceWith","affectedids","index","push","trigger","Event","ajaxreturn","fail","ex","e","exception","isDefaultPrevented","refreshModule","sectionReturn","activityElement","Promise","resolve","reject","replaceActivityHtmlWith","confirmDeleteModule","onconfirm","modtypename","match","modulename","get_string","pluginname","get_strings","key","component","param","type","s","confirm","confirmEditSection","message","replaceActionItem","actionitem","image","stringname","stringcomponent","newaction","then","strings","html","renderPix","pixhtml","catch","defaultEditSectionHandler","sectionElement","actionItem","courseformat","sectionid","setSectionBadge","modules","i","section_availability","first","section","oldmarker","oldActionItem","getActivityFocusedElement","document","getElementById","activeElement","querySelector","activityHTML","focusedPath","newItem","editSection","supportComponents","includes","dataencoded","parseJSON","badgetype","add","sectionbadges","render","js","prependNodeContents","badge","remove","register_module","set_visibility_resource_ui","getDOMNode","updateMovedCmState","params","updateMovedSectionState","addMutations","legacyActivityAction","statemanager","setReadOnly","locked","cmlist","reduce","current","delete","legacySectionAction","forEach","initCoursePage","on","keyCode","moduleId","preventDefault","sectionId","isExecuted","itemid","strNumberSections","modalTitle","newSections","modalBody","create","title","types","SAVE_CANCEL","body","modal","numSections","getBody","addSections","parseInt","val","location","setSaveButtonText","getRoot","shown","select","enter","save","replaceSectionActionItem","debug","refreshSection","newSectionElement","content","event","sectionRefreshed","defaultPrevented"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Various actions on modules and sections in the editing mode - hiding, duplicating, deleting, etc.\n *\n * @module core_course/actions\n * @copyright 2016 Marina Glancy\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 3.3\n */\ndefine(\n [\n 'jquery',\n 'core/ajax',\n 'core/templates',\n 'core/notification',\n 'core/str',\n 'core/url',\n 'core/yui',\n 'core/modal_factory',\n 'core/modal_events',\n 'core/key_codes',\n 'core/log',\n 'core_courseformat/courseeditor',\n 'core/event_dispatcher',\n 'core_course/events'\n ],\n function(\n $,\n ajax,\n templates,\n notification,\n str,\n url,\n Y,\n ModalFactory,\n ModalEvents,\n KeyCodes,\n log,\n editor,\n EventDispatcher,\n CourseEvents\n ) {\n\n // Eventually, core_courseformat/local/content/actions will handle all actions for\n // component compatible formats and the default actions.js won't be necessary anymore.\n // Meanwhile, we filter the migrated actions.\n const componentActions = ['moveSection', 'moveCm', 'addSection', 'deleteSection'];\n\n // The course reactive instance.\n const courseeditor = editor.getCurrentCourseEditor();\n\n // The current course format name (loaded on init).\n let formatname;\n\n var CSS = {\n EDITINPROGRESS: 'editinprogress',\n SECTIONDRAGGABLE: 'sectiondraggable',\n EDITINGMOVE: 'editing_move'\n };\n var SELECTOR = {\n ACTIVITYLI: 'li.activity',\n ACTIONAREA: '.actions',\n ACTIVITYACTION: 'a.cm-edit-action',\n MENU: '.moodle-actionmenu[data-enhance=moodle-core-actionmenu]',\n TOGGLE: '.toggle-display,.dropdown-toggle',\n SECTIONLI: 'li.section',\n SECTIONACTIONMENU: '.section_action_menu',\n ADDSECTIONS: '.changenumsections [data-add-sections]',\n SECTIONBADGES: '[data-region=\"sectionbadges\"]',\n };\n\n Y.use('moodle-course-coursebase', function() {\n var courseformatselector = M.course.format.get_section_selector();\n if (courseformatselector) {\n SELECTOR.SECTIONLI = courseformatselector;\n }\n });\n\n /**\n * Dispatch event wrapper.\n *\n * Old jQuery events will be replaced by native events gradually.\n *\n * @method dispatchEvent\n * @param {String} eventName The name of the event\n * @param {Object} detail Any additional details to pass into the eveent\n * @param {Node|HTMLElement} container The point at which to dispatch the event\n * @param {Object} options\n * @param {Boolean} options.bubbles Whether to bubble up the DOM\n * @param {Boolean} options.cancelable Whether preventDefault() can be called\n * @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM boundary\n * @returns {CustomEvent}\n */\n const dispatchEvent = function(eventName, detail, container, options) {\n // Most actions still uses jQuery node instead of regular HTMLElement.\n if (!(container instanceof Element) && container.get !== undefined) {\n container = container.get(0);\n }\n return EventDispatcher.dispatchEvent(eventName, detail, container, options);\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getId\n *\n * @param {JQuery} element\n * @returns {Integer}\n */\n var getModuleId = function(element) {\n // Check if we have a data-id first.\n const item = element.get(0);\n if (item.dataset.id) {\n return item.dataset.id;\n }\n // Use YUI way if data-id is not present.\n let id;\n Y.use('moodle-course-util', function(Y) {\n id = Y.Moodle.core_course.util.cm.getId(Y.Node(item));\n });\n return id;\n };\n\n /**\n * Wrapper for Y.Moodle.core_course.util.cm.getName\n *\n * @param {JQuery} element\n * @returns {String}\n */\n var getModuleName = function(element) {\n var name;\n Y.use('moodle-course-util', function(Y) {\n name = Y.Moodle.core_course.util.cm.getName(Y.Node(element.get(0)));\n });\n // Check if we have the name in the course state.\n const state = courseeditor.state;\n const cmid = getModuleId(element);\n if (!name && state && cmid) {\n name = state.cm.get(cmid)?.name;\n }\n return name;\n };\n\n /**\n * Wrapper for M.util.add_spinner for an activity\n *\n * @param {JQuery} activity\n * @returns {Node}\n */\n var addActivitySpinner = function(activity) {\n activity.addClass(CSS.EDITINPROGRESS);\n var actionarea = activity.find(SELECTOR.ACTIONAREA).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the activity state element.\n if (activity.data('id') !== undefined) {\n courseeditor.dispatch('cmLock', [activity.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_spinner for a section\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionSpinner = function(sectionelement) {\n sectionelement.addClass(CSS.EDITINPROGRESS);\n var actionarea = sectionelement.find(SELECTOR.SECTIONACTIONMENU).get(0);\n if (actionarea) {\n var spinner = M.util.add_spinner(Y, Y.Node(actionarea));\n spinner.show();\n // Lock the section state element.\n if (sectionelement.data('id') !== undefined) {\n courseeditor.dispatch('sectionLock', [sectionelement.data('id')], true);\n }\n return spinner;\n }\n return null;\n };\n\n /**\n * Wrapper for M.util.add_lightbox\n *\n * @param {JQuery} sectionelement\n * @returns {Node}\n */\n var addSectionLightbox = function(sectionelement) {\n const item = sectionelement.get(0);\n var lightbox = M.util.add_lightbox(Y, Y.Node(item));\n if (item.dataset.for == 'section' && item.dataset.id) {\n courseeditor.dispatch('sectionLock', [item.dataset.id], true);\n lightbox.setAttribute('data-state', 'section');\n lightbox.setAttribute('data-state-id', item.dataset.id);\n }\n lightbox.show();\n return lightbox;\n };\n\n /**\n * Removes the spinner element\n *\n * @param {JQuery} element\n * @param {Node} spinner\n * @param {Number} delay\n */\n var removeSpinner = function(element, spinner, delay) {\n window.setTimeout(function() {\n element.removeClass(CSS.EDITINPROGRESS);\n if (spinner) {\n spinner.hide();\n }\n // Unlock the state element.\n if (element.data('id') !== undefined) {\n const mutation = (element.data('for') === 'section') ? 'sectionLock' : 'cmLock';\n courseeditor.dispatch(mutation, [element.data('id')], false);\n }\n }, delay);\n };\n\n /**\n * Removes the lightbox element\n *\n * @param {Node} lightbox lighbox YUI element returned by addSectionLightbox\n * @param {Number} delay\n */\n var removeLightbox = function(lightbox, delay) {\n if (lightbox) {\n window.setTimeout(function() {\n lightbox.hide();\n // Unlock state if necessary.\n if (lightbox.getAttribute('data-state')) {\n courseeditor.dispatch(\n `${lightbox.getAttribute('data-state')}Lock`,\n [lightbox.getAttribute('data-state-id')],\n false\n );\n }\n }, delay);\n }\n };\n\n /**\n * Initialise action menu for the element (section or module)\n *\n * @param {String} elementid CSS id attribute of the element\n */\n var initActionMenu = function(elementid) {\n // Initialise action menu in the new activity.\n Y.use('moodle-course-coursebase', function() {\n M.course.coursebase.invoke_function('setup_for_resource', '#' + elementid);\n });\n if (M.core.actionmenu && M.core.actionmenu.newDOMNode) {\n M.core.actionmenu.newDOMNode(Y.one('#' + elementid));\n }\n };\n\n /**\n * Returns focus to the element that was clicked or \"Edit\" link if element is no longer visible.\n *\n * @param {String} elementId CSS id attribute of the element\n * @param {String} action data-action property of the element that was clicked\n */\n var focusActionItem = function(elementId, action) {\n var mainelement = $('#' + elementId);\n var selector = '[data-action=' + action + ']';\n if (action === 'groupsseparate' || action === 'groupsvisible' || action === 'groupsnone') {\n // New element will have different data-action.\n selector = '[data-action=groupsseparate],[data-action=groupsvisible],[data-action=groupsnone]';\n }\n if (mainelement.find(selector).is(':visible')) {\n mainelement.find(selector).focus();\n } else {\n // Element not visible, focus the \"Edit\" link.\n mainelement.find(SELECTOR.MENU).find(SELECTOR.TOGGLE).focus();\n }\n };\n\n /**\n * Find next
after the element\n *\n * @param {JQuery} mainElement element that is about to be deleted\n * @returns {JQuery}\n */\n var findNextFocusable = function(mainElement) {\n var tabables = $(\"a:visible\");\n var isInside = false;\n var foundElement = null;\n tabables.each(function() {\n if ($.contains(mainElement[0], this)) {\n isInside = true;\n } else if (isInside) {\n foundElement = this;\n return false; // Returning false in .each() is equivalent to \"break;\" inside the loop in php.\n }\n return true;\n });\n return foundElement;\n };\n\n /**\n * Performs an action on a module (moving, deleting, duplicating, hiding, etc.)\n *\n * @param {JQuery} moduleElement activity element we perform action on\n * @param {Number} cmid\n * @param {JQuery} target the element (menu item) that was clicked\n */\n var editModule = function(moduleElement, cmid, target) {\n var action = target.attr('data-action');\n var spinner = addActivitySpinner(moduleElement);\n var promises = ajax.call([{\n methodname: 'core_course_edit_module',\n args: {id: cmid,\n action: action,\n sectionreturn: target.attr('data-sectionreturn') ? target.attr('data-sectionreturn') : 0\n }\n }], true);\n\n var lightbox;\n if (action === 'duplicate') {\n lightbox = addSectionLightbox(target.closest(SELECTOR.SECTIONLI));\n }\n $.when.apply($, promises)\n .done(function(data) {\n var elementToFocus = findNextFocusable(moduleElement);\n moduleElement.replaceWith(data);\n let affectedids = [];\n // Initialise action menu for activity(ies) added as a result of this.\n $('
' + data + '
').find(SELECTOR.ACTIVITYLI).each(function(index) {\n initActionMenu($(this).attr('id'));\n if (index === 0) {\n focusActionItem($(this).attr('id'), action);\n elementToFocus = null;\n }\n // Save any activity id in cmids.\n affectedids.push(getModuleId($(this)));\n });\n // In case of activity deletion focus the next focusable element.\n if (elementToFocus) {\n elementToFocus.focus();\n }\n // Remove spinner and lightbox with a delay.\n removeSpinner(moduleElement, spinner, 400);\n removeLightbox(lightbox, 400);\n // Trigger event that can be observed by course formats.\n moduleElement.trigger($.Event('coursemoduleedited', {ajaxreturn: data, action: action}));\n\n // Modify cm state.\n courseeditor.dispatch('legacyActivityAction', action, cmid, affectedids);\n\n }).fail(function(ex) {\n // Remove spinner and lightbox.\n removeSpinner(moduleElement, spinner);\n removeLightbox(lightbox);\n // Trigger event that can be observed by course formats.\n var e = $.Event('coursemoduleeditfailed', {exception: ex, action: action});\n moduleElement.trigger(e);\n if (!e.isDefaultPrevented()) {\n notification.exception(ex);\n }\n });\n };\n\n /**\n * Requests html for the module via WS core_course_get_module and updates the module on the course page\n *\n * Used after d&d of the module to another section\n *\n * @param {JQuery|Element} element\n * @param {Number} cmid\n * @param {Number} sectionreturn\n * @return {Promise} the refresh promise\n */\n var refreshModule = function(element, cmid, sectionreturn) {\n\n if (sectionreturn === undefined) {\n sectionreturn = courseeditor.sectionReturn;\n }\n\n const activityElement = $(element);\n var spinner = addActivitySpinner(activityElement);\n var promises = ajax.call([{\n methodname: 'core_course_get_module',\n args: {id: cmid, sectionreturn: sectionreturn}\n }], true);\n\n return new Promise((resolve, reject) => {\n $.when.apply($, promises)\n .done(function(data) {\n removeSpinner(activityElement, spinner, 400);\n replaceActivityHtmlWith(data);\n resolve(data);\n }).fail(function() {\n removeSpinner(activityElement, spinner);\n reject();\n });\n });\n };\n\n /**\n * Requests html for the section via WS core_course_edit_section and updates the section on the course page\n *\n * @param {JQuery|Element} element\n * @param {Number} sectionid\n * @param {Number} sectionreturn\n * @return {Promise} the refresh promise\n */\n var refreshSection = function(element, sectionid, sectionreturn) {\n\n if (sectionreturn === undefined) {\n sectionreturn = courseeditor.sectionReturn;\n }\n\n const sectionElement = $(element);\n const action = 'refresh';\n const promises = ajax.call([{\n methodname: 'core_course_edit_section',\n args: {id: sectionid, action, sectionreturn},\n }], true);\n\n var spinner = addSectionSpinner(sectionElement);\n return new Promise((resolve, reject) => {\n $.when.apply($, promises)\n .done(dataencoded => {\n\n removeSpinner(sectionElement, spinner);\n const data = $.parseJSON(dataencoded);\n\n const newSectionElement = $(data.content);\n sectionElement.replaceWith(newSectionElement);\n\n // Init modules menus.\n $(`${SELECTOR.SECTIONLI}#${sectionid} ${SELECTOR.ACTIVITYLI}`).each(\n (index, activity) => {\n initActionMenu(activity.data('id'));\n }\n );\n\n // Trigger event that can be observed by course formats.\n const event = dispatchEvent(\n CourseEvents.sectionRefreshed,\n {\n ajaxreturn: data,\n action: action,\n newSectionElement: newSectionElement.get(0),\n },\n newSectionElement\n );\n\n if (!event.defaultPrevented) {\n defaultEditSectionHandler(\n newSectionElement, $(SELECTOR.SECTIONLI + '#' + sectionid),\n data,\n formatname,\n sectionid\n );\n }\n resolve(data);\n }).fail(ex => {\n // Trigger event that can be observed by course formats.\n const event = dispatchEvent(\n 'coursesectionrefreshfailed',\n {exception: ex, action: action},\n sectionElement\n );\n if (!event.defaultPrevented) {\n notification.exception(ex);\n }\n reject();\n });\n });\n };\n\n /**\n * Displays the delete confirmation to delete a module\n *\n * @param {JQuery} mainelement activity element we perform action on\n * @param {function} onconfirm function to execute on confirm\n */\n var confirmDeleteModule = function(mainelement, onconfirm) {\n var modtypename = mainelement.attr('class').match(/modtype_([^\\s]*)/)[1];\n var modulename = getModuleName(mainelement);\n\n str.get_string('pluginname', modtypename).done(function(pluginname) {\n var plugindata = {\n type: pluginname,\n name: modulename\n };\n str.get_strings([\n {key: 'confirm', component: 'core'},\n {key: modulename === null ? 'deletechecktype' : 'deletechecktypename', param: plugindata},\n {key: 'yes'},\n {key: 'no'}\n ]).done(function(s) {\n notification.confirm(s[0], s[1], s[2], s[3], onconfirm);\n }\n );\n });\n };\n\n /**\n * Displays the delete confirmation to delete a section\n *\n * @param {String} message confirmation message\n * @param {function} onconfirm function to execute on confirm\n */\n var confirmEditSection = function(message, onconfirm) {\n str.get_strings([\n {key: 'confirm'}, // TODO link text\n {key: 'yes'},\n {key: 'no'}\n ]).done(function(s) {\n notification.confirm(s[0], message, s[1], s[2], onconfirm);\n }\n );\n };\n\n /**\n * Replaces an action menu item with another one (for example Show->Hide, Set marker->Remove marker)\n *\n * @param {JQuery} actionitem\n * @param {String} image new image name (\"i/show\", \"i/hide\", etc.)\n * @param {String} stringname new string for the action menu item\n * @param {String} stringcomponent\n * @param {String} newaction new value for data-action attribute of the link\n * @return {Promise} promise which is resolved when the replacement has completed\n */\n var replaceActionItem = function(actionitem, image, stringname,\n stringcomponent, newaction) {\n\n var stringRequests = [{key: stringname, component: stringcomponent}];\n // Do not provide an icon with duplicate, different text to the menu item.\n\n return str.get_strings(stringRequests).then(function(strings) {\n actionitem.find('span.menu-action-text').html(strings[0]);\n\n return templates.renderPix(image, 'core');\n }).then(function(pixhtml) {\n actionitem.find('.icon').replaceWith(pixhtml);\n actionitem.attr('data-action', newaction);\n return;\n }).catch(notification.exception);\n };\n\n /**\n * Default post-processing for section AJAX edit actions.\n *\n * This can be overridden in course formats by listening to event coursesectionedited:\n *\n * $('body').on('coursesectionedited', 'li.section', function(e) {\n * var action = e.action,\n * sectionElement = $(e.target),\n * data = e.ajaxreturn;\n * // ... Do some processing here.\n * e.preventDefault(); // Prevent default handler.\n * });\n *\n * @param {JQuery} sectionElement\n * @param {JQuery} actionItem\n * @param {Object} data\n * @param {String} courseformat\n * @param {Number} sectionid\n */\n var defaultEditSectionHandler = function(sectionElement, actionItem, data, courseformat, sectionid) {\n var action = actionItem.attr('data-action');\n if (action === 'hide' || action === 'show') {\n if (action === 'hide') {\n sectionElement.addClass('hidden');\n setSectionBadge(sectionElement[0], 'hiddenfromstudents', true);\n replaceActionItem(actionItem, 'i/show',\n 'showfromothers', 'format_' + courseformat, 'show');\n } else {\n setSectionBadge(sectionElement[0], 'hiddenfromstudents', false);\n sectionElement.removeClass('hidden');\n replaceActionItem(actionItem, 'i/hide',\n 'hidefromothers', 'format_' + courseformat, 'hide');\n }\n // Replace the modules with new html (that indicates that they are now hidden or not hidden).\n if (data.modules !== undefined) {\n for (var i in data.modules) {\n replaceActivityHtmlWith(data.modules[i]);\n }\n }\n // Replace the section availability information.\n if (data.section_availability !== undefined) {\n sectionElement.find('.section_availability').first().replaceWith(data.section_availability);\n }\n // Modify course state.\n const section = courseeditor.state.section.get(sectionid);\n if (section !== undefined) {\n courseeditor.dispatch('sectionState', [sectionid]);\n }\n } else if (action === 'setmarker') {\n var oldmarker = $(SELECTOR.SECTIONLI + '.current'),\n oldActionItem = oldmarker.find(SELECTOR.SECTIONACTIONMENU + ' ' + 'a[data-action=removemarker]');\n oldmarker.removeClass('current');\n replaceActionItem(oldActionItem, 'i/marker',\n 'highlight', 'core', 'setmarker');\n sectionElement.addClass('current');\n replaceActionItem(actionItem, 'i/marked',\n 'highlightoff', 'core', 'removemarker');\n courseeditor.dispatch('legacySectionAction', action, sectionid);\n setSectionBadge(sectionElement[0], 'highlighted', true);\n } else if (action === 'removemarker') {\n sectionElement.removeClass('current');\n replaceActionItem(actionItem, 'i/marker',\n 'highlight', 'core', 'setmarker');\n courseeditor.dispatch('legacySectionAction', action, sectionid);\n setSectionBadge(sectionElement[0], 'highlighted', false);\n }\n };\n\n /**\n * Get the focused element path in an activity if any.\n *\n * This method is used to restore focus when the activity HTML is refreshed.\n * Only the main course editor elements can be refocused as they are always present\n * even if the activity content changes.\n *\n * @param {String} id the element id the activity element\n * @return {String|undefined} the inner path of the focused element or undefined\n */\n const getActivityFocusedElement = function(id) {\n const element = document.getElementById(id);\n if (!element || !element.contains(document.activeElement)) {\n return undefined;\n }\n // Check if the actions menu toggler is focused.\n if (element.querySelector(SELECTOR.ACTIONAREA).contains(document.activeElement)) {\n return `${SELECTOR.ACTIONAREA} [tabindex=\"0\"]`;\n }\n // Return the current element id if any.\n if (document.activeElement.id) {\n return `#${document.activeElement.id}`;\n }\n return undefined;\n };\n\n /**\n * Replaces the course module with the new html (used to update module after it was edited or its visibility was changed).\n *\n * @param {String} activityHTML\n */\n var replaceActivityHtmlWith = function(activityHTML) {\n $('
' + activityHTML + '
').find(SELECTOR.ACTIVITYLI).each(function() {\n // Extract id from the new activity html.\n var id = $(this).attr('id');\n // Check if the current focused element is inside the activity.\n let focusedPath = getActivityFocusedElement(id);\n // Find the existing element with the same id and replace its contents with new html.\n $(SELECTOR.ACTIVITYLI + '#' + id).replaceWith(activityHTML);\n // Initialise action menu.\n initActionMenu(id);\n // Re-focus the previous elements.\n if (focusedPath) {\n const newItem = document.getElementById(id);\n newItem.querySelector(focusedPath)?.focus();\n }\n\n });\n };\n\n /**\n * Performs an action on a module (moving, deleting, duplicating, hiding, etc.)\n *\n * @param {JQuery} sectionElement section element we perform action on\n * @param {Nunmber} sectionid\n * @param {JQuery} target the element (menu item) that was clicked\n * @param {String} courseformat\n * @return {boolean} true the action call is sent to the server or false if it is ignored.\n */\n var editSection = function(sectionElement, sectionid, target, courseformat) {\n var action = target.attr('data-action'),\n sectionreturn = target.attr('data-sectionreturn') ? target.attr('data-sectionreturn') : 0;\n\n // Filter direct component handled actions.\n if (courseeditor.supportComponents && componentActions.includes(action)) {\n return false;\n }\n\n var spinner = addSectionSpinner(sectionElement);\n var promises = ajax.call([{\n methodname: 'core_course_edit_section',\n args: {id: sectionid, action: action, sectionreturn: sectionreturn}\n }], true);\n\n var lightbox = addSectionLightbox(sectionElement);\n $.when.apply($, promises)\n .done(function(dataencoded) {\n var data = $.parseJSON(dataencoded);\n removeSpinner(sectionElement, spinner);\n removeLightbox(lightbox);\n sectionElement.find(SELECTOR.SECTIONACTIONMENU).find(SELECTOR.TOGGLE).focus();\n // Trigger event that can be observed by course formats.\n var e = $.Event('coursesectionedited', {ajaxreturn: data, action: action});\n sectionElement.trigger(e);\n if (!e.isDefaultPrevented()) {\n defaultEditSectionHandler(sectionElement, target, data, courseformat, sectionid);\n }\n }).fail(function(ex) {\n // Remove spinner and lightbox.\n removeSpinner(sectionElement, spinner);\n removeLightbox(lightbox);\n // Trigger event that can be observed by course formats.\n var e = $.Event('coursesectioneditfailed', {exception: ex, action: action});\n sectionElement.trigger(e);\n if (!e.isDefaultPrevented()) {\n notification.exception(ex);\n }\n });\n return true;\n };\n\n /**\n * Sets the section badge in the section header.\n *\n * @param {JQuery} sectionElement section element we perform action on\n * @param {String} badgetype the type of badge this is for\n * @param {bool} add true to add, false to remove\n */\n var setSectionBadge = function(sectionElement, badgetype, add) {\n const sectionbadges = sectionElement.querySelector(SELECTOR.SECTIONBADGES);\n if (!sectionbadges) {\n return;\n }\n if (add) {\n templates.render('core_courseformat/local/content/section/badges', {[badgetype]: 1})\n .then(function(html, js) {\n templates.prependNodeContents(sectionbadges, html, js);\n return true;\n }).catch(notification.exception);\n } else {\n const badge = sectionbadges.querySelector('[data-type=\"' + badgetype + '\"]');\n badge.remove();\n }\n };\n\n // Register a function to be executed after D&D of an activity.\n Y.use('moodle-course-coursebase', function() {\n M.course.coursebase.register_module({\n // Ignore camelcase eslint rule for the next line because it is an expected name of the callback.\n // eslint-disable-next-line camelcase\n set_visibility_resource_ui: function(args) {\n var mainelement = $(args.element.getDOMNode());\n var cmid = getModuleId(mainelement);\n if (cmid) {\n var sectionreturn = mainelement.find('.' + CSS.EDITINGMOVE).attr('data-sectionreturn');\n refreshModule(mainelement, cmid, sectionreturn);\n }\n },\n /**\n * Update the course state when some cm is moved via YUI.\n * @param {*} params\n */\n updateMovedCmState: (params) => {\n const state = courseeditor.state;\n\n // Update old section.\n const cm = state.cm.get(params.cmid);\n if (cm !== undefined) {\n courseeditor.dispatch('sectionState', [cm.sectionid]);\n }\n // Update cm state.\n courseeditor.dispatch('cmState', [params.cmid]);\n },\n /**\n * Update the course state when some section is moved via YUI.\n */\n updateMovedSectionState: () => {\n courseeditor.dispatch('courseState');\n },\n });\n });\n\n // From Moodle 4.0 all edit actions are being re-implemented as state mutation.\n // This means all method from this \"actions\" module will be deprecated when all the course\n // interface is migrated to reactive components.\n // Most legacy actions did not provide enough information to regenarate the course so they\n // use the mutations courseState, sectionState and cmState to get the updated state from\n // the server. However, some activity actions where we can prevent an extra webservice\n // call by implementing an adhoc mutation.\n courseeditor.addMutations({\n /**\n * Compatibility function to update Moodle 4.0 course state using legacy actions.\n *\n * This method only updates some actions which does not require to use cmState mutation\n * to get updated data form the server.\n *\n * @param {Object} statemanager the current state in read write mode\n * @param {String} action the performed action\n * @param {Number} cmid the affected course module id\n * @param {Array} affectedids all affected cm ids (for duplicate action)\n */\n legacyActivityAction: function(statemanager, action, cmid, affectedids) {\n\n const state = statemanager.state;\n const cm = state.cm.get(cmid);\n if (cm === undefined) {\n return;\n }\n const section = state.section.get(cm.sectionid);\n if (section === undefined) {\n return;\n }\n\n // Send the element is locked.\n courseeditor.dispatch('cmLock', [cm.id], true);\n\n // Now we do the real mutation.\n statemanager.setReadOnly(false);\n\n // This unlocked will take effect when the read only is restored.\n cm.locked = false;\n\n switch (action) {\n case 'delete':\n // Remove from section.\n section.cmlist = section.cmlist.reduce(\n (cmlist, current) => {\n if (current != cmid) {\n cmlist.push(current);\n }\n return cmlist;\n },\n []\n );\n // Delete form list.\n state.cm.delete(cmid);\n break;\n\n case 'hide':\n case 'show':\n case 'duplicate':\n courseeditor.dispatch('cmState', affectedids);\n break;\n }\n statemanager.setReadOnly(true);\n },\n legacySectionAction: function(statemanager, action, sectionid) {\n\n const state = statemanager.state;\n const section = state.section.get(sectionid);\n if (section === undefined) {\n return;\n }\n\n // Send the element is locked. Reactive events are only triggered when the state\n // read only mode is restored. We want to notify the interface the element is\n // locked so we need to do a quick lock operation before performing the rest\n // of the mutation.\n statemanager.setReadOnly(false);\n section.locked = true;\n statemanager.setReadOnly(true);\n\n // Now we do the real mutation.\n statemanager.setReadOnly(false);\n\n // This locked will take effect when the read only is restored.\n section.locked = false;\n\n switch (action) {\n case 'setmarker':\n // Remove previous marker.\n state.section.forEach((current) => {\n if (current.id != sectionid) {\n current.current = false;\n }\n });\n section.current = true;\n break;\n\n case 'removemarker':\n section.current = false;\n break;\n }\n statemanager.setReadOnly(true);\n },\n });\n\n return /** @alias module:core_course/actions */ {\n\n /**\n * Initialises course page\n *\n * @method init\n * @param {String} courseformat name of the current course format (for fetching strings)\n */\n initCoursePage: function(courseformat) {\n\n formatname = courseformat;\n\n // Add a handler for course module actions.\n $('body').on('click keypress', SELECTOR.ACTIVITYLI + ' ' +\n SELECTOR.ACTIVITYACTION + '[data-action]', function(e) {\n if (e.type === 'keypress' && e.keyCode !== 13) {\n return;\n }\n var actionItem = $(this),\n moduleElement = actionItem.closest(SELECTOR.ACTIVITYLI),\n action = actionItem.attr('data-action'),\n moduleId = getModuleId(moduleElement);\n switch (action) {\n case 'moveleft':\n case 'moveright':\n case 'delete':\n case 'duplicate':\n case 'hide':\n case 'stealth':\n case 'show':\n case 'groupsseparate':\n case 'groupsvisible':\n case 'groupsnone':\n break;\n default:\n // Nothing to do here!\n return;\n }\n if (!moduleId) {\n return;\n }\n e.preventDefault();\n if (action === 'delete') {\n // Deleting requires confirmation.\n confirmDeleteModule(moduleElement, function() {\n editModule(moduleElement, moduleId, actionItem);\n });\n } else {\n editModule(moduleElement, moduleId, actionItem);\n }\n });\n\n // Add a handler for section show/hide actions.\n $('body').on('click keypress', SELECTOR.SECTIONLI + ' ' +\n SELECTOR.SECTIONACTIONMENU + '[data-sectionid] ' +\n 'a[data-action]', function(e) {\n if (e.type === 'keypress' && e.keyCode !== 13) {\n return;\n }\n var actionItem = $(this),\n sectionElement = actionItem.closest(SELECTOR.SECTIONLI),\n sectionId = actionItem.closest(SELECTOR.SECTIONACTIONMENU).attr('data-sectionid');\n\n let isExecuted = true;\n if (actionItem.attr('data-confirm')) {\n // Action requires confirmation.\n confirmEditSection(actionItem.attr('data-confirm'), function() {\n isExecuted = editSection(sectionElement, sectionId, actionItem, courseformat);\n });\n } else {\n isExecuted = editSection(sectionElement, sectionId, actionItem, courseformat);\n }\n // Prevent any other module from capturing the action if it is already in execution.\n if (isExecuted) {\n e.preventDefault();\n }\n });\n\n // The section and activity names are edited using inplace editable.\n // The \"update\" jQuery event must be captured in order to update the course state.\n $('body').on('updated', `${SELECTOR.SECTIONLI} [data-inplaceeditable]`, function(e) {\n if (e.ajaxreturn && e.ajaxreturn.itemid) {\n const state = courseeditor.state;\n const section = state.section.get(e.ajaxreturn.itemid);\n if (section !== undefined) {\n courseeditor.dispatch('sectionState', [e.ajaxreturn.itemid]);\n }\n }\n });\n $('body').on('updated', `${SELECTOR.ACTIVITYLI} [data-inplaceeditable]`, function(e) {\n if (e.ajaxreturn && e.ajaxreturn.itemid) {\n courseeditor.dispatch('cmState', [e.ajaxreturn.itemid]);\n }\n });\n\n // Component-based formats don't use modals to create sections.\n if (courseeditor.supportComponents && componentActions.includes('addSection')) {\n return;\n }\n\n // Add a handler for \"Add sections\" link to ask for a number of sections to add.\n str.get_string('numberweeks').done(function(strNumberSections) {\n var trigger = $(SELECTOR.ADDSECTIONS),\n modalTitle = trigger.attr('data-add-sections'),\n newSections = trigger.attr('data-new-sections');\n var modalBody = $('
' +\n '
');\n modalBody.find('label').html(strNumberSections);\n ModalFactory.create({\n title: modalTitle,\n type: ModalFactory.types.SAVE_CANCEL,\n body: modalBody.html()\n }, trigger)\n .done(function(modal) {\n var numSections = $(modal.getBody()).find('#add_section_numsections'),\n addSections = function() {\n // Check if value of the \"Number of sections\" is a valid positive integer and redirect\n // to adding a section script.\n if ('' + parseInt(numSections.val()) === numSections.val() && parseInt(numSections.val()) >= 1) {\n document.location = trigger.attr('href') + '&numsections=' + parseInt(numSections.val());\n }\n };\n modal.setSaveButtonText(modalTitle);\n modal.getRoot().on(ModalEvents.shown, function() {\n // When modal is shown focus and select the input and add a listener to keypress of \"Enter\".\n numSections.focus().select().on('keydown', function(e) {\n if (e.keyCode === KeyCodes.enter) {\n addSections();\n }\n });\n });\n modal.getRoot().on(ModalEvents.save, function(e) {\n // When modal \"Add\" button is pressed.\n e.preventDefault();\n addSections();\n });\n });\n });\n },\n\n /**\n * Replaces a section action menu item with another one (for example Show->Hide, Set marker->Remove marker)\n *\n * This method can be used by course formats in their listener to the coursesectionedited event\n *\n * @deprecated since Moodle 3.9\n * @param {JQuery} sectionelement\n * @param {String} selector CSS selector inside the section element, for example \"a[data-action=show]\"\n * @param {String} image new image name (\"i/show\", \"i/hide\", etc.)\n * @param {String} stringname new string for the action menu item\n * @param {String} stringcomponent\n * @param {String} newaction new value for data-action attribute of the link\n */\n replaceSectionActionItem: function(sectionelement, selector, image, stringname,\n stringcomponent, newaction) {\n log.debug('replaceSectionActionItem() is deprecated and will be removed.');\n var actionitem = sectionelement.find(SELECTOR.SECTIONACTIONMENU + ' ' + selector);\n replaceActionItem(actionitem, image, stringname, stringcomponent, newaction);\n },\n // Method to refresh a module.\n refreshModule,\n refreshSection,\n };\n });\n"],"file":"actions.min.js"} \ No newline at end of file diff --git a/course/amd/src/actions.js b/course/amd/src/actions.js index 83a00151a16..0e2bc0f7504 100644 --- a/course/amd/src/actions.js +++ b/course/amd/src/actions.js @@ -846,11 +846,7 @@ define( case 'hide': case 'show': - cm.visible = (action === 'show') ? true : false; - break; - case 'duplicate': - // Duplicate requires to get extra data from the server. courseeditor.dispatch('cmState', affectedids); break; } diff --git a/course/format/amd/build/local/courseindex/cm.min.js b/course/format/amd/build/local/courseindex/cm.min.js index 3977fd99485..6609da78b73 100644 --- a/course/format/amd/build/local/courseindex/cm.min.js +++ b/course/format/amd/build/local/courseindex/cm.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseindex/cm",["exports","core_courseformat/local/courseeditor/dndcmitem","core/templates","core/prefetch","core/config"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=f(b);c=f(c);d=f(d);e=f(e);function f(a){return a&&a.__esModule?a:{default:a}}function g(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){g=function(a){return typeof a}}else{g=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return g(a)}function h(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function i(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){h(i,d,e,f,g,"next",a)}function g(a){h(i,d,e,f,g,"throw",a)}f(void 0)})}}function j(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function k(a,b){for(var c=0,d;c.\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\nimport Templates from 'core/templates';\nimport Prefetch from 'core/prefetch';\nimport Config from 'core/config';\n\n// Prefetch the completion icons template.\nconst completionTemplate = 'core_courseformat/local/courseindex/cmcompletion';\nPrefetch.prefetchTemplate(completionTemplate);\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // Default query selectors.\n this.selectors = {\n CM_NAME: `[data-for='cm_name']`,\n CM_COMPLETION: `[data-for='cm_completion']`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n CMHIDDEN: 'dimmed',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'rectrictions',\n PAGEITEM: 'pageitem',\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the course state.\n */\n stateReady(state) {\n this.configDragDrop(this.id);\n const cm = state.cm.get(this.id);\n const course = state.course;\n // Refresh completion icon.\n this._refreshCompletion({\n state,\n element: cm,\n });\n // Check if the current url is the cm url.\n if (window.location.href == cm.url || window.location.href == `${course.baseurl}#${cm.anchor}`) {\n this.reactive.dispatch('setPageItem', 'cm', this.id);\n this.element.scrollIntoView({block: \"center\"});\n }\n // Check if this we are displaying this activity page.\n if (Config.contextid != Config.courseContextId && Config.contextInstanceId == this.id) {\n this.reactive.dispatch('setPageItem', 'cm', this.id, true);\n this.element.scrollIntoView({block: \"center\"});\n }\n // Add anchor logic if the element is not user visible.\n if (!cm.uservisible) {\n this.addEventListener(\n this.getElement(this.selectors.CM_NAME),\n 'click',\n this._activityAnchor,\n );\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n {watch: `cm[${this.id}].completionstate:updated`, handler: this._refreshCompletion},\n {watch: `course.pageItem:updated`, handler: this._refreshPageItem},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n this.getElement(this.selectors.CM_NAME).innerHTML = element.name;\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrectrictions ?? false);\n this.locked = element.locked;\n }\n\n /**\n * Handle a page item update.\n *\n * @param {Object} details the update details\n * @param {Object} details.element the course state data.\n */\n _refreshPageItem({element}) {\n if (!element.pageItem) {\n return;\n }\n const isPageId = (element.pageItem.type == 'cm' && element.pageItem.id == this.id);\n this.element.classList.toggle(this.classes.PAGEITEM, isPageId);\n if (isPageId && !this.reactive.isEditing) {\n this.element.scrollIntoView({block: \"nearest\"});\n }\n }\n\n /**\n * Update the activity completion icon.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data\n * @param {Object} details.element the element data\n */\n async _refreshCompletion({state, element}) {\n // No completion icons are displayed in edit mode.\n if (this.reactive.isEditing || !element.istrackeduser) {\n return;\n }\n // Check if the completion value has changed.\n const completionElement = this.getElement(this.selectors.CM_COMPLETION);\n if (completionElement.dataset.value == element.completionstate) {\n return;\n }\n\n // Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.cmCompletion(state, element);\n\n try {\n const {html, js} = await Templates.renderForPromise(completionTemplate, data);\n Templates.replaceNode(completionElement, html, js);\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * The activity anchor event.\n *\n * @param {Event} event\n */\n _activityAnchor(event) {\n const cm = this.reactive.get('cm', this.id);\n // If the user cannot access the element but the element is present in the page\n // the new url should be an anchor link.\n const element = document.getElementById(cm.anchor);\n if (element) {\n // Marc the element as page item once the event is handled.\n setTimeout(() => {\n this.reactive.dispatch('setPageItem', 'cm', cm.id);\n }, 50);\n return;\n }\n // If the element is not present in the page we need to go to the specific section.\n const course = this.reactive.get('course');\n const section = this.reactive.get('section', cm.sectionid);\n if (!section) {\n return;\n }\n const url = `${course.baseurl}§ion=${section.number}#${cm.anchor}`;\n event.preventDefault();\n window.location = url;\n }\n}\n"],"file":"cm.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseindex/cm.js"],"names":["Prefetch","prefetchTemplate","Component","name","selectors","CM_NAME","CM_COMPLETION","classes","CMHIDDEN","LOCKED","RESTRICTIONS","PAGEITEM","id","element","dataset","state","configDragDrop","cm","get","course","_refreshCompletion","window","location","href","url","baseurl","anchor","reactive","dispatch","scrollIntoView","block","Config","contextid","courseContextId","contextInstanceId","uservisible","addEventListener","getElement","_activityAnchor","watch","handler","remove","_refreshCm","_refreshPageItem","classList","toggle","visible","innerHTML","DRAGGING","dragging","locked","hascmrestrictions","pageItem","isPageId","type","isEditing","istrackeduser","completionElement","value","completionstate","exporter","getExporter","data","cmCompletion","Templates","renderForPromise","html","js","replaceNode","event","document","getElementById","setTimeout","section","sectionid","number","preventDefault","target","DndCmItem"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\nimport Templates from 'core/templates';\nimport Prefetch from 'core/prefetch';\nimport Config from 'core/config';\n\n// Prefetch the completion icons template.\nconst completionTemplate = 'core_courseformat/local/courseindex/cmcompletion';\nPrefetch.prefetchTemplate(completionTemplate);\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // Default query selectors.\n this.selectors = {\n CM_NAME: `[data-for='cm_name']`,\n CM_COMPLETION: `[data-for='cm_completion']`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n CMHIDDEN: 'dimmed',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'restrictions',\n PAGEITEM: 'pageitem',\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the course state.\n */\n stateReady(state) {\n this.configDragDrop(this.id);\n const cm = state.cm.get(this.id);\n const course = state.course;\n // Refresh completion icon.\n this._refreshCompletion({\n state,\n element: cm,\n });\n // Check if the current url is the cm url.\n if (window.location.href == cm.url || window.location.href == `${course.baseurl}#${cm.anchor}`) {\n this.reactive.dispatch('setPageItem', 'cm', this.id);\n this.element.scrollIntoView({block: \"center\"});\n }\n // Check if this we are displaying this activity page.\n if (Config.contextid != Config.courseContextId && Config.contextInstanceId == this.id) {\n this.reactive.dispatch('setPageItem', 'cm', this.id, true);\n this.element.scrollIntoView({block: \"center\"});\n }\n // Add anchor logic if the element is not user visible.\n if (!cm.uservisible) {\n this.addEventListener(\n this.getElement(this.selectors.CM_NAME),\n 'click',\n this._activityAnchor,\n );\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n {watch: `cm[${this.id}].completionstate:updated`, handler: this._refreshCompletion},\n {watch: `course.pageItem:updated`, handler: this._refreshPageItem},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n this.getElement(this.selectors.CM_NAME).innerHTML = element.name;\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrestrictions ?? false);\n this.locked = element.locked;\n }\n\n /**\n * Handle a page item update.\n *\n * @param {Object} details the update details\n * @param {Object} details.element the course state data.\n */\n _refreshPageItem({element}) {\n if (!element.pageItem) {\n return;\n }\n const isPageId = (element.pageItem.type == 'cm' && element.pageItem.id == this.id);\n this.element.classList.toggle(this.classes.PAGEITEM, isPageId);\n if (isPageId && !this.reactive.isEditing) {\n this.element.scrollIntoView({block: \"nearest\"});\n }\n }\n\n /**\n * Update the activity completion icon.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data\n * @param {Object} details.element the element data\n */\n async _refreshCompletion({state, element}) {\n // No completion icons are displayed in edit mode.\n if (this.reactive.isEditing || !element.istrackeduser) {\n return;\n }\n // Check if the completion value has changed.\n const completionElement = this.getElement(this.selectors.CM_COMPLETION);\n if (completionElement.dataset.value == element.completionstate) {\n return;\n }\n\n // Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.cmCompletion(state, element);\n\n try {\n const {html, js} = await Templates.renderForPromise(completionTemplate, data);\n Templates.replaceNode(completionElement, html, js);\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * The activity anchor event.\n *\n * @param {Event} event\n */\n _activityAnchor(event) {\n const cm = this.reactive.get('cm', this.id);\n // If the user cannot access the element but the element is present in the page\n // the new url should be an anchor link.\n const element = document.getElementById(cm.anchor);\n if (element) {\n // Marc the element as page item once the event is handled.\n setTimeout(() => {\n this.reactive.dispatch('setPageItem', 'cm', cm.id);\n }, 50);\n return;\n }\n // If the element is not present in the page we need to go to the specific section.\n const course = this.reactive.get('course');\n const section = this.reactive.get('section', cm.sectionid);\n if (!section) {\n return;\n }\n const url = `${course.baseurl}§ion=${section.number}#${cm.anchor}`;\n event.preventDefault();\n window.location = url;\n }\n}\n"],"file":"cm.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseindex/section.min.js b/course/format/amd/build/local/courseindex/section.min.js index a84ffe3f236..1940edeedbf 100644 --- a/course/format/amd/build/local/courseindex/section.min.js +++ b/course/format/amd/build/local/courseindex/section.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseindex/section",["exports","core_courseformat/local/courseindex/sectiontitle","core_courseformat/local/courseeditor/dndsection"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){e=function(a){return typeof a}}else{e=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return e(a)}function f(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function g(a){for(var b=1,c;b.\n\n/**\n * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/section\n * @class core_courseformat/local/courseindex/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport SectionTitle from 'core_courseformat/local/courseindex/sectiontitle';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class Component extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_item']`,\n SECTION_TITLE: `[data-for='section_title']`,\n CM_LAST: `[data-for=\"cm\"]:last-child`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n SECTIONHIDDEN: 'dimmed',\n SECTIONCURRENT: 'current',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'rectrictions',\n PAGEITEM: 'pageitem',\n };\n\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n this.isPageItem = false;\n }\n\n /**\n * Static method to create a component instance form the mustahce template.\n *\n * @param {string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element passing the full section as affected region.\n const titleitem = new SectionTitle({\n ...this,\n element: sectionItem,\n fullregion: this.element,\n });\n this.configDragDrop(titleitem);\n }\n // Check if the current url is the section url.\n const section = state.section.get(this.id);\n if (window.location.href == section.sectionurl.replace(/&/g, \"&\")) {\n this.reactive.dispatch('setPageItem', 'section', this.id);\n sectionItem.scrollIntoView();\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section[${this.id}]:deleted`, handler: this.remove},\n {watch: `section[${this.id}]:updated`, handler: this._refreshSection},\n {watch: `course.pageItem:updated`, handler: this._refreshPageItem},\n ];\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n return this.getElement(this.selectors.CM_LAST);\n }\n\n /**\n * Update a course index section using the state information.\n *\n * @param {Object} param details the update details.\n * @param {Object} param.element the section element\n */\n _refreshSection({element}) {\n // Update classes.\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n sectionItem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);\n this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current);\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.element.classList.toggle(this.classes.RESTRICTIONS, element.hasrestrictions ?? false);\n this.locked = element.locked;\n // Update title.\n this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title;\n }\n\n /**\n * Handle a page item update.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data.\n * @param {Object} details.element the course state data.\n */\n _refreshPageItem({element, state}) {\n if (!element.pageItem) {\n return;\n }\n if (element.pageItem.sectionId !== this.id && this.isPageItem) {\n this.pageItem = false;\n this.getElement(this.selectors.SECTION_ITEM).classList.remove(this.classes.PAGEITEM);\n return;\n }\n const section = state.section.get(this.id);\n if (section.indexcollapsed && !element.pageItem?.isStatic) {\n this.pageItem = (element.pageItem?.sectionId == this.id);\n } else {\n this.pageItem = (element.pageItem.type == 'section' && element.pageItem.id == this.id);\n }\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n sectionItem.classList.toggle(this.classes.PAGEITEM, this.pageItem ?? false);\n if (this.pageItem && !this.reactive.isEditing) {\n this.element.scrollIntoView({block: \"nearest\"});\n }\n }\n}\n"],"file":"section.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseindex/section.js"],"names":["Component","name","selectors","SECTION_ITEM","SECTION_TITLE","CM_LAST","classes","SECTIONHIDDEN","SECTIONCURRENT","LOCKED","RESTRICTIONS","PAGEITEM","id","element","dataset","isPageItem","state","configState","sectionItem","getElement","reactive","isEditing","supportComponents","titleitem","SectionTitle","fullregion","configDragDrop","section","get","window","location","href","sectionurl","replace","dispatch","scrollIntoView","watch","handler","remove","_refreshSection","_refreshPageItem","classList","toggle","visible","hasrestrictions","current","DRAGGING","dragging","locked","innerHTML","title","pageItem","sectionId","indexcollapsed","isStatic","type","block","target","document","getElementById","DndSection"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/section\n * @class core_courseformat/local/courseindex/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport SectionTitle from 'core_courseformat/local/courseindex/sectiontitle';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class Component extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_item']`,\n SECTION_TITLE: `[data-for='section_title']`,\n CM_LAST: `[data-for=\"cm\"]:last-child`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n SECTIONHIDDEN: 'dimmed',\n SECTIONCURRENT: 'current',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'restrictions',\n PAGEITEM: 'pageitem',\n };\n\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n this.isPageItem = false;\n }\n\n /**\n * Static method to create a component instance form the mustahce template.\n *\n * @param {string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element passing the full section as affected region.\n const titleitem = new SectionTitle({\n ...this,\n element: sectionItem,\n fullregion: this.element,\n });\n this.configDragDrop(titleitem);\n }\n // Check if the current url is the section url.\n const section = state.section.get(this.id);\n if (window.location.href == section.sectionurl.replace(/&/g, \"&\")) {\n this.reactive.dispatch('setPageItem', 'section', this.id);\n sectionItem.scrollIntoView();\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section[${this.id}]:deleted`, handler: this.remove},\n {watch: `section[${this.id}]:updated`, handler: this._refreshSection},\n {watch: `course.pageItem:updated`, handler: this._refreshPageItem},\n ];\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n return this.getElement(this.selectors.CM_LAST);\n }\n\n /**\n * Update a course index section using the state information.\n *\n * @param {Object} param details the update details.\n * @param {Object} param.element the section element\n */\n _refreshSection({element}) {\n // Update classes.\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n sectionItem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);\n sectionItem.classList.toggle(this.classes.RESTRICTIONS, element.hasrestrictions ?? false);\n this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current);\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.locked = element.locked;\n // Update title.\n this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title;\n }\n\n /**\n * Handle a page item update.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data.\n * @param {Object} details.element the course state data.\n */\n _refreshPageItem({element, state}) {\n if (!element.pageItem) {\n return;\n }\n if (element.pageItem.sectionId !== this.id && this.isPageItem) {\n this.pageItem = false;\n this.getElement(this.selectors.SECTION_ITEM).classList.remove(this.classes.PAGEITEM);\n return;\n }\n const section = state.section.get(this.id);\n if (section.indexcollapsed && !element.pageItem?.isStatic) {\n this.pageItem = (element.pageItem?.sectionId == this.id);\n } else {\n this.pageItem = (element.pageItem.type == 'section' && element.pageItem.id == this.id);\n }\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n sectionItem.classList.toggle(this.classes.PAGEITEM, this.pageItem ?? false);\n if (this.pageItem && !this.reactive.isEditing) {\n this.element.scrollIntoView({block: \"nearest\"});\n }\n }\n}\n"],"file":"section.min.js"} \ No newline at end of file diff --git a/course/format/amd/src/local/courseindex/cm.js b/course/format/amd/src/local/courseindex/cm.js index ee39aa66ae2..eb7906549fd 100644 --- a/course/format/amd/src/local/courseindex/cm.js +++ b/course/format/amd/src/local/courseindex/cm.js @@ -50,7 +50,7 @@ export default class Component extends DndCmItem { this.classes = { CMHIDDEN: 'dimmed', LOCKED: 'editinprogress', - RESTRICTIONS: 'rectrictions', + RESTRICTIONS: 'restrictions', PAGEITEM: 'pageitem', }; // We need our id to watch specific events. @@ -131,7 +131,7 @@ export default class Component extends DndCmItem { this.getElement(this.selectors.CM_NAME).innerHTML = element.name; this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false); this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false); - this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrectrictions ?? false); + this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrestrictions ?? false); this.locked = element.locked; } diff --git a/course/format/amd/src/local/courseindex/section.js b/course/format/amd/src/local/courseindex/section.js index 6dca16386fb..4864e3b84b4 100644 --- a/course/format/amd/src/local/courseindex/section.js +++ b/course/format/amd/src/local/courseindex/section.js @@ -46,7 +46,7 @@ export default class Component extends DndSection { SECTIONHIDDEN: 'dimmed', SECTIONCURRENT: 'current', LOCKED: 'editinprogress', - RESTRICTIONS: 'rectrictions', + RESTRICTIONS: 'restrictions', PAGEITEM: 'pageitem', }; @@ -127,10 +127,10 @@ export default class Component extends DndSection { // Update classes. const sectionItem = this.getElement(this.selectors.SECTION_ITEM); sectionItem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible); + sectionItem.classList.toggle(this.classes.RESTRICTIONS, element.hasrestrictions ?? false); this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current); this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false); this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false); - this.element.classList.toggle(this.classes.RESTRICTIONS, element.hasrestrictions ?? false); this.locked = element.locked; // Update title. this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title; diff --git a/course/format/classes/output/local/state/cm.php b/course/format/classes/output/local/state/cm.php index c41e4ba1ab8..eaa6897e3d2 100644 --- a/course/format/classes/output/local/state/cm.php +++ b/course/format/classes/output/local/state/cm.php @@ -86,26 +86,13 @@ class cm implements renderable { 'sectionid' => $section->id, 'sectionnumber' => $section->section, 'uservisible' => $cm->uservisible, + 'hascmrestrictions' => $this->get_has_restrictions(), ]; // Check the user access type to this cm. $info = new info_module($cm); $data->accessvisible = ($data->visible && $info->is_available_for_all()); - // Check if restriction access are visible to the user. - $canviewhidden = has_capability('moodle/course:viewhiddenactivities', $cm->context); - if (!empty($CFG->enableavailability) && $canviewhidden) { - if (has_capability('moodle/course:manageactivities', $cm->context)) { - // Course editors can see all restrictions. - $data->hascmrectrictions = !empty($cm->availability); - } else { - // Some users can see restrictions even if it does not apply to them. - $data->hascmrectrictions = !empty($cm->availableinfo); - } - } else { - $data->hascmrectrictions = !$data->accessvisible || !$cm->uservisible; - } - // Add url if the activity is compatible. $url = $cm->url; if ($url) { @@ -126,4 +113,33 @@ class cm implements renderable { return $data; } + + /** + * Return if the activity has a restrictions icon displayed or not. + * + * @return bool if the activity has visible restrictions for the user. + */ + protected function get_has_restrictions(): bool { + global $CFG; + $cm = $this->cm; + + if (empty($cm->visible) || empty($CFG->enableavailability)) { + return false; + } + // Nothing to be displayed to the user. + if (!$cm->is_visible_on_course_page()) { + return false; + } + // Not allowed to see the module but might be allowed to see some availability. + if (!$cm->uservisible) { + return !empty($cm->availableinfo); + } + // Content editors can see all restrictions if the activity is visible. + if (has_capability('moodle/course:viewhiddenactivities', $cm->context)) { + $ci = new info_module($cm); + return !empty($ci->get_full_information()); + } + // Regular users can only see restrictions if apply to them. + return false; + } } diff --git a/course/format/classes/output/local/state/section.php b/course/format/classes/output/local/state/section.php index f2294a26637..c73c9769c9a 100644 --- a/course/format/classes/output/local/state/section.php +++ b/course/format/classes/output/local/state/section.php @@ -117,21 +117,19 @@ class section implements renderable { $context = context_course::instance($course->id); // Hidden sections have no restriction indicator displayed. - if (!$section->visible || empty($CFG->enableavailability)) { + if (empty($section->visible) || empty($CFG->enableavailability)) { return false; } - if (!has_capability('moodle/course:viewhiddenactivities', $context)) { - // If the section is visible but not user visible means it has some locking rule. - return empty($section->uservisible); - } - - if (has_capability('moodle/course:manageactivities', $context)) { - // Course editors can see all restrictions if the section is visible. - $ci = new info_section($section); - return !empty($ci->get_full_information()); - } else { - // Some users can see restrictions even if it does not apply to them. + // The activity is not visible to the user but it may have some availability information. + if (!$section->uservisible) { return !empty($section->availableinfo); } + // Course editors can see all restrictions if the section is visible. + if (has_capability('moodle/course:viewhiddensections', $context)) { + $ci = new info_section($section); + return !empty($ci->get_full_information()); + } + // Regular users can only see restrictions if apply to them. + return false; } } diff --git a/course/format/templates/local/courseindex/cm.mustache b/course/format/templates/local/courseindex/cm.mustache index b7b3b828421..b935868e025 100644 --- a/course/format/templates/local/courseindex/cm.mustache +++ b/course/format/templates/local/courseindex/cm.mustache @@ -28,12 +28,12 @@ "isactive": 1, "uniqid": "0", "accessvisible": 1, - "hascmrectrictions": 0 + "hascmrestrictions": 0 } }}
  • setup_hasrestrictions_scenario($format, $addcanviewhidden, $rolename, $hasavailability, $available); + $data = $this->setup_hasrestrictions_scenario($format, $rolename, $hasavailability, $available); // Get the cm state. $courseformat = $data->courseformat; @@ -78,14 +76,13 @@ class cm_test extends \advanced_testcase { ); $state = $cmstate->export_for_template($renderer); - $this->assertEquals($expected, $state->hascmrectrictions); + $this->assertEquals($expected, $state->hascmrestrictions); } /** * Setup section or cm has restrictions scenario. * * @param string $format the course format - * @param bool $addcanviewhidden if the canviewhidden capabilities must be added to the role. * @param string $rolename the user role name (editingteacher or student) * @param bool $hasavailability if the activity|section has availability * @param bool $available if the activity availability condition is available or not to the user @@ -93,7 +90,6 @@ class cm_test extends \advanced_testcase { */ private function setup_hasrestrictions_scenario( string $format = 'topics', - bool $addcanviewhidden = false, string $rolename = 'editingteacher', bool $hasavailability = false, bool $available = false @@ -101,6 +97,8 @@ class cm_test extends \advanced_testcase { global $PAGE, $DB; $this->resetAfterTest(); + set_config('enableavailability', 1); + $course = $this->getDataGenerator()->create_course(['numsections' => 1, 'format' => $format]); // Create and enrol user. @@ -112,13 +110,6 @@ class cm_test extends \advanced_testcase { ); $this->setUser($user); - // Add capabilities if necessary. - if ($addcanviewhidden) { - $roleid = $DB->get_field('role', 'id', array('shortname' => $rolename), MUST_EXIST); - $coursecontext = context_course::instance($course->id); - assign_capability('moodle/course:viewhiddenactivities', CAP_ALLOW, $roleid, $coursecontext->id); - } - // Create an activity. $activity = $this->getDataGenerator()->create_module('page', ['course' => $course->id], [ 'section' => 1, @@ -165,225 +156,198 @@ class cm_test extends \advanced_testcase { public function hasrestrictions_state_provider(): array { return [ // Teacher scenarios (topics). - 'Topics, can edit, has availability and is available' => [ + 'Teacher, Topics, can edit, has availability and is available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => true, 'expected' => true, ], - 'Topics, can edit, has availability and is not available' => [ + 'Teacher, Topics, can edit, has availability and is not available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Topics, can edit and has not availability' => [ + 'Teacher, Topics, can edit and has not availability' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => false, 'available' => true, 'expected' => false, ], // Teacher scenarios (weeks). - 'Weeks, can edit, has availability and is available' => [ + 'Teacher, Weeks, can edit, has availability and is available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => true, 'expected' => true, ], - 'Weeks, can edit, has availability and is not available' => [ + 'Teacher, Weeks, can edit, has availability and is not available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Weeks, can edit and has not availability' => [ + 'Teacher, Weeks, can edit and has not availability' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => false, 'available' => true, 'expected' => false, ], // Teacher scenarios (mock format). - 'Mock format, can edit, has availability and is available' => [ + 'Teacher, Mock format, can edit, has availability and is available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => true, 'expected' => true, ], - 'Mock format, can edit, has availability and is not available' => [ + 'Teacher, Mock format, can edit, has availability and is not available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Mock format, can edit and has not availability' => [ + 'Teacher, Mock format, can edit and has not availability' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => false, 'available' => true, 'expected' => false, ], + // Non editing teacher scenarios (topics). + 'Non editing teacher, Topics, can edit, has availability and is available' => [ + 'format' => 'topics', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => true, + 'expected' => true, + ], + 'Non editing teacher, Topics, can edit, has availability and is not available' => [ + 'format' => 'topics', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => false, + 'expected' => true, + ], + 'Non editing teacher, Topics, can edit and has not availability' => [ + 'format' => 'topics', + 'rolename' => 'teacher', + 'hasavailability' => false, + 'available' => true, + 'expected' => false, + ], + // Non editing teacher scenarios (weeks). + 'Non editing teacher, Weeks, can edit, has availability and is available' => [ + 'format' => 'weeks', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => true, + 'expected' => true, + ], + 'Non editing teacher, Weeks, can edit, has availability and is not available' => [ + 'format' => 'weeks', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => false, + 'expected' => true, + ], + 'Non editing teacher, Weeks, can edit and has not availability' => [ + 'format' => 'weeks', + 'rolename' => 'teacher', + 'hasavailability' => false, + 'available' => true, + 'expected' => false, + ], + // Non editing teacher scenarios (mock format). + 'Non editing teacher, Mock format, can edit, has availability and is available' => [ + 'format' => 'theunittest', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => true, + 'expected' => true, + ], + 'Non editing teacher, Mock format, can edit, has availability and is not available' => [ + 'format' => 'theunittest', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => false, + 'expected' => true, + ], + 'Non editing teacher, Mock format, can edit and has not availability' => [ + 'format' => 'theunittest', + 'rolename' => 'teacher', + 'hasavailability' => false, + 'available' => true, + 'expected' => false, + ], // Student scenarios (topics). - 'Topics, cannot edit, has availability and is available' => [ + 'Student, Topics, cannot edit, has availability and is available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => true, 'expected' => false, ], - 'Topics, cannot edit, has availability and is not available' => [ + 'Student, Topics, cannot edit, has availability and is not available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Topics, cannot edit and has not availability' => [ + 'Student, Topics, cannot edit and has not availability' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => false, 'available' => true, 'expected' => false, ], // Student scenarios (weeks). - 'Weeks, cannot edit, has availability and is available' => [ + 'Student, Weeks, cannot edit, has availability and is available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => true, 'expected' => false, ], - 'Weeks, cannot edit, has availability and is not available' => [ + 'Student, Weeks, cannot edit, has availability and is not available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Weeks, cannot edit and has not availability' => [ + 'Student, Weeks, cannot edit and has not availability' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => false, 'available' => true, 'expected' => false, ], // Student scenarios (mock format). - 'Mock format, cannot edit, has availability and is available' => [ + 'Student, Mock format, cannot edit, has availability and is available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => true, 'expected' => false, ], - 'Mock format, cannot edit, has availability and is not available' => [ + 'Student, Mock format, cannot edit, has availability and is not available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Mock format, cannot edit and has not availability' => [ + 'Student, Mock format, cannot edit and has not availability' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, - 'rolename' => 'student', - 'hasavailability' => false, - 'available' => true, - 'expected' => false, - ], - // Students with view hidden activities capabilities (topics). - 'Topics, can view hidden but not edit, has availability and is available' => [ - 'format' => 'topics', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => true, - 'expected' => false, - ], - 'Topics, can view hidden but not edit, has availability and is not available' => [ - 'format' => 'topics', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => false, - 'expected' => true, - ], - 'Topics, can view hidden but not edit and has not availability' => [ - 'format' => 'topics', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => false, - 'available' => true, - 'expected' => false, - ], - // Students with view hidden activities capabilities (weeks). - 'Weeks, can view hidden but not edit, has availability and is available' => [ - 'format' => 'weeks', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => true, - 'expected' => false, - ], - 'Weeks, can view hidden but not edit, has availability and is not available' => [ - 'format' => 'weeks', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => false, - 'expected' => true, - ], - 'Weeks, can view hidden but not edit and has not availability' => [ - 'format' => 'weeks', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => false, - 'available' => true, - 'expected' => false, - ], - // Students with view hidden activities capabilities (mock format). - 'Mock format, can view hidden but not edit, has availability and is available' => [ - 'format' => 'theunittest', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => true, - 'expected' => false, - ], - 'Mock format, can view hidden but not edit, has availability and is not available' => [ - 'format' => 'theunittest', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => false, - 'expected' => true, - ], - 'Mock format, can view hidden but not edit and has not availability' => [ - 'format' => 'theunittest', - 'addcanviewhidden' => true, 'rolename' => 'student', 'hasavailability' => false, 'available' => true, diff --git a/course/format/tests/output/local/state/section_test.php b/course/format/tests/output/local/state/section_test.php index c7a5fcdf0ad..ef12f894a75 100644 --- a/course/format/tests/output/local/state/section_test.php +++ b/course/format/tests/output/local/state/section_test.php @@ -49,7 +49,6 @@ class section_test extends \advanced_testcase { * @covers ::export_for_template * * @param string $format the course format - * @param bool $addcanviewhidden if the canviewhidden capabilities must be added to the role. * @param string $rolename the user role name (editingteacher or student) * @param bool $hasavailability if the activity|section has availability * @param bool $available if the activity availability condition is available or not to the user @@ -57,13 +56,12 @@ class section_test extends \advanced_testcase { */ public function test_section_hasrestrictions_state( string $format = 'topics', - bool $addcanviewhidden = false, string $rolename = 'editingteacher', bool $hasavailability = false, bool $available = false, bool $expected = false ) { - $data = $this->setup_hasrestrictions_scenario($format, $addcanviewhidden, $rolename, $hasavailability, $available); + $data = $this->setup_hasrestrictions_scenario($format, $rolename, $hasavailability, $available); // Get the cm state. $courseformat = $data->courseformat; @@ -84,7 +82,6 @@ class section_test extends \advanced_testcase { * Setup section or cm has restrictions scenario. * * @param string $format the course format - * @param bool $addcanviewhidden if the canviewhidden capabilities must be added to the role. * @param string $rolename the user role name (editingteacher or student) * @param bool $hasavailability if the section has availability * @param bool $available if the section availability condition is available or not to the user @@ -92,7 +89,6 @@ class section_test extends \advanced_testcase { */ private function setup_hasrestrictions_scenario( string $format = 'topics', - bool $addcanviewhidden = false, string $rolename = 'editingteacher', bool $hasavailability = false, bool $available = false @@ -111,13 +107,6 @@ class section_test extends \advanced_testcase { ); $this->setUser($user); - // Add capabilities if necessary. - if ($addcanviewhidden) { - $roleid = $DB->get_field('role', 'id', array('shortname' => $rolename), MUST_EXIST); - $coursecontext = context_course::instance($course->id); - assign_capability('moodle/course:viewhiddenactivities', CAP_ALLOW, $roleid, $coursecontext->id); - } - // Set up the availability settings. if ($hasavailability) { $operation = ($available) ? condition::DIRECTION_UNTIL : condition::DIRECTION_FROM; @@ -159,84 +148,140 @@ class section_test extends \advanced_testcase { public function hasrestrictions_state_provider(): array { return [ // Teacher scenarios (topics). - 'Topics, can edit, has availability and is available' => [ + 'Teacher, Topics, can edit, has availability and is available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => true, 'expected' => true, ], - 'Topics, can edit, has availability and is not available' => [ + 'Teacher, Topics, can edit, has availability and is not available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Topics, can edit and has not availability' => [ + 'Teacher, Topics, can edit and has not availability' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => false, 'available' => true, 'expected' => false, ], // Teacher scenarios (weeks). - 'Weeks, can edit, has availability and is available' => [ + 'Teacher, Weeks, can edit, has availability and is available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => true, 'expected' => true, ], - 'Weeks, can edit, has availability and is not available' => [ + 'Teacher, Weeks, can edit, has availability and is not available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Weeks, can edit and has not availability' => [ + 'Teacher, Weeks, can edit and has not availability' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => false, 'available' => true, 'expected' => false, ], // Teacher scenarios (mock format). - 'Mock format, can edit, has availability and is available' => [ + 'Teacher, Mock format, can edit, has availability and is available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => true, 'expected' => true, ], - 'Mock format, can edit, has availability and is not available' => [ + 'Teacher, Mock format, can edit, has availability and is not available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => true, 'available' => false, 'expected' => true, ], - 'Mock format, can edit and has not availability' => [ + 'Teacher, Mock format, can edit and has not availability' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'editingteacher', 'hasavailability' => false, 'available' => true, 'expected' => false, ], + // Non editing teacher scenarios (topics). + 'Non editing teacher, Topics, can edit, has availability and is available' => [ + 'format' => 'topics', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => true, + 'expected' => false, + ], + 'Non editing teacher, Topics, can edit, has availability and is not available' => [ + 'format' => 'topics', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => false, + 'expected' => false, + ], + 'Non editing teacher, Topics, can edit and has not availability' => [ + 'format' => 'topics', + 'rolename' => 'teacher', + 'hasavailability' => false, + 'available' => true, + 'expected' => false, + ], + // Non editing teacher scenarios (weeks). + 'Non editing teacher, Weeks, can edit, has availability and is available' => [ + 'format' => 'weeks', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => true, + 'expected' => false, + ], + 'Non editing teacher, Weeks, can edit, has availability and is not available' => [ + 'format' => 'weeks', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => false, + 'expected' => false, + ], + 'Non editing teacher, Weeks, can edit and has not availability' => [ + 'format' => 'weeks', + 'rolename' => 'teacher', + 'hasavailability' => false, + 'available' => true, + 'expected' => false, + ], + // Non editing teacher scenarios (mock format). + 'Non editing teacher, Mock format, can edit, has availability and is available' => [ + 'format' => 'theunittest', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => true, + 'expected' => false, + ], + 'Non editing teacher, Mock format, can edit, has availability and is not available' => [ + 'format' => 'theunittest', + 'rolename' => 'teacher', + 'hasavailability' => true, + 'available' => false, + 'expected' => false, + ], + 'Non editing teacher, Mock format, can edit and has not availability' => [ + 'format' => 'theunittest', + 'rolename' => 'teacher', + 'hasavailability' => false, + 'available' => true, + 'expected' => false, + ], // Student scenarios (topics). 'Topics, cannot edit, has availability and is available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => true, @@ -244,7 +289,6 @@ class section_test extends \advanced_testcase { ], 'Topics, cannot edit, has availability and is not available' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => false, @@ -252,7 +296,6 @@ class section_test extends \advanced_testcase { ], 'Topics, cannot edit and has not availability' => [ 'format' => 'topics', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => false, 'available' => true, @@ -261,7 +304,6 @@ class section_test extends \advanced_testcase { // Student scenarios (weeks). 'Weeks, cannot edit, has availability and is available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => true, @@ -269,7 +311,6 @@ class section_test extends \advanced_testcase { ], 'Weeks, cannot edit, has availability and is not available' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => false, @@ -277,7 +318,6 @@ class section_test extends \advanced_testcase { ], 'Weeks, cannot edit and has not availability' => [ 'format' => 'weeks', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => false, 'available' => true, @@ -286,7 +326,6 @@ class section_test extends \advanced_testcase { // Student scenarios (mock format). 'Mock format, cannot edit, has availability and is available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => true, @@ -294,7 +333,6 @@ class section_test extends \advanced_testcase { ], 'Mock format, cannot edit, has availability and is not available' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, 'rolename' => 'student', 'hasavailability' => true, 'available' => false, @@ -302,82 +340,6 @@ class section_test extends \advanced_testcase { ], 'Mock format, cannot edit and has not availability' => [ 'format' => 'theunittest', - 'addcanviewhidden' => false, - 'rolename' => 'student', - 'hasavailability' => false, - 'available' => true, - 'expected' => false, - ], - // Students with view hidden activities capabilities (topics). - 'Topics, can view hidden but not edit, has availability and is available' => [ - 'format' => 'topics', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => true, - 'expected' => false, - ], - 'Topics, can view hidden but not edit, has availability and is not available' => [ - 'format' => 'topics', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => false, - 'expected' => true, - ], - 'Topics, can view hidden but not edit and has not availability' => [ - 'format' => 'topics', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => false, - 'available' => true, - 'expected' => false, - ], - // Students with view hidden activities capabilities (weeks). - 'Weeks, can view hidden but not edit, has availability and is available' => [ - 'format' => 'weeks', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => true, - 'expected' => false, - ], - 'Weeks, can view hidden but not edit, has availability and is not available' => [ - 'format' => 'weeks', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => false, - 'expected' => true, - ], - 'Weeks, can view hidden but not edit and has not availability' => [ - 'format' => 'weeks', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => false, - 'available' => true, - 'expected' => false, - ], - // Students with view hidden activities capabilities (mock format). - 'Mock format, can view hidden but not edit, has availability and is available' => [ - 'format' => 'theunittest', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => true, - 'expected' => false, - ], - 'Mock format, can view hidden but not edit, has availability and is not available' => [ - 'format' => 'theunittest', - 'addcanviewhidden' => true, - 'rolename' => 'student', - 'hasavailability' => true, - 'available' => false, - 'expected' => true, - ], - 'Mock format, can view hidden but not edit and has not availability' => [ - 'format' => 'theunittest', - 'addcanviewhidden' => true, 'rolename' => 'student', 'hasavailability' => false, 'available' => true, diff --git a/theme/boost/scss/moodle/courseindex.scss b/theme/boost/scss/moodle/courseindex.scss index 35d587c533a..8a7715a2054 100644 --- a/theme/boost/scss/moodle/courseindex.scss +++ b/theme/boost/scss/moodle/courseindex.scss @@ -89,7 +89,7 @@ $courseindex-item-current: $primary !default; .courseindex-locked { display: none; } - &.rectrictions { + &.restrictions { .courseindex-locked { display: block; } diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css index 75e798e952f..d76da133bb7 100644 --- a/theme/boost/style/moodle.css +++ b/theme/boost/style/moodle.css @@ -21376,7 +21376,7 @@ div.editor_atto_toolbar button .icon { color: #6a737b; } .courseindex .courseindex-item .courseindex-locked { display: none; } - .courseindex .courseindex-item.rectrictions .courseindex-locked { + .courseindex .courseindex-item.restrictions .courseindex-locked { display: block; } .courseindex .courseindex-item.pageitem { background-color: #0f6cbf; diff --git a/theme/classic/style/moodle.css b/theme/classic/style/moodle.css index e162bbc2b86..97b73c15b7f 100644 --- a/theme/classic/style/moodle.css +++ b/theme/classic/style/moodle.css @@ -21322,7 +21322,7 @@ div.editor_atto_toolbar button .icon { color: #6a737b; } .courseindex .courseindex-item .courseindex-locked { display: none; } - .courseindex .courseindex-item.rectrictions .courseindex-locked { + .courseindex .courseindex-item.restrictions .courseindex-locked { display: block; } .courseindex .courseindex-item.pageitem { background-color: #0f6cbf;