MDL-78850 calendar: course calendar improvement

This commit is contained in:
Meirza 2024-01-26 21:46:56 +07:00 committed by meirzamoodle
parent 99941c0d13
commit edce8cca8b
21 changed files with 132 additions and 63 deletions

View File

@ -80,8 +80,7 @@ Feature: Enable the calendar block in a course and test it's functionality
And I press "Save and display"
And I turn editing mode on
And I add the "Calendar" block
And I click on "Full calendar" "link"
And I set the field "course" to "C1"
And I click on "Course calendar" "link"
And I create a calendar event:
| Type of event | group |
| Group | Group 1 |

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,6 @@
* @copyright 2017 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core_calendar/calendar_view",["jquery","core/notification","core_calendar/selectors","core_calendar/events","core_calendar/view_manager","core_calendar/crud"],(function($,Notification,CalendarSelectors,CalendarEvents,CalendarViewManager,CalendarCrud){return{init:function(root,type){root=$(root),CalendarViewManager.init(root,type),function(root,type){var body=$("body");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 courseId=$(this).val();CalendarViewManager[reloadFunction](root,courseId,null).then((function(){return root.find(CalendarSelectors.courseSelector).val(courseId)})).then((function(){CalendarViewManager.updateUrl("?view=upcoming&course="+courseId)})).fail(Notification.exception)})),body.on(CalendarEvents.filterChanged,(function(e,data){var daysWithEvent=root.find(CalendarSelectors.eventType[data.type]);1==data.hidden?daysWithEvent.addClass("hidden"):daysWithEvent.removeClass("hidden"),CalendarViewManager.foldDayEvents(root)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root);CalendarCrud.registerEditListeners(root,eventFormPromise)}(root,type)}}}));
define("core_calendar/calendar_view",["jquery","core/notification","core_calendar/selectors","core_calendar/events","core_calendar/view_manager","core_calendar/crud"],(function($,Notification,CalendarSelectors,CalendarEvents,CalendarViewManager,CalendarCrud){return{init:function(root,type){root=$(root),CalendarViewManager.init(root,type),function(root,type){var body=$("body");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),courseId=selectElement.val();const courseName=$("option:selected",selectElement).text();CalendarViewManager[reloadFunction](root,courseId,null).then((function(){return root.find(CalendarSelectors.courseSelector).val(courseId)})).then((function(){CalendarViewManager.updateUrl("?view="+type+"&course="+courseId),CalendarViewManager.handleCourseChange(Number(courseId),courseName)})).fail(Notification.exception)})),body.on(CalendarEvents.filterChanged,(function(e,data){var daysWithEvent=root.find(CalendarSelectors.eventType[data.type]);1==data.hidden?daysWithEvent.addClass("hidden"):daysWithEvent.removeClass("hidden"),CalendarViewManager.foldDayEvents(root)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root);CalendarCrud.registerEditListeners(root,eventFormPromise)}(root,type)}}}));
//# sourceMappingURL=calendar_view.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,6 @@
* @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core_calendar/crud",["jquery","core/str","core/notification","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors","core/pending","core/modal_save_cancel"],(function($,Str,Notification,ModalEvents,ModalEventForm,CalendarRepository,CalendarEvents,CalendarModalDelete,CalendarSelectors,Pending,ModalSaveCancel){return{registerRemove:function(root){root.on("click",CalendarSelectors.actions.remove,(function(e){var eventSource=$(this).closest(CalendarSelectors.eventItem);!function(eventId,eventTitle,eventCount){var deletePromise,pendingPromise=new Pending("core_calendar/crud:confirmDeletion"),deleteStrings=[{key:"deleteevent",component:"calendar"}],isRepeatedEvent=(eventCount=parseInt(eventCount,10))>1;isRepeatedEvent?(deleteStrings.push({key:"confirmeventseriesdelete",component:"calendar",param:{name:eventTitle,count:eventCount}}),deletePromise=CalendarModalDelete.create()):(deleteStrings.push({key:"confirmeventdelete",component:"calendar",param:eventTitle}),deletePromise=ModalSaveCancel.create());var stringsPromise=Str.get_strings(deleteStrings);$.when(stringsPromise,deletePromise).then((function(strings,deleteModal){return deleteModal.setRemoveOnClose(!0),deleteModal.setTitle(strings[0]),deleteModal.setBody(strings[1]),isRepeatedEvent||deleteModal.setSaveButtonText(strings[0]),deleteModal.show(),deleteModal.getRoot().on(ModalEvents.save,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedevent");CalendarRepository.deleteEvent(eventId,!1).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!1])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal.getRoot().on(CalendarEvents.deleteAll,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedallevent");CalendarRepository.deleteEvent(eventId,!0).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!0])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)}(eventSource.data("eventId"),eventSource.data("eventTitle"),eventSource.data("eventCount")),e.preventDefault()}))},registerEditListeners:function(root,eventFormModalPromise){var pendingPromise=new Pending("core_calendar/crud:registerEditListeners");return eventFormModalPromise.then((function(modal){return $("body").on(CalendarEvents.editEvent,(function(e,eventId){var target=root.find("[data-event-id=".concat(eventId,"]")),calendarWrapper=root.find(CalendarSelectors.wrapper);modal.setEventId(eventId),modal.setContextId(calendarWrapper.data("contextId")),modal.setReturnElement(target),modal.show(),e.stopImmediatePropagation()})),modal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)},registerEventFormModal:function(root){var eventFormPromise=ModalEventForm.create();return root.on("click",CalendarSelectors.actions.create,(function(e){eventFormPromise.then((function(modal){var wrapper=root.find(CalendarSelectors.wrapper),categoryId=wrapper.data("categoryid");void 0!==categoryId&&modal.setCategoryId(categoryId);var today=root.find(CalendarSelectors.today),firstDay=root.find(CalendarSelectors.day);!today.length&&firstDay.length&&modal.setStartTime(firstDay.data("newEventTimestamp")),modal.setContextId(wrapper.data("contextId")),modal.setCourseId(wrapper.data("courseid")),modal.show()})).catch(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){modal.setEventId(eventWrapper.data("eventId")),modal.setContextId(calendarWrapper.data("contextId")),modal.setCourseId(eventWrapper.data("courseId")),modal.show(),e.stopImmediatePropagation()})).catch(Notification.exception)})),eventFormPromise}}}));
define("core_calendar/crud",["jquery","core/str","core/notification","core/modal_events","core_calendar/modal_event_form","core_calendar/repository","core_calendar/events","core_calendar/modal_delete","core_calendar/selectors","core/pending","core/modal_save_cancel","core/config"],(function($,Str,Notification,ModalEvents,ModalEventForm,CalendarRepository,CalendarEvents,CalendarModalDelete,CalendarSelectors,Pending,ModalSaveCancel,Config){return{registerRemove:function(root){root.on("click",CalendarSelectors.actions.remove,(function(e){var eventSource=$(this).closest(CalendarSelectors.eventItem);!function(eventId,eventTitle,eventCount){var deletePromise,pendingPromise=new Pending("core_calendar/crud:confirmDeletion"),deleteStrings=[{key:"deleteevent",component:"calendar"}],isRepeatedEvent=(eventCount=parseInt(eventCount,10))>1;isRepeatedEvent?(deleteStrings.push({key:"confirmeventseriesdelete",component:"calendar",param:{name:eventTitle,count:eventCount}}),deletePromise=CalendarModalDelete.create()):(deleteStrings.push({key:"confirmeventdelete",component:"calendar",param:eventTitle}),deletePromise=ModalSaveCancel.create());var stringsPromise=Str.get_strings(deleteStrings);$.when(stringsPromise,deletePromise).then((function(strings,deleteModal){return deleteModal.setRemoveOnClose(!0),deleteModal.setTitle(strings[0]),deleteModal.setBody(strings[1]),isRepeatedEvent||deleteModal.setSaveButtonText(strings[0]),deleteModal.show(),deleteModal.getRoot().on(ModalEvents.save,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedevent");CalendarRepository.deleteEvent(eventId,!1).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!1])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal.getRoot().on(CalendarEvents.deleteAll,(function(){var pendingPromise=new Pending("calendar/crud:initModal:deletedallevent");CalendarRepository.deleteEvent(eventId,!0).then((function(){$("body").trigger(CalendarEvents.deleted,[eventId,!0])})).then(pendingPromise.resolve).catch(Notification.exception)})),deleteModal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)}(eventSource.data("eventId"),eventSource.data("eventTitle"),eventSource.data("eventCount")),e.preventDefault()}))},registerEditListeners:function(root,eventFormModalPromise){var pendingPromise=new Pending("core_calendar/crud:registerEditListeners");return eventFormModalPromise.then((function(modal){return $("body").on(CalendarEvents.editEvent,(function(e,eventId){var target=root.find("[data-event-id=".concat(eventId,"]")),calendarWrapper=root.find(CalendarSelectors.wrapper);modal.setEventId(eventId),modal.setContextId(calendarWrapper.data("contextId")),modal.setReturnElement(target),modal.show(),e.stopImmediatePropagation()})),modal})).then((function(modal){return pendingPromise.resolve(),modal})).catch(Notification.exception)},registerEventFormModal:function(root){var eventFormPromise=ModalEventForm.create();return root.on("click",CalendarSelectors.actions.create,(function(e){eventFormPromise.then((function(modal){var wrapper=root.find(CalendarSelectors.wrapper),categoryId=wrapper.data("categoryid");const courseId=wrapper.data("courseid");void 0!==categoryId&&courseId!=Config.siteId&&modal.setCategoryId(categoryId);var today=root.find(CalendarSelectors.today),firstDay=root.find(CalendarSelectors.day);!today.length&&firstDay.length&&modal.setStartTime(firstDay.data("newEventTimestamp")),modal.setContextId(wrapper.data("contextId")),modal.setCourseId(wrapper.data("courseid")),modal.show()})).catch(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){modal.setEventId(eventWrapper.data("eventId")),modal.setContextId(calendarWrapper.data("contextId")),modal.setCourseId(eventWrapper.data("courseId")),modal.show(),e.stopImmediatePropagation()})).catch(Notification.exception)})),eventFormPromise}}}));
//# sourceMappingURL=crud.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,6 @@
* @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core_calendar/selectors",[],(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]",other:"[data-eventtype-other]"},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]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:'select[name="course"]',viewSelector:'div[data-region="view-selector"]',actions:{create:'[data-action="new-event-button"]',edit:'[data-action="edit"]',remove:'[data-action="delete"]',viewEvent:'[data-action="view-event"]',deleteSubscription:'[data-action="delete-subscription"]'},elements:{courseSelector:'select[name="course"]',dateContainer:".clickable.hasevent",dateContent:'[data-region="day-content"]',monthDetailed:".calendarmonth.calendartable"},today:".today",day:'[data-region="day"]',calendarMain:'[data-region="calendar"]',wrapper:".calendarwrapper",eventItem:'[data-type="event"]',links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']"},containers:{loadingIcon:'[data-region="overlay-icon-container"]'},mainCalendar:".maincalendar .heightcontainer",fullCalendarView:"page-calendar-view"}}));
define("core_calendar/selectors",[],(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]",other:"[data-eventtype-other]"},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]",other:"[data-popover-eventtype-other]"},calendarPeriods:{month:"[data-period='month']"},courseSelector:'select[name="course"]',viewSelector:'div[data-region="view-selector"]',actions:{create:'[data-action="new-event-button"]',edit:'[data-action="edit"]',remove:'[data-action="delete"]',viewEvent:'[data-action="view-event"]',deleteSubscription:'[data-action="delete-subscription"]'},elements:{courseSelector:'select[name="course"]',dateContainer:".clickable.hasevent",dateContent:'[data-region="day-content"]',monthDetailed:".calendarmonth.calendartable"},today:".today",day:'[data-region="day"]',calendarMain:'[data-region="calendar"]',wrapper:".calendarwrapper",eventItem:'[data-type="event"]',links:{navLink:".calendarwrapper .arrow_link",eventLink:"[data-region='event-item']",miniDayLink:"[data-region='mini-day-link']"},containers:{loadingIcon:'[data-region="overlay-icon-container"]'},mainCalendar:".maincalendar .heightcontainer",fullCalendarView:"page-calendar-view",pageHeaderHeadings:".page-header-headings h1"}}));
//# sourceMappingURL=selectors.min.js.map

View File

@ -1 +1 @@
{"version":3,"file":"selectors.min.js","sources":["../src/selectors.js"],"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 <http://www.gnu.org/licenses/>.\n\n/**\n * CSS selectors for the calendar.\n *\n * @module core_calendar/selectors\n * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","mainCalendar","fullCalendarView"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,gBAAiB,oCACjBC,UAAW,CACPC,KAAM,wBACNC,SAAU,4BACVC,OAAQ,0BACRC,MAAO,yBACPC,KAAM,wBACNC,MAAO,0BAEXC,YAAa,CACTN,KAAM,gCACNC,SAAU,oCACVC,OAAQ,kCACRC,MAAO,iCACPC,KAAM,gCACNC,MAAO,kCAEXE,gBAAiB,CACbC,MAAO,yBAEXC,eAAgB,wBAChBC,aAAc,mCACdC,QAAS,CACLC,OAAQ,mCACRC,KAAM,uBACNC,OAAQ,yBACRC,UAAW,6BACXC,mBAAoB,uCAExBC,SAAU,CACNR,eAAgB,wBAChBS,cAAe,sBACfC,YAAa,8BACbC,cAAe,gCAEnBC,MAAO,SACPC,IAAK,sBACLC,aAAc,2BACdC,QAAS,mBACTC,UAAW,sBACXC,MAAO,CACHC,QAAS,+BACTC,UAAW,6BACXC,YAAa,iCAEjBC,WAAY,CACRC,YAAa,0CAEjBC,aAAc,iCACdC,iBAAkB"}
{"version":3,"file":"selectors.min.js","sources":["../src/selectors.js"],"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 <http://www.gnu.org/licenses/>.\n\n/**\n * CSS selectors for the calendar.\n *\n * @module core_calendar/selectors\n * @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n pageHeaderHeadings: '.page-header-headings h1',\n };\n});\n"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","mainCalendar","fullCalendarView","pageHeaderHeadings"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,gBAAiB,oCACjBC,UAAW,CACPC,KAAM,wBACNC,SAAU,4BACVC,OAAQ,0BACRC,MAAO,yBACPC,KAAM,wBACNC,MAAO,0BAEXC,YAAa,CACTN,KAAM,gCACNC,SAAU,oCACVC,OAAQ,kCACRC,MAAO,iCACPC,KAAM,gCACNC,MAAO,kCAEXE,gBAAiB,CACbC,MAAO,yBAEXC,eAAgB,wBAChBC,aAAc,mCACdC,QAAS,CACLC,OAAQ,mCACRC,KAAM,uBACNC,OAAQ,yBACRC,UAAW,6BACXC,mBAAoB,uCAExBC,SAAU,CACNR,eAAgB,wBAChBS,cAAe,sBACfC,YAAa,8BACbC,cAAe,gCAEnBC,MAAO,SACPC,IAAK,sBACLC,aAAc,2BACdC,QAAS,mBACTC,UAAW,sBACXC,MAAO,CACHC,QAAS,+BACTC,UAAW,6BACXC,YAAa,iCAEjBC,WAAY,CACRC,YAAa,0CAEjBC,aAAc,iCACdC,iBAAkB,qBAClBC,mBAAoB"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -34,6 +34,7 @@ define([
'core_calendar/crud',
'core_calendar/selectors',
'core/config',
'core/url',
],
function(
$,
@ -45,6 +46,7 @@ function(
CalendarCrud,
CalendarSelectors,
Config,
Url,
) {
var SELECTORS = {
@ -170,26 +172,40 @@ function(
day = dayLink.data('day'),
courseId = dayLink.data('courseid'),
categoryId = dayLink.data('categoryid');
const url = '?view=day&time=' + dayLink.data('timestamp');
const urlParams = {
view: 'day',
time: dayLink.data('timestamp'),
course: courseId,
};
if (viewingFullCalendar) {
// Construct the URL parameter string from the urlParams object.
const urlParamString = Object.entries(urlParams)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root,
'core_calendar/calendar_day').then(function() {
e.preventDefault();
return CalendarViewManager.updateUrl(url);
return CalendarViewManager.updateUrl(urlParamString);
}).catch(Notification.exception);
} else {
window.location.assign(Config.wwwroot + '/calendar/view.php' + url);
window.location.assign(Url.relativeUrl('calendar/view.php', urlParams));
}
});
root.on('change', CalendarSelectors.elements.courseSelector, function() {
var selectElement = $(this);
var courseId = selectElement.val();
const courseName = $("option:selected", selectElement).text();
CalendarViewManager.reloadCurrentMonth(root, courseId, null)
.then(function() {
// We need to get the selector again because the content has changed.
return root.find(CalendarSelectors.elements.courseSelector).val(courseId);
})
.then(function() {
CalendarViewManager.updateUrl('?view=month&course=' + courseId);
CalendarViewManager.handleCourseChange(Number(courseId), courseName);
return;
})
.catch(Notification.exception);
});
@ -205,8 +221,14 @@ function(
if (!viewingFullCalendar && displayingSmallBlockCalendar) {
const dateContainer = target.closest(SELECTORS.DAY);
const url = '?view=day&time=' + dateContainer.data('day-timestamp');
window.location.assign(Config.wwwroot + '/calendar/view.php' + url);
const wrapper = target.closest(CalendarSelectors.wrapper);
const courseId = wrapper.data('courseid');
const params = {
view: 'day',
time: dateContainer.data('day-timestamp'),
course: courseId,
};
window.location.assign(Url.relativeUrl('calendar/view.php', params));
} else {
const hasViewDayLink = target.closest(SELECTORS.VIEW_DAY_LINK).length;
const shouldShowNewEventModal = !hasViewDayLink;

View File

@ -57,13 +57,16 @@ function(
root.on('change', CalendarSelectors.courseSelector, function() {
var selectElement = $(this);
var courseId = selectElement.val();
const courseName = $("option:selected", selectElement).text();
CalendarViewManager[reloadFunction](root, courseId, null)
.then(function() {
// We need to get the selector again because the content has changed.
return root.find(CalendarSelectors.courseSelector).val(courseId);
})
.then(function() {
CalendarViewManager.updateUrl('?view=upcoming&course=' + courseId);
CalendarViewManager.updateUrl('?view=' + type + '&course=' + courseId);
CalendarViewManager.handleCourseChange(Number(courseId), courseName);
return;
})
.fail(Notification.exception);
});

View File

@ -32,6 +32,7 @@ define([
'core_calendar/selectors',
'core/pending',
'core/modal_save_cancel',
'core/config',
],
function(
$,
@ -45,6 +46,7 @@ function(
CalendarSelectors,
Pending,
ModalSaveCancel,
Config,
) {
/**
@ -153,7 +155,8 @@ function(
var wrapper = root.find(CalendarSelectors.wrapper);
var categoryId = wrapper.data('categoryid');
if (typeof categoryId !== 'undefined') {
const courseId = wrapper.data('courseid');
if (typeof categoryId !== 'undefined' && courseId != Config.siteId) {
modal.setCategoryId(categoryId);
}

View File

@ -72,5 +72,6 @@ define([], function() {
},
mainCalendar: '.maincalendar .heightcontainer',
fullCalendarView: 'page-calendar-view',
pageHeaderHeadings: '.page-header-headings h1',
};
});

View File

@ -33,6 +33,8 @@ import CustomEvents from 'core/custom_interaction_events';
import {getString} from 'core/str';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import Url from 'core/url';
import Config from 'core/config';
/**
* Limit number of events per day
@ -220,17 +222,20 @@ const registerEventListeners = (root) => {
if (view == 'month') {
refreshMonthContent(root, year, month, courseId, categoryId, root, 'core_calendar/calendar_month', day)
.then(() => {
updateUrl('?view=month');
updateUrl('?view=month&course=' + courseId);
return;
}).fail(Notification.exception);
} else if (view == 'day') {
refreshDayContent(root, year, month, day, courseId, categoryId, root, 'core_calendar/calendar_day')
.then(() => {
updateUrl('?view=day');
updateUrl('?view=day&course=' + courseId);
return;
}).fail(Notification.exception);
} else if (view == 'upcoming') {
reloadCurrentUpcoming(root, courseId, categoryId, root, 'core_calendar/calendar_upcoming')
.then(() => {
updateUrl('?view=upcoming');
updateUrl('?view=upcoming&course=' + courseId);
return;
}).fail(Notification.exception);
}
}
@ -567,3 +572,31 @@ export const init = (root, view) => {
registerEventListenersForMonthDetailed(calendarTable, pendingId);
}
};
/**
* Handles the change of course and updates the relevant elements on the page.
*
* @param {integer} courseId - The ID of the new course.
* @param {string} courseName - The name of the new course.
* @returns {Promise<void>} - A promise that resolves after the updates are applied.
*/
export const handleCourseChange = async(courseId, courseName) => {
// Select the <ul> element inside the data-region="view-selector".
const ulElement = document.querySelector(CalendarSelectors.viewSelector + ' ul');
// Select all <li><a> elements within the <ul>.
const liElements = ulElement.querySelectorAll('li a');
// Loop through the selected elements and update the courseid.
liElements.forEach(element => {
element.setAttribute('data-courseid', courseId);
});
const calendar = await getString('calendar', 'calendar');
const pageHeaderHeadingsElement = document.querySelector(CalendarSelectors.pageHeaderHeadings);
const courseUrl = Url.relativeUrl('/course/view.php', {id: courseId});
// Apply the page header text.
if (courseId !== Config.siteId) {
pageHeaderHeadingsElement.innerHTML = calendar + ': <a href="' + courseUrl + '">' + courseName + '</a>';
} else {
pageHeaderHeadingsElement.innerHTML = calendar;
}
};

View File

@ -101,9 +101,14 @@ class footer_options_exporter extends exporter {
$values->footerlinks = [];
if ($this->showfullcalendarlink) {
if ($this->calendar->courseid !== SITEID) {
$linkname = get_string('coursecalendar', 'calendar', 'Course');
} else {
$linkname = get_string('fullcalendar', 'calendar');
}
$values->footerlinks[] = (object)[
'url' => $this->get_calendar_url(),
'linkname' => get_string('fullcalendar', 'calendar'),
'linkname' => $linkname,
];
}
@ -148,6 +153,7 @@ class footer_options_exporter extends exporter {
$url = new moodle_url('/calendar/view.php', [
'view' => 'month',
'time' => $this->calendar->time,
'course' => $this->calendar->courseid,
]);
return $url->out(false);

View File

@ -11,12 +11,15 @@ Feature: Perform basic calendar functionality
| student2 | Student | 2 | student2@example.com |
| student3 | Student | 3 | student3@example.com |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "categories" exist:
| name | category | idnumber |
| CatA | 0 | cata |
And the following "courses" exist:
| fullname | shortname | format |
| Course 1 | C1 | topics |
| Course 2 | C2 | topics |
| Course 3 | C3 | topics |
| Course 4 | C4 | topics |
| fullname | shortname | format | category |
| Course 1 | C1 | topics | cata |
| Course 2 | C2 | topics | cata |
| Course 3 | C3 | topics | cata |
| Course 4 | C4 | topics | cata |
And the following "course enrolments" exist:
| user | course | role |
| student1 | C1 | student |
@ -44,7 +47,7 @@ Feature: Perform basic calendar functionality
| Description | Come join this awesome event, sucka! |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Full calendar"
And I follow "Course calendar"
And I should see "Really awesome event!"
And I log out
And I log in as "student2"
@ -61,7 +64,7 @@ Feature: Perform basic calendar functionality
| Description | Come join this awesome event, sucka! |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Full calendar"
And I follow "Course calendar"
And I click on "Really awesome event!" "link"
And "Course 1" "link" should exist in the "Really awesome event!" "dialogue"
And I click on "Close" "button" in the "Really awesome event!" "dialogue"
@ -82,7 +85,7 @@ Feature: Perform basic calendar functionality
| Description | Come join this awesome event |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Full calendar"
And I follow "Course calendar"
Then I follow "Really awesome event!"
@javascript
@ -94,7 +97,7 @@ Feature: Perform basic calendar functionality
| Description | Come join this awesome event, sucka! |
And I log out
When I am on the "Course 1" course page logged in as student1
And I follow "Full calendar"
And I follow "Course calendar"
Then I should not see "Really awesome event!"
@javascript
@ -115,7 +118,7 @@ Feature: Perform basic calendar functionality
| Event title | Really awesome event! |
| Description | Come join this awesome event, sucka! |
And I am on "Course 1" course homepage
When I follow "Full calendar"
When I follow "Course calendar"
And I click on "Really awesome event!" "link"
And I click on "Delete" "button" in the "Really awesome event!" "dialogue"
And I click on "Delete event" "button"
@ -131,7 +134,7 @@ Feature: Perform basic calendar functionality
| Description | Come join this awesome event, sucka! |
| Location | Cube office |
And I am on "Course 1" course homepage
When I follow "Full calendar"
When I follow "Course calendar"
And I click on "Really awesome event!" "link"
And ".location-content" "css_element" should exist
And I should see "Cube office"
@ -153,8 +156,7 @@ Feature: Perform basic calendar functionality
And the following "activities" exist:
| activity | course | idnumber | name | intro | timeopen | timeclose |
| choice | C1 | choice1 | Test choice | Test choice description | ##today## | ##today## |
When I follow "Full calendar"
And I set the field "course" to "C1"
When I follow "Course calendar"
Then I should see "Test choice opens"
And I should see "Test choice closes"
When I click on "Test choice opens" "link"
@ -165,7 +167,7 @@ Feature: Perform basic calendar functionality
And I wait to be redirected
Then I should see "Test choice"
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I follow "Course calendar"
When I click on "Test choice closes" "link"
Then "Delete" "button" should not exist in the "Test choice closes" "dialogue"
And "Edit" "button" should not exist in the "Test choice closes" "dialogue"
@ -177,7 +179,7 @@ Feature: Perform basic calendar functionality
@javascript
Scenario: Attempt to create event without fill required fields should display validation errors
Given I am on the "Course 1" course page logged in as teacher1
And I follow "Full calendar"
And I follow "Course calendar"
And I click on "New event" "button"
When I click on "Save" "button"
Then I should see "Required" in the "Event title" "form_row"
@ -259,7 +261,7 @@ Feature: Perform basic calendar functionality
@javascript @accessibility
Scenario: The calendar page must be accessible
Given I am on the "Course 1" course page logged in as student1
When I follow "Full calendar"
When I follow "Course calendar"
Then the page should meet accessibility standards
And the page should meet "wcag131, wcag143, wcag412" accessibility standards
And the page should meet accessibility standards with "wcag131, wcag143, wcag412" extra tests
@ -302,19 +304,18 @@ Feature: Perform basic calendar functionality
@javascript
Scenario: Changing the event type should clear previous data
Given I am on the "Course 1" course page logged in as admin
And I follow "Full calendar"
And I set the field "course" to "C1"
And I follow "Course calendar"
And I press "New event"
And I set the following fields to these values:
| Event title | Group 1 event |
| Type of event | Group |
And I press "Save"
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I follow "Course calendar"
And I click on "Group 1 event" "link"
And I should see "Group event"
And I should see "Group 1"
When I click on "Edit" "button"
When I click on "Edit" "button" in the "Group 1 event" "dialogue"
And I set the following fields to these values:
| Event title | My own user event |
| Type of event | user |
@ -340,8 +341,9 @@ Feature: Perform basic calendar functionality
And I should see "Course event"
And I click on "Edit" "button" in the "Course 1 event" "dialogue"
And I set the following fields to these values:
| Event title | Category event |
| Type of event | category |
| Event title | Category event |
| Type of event | category |
| Category | CatA |
And I press "Save"
And I click on "Category event" "link"
And I should see "Category event"
@ -353,23 +355,18 @@ Feature: Perform basic calendar functionality
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
# We need this so we can make a category event.
And the following "categories" exist:
| name | category | idnumber |
| CatA | 0 | cata |
And the following "role assigns" exist:
| user | role | contextlevel | reference |
| teacher1 | manager | Category | cata |
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I set the field "course" to "C1"
And I follow "Course calendar"
And I press "New event"
And I set the following fields to these values:
| Event title | type change test event |
| Type of event | User |
And I press "Save"
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I follow "Course calendar"
And I click on "type change test event" "link"
And I should see "User event"
When I click on "Edit" "button"
@ -391,7 +388,7 @@ Feature: Perform basic calendar functionality
And I should see "User event"
# Now test changing from user to group event.
And I am on "Course 1" course homepage
And I follow "Full calendar"
And I follow "Course calendar"
And I click on "type change test event" "link"
And I click on "Edit" "button"
And I set the following fields to these values:

View File

@ -22,7 +22,7 @@ Feature: Limit displayed upcoming events
Scenario: I view calendar details for a future event
Given I am on "Course 1" course homepage with editing mode on
And I follow "Full calendar"
And I follow "Course calendar"
And I click on "a.next" "css_element"
And I click on "a.next" "css_element"
When I create a calendar event:

View File

@ -96,10 +96,6 @@ $course = get_course($courseid);
if ($iscoursecalendar && !empty($courseid)) {
navigation_node::override_active_url(new moodle_url('/course/view.php', array('id' => $course->id)));
$PAGE->navbar->add(
get_string('calendar', 'calendar'),
new moodle_url('/calendar/view.php', ['view' => 'month', 'course' => $course->id])
);
$PAGE->set_secondary_navigation(false);
} else if (!empty($categoryid)) {
core_course_category::get($categoryid); // Check that category exists and can be accessed.
@ -138,13 +134,21 @@ switch($view) {
break;
}
// Print title and header
$PAGE->set_show_course_index(false);
$PAGE->set_pagelayout('standard');
// Print title and header.
$PAGE->set_title("$course->shortname: $strcalendar: $pagetitle");
$headingstr = get_string('calendar', 'core_calendar');
$headingstr = ($iscoursecalendar) ? "{$headingstr}: {$COURSE->shortname}" : $headingstr;
$PAGE->set_heading($headingstr);
// If the user is on the course page,
// then make the course name linkable to ease the user's navigation to the course page.
if ($iscoursecalendar) {
$url = new \moodle_url('/course/view.php', ['id' => $courseid]);
$linkcourse = html_writer::link($url, $course->shortname);
$headingstr = "{$headingstr}: {$linkcourse}";
}
$PAGE->set_heading($headingstr, false);
$renderer = $PAGE->get_renderer('core_calendar');
$calendar->add_sidecalendar_blocks($renderer, true, $view);

View File

@ -330,7 +330,8 @@ class page_requirements_manager {
'contextid' => $contextid,
'contextInstanceId' => (int) $contextinstanceid,
'langrev' => get_string_manager()->get_revision(),
'templaterev' => $this->get_templaterev()
'templaterev' => $this->get_templaterev(),
'siteId' => (int) SITEID,
);
if ($CFG->debugdeveloper) {
$this->M_cfg['developerdebug'] = true;