diff --git a/calendar/amd/build/calendar_threemonth.min.js b/calendar/amd/build/calendar_threemonth.min.js new file mode 100644 index 00000000000..ac1bb8cce4b --- /dev/null +++ b/calendar/amd/build/calendar_threemonth.min.js @@ -0,0 +1 @@ +define(["jquery","core_calendar/selectors","core_calendar/events","core/templates","core_calendar/view_manager"],function(a,b,c,d,e){var f=function(d){var f=a("body");f.on(c.monthChanged,function(a,b,c,e){d.queue(function(d){return g(a,b,c,e).then(function(){return d()})})});var g=function(c,f,g,h){var i=d.find('[data-year="'+f+'"][data-month="'+g+'"]'),j=i.closest(b.calendarPeriods.month),k=d.find(b.calendarPeriods.month),l=a(k[0]),m=a(k[2]),n=a("");n.attr("data-template","core_calendar/threemonth_month"),n.attr("data-includenavigation",!1);var o=a("
");o.hide(),o.append(n);var p,q,r;return j.is(l)?(o.insertBefore(l),p=l.data("previousYear"),q=l.data("previousMonth"),r=m):j.is(m)&&(o.insertAfter(m),p=m.data("nextYear"),q=m.data("nextMonth"),r=l),e.refreshMonthContent(n,p,q,h,n).then(function(){var b=a.Deferred(),c=a.Deferred();return r.slideUp("fast",function(){a(this).remove(),b.resolve()}),o.slideDown("fast",function(){c.resolve()}),a.when(b,c)})}};return{init:function(b){b=a(b),f(b)}}}); \ No newline at end of file diff --git a/calendar/amd/build/selectors.min.js b/calendar/amd/build/selectors.min.js index 8dbeb185f37..a81f332e0c2 100644 --- a/calendar/amd/build/selectors.min.js +++ b/calendar/amd/build/selectors.min.js @@ -1 +1 @@ -define([],function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]"},popoverType:{site:"[data-popover-eventtype-site]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]"}}}); \ No newline at end of file +define([],function(){return{eventFilterItem:"[data-action='filter-event-type']",eventType:{site:"[data-eventtype-site]",course:"[data-eventtype-course]",group:"[data-eventtype-group]",user:"[data-eventtype-user]"},popoverType:{site:"[data-popover-eventtype-site]",course:"[data-popover-eventtype-course]",group:"[data-popover-eventtype-group]",user:"[data-popover-eventtype-user]"},calendarPeriods:{month:"[data-period='month']"}}}); \ No newline at end of file diff --git a/calendar/amd/src/calendar_threemonth.js b/calendar/amd/src/calendar_threemonth.js new file mode 100644 index 00000000000..a043887dca3 --- /dev/null +++ b/calendar/amd/src/calendar_threemonth.js @@ -0,0 +1,123 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * This module handles display of multiple mini calendars in a view, and + * movement through them. + * + * @module core_calendar/calendar_threemonth + * @package core_calendar + * @copyright 2017 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define([ + 'jquery', + 'core_calendar/selectors', + 'core_calendar/events', + 'core/templates', + 'core_calendar/view_manager', +], +function( + $, + CalendarSelectors, + CalendarEvents, + Templates, + CalendarViewManager +) { + + /** + * Listen to and handle any calendar events fired by the calendar UI. + * + * @method registerCalendarEventListeners + * @param {object} root The calendar root element + */ + var registerCalendarEventListeners = function(root) { + var body = $('body'); + body.on(CalendarEvents.monthChanged, function(e, year, month, courseId) { + // We have to use a queue here because the calling code is decoupled from these listeners. + // It's possible for the event to be called multiple times before one call is fully resolved. + root.queue(function(next) { + return processRequest(e, year, month, courseId) + .then(function() { + return next(); + }); + }); + }); + + var processRequest = function(e, year, month, courseId) { + var newCurrentMonth = root.find('[data-year="' + year + '"][data-month="' + month + '"]'); + var newParent = newCurrentMonth.closest(CalendarSelectors.calendarPeriods.month); + var allMonths = root.find(CalendarSelectors.calendarPeriods.month); + + var previousMonth = $(allMonths[0]); + var nextMonth = $(allMonths[2]); + + var placeHolder = $(''); + placeHolder.attr('data-template', 'core_calendar/threemonth_month'); + placeHolder.attr('data-includenavigation', false); + var placeHolderContainer = $('
'); + placeHolderContainer.hide(); + placeHolderContainer.append(placeHolder); + + var requestYear; + var requestMonth; + var oldMonth; + + if (newParent.is(previousMonth)) { + // Fetch the new previous month. + placeHolderContainer.insertBefore(previousMonth); + + requestYear = previousMonth.data('previousYear'); + requestMonth = previousMonth.data('previousMonth'); + oldMonth = nextMonth; + } else if (newParent.is(nextMonth)) { + // Fetch the new next month. + placeHolderContainer.insertAfter(nextMonth); + requestYear = nextMonth.data('nextYear'); + requestMonth = nextMonth.data('nextMonth'); + oldMonth = previousMonth; + } + + return CalendarViewManager.refreshMonthContent( + placeHolder, + requestYear, + requestMonth, + courseId, + placeHolder + ) + .then(function() { + var slideUpPromise = $.Deferred(); + var slideDownPromise = $.Deferred(); + oldMonth.slideUp('fast', function() { + $(this).remove(); + slideUpPromise.resolve(); + }); + placeHolderContainer.slideDown('fast', function() { + slideDownPromise.resolve(); + }); + + return $.when(slideUpPromise, slideDownPromise); + }); + }; + }; + + return { + init: function(root) { + root = $(root); + + registerCalendarEventListeners(root); + } + }; +}); diff --git a/calendar/amd/src/selectors.js b/calendar/amd/src/selectors.js index 89bb65a5126..a22a86d9963 100644 --- a/calendar/amd/src/selectors.js +++ b/calendar/amd/src/selectors.js @@ -36,5 +36,8 @@ define([], function() { group: "[data-popover-eventtype-group]", user: "[data-popover-eventtype-user]", }, + calendarPeriods: { + month: "[data-period='month']", + }, }; }); diff --git a/calendar/classes/external/month_exporter.php b/calendar/classes/external/month_exporter.php index 3bed31f1079..bb599466c94 100644 --- a/calendar/classes/external/month_exporter.php +++ b/calendar/classes/external/month_exporter.php @@ -55,6 +55,7 @@ class month_exporter extends exporter { protected $url; /** + * @var bool $includenavigation Whether navigation should be included on the output. */ protected $includenavigation = true; @@ -349,6 +350,12 @@ class month_exporter extends exporter { return $type->timestamp_to_date_array($time); } + /** + * Set whether the navigation should be shown. + * + * @param bool $include + * @return $this + */ public function set_includenavigation($include) { $this->includenavigation = $include; diff --git a/calendar/lib.php b/calendar/lib.php index 1b8d9135f7d..9b4257ada8e 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -973,15 +973,29 @@ class calendar_information { $year = $date['year']; } if (checkdate($month, $day, $year)) { - $this->time = make_timestamp($year, $month, $day); + $time = make_timestamp($year, $month, $day); } else { - $this->time = time(); + $time = time(); } - } else if (!empty($time)) { - $this->time = $time; - } else { - $this->time = time(); } + + $this->set_time($time); + } + + /** + * Set the time period of this instance. + * + * @param int $time the unixtimestamp representing the date we want to view. + * @return $this + */ + public function set_time($time = null) { + if ($time === null) { + $this->time = time(); + } else { + $this->time = $time; + } + + return $this; } /** @@ -3383,7 +3397,7 @@ function calendar_get_view(\calendar_information $calendar, $view, $includenavig $monthdays = $type->get_num_days_in_month($date['year'], $date['mon']); $tend = $tstart + ($monthdays * DAYSECS) - 1; $selectortitle = get_string('detailedmonthviewfor', 'calendar'); - if ($view === 'mini') { + if ($view === 'mini' || $view === 'minithree') { $template = 'core_calendar/calendar_mini'; } else { $template = 'core_calendar/calendar_month'; diff --git a/calendar/renderer.php b/calendar/renderer.php index dc597abf2e6..c0ce327e0fb 100644 --- a/calendar/renderer.php +++ b/calendar/renderer.php @@ -61,31 +61,45 @@ class core_calendar_renderer extends plugin_renderer_base { public function fake_block_threemonths(calendar_information $calendar) { // Get the calendar type we are using. $calendartype = \core_calendar\type_factory::get_calendar_instance(); + $time = $calendartype->timestamp_to_date_array($calendar->time); - $date = $calendartype->timestamp_to_date_array($calendar->time); + $current = $calendar->time; + $prev = $calendartype->convert_to_timestamp( + $time['year'], + $time['mon'] - 1, + $time['mday'] + ); + $next = $calendartype->convert_to_timestamp( + $time['year'], + $time['mon'] + 1, + $time['mday'] + ); - $prevmonth = calendar_sub_month($date['mon'], $date['year']); - $prevmonthtime = $calendartype->convert_to_gregorian($prevmonth[1], $prevmonth[0], 1); - $prevmonthtime = make_timestamp($prevmonthtime['year'], $prevmonthtime['month'], $prevmonthtime['day'], - $prevmonthtime['hour'], $prevmonthtime['minute']); + $content = ''; - $nextmonth = calendar_add_month($date['mon'], $date['year']); - $nextmonthtime = $calendartype->convert_to_gregorian($nextmonth[1], $nextmonth[0], 1); - $nextmonthtime = make_timestamp($nextmonthtime['year'], $nextmonthtime['month'], $nextmonthtime['day'], - $nextmonthtime['hour'], $nextmonthtime['minute']); + // Previous. + $calendar->set_time($prev); + list($previousmonth, ) = calendar_get_view($calendar, 'minithree', false); - $content = html_writer::start_tag('div', array('class' => 'minicalendarblock')); - $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users, - false, false, 'display', $calendar->courseid, $prevmonthtime); - $content .= html_writer::end_tag('div'); - $content .= html_writer::start_tag('div', array('class' => 'minicalendarblock')); - $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users, - false, false, 'display', $calendar->courseid, $calendar->time); - $content .= html_writer::end_tag('div'); - $content .= html_writer::start_tag('div', array('class' => 'minicalendarblock')); - $content .= calendar_get_mini($calendar->courses, $calendar->groups, $calendar->users, - false, false, 'display', $calendar->courseid, $nextmonthtime); - $content .= html_writer::end_tag('div'); + // Current month. + $calendar->set_time($current); + list($currentmonth, ) = calendar_get_view($calendar, 'minithree', false); + + // Next month. + $calendar->set_time($next); + list($nextmonth, ) = calendar_get_view($calendar, 'minithree', false); + + // Reset the time back. + $calendar->set_time($current); + + $data = (object) [ + 'previousmonth' => $previousmonth, + 'currentmonth' => $currentmonth, + 'nextmonth' => $nextmonth, + ]; + + $template = 'core_calendar/calendar_threemonth'; + $content .= $this->render_from_template($template, $data); return $content; } diff --git a/calendar/templates/calendar_mini.mustache b/calendar/templates/calendar_mini.mustache index 8f639ed1dae..5b91ac6f08f 100644 --- a/calendar/templates/calendar_mini.mustache +++ b/calendar/templates/calendar_mini.mustache @@ -34,6 +34,7 @@ {{> core_calendar/month_mini}}
diff --git a/calendar/templates/calendar_threemonth.mustache b/calendar/templates/calendar_threemonth.mustache new file mode 100644 index 00000000000..b9e41b3d7fb --- /dev/null +++ b/calendar/templates/calendar_threemonth.mustache @@ -0,0 +1,49 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template calendar/calendar_threemonth + + Calendar view to show three months as a block. + + The purpose of this template is to render a set of three months of calendar_mini in a block. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Example context (json): + { + } +}} +
+ {{#previousmonth}} + {{> core_calendar/threemonth_month}} + {{/previousmonth}} + {{#currentmonth}} + {{> core_calendar/threemonth_month}} + {{/currentmonth}} + {{#nextmonth}} + {{> core_calendar/threemonth_month}} + {{/nextmonth}} +
+{{#js}} +require(['jquery', 'core_calendar/calendar_threemonth'], function($, CalendarThreeMonth) { + CalendarThreeMonth.init($("#calendar-multi-{{uniqid}}")); +}); +{{/js}} diff --git a/calendar/templates/threemonth_month.mustache b/calendar/templates/threemonth_month.mustache new file mode 100644 index 00000000000..8d175369a26 --- /dev/null +++ b/calendar/templates/threemonth_month.mustache @@ -0,0 +1,39 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template calendar/calendar_threemonth + + Calendar view to show three months as a block. + + The purpose of this template is to render a set of three months of calendar_mini in a block. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Example context (json): + { + } +}} +
+ {{> core_calendar/calendar_mini}} +