Merge branch 'MDL-59751-master-v2' of git://github.com/lameze/moodle

This commit is contained in:
Jun Pataleta
2017-10-05 14:53:31 +08:00
30 changed files with 808 additions and 220 deletions
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){var n={ROOT:"[data-region='calendar']",DAY:"[data-region='day']",EVENT_ITEM:"[data-region='event-item']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']",DAY_CONTENT:"[data-region='day-content']",LOADING_ICON:".loading-icon",VIEW_DAY_LINK:"[data-action='view-day-link']",CALENDAR_MONTH_WRAPPER:".calendarwrapper",COURSE_SELECTOR:'select[name="course"]',TODAY:".today"},o=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},p=function(a){k.getEventById(a).then(function(b){if(!b.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+a);var c=b.event;return o(c.eventtype).then(function(a){return c.eventtype=a,c})}).then(function(a){var b={title:a.name,type:j.TYPE,body:d.render("core_calendar/event_summary_body",a),templateContext:{canedit:a.canedit,candelete:a.candelete,isactionevent:a.isactionevent,url:a.url}};return h.create(b)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},q=function(b,c,f,g){var h=null,i=g.attr("data-day-timestamp");f&&(h=f.attr("data-day-timestamp")),f&&h==i||d.render("core/loading",{}).then(function(a,b){g.find(n.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(n.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(f,a,b))}).then(function(){return k.updateEventStartDay(c,i)}).then(function(){a("body").trigger(l.eventMoved,[c,f,g])}).always(function(){var a=g.find(n.LOADING_ICON);if(g.find(n.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(n.LOADING_ICON);f.find(n.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},r=function(a){var b=a.find(n.NEW_EVENT_BUTTON),c=b.attr("data-context-id");return h.create({type:i.TYPE,large:!0,templateContext:{contextid:c}})},s=function(b,c){var d=a("body");d.on(l.created,function(){m.reloadCurrentMonth(b)}),d.on(l.deleted,function(){m.reloadCurrentMonth(b)}),d.on(l.updated,function(){m.reloadCurrentMonth(b)}),d.on(l.editActionEvent,function(a,b){window.location.assign(b)}),d.on(l.moveEvent,q),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(b,c){a.setEventId(c),a.show()})}).fail(e.exception)},t=function(b){b.on("click",n.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null;d=c.is(n.EVENT_LINK)?c.attr("data-event-id"):c.find(n.EVENT_LINK).attr("data-event-id"),p(d)}),b.on("change",n.COURSE_SELECTOR,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d,null).then(function(){return b.find(n.COURSE_SELECTOR).val(d)}).fail(e.exception)});var c=r(b);s(b,c),f.define(b,[f.events.activate]),b.on("click",n.NEW_EVENT_BUTTON,function(a){c.then(function(a){var c=b.find(n.CALENDAR_MONTH_WRAPPER);a.setCourseId(c.data("courseid"));var d=c.data("categoryid");"undefined"!=typeof d&&a.setCategoryId(d);var e=b.find(n.TODAY);e.length||a.setStartTime(b.find(n.DAY).attr("data-new-event-timestamp")),a.show()}).fail(e.exception),a.preventDefault()}),b.on("click",n.DAY,function(b){var d=a(b.target);if(!d.is(n.VIEW_DAY_LINK)){var f=a(this).attr("data-new-event-timestamp");c.then(function(a){var b=d.closest(n.CALENDAR_MONTH_WRAPPER);a.setCourseId(b.data("courseid"));var c=b.data("categoryid");"undefined"!=typeof c&&a.setCategoryId(c),a.setStartTime(f),a.show()}).fail(e.exception),b.preventDefault()}})};return{init:function(b){b=a(b),m.init(b),t(b)}}});
define(["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p={ROOT:"[data-region='calendar']",DAY:"[data-region='day']",EVENT_ITEM:"[data-region='event-item']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']",DAY_CONTENT:"[data-region='day-content']",LOADING_ICON:".loading-icon",VIEW_DAY_LINK:"[data-action='view-day-link']",CALENDAR_MONTH_WRAPPER:".calendarwrapper",COURSE_SELECTOR:'select[name="course"]',TODAY:".today"},q=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},r=function(a){k.getEventById(a).then(function(b){if(!b.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+a);var c=b.event;return q(c.eventtype).then(function(a){return c.eventtype=a,c})}).then(function(a){var b={title:a.name,type:j.TYPE,body:d.render("core_calendar/event_summary_body",a),templateContext:{canedit:a.canedit,candelete:a.candelete,isactionevent:a.isactionevent,url:a.url}};return h.create(b)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},s=function(b,c,f,g){var h=null,i=g.attr("data-day-timestamp");f&&(h=f.attr("data-day-timestamp")),f&&h==i||d.render("core/loading",{}).then(function(a,b){g.find(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(f,a,b))}).then(function(){return k.updateEventStartDay(c,i)}).then(function(){a("body").trigger(l.eventMoved,[c,f,g])}).always(function(){var a=g.find(p.LOADING_ICON);if(g.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(p.LOADING_ICON);f.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},t=function(b,c){var d=a("body");d.on(l.created,function(){m.reloadCurrentMonth(b)}),d.on(l.deleted,function(){m.reloadCurrentMonth(b)}),d.on(l.updated,function(){m.reloadCurrentMonth(b)}),d.on(l.editActionEvent,function(a,b){window.location.assign(b)}),d.on(l.moveEvent,s),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(c,d){var e=b.find(o.wrapper);a.setEventId(d),a.setContextId(e.data("contextId")),a.show()})}).fail(e.exception)},u=function(b){b.on("click",p.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null;d=c.is(p.EVENT_LINK)?c.attr("data-event-id"):c.find(p.EVENT_LINK).attr("data-event-id"),r(d)}),b.on("change",p.COURSE_SELECTOR,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d,null).then(function(){return b.find(p.COURSE_SELECTOR).val(d)}).fail(e.exception)});var c=n.registerEventFormModal(b);t(b,c),b.on("click",p.DAY,function(b){var d=a(b.target);if(!d.is(p.VIEW_DAY_LINK)){var f=a(this).attr("data-new-event-timestamp");c.then(function(a){var b=d.closest(o.wrapper);a.setCourseId(b.data("courseid"));var c=b.data("categoryid");"undefined"!=typeof c&&a.setCategoryId(c),a.setContextId(b.data("contextId")),a.setStartTime(f),a.show()}).fail(e.exception),b.preventDefault()}})};return{init:function(b){b=a(b),m.init(b),u(b)}}});
+1
View File
@@ -0,0 +1 @@
define(["jquery","core/str","core/notification","core_calendar/selectors","core_calendar/events","core_calendar/view_manager","core_calendar/repository","core/modal_factory","core_calendar/modal_event_form","core/modal_events","core_calendar/crud"],function(a,b,c,d,e,f,g,h,i,j,k){var l=function(b,g){var h=a("body");k.registerEventFormModal(b),k.registerRemove(b);var i="reloadCurrent"+g.charAt(0).toUpperCase()+g.slice(1);h.on(e.created,function(){f[i](b)}),h.on(e.deleted,function(){f[i](b)}),h.on(e.updated,function(){f[i](b)}),b.on("change",d.courseSelector,function(){var e=a(this),g=e.val();f[i](b,g).then(function(){return b.find(d.courseSelector).val(g)}).fail(c.exception)}),h.on(e.filterChanged,function(a,c){var e=b.find(d.eventType[c.type]);1==c.hidden?e.addClass("hidden"):e.removeClass("hidden")})};return{init:function(b,c){b=a(b),f.init(b,c),l(b,c)}}});
+1
View File
@@ -0,0 +1 @@
define(["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){function n(d,e,f){var i=[{key:"deleteevent",component:"calendar"}];f=parseInt(f,10);var m,n=f>1;n?(i.push({key:"confirmeventseriesdelete",component:"calendar",param:{name:e,count:f}}),m=g.create({type:l.TYPE})):(i.push({key:"confirmeventdelete",component:"calendar",param:e}),m=g.create({type:g.types.SAVE_CANCEL})),m.then(function(a){a.show()}).fail(c.exception);var o=b.get_strings(i),p=a.when(o,m).then(function(b,e){return e.setTitle(b[0]),e.setBody(b[1]),n||e.setSaveButtonText(b[0]),e.getRoot().on(h.save,function(){j.deleteEvent(d,!1).then(function(){a("body").trigger(k.deleted,[d,!1])})["catch"](c.exception)}),e.getRoot().on(k.deleteAll,function(){j.deleteEvent(d,!0).then(function(){a("body").trigger(k.deleted,[d,!0])})["catch"](c.exception)}),e}).fail(c.exception);return p}function o(b){b.on("click",m.actions.remove,function(b){var c=a(this).closest(m.eventItem),d=c.data("eventId"),e=c.data("eventTitle"),f=c.data("eventCount");n(d,e,f),b.preventDefault()})}var p=function(b){var d=g.create({type:i.TYPE,large:!0});return b.on("click",m.actions.create,function(a){d.then(function(a){var c=b.find(m.wrapper),d=c.data("categoryid");"undefined"!=typeof d&&a.setCategoryId(d);var e=b.find(m.today),f=b.find(m.day);!e.length&&f.length&&a.setStartTime(f.data("newEventTimestamp")),a.setContextId(c.data("contextId")),a.setCourseId(c.data("courseid")),a.show()}).fail(c.exception),a.preventDefault()}),b.on("click",m.actions.edit,function(b){b.preventDefault();var e=a(b.currentTarget),f=e.closest(m.wrapper),g=e.closest(m.eventItem);d.then(function(a){a.setEventId(g.data("eventId")),a.setContextId(f.data("contextId")),a.show()}).fail(c.exception)}),d};return{registerRemove:o,registerEventFormModal:p}});
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/event","core/str","core/notification","core/templates","core/custom_interaction_events","core/modal","core/modal_registry","core/fragment","core_calendar/events","core_calendar/repository"],function(a,b,c,d,e,f,g,h,i,j,k){var l=!1,m={SAVE_BUTTON:'[data-action="save"]',LOADING_ICON_CONTAINER:'[data-region="loading-icon-container"]'},n=function(a){g.call(this,a),this.eventId=null,this.startTime=null,this.courseId=null,this.categoryId=null,this.reloadingBody=!1,this.reloadingTitle=!1,this.saveButton=this.getFooter().find(m.SAVE_BUTTON)};return n.TYPE="core_calendar-modal_event_form",n.prototype=Object.create(g.prototype),n.prototype.constructor=n,n.prototype.setCourseId=function(a){this.courseId=a},n.prototype.getCourseId=function(){return this.courseId},n.prototype.setCategoryId=function(a){this.categoryId=a},n.prototype.getCategoryId=function(){return this.categoryId},n.prototype.hasCourseId=function(){return null!==this.courseId},n.prototype.hasCategoryId=function(){return null!==this.categoryId},n.prototype.setEventId=function(a){this.eventId=a},n.prototype.getEventId=function(){return this.eventId},n.prototype.hasEventId=function(){return null!==this.eventId},n.prototype.setStartTime=function(a){this.startTime=a},n.prototype.getStartTime=function(){return this.startTime},n.prototype.hasStartTime=function(){return null!==this.startTime},n.prototype.getForm=function(){return this.getBody().find("form")},n.prototype.disableButtons=function(){this.saveButton.prop("disabled",!0)},n.prototype.enableButtons=function(){this.saveButton.prop("disabled",!1)},n.prototype.reloadTitleContent=function(){return this.reloadingTitle?this.titlePromise:(this.reloadingTitle=!0,this.hasEventId()?this.titlePromise=c.get_string("editevent","calendar"):this.titlePromise=c.get_string("newevent","calendar"),this.titlePromise.then(function(a){return this.setTitle(a),a}.bind(this)).always(function(){this.reloadingTitle=!1}.bind(this)).fail(d.exception),this.titlePromise)},n.prototype.reloadBodyContent=function(a){if(this.reloadingBody)return this.bodyPromise;this.reloadingBody=!0,this.disableButtons();var b=this.saveButton.attr("data-context-id"),c={};return this.hasEventId()&&(c.eventid=this.getEventId()),this.hasStartTime()&&(c.starttime=this.getStartTime()),this.hasCourseId()&&(c.courseid=this.getCourseId()),this.hasCategoryId()&&(c.categoryid=this.getCategoryId()),"undefined"!=typeof a&&(c.formdata=a),this.bodyPromise=i.loadFragment("calendar","event_form",b,c),this.setBody(this.bodyPromise),this.bodyPromise.then(function(){this.enableButtons()}.bind(this)).fail(d.exception).always(function(){this.reloadingBody=!1}.bind(this)).fail(d.exception),this.bodyPromise},n.prototype.reloadAllContent=function(){return a.when(this.reloadTitleContent(),this.reloadBodyContent())},n.prototype.show=function(){this.reloadAllContent(),g.prototype.show.call(this)},n.prototype.hide=function(){g.prototype.hide.call(this),this.setEventId(null),this.setStartTime(null),this.setCourseId(null),this.setCategoryId(null)},n.prototype.getFormData=function(){return this.getForm().serialize()},n.prototype.save=function(){var b=this.saveButton.find(m.LOADING_ICON_CONTAINER);b.removeClass("hidden"),this.disableButtons();var c=this.getFormData();return k.submitCreateUpdateForm(c).then(function(b){return b.validationerror?void this.reloadBodyContent(c):(this.hide(),void(this.hasEventId()?a("body").trigger(j.updated,[b.event]):a("body").trigger(j.created,[b.event])))}.bind(this)).always(function(){b.addClass("hidden"),this.enableButtons()}.bind(this)).fail(d.exception)},n.prototype.registerEventListeners=function(){g.prototype.registerEventListeners.call(this),this.getModal().on(f.events.activate,m.SAVE_BUTTON,function(a,b){this.getForm().submit(),b.originalEvent.preventDefault(),a.stopPropagation()}.bind(this)),this.getModal().on("submit",function(a){this.save(),a.preventDefault(),a.stopPropagation()}.bind(this))},l||(h.register(n.TYPE,n,"calendar/modal_event_form"),l=!0),n});
define(["jquery","core/event","core/str","core/notification","core/templates","core/custom_interaction_events","core/modal","core/modal_registry","core/fragment","core_calendar/events","core_calendar/repository"],function(a,b,c,d,e,f,g,h,i,j,k){var l=!1,m={SAVE_BUTTON:'[data-action="save"]',LOADING_ICON_CONTAINER:'[data-region="loading-icon-container"]'},n=function(a){g.call(this,a),this.eventId=null,this.startTime=null,this.courseId=null,this.categoryId=null,this.contextId=null,this.reloadingBody=!1,this.reloadingTitle=!1,this.saveButton=this.getFooter().find(m.SAVE_BUTTON)};return n.TYPE="core_calendar-modal_event_form",n.prototype=Object.create(g.prototype),n.prototype.constructor=n,n.prototype.setContextId=function(a){this.contextId=a},n.prototype.getContextId=function(){return this.contextId},n.prototype.setCourseId=function(a){this.courseId=a},n.prototype.getCourseId=function(){return this.courseId},n.prototype.setCategoryId=function(a){this.categoryId=a},n.prototype.getCategoryId=function(){return this.categoryId},n.prototype.hasCourseId=function(){return null!==this.courseId},n.prototype.hasCategoryId=function(){return null!==this.categoryId},n.prototype.setEventId=function(a){this.eventId=a},n.prototype.getEventId=function(){return this.eventId},n.prototype.hasEventId=function(){return null!==this.eventId},n.prototype.setStartTime=function(a){this.startTime=a},n.prototype.getStartTime=function(){return this.startTime},n.prototype.hasStartTime=function(){return null!==this.startTime},n.prototype.getForm=function(){return this.getBody().find("form")},n.prototype.disableButtons=function(){this.saveButton.prop("disabled",!0)},n.prototype.enableButtons=function(){this.saveButton.prop("disabled",!1)},n.prototype.reloadTitleContent=function(){return this.reloadingTitle?this.titlePromise:(this.reloadingTitle=!0,this.hasEventId()?this.titlePromise=c.get_string("editevent","calendar"):this.titlePromise=c.get_string("newevent","calendar"),this.titlePromise.then(function(a){return this.setTitle(a),a}.bind(this)).always(function(){this.reloadingTitle=!1}.bind(this)).fail(d.exception),this.titlePromise)},n.prototype.reloadBodyContent=function(a){if(this.reloadingBody)return this.bodyPromise;this.reloadingBody=!0,this.disableButtons();var b={};return this.hasEventId()&&(b.eventid=this.getEventId()),this.hasStartTime()&&(b.starttime=this.getStartTime()),this.hasCourseId()&&(b.courseid=this.getCourseId()),this.hasCategoryId()&&(b.categoryid=this.getCategoryId()),"undefined"!=typeof a&&(b.formdata=a),this.bodyPromise=i.loadFragment("calendar","event_form",this.getContextId(),b),this.setBody(this.bodyPromise),this.bodyPromise.then(function(){this.enableButtons()}.bind(this)).fail(d.exception).always(function(){this.reloadingBody=!1}.bind(this)).fail(d.exception),this.bodyPromise},n.prototype.reloadAllContent=function(){return a.when(this.reloadTitleContent(),this.reloadBodyContent())},n.prototype.show=function(){this.reloadAllContent(),g.prototype.show.call(this)},n.prototype.hide=function(){g.prototype.hide.call(this),this.setEventId(null),this.setStartTime(null),this.setCourseId(null),this.setCategoryId(null)},n.prototype.getFormData=function(){return this.getForm().serialize()},n.prototype.save=function(){var b=this.saveButton.find(m.LOADING_ICON_CONTAINER);b.removeClass("hidden"),this.disableButtons();var c=this.getFormData();return k.submitCreateUpdateForm(c).then(function(b){return b.validationerror?void this.reloadBodyContent(c):(this.hide(),void(this.hasEventId()?a("body").trigger(j.updated,[b.event]):a("body").trigger(j.created,[b.event])))}.bind(this)).always(function(){b.addClass("hidden"),this.enableButtons()}.bind(this)).fail(d.exception)},n.prototype.registerEventListeners=function(){g.prototype.registerEventListeners.call(this),this.getModal().on(f.events.activate,m.SAVE_BUTTON,function(a,b){this.getForm().submit(),b.originalEvent.preventDefault(),a.stopPropagation()}.bind(this)),this.getModal().on("submit",function(a){this.save(),a.preventDefault(),a.stopPropagation()}.bind(this))},l||(h.register(n.TYPE,n,"calendar/modal_event_form"),l=!0),n});
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/ajax"],function(a,b){var c=function(a,c){"undefined"==typeof c&&(c=!1);var d={methodname:"core_calendar_delete_calendar_events",args:{events:[{eventid:a,repeat:c}]}};return b.call([d])[0]},d=function(a){var c={methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:a}};return b.call([c])[0]},e=function(a){var c={methodname:"core_calendar_submit_create_update_form",args:{formdata:a}};return b.call([c])[0]},f=function(a,c,d,e,f){var g={methodname:"core_calendar_get_calendar_monthly_view",args:{year:a,month:c,courseid:d,categoryid:e,includenavigation:f}};return b.call([g])[0]},g=function(a,c){var d={methodname:"core_calendar_update_event_start_day",args:{eventid:a,daytimestamp:c}};return b.call([d])[0]};return{getEventById:d,deleteEvent:c,updateEventStartDay:g,submitCreateUpdateForm:e,getCalendarMonthData:f}});
define(["jquery","core/ajax"],function(a,b){var c=function(a,c){"undefined"==typeof c&&(c=!1);var d={methodname:"core_calendar_delete_calendar_events",args:{events:[{eventid:a,repeat:c}]}};return b.call([d])[0]},d=function(a){var c={methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:a}};return b.call([c])[0]},e=function(a){var c={methodname:"core_calendar_submit_create_update_form",args:{formdata:a}};return b.call([c])[0]},f=function(a,c,d,e,f){var g={methodname:"core_calendar_get_calendar_monthly_view",args:{year:a,month:c,courseid:d,categoryid:e,includenavigation:f}};return b.call([g])[0]},g=function(a,c){var d={methodname:"core_calendar_update_event_start_day",args:{eventid:a,daytimestamp:c}};return b.call([d])[0]},h=function(a){var c={methodname:"core_calendar_get_calendar_upcoming_view",args:{courseid:a}};return b.call([c])[0]};return{getEventById:d,deleteEvent:c,updateEventStartDay:g,submitCreateUpdateForm:e,getCalendarMonthData:f,getCalendarUpcomingData:h}});
+1 -1
View File
@@ -1 +1 @@
define([],function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]"},calendarPeriods:{month:"[data-period='month']"}}});
define([],function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",category:"[data-eventtype-category]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]"},popoverType:{site:"[data-popover-eventtype-site]",category:"[data-popover-eventtype-category]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:'select[name="course"]',actions:{create:'[data-action="new-event-button"]',edit:'[data-action="edit"]',remove:'[data-action="delete"]'},today:".today",day:'[data-region="day"]',wrapper:".calendarwrapper",eventItem:'[data-type="event"]'}});
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/repository","core_calendar/events","core_calendar/modal_delete"],function(a,b,c,d,e,f,g,h,i,j,k){function l(d,e){var f,l=[{key:"deleteevent",component:"calendar"}],m=parseInt(d.getEventCount(),10),n=m>1;n?(l.push({key:"confirmeventseriesdelete",component:"calendar",param:{name:e,count:m}}),f=g.create({type:k.TYPE},d.getDeleteButton())):(l.push({key:"confirmeventdelete",component:"calendar",param:e}),f=g.create({type:g.types.SAVE_CANCEL},d.getDeleteButton()));var o=d.getEventId(),p=b.get_strings(l);a.when(p,f).then(function(b,e){return e.setTitle(b[0]),e.setBody(b[1]),n||e.setSaveButtonText(b[0]),e.getRoot().on(h.save,function(){i.deleteEvent(o,!1).then(function(){a("body").trigger(j.deleted,[o,!1]),d.hide()})["catch"](c.exception)}),e.getRoot().on(j.deleteAll,function(){i.deleteEvent(o,!0).then(function(){a("body").trigger(j.deleted,[o,!0]),d.hide()})["catch"](c.exception)}),e}).fail(c.exception)}var m=!1,n={ROOT:"[data-region='summary-modal-container']",EDIT_BUTTON:'[data-action="edit"]',DELETE_BUTTON:'[data-action="delete"]'},o=function(a){e.call(this,a)};return o.TYPE="core_calendar-event_summary",o.prototype=Object.create(e.prototype),o.prototype.constructor=o,o.prototype.getEditButton=function(){return"undefined"==typeof this.editButton&&(this.editButton=this.getFooter().find(n.EDIT_BUTTON)),this.editButton},o.prototype.getDeleteButton=function(){return"undefined"==typeof this.deleteButton&&(this.deleteButton=this.getFooter().find(n.DELETE_BUTTON)),this.deleteButton},o.prototype.getEventId=function(){return this.getBody().find(n.ROOT).attr("data-event-id")},o.prototype.getEventCount=function(){return this.getBody().find(n.ROOT).attr("data-event-event-count")},o.prototype.getEditUrl=function(){return this.getBody().find(n.ROOT).attr("data-edit-url")},o.prototype.isActionEvent=function(){return"true"==this.getBody().find(n.ROOT).attr("data-action-event")},o.prototype.registerEventListeners=function(){e.prototype.registerEventListeners.call(this),this.getRoot().on(h.bodyRendered,function(){var a=this.getBody().find(n.ROOT).attr("data-event-title");l(this,a)}.bind(this)),d.define(this.getEditButton(),[d.events.activate]),this.getEditButton().on(d.events.activate,function(b,c){this.isActionEvent()?a("body").trigger(j.editActionEvent,[this.getEditUrl()]):a("body").trigger(j.editEvent,[this.getEventId()]),this.hide(),b.preventDefault(),b.stopPropagation(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()}.bind(this))},m||(f.register(o.TYPE,o,"core_calendar/event_summary_modal"),m=!0),o});
define(["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/repository","core_calendar/events","core_calendar/crud"],function(a,b,c,d,e,f,g,h,i,j,k){var l=!1,m={ROOT:"[data-region='summary-modal-container']",EDIT_BUTTON:'[data-action="edit"]',DELETE_BUTTON:'[data-action="delete"]'},n=function(a){e.call(this,a)};return n.TYPE="core_calendar-event_summary",n.prototype=Object.create(e.prototype),n.prototype.constructor=n,n.prototype.getEditButton=function(){return"undefined"==typeof this.editButton&&(this.editButton=this.getFooter().find(m.EDIT_BUTTON)),this.editButton},n.prototype.getDeleteButton=function(){return"undefined"==typeof this.deleteButton&&(this.deleteButton=this.getFooter().find(m.DELETE_BUTTON)),this.deleteButton},n.prototype.getEventId=function(){return this.getBody().find(m.ROOT).attr("data-event-id")},n.prototype.getEventTitle=function(){return this.getBody().find(m.ROOT).attr("data-event-title")},n.prototype.getEventCount=function(){return this.getBody().find(m.ROOT).attr("data-event-count")},n.prototype.getEditUrl=function(){return this.getBody().find(m.ROOT).attr("data-edit-url")},n.prototype.isActionEvent=function(){return"true"==this.getBody().find(m.ROOT).attr("data-action-event")},n.prototype.registerEventListeners=function(){e.prototype.registerEventListeners.call(this),this.getRoot().on(h.bodyRendered,function(){this.getModal().data({eventTitle:this.getEventTitle(),eventId:this.getEventId(),eventCount:this.getEventCount()}).attr("data-type","event"),k.registerRemove(this.getModal())}.bind(this)),a("body").on(j.deleted,function(){this.hide()}.bind(this)),d.define(this.getEditButton(),[d.events.activate]),this.getEditButton().on(d.events.activate,function(b,c){this.isActionEvent()?a("body").trigger(j.editActionEvent,[this.getEditUrl()]):a("body").trigger(j.editEvent,[this.getEventId()]),this.hide(),b.preventDefault(),b.stopPropagation(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()}.bind(this))},l||(f.register(n.TYPE,n,"core_calendar/event_summary_modal"),l=!0),n});
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/templates","core/notification","core_calendar/repository","core_calendar/events"],function(a,b,c,d,e){var f={ROOT:"[data-region='calendar']",CALENDAR_NAV_LINK:".calendarwrapper .arrow_link",CALENDAR_MONTH_WRAPPER:".calendarwrapper",LOADING_ICON_CONTAINER:'[data-region="overlay-icon-container"]'},g=function(b){b=a(b),b.on("click",f.CALENDAR_NAV_LINK,function(c){var d=b.find(f.CALENDAR_MONTH_WRAPPER),e=d.data("courseid"),g=d.data("categoryid"),h=a(c.currentTarget);i(b,h.attr("href"),h.data("year"),h.data("month"),e,g),c.preventDefault()})},h=function(g,h,i,j,m,n){k(g),n=n||g.find(f.CALENDAR_MONTH_WRAPPER),M.util.js_pending([g.get("id"),h,i,j].join("-"));var o=g.data("includenavigation");return d.getCalendarMonthData(h,i,j,m,o).then(function(a){return b.render(g.attr("data-template"),a)}).then(function(a,c){return b.replaceNode(n,a,c)}).then(function(){a("body").trigger(e.viewUpdated)}).always(function(){return M.util.js_complete([g.get("id"),h,i,j].join("-")),l(g)}).fail(c.exception)},i=function(b,c,d,f,g,i){return h(b,d,f,g,i).then(function(){return c.length&&"#"!==c&&window.history.pushState({},"",c),arguments}).then(function(){return a("body").trigger(e.monthChanged,[d,f,g,i]),arguments})},j=function(a,b,c){var d=a.find(f.CALENDAR_MONTH_WRAPPER).data("year"),e=a.find(f.CALENDAR_MONTH_WRAPPER).data("month");return"undefined"==typeof b&&(b=a.find(f.CALENDAR_MONTH_WRAPPER).data("courseid")),"undefined"==typeof c&&(c=a.find(f.CALENDAR_MONTH_WRAPPER).data("categoryid")),h(a,d,e,b,c)},k=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.removeClass("hidden")},l=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.addClass("hidden")};return{init:function(a){g(a)},reloadCurrentMonth:j,changeMonth:i,refreshMonthContent:h}});
define(["jquery","core/templates","core/notification","core_calendar/repository","core_calendar/events"],function(a,b,c,d,e){var f={ROOT:"[data-region='calendar']",CALENDAR_NAV_LINK:".calendarwrapper .arrow_link",CALENDAR_MONTH_WRAPPER:".calendarwrapper",LOADING_ICON_CONTAINER:'[data-region="overlay-icon-container"]'},g=function(b){b=a(b),b.on("click",f.CALENDAR_NAV_LINK,function(c){var d=b.find(f.CALENDAR_MONTH_WRAPPER),e=d.data("courseid"),g=d.data("categoryid"),h=a(c.currentTarget);i(b,h.attr("href"),h.data("year"),h.data("month"),e,g),c.preventDefault()})},h=function(g,h,i,j,m,n){k(g),n=n||g.find(f.CALENDAR_MONTH_WRAPPER),M.util.js_pending([g.get("id"),h,i,j].join("-"));var o=g.data("includenavigation");return d.getCalendarMonthData(h,i,j,m,o).then(function(a){return b.render(g.attr("data-template"),a)}).then(function(a,c){return b.replaceNode(n,a,c)}).then(function(){a("body").trigger(e.viewUpdated)}).always(function(){return M.util.js_complete([g.get("id"),h,i,j].join("-")),l(g)}).fail(c.exception)},i=function(b,c,d,f,g,i){return h(b,d,f,g,i).then(function(){return c.length&&"#"!==c&&window.history.pushState({},"",c),arguments}).then(function(){return a("body").trigger(e.monthChanged,[d,f,g,i]),arguments})},j=function(a,b,c){var d=a.find(f.CALENDAR_MONTH_WRAPPER).data("year"),e=a.find(f.CALENDAR_MONTH_WRAPPER).data("month");return"undefined"==typeof b&&(b=a.find(f.CALENDAR_MONTH_WRAPPER).data("courseid")),"undefined"==typeof c&&(c=a.find(f.CALENDAR_MONTH_WRAPPER).data("categoryid")),h(a,d,e,b,c)},k=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.removeClass("hidden")},l=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.addClass("hidden")},m=function(g,h){k(g);var i=g.find(f.CALENDAR_MONTH_WRAPPER);return h||(h=g.find(f.CALENDAR_MONTH_WRAPPER).data("courseid")),d.getCalendarUpcomingData(h).then(function(a){return b.render(g.attr("data-template"),a)}).then(function(a,c){return window.history.replaceState(null,null,"?view=upcoming&course="+h),b.replaceNode(i,a,c)}).then(function(){a("body").trigger(e.viewUpdated)}).always(function(){return l(g)}).fail(c.exception)};return{init:function(a){g(a)},reloadCurrentMonth:j,changeMonth:i,refreshMonthContent:h,reloadCurrentUpcoming:m}});
+12 -55
View File
@@ -38,7 +38,9 @@ define([
'core_calendar/summary_modal',
'core_calendar/repository',
'core_calendar/events',
'core_calendar/view_manager'
'core_calendar/view_manager',
'core_calendar/crud',
'core_calendar/selectors',
],
function(
$,
@@ -53,7 +55,9 @@ define([
SummaryModal,
CalendarRepository,
CalendarEvents,
CalendarViewManager
CalendarViewManager,
CalendarCrud,
CalendarSelectors
) {
var SELECTORS = {
@@ -192,29 +196,6 @@ define([
}
};
/**
* Create the event form modal for creating new events and
* editing existing events.
*
* @method registerEventFormModal
* @param {object} root The calendar root element
* @return {object} The create modal promise
*/
var registerEventFormModal = function(root) {
var newEventButton = root.find(SELECTORS.NEW_EVENT_BUTTON);
var contextId = newEventButton.attr('data-context-id');
return ModalFactory.create(
{
type: ModalEventForm.TYPE,
large: true,
templateContext: {
contextid: contextId
}
}
);
};
/**
* Listen to and handle any calendar events fired by the calendar UI.
*
@@ -250,7 +231,9 @@ define([
// When something within the calendar tells us the user wants
// to edit an event then show the event form modal.
body.on(CalendarEvents.editEvent, function(e, eventId) {
var calendarWrapper = root.find(CalendarSelectors.wrapper);
modal.setEventId(eventId);
modal.setContextId(calendarWrapper.data('contextId'));
modal.show();
});
return;
@@ -294,44 +277,18 @@ define([
.fail(Notification.exception);
});
var eventFormPromise = registerEventFormModal(root);
var eventFormPromise = CalendarCrud.registerEventFormModal(root);
registerCalendarEventListeners(root, eventFormPromise);
// Bind click event on the new event button.
CustomEvents.define(root, [CustomEvents.events.activate]);
root.on('click', SELECTORS.NEW_EVENT_BUTTON, function(e) {
eventFormPromise.then(function(modal) {
var wrapper = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER);
modal.setCourseId(wrapper.data('courseid'));
var categoryId = wrapper.data('categoryid');
if (typeof categoryId !== 'undefined') {
modal.setCategoryId(categoryId);
}
// Attempt to find the cell for today.
// If it can't be found, then use the start time of the first day on the calendar.
var today = root.find(SELECTORS.TODAY);
if (!today.length) {
modal.setStartTime(root.find(SELECTORS.DAY).attr('data-new-event-timestamp'));
}
modal.show();
return;
})
.fail(Notification.exception);
e.preventDefault();
});
// Bind click events to calendar days.
root.on('click', SELECTORS.DAY, function(e) {
var target = $(e.target);
if (!target.is(SELECTORS.VIEW_DAY_LINK)) {
var startTime = $(this).attr('data-new-event-timestamp');
eventFormPromise.then(function(modal) {
var wrapper = target.closest(SELECTORS.CALENDAR_MONTH_WRAPPER);
var wrapper = target.closest(CalendarSelectors.wrapper);
modal.setCourseId(wrapper.data('courseid'));
var categoryId = wrapper.data('categoryid');
@@ -339,6 +296,7 @@ define([
modal.setCategoryId(categoryId);
}
modal.setContextId(wrapper.data('contextId'));
modal.setStartTime(startTime);
modal.show();
return;
@@ -353,7 +311,6 @@ define([
return {
init: function(root) {
root = $(root);
CalendarViewManager.init(root);
registerEventListeners(root);
}
+98
View File
@@ -0,0 +1,98 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This module is responsible for handle calendar day and upcoming view.
*
* @module core_calendar/calendar
* @package core_calendar
* @copyright 2017 Simey Lameze <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define([
'jquery',
'core/str',
'core/notification',
'core_calendar/selectors',
'core_calendar/events',
'core_calendar/view_manager',
'core_calendar/repository',
'core/modal_factory',
'core_calendar/modal_event_form',
'core/modal_events',
'core_calendar/crud'
],
function(
$,
Str,
Notification,
CalendarSelectors,
CalendarEvents,
CalendarViewManager,
CalendarRepository,
ModalFactory,
ModalEventForm,
ModalEvents,
CalendarCrud
) {
var registerEventListeners = function(root, type) {
var body = $('body');
CalendarCrud.registerEventFormModal(root);
CalendarCrud.registerRemove(root);
var reloadFunction = 'reloadCurrent' + type.charAt(0).toUpperCase() + type.slice(1);
body.on(CalendarEvents.created, function() {
CalendarViewManager[reloadFunction](root);
});
body.on(CalendarEvents.deleted, function() {
CalendarViewManager[reloadFunction](root);
});
body.on(CalendarEvents.updated, function() {
CalendarViewManager[reloadFunction](root);
});
root.on('change', CalendarSelectors.courseSelector, function() {
var selectElement = $(this);
var courseId = selectElement.val();
CalendarViewManager[reloadFunction](root, courseId)
.then(function() {
// We need to get the selector again because the content has changed.
return root.find(CalendarSelectors.courseSelector).val(courseId);
})
.fail(Notification.exception);
});
body.on(CalendarEvents.filterChanged, function(e, data) {
var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);
if (data.hidden == true) {
daysWithEvent.addClass('hidden');
} else {
daysWithEvent.removeClass('hidden');
}
});
};
return {
init: function(root, type) {
root = $(root);
CalendarViewManager.init(root, type);
registerEventListeners(root, type);
}
};
});
+230
View File
@@ -0,0 +1,230 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A module to handle CRUD operations within the UI.
*
* @module core_calendar/crud
* @package core_calendar
* @copyright 2017 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define([
'jquery',
'core/str',
'core/notification',
'core/custom_interaction_events',
'core/modal',
'core/modal_registry',
'core/modal_factory',
'core/modal_events',
'core_calendar/modal_event_form',
'core_calendar/repository',
'core_calendar/events',
'core_calendar/modal_delete',
'core_calendar/selectors',
],
function(
$,
Str,
Notification,
CustomEvents,
Modal,
ModalRegistry,
ModalFactory,
ModalEvents,
ModalEventForm,
CalendarRepository,
CalendarEvents,
ModalDelete,
CalendarSelectors
) {
/**
* Prepares the action for the summary modal's delete action.
*
* @param {Number} eventId The ID of the event.
* @param {string} eventTitle The event title.
* @param {Number} eventCount The number of events in the series.
* @return {Promise}
*/
function confirmDeletion(eventId, eventTitle, eventCount) {
var deleteStrings = [
{
key: 'deleteevent',
component: 'calendar'
},
];
eventCount = parseInt(eventCount, 10);
var deletePromise;
var isRepeatedEvent = eventCount > 1;
if (isRepeatedEvent) {
deleteStrings.push({
key: 'confirmeventseriesdelete',
component: 'calendar',
param: {
name: eventTitle,
count: eventCount,
},
});
deletePromise = ModalFactory.create(
{
type: ModalDelete.TYPE
}
);
} else {
deleteStrings.push({
key: 'confirmeventdelete',
component: 'calendar',
param: eventTitle
});
deletePromise = ModalFactory.create(
{
type: ModalFactory.types.SAVE_CANCEL
}
);
}
deletePromise.then(function(deleteModal) {
deleteModal.show();
return;
})
.fail(Notification.exception);
var stringsPromise = Str.get_strings(deleteStrings);
var finalPromise = $.when(stringsPromise, deletePromise)
.then(function(strings, deleteModal) {
deleteModal.setTitle(strings[0]);
deleteModal.setBody(strings[1]);
if (!isRepeatedEvent) {
deleteModal.setSaveButtonText(strings[0]);
}
deleteModal.getRoot().on(ModalEvents.save, function() {
CalendarRepository.deleteEvent(eventId, false)
.then(function() {
$('body').trigger(CalendarEvents.deleted, [eventId, false]);
return;
})
.catch(Notification.exception);
});
deleteModal.getRoot().on(CalendarEvents.deleteAll, function() {
CalendarRepository.deleteEvent(eventId, true)
.then(function() {
$('body').trigger(CalendarEvents.deleted, [eventId, true]);
return;
})
.catch(Notification.exception);
});
return deleteModal;
})
.fail(Notification.exception);
return finalPromise;
}
/**
* Create the event form modal for creating new events and
* editing existing events.
*
* @method registerEventFormModal
* @param {object} root The calendar root element
* @return {object} The create modal promise
*/
var registerEventFormModal = function(root) {
var eventFormPromise = ModalFactory.create({
type: ModalEventForm.TYPE,
large: true
});
// Bind click event on the new event button.
root.on('click', CalendarSelectors.actions.create, function(e) {
eventFormPromise.then(function(modal) {
var wrapper = root.find(CalendarSelectors.wrapper);
var categoryId = wrapper.data('categoryid');
if (typeof categoryId !== 'undefined') {
modal.setCategoryId(categoryId);
}
// Attempt to find the cell for today.
// If it can't be found, then use the start time of the first day on the calendar.
var today = root.find(CalendarSelectors.today);
var firstDay = root.find(CalendarSelectors.day);
if (!today.length && firstDay.length) {
modal.setStartTime(firstDay.data('newEventTimestamp'));
}
modal.setContextId(wrapper.data('contextId'));
modal.setCourseId(wrapper.data('courseid'));
modal.show();
return;
})
.fail(Notification.exception);
e.preventDefault();
});
root.on('click', CalendarSelectors.actions.edit, function(e) {
e.preventDefault();
var target = $(e.currentTarget),
calendarWrapper = target.closest(CalendarSelectors.wrapper),
eventWrapper = target.closest(CalendarSelectors.eventItem);
eventFormPromise.then(function(modal) {
// When something within the calendar tells us the user wants
// to edit an event then show the event form modal.
modal.setEventId(eventWrapper.data('eventId'));
modal.setContextId(calendarWrapper.data('contextId'));
modal.show();
return;
}).fail(Notification.exception);
});
return eventFormPromise;
};
/**
* Register the listeners required to remove the event.
*
* @param {jQuery} root
*/
function registerRemove(root) {
root.on('click', CalendarSelectors.actions.remove, function(e) {
// Fetch the event title, count, and pass them into the new dialogue.
var eventSource = $(this).closest(CalendarSelectors.eventItem);
var eventId = eventSource.data('eventId'),
eventTitle = eventSource.data('eventTitle'),
eventCount = eventSource.data('eventCount');
confirmDeletion(eventId, eventTitle, eventCount);
e.preventDefault();
});
}
return {
registerRemove: registerRemove,
registerEventFormModal: registerEventFormModal
};
});
+22 -2
View File
@@ -66,6 +66,7 @@ define([
this.startTime = null;
this.courseId = null;
this.categoryId = null;
this.contextId = null;
this.reloadingBody = false;
this.reloadingTitle = false;
this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);
@@ -75,6 +76,26 @@ define([
ModalEventForm.prototype = Object.create(Modal.prototype);
ModalEventForm.prototype.constructor = ModalEventForm;
/**
* Set the context id to the given value.
*
* @method setContextId
* @param {Number} id The event id
*/
ModalEventForm.prototype.setContextId = function(id) {
this.contextId = id;
};
/**
* Retrieve the current context id, if any.
*
* @method getContextId
* @return {Number|null} The event id
*/
ModalEventForm.prototype.getContextId = function() {
return this.contextId;
};
/**
* Set the course id to the given value.
*
@@ -278,7 +299,6 @@ define([
this.reloadingBody = true;
this.disableButtons();
var contextId = this.saveButton.attr('data-context-id');
var args = {};
if (this.hasEventId()) {
@@ -301,7 +321,7 @@ define([
args.formdata = formData;
}
this.bodyPromise = Fragment.loadFragment('calendar', 'event_form', contextId, args);
this.bodyPromise = Fragment.loadFragment('calendar', 'event_form', this.getContextId(), args);
this.setBody(this.bodyPromise);
+20 -1
View File
@@ -133,11 +133,30 @@ define(['jquery', 'core/ajax'], function($, Ajax) {
return Ajax.call([request])[0];
};
/**
* Get calendar upcoming data.
*
* @method getCalendarUpcomingData
* @param {Number} courseid The course id.
* @return {promise} Resolved with the month view data.
*/
var getCalendarUpcomingData = function(courseid) {
var request = {
methodname: 'core_calendar_get_calendar_upcoming_view',
args: {
courseid: courseid,
}
};
return Ajax.call([request])[0];
};
return {
getEventById: getEventById,
deleteEvent: deleteEvent,
updateEventStartDay: updateEventStartDay,
submitCreateUpdateForm: submitCreateUpdateForm,
getCalendarMonthData: getCalendarMonthData
getCalendarMonthData: getCalendarMonthData,
getCalendarUpcomingData: getCalendarUpcomingData
};
});
+10
View File
@@ -41,5 +41,15 @@ define([], function() {
calendarPeriods: {
month: "[data-period='month']",
},
courseSelector: 'select[name="course"]',
actions: {
create: '[data-action="new-event-button"]',
edit: '[data-action="edit"]',
remove: '[data-action="delete"]',
},
today: '.today',
day: '[data-region="day"]',
wrapper: '.calendarwrapper',
eventItem: '[data-type="event"]',
};
});
+28 -90
View File
@@ -32,7 +32,7 @@ define([
'core/modal_events',
'core_calendar/repository',
'core_calendar/events',
'core_calendar/modal_delete',
'core_calendar/crud',
],
function(
$,
@@ -45,7 +45,7 @@ function(
ModalEvents,
CalendarRepository,
CalendarEvents,
ModalDelete
CalendarCrud
) {
var registered = false;
@@ -110,6 +110,18 @@ function(
return this.getBody().find(SELECTORS.ROOT).attr('data-event-id');
};
/**
* Get the title for the event being shown in this modal. This value is
* not cached because it will change depending on which event is
* being displayed.
*
* @method getEventTitle
* @return {String}
*/
ModalEventSummary.prototype.getEventTitle = function() {
return this.getBody().find(SELECTORS.ROOT).attr('data-event-title');
};
/**
* Get the number of events in the series for the event being shown in
* this modal. This value is not cached because it will change
@@ -119,7 +131,7 @@ function(
* @return {int}
*/
ModalEventSummary.prototype.getEventCount = function() {
return this.getBody().find(SELECTORS.ROOT).attr('data-event-event-count');
return this.getBody().find(SELECTORS.ROOT).attr('data-event-count');
};
/**
@@ -154,8 +166,19 @@ function(
// We have to wait for the modal to finish rendering in order to ensure that
// the data-event-title property is available to use as the modal title.
this.getRoot().on(ModalEvents.bodyRendered, function() {
var eventTitle = this.getBody().find(SELECTORS.ROOT).attr('data-event-title');
prepareDeleteAction(this, eventTitle);
this.getModal().data({
eventTitle: this.getEventTitle(),
eventId: this.getEventId(),
eventCount: this.getEventCount(),
})
.attr('data-type', 'event');
CalendarCrud.registerRemove(this.getModal());
}.bind(this));
$('body').on(CalendarEvents.deleted, function() {
// Close the dialogue on delete.
this.hide();
}.bind(this));
CustomEvents.define(this.getEditButton(), [
@@ -163,7 +186,6 @@ function(
]);
this.getEditButton().on(CustomEvents.events.activate, function(e, data) {
if (this.isActionEvent()) {
// Action events cannot be edited on the event form and must be redirected to the module UI.
$('body').trigger(CalendarEvents.editActionEvent, [this.getEditUrl()]);
@@ -184,90 +206,6 @@ function(
}.bind(this));
};
/**
* Prepares the action for the summary modal's delete action.
*
* @param {ModalEventSummary} summaryModal The summary modal instance.
* @param {string} eventTitle The event title.
*/
function prepareDeleteAction(summaryModal, eventTitle) {
var deleteStrings = [
{
key: 'deleteevent',
component: 'calendar'
},
];
var eventCount = parseInt(summaryModal.getEventCount(), 10);
var deletePromise;
var isRepeatedEvent = eventCount > 1;
if (isRepeatedEvent) {
deleteStrings.push({
key: 'confirmeventseriesdelete',
component: 'calendar',
param: {
name: eventTitle,
count: eventCount,
},
});
deletePromise = ModalFactory.create(
{
type: ModalDelete.TYPE
},
summaryModal.getDeleteButton()
);
} else {
deleteStrings.push({
key: 'confirmeventdelete',
component: 'calendar',
param: eventTitle
});
deletePromise = ModalFactory.create(
{
type: ModalFactory.types.SAVE_CANCEL
},
summaryModal.getDeleteButton()
);
}
var eventId = summaryModal.getEventId();
var stringsPromise = Str.get_strings(deleteStrings);
$.when(stringsPromise, deletePromise)
.then(function(strings, deleteModal) {
deleteModal.setTitle(strings[0]);
deleteModal.setBody(strings[1]);
if (!isRepeatedEvent) {
deleteModal.setSaveButtonText(strings[0]);
}
deleteModal.getRoot().on(ModalEvents.save, function() {
CalendarRepository.deleteEvent(eventId, false)
.then(function() {
$('body').trigger(CalendarEvents.deleted, [eventId, false]);
summaryModal.hide();
return;
})
.catch(Notification.exception);
});
deleteModal.getRoot().on(CalendarEvents.deleteAll, function() {
CalendarRepository.deleteEvent(eventId, true)
.then(function() {
$('body').trigger(CalendarEvents.deleted, [eventId, true]);
summaryModal.hide();
return;
})
.catch(Notification.exception);
});
return deleteModal;
})
.fail(Notification.exception);
}
// Automatically register with the modal registry the first time this module is imported so that you can create modals
// of this type using the modal factory.
if (!registered) {
+36 -1
View File
@@ -159,12 +159,47 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
loadingIconContainer.addClass('hidden');
};
/**
* Reload the current month view data.
*
* @param {object} root The container element.
* @param {Number} courseId The course id.
* @return {promise}
*/
var reloadCurrentUpcoming = function(root, courseId) {
startLoading(root);
var target = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER);
if (!courseId) {
courseId = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('courseid');
}
return CalendarRepository.getCalendarUpcomingData(courseId)
.then(function(context) {
return Templates.render(root.attr('data-template'), context);
})
.then(function(html, js) {
window.history.replaceState(null, null, '?view=upcoming&course=' + courseId);
return Templates.replaceNode(target, html, js);
})
.then(function() {
$('body').trigger(CalendarEvents.viewUpdated);
return;
})
.always(function() {
return stopLoading(root);
})
.fail(Notification.exception);
};
return {
init: function(root) {
registerEventListeners(root);
},
reloadCurrentMonth: reloadCurrentMonth,
changeMonth: changeMonth,
refreshMonthContent: refreshMonthContent
refreshMonthContent: refreshMonthContent,
reloadCurrentUpcoming: reloadCurrentUpcoming
};
});
+169
View File
@@ -0,0 +1,169 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains event class for displaying the upcoming view.
*
* @package core_calendar
* @copyright 2017 Simey Lameze <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_calendar\external;
defined('MOODLE_INTERNAL') || die();
use core\external\exporter;
use renderer_base;
use moodle_url;
use \core_calendar\local\event\container;
/**
* Class for displaying the day view.
*
* @package core_calendar
* @copyright 2017 Simey Lameze <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class calendar_upcoming_exporter extends exporter {
/**
* @var \calendar_information $calendar The calendar to be rendered.
*/
protected $calendar;
/**
* @var moodle_url $url The URL for the upcoming view page.
*/
protected $url;
/**
* Constructor for upcoming exporter.
*
* @param \calendar_information $calendar The calendar being represented.
* @param array $related The related information
*/
public function __construct(\calendar_information $calendar, $related) {
$this->calendar = $calendar;
parent::__construct([], $related);
}
/**
* Return the list of additional properties.
*
* @return array
*/
protected static function define_other_properties() {
return [
'events' => [
'type' => calendar_event_exporter::read_properties_definition(),
'multiple' => true,
],
'defaulteventcontext' => [
'type' => PARAM_INT,
'default' => null,
],
'filter_selector' => [
'type' => PARAM_RAW,
],
'courseid' => [
'type' => PARAM_INT,
],
];
}
/**
* Get the additional values to inject while exporting.
*
* @param renderer_base $output The renderer.
* @return array Keys are the property names, values are their values.
*/
protected function get_other_values(renderer_base $output) {
$timestamp = $this->calendar->time;
$cache = $this->related['cache'];
$url = new moodle_url('/calendar/view.php', [
'view' => 'upcoming',
'time' => $timestamp,
'course' => $this->calendar->course->id,
]);
$this->url = $url;
$return['events'] = array_map(function($event) use ($cache, $output, $url) {
$context = $cache->get_context($event);
$course = $cache->get_course($event);
$exporter = new calendar_event_exporter($event, [
'context' => $context,
'course' => $course,
'daylink' => $url,
'type' => $this->related['type'],
'today' => $this->calendar->time,
]);
$data = $exporter->export($output);
// We need to override default formatted time because it differs from day view.
// Formatted time for upcoming view adds a link to the day view.
$legacyevent = container::get_event_mapper()->from_event_to_legacy_event($event);
$data->formattedtime = calendar_format_event_time($legacyevent, time(), null);
return $data;
}, $this->related['events']);
if ($context = $this->get_default_add_context()) {
$return['defaulteventcontext'] = $context->id;
}
$return['filter_selector'] = $this->get_course_filter_selector($output);
$return['courseid'] = $this->calendar->courseid;
return $return;
}
/**
* Get the default context for use when adding a new event.
*
* @return null|\context
*/
protected function get_default_add_context() {
if (calendar_user_can_add_event($this->calendar->course)) {
return \context_course::instance($this->calendar->course->id);
}
return null;
}
/**
* Get the course filter selector.
*
* @param renderer_base $output
* @return string The html code for the course filter selector.
*/
protected function get_course_filter_selector(renderer_base $output) {
$langstr = get_string('upcomingeventsfor', 'calendar');
return $output->course_filter_selector($this->url, $langstr);
}
/**
* Returns a list of objects that are related.
*
* @return array
*/
protected static function define_related() {
return [
'events' => '\core_calendar\local\event\entities\event_interface[]',
'cache' => '\core_calendar\external\events_related_objects_cache',
'type' => '\core_calendar\type_base',
];
}
}
+57
View File
@@ -1051,4 +1051,61 @@ class core_calendar_external extends external_api {
)
);
}
/**
* Get data for the monthly calendar view.
*
* @param int $courseid The course to be included
* @return array
*/
public static function get_calendar_upcoming_view($courseid) {
global $CFG, $DB, $USER, $PAGE;
require_once($CFG->dirroot."/calendar/lib.php");
// Parameter validation.
self::validate_parameters(self::get_calendar_upcoming_view_parameters(), [
'courseid' => $courseid,
]);
if ($courseid != SITEID && !empty($courseid)) {
// Course ID must be valid and existing.
$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
$courses = [$course->id => $course];
} else {
$course = get_site();
$courses = calendar_get_default_courses();
}
$context = \context_user::instance($USER->id);
self::validate_context($context);
$calendar = new calendar_information(0, 0, 0, time());
$calendar->set_sources($course, $courses);
list($data, $template) = calendar_get_view($calendar, 'upcoming');
return $data;
}
/**
* Returns description of method parameters.
*
* @return external_function_parameters
*/
public static function get_calendar_upcoming_view_parameters() {
return new external_function_parameters(
[
'courseid' => new external_value(PARAM_INT, 'Course being viewed', VALUE_DEFAULT, SITEID, NULL_ALLOWED),
]
);
}
/**
* Returns description of method result value.
*
* @return external_description
*/
public static function get_calendar_upcoming_view_returns() {
return \core_calendar\external\calendar_upcoming_exporter::get_read_structure();
}
}
+7 -2
View File
@@ -3153,8 +3153,9 @@ function calendar_get_view(\calendar_information $calendar, $view, $includenavig
} else {
$defaultlookahead = CALENDAR_DEFAULT_UPCOMING_LOOKAHEAD;
}
$tstart = $type->convert_to_timestamp($date['year'], $date['mon'], 1);
$tend = $tstart + get_user_preferences('calendar_lookahead', $defaultlookahead);
$tstart = $type->convert_to_timestamp($date['year'], $date['mon'], $date['mday'], $date['hours']);
$tend = usergetmidnight($tstart + DAYSECS * $defaultlookahead + 3 * HOURSECS) - 1;
} else {
$tstart = $type->convert_to_timestamp($date['year'], $date['mon'], 1);
$monthdays = $type->get_num_days_in_month($date['year'], $date['mon']);
@@ -3234,6 +3235,10 @@ function calendar_get_view(\calendar_information $calendar, $view, $includenavig
$day = new \core_calendar\external\day_exporter($calendar, $daydata, $related);
$data = $day->export($renderer);
$template = 'core_calendar/day_detailed';
} else if ($view == "upcoming") {
$upcoming = new \core_calendar\external\calendar_upcoming_exporter($calendar, $related);
$data = $upcoming->export($renderer);
$template = 'core_calendar/calendar_upcoming';
}
return [$data, $template];
-40
View File
@@ -232,46 +232,6 @@ class core_calendar_renderer extends plugin_renderer_base {
return html_writer::tag('div', $eventhtml, array('class' => 'event', 'id' => 'event_' . $event->id));
}
/**
* Displays upcoming events
*
* @param calendar_information $calendar
* @param int $futuredays
* @param int $maxevents
* @return string
*/
public function show_upcoming_events(calendar_information $calendar, $futuredays, $maxevents, moodle_url $returnurl = null) {
if ($returnurl === null) {
$returnurl = $this->page->url;
}
$events = calendar_get_upcoming($calendar->courses, $calendar->groups, $calendar->users,
$futuredays, $maxevents);
$output = html_writer::start_tag('div', array('class'=>'header'));
$output .= $this->course_filter_selector($returnurl, get_string('upcomingeventsfor', 'calendar'));
if (calendar_user_can_add_event($calendar->course)) {
$output .= $this->add_event_button($calendar->course->id);
}
$output .= html_writer::end_tag('div');
if ($events) {
$output .= html_writer::start_tag('div', array('class' => 'eventlist'));
foreach ($events as $event) {
// Convert to calendar_event object so that we transform description accordingly.
$event = new calendar_event($event);
$event->calendarcourseid = $calendar->courseid;
$output .= $this->event($event);
}
$output .= html_writer::end_tag('div');
} else {
$output .= html_writer::span(get_string('noupcomingevents', 'calendar'), 'calendar-information calendar-no-results');
}
return $output;
}
/**
* Displays a course filter selector
*
@@ -0,0 +1,41 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template calendar/calendar_upcoming
Calendar upcoming view.
The purpose of this template is to render the calendar upcoming view.
Classes required for JS:
* none
Data attributes required for JS:
* none
Example context (json):
{
}
}}
<div id="calendar-upcoming-{{uniqid}}" data-template="core_calendar/upcoming_detailed">
{{> core_calendar/upcoming_detailed}}
</div>
{{#js}}
require(['jquery', 'core_calendar/calendar_view'], function($, CalendarView) {
CalendarView.init($("#calendar-upcoming-{{uniqid}}"), 'upcoming');
});
{{/js}}
+12 -4
View File
@@ -31,17 +31,25 @@
{
}
}}
<div class="event">
<div{{!
}} data-type="event"{{!
}} data-course-id="{{course.id}}"{{!
}} data-event-id="{{id}}"{{!
}} class="event"{{!
}} data-eventtype-{{calendareventtype}}="1"{{!
}} data-event-title="{{name}}"{{!
}} data-event-count="{{eventcount}}"{{!
}}>
<div class="card">
<div class="box card-header clearfix p-y-1">
<div class="commands pull-xs-right">
{{#canedit}}
{{#candelete}}
<a href="{{deleteurl}}">
<a href="{{deleteurl}}" data-action="delete">
{{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}
</a>
{{/candelete}}
<a href="{{editurl}}">
<a href="{{editurl}}" data-action="edit">
{{#pix}}t/edit, core, {{#str}}edit{{/str}}{{/pix}}
</a>
{{/canedit}}
@@ -65,4 +73,4 @@
{{/groupname}}
</div>
</div>
</div>
</div>
+1 -1
View File
@@ -31,7 +31,7 @@
{
}
}}
<div class="eventlist">
<div class="eventlist m-y-1">
{{#events}}
{{> core_calendar/event_item }}
{{/events}}
@@ -32,7 +32,7 @@
}} data-region="summary-modal-container"{{!
}} data-event-id="{{id}}"{{!
}} data-event-title="{{name}}"{{!
}} data-event-event-count="{{eventcount}}"{{!
}} data-event-count="{{eventcount}}"{{!
}} data-event-="{{repeatid}}"{{!
}} data-action-event="{{isactionevent}}"{{!
}} data-edit-url="{{editurl}}"{{!
+4 -3
View File
@@ -31,8 +31,9 @@
{
}
}}
{{#filter_selector}}
<div class="header">
{{{filter_selector}}}
{{#filter_selector}}
{{{filter_selector}}}
{{/filter_selector}}
{{> core_calendar/add_event_button}}
</div>
{{/filter_selector}}
+1 -1
View File
@@ -35,11 +35,11 @@
}} class="calendarwrapper"{{!
}}{{#courseid}} data-courseid="{{courseid}}"{{/courseid}}{{!
}}{{#categoryid}} data-categoryid="{{categoryid}}"{{/categoryid}}{{!
}} data-context-id="{{defaulteventcontext}}"{{!
}} data-month="{{date.mon}}"{{!
}} data-year="{{date.year}}"{{!
}}>
{{> core_calendar/header }}
{{> core_calendar/add_event_button}}
{{> core_calendar/month_navigation }}
{{> core/overlay_loading}}
<table id="month-detailed-{{uniqid}}" class="calendarmonth calendartable card-deck m-b-0">
@@ -0,0 +1,38 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template calendar/upcoming_detailed
Calendar upcoming detailed.
The purpose of this template is to render the calendar upcoming detailed view.
Classes required for JS:
* none
Data attributes required for JS:
* none
Example context (json):
{
}
}}
<div class="calendarwrapper" data-view="upcoming" data-context-id="{{defaulteventcontext}}" data-courseid="{{courseid}}">
{{> core_calendar/header}}
{{> core/overlay_loading}}
{{> core_calendar/event_list }}
</div>
+2 -12
View File
@@ -144,18 +144,8 @@ if ($view == 'day' || $view == 'upcoming') {
echo $renderer->render_from_template($template, $data);
break;
case 'upcoming':
$defaultlookahead = CALENDAR_DEFAULT_UPCOMING_LOOKAHEAD;
if (isset($CFG->calendar_lookahead)) {
$defaultlookahead = intval($CFG->calendar_lookahead);
}
$lookahead = get_user_preferences('calendar_lookahead', $defaultlookahead);
$defaultmaxevents = CALENDAR_DEFAULT_UPCOMING_MAXEVENTS;
if (isset($CFG->calendar_maxevents)) {
$defaultmaxevents = intval($CFG->calendar_maxevents);
}
$maxevents = get_user_preferences('calendar_maxevents', $defaultmaxevents);
echo $renderer->show_upcoming_events($calendar, $lookahead, $maxevents);
list($data, $template) = calendar_get_view($calendar, $view);
echo $renderer->render_from_template($template, $data);
break;
}
} else if ($view == 'month') {
+10
View File
@@ -68,6 +68,16 @@ $functions = array(
'ajax' => true,
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
'core_calendar_get_calendar_upcoming_view' => array(
'classname' => 'core_calendar_external',
'methodname' => 'get_calendar_upcoming_view',
'description' => 'Fetch the upcoming view data for a calendar',
'classpath' => 'calendar/externallib.php',
'type' => 'read',
'capabilities' => '',
'ajax' => true,
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
'core_calendar_update_event_start_day' => array(
'classname' => 'core_calendar_external',
'methodname' => 'update_event_start_day',
+1 -1
View File
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2017092900.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2017092900.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.