diff --git a/blocks/calendar_month/block_calendar_month.php b/blocks/calendar_month/block_calendar_month.php index fe3b998a6c8..96350fd5119 100644 --- a/blocks/calendar_month/block_calendar_month.php +++ b/blocks/calendar_month/block_calendar_month.php @@ -56,6 +56,9 @@ class block_calendar_month extends block_base { $calendar = \calendar_information::create(time(), $courseid, $categoryid); list($data, $template) = calendar_get_view($calendar, 'monthblock', isloggedin()); + // Add a flag that this is coming from calendar block. + $data->iscalendarblock = true; + $renderer = $this->page->get_renderer('core_calendar'); $this->content->text .= $renderer->render_from_template($template, $data); diff --git a/blocks/calendar_month/tests/behat/block_calendar_month.feature b/blocks/calendar_month/tests/behat/block_calendar_month.feature index 08481025931..691f5b95afd 100644 --- a/blocks/calendar_month/tests/behat/block_calendar_month.feature +++ b/blocks/calendar_month/tests/behat/block_calendar_month.feature @@ -90,3 +90,22 @@ Feature: Enable the calendar block in a course and test it's functionality Then I should see "Group Event" And I am on the "Course 1" course page logged in as student2 And I should not see "Group Event" + + @javascript + Scenario: Click on today's course event on the calendar view page's calendar block + Given I log in as "admin" + And I create a calendar event with form data: + | id_eventtype | Site | + | id_name | Site Event | + And I am on site homepage + And I turn editing mode on + And I add the "Calendar" block + And I configure the "Calendar" block + And I set the following fields to these values: + | Page contexts | Display throughout the entire site | + And I press "Save changes" + When I am on "Course 1" course homepage + And I follow "Course calendar" + And I click on today in the mini-calendar block + Then I should see "Site Event" in the "Calendar" "block" + And ".popover" "css_element" should not exist diff --git a/calendar/amd/build/calendar.min.js b/calendar/amd/build/calendar.min.js index 117ff46a1e4..75b98b5e5ce 100644 --- a/calendar/amd/build/calendar.min.js +++ b/calendar/amd/build/calendar.min.js @@ -9,6 +9,6 @@ * @copyright 2017 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("core_calendar/calendar",["jquery","core/templates","core/notification","core_calendar/repository","core_calendar/events","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors","core/config","core/url","core/str"],(function($,Templates,Notification,CalendarRepository,CalendarEvents,CalendarViewManager,CalendarCrud,CalendarSelectors,Config,Url,Str){var SELECTORS_DAY="[data-region='day']",SELECTORS_DAY_CONTENT="[data-region='day-content']",SELECTORS_LOADING_ICON=".loading-icon",SELECTORS_VIEW_DAY_LINK="[data-action='view-day-link']",SELECTORS_CALENDAR_MONTH_WRAPPER=".calendarwrapper",SELECTORS_SCREEN_READER_ANNOUNCEMENTS=".calendar-announcements",SELECTORS_CURRENT_MONTH=".calendar-controls .current",handleMoveEvent=function(e,eventId,originElement,destinationElement){var originTimestamp=null,destinationTimestamp=destinationElement.attr("data-day-timestamp");originElement&&(originTimestamp=originElement.attr("data-day-timestamp")),originElement&&originTimestamp==destinationTimestamp||Templates.render("core/loading",{}).then((function(html,js){destinationElement.find(SELECTORS_DAY_CONTENT).addClass("hidden"),Templates.appendNodeContents(destinationElement,html,js),originElement&&(originElement.find(SELECTORS_DAY_CONTENT).addClass("hidden"),Templates.appendNodeContents(originElement,html,js))})).then((function(){return CalendarRepository.updateEventStartDay(eventId,destinationTimestamp)})).then((function(){$("body").trigger(CalendarEvents.eventMoved,[eventId,originElement,destinationElement])})).always((function(){var destinationLoadingElement=destinationElement.find(SELECTORS_LOADING_ICON);if(destinationElement.find(SELECTORS_DAY_CONTENT).removeClass("hidden"),Templates.replaceNode(destinationLoadingElement,"",""),originElement){var originLoadingElement=originElement.find(SELECTORS_LOADING_ICON);originElement.find(SELECTORS_DAY_CONTENT).removeClass("hidden"),Templates.replaceNode(originLoadingElement,"","")}})).catch(Notification.exception)},registerEventListeners=function(root){const viewingFullCalendar=document.getElementById(CalendarSelectors.fullCalendarView);root.on("click",SELECTORS_VIEW_DAY_LINK,(function(e){var dayLink=$(e.target).closest(SELECTORS_VIEW_DAY_LINK),year=dayLink.data("year"),month=dayLink.data("month"),day=dayLink.data("day"),courseId=dayLink.data("courseid"),categoryId=dayLink.data("categoryid");const urlParams={view:"day",time:dayLink.data("timestamp"),course:courseId};if(viewingFullCalendar){const urlParamString=Object.entries(urlParams).map((_ref=>{let[key,value]=_ref;return"".concat(encodeURIComponent(key),"=").concat(encodeURIComponent(value))})).join("&");CalendarViewManager.refreshDayContent(root,year,month,day,courseId,categoryId,root,"core_calendar/calendar_day").then((function(){return e.preventDefault(),CalendarViewManager.updateUrl(urlParamString)})).catch(Notification.exception)}else window.location.assign(Url.relativeUrl("calendar/view.php",urlParams))})),root.on("change",CalendarSelectors.elements.courseSelector,(function(){var selectElement=$(this),courseId=selectElement.val();const courseName=$("option:selected",selectElement).text();CalendarViewManager.reloadCurrentMonth(root,courseId,null).then((function(){return root.find(CalendarSelectors.elements.courseSelector).val(courseId)})).then((function(){CalendarViewManager.updateUrl("?view=month&course="+courseId),CalendarViewManager.handleCourseChange(Number(courseId),courseName)})).catch(Notification.exception)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root),contextId=$(SELECTORS_CALENDAR_MONTH_WRAPPER).data("context-id");!function(root,eventFormModalPromise){var body=$("body");body.on(CalendarEvents.created,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.deleted,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.updated,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.editActionEvent,(function(e,url){window.location.assign(url)})),body.on(CalendarEvents.moveEvent,handleMoveEvent),body.on(CalendarEvents.eventMoved,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.monthChanged,root,(async function(){const monthName=body.find(SELECTORS_CURRENT_MONTH).text(),monthAnnoucement=await Str.get_string("newmonthannouncement","calendar",monthName);body.find(SELECTORS_SCREEN_READER_ANNOUNCEMENTS).html(monthAnnoucement)})),CalendarCrud.registerEditListeners(root,eventFormModalPromise)}(root,eventFormPromise),contextId&&root.on("click",SELECTORS_DAY,(function(e){var target=$(e.target);const displayingSmallBlockCalendar="side-pre"===root.parents("aside").data("blockregion");if(!viewingFullCalendar&&displayingSmallBlockCalendar){const dateContainer=target.closest(SELECTORS_DAY),courseId=target.closest(CalendarSelectors.wrapper).data("courseid"),params={view:"day",time:dateContainer.data("day-timestamp"),course:courseId};window.location.assign(Url.relativeUrl("calendar/view.php",params))}else{if(!target.closest(SELECTORS_VIEW_DAY_LINK).length){var startTime=$(this).attr("data-new-event-timestamp");eventFormPromise.then((function(modal){var wrapper=target.closest(CalendarSelectors.wrapper);modal.setCourseId(wrapper.data("courseid"));var categoryId=wrapper.data("categoryid");void 0!==categoryId&&modal.setCategoryId(categoryId),modal.setContextId(wrapper.data("contextId")),modal.setStartTime(startTime),modal.show()})).catch(Notification.exception)}}e.preventDefault()}))};return{init:function(root){root=$(root),CalendarViewManager.init(root),registerEventListeners(root)}}})); +define("core_calendar/calendar",["jquery","core/templates","core/notification","core_calendar/repository","core_calendar/events","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors","core/url","core/str"],(function($,Templates,Notification,CalendarRepository,CalendarEvents,CalendarViewManager,CalendarCrud,CalendarSelectors,Url,Str){var SELECTORS_DAY="[data-region='day']",SELECTORS_DAY_CONTENT="[data-region='day-content']",SELECTORS_LOADING_ICON=".loading-icon",SELECTORS_VIEW_DAY_LINK="[data-action='view-day-link']",SELECTORS_CALENDAR_MONTH_WRAPPER=".calendarwrapper",SELECTORS_SCREEN_READER_ANNOUNCEMENTS=".calendar-announcements",SELECTORS_CURRENT_MONTH=".calendar-controls .current",handleMoveEvent=function(e,eventId,originElement,destinationElement){var originTimestamp=null,destinationTimestamp=destinationElement.attr("data-day-timestamp");originElement&&(originTimestamp=originElement.attr("data-day-timestamp")),originElement&&originTimestamp==destinationTimestamp||Templates.render("core/loading",{}).then((function(html,js){destinationElement.find(SELECTORS_DAY_CONTENT).addClass("hidden"),Templates.appendNodeContents(destinationElement,html,js),originElement&&(originElement.find(SELECTORS_DAY_CONTENT).addClass("hidden"),Templates.appendNodeContents(originElement,html,js))})).then((function(){return CalendarRepository.updateEventStartDay(eventId,destinationTimestamp)})).then((function(){$("body").trigger(CalendarEvents.eventMoved,[eventId,originElement,destinationElement])})).always((function(){var destinationLoadingElement=destinationElement.find(SELECTORS_LOADING_ICON);if(destinationElement.find(SELECTORS_DAY_CONTENT).removeClass("hidden"),Templates.replaceNode(destinationLoadingElement,"",""),originElement){var originLoadingElement=originElement.find(SELECTORS_LOADING_ICON);originElement.find(SELECTORS_DAY_CONTENT).removeClass("hidden"),Templates.replaceNode(originLoadingElement,"","")}})).catch(Notification.exception)},registerEventListeners=function(root,isCalendarBlock){const viewingFullCalendar=document.getElementById(CalendarSelectors.fullCalendarView);root.on("click",SELECTORS_VIEW_DAY_LINK,(function(e){var dayLink=$(e.target).closest(SELECTORS_VIEW_DAY_LINK),year=dayLink.data("year"),month=dayLink.data("month"),day=dayLink.data("day"),courseId=dayLink.data("courseid"),categoryId=dayLink.data("categoryid");const urlParams={view:"day",time:dayLink.data("timestamp"),course:courseId};if(viewingFullCalendar){const urlParamString=Object.entries(urlParams).map((_ref=>{let[key,value]=_ref;return"".concat(encodeURIComponent(key),"=").concat(encodeURIComponent(value))})).join("&");CalendarViewManager.refreshDayContent(root,year,month,day,courseId,categoryId,root,"core_calendar/calendar_day",isCalendarBlock).then((function(){e.preventDefault(),isCalendarBlock||CalendarViewManager.updateUrl("?"+urlParamString)})).catch(Notification.exception)}else window.location.assign(Url.relativeUrl("calendar/view.php",urlParams))})),root.on("change",CalendarSelectors.elements.courseSelector,(function(){var selectElement=$(this),courseId=selectElement.val();const courseName=$("option:selected",selectElement).text();CalendarViewManager.reloadCurrentMonth(root,courseId,null).then((function(){return root.find(CalendarSelectors.elements.courseSelector).val(courseId)})).then((function(){CalendarViewManager.updateUrl("?view=month&course="+courseId),CalendarViewManager.handleCourseChange(Number(courseId),courseName)})).catch(Notification.exception)}));var eventFormPromise=CalendarCrud.registerEventFormModal(root),contextId=$(SELECTORS_CALENDAR_MONTH_WRAPPER).data("context-id");!function(root,eventFormModalPromise){var body=$("body");body.on(CalendarEvents.created,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.deleted,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.updated,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.editActionEvent,(function(e,url){window.location.assign(url)})),body.on(CalendarEvents.moveEvent,handleMoveEvent),body.on(CalendarEvents.eventMoved,(function(){CalendarViewManager.reloadCurrentMonth(root)})),body.on(CalendarEvents.monthChanged,root,(async function(){const monthName=body.find(SELECTORS_CURRENT_MONTH).text(),monthAnnoucement=await Str.get_string("newmonthannouncement","calendar",monthName);body.find(SELECTORS_SCREEN_READER_ANNOUNCEMENTS).html(monthAnnoucement)})),CalendarCrud.registerEditListeners(root,eventFormModalPromise)}(root,eventFormPromise),contextId&&root.on("click",SELECTORS_DAY,(function(e){var target=$(e.target);const displayingSmallBlockCalendar="side-pre"===root.parents("aside").data("blockregion");if(!viewingFullCalendar&&displayingSmallBlockCalendar){const dateContainer=target.closest(SELECTORS_DAY),courseId=target.closest(CalendarSelectors.wrapper).data("courseid"),params={view:"day",time:dateContainer.data("day-timestamp"),course:courseId};window.location.assign(Url.relativeUrl("calendar/view.php",params))}else{if(!target.closest(SELECTORS_VIEW_DAY_LINK).length){var startTime=$(this).attr("data-new-event-timestamp");eventFormPromise.then((function(modal){var wrapper=target.closest(CalendarSelectors.wrapper);modal.setCourseId(wrapper.data("courseid"));var categoryId=wrapper.data("categoryid");void 0!==categoryId&&modal.setCategoryId(categoryId),modal.setContextId(wrapper.data("contextId")),modal.setStartTime(startTime),modal.show()})).catch(Notification.exception)}}e.preventDefault()}))};return{init:function(root){let isCalendarBlock=arguments.length>1&&void 0!==arguments[1]&&arguments[1];root=$(root),CalendarViewManager.init(root,"month",isCalendarBlock),registerEventListeners(root,isCalendarBlock)}}})); //# sourceMappingURL=calendar.min.js.map \ No newline at end of file diff --git a/calendar/amd/build/calendar.min.js.map b/calendar/amd/build/calendar.min.js.map index ce0ac0f82e0..621e8998b97 100644 --- a/calendar/amd/build/calendar.min.js.map +++ b/calendar/amd/build/calendar.min.js.map @@ -1 +1 @@ -{"version":3,"file":"calendar.min.js","sources":["../src/calendar.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 .\n\n/**\n * This module is the highest level module for the calendar. It is\n * responsible for initialising all of the components required for\n * the calendar to run. It also coordinates the interaction between\n * components by listening for and responding to different events\n * triggered within the calendar UI.\n *\n * @module core_calendar/calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/crud',\n 'core_calendar/selectors',\n 'core/config',\n 'core/url',\n 'core/str',\n],\nfunction(\n $,\n Templates,\n Notification,\n CalendarRepository,\n CalendarEvents,\n CalendarViewManager,\n CalendarCrud,\n CalendarSelectors,\n Config,\n Url,\n Str,\n) {\n\n var SELECTORS = {\n ROOT: \"[data-region='calendar']\",\n DAY: \"[data-region='day']\",\n NEW_EVENT_BUTTON: \"[data-action='new-event-button']\",\n DAY_CONTENT: \"[data-region='day-content']\",\n LOADING_ICON: '.loading-icon',\n VIEW_DAY_LINK: \"[data-action='view-day-link']\",\n CALENDAR_MONTH_WRAPPER: \".calendarwrapper\",\n TODAY: '.today',\n DAY_NUMBER_CIRCLE: '.day-number-circle',\n DAY_NUMBER: '.day-number',\n SCREEN_READER_ANNOUNCEMENTS: '.calendar-announcements',\n CURRENT_MONTH: '.calendar-controls .current'\n };\n\n /**\n * Handler for the drag and drop move event. Provides a loading indicator\n * while the request is sent to the server to update the event start date.\n *\n * Triggers a eventMoved calendar javascript event if the event was successfully\n * updated.\n *\n * @param {event} e The calendar move event\n * @param {int} eventId The event id being moved\n * @param {object|null} originElement The jQuery element for where the event is moving from\n * @param {object} destinationElement The jQuery element for where the event is moving to\n */\n var handleMoveEvent = function(e, eventId, originElement, destinationElement) {\n var originTimestamp = null;\n var destinationTimestamp = destinationElement.attr('data-day-timestamp');\n\n if (originElement) {\n originTimestamp = originElement.attr('data-day-timestamp');\n }\n\n // If the event has actually changed day.\n if (!originElement || originTimestamp != destinationTimestamp) {\n Templates.render('core/loading', {})\n .then(function(html, js) {\n // First we show some loading icons in each of the days being affected.\n destinationElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(destinationElement, html, js);\n\n if (originElement) {\n originElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(originElement, html, js);\n }\n return;\n })\n .then(function() {\n // Send a request to the server to make the change.\n return CalendarRepository.updateEventStartDay(eventId, destinationTimestamp);\n })\n .then(function() {\n // If the update was successful then broadcast an event letting the calendar\n // know that an event has been moved.\n $('body').trigger(CalendarEvents.eventMoved, [eventId, originElement, destinationElement]);\n return;\n })\n .always(function() {\n // Always remove the loading icons regardless of whether the update\n // request was successful or not.\n var destinationLoadingElement = destinationElement.find(SELECTORS.LOADING_ICON);\n destinationElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(destinationLoadingElement, '', '');\n\n if (originElement) {\n var originLoadingElement = originElement.find(SELECTORS.LOADING_ICON);\n originElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(originLoadingElement, '', '');\n }\n return;\n })\n .catch(Notification.exception);\n }\n };\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n * @param {object} eventFormModalPromise A promise reolved with the event form modal\n */\n var registerCalendarEventListeners = function(root, eventFormModalPromise) {\n var body = $('body');\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.editActionEvent, function(e, url) {\n // Action events needs to be edit directly on the course module.\n window.location.assign(url);\n });\n // Handle the event fired by the drag and drop code.\n body.on(CalendarEvents.moveEvent, handleMoveEvent);\n // When an event is successfully moved we should updated the UI.\n body.on(CalendarEvents.eventMoved, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n // Announce the newly loaded month to screen readers.\n body.on(CalendarEvents.monthChanged, root, async function() {\n const monthName = body.find(SELECTORS.CURRENT_MONTH).text();\n const monthAnnoucement = await Str.get_string('newmonthannouncement', 'calendar', monthName);\n body.find(SELECTORS.SCREEN_READER_ANNOUNCEMENTS).html(monthAnnoucement);\n });\n\n CalendarCrud.registerEditListeners(root, eventFormModalPromise);\n };\n\n /**\n * Register event listeners for the module.\n *\n * @param {object} root The calendar root element\n */\n var registerEventListeners = function(root) {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n // Listen the click on the day link to render the day view.\n root.on('click', SELECTORS.VIEW_DAY_LINK, function(e) {\n var dayLink = $(e.target).closest(SELECTORS.VIEW_DAY_LINK);\n var year = dayLink.data('year'),\n month = dayLink.data('month'),\n day = dayLink.data('day'),\n courseId = dayLink.data('courseid'),\n categoryId = dayLink.data('categoryid');\n const urlParams = {\n view: 'day',\n time: dayLink.data('timestamp'),\n course: courseId,\n };\n if (viewingFullCalendar) {\n // Construct the URL parameter string from the urlParams object.\n const urlParamString = Object.entries(urlParams)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&');\n CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root,\n 'core_calendar/calendar_day').then(function() {\n e.preventDefault();\n return CalendarViewManager.updateUrl(urlParamString);\n }).catch(Notification.exception);\n } else {\n window.location.assign(Url.relativeUrl('calendar/view.php', urlParams));\n }\n });\n\n root.on('change', CalendarSelectors.elements.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n const courseName = $(\"option:selected\", selectElement).text();\n CalendarViewManager.reloadCurrentMonth(root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.elements.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=month&course=' + courseId);\n CalendarViewManager.handleCourseChange(Number(courseId), courseName);\n return;\n })\n .catch(Notification.exception);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root),\n contextId = $(SELECTORS.CALENDAR_MONTH_WRAPPER).data('context-id');\n registerCalendarEventListeners(root, eventFormPromise);\n\n if (contextId) {\n // Bind click events to calendar days.\n root.on('click', SELECTORS.DAY, function(e) {\n var target = $(e.target);\n const displayingSmallBlockCalendar = root.parents('aside').data('blockregion') === 'side-pre';\n\n if (!viewingFullCalendar && displayingSmallBlockCalendar) {\n const dateContainer = target.closest(SELECTORS.DAY);\n const wrapper = target.closest(CalendarSelectors.wrapper);\n const courseId = wrapper.data('courseid');\n const params = {\n view: 'day',\n time: dateContainer.data('day-timestamp'),\n course: courseId,\n };\n window.location.assign(Url.relativeUrl('calendar/view.php', params));\n } else {\n const hasViewDayLink = target.closest(SELECTORS.VIEW_DAY_LINK).length;\n const shouldShowNewEventModal = !hasViewDayLink;\n if (shouldShowNewEventModal) {\n var startTime = $(this).attr('data-new-event-timestamp');\n eventFormPromise.then(function(modal) {\n var wrapper = target.closest(CalendarSelectors.wrapper);\n modal.setCourseId(wrapper.data('courseid'));\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setStartTime(startTime);\n modal.show();\n return;\n }).catch(Notification.exception);\n }\n }\n e.preventDefault();\n });\n }\n };\n\n return {\n init: function(root) {\n root = $(root);\n CalendarViewManager.init(root);\n registerEventListeners(root);\n }\n };\n});\n"],"names":["define","$","Templates","Notification","CalendarRepository","CalendarEvents","CalendarViewManager","CalendarCrud","CalendarSelectors","Config","Url","Str","SELECTORS","handleMoveEvent","e","eventId","originElement","destinationElement","originTimestamp","destinationTimestamp","attr","render","then","html","js","find","addClass","appendNodeContents","updateEventStartDay","trigger","eventMoved","always","destinationLoadingElement","removeClass","replaceNode","originLoadingElement","catch","exception","registerEventListeners","root","viewingFullCalendar","document","getElementById","fullCalendarView","on","dayLink","target","closest","year","data","month","day","courseId","categoryId","urlParams","view","time","course","urlParamString","Object","entries","map","_ref","key","value","encodeURIComponent","join","refreshDayContent","preventDefault","updateUrl","window","location","assign","relativeUrl","elements","courseSelector","selectElement","this","val","courseName","text","reloadCurrentMonth","handleCourseChange","Number","eventFormPromise","registerEventFormModal","contextId","eventFormModalPromise","body","created","deleted","updated","editActionEvent","url","moveEvent","monthChanged","async","monthName","monthAnnoucement","get_string","registerEditListeners","registerCalendarEventListeners","displayingSmallBlockCalendar","parents","dateContainer","wrapper","params","length","startTime","modal","setCourseId","setCategoryId","setContextId","setStartTime","show","init"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"calendar.min.js","sources":["../src/calendar.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 .\n\n/**\n * This module is the highest level module for the calendar. It is\n * responsible for initialising all of the components required for\n * the calendar to run. It also coordinates the interaction between\n * components by listening for and responding to different events\n * triggered within the calendar UI.\n *\n * @module core_calendar/calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'core_calendar/repository',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/crud',\n 'core_calendar/selectors',\n 'core/url',\n 'core/str',\n],\nfunction(\n $,\n Templates,\n Notification,\n CalendarRepository,\n CalendarEvents,\n CalendarViewManager,\n CalendarCrud,\n CalendarSelectors,\n Url,\n Str,\n) {\n\n var SELECTORS = {\n ROOT: \"[data-region='calendar']\",\n DAY: \"[data-region='day']\",\n NEW_EVENT_BUTTON: \"[data-action='new-event-button']\",\n DAY_CONTENT: \"[data-region='day-content']\",\n LOADING_ICON: '.loading-icon',\n VIEW_DAY_LINK: \"[data-action='view-day-link']\",\n CALENDAR_MONTH_WRAPPER: \".calendarwrapper\",\n TODAY: '.today',\n DAY_NUMBER_CIRCLE: '.day-number-circle',\n DAY_NUMBER: '.day-number',\n SCREEN_READER_ANNOUNCEMENTS: '.calendar-announcements',\n CURRENT_MONTH: '.calendar-controls .current'\n };\n\n /**\n * Handler for the drag and drop move event. Provides a loading indicator\n * while the request is sent to the server to update the event start date.\n *\n * Triggers a eventMoved calendar javascript event if the event was successfully\n * updated.\n *\n * @param {event} e The calendar move event\n * @param {int} eventId The event id being moved\n * @param {object|null} originElement The jQuery element for where the event is moving from\n * @param {object} destinationElement The jQuery element for where the event is moving to\n */\n var handleMoveEvent = function(e, eventId, originElement, destinationElement) {\n var originTimestamp = null;\n var destinationTimestamp = destinationElement.attr('data-day-timestamp');\n\n if (originElement) {\n originTimestamp = originElement.attr('data-day-timestamp');\n }\n\n // If the event has actually changed day.\n if (!originElement || originTimestamp != destinationTimestamp) {\n Templates.render('core/loading', {})\n .then(function(html, js) {\n // First we show some loading icons in each of the days being affected.\n destinationElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(destinationElement, html, js);\n\n if (originElement) {\n originElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');\n Templates.appendNodeContents(originElement, html, js);\n }\n return;\n })\n .then(function() {\n // Send a request to the server to make the change.\n return CalendarRepository.updateEventStartDay(eventId, destinationTimestamp);\n })\n .then(function() {\n // If the update was successful then broadcast an event letting the calendar\n // know that an event has been moved.\n $('body').trigger(CalendarEvents.eventMoved, [eventId, originElement, destinationElement]);\n return;\n })\n .always(function() {\n // Always remove the loading icons regardless of whether the update\n // request was successful or not.\n var destinationLoadingElement = destinationElement.find(SELECTORS.LOADING_ICON);\n destinationElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(destinationLoadingElement, '', '');\n\n if (originElement) {\n var originLoadingElement = originElement.find(SELECTORS.LOADING_ICON);\n originElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');\n Templates.replaceNode(originLoadingElement, '', '');\n }\n return;\n })\n .catch(Notification.exception);\n }\n };\n\n /**\n * Listen to and handle any calendar events fired by the calendar UI.\n *\n * @method registerCalendarEventListeners\n * @param {object} root The calendar root element\n * @param {object} eventFormModalPromise A promise reolved with the event form modal\n */\n var registerCalendarEventListeners = function(root, eventFormModalPromise) {\n var body = $('body');\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n body.on(CalendarEvents.editActionEvent, function(e, url) {\n // Action events needs to be edit directly on the course module.\n window.location.assign(url);\n });\n // Handle the event fired by the drag and drop code.\n body.on(CalendarEvents.moveEvent, handleMoveEvent);\n // When an event is successfully moved we should updated the UI.\n body.on(CalendarEvents.eventMoved, function() {\n CalendarViewManager.reloadCurrentMonth(root);\n });\n // Announce the newly loaded month to screen readers.\n body.on(CalendarEvents.monthChanged, root, async function() {\n const monthName = body.find(SELECTORS.CURRENT_MONTH).text();\n const monthAnnoucement = await Str.get_string('newmonthannouncement', 'calendar', monthName);\n body.find(SELECTORS.SCREEN_READER_ANNOUNCEMENTS).html(monthAnnoucement);\n });\n\n CalendarCrud.registerEditListeners(root, eventFormModalPromise);\n };\n\n /**\n * Register event listeners for the module.\n *\n * @param {object} root The calendar root element\n * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.\n */\n var registerEventListeners = function(root, isCalendarBlock) {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n // Listen the click on the day link to render the day view.\n root.on('click', SELECTORS.VIEW_DAY_LINK, function(e) {\n var dayLink = $(e.target).closest(SELECTORS.VIEW_DAY_LINK);\n var year = dayLink.data('year'),\n month = dayLink.data('month'),\n day = dayLink.data('day'),\n courseId = dayLink.data('courseid'),\n categoryId = dayLink.data('categoryid');\n const urlParams = {\n view: 'day',\n time: dayLink.data('timestamp'),\n course: courseId,\n };\n if (viewingFullCalendar) {\n // Construct the URL parameter string from the urlParams object.\n const urlParamString = Object.entries(urlParams)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&');\n CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root,\n 'core_calendar/calendar_day', isCalendarBlock).then(function() {\n e.preventDefault();\n // Update the URL if it's not calendar block.\n if (!isCalendarBlock) {\n CalendarViewManager.updateUrl('?' + urlParamString);\n }\n return;\n }).catch(Notification.exception);\n } else {\n window.location.assign(Url.relativeUrl('calendar/view.php', urlParams));\n }\n });\n\n root.on('change', CalendarSelectors.elements.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n const courseName = $(\"option:selected\", selectElement).text();\n CalendarViewManager.reloadCurrentMonth(root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.elements.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=month&course=' + courseId);\n CalendarViewManager.handleCourseChange(Number(courseId), courseName);\n return;\n })\n .catch(Notification.exception);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root),\n contextId = $(SELECTORS.CALENDAR_MONTH_WRAPPER).data('context-id');\n registerCalendarEventListeners(root, eventFormPromise);\n\n if (contextId) {\n // Bind click events to calendar days.\n root.on('click', SELECTORS.DAY, function(e) {\n var target = $(e.target);\n const displayingSmallBlockCalendar = root.parents('aside').data('blockregion') === 'side-pre';\n\n if (!viewingFullCalendar && displayingSmallBlockCalendar) {\n const dateContainer = target.closest(SELECTORS.DAY);\n const wrapper = target.closest(CalendarSelectors.wrapper);\n const courseId = wrapper.data('courseid');\n const params = {\n view: 'day',\n time: dateContainer.data('day-timestamp'),\n course: courseId,\n };\n window.location.assign(Url.relativeUrl('calendar/view.php', params));\n } else {\n const hasViewDayLink = target.closest(SELECTORS.VIEW_DAY_LINK).length;\n const shouldShowNewEventModal = !hasViewDayLink;\n if (shouldShowNewEventModal) {\n var startTime = $(this).attr('data-new-event-timestamp');\n eventFormPromise.then(function(modal) {\n var wrapper = target.closest(CalendarSelectors.wrapper);\n modal.setCourseId(wrapper.data('courseid'));\n\n var categoryId = wrapper.data('categoryid');\n if (typeof categoryId !== 'undefined') {\n modal.setCategoryId(categoryId);\n }\n\n modal.setContextId(wrapper.data('contextId'));\n modal.setStartTime(startTime);\n modal.show();\n return;\n }).catch(Notification.exception);\n }\n }\n e.preventDefault();\n });\n }\n };\n\n return {\n /**\n * Initializes the calendar view manager and registers event listeners.\n *\n * @param {HTMLElement} root - The root element where the calendar view manager and event listeners will be attached.\n * @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block.\n */\n init: function(root, isCalendarBlock = false) {\n root = $(root);\n CalendarViewManager.init(root, 'month', isCalendarBlock);\n registerEventListeners(root, isCalendarBlock);\n }\n };\n});\n"],"names":["define","$","Templates","Notification","CalendarRepository","CalendarEvents","CalendarViewManager","CalendarCrud","CalendarSelectors","Url","Str","SELECTORS","handleMoveEvent","e","eventId","originElement","destinationElement","originTimestamp","destinationTimestamp","attr","render","then","html","js","find","addClass","appendNodeContents","updateEventStartDay","trigger","eventMoved","always","destinationLoadingElement","removeClass","replaceNode","originLoadingElement","catch","exception","registerEventListeners","root","isCalendarBlock","viewingFullCalendar","document","getElementById","fullCalendarView","on","dayLink","target","closest","year","data","month","day","courseId","categoryId","urlParams","view","time","course","urlParamString","Object","entries","map","_ref","key","value","encodeURIComponent","join","refreshDayContent","preventDefault","updateUrl","window","location","assign","relativeUrl","elements","courseSelector","selectElement","this","val","courseName","text","reloadCurrentMonth","handleCourseChange","Number","eventFormPromise","registerEventFormModal","contextId","eventFormModalPromise","body","created","deleted","updated","editActionEvent","url","moveEvent","monthChanged","async","monthName","monthAnnoucement","get_string","registerEditListeners","registerCalendarEventListeners","displayingSmallBlockCalendar","parents","dateContainer","wrapper","params","length","startTime","modal","setCourseId","setCategoryId","setContextId","setStartTime","show","init"],"mappings":"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"} \ No newline at end of file diff --git a/calendar/amd/build/calendar_view.min.js b/calendar/amd/build/calendar_view.min.js index ea95fe5c921..7036b14f612 100644 --- a/calendar/amd/build/calendar_view.min.js +++ b/calendar/amd/build/calendar_view.min.js @@ -5,6 +5,6 @@ * @copyright 2017 Simey Lameze * @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 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)}}})); +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){var registerEventListeners=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)};return{init:function(root,type){let isCalendarBlock=arguments.length>2&&void 0!==arguments[2]&&arguments[2];root=$(root),CalendarViewManager.init(root,type,isCalendarBlock),registerEventListeners(root,type)}}})); //# sourceMappingURL=calendar_view.min.js.map \ No newline at end of file diff --git a/calendar/amd/build/calendar_view.min.js.map b/calendar/amd/build/calendar_view.min.js.map index 62d6024ba40..ff5df73ff6b 100644 --- a/calendar/amd/build/calendar_view.min.js.map +++ b/calendar/amd/build/calendar_view.min.js.map @@ -1 +1 @@ -{"version":3,"file":"calendar_view.min.js","sources":["../src/calendar_view.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 .\n\n/**\n * This module is responsible for handle calendar day and upcoming view.\n *\n * @module core_calendar/calendar_view\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/crud'\n],\nfunction(\n $,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager,\n CalendarCrud\n) {\n\n var registerEventListeners = function(root, type) {\n var body = $('body');\n\n CalendarCrud.registerRemove(root);\n\n var reloadFunction = 'reloadCurrent' + type.charAt(0).toUpperCase() + type.slice(1);\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager[reloadFunction](root);\n });\n\n root.on('change', CalendarSelectors.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n const courseName = $(\"option:selected\", selectElement).text();\n CalendarViewManager[reloadFunction](root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=' + type + '&course=' + courseId);\n CalendarViewManager.handleCourseChange(Number(courseId), courseName);\n return;\n })\n .fail(Notification.exception);\n });\n\n body.on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n if (data.hidden == true) {\n daysWithEvent.addClass('hidden');\n } else {\n daysWithEvent.removeClass('hidden');\n }\n CalendarViewManager.foldDayEvents(root);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root);\n CalendarCrud.registerEditListeners(root, eventFormPromise);\n };\n\n return {\n init: function(root, type) {\n root = $(root);\n\n CalendarViewManager.init(root, type);\n registerEventListeners(root, type);\n }\n };\n });\n"],"names":["define","$","Notification","CalendarSelectors","CalendarEvents","CalendarViewManager","CalendarCrud","init","root","type","body","registerRemove","reloadFunction","charAt","toUpperCase","slice","on","created","deleted","updated","courseSelector","selectElement","this","courseId","val","courseName","text","then","find","updateUrl","handleCourseChange","Number","fail","exception","filterChanged","e","data","daysWithEvent","eventType","hidden","addClass","removeClass","foldDayEvents","eventFormPromise","registerEventFormModal","registerEditListeners","registerEventListeners"],"mappings":";;;;;;;AAsBAA,qCAAO,CACH,SACA,oBACA,0BACA,uBACA,6BACA,uBAEJ,SACIC,EACAC,aACAC,kBACAC,eACAC,oBACAC,oBAmDW,CACHC,KAAM,SAASC,KAAMC,MACjBD,KAAOP,EAAEO,MAETH,oBAAoBE,KAAKC,KAAMC,MApDV,SAASD,KAAMC,UACpCC,KAAOT,EAAE,QAEbK,aAAaK,eAAeH,UAExBI,eAAiB,gBAAkBH,KAAKI,OAAO,GAAGC,cAAgBL,KAAKM,MAAM,GAEjFL,KAAKM,GAAGZ,eAAea,SAAS,WAC5BZ,oBAAoBO,gBAAgBJ,SAExCE,KAAKM,GAAGZ,eAAec,SAAS,WAC5Bb,oBAAoBO,gBAAgBJ,SAExCE,KAAKM,GAAGZ,eAAee,SAAS,WAC5Bd,oBAAoBO,gBAAgBJ,SAGxCA,KAAKQ,GAAG,SAAUb,kBAAkBiB,gBAAgB,eAC5CC,cAAgBpB,EAAEqB,MAClBC,SAAWF,cAAcG,YACvBC,WAAaxB,EAAE,kBAAmBoB,eAAeK,OACvDrB,oBAAoBO,gBAAgBJ,KAAMe,SAAU,MAC/CI,MAAK,kBAEKnB,KAAKoB,KAAKzB,kBAAkBiB,gBAAgBI,IAAID,aAE1DI,MAAK,WACFtB,oBAAoBwB,UAAU,SAAWpB,KAAO,WAAac,UAC7DlB,oBAAoByB,mBAAmBC,OAAOR,UAAWE,eAG5DO,KAAK9B,aAAa+B,cAG3BvB,KAAKM,GAAGZ,eAAe8B,eAAe,SAASC,EAAGC,UAC1CC,cAAgB7B,KAAKoB,KAAKzB,kBAAkBmC,UAAUF,KAAK3B,OAC5C,GAAf2B,KAAKG,OACLF,cAAcG,SAAS,UAEvBH,cAAcI,YAAY,UAE9BpC,oBAAoBqC,cAAclC,aAGlCmC,iBAAmBrC,aAAasC,uBAAuBpC,MAC3DF,aAAauC,sBAAsBrC,KAAMmC,kBAQrCG,CAAuBtC,KAAMC"} \ No newline at end of file +{"version":3,"file":"calendar_view.min.js","sources":["../src/calendar_view.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 .\n\n/**\n * This module is responsible for handle calendar day and upcoming view.\n *\n * @module core_calendar/calendar_view\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/crud'\n],\nfunction(\n $,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager,\n CalendarCrud\n) {\n\n var registerEventListeners = function(root, type) {\n var body = $('body');\n\n CalendarCrud.registerRemove(root);\n\n var reloadFunction = 'reloadCurrent' + type.charAt(0).toUpperCase() + type.slice(1);\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager[reloadFunction](root);\n });\n\n root.on('change', CalendarSelectors.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n const courseName = $(\"option:selected\", selectElement).text();\n CalendarViewManager[reloadFunction](root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=' + type + '&course=' + courseId);\n CalendarViewManager.handleCourseChange(Number(courseId), courseName);\n return;\n })\n .fail(Notification.exception);\n });\n\n body.on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n if (data.hidden == true) {\n daysWithEvent.addClass('hidden');\n } else {\n daysWithEvent.removeClass('hidden');\n }\n CalendarViewManager.foldDayEvents(root);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root);\n CalendarCrud.registerEditListeners(root, eventFormPromise);\n };\n\n return {\n init: function(root, type, isCalendarBlock = false) {\n root = $(root);\n\n CalendarViewManager.init(root, type, isCalendarBlock);\n registerEventListeners(root, type, isCalendarBlock);\n }\n };\n });\n"],"names":["define","$","Notification","CalendarSelectors","CalendarEvents","CalendarViewManager","CalendarCrud","registerEventListeners","root","type","body","registerRemove","reloadFunction","charAt","toUpperCase","slice","on","created","deleted","updated","courseSelector","selectElement","this","courseId","val","courseName","text","then","find","updateUrl","handleCourseChange","Number","fail","exception","filterChanged","e","data","daysWithEvent","eventType","hidden","addClass","removeClass","foldDayEvents","eventFormPromise","registerEventFormModal","registerEditListeners","init","isCalendarBlock"],"mappings":";;;;;;;AAsBAA,qCAAO,CACH,SACA,oBACA,0BACA,uBACA,6BACA,uBAEJ,SACIC,EACAC,aACAC,kBACAC,eACAC,oBACAC,kBAGQC,uBAAyB,SAASC,KAAMC,UACpCC,KAAOT,EAAE,QAEbK,aAAaK,eAAeH,UAExBI,eAAiB,gBAAkBH,KAAKI,OAAO,GAAGC,cAAgBL,KAAKM,MAAM,GAEjFL,KAAKM,GAAGZ,eAAea,SAAS,WAC5BZ,oBAAoBO,gBAAgBJ,SAExCE,KAAKM,GAAGZ,eAAec,SAAS,WAC5Bb,oBAAoBO,gBAAgBJ,SAExCE,KAAKM,GAAGZ,eAAee,SAAS,WAC5Bd,oBAAoBO,gBAAgBJ,SAGxCA,KAAKQ,GAAG,SAAUb,kBAAkBiB,gBAAgB,eAC5CC,cAAgBpB,EAAEqB,MAClBC,SAAWF,cAAcG,YACvBC,WAAaxB,EAAE,kBAAmBoB,eAAeK,OACvDrB,oBAAoBO,gBAAgBJ,KAAMe,SAAU,MAC/CI,MAAK,kBAEKnB,KAAKoB,KAAKzB,kBAAkBiB,gBAAgBI,IAAID,aAE1DI,MAAK,WACFtB,oBAAoBwB,UAAU,SAAWpB,KAAO,WAAac,UAC7DlB,oBAAoByB,mBAAmBC,OAAOR,UAAWE,eAG5DO,KAAK9B,aAAa+B,cAG3BvB,KAAKM,GAAGZ,eAAe8B,eAAe,SAASC,EAAGC,UAC1CC,cAAgB7B,KAAKoB,KAAKzB,kBAAkBmC,UAAUF,KAAK3B,OAC5C,GAAf2B,KAAKG,OACLF,cAAcG,SAAS,UAEvBH,cAAcI,YAAY,UAE9BpC,oBAAoBqC,cAAclC,aAGlCmC,iBAAmBrC,aAAasC,uBAAuBpC,MAC3DF,aAAauC,sBAAsBrC,KAAMmC,yBAGtC,CACHG,KAAM,SAAStC,KAAMC,UAAMsC,wEACvBvC,KAAOP,EAAEO,MAETH,oBAAoByC,KAAKtC,KAAMC,KAAMsC,iBACrCxC,uBAAuBC,KAAMC"} \ No newline at end of file diff --git a/calendar/amd/build/popover.min.js b/calendar/amd/build/popover.min.js index e7c42111597..a7a5bf451fe 100644 --- a/calendar/amd/build/popover.min.js +++ b/calendar/amd/build/popover.min.js @@ -6,6 +6,6 @@ define("core_calendar/popover",["theme_boost/popover","jquery","core_calendar/se * @copyright 2021 Huong Nguyen * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since 4.0 - */function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj},CalendarSelectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(CalendarSelectors);const isPopoverConfigured=new Map,showPopover=target=>{const dateContainer=target.closest(CalendarSelectors.elements.dateContainer);if(!isPopoverConfigured.has(dateContainer)){(0,_jquery.default)(target).popover({trigger:"manual",placement:"top",html:!0,title:dateContainer.dataset.title,content:()=>{const source=(0,_jquery.default)(dateContainer).find(CalendarSelectors.elements.dateContent),content=(0,_jquery.default)("
");if(source.length){const temptContent=source.find(".hidden").clone(!1);content.html(temptContent.html())}return content.html()}}),isPopoverConfigured.set(dateContainer,!0)}(dateContainer=>"none"===window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display)(dateContainer)&&((0,_jquery.default)(target).popover("show"),target.addEventListener("mouseleave",hidePopover),target.addEventListener("focusout",hidePopover))},hidePopover=e=>{const target=e.target,dateContainer=e.target.closest(CalendarSelectors.elements.dateContainer);if(dateContainer&&isPopoverConfigured.has(dateContainer)){const isTargetActive=target.contains(document.activeElement),isTargetHover=target.matches(":hover");isTargetActive||isTargetHover||((0,_jquery.default)(target).popover("hide"),target.removeEventListener("mouseleave",hidePopover),target.removeEventListener("focusout",hidePopover))}};let listenersRegistered=!1;listenersRegistered||((()=>{const showPopoverHandler=e=>{const dayLink=e.target.closest(CalendarSelectors.links.dayLink);dayLink&&(e.preventDefault(),showPopover(dayLink))};document.addEventListener("mouseover",showPopoverHandler),document.addEventListener("focusin",showPopoverHandler)})(),listenersRegistered=!0)})); + */function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj},CalendarSelectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(CalendarSelectors);const isPopoverConfigured=new Map,showPopover=target=>{const dateContainer=target.closest(CalendarSelectors.elements.dateContainer);if(!isPopoverConfigured.has(dateContainer)){(0,_jquery.default)(target).popover({trigger:"manual",placement:"top",html:!0,title:dateContainer.dataset.title,content:()=>{const source=(0,_jquery.default)(dateContainer).find(CalendarSelectors.elements.dateContent),content=(0,_jquery.default)("
");if(source.length){const temptContent=source.find(".hidden").clone(!1);content.html(temptContent.html())}return content.html()},animation:!1}),isPopoverConfigured.set(dateContainer,!0)}(dateContainer=>"none"===window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display)(dateContainer)&&((0,_jquery.default)(target).popover("show"),target.addEventListener("mouseleave",hidePopover),target.addEventListener("focusout",hidePopover),target.addEventListener("click",hidePopover))},hidePopover=e=>{const target=e.target,dateContainer=e.target.closest(CalendarSelectors.elements.dateContainer);if(dateContainer&&isPopoverConfigured.has(dateContainer)){const isTargetActive=target.contains(document.activeElement),isTargetHover=target.matches(":hover"),isTargetClicked=document.activeElement.contains(target);let removeListener=!0;isTargetActive||isTargetHover?isTargetClicked?(0,_jquery.default)(document.activeElement).popover("hide"):removeListener=!1:(0,_jquery.default)(target).popover("hide"),removeListener&&(target.removeEventListener("mouseleave",hidePopover),target.removeEventListener("focusout",hidePopover),target.removeEventListener("click",hidePopover))}};let listenersRegistered=!1;listenersRegistered||((()=>{const showPopoverHandler=e=>{const dayLink=e.target.closest(CalendarSelectors.links.dayLink);dayLink&&(e.preventDefault(),showPopover(dayLink))};document.addEventListener("mouseover",showPopoverHandler),document.addEventListener("focusin",showPopoverHandler)})(),listenersRegistered=!0)})); //# sourceMappingURL=popover.min.js.map \ No newline at end of file diff --git a/calendar/amd/build/popover.min.js.map b/calendar/amd/build/popover.min.js.map index abf62598844..1d406bf8da5 100644 --- a/calendar/amd/build/popover.min.js.map +++ b/calendar/amd/build/popover.min.js.map @@ -1 +1 @@ -{"version":3,"file":"popover.min.js","sources":["../src/popover.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 .\n\n/**\n * Javascript popover for the `core_calendar` subsystem.\n *\n * @module core_calendar/popover\n * @copyright 2021 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport 'theme_boost/popover';\nimport jQuery from 'jquery';\nimport * as CalendarSelectors from 'core_calendar/selectors';\n\n/**\n * Check if we are allowing to enable the popover or not.\n * @param {Element} dateContainer\n * @returns {boolean}\n */\nconst isPopoverAvailable = (dateContainer) => {\n return window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display === 'none';\n};\n\nconst isPopoverConfigured = new Map();\n\nconst showPopover = target => {\n const dateContainer = target.closest(CalendarSelectors.elements.dateContainer);\n if (!isPopoverConfigured.has(dateContainer)) {\n const dateEle = jQuery(target);\n dateEle.popover({\n trigger: 'manual',\n placement: 'top',\n html: true,\n title: dateContainer.dataset.title,\n content: () => {\n const source = jQuery(dateContainer).find(CalendarSelectors.elements.dateContent);\n const content = jQuery('
');\n if (source.length) {\n const temptContent = source.find('.hidden').clone(false);\n content.html(temptContent.html());\n }\n return content.html();\n }\n });\n\n isPopoverConfigured.set(dateContainer, true);\n }\n\n if (isPopoverAvailable(dateContainer)) {\n jQuery(target).popover('show');\n target.addEventListener('mouseleave', hidePopover);\n target.addEventListener('focusout', hidePopover);\n }\n};\n\nconst hidePopover = e => {\n const target = e.target;\n const dateContainer = e.target.closest(CalendarSelectors.elements.dateContainer);\n if (!dateContainer) {\n return;\n }\n if (isPopoverConfigured.has(dateContainer)) {\n const isTargetActive = target.contains(document.activeElement);\n const isTargetHover = target.matches(':hover');\n if (!isTargetActive && !isTargetHover) {\n jQuery(target).popover('hide');\n target.removeEventListener('mouseleave', hidePopover);\n target.removeEventListener('focusout', hidePopover);\n }\n }\n};\n\n/**\n * Register events for date container.\n */\nconst registerEventListeners = () => {\n const showPopoverHandler = (e) => {\n const dayLink = e.target.closest(CalendarSelectors.links.dayLink);\n if (!dayLink) {\n return;\n }\n\n e.preventDefault();\n showPopover(dayLink);\n };\n\n document.addEventListener('mouseover', showPopoverHandler);\n document.addEventListener('focusin', showPopoverHandler);\n};\n\nlet listenersRegistered = false;\nif (!listenersRegistered) {\n registerEventListeners();\n listenersRegistered = true;\n}\n"],"names":["isPopoverConfigured","Map","showPopover","target","dateContainer","closest","CalendarSelectors","elements","has","popover","trigger","placement","html","title","dataset","content","source","find","dateContent","length","temptContent","clone","set","window","getComputedStyle","querySelector","display","isPopoverAvailable","addEventListener","hidePopover","e","isTargetActive","contains","document","activeElement","isTargetHover","matches","removeEventListener","listenersRegistered","showPopoverHandler","dayLink","links","preventDefault","registerEventListeners"],"mappings":";;;;;;;;wgCAqCMA,oBAAsB,IAAIC,IAE1BC,YAAcC,eACVC,cAAgBD,OAAOE,QAAQC,kBAAkBC,SAASH,mBAC3DJ,oBAAoBQ,IAAIJ,eAAgB,EACzB,mBAAOD,QACfM,QAAQ,CACZC,QAAS,SACTC,UAAW,MACXC,MAAM,EACNC,MAAOT,cAAcU,QAAQD,MAC7BE,QAAS,WACCC,QAAS,mBAAOZ,eAAea,KAAKX,kBAAkBC,SAASW,aAC/DH,SAAU,mBAAO,YACnBC,OAAOG,OAAQ,OACTC,aAAeJ,OAAOC,KAAK,WAAWI,OAAM,GAClDN,QAAQH,KAAKQ,aAAaR,eAEvBG,QAAQH,UAIvBZ,oBAAoBsB,IAAIlB,eAAe,GA1BnBA,CAAAA,eACwF,SAAzGmB,OAAOC,iBAAiBpB,cAAcqB,cAAcnB,kBAAkBC,SAASW,cAAcQ,QA4BhGC,CAAmBvB,qCACZD,QAAQM,QAAQ,QACvBN,OAAOyB,iBAAiB,aAAcC,aACtC1B,OAAOyB,iBAAiB,WAAYC,eAItCA,YAAcC,UACV3B,OAAS2B,EAAE3B,OACXC,cAAgB0B,EAAE3B,OAAOE,QAAQC,kBAAkBC,SAASH,kBAC7DA,eAGDJ,oBAAoBQ,IAAIJ,eAAgB,OAClC2B,eAAiB5B,OAAO6B,SAASC,SAASC,eAC1CC,cAAgBhC,OAAOiC,QAAQ,UAChCL,gBAAmBI,oCACbhC,QAAQM,QAAQ,QACvBN,OAAOkC,oBAAoB,aAAcR,aACzC1B,OAAOkC,oBAAoB,WAAYR,oBAuB/CS,qBAAsB,EACrBA,sBAhB0B,YACrBC,mBAAsBT,UAClBU,QAAUV,EAAE3B,OAAOE,QAAQC,kBAAkBmC,MAAMD,SACpDA,UAILV,EAAEY,iBACFxC,YAAYsC,WAGhBP,SAASL,iBAAiB,YAAaW,oBACvCN,SAASL,iBAAiB,UAAWW,qBAKrCI,GACAL,qBAAsB"} \ No newline at end of file +{"version":3,"file":"popover.min.js","sources":["../src/popover.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 .\n\n/**\n * Javascript popover for the `core_calendar` subsystem.\n *\n * @module core_calendar/popover\n * @copyright 2021 Huong Nguyen \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport 'theme_boost/popover';\nimport jQuery from 'jquery';\nimport * as CalendarSelectors from 'core_calendar/selectors';\n\n/**\n * Check if we are allowing to enable the popover or not.\n * @param {Element} dateContainer\n * @returns {boolean}\n */\nconst isPopoverAvailable = (dateContainer) => {\n return window.getComputedStyle(dateContainer.querySelector(CalendarSelectors.elements.dateContent)).display === 'none';\n};\n\nconst isPopoverConfigured = new Map();\n\nconst showPopover = target => {\n const dateContainer = target.closest(CalendarSelectors.elements.dateContainer);\n if (!isPopoverConfigured.has(dateContainer)) {\n const dateEle = jQuery(target);\n dateEle.popover({\n trigger: 'manual',\n placement: 'top',\n html: true,\n title: dateContainer.dataset.title,\n content: () => {\n const source = jQuery(dateContainer).find(CalendarSelectors.elements.dateContent);\n const content = jQuery('
');\n if (source.length) {\n const temptContent = source.find('.hidden').clone(false);\n content.html(temptContent.html());\n }\n return content.html();\n },\n 'animation': false,\n });\n\n isPopoverConfigured.set(dateContainer, true);\n }\n\n if (isPopoverAvailable(dateContainer)) {\n jQuery(target).popover('show');\n target.addEventListener('mouseleave', hidePopover);\n target.addEventListener('focusout', hidePopover);\n // Set up the hide function to the click event type.\n target.addEventListener('click', hidePopover);\n }\n};\n\nconst hidePopover = e => {\n const target = e.target;\n const dateContainer = e.target.closest(CalendarSelectors.elements.dateContainer);\n if (!dateContainer) {\n return;\n }\n if (isPopoverConfigured.has(dateContainer)) {\n const isTargetActive = target.contains(document.activeElement);\n const isTargetHover = target.matches(':hover');\n\n // Checks if a target element is clicked or pressed.\n const isTargetClicked = document.activeElement.contains(target);\n\n let removeListener = true;\n if (!isTargetActive && !isTargetHover) {\n jQuery(target).popover('hide');\n } else if (isTargetClicked) {\n jQuery(document.activeElement).popover('hide');\n } else {\n removeListener = false;\n }\n\n if (removeListener) {\n target.removeEventListener('mouseleave', hidePopover);\n target.removeEventListener('focusout', hidePopover);\n target.removeEventListener('click', hidePopover);\n }\n }\n};\n\n/**\n * Register events for date container.\n */\nconst registerEventListeners = () => {\n const showPopoverHandler = (e) => {\n const dayLink = e.target.closest(CalendarSelectors.links.dayLink);\n if (!dayLink) {\n return;\n }\n\n e.preventDefault();\n showPopover(dayLink);\n };\n\n document.addEventListener('mouseover', showPopoverHandler);\n document.addEventListener('focusin', showPopoverHandler);\n};\n\nlet listenersRegistered = false;\nif (!listenersRegistered) {\n registerEventListeners();\n listenersRegistered = true;\n}\n"],"names":["isPopoverConfigured","Map","showPopover","target","dateContainer","closest","CalendarSelectors","elements","has","popover","trigger","placement","html","title","dataset","content","source","find","dateContent","length","temptContent","clone","set","window","getComputedStyle","querySelector","display","isPopoverAvailable","addEventListener","hidePopover","e","isTargetActive","contains","document","activeElement","isTargetHover","matches","isTargetClicked","removeListener","removeEventListener","listenersRegistered","showPopoverHandler","dayLink","links","preventDefault","registerEventListeners"],"mappings":";;;;;;;;wgCAqCMA,oBAAsB,IAAIC,IAE1BC,YAAcC,eACVC,cAAgBD,OAAOE,QAAQC,kBAAkBC,SAASH,mBAC3DJ,oBAAoBQ,IAAIJ,eAAgB,EACzB,mBAAOD,QACfM,QAAQ,CACZC,QAAS,SACTC,UAAW,MACXC,MAAM,EACNC,MAAOT,cAAcU,QAAQD,MAC7BE,QAAS,WACCC,QAAS,mBAAOZ,eAAea,KAAKX,kBAAkBC,SAASW,aAC/DH,SAAU,mBAAO,YACnBC,OAAOG,OAAQ,OACTC,aAAeJ,OAAOC,KAAK,WAAWI,OAAM,GAClDN,QAAQH,KAAKQ,aAAaR,eAEvBG,QAAQH,mBAEN,IAGjBZ,oBAAoBsB,IAAIlB,eAAe,GA3BnBA,CAAAA,eACwF,SAAzGmB,OAAOC,iBAAiBpB,cAAcqB,cAAcnB,kBAAkBC,SAASW,cAAcQ,QA6BhGC,CAAmBvB,qCACZD,QAAQM,QAAQ,QACvBN,OAAOyB,iBAAiB,aAAcC,aACtC1B,OAAOyB,iBAAiB,WAAYC,aAEpC1B,OAAOyB,iBAAiB,QAASC,eAInCA,YAAcC,UACV3B,OAAS2B,EAAE3B,OACXC,cAAgB0B,EAAE3B,OAAOE,QAAQC,kBAAkBC,SAASH,kBAC7DA,eAGDJ,oBAAoBQ,IAAIJ,eAAgB,OAClC2B,eAAiB5B,OAAO6B,SAASC,SAASC,eAC1CC,cAAgBhC,OAAOiC,QAAQ,UAG/BC,gBAAkBJ,SAASC,cAAcF,SAAS7B,YAEpDmC,gBAAiB,EAChBP,gBAAmBI,cAEbE,oCACAJ,SAASC,eAAezB,QAAQ,QAEvC6B,gBAAiB,sBAJVnC,QAAQM,QAAQ,QAOvB6B,iBACAnC,OAAOoC,oBAAoB,aAAcV,aACzC1B,OAAOoC,oBAAoB,WAAYV,aACvC1B,OAAOoC,oBAAoB,QAASV,oBAuB5CW,qBAAsB,EACrBA,sBAhB0B,YACrBC,mBAAsBX,UAClBY,QAAUZ,EAAE3B,OAAOE,QAAQC,kBAAkBqC,MAAMD,SACpDA,UAILZ,EAAEc,iBACF1C,YAAYwC,WAGhBT,SAASL,iBAAiB,YAAaa,oBACvCR,SAASL,iBAAiB,UAAWa,qBAKrCI,GACAL,qBAAsB"} \ No newline at end of file diff --git a/calendar/amd/build/view_manager.min.js b/calendar/amd/build/view_manager.min.js index 10e3eab5f11..f7f4660c298 100644 --- a/calendar/amd/build/view_manager.min.js +++ b/calendar/amd/build/view_manager.min.js @@ -5,6 +5,6 @@ define("core_calendar/view_manager",["exports","jquery","core/templates","core/n * @module core_calendar/view_manager * @copyright 2017 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.updateUrl=_exports.reloadCurrentUpcoming=_exports.reloadCurrentMonth=_exports.reloadCurrentDay=_exports.registerEventListenersForMonthDetailed=_exports.refreshMonthContent=_exports.refreshDayContent=_exports.init=_exports.handleCourseChange=_exports.foldDayEvents=_exports.changeMonth=_exports.changeDay=void 0,_jquery=_interopRequireDefault(_jquery),_templates=_interopRequireDefault(_templates),_notification=_interopRequireDefault(_notification),CalendarRepository=_interopRequireWildcard(CalendarRepository),_events=_interopRequireDefault(_events),CalendarSelectors=_interopRequireWildcard(CalendarSelectors),_modal_events=_interopRequireDefault(_modal_events),_summary_modal=_interopRequireDefault(_summary_modal),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),_pending=_interopRequireDefault(_pending),_url=_interopRequireDefault(_url),_config=_interopRequireDefault(_config);const foldDayEvents=()=>{const days=(0,_jquery.default)(CalendarSelectors.elements.monthDetailed).find(CalendarSelectors.day);0!==days.length&&days.each((function(){const dayContainer=(0,_jquery.default)(this),eventsSelector="".concat(CalendarSelectors.elements.dateContent," ul li[data-event-eventtype]"),filteredEventsSelector="".concat(CalendarSelectors.elements.dateContent,' ul li[data-event-filtered="true"]'),moreEventsSelector="".concat(CalendarSelectors.elements.dateContent,' [data-action="view-more-events"]'),events=dayContainer.find(eventsSelector);if(0===events.length)return;const numberOfFiltered=dayContainer.find(filteredEventsSelector).length,numberOfEvents=events.length-numberOfFiltered;let count=1;events.each((function(){const event=(0,_jquery.default)(this);"true"!==event.attr("data-event-filtered")?count>5-(5===numberOfEvents?0:1)?(event.attr("data-event-folded","true"),event.hide()):(event.attr("data-event-folded","false"),event.show(),count++):event.attr("data-event-folded","false")}));const moreEventsLink=dayContainer.find(moreEventsSelector);if(numberOfEvents>5){const numberOfHiddenEvents=numberOfEvents-5+1;moreEventsLink.show(),(0,_str.getString)("moreevents","calendar",numberOfHiddenEvents).then((str=>{const link=moreEventsLink.find("strong a");return moreEventsLink.attr("data-event-folded","false"),link.text(str),str})).catch(_notification.default.exception)}else moreEventsLink.hide()}))};_exports.foldDayEvents=foldDayEvents;const registerEventListenersForMonthDetailed=pendingId=>{const events="".concat(_events.default.viewUpdated);(0,_jquery.default)("body").on(events,(function(e){foldDayEvents()})),foldDayEvents(),(0,_jquery.default)("body").on(_events.default.filterChanged,(function(e,data){const root=(0,_jquery.default)(CalendarSelectors.elements.monthDetailed),pending=new _pending.default(pendingId),target=root.find(CalendarSelectors.eventType[data.type]),transitionPromise=_jquery.default.Deferred();data.hidden?transitionPromise.then((function(){return target.attr("data-event-filtered","true"),target.hide().promise()})).fail():transitionPromise.then((function(){return target.attr("data-event-filtered","false"),target.show().promise()})).fail(),transitionPromise.then((function(){foldDayEvents()})).always(pending.resolve).fail(),transitionPromise.resolve()}))};_exports.registerEventListenersForMonthDetailed=registerEventListenersForMonthDetailed;const refreshMonthContent=function(root,year,month,courseId,categoryId){let target=arguments.length>5&&void 0!==arguments[5]?arguments[5]:null,template=arguments.length>6&&void 0!==arguments[6]?arguments[6]:"",day=arguments.length>7&&void 0!==arguments[7]?arguments[7]:1;startLoading(root),target=target||root.find(CalendarSelectors.wrapper),template=template||root.attr("data-template"),M.util.js_pending([root.get("id"),year,month,courseId].join("-"));const includenavigation=root.data("includenavigation"),mini=root.data("mini"),viewMode=target.data("view");return CalendarRepository.getCalendarMonthData(year,month,courseId,categoryId,includenavigation,mini,day,viewMode).then((context=>_templates.default.render(template,context))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((()=>(M.util.js_complete([root.get("id"),year,month,courseId].join("-")),stopLoading(root)))).fail(_notification.default.exception)};_exports.refreshMonthContent=refreshMonthContent;const changeMonth=function(root,url,year,month,courseId,categoryId){let day=arguments.length>6&&void 0!==arguments[6]?arguments[6]:1;return refreshMonthContent(root,year,month,courseId,categoryId,null,"",day).then((function(){url.length&&"#"!==url&&updateUrl(url);for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++)args[_key]=arguments[_key];return args})).then((function(){(0,_jquery.default)("body").trigger(_events.default.monthChanged,[year,month,courseId,categoryId]);for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++)args[_key2]=arguments[_key2];return args}))};_exports.changeMonth=changeMonth;_exports.reloadCurrentMonth=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const year=root.find(CalendarSelectors.wrapper).data("year"),month=root.find(CalendarSelectors.wrapper).data("month"),day=root.find(CalendarSelectors.wrapper).data("day");return courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),refreshMonthContent(root,year,month,courseId,categoryId,null,"",day).then((function(){(0,_jquery.default)("body").trigger(_events.default.courseChanged,[year,month,courseId,categoryId]);for(var _len3=arguments.length,args=new Array(_len3),_key3=0;_key3<_len3;_key3++)args[_key3]=arguments[_key3];return args}))};const refreshDayContent=function(root,year,month,day,courseId,categoryId){let target=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,template=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"";startLoading(root),target&&0!=target.length||(target=root.find(CalendarSelectors.wrapper)),template=template||root.attr("data-template"),M.util.js_pending([root.get("id"),year,month,day,courseId,categoryId].join("-"));const includenavigation=root.data("includenavigation");return CalendarRepository.getCalendarDayData(year,month,day,courseId,categoryId,includenavigation).then((context=>(context.viewingday=!0,context.showviewselector=!0,_templates.default.render(template,context)))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((()=>(M.util.js_complete([root.get("id"),year,month,day,courseId,categoryId].join("-")),stopLoading(root)))).fail(_notification.default.exception)};_exports.refreshDayContent=refreshDayContent;_exports.reloadCurrentDay=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const wrapper=root.find(CalendarSelectors.wrapper),year=wrapper.data("year"),month=wrapper.data("month"),day=wrapper.data("day");return courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),refreshDayContent(root,year,month,day,courseId,categoryId)};const changeDay=(root,url,year,month,day,courseId,categoryId)=>refreshDayContent(root,year,month,day,courseId,categoryId).then((function(){url.length&&"#"!==url&&updateUrl(url);for(var _len4=arguments.length,args=new Array(_len4),_key4=0;_key4<_len4;_key4++)args[_key4]=arguments[_key4];return args})).then((function(){(0,_jquery.default)("body").trigger(_events.default.dayChanged,[year,month,courseId,categoryId]);for(var _len5=arguments.length,args=new Array(_len5),_key5=0;_key5<_len5;_key5++)args[_key5]=arguments[_key5];return args}));_exports.changeDay=changeDay;const updateUrl=url=>{document.getElementById(CalendarSelectors.fullCalendarView)&&window.history.pushState({},"",url)};_exports.updateUrl=updateUrl;const startLoading=root=>{root.find(CalendarSelectors.containers.loadingIcon).removeClass("hidden")},stopLoading=root=>{root.find(CalendarSelectors.containers.loadingIcon).addClass("hidden")},reloadCurrentUpcoming=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,target=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,template=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"";return startLoading(root),target=target||root.find(CalendarSelectors.wrapper),template=template||root.attr("data-template"),courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),CalendarRepository.getCalendarUpcomingData(courseId,categoryId).then((context=>(context.viewingupcoming=!0,context.showviewselector=!0,_templates.default.render(template,context)))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((function(){return stopLoading(root)})).fail(_notification.default.exception)};_exports.reloadCurrentUpcoming=reloadCurrentUpcoming;const renderEventSummaryModal=eventId=>{const pendingPromise=new _pending.default("core_calendar/view_manager:renderEventSummaryModal");return CalendarRepository.getEventById(eventId).then((getEventResponse=>{if(!getEventResponse.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+eventId);return getEventResponse.event})).then((eventData=>{const modalParams={title:eventData.name,body:_templates.default.render("core_calendar/event_summary_body",eventData),templateContext:{canedit:eventData.canedit,candelete:eventData.candelete,headerclasses:(eventType=eventData.normalisedeventtype,"calendar_event_"+eventType),isactionevent:eventData.isactionevent,url:eventData.url,action:eventData.action}};var eventType;return _summary_modal.default.create(modalParams)})).then((modal=>(modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal.show(),modal))).then((modal=>(pendingPromise.resolve(),modal))).catch(_notification.default.exception)};_exports.init=(root,view)=>{(0,_prefetch.prefetchStrings)("calendar",["moreevents"]),foldDayEvents(),(root=>{(root=(0,_jquery.default)(root)).on("click",CalendarSelectors.links.eventLink,(e=>{const target=e.target;let eventLink=null,eventId=null;const pendingPromise=new _pending.default("core_calendar/view_manager:eventLink:click");eventLink=target.matches(CalendarSelectors.actions.viewEvent)?target:target.closest(CalendarSelectors.actions.viewEvent),eventId=eventLink?eventLink.dataset.eventId:target.querySelector(CalendarSelectors.actions.viewEvent).dataset.eventId,eventId?(e.preventDefault(),e.stopPropagation(),renderEventSummaryModal(eventId).then(pendingPromise.resolve).catch()):pendingPromise.resolve()})),root.on("click",CalendarSelectors.links.navLink,(e=>{const wrapper=root.find(CalendarSelectors.wrapper),view=wrapper.data("view"),courseId=wrapper.data("courseid"),categoryId=wrapper.data("categoryid"),link=e.currentTarget;"month"===view||"monthblock"===view?(changeMonth(root,link.href,link.dataset.year,link.dataset.month,courseId,categoryId,link.dataset.day),e.preventDefault()):"day"===view&&(changeDay(root,link.href,link.dataset.year,link.dataset.month,link.dataset.day,courseId,categoryId),e.preventDefault())}));const viewSelector=root.find(CalendarSelectors.viewSelector);_custom_interaction_events.default.define(viewSelector,[_custom_interaction_events.default.events.activate]),viewSelector.on(_custom_interaction_events.default.events.activate,(e=>{e.preventDefault();const option=e.target;if(option.classList.contains("active"))return;const view=option.dataset.view,year=option.dataset.year,month=option.dataset.month,day=option.dataset.day,courseId=option.dataset.courseid,categoryId=option.dataset.categoryid;"month"==view?refreshMonthContent(root,year,month,courseId,categoryId,root,"core_calendar/calendar_month",day).then((()=>{updateUrl("?view=month&course="+courseId)})).fail(_notification.default.exception):"day"==view?refreshDayContent(root,year,month,day,courseId,categoryId,root,"core_calendar/calendar_day").then((()=>{updateUrl("?view=day&course="+courseId)})).fail(_notification.default.exception):"upcoming"==view&&reloadCurrentUpcoming(root,courseId,categoryId,root,"core_calendar/calendar_upcoming").then((()=>{updateUrl("?view=upcoming&course="+courseId)})).fail(_notification.default.exception)}))})(root);const calendarTable=root.find(CalendarSelectors.elements.monthDetailed);if(calendarTable.length){"month-detailed-".concat(calendarTable.id,"-filterChanged");registerEventListenersForMonthDetailed(calendarTable)}};_exports.handleCourseChange=async(courseId,courseName)=>{document.querySelector(CalendarSelectors.viewSelector+" ul").querySelectorAll("li a").forEach((element=>{element.setAttribute("data-courseid",courseId)}));const calendar=await(0,_str.getString)("calendar","calendar"),pageHeaderHeadingsElement=document.querySelector(CalendarSelectors.pageHeaderHeadings),courseUrl=_url.default.relativeUrl("/course/view.php",{id:courseId});courseId!==_config.default.siteId?pageHeaderHeadingsElement.innerHTML=calendar+': '+courseName+"":pageHeaderHeadingsElement.innerHTML=calendar}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.updateUrl=_exports.reloadCurrentUpcoming=_exports.reloadCurrentMonth=_exports.reloadCurrentDay=_exports.registerEventListenersForMonthDetailed=_exports.refreshMonthContent=_exports.refreshDayContent=_exports.init=_exports.handleCourseChange=_exports.foldDayEvents=_exports.changeMonth=_exports.changeDay=void 0,_jquery=_interopRequireDefault(_jquery),_templates=_interopRequireDefault(_templates),_notification=_interopRequireDefault(_notification),CalendarRepository=_interopRequireWildcard(CalendarRepository),_events=_interopRequireDefault(_events),CalendarSelectors=_interopRequireWildcard(CalendarSelectors),_modal_events=_interopRequireDefault(_modal_events),_summary_modal=_interopRequireDefault(_summary_modal),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),_pending=_interopRequireDefault(_pending),_url=_interopRequireDefault(_url),_config=_interopRequireDefault(_config);const foldDayEvents=()=>{const days=(0,_jquery.default)(CalendarSelectors.elements.monthDetailed).find(CalendarSelectors.day);0!==days.length&&days.each((function(){const dayContainer=(0,_jquery.default)(this),eventsSelector="".concat(CalendarSelectors.elements.dateContent," ul li[data-event-eventtype]"),filteredEventsSelector="".concat(CalendarSelectors.elements.dateContent,' ul li[data-event-filtered="true"]'),moreEventsSelector="".concat(CalendarSelectors.elements.dateContent,' [data-action="view-more-events"]'),events=dayContainer.find(eventsSelector);if(0===events.length)return;const numberOfFiltered=dayContainer.find(filteredEventsSelector).length,numberOfEvents=events.length-numberOfFiltered;let count=1;events.each((function(){const event=(0,_jquery.default)(this);"true"!==event.attr("data-event-filtered")?count>5-(5===numberOfEvents?0:1)?(event.attr("data-event-folded","true"),event.hide()):(event.attr("data-event-folded","false"),event.show(),count++):event.attr("data-event-folded","false")}));const moreEventsLink=dayContainer.find(moreEventsSelector);if(numberOfEvents>5){const numberOfHiddenEvents=numberOfEvents-5+1;moreEventsLink.show(),(0,_str.getString)("moreevents","calendar",numberOfHiddenEvents).then((str=>{const link=moreEventsLink.find("strong a");return moreEventsLink.attr("data-event-folded","false"),link.text(str),str})).catch(_notification.default.exception)}else moreEventsLink.hide()}))};_exports.foldDayEvents=foldDayEvents;const registerEventListenersForMonthDetailed=pendingId=>{const events="".concat(_events.default.viewUpdated);(0,_jquery.default)("body").on(events,(function(e){foldDayEvents()})),foldDayEvents(),(0,_jquery.default)("body").on(_events.default.filterChanged,(function(e,data){const root=(0,_jquery.default)(CalendarSelectors.elements.monthDetailed),pending=new _pending.default(pendingId),target=root.find(CalendarSelectors.eventType[data.type]),transitionPromise=_jquery.default.Deferred();data.hidden?transitionPromise.then((function(){return target.attr("data-event-filtered","true"),target.hide().promise()})).fail():transitionPromise.then((function(){return target.attr("data-event-filtered","false"),target.show().promise()})).fail(),transitionPromise.then((function(){foldDayEvents()})).always(pending.resolve).fail(),transitionPromise.resolve()}))};_exports.registerEventListenersForMonthDetailed=registerEventListenersForMonthDetailed;const refreshMonthContent=function(root,year,month,courseId,categoryId){let target=arguments.length>5&&void 0!==arguments[5]?arguments[5]:null,template=arguments.length>6&&void 0!==arguments[6]?arguments[6]:"",day=arguments.length>7&&void 0!==arguments[7]?arguments[7]:1;startLoading(root),target=target||root.find(CalendarSelectors.wrapper),template=template||root.attr("data-template"),M.util.js_pending([root.get("id"),year,month,courseId].join("-"));const includenavigation=root.data("includenavigation"),mini=root.data("mini"),viewMode=target.data("view");return CalendarRepository.getCalendarMonthData(year,month,courseId,categoryId,includenavigation,mini,day,viewMode).then((context=>_templates.default.render(template,context))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((()=>(M.util.js_complete([root.get("id"),year,month,courseId].join("-")),stopLoading(root)))).fail(_notification.default.exception)};_exports.refreshMonthContent=refreshMonthContent;const changeMonth=function(root,url,year,month,courseId,categoryId){let day=arguments.length>6&&void 0!==arguments[6]?arguments[6]:1,isCalendarBlock=arguments.length>7&&void 0!==arguments[7]&&arguments[7];return refreshMonthContent(root,year,month,courseId,categoryId,null,"",day).then((function(){url.length&&"#"!==url&&!isCalendarBlock&&updateUrl(url);for(var _len=arguments.length,args=new Array(_len),_key=0;_key<_len;_key++)args[_key]=arguments[_key];return args})).then((function(){(0,_jquery.default)("body").trigger(_events.default.monthChanged,[year,month,courseId,categoryId,day,isCalendarBlock]);for(var _len2=arguments.length,args=new Array(_len2),_key2=0;_key2<_len2;_key2++)args[_key2]=arguments[_key2];return args}))};_exports.changeMonth=changeMonth;_exports.reloadCurrentMonth=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const year=root.find(CalendarSelectors.wrapper).data("year"),month=root.find(CalendarSelectors.wrapper).data("month"),day=root.find(CalendarSelectors.wrapper).data("day");return courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),refreshMonthContent(root,year,month,courseId,categoryId,null,"",day).then((function(){(0,_jquery.default)("body").trigger(_events.default.courseChanged,[year,month,courseId,categoryId]);for(var _len3=arguments.length,args=new Array(_len3),_key3=0;_key3<_len3;_key3++)args[_key3]=arguments[_key3];return args}))};const refreshDayContent=function(root,year,month,day,courseId,categoryId){let target=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,template=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"",isCalendarBlock=arguments.length>8&&void 0!==arguments[8]&&arguments[8];startLoading(root),target&&0!=target.length||(target=root.find(CalendarSelectors.wrapper)),template=template||root.attr("data-template"),M.util.js_pending([root.get("id"),year,month,day,courseId,categoryId].join("-"));const includenavigation=root.data("includenavigation");return CalendarRepository.getCalendarDayData(year,month,day,courseId,categoryId,includenavigation).then((context=>(context.viewingday=!0,context.showviewselector=!0,context.iscalendarblock=isCalendarBlock,_templates.default.render(template,context)))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((()=>(M.util.js_complete([root.get("id"),year,month,day,courseId,categoryId].join("-")),stopLoading(root)))).fail(_notification.default.exception)};_exports.refreshDayContent=refreshDayContent;_exports.reloadCurrentDay=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const wrapper=root.find(CalendarSelectors.wrapper),year=wrapper.data("year"),month=wrapper.data("month"),day=wrapper.data("day");return courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),refreshDayContent(root,year,month,day,courseId,categoryId)};const changeDay=function(root,url,year,month,day,courseId,categoryId){let isCalendarBlock=arguments.length>7&&void 0!==arguments[7]&&arguments[7];return refreshDayContent(root,year,month,day,courseId,categoryId,null,"",isCalendarBlock).then((function(){url.length&&"#"!==url&&!isCalendarBlock&&updateUrl(url);for(var _len4=arguments.length,args=new Array(_len4),_key4=0;_key4<_len4;_key4++)args[_key4]=arguments[_key4];return args})).then((function(){(0,_jquery.default)("body").trigger(_events.default.dayChanged,[year,month,courseId,categoryId,isCalendarBlock]);for(var _len5=arguments.length,args=new Array(_len5),_key5=0;_key5<_len5;_key5++)args[_key5]=arguments[_key5];return args}))};_exports.changeDay=changeDay;const updateUrl=url=>{document.getElementById(CalendarSelectors.fullCalendarView)&&window.history.pushState({},"",url)};_exports.updateUrl=updateUrl;const startLoading=root=>{root.find(CalendarSelectors.containers.loadingIcon).removeClass("hidden")},stopLoading=root=>{root.find(CalendarSelectors.containers.loadingIcon).addClass("hidden")},reloadCurrentUpcoming=function(root){let courseId=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,categoryId=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,target=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,template=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"";return startLoading(root),target=target||root.find(CalendarSelectors.wrapper),template=template||root.attr("data-template"),courseId=courseId||root.find(CalendarSelectors.wrapper).data("courseid"),categoryId=categoryId||root.find(CalendarSelectors.wrapper).data("categoryid"),CalendarRepository.getCalendarUpcomingData(courseId,categoryId).then((context=>(context.viewingupcoming=!0,context.showviewselector=!0,_templates.default.render(template,context)))).then(((html,js)=>_templates.default.replaceNode(target,html,js))).then((()=>{document.querySelector("body").dispatchEvent(new CustomEvent(_events.default.viewUpdated))})).always((function(){return stopLoading(root)})).fail(_notification.default.exception)};_exports.reloadCurrentUpcoming=reloadCurrentUpcoming;const renderEventSummaryModal=eventId=>{const pendingPromise=new _pending.default("core_calendar/view_manager:renderEventSummaryModal");return CalendarRepository.getEventById(eventId).then((getEventResponse=>{if(!getEventResponse.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+eventId);return getEventResponse.event})).then((eventData=>{const modalParams={title:eventData.name,body:_templates.default.render("core_calendar/event_summary_body",eventData),templateContext:{canedit:eventData.canedit,candelete:eventData.candelete,headerclasses:(eventType=eventData.normalisedeventtype,"calendar_event_"+eventType),isactionevent:eventData.isactionevent,url:eventData.url,action:eventData.action}};var eventType;return _summary_modal.default.create(modalParams)})).then((modal=>(modal.getRoot().on(_modal_events.default.hidden,(function(){modal.destroy()})),modal.show(),modal))).then((modal=>(pendingPromise.resolve(),modal))).catch(_notification.default.exception)};_exports.init=(root,view,isCalendarBlock)=>{(0,_prefetch.prefetchStrings)("calendar",["moreevents"]),foldDayEvents(),((root,isCalendarBlock)=>{(root=(0,_jquery.default)(root)).on("click",CalendarSelectors.links.eventLink,(e=>{const target=e.target;let eventLink=null,eventId=null;const pendingPromise=new _pending.default("core_calendar/view_manager:eventLink:click");eventLink=target.matches(CalendarSelectors.actions.viewEvent)?target:target.closest(CalendarSelectors.actions.viewEvent),eventId=eventLink?eventLink.dataset.eventId:target.querySelector(CalendarSelectors.actions.viewEvent).dataset.eventId,eventId?(e.preventDefault(),e.stopPropagation(),renderEventSummaryModal(eventId).then(pendingPromise.resolve).catch()):pendingPromise.resolve()})),root.on("click",CalendarSelectors.links.navLink,(e=>{const wrapper=root.find(CalendarSelectors.wrapper),view=wrapper.data("view"),courseId=wrapper.data("courseid"),categoryId=wrapper.data("categoryid"),link=e.currentTarget;"month"===view||"monthblock"===view?(changeMonth(root,link.href,link.dataset.year,link.dataset.month,courseId,categoryId,link.dataset.day,isCalendarBlock),e.preventDefault()):"day"===view&&(changeDay(root,link.href,link.dataset.year,link.dataset.month,link.dataset.day,courseId,categoryId,isCalendarBlock),e.preventDefault())}));const viewSelector=root.find(CalendarSelectors.viewSelector);_custom_interaction_events.default.define(viewSelector,[_custom_interaction_events.default.events.activate]),viewSelector.on(_custom_interaction_events.default.events.activate,(e=>{e.preventDefault();const option=e.target;if(option.classList.contains("active"))return;const view=option.dataset.view,year=option.dataset.year,month=option.dataset.month,day=option.dataset.day,courseId=option.dataset.courseid,categoryId=option.dataset.categoryid;"month"==view?refreshMonthContent(root,year,month,courseId,categoryId,root,"core_calendar/calendar_month",day).then((()=>{updateUrl("?view=month&course="+courseId)})).fail(_notification.default.exception):"day"==view?refreshDayContent(root,year,month,day,courseId,categoryId,root,"core_calendar/calendar_day").then((()=>{updateUrl("?view=day&course="+courseId)})).fail(_notification.default.exception):"upcoming"==view&&reloadCurrentUpcoming(root,courseId,categoryId,root,"core_calendar/calendar_upcoming").then((()=>{updateUrl("?view=upcoming&course="+courseId)})).fail(_notification.default.exception)}))})(root,isCalendarBlock);const calendarTable=root.find(CalendarSelectors.elements.monthDetailed);if(calendarTable.length){"month-detailed-".concat(calendarTable.id,"-filterChanged");registerEventListenersForMonthDetailed(calendarTable)}};_exports.handleCourseChange=async(courseId,courseName)=>{document.querySelector(CalendarSelectors.viewSelector+" ul").querySelectorAll("li a").forEach((element=>{element.setAttribute("data-courseid",courseId)}));const calendar=await(0,_str.getString)("calendar","calendar"),pageHeaderHeadingsElement=document.querySelector(CalendarSelectors.pageHeaderHeadings),courseUrl=_url.default.relativeUrl("/course/view.php",{id:courseId});courseId!==_config.default.siteId?pageHeaderHeadingsElement.innerHTML=calendar+': '+courseName+"":pageHeaderHeadingsElement.innerHTML=calendar}})); //# sourceMappingURL=view_manager.min.js.map \ No newline at end of file diff --git a/calendar/amd/build/view_manager.min.js.map b/calendar/amd/build/view_manager.min.js.map index 6e84fa0ed87..01bd18866d2 100644 --- a/calendar/amd/build/view_manager.min.js.map +++ b/calendar/amd/build/view_manager.min.js.map @@ -1 +1 @@ -{"version":3,"file":"view_manager.min.js","sources":["../src/view_manager.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 .\n\n/**\n * A javascript module to handler calendar view changes.\n *\n * @module core_calendar/view_manager\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Templates from 'core/templates';\nimport Notification from 'core/notification';\nimport * as CalendarRepository from 'core_calendar/repository';\nimport CalendarEvents from 'core_calendar/events';\nimport * as CalendarSelectors from 'core_calendar/selectors';\nimport ModalEvents from 'core/modal_events';\nimport SummaryModal from 'core_calendar/summary_modal';\nimport CustomEvents from 'core/custom_interaction_events';\nimport {getString} from 'core/str';\nimport Pending from 'core/pending';\nimport {prefetchStrings} from 'core/prefetch';\nimport Url from 'core/url';\nimport Config from 'core/config';\n\n/**\n * Limit number of events per day\n *\n */\nconst LIMIT_DAY_EVENTS = 5;\n\n/**\n * Hide day events if more than 5.\n *\n */\nexport const foldDayEvents = () => {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const days = root.find(CalendarSelectors.day);\n if (days.length === 0) {\n return;\n }\n days.each(function() {\n const dayContainer = $(this);\n const eventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-eventtype]`;\n const filteredEventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-filtered=\"true\"]`;\n const moreEventsSelector = `${CalendarSelectors.elements.dateContent} [data-action=\"view-more-events\"]`;\n const events = dayContainer.find(eventsSelector);\n if (events.length === 0) {\n return;\n }\n\n const filteredEvents = dayContainer.find(filteredEventsSelector);\n const numberOfFiltered = filteredEvents.length;\n const numberOfEvents = events.length - numberOfFiltered;\n\n let count = 1;\n events.each(function() {\n const event = $(this);\n const isNotFiltered = event.attr('data-event-filtered') !== 'true';\n const offset = (numberOfEvents === LIMIT_DAY_EVENTS) ? 0 : 1;\n if (isNotFiltered) {\n if (count > LIMIT_DAY_EVENTS - offset) {\n event.attr('data-event-folded', 'true');\n event.hide();\n } else {\n event.attr('data-event-folded', 'false');\n event.show();\n count++;\n }\n } else {\n // It's being filtered out.\n event.attr('data-event-folded', 'false');\n }\n });\n\n const moreEventsLink = dayContainer.find(moreEventsSelector);\n if (numberOfEvents > LIMIT_DAY_EVENTS) {\n const numberOfHiddenEvents = numberOfEvents - LIMIT_DAY_EVENTS + 1;\n moreEventsLink.show();\n getString('moreevents', 'calendar', numberOfHiddenEvents).then(str => {\n const link = moreEventsLink.find('strong a');\n moreEventsLink.attr('data-event-folded', 'false');\n link.text(str);\n return str;\n }).catch(Notification.exception);\n } else {\n moreEventsLink.hide();\n }\n });\n};\n\n/**\n * Register and handle month calendar events.\n *\n * @param {string} pendingId pending id.\n */\nexport const registerEventListenersForMonthDetailed = (pendingId) => {\n const events = `${CalendarEvents.viewUpdated}`;\n $('body').on(events, function(e) {\n foldDayEvents(e);\n });\n foldDayEvents();\n $('body').on(CalendarEvents.filterChanged, function(e, data) {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const pending = new Pending(pendingId);\n const target = root.find(CalendarSelectors.eventType[data.type]);\n const transitionPromise = $.Deferred();\n if (data.hidden) {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'true');\n return target.hide().promise();\n }).fail();\n } else {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'false');\n return target.show().promise();\n }).fail();\n }\n\n transitionPromise.then(function() {\n foldDayEvents();\n return;\n })\n .always(pending.resolve)\n .fail();\n\n transitionPromise.resolve();\n });\n};\n\n/**\n * Register event listeners for the module.\n *\n * @param {object} root The root element.\n */\nconst registerEventListeners = (root) => {\n root = $(root);\n\n // Bind click events to event links.\n root.on('click', CalendarSelectors.links.eventLink, (e) => {\n const target = e.target;\n let eventLink = null;\n let eventId = null;\n const pendingPromise = new Pending('core_calendar/view_manager:eventLink:click');\n\n if (target.matches(CalendarSelectors.actions.viewEvent)) {\n eventLink = target;\n } else {\n eventLink = target.closest(CalendarSelectors.actions.viewEvent);\n }\n\n if (eventLink) {\n eventId = eventLink.dataset.eventId;\n } else {\n eventId = target.querySelector(CalendarSelectors.actions.viewEvent).dataset.eventId;\n }\n\n if (eventId) {\n // A link was found. Show the modal.\n\n e.preventDefault();\n // We've handled the event so stop it from bubbling\n // and causing the day click handler to fire.\n e.stopPropagation();\n\n renderEventSummaryModal(eventId)\n .then(pendingPromise.resolve)\n .catch();\n } else {\n pendingPromise.resolve();\n }\n });\n\n root.on('click', CalendarSelectors.links.navLink, (e) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const view = wrapper.data('view');\n const courseId = wrapper.data('courseid');\n const categoryId = wrapper.data('categoryid');\n const link = e.currentTarget;\n\n if (view === 'month' || view === 'monthblock') {\n changeMonth(root, link.href, link.dataset.year, link.dataset.month, courseId, categoryId, link.dataset.day);\n e.preventDefault();\n } else if (view === 'day') {\n changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day, courseId, categoryId);\n e.preventDefault();\n }\n });\n\n const viewSelector = root.find(CalendarSelectors.viewSelector);\n CustomEvents.define(viewSelector, [CustomEvents.events.activate]);\n viewSelector.on(\n CustomEvents.events.activate,\n (e) => {\n e.preventDefault();\n\n const option = e.target;\n if (option.classList.contains('active')) {\n return;\n }\n\n const view = option.dataset.view,\n year = option.dataset.year,\n month = option.dataset.month,\n day = option.dataset.day,\n courseId = option.dataset.courseid,\n categoryId = option.dataset.categoryid;\n\n if (view == 'month') {\n refreshMonthContent(root, year, month, courseId, categoryId, root, 'core_calendar/calendar_month', day)\n .then(() => {\n updateUrl('?view=month&course=' + courseId);\n return;\n }).fail(Notification.exception);\n } else if (view == 'day') {\n refreshDayContent(root, year, month, day, courseId, categoryId, root, 'core_calendar/calendar_day')\n .then(() => {\n updateUrl('?view=day&course=' + courseId);\n return;\n }).fail(Notification.exception);\n } else if (view == 'upcoming') {\n reloadCurrentUpcoming(root, courseId, categoryId, root, 'core_calendar/calendar_upcoming')\n .then(() => {\n updateUrl('?view=upcoming&course=' + courseId);\n return;\n }).fail(Notification.exception);\n }\n }\n );\n};\n\n/**\n * Refresh the month content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @param {number} day Day (optional)\n * @return {promise}\n */\nexport const refreshMonthContent = (root, year, month, courseId, categoryId, target = null, template = '', day = 1) => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, courseId].join('-'));\n const includenavigation = root.data('includenavigation');\n const mini = root.data('mini');\n const viewMode = target.data('view');\n return CalendarRepository.getCalendarMonthData(year, month, courseId, categoryId, includenavigation, mini, day, viewMode)\n .then(context => {\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, courseId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The container element\n * @param {string} url The calendar url to be shown\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {number} day Day (optional)\n * @return {promise}\n */\nexport const changeMonth = (root, url, year, month, courseId, categoryId, day = 1) => {\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day)\n .then((...args) => {\n if (url.length && url !== '#') {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentMonth = (root, courseId = 0, categoryId = 0) => {\n const year = root.find(CalendarSelectors.wrapper).data('year');\n const month = root.find(CalendarSelectors.wrapper).data('month');\n const day = root.find(CalendarSelectors.wrapper).data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day).\n then((...args) => {\n $('body').trigger(CalendarEvents.courseChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n\n/**\n * Refresh the day content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} day Day\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n *\n * @return {promise}\n */\nexport const refreshDayContent = (root, year, month, day, courseId, categoryId, target = null, template = '') => {\n startLoading(root);\n\n if (!target || target.length == 0){\n target = root.find(CalendarSelectors.wrapper);\n }\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n const includenavigation = root.data('includenavigation');\n return CalendarRepository.getCalendarDayData(year, month, day, courseId, categoryId, includenavigation)\n .then((context) => {\n context.viewingday = true;\n context.showviewselector = true;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Reload the current day view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentDay = (root, courseId = 0, categoryId = 0) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const year = wrapper.data('year');\n const month = wrapper.data('month');\n const day = wrapper.data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshDayContent(root, year, month, day, courseId, categoryId);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The root element.\n * @param {String} url The calendar url to be shown\n * @param {Number} year Year\n * @param {Number} month Month\n * @param {Number} day Day\n * @param {Number} courseId The id of the course whose events are shown\n * @param {Number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const changeDay = (root, url, year, month, day, courseId, categoryId) => {\n return refreshDayContent(root, year, month, day, courseId, categoryId)\n .then((...args) => {\n if (url.length && url !== '#') {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n/**\n * Update calendar URL.\n *\n * @param {String} url The calendar url to be updated.\n */\nexport const updateUrl = (url) => {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n\n // We want to update the url only if the user is viewing the full calendar.\n if (viewingFullCalendar) {\n window.history.pushState({}, '', url);\n }\n};\n\n/**\n * Set the element state to loading.\n *\n * @param {object} root The container element\n * @method startLoading\n */\nconst startLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.removeClass('hidden');\n};\n\n/**\n * Remove the loading state from the element.\n *\n * @param {object} root The container element\n * @method stopLoading\n */\nconst stopLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.addClass('hidden');\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @return {promise}\n */\nexport const reloadCurrentUpcoming = (root, courseId = 0, categoryId = 0, target = null, template = '') => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return CalendarRepository.getCalendarUpcomingData(courseId, categoryId)\n .then((context) => {\n context.viewingupcoming = true;\n context.showviewselector = true;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(function() {\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Get the CSS class to apply for the given event type.\n *\n * @param {string} eventType The calendar event type\n * @return {string}\n */\nconst getEventTypeClassFromType = (eventType) => {\n return 'calendar_event_' + eventType;\n};\n\n/**\n * Render the event summary modal.\n *\n * @param {Number} eventId The calendar event id.\n * @returns {Promise}\n */\nconst renderEventSummaryModal = (eventId) => {\n const pendingPromise = new Pending('core_calendar/view_manager:renderEventSummaryModal');\n\n // Calendar repository promise.\n return CalendarRepository.getEventById(eventId)\n .then((getEventResponse) => {\n if (!getEventResponse.event) {\n throw new Error('Error encountered while trying to fetch calendar event with ID: ' + eventId);\n }\n\n return getEventResponse.event;\n })\n .then(eventData => {\n // Build the modal parameters from the event data.\n const modalParams = {\n title: eventData.name,\n body: Templates.render('core_calendar/event_summary_body', eventData),\n templateContext: {\n canedit: eventData.canedit,\n candelete: eventData.candelete,\n headerclasses: getEventTypeClassFromType(eventData.normalisedeventtype),\n isactionevent: eventData.isactionevent,\n url: eventData.url,\n action: eventData.action\n }\n };\n\n // Create the modal.\n return SummaryModal.create(modalParams);\n })\n .then(modal => {\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Finally, render the modal!\n modal.show();\n\n return modal;\n })\n .then(modal => {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n};\n\nexport const init = (root, view) => {\n prefetchStrings('calendar', ['moreevents']);\n foldDayEvents();\n registerEventListeners(root, view);\n const calendarTable = root.find(CalendarSelectors.elements.monthDetailed);\n if (calendarTable.length) {\n const pendingId = `month-detailed-${calendarTable.id}-filterChanged`;\n registerEventListenersForMonthDetailed(calendarTable, pendingId);\n }\n};\n\n/**\n * Handles the change of course and updates the relevant elements on the page.\n *\n * @param {integer} courseId - The ID of the new course.\n * @param {string} courseName - The name of the new course.\n * @returns {Promise} - A promise that resolves after the updates are applied.\n */\nexport const handleCourseChange = async(courseId, courseName) => {\n // Select the
    element inside the data-region=\"view-selector\".\n const ulElement = document.querySelector(CalendarSelectors.viewSelector + ' ul');\n // Select all
  • elements within the
      .\n const liElements = ulElement.querySelectorAll('li a');\n // Loop through the selected elements and update the courseid.\n liElements.forEach(element => {\n element.setAttribute('data-courseid', courseId);\n });\n\n const calendar = await getString('calendar', 'calendar');\n const pageHeaderHeadingsElement = document.querySelector(CalendarSelectors.pageHeaderHeadings);\n const courseUrl = Url.relativeUrl('/course/view.php', {id: courseId});\n // Apply the page header text.\n if (courseId !== Config.siteId) {\n pageHeaderHeadingsElement.innerHTML = calendar + ': ' + courseName + '';\n } else {\n pageHeaderHeadingsElement.innerHTML = calendar;\n }\n};"],"names":["foldDayEvents","days","CalendarSelectors","elements","monthDetailed","find","day","length","each","dayContainer","this","eventsSelector","dateContent","filteredEventsSelector","moreEventsSelector","events","numberOfFiltered","numberOfEvents","count","event","attr","hide","show","moreEventsLink","numberOfHiddenEvents","then","str","link","text","catch","Notification","exception","registerEventListenersForMonthDetailed","pendingId","CalendarEvents","viewUpdated","on","e","filterChanged","data","root","pending","Pending","target","eventType","type","transitionPromise","$","Deferred","hidden","promise","fail","always","resolve","refreshMonthContent","year","month","courseId","categoryId","template","startLoading","wrapper","M","util","js_pending","get","join","includenavigation","mini","viewMode","CalendarRepository","getCalendarMonthData","context","Templates","render","html","js","replaceNode","document","querySelector","dispatchEvent","CustomEvent","js_complete","stopLoading","changeMonth","url","updateUrl","args","trigger","monthChanged","courseChanged","refreshDayContent","getCalendarDayData","viewingday","showviewselector","changeDay","dayChanged","getElementById","fullCalendarView","window","history","pushState","containers","loadingIcon","removeClass","addClass","reloadCurrentUpcoming","getCalendarUpcomingData","viewingupcoming","renderEventSummaryModal","eventId","pendingPromise","getEventById","getEventResponse","Error","eventData","modalParams","title","name","body","templateContext","canedit","candelete","headerclasses","normalisedeventtype","isactionevent","action","SummaryModal","create","modal","getRoot","ModalEvents","destroy","view","links","eventLink","matches","actions","viewEvent","closest","dataset","preventDefault","stopPropagation","navLink","currentTarget","href","viewSelector","define","CustomEvents","activate","option","classList","contains","courseid","categoryid","registerEventListeners","calendarTable","id","async","courseName","querySelectorAll","forEach","element","setAttribute","calendar","pageHeaderHeadingsElement","pageHeaderHeadings","courseUrl","Url","relativeUrl","Config","siteId","innerHTML"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"view_manager.min.js","sources":["../src/view_manager.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 .\n\n/**\n * A javascript module to handler calendar view changes.\n *\n * @module core_calendar/view_manager\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport Templates from 'core/templates';\nimport Notification from 'core/notification';\nimport * as CalendarRepository from 'core_calendar/repository';\nimport CalendarEvents from 'core_calendar/events';\nimport * as CalendarSelectors from 'core_calendar/selectors';\nimport ModalEvents from 'core/modal_events';\nimport SummaryModal from 'core_calendar/summary_modal';\nimport CustomEvents from 'core/custom_interaction_events';\nimport {getString} from 'core/str';\nimport Pending from 'core/pending';\nimport {prefetchStrings} from 'core/prefetch';\nimport Url from 'core/url';\nimport Config from 'core/config';\n\n/**\n * Limit number of events per day\n *\n */\nconst LIMIT_DAY_EVENTS = 5;\n\n/**\n * Hide day events if more than 5.\n *\n */\nexport const foldDayEvents = () => {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const days = root.find(CalendarSelectors.day);\n if (days.length === 0) {\n return;\n }\n days.each(function() {\n const dayContainer = $(this);\n const eventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-eventtype]`;\n const filteredEventsSelector = `${CalendarSelectors.elements.dateContent} ul li[data-event-filtered=\"true\"]`;\n const moreEventsSelector = `${CalendarSelectors.elements.dateContent} [data-action=\"view-more-events\"]`;\n const events = dayContainer.find(eventsSelector);\n if (events.length === 0) {\n return;\n }\n\n const filteredEvents = dayContainer.find(filteredEventsSelector);\n const numberOfFiltered = filteredEvents.length;\n const numberOfEvents = events.length - numberOfFiltered;\n\n let count = 1;\n events.each(function() {\n const event = $(this);\n const isNotFiltered = event.attr('data-event-filtered') !== 'true';\n const offset = (numberOfEvents === LIMIT_DAY_EVENTS) ? 0 : 1;\n if (isNotFiltered) {\n if (count > LIMIT_DAY_EVENTS - offset) {\n event.attr('data-event-folded', 'true');\n event.hide();\n } else {\n event.attr('data-event-folded', 'false');\n event.show();\n count++;\n }\n } else {\n // It's being filtered out.\n event.attr('data-event-folded', 'false');\n }\n });\n\n const moreEventsLink = dayContainer.find(moreEventsSelector);\n if (numberOfEvents > LIMIT_DAY_EVENTS) {\n const numberOfHiddenEvents = numberOfEvents - LIMIT_DAY_EVENTS + 1;\n moreEventsLink.show();\n getString('moreevents', 'calendar', numberOfHiddenEvents).then(str => {\n const link = moreEventsLink.find('strong a');\n moreEventsLink.attr('data-event-folded', 'false');\n link.text(str);\n return str;\n }).catch(Notification.exception);\n } else {\n moreEventsLink.hide();\n }\n });\n};\n\n/**\n * Register and handle month calendar events.\n *\n * @param {string} pendingId pending id.\n */\nexport const registerEventListenersForMonthDetailed = (pendingId) => {\n const events = `${CalendarEvents.viewUpdated}`;\n $('body').on(events, function(e) {\n foldDayEvents(e);\n });\n foldDayEvents();\n $('body').on(CalendarEvents.filterChanged, function(e, data) {\n const root = $(CalendarSelectors.elements.monthDetailed);\n const pending = new Pending(pendingId);\n const target = root.find(CalendarSelectors.eventType[data.type]);\n const transitionPromise = $.Deferred();\n if (data.hidden) {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'true');\n return target.hide().promise();\n }).fail();\n } else {\n transitionPromise.then(function() {\n target.attr('data-event-filtered', 'false');\n return target.show().promise();\n }).fail();\n }\n\n transitionPromise.then(function() {\n foldDayEvents();\n return;\n })\n .always(pending.resolve)\n .fail();\n\n transitionPromise.resolve();\n });\n};\n\n/**\n * Register event listeners for the module.\n *\n * @param {object} root The root element.\n * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.\n */\nconst registerEventListeners = (root, isCalendarBlock) => {\n root = $(root);\n\n // Bind click events to event links.\n root.on('click', CalendarSelectors.links.eventLink, (e) => {\n const target = e.target;\n let eventLink = null;\n let eventId = null;\n const pendingPromise = new Pending('core_calendar/view_manager:eventLink:click');\n\n if (target.matches(CalendarSelectors.actions.viewEvent)) {\n eventLink = target;\n } else {\n eventLink = target.closest(CalendarSelectors.actions.viewEvent);\n }\n\n if (eventLink) {\n eventId = eventLink.dataset.eventId;\n } else {\n eventId = target.querySelector(CalendarSelectors.actions.viewEvent).dataset.eventId;\n }\n\n if (eventId) {\n // A link was found. Show the modal.\n\n e.preventDefault();\n // We've handled the event so stop it from bubbling\n // and causing the day click handler to fire.\n e.stopPropagation();\n\n renderEventSummaryModal(eventId)\n .then(pendingPromise.resolve)\n .catch();\n } else {\n pendingPromise.resolve();\n }\n });\n\n root.on('click', CalendarSelectors.links.navLink, (e) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const view = wrapper.data('view');\n const courseId = wrapper.data('courseid');\n const categoryId = wrapper.data('categoryid');\n const link = e.currentTarget;\n\n if (view === 'month' || view === 'monthblock') {\n changeMonth(root, link.href, link.dataset.year, link.dataset.month,\n courseId, categoryId, link.dataset.day, isCalendarBlock);\n e.preventDefault();\n } else if (view === 'day') {\n changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day,\n courseId, categoryId, isCalendarBlock);\n e.preventDefault();\n }\n });\n\n const viewSelector = root.find(CalendarSelectors.viewSelector);\n CustomEvents.define(viewSelector, [CustomEvents.events.activate]);\n viewSelector.on(\n CustomEvents.events.activate,\n (e) => {\n e.preventDefault();\n\n const option = e.target;\n if (option.classList.contains('active')) {\n return;\n }\n\n const view = option.dataset.view,\n year = option.dataset.year,\n month = option.dataset.month,\n day = option.dataset.day,\n courseId = option.dataset.courseid,\n categoryId = option.dataset.categoryid;\n\n if (view == 'month') {\n refreshMonthContent(root, year, month, courseId, categoryId, root, 'core_calendar/calendar_month', day)\n .then(() => {\n updateUrl('?view=month&course=' + courseId);\n return;\n }).fail(Notification.exception);\n } else if (view == 'day') {\n refreshDayContent(root, year, month, day, courseId, categoryId, root, 'core_calendar/calendar_day')\n .then(() => {\n updateUrl('?view=day&course=' + courseId);\n return;\n }).fail(Notification.exception);\n } else if (view == 'upcoming') {\n reloadCurrentUpcoming(root, courseId, categoryId, root, 'core_calendar/calendar_upcoming')\n .then(() => {\n updateUrl('?view=upcoming&course=' + courseId);\n return;\n }).fail(Notification.exception);\n }\n }\n );\n};\n\n/**\n * Refresh the month content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @param {number} day Day (optional)\n * @return {promise}\n */\nexport const refreshMonthContent = (root, year, month, courseId, categoryId, target = null, template = '', day = 1) => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, courseId].join('-'));\n const includenavigation = root.data('includenavigation');\n const mini = root.data('mini');\n const viewMode = target.data('view');\n return CalendarRepository.getCalendarMonthData(year, month, courseId, categoryId, includenavigation, mini, day, viewMode)\n .then(context => {\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, courseId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The container element\n * @param {string} url The calendar url to be shown\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {number} day Day (optional)\n * @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block.\n * @return {promise}\n */\nexport const changeMonth = (root, url, year, month, courseId, categoryId, day = 1, isCalendarBlock = false) => {\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day)\n .then((...args) => {\n if (url.length && url !== '#' && !isCalendarBlock) {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId, day, isCalendarBlock]);\n return args;\n });\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentMonth = (root, courseId = 0, categoryId = 0) => {\n const year = root.find(CalendarSelectors.wrapper).data('year');\n const month = root.find(CalendarSelectors.wrapper).data('month');\n const day = root.find(CalendarSelectors.wrapper).data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day).\n then((...args) => {\n $('body').trigger(CalendarEvents.courseChanged, [year, month, courseId, categoryId]);\n return args;\n });\n};\n\n\n/**\n * Refresh the day content.\n *\n * @param {object} root The root element.\n * @param {number} year Year\n * @param {number} month Month\n * @param {number} day Day\n * @param {number} courseId The id of the course whose events are shown\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.\n *\n * @return {promise}\n */\nexport const refreshDayContent = (root, year, month, day, courseId, categoryId,\n target = null, template = '', isCalendarBlock = false) => {\n startLoading(root);\n\n if (!target || target.length == 0){\n target = root.find(CalendarSelectors.wrapper);\n }\n template = template || root.attr('data-template');\n M.util.js_pending([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n const includenavigation = root.data('includenavigation');\n return CalendarRepository.getCalendarDayData(year, month, day, courseId, categoryId, includenavigation)\n .then((context) => {\n context.viewingday = true;\n context.showviewselector = true;\n context.iscalendarblock = isCalendarBlock;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(() => {\n M.util.js_complete([root.get('id'), year, month, day, courseId, categoryId].join('-'));\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Reload the current day view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @return {promise}\n */\nexport const reloadCurrentDay = (root, courseId = 0, categoryId = 0) => {\n const wrapper = root.find(CalendarSelectors.wrapper);\n const year = wrapper.data('year');\n const month = wrapper.data('month');\n const day = wrapper.data('day');\n\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return refreshDayContent(root, year, month, day, courseId, categoryId);\n};\n\n/**\n * Handle changes to the current calendar view.\n *\n * @param {object} root The root element.\n * @param {String} url The calendar url to be shown\n * @param {Number} year Year\n * @param {Number} month Month\n * @param {Number} day Day\n * @param {Number} courseId The id of the course whose events are shown\n * @param {Number} categoryId The id of the category whose events are shown\n * @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block.\n * @return {promise}\n */\nexport const changeDay = (root, url, year, month, day, courseId, categoryId, isCalendarBlock = false) => {\n return refreshDayContent(root, year, month, day, courseId, categoryId, null, '', isCalendarBlock)\n .then((...args) => {\n if (url.length && url !== '#' && !isCalendarBlock) {\n updateUrl(url);\n }\n return args;\n })\n .then((...args) => {\n $('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId, isCalendarBlock]);\n return args;\n });\n};\n\n/**\n * Update calendar URL.\n *\n * @param {String} url The calendar url to be updated.\n */\nexport const updateUrl = (url) => {\n const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);\n\n // We want to update the url only if the user is viewing the full calendar.\n if (viewingFullCalendar) {\n window.history.pushState({}, '', url);\n }\n};\n\n/**\n * Set the element state to loading.\n *\n * @param {object} root The container element\n * @method startLoading\n */\nconst startLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.removeClass('hidden');\n};\n\n/**\n * Remove the loading state from the element.\n *\n * @param {object} root The container element\n * @method stopLoading\n */\nconst stopLoading = (root) => {\n const loadingIconContainer = root.find(CalendarSelectors.containers.loadingIcon);\n\n loadingIconContainer.addClass('hidden');\n};\n\n/**\n * Reload the current month view data.\n *\n * @param {object} root The container element.\n * @param {number} courseId The course id.\n * @param {number} categoryId The id of the category whose events are shown\n * @param {object} target The element being replaced. If not specified, the calendarwrapper is used.\n * @param {string} template The template to be rendered.\n * @return {promise}\n */\nexport const reloadCurrentUpcoming = (root, courseId = 0, categoryId = 0, target = null, template = '') => {\n startLoading(root);\n\n target = target || root.find(CalendarSelectors.wrapper);\n template = template || root.attr('data-template');\n courseId = courseId || root.find(CalendarSelectors.wrapper).data('courseid');\n categoryId = categoryId || root.find(CalendarSelectors.wrapper).data('categoryid');\n\n return CalendarRepository.getCalendarUpcomingData(courseId, categoryId)\n .then((context) => {\n context.viewingupcoming = true;\n context.showviewselector = true;\n return Templates.render(template, context);\n })\n .then((html, js) => {\n return Templates.replaceNode(target, html, js);\n })\n .then(() => {\n document.querySelector('body').dispatchEvent(new CustomEvent(CalendarEvents.viewUpdated));\n return;\n })\n .always(function() {\n return stopLoading(root);\n })\n .fail(Notification.exception);\n};\n\n/**\n * Get the CSS class to apply for the given event type.\n *\n * @param {string} eventType The calendar event type\n * @return {string}\n */\nconst getEventTypeClassFromType = (eventType) => {\n return 'calendar_event_' + eventType;\n};\n\n/**\n * Render the event summary modal.\n *\n * @param {Number} eventId The calendar event id.\n * @returns {Promise}\n */\nconst renderEventSummaryModal = (eventId) => {\n const pendingPromise = new Pending('core_calendar/view_manager:renderEventSummaryModal');\n\n // Calendar repository promise.\n return CalendarRepository.getEventById(eventId)\n .then((getEventResponse) => {\n if (!getEventResponse.event) {\n throw new Error('Error encountered while trying to fetch calendar event with ID: ' + eventId);\n }\n\n return getEventResponse.event;\n })\n .then(eventData => {\n // Build the modal parameters from the event data.\n const modalParams = {\n title: eventData.name,\n body: Templates.render('core_calendar/event_summary_body', eventData),\n templateContext: {\n canedit: eventData.canedit,\n candelete: eventData.candelete,\n headerclasses: getEventTypeClassFromType(eventData.normalisedeventtype),\n isactionevent: eventData.isactionevent,\n url: eventData.url,\n action: eventData.action\n }\n };\n\n // Create the modal.\n return SummaryModal.create(modalParams);\n })\n .then(modal => {\n // Handle hidden event.\n modal.getRoot().on(ModalEvents.hidden, function() {\n // Destroy when hidden.\n modal.destroy();\n });\n\n // Finally, render the modal!\n modal.show();\n\n return modal;\n })\n .then(modal => {\n pendingPromise.resolve();\n\n return modal;\n })\n .catch(Notification.exception);\n};\n\n/**\n * Initializes the calendar component by prefetching strings, folding day events,\n * and registering event listeners.\n *\n * @param {HTMLElement} root - The root element where the calendar view manager and event listeners will be attached.\n * @param {string} view - A flag indicating whether this is a calendar block.\n * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block.\n */\nexport const init = (root, view, isCalendarBlock) => {\n prefetchStrings('calendar', ['moreevents']);\n foldDayEvents();\n registerEventListeners(root, isCalendarBlock);\n const calendarTable = root.find(CalendarSelectors.elements.monthDetailed);\n if (calendarTable.length) {\n const pendingId = `month-detailed-${calendarTable.id}-filterChanged`;\n registerEventListenersForMonthDetailed(calendarTable, pendingId);\n }\n};\n\n/**\n * Handles the change of course and updates the relevant elements on the page.\n *\n * @param {integer} courseId - The ID of the new course.\n * @param {string} courseName - The name of the new course.\n * @returns {Promise} - A promise that resolves after the updates are applied.\n */\nexport const handleCourseChange = async(courseId, courseName) => {\n // Select the
        element inside the data-region=\"view-selector\".\n const ulElement = document.querySelector(CalendarSelectors.viewSelector + ' ul');\n // Select all
      • elements within the
          .\n const liElements = ulElement.querySelectorAll('li a');\n // Loop through the selected elements and update the courseid.\n liElements.forEach(element => {\n element.setAttribute('data-courseid', courseId);\n });\n\n const calendar = await getString('calendar', 'calendar');\n const pageHeaderHeadingsElement = document.querySelector(CalendarSelectors.pageHeaderHeadings);\n const courseUrl = Url.relativeUrl('/course/view.php', {id: courseId});\n // Apply the page header text.\n if (courseId !== Config.siteId) {\n pageHeaderHeadingsElement.innerHTML = calendar + ': ' + courseName + '';\n } else {\n pageHeaderHeadingsElement.innerHTML = calendar;\n }\n};"],"names":["foldDayEvents","days","CalendarSelectors","elements","monthDetailed","find","day","length","each","dayContainer","this","eventsSelector","dateContent","filteredEventsSelector","moreEventsSelector","events","numberOfFiltered","numberOfEvents","count","event","attr","hide","show","moreEventsLink","numberOfHiddenEvents","then","str","link","text","catch","Notification","exception","registerEventListenersForMonthDetailed","pendingId","CalendarEvents","viewUpdated","on","e","filterChanged","data","root","pending","Pending","target","eventType","type","transitionPromise","$","Deferred","hidden","promise","fail","always","resolve","refreshMonthContent","year","month","courseId","categoryId","template","startLoading","wrapper","M","util","js_pending","get","join","includenavigation","mini","viewMode","CalendarRepository","getCalendarMonthData","context","Templates","render","html","js","replaceNode","document","querySelector","dispatchEvent","CustomEvent","js_complete","stopLoading","changeMonth","url","isCalendarBlock","updateUrl","args","trigger","monthChanged","courseChanged","refreshDayContent","getCalendarDayData","viewingday","showviewselector","iscalendarblock","changeDay","dayChanged","getElementById","fullCalendarView","window","history","pushState","containers","loadingIcon","removeClass","addClass","reloadCurrentUpcoming","getCalendarUpcomingData","viewingupcoming","renderEventSummaryModal","eventId","pendingPromise","getEventById","getEventResponse","Error","eventData","modalParams","title","name","body","templateContext","canedit","candelete","headerclasses","normalisedeventtype","isactionevent","action","SummaryModal","create","modal","getRoot","ModalEvents","destroy","view","links","eventLink","matches","actions","viewEvent","closest","dataset","preventDefault","stopPropagation","navLink","currentTarget","href","viewSelector","define","CustomEvents","activate","option","classList","contains","courseid","categoryid","registerEventListeners","calendarTable","id","async","courseName","querySelectorAll","forEach","element","setAttribute","calendar","pageHeaderHeadingsElement","pageHeaderHeadings","courseUrl","Url","relativeUrl","Config","siteId","innerHTML"],"mappings":";;;;;;;69BAgDaA,cAAgB,WAEnBC,MADO,mBAAEC,kBAAkBC,SAASC,eACxBC,KAAKH,kBAAkBI,KACrB,IAAhBL,KAAKM,QAGTN,KAAKO,MAAK,iBACAC,cAAe,mBAAEC,MACjBC,yBAAoBT,kBAAkBC,SAASS,4CAC/CC,iCAA4BX,kBAAkBC,SAASS,kDACvDE,6BAAwBZ,kBAAkBC,SAASS,iDACnDG,OAASN,aAAaJ,KAAKM,mBACX,IAAlBI,OAAOR,oBAKLS,iBADiBP,aAAaJ,KAAKQ,wBACDN,OAClCU,eAAiBF,OAAOR,OAASS,qBAEnCE,MAAQ,EACZH,OAAOP,MAAK,iBACFW,OAAQ,mBAAET,MAC4C,SAAtCS,MAAMC,KAAK,uBAGzBF,MAhCK,GAAA,IA8BGD,eAAuC,EAAI,IAGnDE,MAAMC,KAAK,oBAAqB,QAChCD,MAAME,SAENF,MAAMC,KAAK,oBAAqB,SAChCD,MAAMG,OACNJ,SAIJC,MAAMC,KAAK,oBAAqB,kBAIlCG,eAAiBd,aAAaJ,KAAKS,uBACrCG,eA/Ca,EA+CsB,OAC7BO,qBAAuBP,eAhDhB,EAgDoD,EACjEM,eAAeD,0BACL,aAAc,WAAYE,sBAAsBC,MAAKC,YACrDC,KAAOJ,eAAelB,KAAK,mBACjCkB,eAAeH,KAAK,oBAAqB,SACzCO,KAAKC,KAAKF,KACHA,OACRG,MAAMC,sBAAaC,gBAEtBR,eAAeF,sDAUdW,uCAA0CC,kBAC7ClB,iBAAYmB,gBAAeC,iCAC/B,QAAQC,GAAGrB,QAAQ,SAASsB,GAC1BrC,mBAEJA,oCACE,QAAQoC,GAAGF,gBAAeI,eAAe,SAASD,EAAGE,YAC7CC,MAAO,mBAAEtC,kBAAkBC,SAASC,eACpCqC,QAAU,IAAIC,iBAAQT,WACtBU,OAASH,KAAKnC,KAAKH,kBAAkB0C,UAAUL,KAAKM,OACpDC,kBAAoBC,gBAAEC,WACxBT,KAAKU,OACLH,kBAAkBrB,MAAK,kBACnBkB,OAAOvB,KAAK,sBAAuB,QAC5BuB,OAAOtB,OAAO6B,aACtBC,OAEHL,kBAAkBrB,MAAK,kBACnBkB,OAAOvB,KAAK,sBAAuB,SAC5BuB,OAAOrB,OAAO4B,aACtBC,OAGPL,kBAAkBrB,MAAK,WACnBzB,mBAGHoD,OAAOX,QAAQY,SACfF,OAEDL,kBAAkBO,2GAyHbC,oBAAsB,SAACd,KAAMe,KAAMC,MAAOC,SAAUC,gBAAYf,8DAAS,KAAMgB,gEAAW,GAAIrD,2DAAM,EAC7GsD,aAAapB,MAEbG,OAASA,QAAUH,KAAKnC,KAAKH,kBAAkB2D,SAC/CF,SAAWA,UAAYnB,KAAKpB,KAAK,iBACjC0C,EAAEC,KAAKC,WAAW,CAACxB,KAAKyB,IAAI,MAAOV,KAAMC,MAAOC,UAAUS,KAAK,YACzDC,kBAAoB3B,KAAKD,KAAK,qBAC9B6B,KAAO5B,KAAKD,KAAK,QACjB8B,SAAW1B,OAAOJ,KAAK,eACtB+B,mBAAmBC,qBAAqBhB,KAAMC,MAAOC,SAAUC,WAAYS,kBAAmBC,KAAM9D,IAAK+D,UAC3G5C,MAAK+C,SACKC,mBAAUC,OAAOf,SAAUa,WAErC/C,MAAK,CAACkD,KAAMC,KACFH,mBAAUI,YAAYlC,OAAQgC,KAAMC,MAE9CnD,MAAK,KACFqD,SAASC,cAAc,QAAQC,cAAc,IAAIC,YAAY/C,gBAAeC,iBAG/EiB,QAAO,KACJU,EAAEC,KAAKmB,YAAY,CAAC1C,KAAKyB,IAAI,MAAOV,KAAMC,MAAOC,UAAUS,KAAK,MACzDiB,YAAY3C,SAEtBW,KAAKrB,sBAAaC,mEAgBdqD,YAAc,SAAC5C,KAAM6C,IAAK9B,KAAMC,MAAOC,SAAUC,gBAAYpD,2DAAM,EAAGgF,+EACxEhC,oBAAoBd,KAAMe,KAAMC,MAAOC,SAAUC,WAAY,KAAM,GAAIpD,KACzEmB,MAAK,WACE4D,IAAI9E,QAAkB,MAAR8E,MAAgBC,iBAC9BC,UAAUF,mCAFRG,6CAAAA,kCAICA,QAEV/D,MAAK,+BACA,QAAQgE,QAAQvD,gBAAewD,aAAc,CAACnC,KAAMC,MAAOC,SAAUC,WAAYpD,IAAKgF,iDADlFE,kDAAAA,oCAECA,sEAYe,SAAChD,UAAMiB,gEAAW,EAAGC,kEAAa,QAC1DH,KAAOf,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,QACjDiB,MAAQhB,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,SAClDjC,IAAMkC,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,cAEtDkB,SAAWA,UAAYjB,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,YACjEmB,WAAaA,YAAclB,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,cAE9De,oBAAoBd,KAAMe,KAAMC,MAAOC,SAAUC,WAAY,KAAM,GAAIpD,KAC1EmB,MAAK,+BACC,QAAQgE,QAAQvD,gBAAeyD,cAAe,CAACpC,KAAMC,MAAOC,SAAUC,4CADnE8B,kDAAAA,oCAEEA,eAoBNI,kBAAoB,SAACpD,KAAMe,KAAMC,MAAOlD,IAAKmD,SAAUC,gBAChEf,8DAAS,KAAMgB,gEAAW,GAAI2B,wEAC9B1B,aAAapB,MAERG,QAA2B,GAAjBA,OAAOpC,SAClBoC,OAASH,KAAKnC,KAAKH,kBAAkB2D,UAEzCF,SAAWA,UAAYnB,KAAKpB,KAAK,iBACjC0C,EAAEC,KAAKC,WAAW,CAACxB,KAAKyB,IAAI,MAAOV,KAAMC,MAAOlD,IAAKmD,SAAUC,YAAYQ,KAAK,YAC1EC,kBAAoB3B,KAAKD,KAAK,4BAC7B+B,mBAAmBuB,mBAAmBtC,KAAMC,MAAOlD,IAAKmD,SAAUC,WAAYS,mBAChF1C,MAAM+C,UACHA,QAAQsB,YAAa,EACrBtB,QAAQuB,kBAAmB,EAC3BvB,QAAQwB,gBAAkBV,gBACnBb,mBAAUC,OAAOf,SAAUa,YAErC/C,MAAK,CAACkD,KAAMC,KACFH,mBAAUI,YAAYlC,OAAQgC,KAAMC,MAE9CnD,MAAK,KACFqD,SAASC,cAAc,QAAQC,cAAc,IAAIC,YAAY/C,gBAAeC,iBAG/EiB,QAAO,KACJU,EAAEC,KAAKmB,YAAY,CAAC1C,KAAKyB,IAAI,MAAOV,KAAMC,MAAOlD,IAAKmD,SAAUC,YAAYQ,KAAK,MAC1EiB,YAAY3C,SAEtBW,KAAKrB,sBAAaC,mFAWK,SAACS,UAAMiB,gEAAW,EAAGC,kEAAa,QACxDG,QAAUrB,KAAKnC,KAAKH,kBAAkB2D,SACtCN,KAAOM,QAAQtB,KAAK,QACpBiB,MAAQK,QAAQtB,KAAK,SACrBjC,IAAMuD,QAAQtB,KAAK,cAEzBkB,SAAWA,UAAYjB,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,YACjEmB,WAAaA,YAAclB,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,cAE9DqD,kBAAkBpD,KAAMe,KAAMC,MAAOlD,IAAKmD,SAAUC,mBAgBlDuC,UAAY,SAACzD,KAAM6C,IAAK9B,KAAMC,MAAOlD,IAAKmD,SAAUC,gBAAY4B,+EAClEM,kBAAkBpD,KAAMe,KAAMC,MAAOlD,IAAKmD,SAAUC,WAAY,KAAM,GAAI4B,iBAC5E7D,MAAK,WACE4D,IAAI9E,QAAkB,MAAR8E,MAAgBC,iBAC9BC,UAAUF,oCAFRG,kDAAAA,oCAICA,QAEV/D,MAAK,+BACA,QAAQgE,QAAQvD,gBAAegE,WAAY,CAAC3C,KAAMC,MAAOC,SAAUC,WAAY4B,iDAD3EE,kDAAAA,oCAECA,4CASND,UAAaF,MACMP,SAASqB,eAAejG,kBAAkBkG,mBAIlEC,OAAOC,QAAQC,UAAU,GAAI,GAAIlB,yCAUnCzB,aAAgBpB,OACWA,KAAKnC,KAAKH,kBAAkBsG,WAAWC,aAE/CC,YAAY,WAS/BvB,YAAe3C,OACYA,KAAKnC,KAAKH,kBAAkBsG,WAAWC,aAE/CE,SAAS,WAarBC,sBAAwB,SAACpE,UAAMiB,gEAAW,EAAGC,kEAAa,EAAGf,8DAAS,KAAMgB,gEAAW,UAChGC,aAAapB,MAEbG,OAASA,QAAUH,KAAKnC,KAAKH,kBAAkB2D,SAC/CF,SAAWA,UAAYnB,KAAKpB,KAAK,iBACjCqC,SAAWA,UAAYjB,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,YACjEmB,WAAaA,YAAclB,KAAKnC,KAAKH,kBAAkB2D,SAAStB,KAAK,cAE9D+B,mBAAmBuC,wBAAwBpD,SAAUC,YACvDjC,MAAM+C,UACHA,QAAQsC,iBAAkB,EAC1BtC,QAAQuB,kBAAmB,EACpBtB,mBAAUC,OAAOf,SAAUa,YAErC/C,MAAK,CAACkD,KAAMC,KACFH,mBAAUI,YAAYlC,OAAQgC,KAAMC,MAE9CnD,MAAK,KACFqD,SAASC,cAAc,QAAQC,cAAc,IAAIC,YAAY/C,gBAAeC,iBAG/EiB,QAAO,kBACG+B,YAAY3C,SAEtBW,KAAKrB,sBAAaC,uEAmBrBgF,wBAA2BC,gBACvBC,eAAiB,IAAIvE,iBAAQ,6DAG5B4B,mBAAmB4C,aAAaF,SACtCvF,MAAM0F,uBACEA,iBAAiBhG,YACZ,IAAIiG,MAAM,mEAAqEJ,gBAGlFG,iBAAiBhG,SAE3BM,MAAK4F,kBAEIC,YAAc,CAChBC,MAAOF,UAAUG,KACjBC,KAAMhD,mBAAUC,OAAO,mCAAoC2C,WAC3DK,gBAAiB,CACbC,QAASN,UAAUM,QACnBC,UAAWP,UAAUO,UACrBC,eA9BmBjF,UA8BsByE,UAAUS,oBA7BxD,kBAAoBlF,WA8BfmF,cAAeV,UAAUU,cACzB1C,IAAKgC,UAAUhC,IACf2C,OAAQX,UAAUW,SAjCCpF,IAAAA,iBAsCpBqF,uBAAaC,OAAOZ,gBAE9B7F,MAAK0G,QAEFA,MAAMC,UAAUhG,GAAGiG,sBAAYpF,QAAQ,WAEnCkF,MAAMG,aAIVH,MAAM7G,OAEC6G,SAEV1G,MAAK0G,QACFlB,eAAe5D,UAER8E,SAEVtG,MAAMC,sBAAaC,0BAWJ,CAACS,KAAM+F,KAAMjD,iDACb,WAAY,CAAC,eAC7BtF,gBAjb2B,EAACwC,KAAM8C,oBAClC9C,MAAO,mBAAEA,OAGJJ,GAAG,QAASlC,kBAAkBsI,MAAMC,WAAYpG,UAC3CM,OAASN,EAAEM,WACb8F,UAAY,KACZzB,QAAU,WACRC,eAAiB,IAAIvE,iBAAQ,8CAG/B+F,UADA9F,OAAO+F,QAAQxI,kBAAkByI,QAAQC,WAC7BjG,OAEAA,OAAOkG,QAAQ3I,kBAAkByI,QAAQC,WAIrD5B,QADAyB,UACUA,UAAUK,QAAQ9B,QAElBrE,OAAOoC,cAAc7E,kBAAkByI,QAAQC,WAAWE,QAAQ9B,QAG5EA,SAGA3E,EAAE0G,iBAGF1G,EAAE2G,kBAEFjC,wBAAwBC,SACvBvF,KAAKwF,eAAe5D,SACpBxB,SAEDoF,eAAe5D,aAIvBb,KAAKJ,GAAG,QAASlC,kBAAkBsI,MAAMS,SAAU5G,UACzCwB,QAAUrB,KAAKnC,KAAKH,kBAAkB2D,SACtC0E,KAAO1E,QAAQtB,KAAK,QACpBkB,SAAWI,QAAQtB,KAAK,YACxBmB,WAAaG,QAAQtB,KAAK,cAC1BZ,KAAOU,EAAE6G,cAEF,UAATX,MAA6B,eAATA,MACpBnD,YAAY5C,KAAMb,KAAKwH,KAAMxH,KAAKmH,QAAQvF,KAAM5B,KAAKmH,QAAQtF,MACzDC,SAAUC,WAAY/B,KAAKmH,QAAQxI,IAAKgF,iBAC5CjD,EAAE0G,kBACc,QAATR,OACPtC,UAAUzD,KAAMb,KAAKwH,KAAMxH,KAAKmH,QAAQvF,KAAM5B,KAAKmH,QAAQtF,MAAO7B,KAAKmH,QAAQxI,IAC3EmD,SAAUC,WAAY4B,iBAC1BjD,EAAE0G,2BAIJK,aAAe5G,KAAKnC,KAAKH,kBAAkBkJ,iDACpCC,OAAOD,aAAc,CAACE,mCAAavI,OAAOwI,WACvDH,aAAahH,GACTkH,mCAAavI,OAAOwI,UACnBlH,IACGA,EAAE0G,uBAEIS,OAASnH,EAAEM,UACb6G,OAAOC,UAAUC,SAAS,uBAIxBnB,KAAOiB,OAAOV,QAAQP,KACxBhF,KAAOiG,OAAOV,QAAQvF,KACtBC,MAAQgG,OAAOV,QAAQtF,MACvBlD,IAAMkJ,OAAOV,QAAQxI,IACrBmD,SAAW+F,OAAOV,QAAQa,SAC1BjG,WAAa8F,OAAOV,QAAQc,WAEpB,SAARrB,KACAjF,oBAAoBd,KAAMe,KAAMC,MAAOC,SAAUC,WAAYlB,KAAM,+BAAgClC,KAC9FmB,MAAK,KACF8D,UAAU,sBAAwB9B,aAEnCN,KAAKrB,sBAAaC,WACV,OAARwG,KACP3C,kBAAkBpD,KAAMe,KAAMC,MAAOlD,IAAKmD,SAAUC,WAAYlB,KAAM,8BACjEf,MAAK,KACF8D,UAAU,oBAAsB9B,aAEjCN,KAAKrB,sBAAaC,WACV,YAARwG,MACP3B,sBAAsBpE,KAAMiB,SAAUC,WAAYlB,KAAM,mCACnDf,MAAK,KACF8D,UAAU,yBAA2B9B,aAEtCN,KAAKrB,sBAAaC,eAsVrC8H,CAAuBrH,KAAM8C,uBACvBwE,cAAgBtH,KAAKnC,KAAKH,kBAAkBC,SAASC,kBACvD0J,cAAcvJ,OAAQ,0BACcuJ,cAAcC,qBAClD/H,uCAAuC8H,6CAWbE,MAAMvG,SAAUwG,cAE5BnF,SAASC,cAAc7E,kBAAkBkJ,aAAe,OAE7Cc,iBAAiB,QAEnCC,SAAQC,UACfA,QAAQC,aAAa,gBAAiB5G,mBAGpC6G,eAAiB,kBAAU,WAAY,YACvCC,0BAA4BzF,SAASC,cAAc7E,kBAAkBsK,oBACrEC,UAAYC,aAAIC,YAAY,mBAAoB,CAACZ,GAAItG,WAEvDA,WAAamH,gBAAOC,OACpBN,0BAA0BO,UAAYR,SAAW,cAAgBG,UAAY,KAAOR,WAAa,OAEjGM,0BAA0BO,UAAYR"} \ No newline at end of file diff --git a/calendar/amd/src/calendar.js b/calendar/amd/src/calendar.js index ee978d65f8a..b725c66381f 100644 --- a/calendar/amd/src/calendar.js +++ b/calendar/amd/src/calendar.js @@ -33,7 +33,6 @@ define([ 'core_calendar/view_manager', 'core_calendar/crud', 'core_calendar/selectors', - 'core/config', 'core/url', 'core/str', ], @@ -46,7 +45,6 @@ function( CalendarViewManager, CalendarCrud, CalendarSelectors, - Config, Url, Str, ) { @@ -171,8 +169,9 @@ function( * Register event listeners for the module. * * @param {object} root The calendar root element + * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block. */ - var registerEventListeners = function(root) { + var registerEventListeners = function(root, isCalendarBlock) { const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView); // Listen the click on the day link to render the day view. root.on('click', SELECTORS.VIEW_DAY_LINK, function(e) { @@ -193,9 +192,13 @@ function( .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) .join('&'); CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root, - 'core_calendar/calendar_day').then(function() { + 'core_calendar/calendar_day', isCalendarBlock).then(function() { e.preventDefault(); - return CalendarViewManager.updateUrl(urlParamString); + // Update the URL if it's not calendar block. + if (!isCalendarBlock) { + CalendarViewManager.updateUrl('?' + urlParamString); + } + return; }).catch(Notification.exception); } else { window.location.assign(Url.relativeUrl('calendar/view.php', urlParams)); @@ -266,10 +269,16 @@ function( }; return { - init: function(root) { + /** + * Initializes the calendar view manager and registers event listeners. + * + * @param {HTMLElement} root - The root element where the calendar view manager and event listeners will be attached. + * @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block. + */ + init: function(root, isCalendarBlock = false) { root = $(root); - CalendarViewManager.init(root); - registerEventListeners(root); + CalendarViewManager.init(root, 'month', isCalendarBlock); + registerEventListeners(root, isCalendarBlock); } }; }); diff --git a/calendar/amd/src/calendar_view.js b/calendar/amd/src/calendar_view.js index d03678e39cc..f631c950a56 100644 --- a/calendar/amd/src/calendar_view.js +++ b/calendar/amd/src/calendar_view.js @@ -86,11 +86,11 @@ function( }; return { - init: function(root, type) { + init: function(root, type, isCalendarBlock = false) { root = $(root); - CalendarViewManager.init(root, type); - registerEventListeners(root, type); + CalendarViewManager.init(root, type, isCalendarBlock); + registerEventListeners(root, type, isCalendarBlock); } }; }); diff --git a/calendar/amd/src/popover.js b/calendar/amd/src/popover.js index e4434dfb6ef..5a8cba46573 100644 --- a/calendar/amd/src/popover.js +++ b/calendar/amd/src/popover.js @@ -54,7 +54,8 @@ const showPopover = target => { content.html(temptContent.html()); } return content.html(); - } + }, + 'animation': false, }); isPopoverConfigured.set(dateContainer, true); @@ -64,6 +65,8 @@ const showPopover = target => { jQuery(target).popover('show'); target.addEventListener('mouseleave', hidePopover); target.addEventListener('focusout', hidePopover); + // Set up the hide function to the click event type. + target.addEventListener('click', hidePopover); } }; @@ -76,10 +79,23 @@ const hidePopover = e => { if (isPopoverConfigured.has(dateContainer)) { const isTargetActive = target.contains(document.activeElement); const isTargetHover = target.matches(':hover'); + + // Checks if a target element is clicked or pressed. + const isTargetClicked = document.activeElement.contains(target); + + let removeListener = true; if (!isTargetActive && !isTargetHover) { jQuery(target).popover('hide'); + } else if (isTargetClicked) { + jQuery(document.activeElement).popover('hide'); + } else { + removeListener = false; + } + + if (removeListener) { target.removeEventListener('mouseleave', hidePopover); target.removeEventListener('focusout', hidePopover); + target.removeEventListener('click', hidePopover); } } }; diff --git a/calendar/amd/src/view_manager.js b/calendar/amd/src/view_manager.js index 8289b5cb29c..91792a903b4 100644 --- a/calendar/amd/src/view_manager.js +++ b/calendar/amd/src/view_manager.js @@ -145,8 +145,9 @@ export const registerEventListenersForMonthDetailed = (pendingId) => { * Register event listeners for the module. * * @param {object} root The root element. + * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block. */ -const registerEventListeners = (root) => { +const registerEventListeners = (root, isCalendarBlock) => { root = $(root); // Bind click events to event links. @@ -192,10 +193,12 @@ const registerEventListeners = (root) => { const link = e.currentTarget; if (view === 'month' || view === 'monthblock') { - changeMonth(root, link.href, link.dataset.year, link.dataset.month, courseId, categoryId, link.dataset.day); + changeMonth(root, link.href, link.dataset.year, link.dataset.month, + courseId, categoryId, link.dataset.day, isCalendarBlock); e.preventDefault(); } else if (view === 'day') { - changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day, courseId, categoryId); + changeDay(root, link.href, link.dataset.year, link.dataset.month, link.dataset.day, + courseId, categoryId, isCalendarBlock); e.preventDefault(); } }); @@ -292,18 +295,19 @@ export const refreshMonthContent = (root, year, month, courseId, categoryId, tar * @param {number} courseId The id of the course whose events are shown * @param {number} categoryId The id of the category whose events are shown * @param {number} day Day (optional) + * @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block. * @return {promise} */ -export const changeMonth = (root, url, year, month, courseId, categoryId, day = 1) => { +export const changeMonth = (root, url, year, month, courseId, categoryId, day = 1, isCalendarBlock = false) => { return refreshMonthContent(root, year, month, courseId, categoryId, null, '', day) .then((...args) => { - if (url.length && url !== '#') { + if (url.length && url !== '#' && !isCalendarBlock) { updateUrl(url); } return args; }) .then((...args) => { - $('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId]); + $('body').trigger(CalendarEvents.monthChanged, [year, month, courseId, categoryId, day, isCalendarBlock]); return args; }); }; @@ -343,10 +347,12 @@ export const reloadCurrentMonth = (root, courseId = 0, categoryId = 0) => { * @param {number} categoryId The id of the category whose events are shown * @param {object} target The element being replaced. If not specified, the calendarwrapper is used. * @param {string} template The template to be rendered. + * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block. * * @return {promise} */ -export const refreshDayContent = (root, year, month, day, courseId, categoryId, target = null, template = '') => { +export const refreshDayContent = (root, year, month, day, courseId, categoryId, + target = null, template = '', isCalendarBlock = false) => { startLoading(root); if (!target || target.length == 0){ @@ -359,6 +365,7 @@ export const refreshDayContent = (root, year, month, day, courseId, categoryId, .then((context) => { context.viewingday = true; context.showviewselector = true; + context.iscalendarblock = isCalendarBlock; return Templates.render(template, context); }) .then((html, js) => { @@ -405,18 +412,19 @@ export const reloadCurrentDay = (root, courseId = 0, categoryId = 0) => { * @param {Number} day Day * @param {Number} courseId The id of the course whose events are shown * @param {Number} categoryId The id of the category whose events are shown + * @param {boolean} [isCalendarBlock=false] - A flag indicating whether this is a calendar block. * @return {promise} */ -export const changeDay = (root, url, year, month, day, courseId, categoryId) => { - return refreshDayContent(root, year, month, day, courseId, categoryId) +export const changeDay = (root, url, year, month, day, courseId, categoryId, isCalendarBlock = false) => { + return refreshDayContent(root, year, month, day, courseId, categoryId, null, '', isCalendarBlock) .then((...args) => { - if (url.length && url !== '#') { + if (url.length && url !== '#' && !isCalendarBlock) { updateUrl(url); } return args; }) .then((...args) => { - $('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId]); + $('body').trigger(CalendarEvents.dayChanged, [year, month, courseId, categoryId, isCalendarBlock]); return args; }); }; @@ -562,10 +570,18 @@ const renderEventSummaryModal = (eventId) => { .catch(Notification.exception); }; -export const init = (root, view) => { +/** + * Initializes the calendar component by prefetching strings, folding day events, + * and registering event listeners. + * + * @param {HTMLElement} root - The root element where the calendar view manager and event listeners will be attached. + * @param {string} view - A flag indicating whether this is a calendar block. + * @param {boolean} isCalendarBlock - A flag indicating whether this is a calendar block. + */ +export const init = (root, view, isCalendarBlock) => { prefetchStrings('calendar', ['moreevents']); foldDayEvents(); - registerEventListeners(root, view); + registerEventListeners(root, isCalendarBlock); const calendarTable = root.find(CalendarSelectors.elements.monthDetailed); if (calendarTable.length) { const pendingId = `month-detailed-${calendarTable.id}-filterChanged`; diff --git a/calendar/templates/calendar_day.mustache b/calendar/templates/calendar_day.mustache index e9ffd4375a8..c813b3143cd 100644 --- a/calendar/templates/calendar_day.mustache +++ b/calendar/templates/calendar_day.mustache @@ -29,6 +29,7 @@ Example context (json): { + "iscalendarblock": false } }}
          @@ -37,6 +38,7 @@
          {{#js}} require(['jquery', 'core_calendar/calendar_view'], function($, CalendarView) { - CalendarView.init($("#calendar-day-{{uniqid}}"), 'day'); + const isCalendarBlock = {{#iscalendarblock}}true{{/iscalendarblock}}{{^iscalendarblock}}false{{/iscalendarblock}}; + CalendarView.init($("#calendar-day-{{uniqid}}"), 'day', isCalendarBlock); }); {{/js}} diff --git a/calendar/templates/calendar_month.mustache b/calendar/templates/calendar_month.mustache index 28517c1e758..11f59abdcd6 100644 --- a/calendar/templates/calendar_month.mustache +++ b/calendar/templates/calendar_month.mustache @@ -29,6 +29,7 @@ Example context (json): { + "iscalendarblock": false } }}
          @@ -37,6 +38,7 @@
          {{#js}} require(['jquery', 'core_calendar/calendar', 'core_calendar/popover'], function($, Calendar, calendarPopover) { - Calendar.init($("#calendar-month-{{uniqid}}-{{calendarinstanceid}}")); + const isCalendarBlock = {{#iscalendarblock}}true{{/iscalendarblock}}{{^iscalendarblock}}false{{/iscalendarblock}}; + Calendar.init($("#calendar-month-{{uniqid}}-{{calendarinstanceid}}"), isCalendarBlock); }); {{/js}} diff --git a/calendar/tests/behat/behat_calendar.php b/calendar/tests/behat/behat_calendar.php index acc758bbd16..75c81ea333a 100644 --- a/calendar/tests/behat/behat_calendar.php +++ b/calendar/tests/behat/behat_calendar.php @@ -132,6 +132,26 @@ class behat_calendar extends behat_base { ); } + /** + * Click on a specific day in the mini-calendar. + * + * @Given /^I click on day "(?P\d+)" of this month in the mini-calendar block(?P responsive view|)$/ + * + * @param int $day The day of the current month. + * @param string $responsive If not null, find the responsive version of the link. + */ + public function i_click_on_day_of_this_month_in_mini_calendar_block(int $day, string $responsive = ''): void { + $this->execute( + contextapi: "behat_general::i_click_on_in_the", + params: [ + $day, + empty($responsive) ? 'core_calendar > calendar day' : 'core_calendar > responsive calendar day', + '', + 'core_calendar > mini calendar block', + ], + ); + } + /** * Hover over today in the mini-calendar. * @@ -144,6 +164,20 @@ class behat_calendar extends behat_base { $this->i_hover_over_day_of_this_month_in_mini_calendar_block($todaysday, $responsive); } + /** + * Click on today in the mini-calendar. + * + * @Given /^I click on today in the mini-calendar block( responsive view|)$/ + * + * @param string $responsive If not empty, use the responsive calendar link. + */ + public function i_click_on_today_in_mini_calendar_block(string $responsive = ''): void { + $this->i_click_on_day_of_this_month_in_mini_calendar_block( + day: date('j'), + responsive: $responsive, + ); + } + /** * Navigate to a specific month in the calendar. *