This commit is contained in:
Ilya Tregubov 2024-03-05 11:23:17 +08:00
commit dcc9324b68
24 changed files with 175 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

@ -3756,6 +3756,11 @@ function core_course_core_calendar_get_valid_event_timestart_range(\calendar_eve
function core_course_drawer(): string {
global $PAGE;
// If the course index is explicitly set and if it should be hidden.
if ($PAGE->get_show_course_index() === false) {
return '';
}
// Only add course index on non-site course pages.
if (!$PAGE->course || $PAGE->course->id == SITEID) {
return '';

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;

View File

@ -432,6 +432,11 @@ class moodle_page {
*/
protected $_forcelockallblocks = false;
/**
* @var bool Indicates whether the course index drawer should be shown.
*/
protected bool $_showcourseindex = true;
/**
* Force the settings menu to be displayed on this page. This will only force the
* settings menu on an activity / resource page that is being displayed on a theme that
@ -2477,4 +2482,24 @@ class moodle_page {
public function get_navigation_overflow_state(): bool {
return $this->_navigationoverflow;
}
/**
* Set the status for displaying the course index.
*
* @param bool $state
* - `true` (default) if the course index should be shown.
* - `false` if the course index should be hidden.
*/
public function set_show_course_index(bool $state): void {
$this->_showcourseindex = $state;
}
/**
* Get the current status for displaying the course index.
*
* @return bool
*/
public function get_show_course_index(): bool {
return $this->_showcourseindex;
}
}

View File

@ -875,6 +875,19 @@ class moodle_page_test extends \advanced_testcase {
$this->testpage->force_lock_all_blocks();
$this->assertFalse($this->testpage->user_can_edit_blocks());
}
/**
* Test the method to set and retrieve the show_course_index property.
*
* @covers ::set_show_course_index
* @covers ::get_show_course_index
* @return void
*/
public function test_show_course_index(): void {
$page = new \moodle_page();
$page->set_show_course_index(false);
$this->assertFalse($page->get_show_course_index());
}
}
/**