Merge branch 'MDL-59392-master' of git://github.com/andrewnicols/moodle
This commit is contained in:
@@ -70,29 +70,26 @@ class block_calendar_month extends block_base {
|
||||
if ($issite) {
|
||||
// Being displayed at site level. This will cause the filter to fall back to auto-detecting
|
||||
// the list of courses it will be grabbing events from.
|
||||
$filtercourse = calendar_get_default_courses();
|
||||
$course = get_site();
|
||||
$courses = calendar_get_default_courses();
|
||||
} else {
|
||||
// Forcibly filter events to include only those from the particular course we are in.
|
||||
$filtercourse = array($courseid => $this->page->course);
|
||||
$course = $this->page->course;
|
||||
$courses = [$course->id => $course];
|
||||
}
|
||||
|
||||
list($courses, $group, $user) = calendar_set_filters($filtercourse);
|
||||
if ($issite) {
|
||||
// For the front page.
|
||||
$this->content->text .= calendar_get_mini($courses, $group, $user, false, false,
|
||||
'frontpage', $courseid, $time);
|
||||
// No filters for now.
|
||||
} else {
|
||||
// For any other course.
|
||||
$this->content->text .= calendar_get_mini($courses, $group, $user, false, false,
|
||||
'course', $courseid, $time);
|
||||
$this->content->text .= '<h3 class="eventskey">'.get_string('eventskey', 'calendar').'</h3>';
|
||||
$this->content->text .= '<div class="filters calendar_filters">' .
|
||||
calendar_filter_controls($this->page->url) . '</div>';
|
||||
$renderer = $this->page->get_renderer('core_calendar');
|
||||
|
||||
$calendar = new calendar_information(0, 0, 0, $time);
|
||||
$calendar->prepare_for_view($course, $courses);
|
||||
|
||||
list($data, $template) = calendar_get_view($calendar, 'mini');
|
||||
$this->content->text .= $renderer->render_from_template($template, $data);
|
||||
|
||||
if (!$issite) {
|
||||
$this->content->text .= $renderer->event_filter();
|
||||
}
|
||||
|
||||
return $this->content;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ Feature: Enable the calendar block in a course and test it's functionality
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
When I add the "Calendar" block
|
||||
Then I should see "Events key" in the "Calendar" "block"
|
||||
Then "Calendar" "block" should exist
|
||||
|
||||
@javascript
|
||||
Scenario: View a global event in the calendar block
|
||||
@@ -136,9 +136,14 @@ Feature: Enable the calendar block in a course and test it's functionality
|
||||
And I press "Save and display"
|
||||
And I turn editing mode on
|
||||
And I add the "Calendar" block
|
||||
And I create a calendar event with form data:
|
||||
And I click on "This month" "link"
|
||||
And I click on "New event" "button"
|
||||
And I set the following fields to these values:
|
||||
| id_eventtype | Group |
|
||||
| id_name | Group Event |
|
||||
And I set the following fields to these values:
|
||||
| Group | Group 1 |
|
||||
And I press "Save"
|
||||
And I log out
|
||||
Then I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
@@ -150,7 +155,7 @@ Feature: Enable the calendar block in a course and test it's functionality
|
||||
And I hover over today in the calendar
|
||||
And I should not see "Group Event"
|
||||
|
||||
@javascript
|
||||
@javascript @arn
|
||||
Scenario: Filter group events in the calendar block
|
||||
Given the following "groups" exist:
|
||||
| name | course | idnumber |
|
||||
@@ -173,9 +178,14 @@ Feature: Enable the calendar block in a course and test it's functionality
|
||||
| id_eventtype | Course |
|
||||
| id_name | Course Event 1 |
|
||||
And I am on "Course 1" course homepage
|
||||
And I create a calendar event with form data:
|
||||
And I click on "This month" "link"
|
||||
And I click on "New event" "button"
|
||||
And I set the following fields to these values:
|
||||
| id_eventtype | Group |
|
||||
| id_name | Group Event 1 |
|
||||
And I set the following fields to these values:
|
||||
| Group | Group 1 |
|
||||
And I press "Save"
|
||||
And I log out
|
||||
Then I log in as "student1"
|
||||
And I am on "Course 1" course homepage
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
define(["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){var n={ROOT:"[data-region='calendar']",DAY:"[data-region='day']",EVENT_ITEM:"[data-region='event-item']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']",DAY_CONTENT:"[data-region='day-content']",LOADING_ICON:".loading-icon",VIEW_DAY_LINK:"[data-action='view-day-link']",CALENDAR_MONTH_WRAPPER:".calendarwrapper",COURSE_SELECTOR:'select[name="course"]'},o=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},p=function(a){return c.get_string("subsource","core_calendar",a).then(function(b){return a.url?'<a href="'+a.url+'">'+b+"</a>":b})},q=function(b){k.getEventById(b).then(function(c){if(!c.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+b);var d=c.event,e=o(d.eventtype);if(d.displayeventsource){d.subscription=JSON.parse(d.subscription);var f={url:d.subscription.url,name:d.subscription.name},g=p(f);return a.when(e,g).then(function(a,b){return d.eventtype=a,d.source=b,d})}return e.then(function(a){return d.eventtype=a,d})}).then(function(a){var b={title:a.name,type:j.TYPE,body:d.render("core_calendar/event_summary_body",a),templateContext:{canedit:a.canedit,candelete:a.candelete,isactionevent:a.isactionevent,url:a.url}};return h.create(b)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},r=function(b,c,f,g){var h=null,i=g.attr("data-day-timestamp");f&&(h=f.attr("data-day-timestamp")),f&&h==i||d.render("core/loading",{}).then(function(a,b){g.find(n.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(n.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(f,a,b))}).then(function(){return k.updateEventStartDay(c,i)}).then(function(){a("body").trigger(l.eventMoved,[c,f,g])}).always(function(){var a=g.find(n.LOADING_ICON);if(g.find(n.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(n.LOADING_ICON);f.find(n.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},s=function(a){var b=a.find(n.NEW_EVENT_BUTTON),c=b.attr("data-context-id");return h.create({type:i.TYPE,large:!0,templateContext:{contextid:c}},[a,n.NEW_EVENT_BUTTON])},t=function(b,c){var d=a("body"),e=a(b).find(n.CALENDAR_MONTH_WRAPPER).data("courseid");d.on(l.created,function(){m.reloadCurrentMonth(b)}),d.on(l.deleted,function(){m.reloadCurrentMonth(b)}),d.on(l.updated,function(){m.reloadCurrentMonth(b)}),d.on(l.editActionEvent,function(a,b){window.location.assign(b)}),d.on(l.moveEvent,r),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(b,c){a.setEventId(c),a.show()}),a.setCourseId(e)})},u=function(){var b=a(n.ROOT);b.on("click",n.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null;d=c.is(n.EVENT_LINK)?c.attr("data-event-id"):c.find(n.EVENT_LINK).attr("data-event-id"),q(d)}),b.on("change",n.COURSE_SELECTOR,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d).then(function(){return b.find(n.COURSE_SELECTOR).val(d)}).fail(e.exception)});var c=s(b);t(b,c),b.on("click",n.DAY,function(b){var d=a(b.target);if(!d.is(n.VIEW_DAY_LINK)){var e=a(this).attr("data-new-event-timestamp");c.then(function(a){a.setStartTime(e),a.show()}),b.preventDefault()}})};return{init:function(){m.init(),u()}}});
|
||||
define(["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_events","core/modal_factory","core_calendar/modal_event_form","core_calendar/summary_modal","core_calendar/repository","core_calendar/events","core_calendar/view_manager"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){var n={ROOT:"[data-region='calendar']",DAY:"[data-region='day']",EVENT_ITEM:"[data-region='event-item']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']",DAY_CONTENT:"[data-region='day-content']",LOADING_ICON:".loading-icon",VIEW_DAY_LINK:"[data-action='view-day-link']",CALENDAR_MONTH_WRAPPER:".calendarwrapper",COURSE_SELECTOR:'select[name="course"]'},o=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},p=function(a){return c.get_string("subsource","core_calendar",a).then(function(b){return a.url?'<a href="'+a.url+'">'+b+"</a>":b})},q=function(b){k.getEventById(b).then(function(c){if(!c.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+b);var d=c.event,e=o(d.eventtype);if(d.displayeventsource){d.subscription=JSON.parse(d.subscription);var f={url:d.subscription.url,name:d.subscription.name},g=p(f);return a.when(e,g).then(function(a,b){return d.eventtype=a,d.source=b,d})}return e.then(function(a){return d.eventtype=a,d})}).then(function(a){var b={title:a.name,type:j.TYPE,body:d.render("core_calendar/event_summary_body",a),templateContext:{canedit:a.canedit,candelete:a.candelete,isactionevent:a.isactionevent,url:a.url}};return h.create(b)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},r=function(b,c,f,g){var h=null,i=g.attr("data-day-timestamp");f&&(h=f.attr("data-day-timestamp")),f&&h==i||d.render("core/loading",{}).then(function(a,b){g.find(n.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(n.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(f,a,b))}).then(function(){return k.updateEventStartDay(c,i)}).then(function(){a("body").trigger(l.eventMoved,[c,f,g])}).always(function(){var a=g.find(n.LOADING_ICON);if(g.find(n.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(n.LOADING_ICON);f.find(n.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},s=function(a){var b=a.find(n.NEW_EVENT_BUTTON),c=b.attr("data-context-id");return h.create({type:i.TYPE,large:!0,templateContext:{contextid:c}},[a,n.NEW_EVENT_BUTTON])},t=function(b,c){var d=a("body"),e=a(b).find(n.CALENDAR_MONTH_WRAPPER).data("courseid");d.on(l.created,function(){m.reloadCurrentMonth(b)}),d.on(l.deleted,function(){m.reloadCurrentMonth(b)}),d.on(l.updated,function(){m.reloadCurrentMonth(b)}),d.on(l.editActionEvent,function(a,b){window.location.assign(b)}),d.on(l.moveEvent,r),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(b,c){a.setEventId(c),a.show()}),a.setCourseId(e)})},u=function(b){b.on("click",n.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null;d=c.is(n.EVENT_LINK)?c.attr("data-event-id"):c.find(n.EVENT_LINK).attr("data-event-id"),q(d)}),b.on("change",n.COURSE_SELECTOR,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d).then(function(){return b.find(n.COURSE_SELECTOR).val(d)}).fail(e.exception)});var c=s(b);t(b,c),b.on("click",n.DAY,function(b){var d=a(b.target);if(!d.is(n.VIEW_DAY_LINK)){var e=a(this).attr("data-new-event-timestamp");c.then(function(a){a.setStartTime(e),a.show()}),b.preventDefault()}})};return{init:function(b){b=a(b),m.init(b),u(b)}}});
|
||||
+1
@@ -0,0 +1 @@
|
||||
define(["jquery","core_calendar/selectors","core_calendar/events","core/str","core/templates"],function(a,b,c,d,e){var f=function(d){d.on("click",b.eventFilterItem,function(b){var c=a(b.currentTarget);g(c),b.preventDefault()}),a("body").on(c.viewUpdated,function(){var c=d.find(b.eventFilterItem);c.each(function(b,c){if(c=a(c),c.data("eventtype-hidden")){var d=i(c);h(d)}})})},g=function(a){var b=i(a);return b.hidden=!b.hidden,d.get_string("eventtype"+b.type,"calendar").then(function(a){return b.name=a,b}).then(function(a){return e.render("core_calendar/event_filter_key",a)}).then(function(b,c){return e.replaceNode(a,b,c)}).then(function(){h(b)})},h=function(b){M.util.js_pending("month-mini-filterChanged"),a("body").trigger(c.filterChanged,{type:b.type,hidden:b.hidden}),M.util.js_complete("month-mini-filterChanged")},i=function(a){return{type:a.data("eventtype"),hidden:a.data("eventtype-hidden")}};return{init:function(b){b=a(b),f(b)}}});
|
||||
+1
@@ -0,0 +1 @@
|
||||
define(["jquery","core_calendar/selectors","core_calendar/events","core_calendar/view_manager"],function(a,b,c,d){var e=function(d){a("body").on(c.filterChanged,function(a,c){var e=d.find(b.eventType[c.type]);e.toggleClass("calendar_event_"+c.type,!c.hidden)})};return{init:function(b){b=a(b),d.init(b),e(b)}}});
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
define([],function(){return{created:"calendar-events:created",deleted:"calendar-events:deleted",updated:"calendar-events:updated",editEvent:"calendar-events:edit_event",editActionEvent:"calendar-events:edit_action_event",eventMoved:"calendar-events:event_moved",monthChanged:"calendar-events:month_changed",moveEvent:"calendar-events:move_event"}});
|
||||
define([],function(){return{created:"calendar-events:created",deleted:"calendar-events:deleted",updated:"calendar-events:updated",editEvent:"calendar-events:edit_event",editActionEvent:"calendar-events:edit_action_event",eventMoved:"calendar-events:event_moved",monthChanged:"calendar-events:month_changed",moveEvent:"calendar-events:move_event",filterChanged:"calendar-events:filter_changed",viewUpdated:"calendar-events:view_updated"}});
|
||||
Vendored
+1
@@ -0,0 +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]"}}});
|
||||
+1
-1
@@ -1 +1 @@
|
||||
define(["jquery","core/templates","core/notification","core_calendar/repository","core_calendar/events"],function(a,b,c,d,e){var f={ROOT:"[data-region='calendar']",CALENDAR_NAV_LINK:".calendarwrapper .arrow_link",CALENDAR_MONTH_WRAPPER:".calendarwrapper",LOADING_ICON_CONTAINER:'[data-region="overlay-icon-container"]'},g=function(b){b=a(b),b.on("click",f.CALENDAR_NAV_LINK,function(c){var d=a(b).find(f.CALENDAR_MONTH_WRAPPER).data("courseid"),e=a(c.currentTarget);i(e.attr("href"),e.data("time"),d),c.preventDefault()})},h=function(e,g){var h=a(f.ROOT);return k(h),d.getCalendarMonthData(e,g).then(function(a){return b.render("core_calendar/month_detailed",a)}).then(function(a,c){return b.replaceNode(f.CALENDAR_MONTH_WRAPPER,a,c)}).always(function(){return l(h)}).fail(c.exception)},i=function(b,c,d){return h(c,d).then(function(){return window.history.pushState({},"",b),arguments}).then(function(){return a("body").trigger(e.monthChanged,[c,d]),arguments})},j=function(a,b){var c=a.find(f.CALENDAR_MONTH_WRAPPER).data("current-time");return b||(b=a.find(f.CALENDAR_MONTH_WRAPPER).data("courseid")),h(c,b)},k=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.removeClass("hidden")},l=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.addClass("hidden")};return{init:function(){g(f.ROOT)},reloadCurrentMonth:j,changeMonth:i,refreshMonthContent:h}});
|
||||
define(["jquery","core/templates","core/notification","core_calendar/repository","core_calendar/events"],function(a,b,c,d,e){var f={ROOT:"[data-region='calendar']",CALENDAR_NAV_LINK:".calendarwrapper .arrow_link",CALENDAR_MONTH_WRAPPER:".calendarwrapper",LOADING_ICON_CONTAINER:'[data-region="overlay-icon-container"]'},g=function(b){b=a(b),b.on("click",f.CALENDAR_NAV_LINK,function(c){var d=a(b).find(f.CALENDAR_MONTH_WRAPPER).data("courseid"),e=a(c.currentTarget);i(b,e.attr("href"),e.data("time"),d),c.preventDefault()})},h=function(g,h,i){return k(g),d.getCalendarMonthData(h,i).then(function(a){return b.render(g.attr("data-template"),a)}).then(function(a,c){return b.replaceNode(g.find(f.CALENDAR_MONTH_WRAPPER),a,c)}).then(function(){a("body").trigger(e.viewUpdated)}).always(function(){return l(g)}).fail(c.exception)},i=function(b,c,d,f){return h(b,d,f).then(function(){return c.length&&"#"!==c&&window.history.pushState({},"",c),arguments}).then(function(){return a("body").trigger(e.monthChanged,[d,f]),arguments})},j=function(a,b){var c=a.find(f.CALENDAR_MONTH_WRAPPER).data("current-time");return b||(b=a.find(f.CALENDAR_MONTH_WRAPPER).data("courseid")),h(a,c,b)},k=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.removeClass("hidden")},l=function(a){var b=a.find(f.LOADING_ICON_CONTAINER);b.addClass("hidden")};return{init:function(a){g(a)},reloadCurrentMonth:j,changeMonth:i,refreshMonthContent:h}});
|
||||
@@ -296,9 +296,7 @@ define([
|
||||
/**
|
||||
* Register event listeners for the module.
|
||||
*/
|
||||
var registerEventListeners = function() {
|
||||
var root = $(SELECTORS.ROOT);
|
||||
|
||||
var registerEventListeners = function(root) {
|
||||
// Bind click events to event links.
|
||||
root.on('click', SELECTORS.EVENT_ITEM, function(e) {
|
||||
e.preventDefault();
|
||||
@@ -350,9 +348,11 @@ define([
|
||||
};
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
CalendarViewManager.init();
|
||||
registerEventListeners();
|
||||
init: function(root) {
|
||||
root = $(root);
|
||||
|
||||
CalendarViewManager.init(root);
|
||||
registerEventListeners(root);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This module is responsible for the calendar filter.
|
||||
*
|
||||
* @module core_calendar/calendar_filter
|
||||
* @package core_calendar
|
||||
* @copyright 2017 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core_calendar/selectors',
|
||||
'core_calendar/events',
|
||||
'core/str',
|
||||
'core/templates',
|
||||
],
|
||||
function(
|
||||
$,
|
||||
CalendarSelectors,
|
||||
CalendarEvents,
|
||||
Str,
|
||||
Templates
|
||||
) {
|
||||
|
||||
var registerEventListeners = function(root) {
|
||||
root.on('click', CalendarSelectors.eventFilterItem, function(e) {
|
||||
var target = $(e.currentTarget);
|
||||
|
||||
toggleFilter(target);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$('body').on(CalendarEvents.viewUpdated, function() {
|
||||
var filters = root.find(CalendarSelectors.eventFilterItem);
|
||||
|
||||
filters.each(function(i, filter) {
|
||||
filter = $(filter);
|
||||
if (filter.data('eventtype-hidden')) {
|
||||
var data = getFilterData(filter);
|
||||
fireFilterChangedEvent(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var toggleFilter = function(target) {
|
||||
var data = getFilterData(target);
|
||||
|
||||
// Toggle the hidden. We need to render the template before we change the value.
|
||||
data.hidden = !data.hidden;
|
||||
|
||||
return Str.get_string('eventtype' + data.type, 'calendar')
|
||||
.then(function(nameStr) {
|
||||
data.name = nameStr;
|
||||
|
||||
return data;
|
||||
})
|
||||
.then(function(context) {
|
||||
return Templates.render('core_calendar/event_filter_key', context);
|
||||
})
|
||||
.then(function(html, js) {
|
||||
return Templates.replaceNode(target, html, js);
|
||||
})
|
||||
.then(function() {
|
||||
fireFilterChangedEvent(data);
|
||||
return;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire the filterChanged event for the specified data.
|
||||
*
|
||||
* @param {object} data The data to include
|
||||
*/
|
||||
var fireFilterChangedEvent = function(data) {
|
||||
M.util.js_pending("month-mini-filterChanged");
|
||||
$('body').trigger(CalendarEvents.filterChanged, {
|
||||
type: data.type,
|
||||
hidden: data.hidden,
|
||||
});
|
||||
M.util.js_complete("month-mini-filterChanged");
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the filter data for the specified target.
|
||||
*
|
||||
* @param {jQuery} target The target node
|
||||
* @return {Object}
|
||||
*/
|
||||
var getFilterData = function(target) {
|
||||
return {
|
||||
type: target.data('eventtype'),
|
||||
hidden: target.data('eventtype-hidden'),
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
init: function(root) {
|
||||
root = $(root);
|
||||
|
||||
registerEventListeners(root);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This module is the highest level module for the calendar. It is
|
||||
* responsible for initialising all of the components required for
|
||||
* the calendar to run. It also coordinates the interaction between
|
||||
* components by listening for and responding to different events
|
||||
* triggered within the calendar UI.
|
||||
*
|
||||
* @module core_calendar/calendar
|
||||
* @package core_calendar
|
||||
* @copyright 2017 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([
|
||||
'jquery',
|
||||
'core_calendar/selectors',
|
||||
'core_calendar/events',
|
||||
'core_calendar/view_manager',
|
||||
],
|
||||
function(
|
||||
$,
|
||||
CalendarSelectors,
|
||||
CalendarEvents,
|
||||
CalendarViewManager
|
||||
) {
|
||||
|
||||
var registerEventListeners = function(root) {
|
||||
$('body').on(CalendarEvents.filterChanged, function(e, data) {
|
||||
var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);
|
||||
|
||||
daysWithEvent.toggleClass('calendar_event_' + data.type, !data.hidden);
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
init: function(root) {
|
||||
root = $(root);
|
||||
|
||||
CalendarViewManager.init(root);
|
||||
registerEventListeners(root);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -31,6 +31,8 @@ define([], function() {
|
||||
editActionEvent: 'calendar-events:edit_action_event',
|
||||
eventMoved: 'calendar-events:event_moved',
|
||||
monthChanged: 'calendar-events:month_changed',
|
||||
moveEvent: 'calendar-events:move_event'
|
||||
moveEvent: 'calendar-events:move_event',
|
||||
filterChanged: 'calendar-events:filter_changed',
|
||||
viewUpdated: 'calendar-events:view_updated',
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This module is responsible for the calendar filter.
|
||||
*
|
||||
* @module core_calendar/calendar_selectors
|
||||
* @package core_calendar
|
||||
* @copyright 2017 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
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]",
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -42,7 +42,7 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
|
||||
root.on('click', SELECTORS.CALENDAR_NAV_LINK, function(e) {
|
||||
var courseId = $(root).find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('courseid');
|
||||
var link = $(e.currentTarget);
|
||||
changeMonth(link.attr('href'), link.data('time'), courseId);
|
||||
changeMonth(root, link.attr('href'), link.data('time'), courseId);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
@@ -55,17 +55,19 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
|
||||
* @param {Number} courseid The id of the course whose events are shown
|
||||
* @return {promise}
|
||||
*/
|
||||
var refreshMonthContent = function(time, courseid) {
|
||||
var root = $(SELECTORS.ROOT);
|
||||
|
||||
var refreshMonthContent = function(root, time, courseid) {
|
||||
startLoading(root);
|
||||
|
||||
return CalendarRepository.getCalendarMonthData(time, courseid)
|
||||
.then(function(context) {
|
||||
return Templates.render('core_calendar/month_detailed', context);
|
||||
return Templates.render(root.attr('data-template'), context);
|
||||
})
|
||||
.then(function(html, js) {
|
||||
return Templates.replaceNode(SELECTORS.CALENDAR_MONTH_WRAPPER, html, js);
|
||||
return Templates.replaceNode(root.find(SELECTORS.CALENDAR_MONTH_WRAPPER), html, js);
|
||||
})
|
||||
.then(function() {
|
||||
$('body').trigger(CalendarEvents.viewUpdated);
|
||||
return;
|
||||
})
|
||||
.always(function() {
|
||||
return stopLoading(root);
|
||||
@@ -81,10 +83,12 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
|
||||
* @param {Number} courseid The id of the course whose events are shown
|
||||
* @return {promise}
|
||||
*/
|
||||
var changeMonth = function(url, time, courseid) {
|
||||
return refreshMonthContent(time, courseid)
|
||||
var changeMonth = function(root, url, time, courseid) {
|
||||
return refreshMonthContent(root, time, courseid)
|
||||
.then(function() {
|
||||
window.history.pushState({}, '', url);
|
||||
if (url.length && url !== '#') {
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
return arguments;
|
||||
})
|
||||
.then(function() {
|
||||
@@ -106,7 +110,7 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
|
||||
if (!courseId) {
|
||||
courseId = root.find(SELECTORS.CALENDAR_MONTH_WRAPPER).data('courseid');
|
||||
}
|
||||
return refreshMonthContent(time, courseId);
|
||||
return refreshMonthContent(root, time, courseId);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -134,8 +138,8 @@ define(['jquery', 'core/templates', 'core/notification', 'core_calendar/reposito
|
||||
};
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
registerEventListeners(SELECTORS.ROOT);
|
||||
init: function(root) {
|
||||
registerEventListeners(root);
|
||||
},
|
||||
reloadCurrentMonth: reloadCurrentMonth,
|
||||
changeMonth: changeMonth,
|
||||
|
||||
@@ -47,6 +47,16 @@ class calendar_event_exporter extends event_exporter_base {
|
||||
|
||||
$values = parent::define_other_properties();
|
||||
$values['url'] = ['type' => PARAM_URL];
|
||||
$values['islastday'] = [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
];
|
||||
$values['calendareventtype'] = [
|
||||
'type' => PARAM_TEXT,
|
||||
];
|
||||
$values['popupname'] = [
|
||||
'type' => PARAM_RAW,
|
||||
];
|
||||
|
||||
return $values;
|
||||
}
|
||||
@@ -58,6 +68,8 @@ class calendar_event_exporter extends event_exporter_base {
|
||||
* @return array Keys are the property names, values are their values.
|
||||
*/
|
||||
protected function get_other_values(renderer_base $output) {
|
||||
global $CFG;
|
||||
|
||||
$values = parent::get_other_values($output);
|
||||
|
||||
$eventid = $this->event->get_id();
|
||||
@@ -65,6 +77,55 @@ class calendar_event_exporter extends event_exporter_base {
|
||||
$url = new \moodle_url($this->related['daylink'], [], "event_{$eventid}");
|
||||
$values['url'] = $url->out(false);
|
||||
|
||||
$values['islastday'] = false;
|
||||
$today = $this->related['type']->timestamp_to_date_array($this->related['today']);
|
||||
|
||||
$values['popupname'] = $this->event->get_name();
|
||||
|
||||
$times = $this->event->get_times();
|
||||
if ($duration = $times->get_duration()) {
|
||||
$enddate = $this->related['type']->timestamp_to_date_array($times->get_end_time()->getTimestamp());
|
||||
$values['islastday'] = true;
|
||||
$values['islastday'] = $values['islastday'] && $enddate['year'] == $today['year'];
|
||||
$values['islastday'] = $values['islastday'] && $enddate['mon'] == $today['mon'];
|
||||
$values['islastday'] = $values['islastday'] && $enddate['mday'] == $today['mday'];
|
||||
}
|
||||
|
||||
$subscription = $this->event->get_subscription();
|
||||
if ($subscription && !empty($subscription->get('id')) && $CFG->calendar_showicalsource) {
|
||||
$a = (object) [
|
||||
'name' => $values['popupname'],
|
||||
'source' => $subscription->get('name'),
|
||||
];
|
||||
$values['popupname'] = get_string('namewithsource', 'calendar', $a);
|
||||
} else {
|
||||
if ($values['islastday']) {
|
||||
$startdate = $this->related['type']->timestamp_to_date_array($times->get_start_time()->getTimestamp());
|
||||
$samedate = true;
|
||||
$samedate = $samedate && $startdate['mon'] == $enddate['mon'];
|
||||
$samedate = $samedate && $startdate['year'] == $enddate['year'];
|
||||
$samedate = $samedate && $startdate['mday'] == $enddate['mday'];
|
||||
|
||||
if (!$samedate) {
|
||||
$values['popupname'] = get_string('eventendtimewrapped', 'calendar', $values['popupname']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include course's shortname into the event name, if applicable.
|
||||
$course = $this->event->get_course();
|
||||
if ($course && $course->get('id') && $course->get('id') !== SITEID) {
|
||||
$eventnameparams = (object) [
|
||||
'name' => $values['popupname'],
|
||||
'course' => format_string($course->get('shortname'), true, [
|
||||
'context' => $this->related['context'],
|
||||
])
|
||||
];
|
||||
$values['popupname'] = get_string('eventnameandcourse', 'calendar', $eventnameparams);
|
||||
}
|
||||
|
||||
$values['calendareventtype'] = $this->get_calendar_event_type();
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
@@ -76,7 +137,24 @@ class calendar_event_exporter extends event_exporter_base {
|
||||
protected static function define_related() {
|
||||
$related = parent::define_related();
|
||||
$related['daylink'] = \moodle_url::class;
|
||||
$related['type'] = '\core_calendar\type_base';
|
||||
$related['today'] = 'int';
|
||||
|
||||
return $related;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the normalised event type.
|
||||
* Activity events are normalised to be course events.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_calendar_event_type() {
|
||||
$type = $this->event->get_type();
|
||||
if ($type == 'open' || $type == 'close') {
|
||||
$type = 'course';
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
|
||||
+88
-11
@@ -39,6 +39,24 @@ use moodle_url;
|
||||
*/
|
||||
class day_exporter extends exporter {
|
||||
|
||||
/**
|
||||
* @var \calendar_information $calendar The calendar being displayed.
|
||||
*/
|
||||
protected $calendar;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \calendar_information $calendar The calendar information for the period being displayed
|
||||
* @param mixed $data Either an stdClass or an array of values.
|
||||
* @param array $related Related objects.
|
||||
*/
|
||||
public function __construct(\calendar_information $calendar, $data, $related) {
|
||||
$this->calendar = $calendar;
|
||||
|
||||
parent::__construct($data, $related);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of properties.
|
||||
*
|
||||
@@ -69,6 +87,15 @@ class day_exporter extends exporter {
|
||||
'yday' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
// These are additional params.
|
||||
'istoday' => [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
],
|
||||
'isweekend' => [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -85,14 +112,6 @@ class day_exporter extends exporter {
|
||||
'neweventtimestamp' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'istoday' => [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
],
|
||||
'isweekend' => [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
],
|
||||
'viewdaylink' => [
|
||||
'type' => PARAM_URL,
|
||||
'optional' => true,
|
||||
@@ -100,7 +119,19 @@ class day_exporter extends exporter {
|
||||
'events' => [
|
||||
'type' => calendar_event_exporter::read_properties_definition(),
|
||||
'multiple' => true,
|
||||
]
|
||||
],
|
||||
'calendareventtypes' => [
|
||||
'type' => PARAM_RAW,
|
||||
'multiple' => true,
|
||||
],
|
||||
'popovertitle' => [
|
||||
'type' => PARAM_RAW,
|
||||
'default' => '',
|
||||
],
|
||||
'haslastdayofevent' => [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -131,22 +162,46 @@ class day_exporter extends exporter {
|
||||
$url = new moodle_url('/calendar/view.php', [
|
||||
'view' => 'day',
|
||||
'time' => $timestamp,
|
||||
'course' => $this->calendar->course->id,
|
||||
]);
|
||||
$return['viewdaylink'] = $url->out(false);
|
||||
|
||||
$cache = $this->related['cache'];
|
||||
$return['events'] = array_map(function($event) use ($cache, $output, $url) {
|
||||
$eventexporters = array_map(function($event) use ($cache, $output, $url) {
|
||||
$context = $cache->get_context($event);
|
||||
$course = $cache->get_course($event);
|
||||
$exporter = new calendar_event_exporter($event, [
|
||||
'context' => $context,
|
||||
'course' => $course,
|
||||
'daylink' => $url,
|
||||
'type' => $this->related['type'],
|
||||
'today' => $this->data[0],
|
||||
]);
|
||||
|
||||
return $exporter->export($output);
|
||||
return $exporter;
|
||||
}, $this->related['events']);
|
||||
|
||||
$return['events'] = array_map(function($exporter) use ($output) {
|
||||
return $exporter->export($output);
|
||||
}, $eventexporters);
|
||||
|
||||
if ($popovertitle = $this->get_popover_title()) {
|
||||
$return['popovertitle'] = $popovertitle;
|
||||
}
|
||||
|
||||
$return['calendareventtypes'] = array_map(function($exporter) {
|
||||
return $exporter->get_calendar_event_type();
|
||||
}, $eventexporters);
|
||||
$return['calendareventtypes'] = array_values(array_unique($return['calendareventtypes']));
|
||||
|
||||
$return['haslastdayofevent'] = false;
|
||||
foreach ($return['events'] as $event) {
|
||||
if ($event->islastday) {
|
||||
$return['haslastdayofevent'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -162,4 +217,26 @@ class day_exporter extends exporter {
|
||||
'type' => '\core_calendar\type_base',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the title for this popover.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_popover_title() {
|
||||
$title = null;
|
||||
|
||||
$userdate = userdate($this->data[0], get_string('strftimedayshort'));
|
||||
if (count($this->related['events'])) {
|
||||
$title = get_string('eventsfor', 'calendar', $userdate);
|
||||
} else if ($this->data['istoday']) {
|
||||
$title = $userdate;
|
||||
}
|
||||
|
||||
if ($this->data['istoday']) {
|
||||
$title = get_string('todayplustitle', 'calendar', $userdate);
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
}
|
||||
|
||||
+54
-11
@@ -76,7 +76,19 @@ class month_exporter extends exporter {
|
||||
|
||||
$related['type'] = $type;
|
||||
|
||||
parent::__construct([], $related);
|
||||
$data = [
|
||||
'url' => $this->url->out(false),
|
||||
];
|
||||
|
||||
parent::__construct($data, $related);
|
||||
}
|
||||
|
||||
protected static function define_properties() {
|
||||
return [
|
||||
'url' => [
|
||||
'type' => PARAM_URL,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,15 +118,38 @@ class month_exporter extends exporter {
|
||||
'view' => [
|
||||
'type' => PARAM_ALPHA,
|
||||
],
|
||||
'time' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'periodname' => [
|
||||
// Note: We must use RAW here because the calendar type returns the formatted month name based on a
|
||||
// calendar format.
|
||||
'type' => PARAM_RAW,
|
||||
],
|
||||
'previousperiod' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'previousperiodname' => [
|
||||
// Note: We must use RAW here because the calendar type returns the formatted month name based on a
|
||||
// calendar format.
|
||||
'type' => PARAM_RAW,
|
||||
],
|
||||
'nextperiod' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'time' => [
|
||||
'type' => PARAM_INT,
|
||||
]
|
||||
'nextperiodname' => [
|
||||
// Note: We must use RAW here because the calendar type returns the formatted month name based on a
|
||||
// calendar format.
|
||||
'type' => PARAM_RAW,
|
||||
],
|
||||
'larrow' => [
|
||||
// The left arrow defined by the theme.
|
||||
'type' => PARAM_RAW,
|
||||
],
|
||||
'rarrow' => [
|
||||
// The right arrow defined by the theme.
|
||||
'type' => PARAM_RAW,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -125,16 +160,24 @@ class month_exporter extends exporter {
|
||||
* @return array Keys are the property names, values are their values.
|
||||
*/
|
||||
protected function get_other_values(renderer_base $output) {
|
||||
$previousperiod = $this->get_previous_month_timestamp();
|
||||
$nextperiod = $this->get_next_month_timestamp();
|
||||
|
||||
return [
|
||||
'courseid' => $this->calendar->courseid,
|
||||
'view' => 'month',
|
||||
'previousperiod' => $this->get_previous_month_timestamp(),
|
||||
'nextperiod' => $this->get_next_month_timestamp(),
|
||||
'filter_selector' => $this->get_course_filter_selector($output),
|
||||
'navigation' => $this->get_navigation($output),
|
||||
'weeks' => $this->get_weeks($output),
|
||||
'daynames' => $this->get_day_names($output),
|
||||
'time' => $this->calendar->time
|
||||
'view' => 'month',
|
||||
'time' => $this->calendar->time,
|
||||
'periodname' => userdate($this->calendar->time, get_string('strftimemonthyear')),
|
||||
'previousperiod' => $previousperiod,
|
||||
'previousperiodname' => userdate($previousperiod, get_string('strftimemonthyear')),
|
||||
'nextperiod' => $nextperiod,
|
||||
'nextperiodname' => userdate($nextperiod, get_string('strftimemonthyear')),
|
||||
'larrow' => $output->larrow(),
|
||||
'rarrow' => $output->rarrow(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -213,13 +256,13 @@ class month_exporter extends exporter {
|
||||
$prepadding = ($firstdayno + $daysinweek - 1) % $daysinweek;
|
||||
$daysinfirstweek = $daysinweek - $prepadding;
|
||||
$days = array_slice($alldays, 0, $daysinfirstweek);
|
||||
$week = new week_exporter($days, $prepadding, ($daysinweek - count($days) - $prepadding), $this->related);
|
||||
$week = new week_exporter($this->calendar, $days, $prepadding, ($daysinweek - count($days) - $prepadding), $this->related);
|
||||
$weeks[] = $week->export($output);
|
||||
|
||||
// Now chunk up the remaining day. and turn them into weeks.
|
||||
$daychunks = array_chunk(array_slice($alldays, $daysinfirstweek), $daysinweek);
|
||||
foreach ($daychunks as $days) {
|
||||
$week = new week_exporter($days, 0, ($daysinweek - count($days)), $this->related);
|
||||
$week = new week_exporter($this->calendar, $days, 0, ($daysinweek - count($days)), $this->related);
|
||||
$weeks[] = $week->export($output);
|
||||
}
|
||||
|
||||
@@ -279,7 +322,7 @@ class month_exporter extends exporter {
|
||||
*/
|
||||
protected function get_next_month_timestamp() {
|
||||
$date = $this->related['type']->timestamp_to_date_array($this->calendar->time);
|
||||
$month = calendar_sub_month($date['mon'], $date['year']);
|
||||
$month = calendar_add_month($date['mon'], $date['year']);
|
||||
$monthtime = $this->related['type']->convert_to_gregorian($month[1], $month[0], 1);
|
||||
|
||||
return make_timestamp($monthtime['year'], $monthtime['month'], $monthtime['day'], $monthtime['hour'], $monthtime['minute']);
|
||||
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Contains event class for displaying the day on month view.
|
||||
*
|
||||
* @package core_calendar
|
||||
* @copyright 2017 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_calendar\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use renderer_base;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Class for displaying the day on month view.
|
||||
*
|
||||
* @package core_calendar
|
||||
* @copyright 2017 Andrew Nicols <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class week_day_exporter extends day_exporter {
|
||||
|
||||
/**
|
||||
* Return the list of additional properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_other_properties() {
|
||||
$return = parent::define_other_properties();
|
||||
$return = array_merge($return, [
|
||||
'timestamp' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'neweventtimestamp' => [
|
||||
'type' => PARAM_INT,
|
||||
],
|
||||
'viewdaylink' => [
|
||||
'type' => PARAM_URL,
|
||||
'optional' => true,
|
||||
],
|
||||
'calendareventtypes' => [
|
||||
'type' => PARAM_RAW,
|
||||
'multiple' => true,
|
||||
],
|
||||
'popovertitle' => [
|
||||
'type' => PARAM_RAW,
|
||||
'default' => '',
|
||||
],
|
||||
'haslastdayofevent' => [
|
||||
'type' => PARAM_BOOL,
|
||||
'default' => false,
|
||||
],
|
||||
]);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the additional values to inject while exporting.
|
||||
*
|
||||
* @param renderer_base $output The renderer.
|
||||
* @return array Keys are the property names, values are their values.
|
||||
*/
|
||||
protected function get_other_values(renderer_base $output) {
|
||||
$timestamp = $this->data[0];
|
||||
// Need to account for user's timezone.
|
||||
$usernow = usergetdate(time());
|
||||
$today = new \DateTimeImmutable();
|
||||
// The start time should use the day's date but the current
|
||||
// time of the day (adjusted for user's timezone).
|
||||
$neweventstarttime = $today->setTimestamp($timestamp)->setTime(
|
||||
$usernow['hours'],
|
||||
$usernow['minutes'],
|
||||
$usernow['seconds']
|
||||
);
|
||||
|
||||
$return = [
|
||||
'timestamp' => $timestamp,
|
||||
'neweventtimestamp' => $neweventstarttime->getTimestamp()
|
||||
];
|
||||
|
||||
$url = new moodle_url('/calendar/view.php', [
|
||||
'view' => 'day',
|
||||
'time' => $timestamp,
|
||||
'course' => $this->calendar->course->id,
|
||||
]);
|
||||
$return['viewdaylink'] = $url->out(false);
|
||||
|
||||
$cache = $this->related['cache'];
|
||||
$eventexporters = array_map(function($event) use ($cache, $output, $url) {
|
||||
$context = $cache->get_context($event);
|
||||
$course = $cache->get_course($event);
|
||||
$exporter = new calendar_event_exporter($event, [
|
||||
'context' => $context,
|
||||
'course' => $course,
|
||||
'daylink' => $url,
|
||||
'type' => $this->related['type'],
|
||||
'today' => $this->data[0],
|
||||
]);
|
||||
|
||||
return $exporter;
|
||||
}, $this->related['events']);
|
||||
|
||||
$return['events'] = array_map(function($exporter) use ($output) {
|
||||
return $exporter->export($output);
|
||||
}, $eventexporters);
|
||||
|
||||
if ($popovertitle = $this->get_popover_title()) {
|
||||
$return['popovertitle'] = $popovertitle;
|
||||
}
|
||||
|
||||
$return['calendareventtypes'] = array_map(function($exporter) {
|
||||
return $exporter->get_calendar_event_type();
|
||||
}, $eventexporters);
|
||||
$return['calendareventtypes'] = array_values(array_unique($return['calendareventtypes']));
|
||||
|
||||
$return['haslastdayofevent'] = false;
|
||||
foreach ($return['events'] as $event) {
|
||||
if ($event->islastday) {
|
||||
$return['haslastdayofevent'] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of objects that are related.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function define_related() {
|
||||
return [
|
||||
'events' => '\core_calendar\local\event\entities\event_interface[]',
|
||||
'cache' => '\core_calendar\external\events_related_objects_cache',
|
||||
'type' => '\core_calendar\type_base',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the title for this popover.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_popover_title() {
|
||||
$title = null;
|
||||
|
||||
$userdate = userdate($this->data[0], get_string('strftimedayshort'));
|
||||
if (count($this->related['events'])) {
|
||||
$title = get_string('eventsfor', 'calendar', $userdate);
|
||||
} else if ($this->data['istoday']) {
|
||||
$title = $userdate;
|
||||
}
|
||||
|
||||
if ($this->data['istoday']) {
|
||||
$title = get_string('todayplustitle', 'calendar', $userdate);
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
}
|
||||
+26
-3
@@ -53,18 +53,25 @@ class week_exporter extends exporter {
|
||||
*/
|
||||
protected $postpadding = 0;
|
||||
|
||||
/**
|
||||
* @var \calendar_information $calendar The calendar being displayed.
|
||||
*/
|
||||
protected $calendar;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \calendar_information $calendar The calendar information for the period being displayed
|
||||
* @param mixed $days An array of day_exporter objects.
|
||||
* @param int $prepadding The number of pre-padding days at the start of the week.
|
||||
* @param int $postpadding The number of post-padding days at the start of the week.
|
||||
* @param array $related Related objects.
|
||||
*/
|
||||
public function __construct($days, $prepadding, $postpadding, $related) {
|
||||
public function __construct(\calendar_information $calendar, $days, $prepadding, $postpadding, $related) {
|
||||
$this->days = $days;
|
||||
$this->prepadding = $prepadding;
|
||||
$this->postpadding = $postpadding;
|
||||
$this->calendar = $calendar;
|
||||
|
||||
parent::__construct([], $related);
|
||||
}
|
||||
@@ -85,7 +92,7 @@ class week_exporter extends exporter {
|
||||
'multiple' => true,
|
||||
],
|
||||
'days' => [
|
||||
'type' => day_exporter::read_properties_definition(),
|
||||
'type' => week_day_exporter::read_properties_definition(),
|
||||
'multiple' => true,
|
||||
],
|
||||
];
|
||||
@@ -98,6 +105,7 @@ class week_exporter extends exporter {
|
||||
* @return array Keys are the property names, values are their values.
|
||||
*/
|
||||
protected function get_other_values(renderer_base $output) {
|
||||
global $CFG;
|
||||
$return = [
|
||||
'prepadding' => [],
|
||||
'postpadding' => [],
|
||||
@@ -112,6 +120,14 @@ class week_exporter extends exporter {
|
||||
}
|
||||
|
||||
$return['days'] = [];
|
||||
$today = $this->related['type']->timestamp_to_date_array(time());
|
||||
|
||||
$weekend = CALENDAR_DEFAULT_WEEKEND;
|
||||
if (isset($CFG->calendar_weekend)) {
|
||||
$weekend = intval($CFG->calendar_weekend);
|
||||
}
|
||||
$numberofdaysinweek = $this->related['type']->get_num_weekdays();
|
||||
|
||||
foreach ($this->days as $daydata) {
|
||||
$events = [];
|
||||
foreach ($this->related['events'] as $event) {
|
||||
@@ -132,7 +148,14 @@ class week_exporter extends exporter {
|
||||
$events[] = $event;
|
||||
}
|
||||
|
||||
$day = new day_exporter($daydata, [
|
||||
$istoday = true;
|
||||
$istoday = $istoday && $today['year'] == $daydata['year'];
|
||||
$istoday = $istoday && $today['yday'] == $daydata['yday'];
|
||||
$daydata['istoday'] = $istoday;
|
||||
|
||||
$daydata['isweekend'] = !!($weekend & (1 << ($daydata['wday'] % $numberofdaysinweek)));
|
||||
|
||||
$day = new week_day_exporter($this->calendar, $daydata, [
|
||||
'events' => $events,
|
||||
'cache' => $this->related['cache'],
|
||||
'type' => $this->related['type'],
|
||||
|
||||
+29
-85
@@ -1049,7 +1049,7 @@ class calendar_information {
|
||||
public function add_sidecalendar_blocks(core_calendar_renderer $renderer, $showfilters=false, $view=null) {
|
||||
if ($showfilters) {
|
||||
$filters = new block_contents();
|
||||
$filters->content = $renderer->fake_block_filters($this->courseid, 0, 0, 0, $view, $this->courses);
|
||||
$filters->content = $renderer->event_filter();
|
||||
$filters->footer = '';
|
||||
$filters->title = get_string('eventskey', 'calendar');
|
||||
$renderer->add_pretend_calendar_block($filters, BLOCK_POS_RIGHT);
|
||||
@@ -1478,7 +1478,7 @@ function calendar_get_mini($courses, $groups, $users, $calmonth = false, $calyea
|
||||
|
||||
// Class and cell content.
|
||||
if (isset($typesbyday[$day]['startglobal'])) {
|
||||
$class .= ' calendar_event_global';
|
||||
$class .= ' calendar_event_site';
|
||||
} else if (isset($typesbyday[$day]['startcourse'])) {
|
||||
$class .= ' calendar_event_course';
|
||||
} else if (isset($typesbyday[$day]['startgroup'])) {
|
||||
@@ -1981,88 +1981,6 @@ function calendar_top_controls($type, $data) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a filter control element.
|
||||
*
|
||||
* @param moodle_url $url of the filter
|
||||
* @param int $type constant defining the type filter
|
||||
* @return string html content of the element
|
||||
*/
|
||||
function calendar_filter_controls_element(moodle_url $url, $type) {
|
||||
global $OUTPUT;
|
||||
|
||||
switch ($type) {
|
||||
case CALENDAR_EVENT_GLOBAL:
|
||||
$typeforhumans = 'global';
|
||||
$class = 'calendar_event_global';
|
||||
break;
|
||||
case CALENDAR_EVENT_COURSE:
|
||||
$typeforhumans = 'course';
|
||||
$class = 'calendar_event_course';
|
||||
break;
|
||||
case CALENDAR_EVENT_GROUP:
|
||||
$typeforhumans = 'groups';
|
||||
$class = 'calendar_event_group';
|
||||
break;
|
||||
case CALENDAR_EVENT_USER:
|
||||
$typeforhumans = 'user';
|
||||
$class = 'calendar_event_user';
|
||||
break;
|
||||
}
|
||||
|
||||
if (calendar_show_event_type($type)) {
|
||||
$icon = $OUTPUT->pix_icon('t/hide', get_string('hide'));
|
||||
$str = get_string('hide' . $typeforhumans . 'events', 'calendar');
|
||||
} else {
|
||||
$icon = $OUTPUT->pix_icon('t/show', get_string('show'));
|
||||
$str = get_string('show' . $typeforhumans . 'events', 'calendar');
|
||||
}
|
||||
$content = \html_writer::start_tag('li', array('class' => 'calendar_event'));
|
||||
$content .= \html_writer::start_tag('a', array('href' => $url, 'rel' => 'nofollow'));
|
||||
$content .= \html_writer::tag('span', $icon, array('class' => $class));
|
||||
$content .= \html_writer::tag('span', $str, array('class' => 'eventname'));
|
||||
$content .= \html_writer::end_tag('a');
|
||||
$content .= \html_writer::end_tag('li');
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the controls filter for calendar.
|
||||
*
|
||||
* Filter is used to hide calendar info from the display page.
|
||||
*
|
||||
|
||||
* @param moodle_url $returnurl return-url for filter controls
|
||||
* @return string $content return filter controls in html
|
||||
*/
|
||||
function calendar_filter_controls(moodle_url $returnurl) {
|
||||
$groupevents = true;
|
||||
|
||||
$seturl = new \moodle_url('/calendar/set.php', array('return' => base64_encode($returnurl->out_as_local_url(false)),
|
||||
'sesskey' => sesskey()));
|
||||
$content = \html_writer::start_tag('ul');
|
||||
|
||||
$seturl->param('var', 'showglobal');
|
||||
$content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_GLOBAL);
|
||||
|
||||
$seturl->param('var', 'showcourses');
|
||||
$content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_COURSE);
|
||||
|
||||
if (isloggedin() && !isguestuser()) {
|
||||
if ($groupevents) {
|
||||
// This course MIGHT have group events defined, so show the filter.
|
||||
$seturl->param('var', 'showgroups');
|
||||
$content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_GROUP);
|
||||
}
|
||||
$seturl->param('var', 'showuser');
|
||||
$content .= calendar_filter_controls_element($seturl, CALENDAR_EVENT_USER);
|
||||
}
|
||||
$content .= \html_writer::end_tag('ul');
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the representation day.
|
||||
*
|
||||
@@ -3464,6 +3382,11 @@ function calendar_get_view(\calendar_information $calendar, $view) {
|
||||
$monthdays = $type->get_num_days_in_month($date['year'], $date['mon']);
|
||||
$tend = $tstart + ($monthdays * DAYSECS) - 1;
|
||||
$selectortitle = get_string('detailedmonthviewfor', 'calendar');
|
||||
if ($view === 'mini') {
|
||||
$template = 'core_calendar/calendar_mini';
|
||||
} else {
|
||||
$template = 'core_calendar/calendar_month';
|
||||
}
|
||||
}
|
||||
|
||||
list($userparam, $groupparam, $courseparam) = array_map(function($param) {
|
||||
@@ -3518,7 +3441,6 @@ function calendar_get_view(\calendar_information $calendar, $view) {
|
||||
|
||||
$month = new \core_calendar\external\month_exporter($calendar, $type, $related);
|
||||
$data = $month->export($renderer);
|
||||
$template = 'core_calendar/month_detailed';
|
||||
|
||||
return [$data, $template];
|
||||
}
|
||||
@@ -3654,3 +3576,25 @@ function calendar_get_footer_options($calendar) {
|
||||
|
||||
return [$data, $template];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of potential calendar filter types as a type => name
|
||||
* combination.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function calendar_get_filter_types() {
|
||||
$types = [
|
||||
'site',
|
||||
'course',
|
||||
'group',
|
||||
'user',
|
||||
];
|
||||
|
||||
return array_map(function($type) {
|
||||
return [
|
||||
'type' => $type,
|
||||
'name' => get_string("eventtype{$type}", "calendar"),
|
||||
];
|
||||
}, $types);
|
||||
}
|
||||
|
||||
+12
-18
@@ -50,24 +50,6 @@ class core_calendar_renderer extends plugin_renderer_base {
|
||||
return html_writer::end_tag('div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces the content for the filters block (pretend block)
|
||||
*
|
||||
* @param int $courseid
|
||||
* @param int $day
|
||||
* @param int $month
|
||||
* @param int $year
|
||||
* @param int $view
|
||||
* @param int $courses
|
||||
* @return string
|
||||
*/
|
||||
public function fake_block_filters($courseid, $day, $month, $year, $view, $courses) {
|
||||
$returnurl = $this->page->url;
|
||||
$returnurl->param('course', $courseid);
|
||||
return html_writer::tag('div', calendar_filter_controls($returnurl),
|
||||
array('class' => 'calendar_filters filters'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces the content for the three months block (pretend block)
|
||||
*
|
||||
@@ -502,4 +484,16 @@ class core_calendar_renderer extends plugin_renderer_base {
|
||||
$html .= html_writer::end_tag('form');
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the event filter region.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function event_filter() {
|
||||
$data = [
|
||||
'eventtypes' => calendar_get_filter_types(),
|
||||
];
|
||||
return $this->render_from_template('core_calendar/event_filter', $data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Sets the events filter for the calendar view.
|
||||
*
|
||||
* @package core_calendar
|
||||
* @copyright 2003 Jon Papaioannou ([email protected])
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
require_once('../config.php');
|
||||
require_once($CFG->dirroot.'/calendar/lib.php');
|
||||
|
||||
$var = required_param('var', PARAM_ALPHA);
|
||||
$return = clean_param(base64_decode(required_param('return', PARAM_RAW)), PARAM_LOCALURL);
|
||||
$courseid = optional_param('id', -1, PARAM_INT);
|
||||
if ($courseid != -1) {
|
||||
$return = new moodle_url($return, array('course' => $courseid));
|
||||
} else {
|
||||
$return = new moodle_url($return);
|
||||
}
|
||||
|
||||
if (!confirm_sesskey()) {
|
||||
// Do not call require_sesskey() since this page may be accessed without session (for example by bots).
|
||||
redirect($return);
|
||||
}
|
||||
|
||||
$url = new moodle_url('/calendar/set.php', array('return'=>base64_encode($return->out_as_local_url(false)), 'course' => $courseid, 'var'=>$var, 'sesskey'=>sesskey()));
|
||||
$PAGE->set_url($url);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
switch($var) {
|
||||
case 'showgroups':
|
||||
calendar_set_event_type_display(CALENDAR_EVENT_GROUP);
|
||||
break;
|
||||
case 'showcourses':
|
||||
calendar_set_event_type_display(CALENDAR_EVENT_COURSE);
|
||||
break;
|
||||
case 'showglobal':
|
||||
calendar_set_event_type_display(CALENDAR_EVENT_GLOBAL);
|
||||
break;
|
||||
case 'showuser':
|
||||
calendar_set_event_type_display(CALENDAR_EVENT_USER);
|
||||
break;
|
||||
}
|
||||
|
||||
redirect($return);
|
||||
@@ -0,0 +1,45 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template calendar/calendar_mini
|
||||
|
||||
Calendar month view for blocks.
|
||||
|
||||
The purpose of this template is to render the month view for blocks.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div{{!
|
||||
}} id="calendar-month-{{uniqid}}-{{time}}" {{!
|
||||
}} data-template="core_calendar/month_mini" {{!
|
||||
}} data-includenavigation="{{#includenavigation}}true{{/includenavigation}}{{^includenavigation}}false{{/includenavigation}}"{{!
|
||||
}}>
|
||||
{{> core_calendar/month_mini}}
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['jquery', 'core_calendar/calendar_mini'], function($, CalendarMini) {
|
||||
CalendarMini.init($("#calendar-month-{{uniqid}}-{{time}}"));
|
||||
});
|
||||
{{/js}}
|
||||
@@ -0,0 +1,41 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template calendar/calendar_month
|
||||
|
||||
Calendar month view for blcoks.
|
||||
|
||||
The purpose of this template is to render the main, detailed monthly view.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div id="calendar-month-{{uniqid}}" data-template="core_calendar/month_detailed">
|
||||
{{> core_calendar/month_detailed}}
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['jquery', 'core_calendar/calendar'], function($, Calendar) {
|
||||
Calendar.init($("#calendar-month-{{uniqid}}"));
|
||||
});
|
||||
{{/js}}
|
||||
@@ -0,0 +1,45 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template calendar/event_filter
|
||||
|
||||
Filter to select which event types displayed on this page.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div id="event-filter-{{uniqid}}" class="calendar_filters m-t-2">
|
||||
<ul>
|
||||
{{#eventtypes}}
|
||||
<li>
|
||||
{{> core_calendar/event_filter_key }}
|
||||
</li>
|
||||
{{/eventtypes}}
|
||||
</ul>
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['jquery', 'core_calendar/calendar_filter'], function($, CalendarFilter) {
|
||||
CalendarFilter.init($("#event-filter-{{uniqid}}"));
|
||||
});
|
||||
{{/js}}
|
||||
@@ -0,0 +1,45 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template calendar/event_filter_key
|
||||
|
||||
Key item for the event filter.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<a href="#" data-action="filter-event-type" data-eventtype="{{type}}" data-eventtype-hidden="{{hidden}}">
|
||||
{{^hidden}}
|
||||
<span class="calendar_event_{{type}}">
|
||||
{{#pix}}i/hide, core, {{#str}}hideeventtype, calendar, {{name}}{{/str}}{{/pix}}
|
||||
</span>
|
||||
<span class="eventname">{{#str}}hideeventtype, calendar, {{name}}{{/str}}</span>
|
||||
{{/hidden}}
|
||||
{{#hidden}}
|
||||
<span class="calendar_event_{{type}}">
|
||||
{{#pix}}i/show, core, {{#str}}showeventtype, calendar, {{name}}{{/str}}{{/pix}}
|
||||
</span>
|
||||
<span class="eventname">{{#str}}showeventtype, calendar, {{name}}{{/str}}</span>
|
||||
{{/hidden}}
|
||||
</a>
|
||||
@@ -29,10 +29,10 @@
|
||||
}}
|
||||
{{< core/hover_tooltip }}
|
||||
{{$anchor}}
|
||||
<a href="{{url}}">{{day}}</a>
|
||||
<a href="{{url}}">{{$day}}{{day}}{{/day}}</a>
|
||||
{{/anchor}}
|
||||
{{$tooltip}}
|
||||
<b>{{title}}</b>
|
||||
{{{content}}}
|
||||
<b>{{$title}}{{title}}{{/title}}</b>
|
||||
{{$content}}{{{content}}}{{/content}}
|
||||
{{/tooltip}}
|
||||
{{/ core/hover_tooltip }}
|
||||
|
||||
@@ -77,8 +77,9 @@
|
||||
<li class="events-underway">[{{name}}]</li>
|
||||
{{/underway}}
|
||||
{{^underway}}
|
||||
<li class="calendar_event_{{eventtype}}"
|
||||
<li class="calendar_event_{{calendareventtype}}"
|
||||
data-region="event-item"
|
||||
data-eventtype-{{calendareventtype}}="1"
|
||||
{{#canedit}}
|
||||
draggable="true"
|
||||
data-drag-type="move"
|
||||
@@ -113,8 +114,28 @@
|
||||
</table>
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['jquery', 'core_calendar/month_view_drag_drop'], function($, DragDrop) {
|
||||
require([
|
||||
'jquery',
|
||||
'core_calendar/month_view_drag_drop',
|
||||
'core_calendar/selectors',
|
||||
'core_calendar/events',
|
||||
], function(
|
||||
$,
|
||||
DragDrop,
|
||||
CalendarSelectors,
|
||||
CalendarEvents
|
||||
) {
|
||||
var root = $('#month-detailed-{{uniqid}}');
|
||||
DragDrop.init(root);
|
||||
|
||||
$('body').on(CalendarEvents.filterChanged, function(e, data) {
|
||||
M.util.js_pending("month-detailed-{{uniqid}}-filterChanged");
|
||||
// A filter value has been changed.
|
||||
// Find all matching cells in the popover data, and hide them.
|
||||
$("#month-detailed-{{uniqid}}")
|
||||
.find(CalendarSelectors.eventType[data.type])
|
||||
.toggleClass('hidden', !!data.hidden);
|
||||
M.util.js_complete("month-detailed-{{uniqid}}-filterChanged");
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template calendar/month_mini
|
||||
|
||||
Calendar month view for blocks.
|
||||
|
||||
The purpose of this template is to render the month view for blocks.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div id="month-mini-{{uniqid}}-{{time}}" class="calendarwrapper" data-courseid="{{courseid}}" data-current-time="{{time}}">
|
||||
{{> core/overlay_loading}}
|
||||
<table class="minicalendar calendartable">
|
||||
<caption class="calendar-controls">
|
||||
<a href="#" class="arrow_link previous" title="{{#str}}monthprev, calendar{{/str}}" data-time="{{previousperiod}}"><span class="arrow">{{{larrow}}}</span></a>
|
||||
<span class="hide"> | </span>
|
||||
<span class="current">
|
||||
<a href="{{{url}}}" title="{{#str}}monththis, calendar{{/str}}" data-time="">{{periodname}}</a>
|
||||
</span>
|
||||
<span class="hide"> | </span>
|
||||
<a href="#" class="arrow_link next" title="{{#str}}monthnext, calendar{{/str}}" data-time="{{nextperiod}}"><span class="arrow">{{{rarrow}}}</span></a>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
{{# daynames }}
|
||||
<th class="header text-xs-center" scope="col">
|
||||
<abbr title="{{fullname}}">{{shortname}}</abbr>
|
||||
</th>
|
||||
{{/ daynames }}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#weeks}}
|
||||
<tr data-region="month-view-week">
|
||||
{{#prepadding}}
|
||||
<td class="dayblank"> </td>
|
||||
{{/prepadding}}
|
||||
{{#days}}
|
||||
<td class="day text-center{{!
|
||||
This is the list of additional classes to display.
|
||||
|
||||
This cell is for today.
|
||||
}}{{#istoday}} today{{/istoday}}{{!
|
||||
|
||||
This day falls on a weekend.
|
||||
}}{{#isweekend}} weekend{{/isweekend}}{{!
|
||||
|
||||
There is at least one event.
|
||||
}}{{#events.0}} hasevent{{/events.0}}{{!
|
||||
|
||||
There are events on this day which span multiple days.
|
||||
}}{{#durationevents.0}} duration{{/durationevents.0}}{{!
|
||||
}}{{#durationevents}} duration_{{.}}{{/durationevents}}{{!
|
||||
}}{{#islastday}} duraction_finish{{/islastday}}{{!
|
||||
|
||||
These event types fall on this day.
|
||||
}}{{#calendareventtypes}}{{!
|
||||
}} calendar_event_{{.}}{{!
|
||||
}}{{/calendareventtypes}}{{!
|
||||
|
||||
This day contains the last day of an event.
|
||||
}}{{#haslastdayofevent}}{{!
|
||||
}} duration_finish{{!
|
||||
}}{{/haslastdayofevent}}{{!
|
||||
}}"{{!
|
||||
|
||||
Add data-eventtype-[eventtype] data attributes.
|
||||
These are used to show and hide events using the filter.
|
||||
}}{{#calendareventtypes}}{{!
|
||||
}} data-eventtype-{{.}}="1"{{!
|
||||
}}{{/calendareventtypes}}{{!
|
||||
|
||||
This is the timestamp for this month.
|
||||
}} data-day-timestamp="{{timestamp}}"{{!
|
||||
}}>{{!
|
||||
}}{{#popovertitle}}
|
||||
{{< core_calendar/minicalendar_day_link }}
|
||||
{{$day}}{{mday}}{{/day}}
|
||||
{{$url}}{{viewdaylink}}{{/url}}
|
||||
{{$title}}{{popovertitle}}{{/title}}
|
||||
{{$nocontent}}{{#str}}eventnone, calendar{{/str}}{{/nocontent}}
|
||||
{{$content}}
|
||||
{{#events}}
|
||||
<div data-popover-eventtype-{{calendareventtype}}="1">
|
||||
{{#modulename}}
|
||||
{{#pix}} icon, {{modulename}} {{/pix}}
|
||||
{{/modulename}}
|
||||
{{^modulename}}
|
||||
{{#pix}} i/{{eventtype}}event, core {{/pix}}
|
||||
{{/modulename}}
|
||||
{{{popupname}}}
|
||||
</div>
|
||||
{{/events}}
|
||||
{{/content}}
|
||||
{{/ core_calendar/minicalendar_day_link }}
|
||||
{{/popovertitle}}{{!
|
||||
}}{{^popovertitle}}
|
||||
{{mday}}
|
||||
{{/popovertitle}}{{!
|
||||
}}</td>
|
||||
{{/days}}
|
||||
{{#postpadding}}
|
||||
<td class="dayblank"> </td>
|
||||
{{/postpadding}}
|
||||
</tr>
|
||||
{{/weeks}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{#js}}
|
||||
require([
|
||||
'jquery',
|
||||
'core_calendar/selectors',
|
||||
'core_calendar/events',
|
||||
], function(
|
||||
$,
|
||||
CalendarSelectors,
|
||||
CalendarEvents
|
||||
) {
|
||||
|
||||
$('body').on(CalendarEvents.filterChanged, function(e, data) {
|
||||
M.util.js_pending("month-mini-{{uniqid}}-filterChanged");
|
||||
// A filter value has been changed.
|
||||
// Find all matching cells in the popover data, and hide them.
|
||||
$("#month-mini-{{uniqid}}-{{time}}")
|
||||
.find(CalendarSelectors.popoverType[data.type])
|
||||
.toggleClass('hidden', !!data.hidden);
|
||||
M.util.js_complete("month-mini-{{uniqid}}-filterChanged");
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
@@ -84,9 +84,9 @@ class behat_calendar extends behat_base {
|
||||
* @param int $day The day of the current month
|
||||
*/
|
||||
public function i_hover_over_day_of_this_month_in_calendar($day) {
|
||||
$summarytitle = get_string('calendarheading', 'calendar', userdate(time(), get_string('strftimemonthyear')));
|
||||
$summarytitle = userdate(time(), get_string('strftimemonthyear'));
|
||||
// The current month table.
|
||||
$currentmonth = "table[contains(concat(' ', normalize-space(@summary), ' '), ' {$summarytitle} ')]";
|
||||
$currentmonth = "table[descendant::*[self::caption[contains(concat(' ', normalize-space(.), ' '), ' {$summarytitle} ')]]]";
|
||||
|
||||
// Strings for the class cell match.
|
||||
$cellclasses = "contains(concat(' ', normalize-space(@class), ' '), ' day ')";
|
||||
@@ -95,6 +95,7 @@ class behat_calendar extends behat_base {
|
||||
$dayofmonth = "a[{$daycontains}]";
|
||||
|
||||
$xpath = '//' . $currentmonth . '/descendant::' . $daycell . '/' . $dayofmonth;
|
||||
$this->execute("behat_general::wait_until_the_page_is_ready");
|
||||
$this->execute("behat_general::i_hover", array($xpath, "xpath_element"));
|
||||
|
||||
}
|
||||
|
||||
@@ -161,5 +161,4 @@ echo html_writer::end_tag('div');
|
||||
list($data, $template) = calendar_get_footer_options($calendar);
|
||||
echo $renderer->render_from_template($template, $data);
|
||||
|
||||
$PAGE->requires->js_call_amd('core_calendar/calendar', 'init');
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
+4
-2
@@ -30,8 +30,6 @@ $string['activitynext'] = 'Next activity';
|
||||
$string['activityprev'] = 'Previous activity';
|
||||
$string['breadcrumb'] = 'Breadcrumb trail';
|
||||
$string['hideblocka'] = 'Hide {$a} block';
|
||||
$string['monthnext'] = 'Next month';
|
||||
$string['monthprev'] = 'Previous month';
|
||||
$string['showblocka'] = 'Show {$a} block';
|
||||
$string['sitemap'] = 'Site map';
|
||||
$string['skipa'] = 'Skip {$a}';
|
||||
@@ -41,3 +39,7 @@ $string['skipto'] = 'Skip to {$a}';
|
||||
$string['tocontent'] = 'Skip to main content';
|
||||
$string['tonavigation'] = 'Go to navigation';
|
||||
$string['youarehere'] = 'You are here';
|
||||
|
||||
// Deprecated since Moodle 3.4.
|
||||
$string['monthnext'] = 'Next month';
|
||||
$string['monthprev'] = 'Previous month';
|
||||
|
||||
+30
-17
@@ -90,6 +90,7 @@ $string['eventdate'] = 'Date';
|
||||
$string['eventdescription'] = 'Description';
|
||||
$string['eventduration'] = 'Duration';
|
||||
$string['eventendtime'] = 'End time';
|
||||
$string['eventendtimewrapped'] = '{$a} (End time)';
|
||||
$string['eventinstanttime'] = 'Time';
|
||||
$string['eventkind'] = 'Type of event';
|
||||
$string['eventname'] = 'Event title';
|
||||
@@ -135,10 +136,14 @@ $string['gotocalendar'] = 'Go to calendar';
|
||||
$string['group'] = 'Group';
|
||||
$string['groupevent'] = 'Group event';
|
||||
$string['groupevents'] = 'Group events';
|
||||
$string['hidecourseevents'] = 'Hide course events';
|
||||
$string['hideglobalevents'] = 'Hide global events';
|
||||
$string['hidegroupsevents'] = 'Hide group events';
|
||||
$string['hideuserevents'] = 'Hide user events';
|
||||
$string['eventtypeglobal'] = 'global';
|
||||
$string['eventtypesite'] = 'global';
|
||||
$string['eventtypecourse'] = 'course';
|
||||
$string['eventtypemodule'] = 'module';
|
||||
$string['eventtypegroup'] = 'group';
|
||||
$string['eventtypeuser'] = 'user';
|
||||
$string['hideeventtype'] = 'Hide {$a} events';
|
||||
$string['showeventtype'] = 'Show {$a} events';
|
||||
$string['hourly'] = 'Hourly';
|
||||
$string['ical'] = 'iCal';
|
||||
$string['importcalendar'] = 'Import calendar';
|
||||
@@ -159,9 +164,10 @@ $string['monday'] = 'Monday';
|
||||
$string['monthly'] = 'Monthly';
|
||||
$string['monthlyview'] = 'Monthly view';
|
||||
$string['monthnext'] = 'Next month';
|
||||
$string['monthprev'] = 'Previous month';
|
||||
$string['monththis'] = 'This month';
|
||||
$string['more'] = 'More';
|
||||
$string['namewithsource'] = '{$a->name}({$a->source})';
|
||||
$string['namewithsource'] = '{$a->name} ({$a->source})';
|
||||
$string['never'] = 'Never';
|
||||
$string['newevent'] = 'New event';
|
||||
$string['notitle'] = 'no title';
|
||||
@@ -194,10 +200,6 @@ $string['repeatweeksl'] = 'Repeat weekly, creating altogether';
|
||||
$string['repeatweeksr'] = 'events';
|
||||
$string['sat'] = 'Sat';
|
||||
$string['saturday'] = 'Saturday';
|
||||
$string['showcourseevents'] = 'Show course events';
|
||||
$string['showglobalevents'] = 'Show global events';
|
||||
$string['showgroupsevents'] = 'Show group events';
|
||||
$string['showuserevents'] = 'Show user events';
|
||||
$string['shown'] = 'shown';
|
||||
$string['siteevents'] = 'Site events';
|
||||
$string['spanningevents'] = 'Events underway';
|
||||
@@ -214,17 +216,10 @@ $string['timeformat_12'] = '12-hour (am/pm)';
|
||||
$string['timeformat_24'] = '24-hour';
|
||||
$string['timeperiod'] = 'Time period';
|
||||
$string['today'] = 'Today';
|
||||
$string['todayplustitle'] = 'Today {$a}';
|
||||
$string['tomorrow'] = 'Tomorrow';
|
||||
$string['tt_deleteevent'] = 'Delete event';
|
||||
$string['tt_editevent'] = 'Edit event';
|
||||
$string['tt_hidecourse'] = 'Course events are shown (click to hide)';
|
||||
$string['tt_hideglobal'] = 'Global events are shown (click to hide)';
|
||||
$string['tt_hidegroups'] = 'Group events are shown (click to hide)';
|
||||
$string['tt_hideuser'] = 'User events are shown (click to hide)';
|
||||
$string['tt_showcourse'] = 'Course events are hidden (click to show)';
|
||||
$string['tt_showglobal'] = 'Global events are hidden (click to show)';
|
||||
$string['tt_showgroups'] = 'Group events are hidden (click to show)';
|
||||
$string['tt_showuser'] = 'User events are hidden (click to show)';
|
||||
$string['tue'] = 'Tue';
|
||||
$string['tuesday'] = 'Tuesday';
|
||||
$string['typeclose'] = 'Close event';
|
||||
@@ -252,3 +247,21 @@ $string['youcandeleteallrepeats'] = 'This event is part of a repeating event ser
|
||||
|
||||
// Deprecated since Moodle 3.2.
|
||||
$string['for'] = 'for';
|
||||
|
||||
// Deprecated since Moodle 3.4.
|
||||
$string['tt_hidecourse'] = 'Course events are shown (click to hide)';
|
||||
$string['tt_hideglobal'] = 'Global events are shown (click to hide)';
|
||||
$string['tt_hidegroups'] = 'Group events are shown (click to hide)';
|
||||
$string['tt_hideuser'] = 'User events are shown (click to hide)';
|
||||
$string['tt_showcourse'] = 'Course events are hidden (click to show)';
|
||||
$string['tt_showglobal'] = 'Global events are hidden (click to show)';
|
||||
$string['tt_showgroups'] = 'Group events are hidden (click to show)';
|
||||
$string['tt_showuser'] = 'User events are hidden (click to show)';
|
||||
$string['hidecourseevents'] = 'Hide course events';
|
||||
$string['hideglobalevents'] = 'Hide global events';
|
||||
$string['hidegroupsevents'] = 'Hide group events';
|
||||
$string['hideuserevents'] = 'Hide user events';
|
||||
$string['showcourseevents'] = 'Show course events';
|
||||
$string['showglobalevents'] = 'Show global events';
|
||||
$string['showgroupsevents'] = 'Show group events';
|
||||
$string['showuserevents'] = 'Show user events';
|
||||
|
||||
@@ -61,3 +61,21 @@ error:backpackloginfailed,core_badges
|
||||
signinwithyouremail,core_badges
|
||||
sectionusedefaultname,core
|
||||
registermoochtips,core_hub
|
||||
monthnext,core_access
|
||||
monthprev,core_access
|
||||
tt_hidecourse,core_calendar
|
||||
tt_hideglobal,core_calendar
|
||||
tt_hidegroups,core_calendar
|
||||
tt_hideuser,core_calendar
|
||||
tt_showcourse,core_calendar
|
||||
tt_showglobal,core_calendar
|
||||
tt_showgroups,core_calendar
|
||||
tt_showuser,core_calendar
|
||||
hidecourseevents,core_calendar
|
||||
hideglobalevents,core_calendar
|
||||
hidegroupsevents,core_calendar
|
||||
hideuserevents,core_calendar
|
||||
showcourseevents,core_calendar
|
||||
showglobalevents,core_calendar
|
||||
showgroupsevents,core_calendar
|
||||
showuserevents,core_calendar
|
||||
|
||||
@@ -355,3 +355,13 @@ table.calendartable caption {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.calendarwrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.day-popover-content {
|
||||
&:empty + .day-popover-alternate {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,38 @@
|
||||
"content": "<img class='icon smallicon' src='../../../pix/i/siteevent.svg'>Test site event"
|
||||
}
|
||||
}}
|
||||
<a href="{{url}}"
|
||||
data-container="body"
|
||||
data-toggle="popover"
|
||||
data-html="true"
|
||||
data-trigger="hover"
|
||||
data-placement="top"
|
||||
data-title="{{title}}"
|
||||
data-content="{{content}}"
|
||||
>{{day}}</a>
|
||||
<a {{!
|
||||
}} id="calendar-day-popover-link-{{courseid}}-{{year}}-{{yday}}-{{uniqid}}"{{!
|
||||
}} href="{{$url}}{{url}}{{/url}}"{{!
|
||||
}} data-container="body"{{!
|
||||
}} data-toggle="popover"{{!
|
||||
}} data-html="true"{{!
|
||||
}} data-trigger="hover"{{!
|
||||
}} data-placement="top"{{!
|
||||
}} data-title="{{$title}}{{title}}{{/title}}"{{!
|
||||
}} data-alternate="{{$nocontent}}{{/nocontent}}"{{!
|
||||
}}>{{$day}}{{day}}{{/day}}</a>
|
||||
<div class="hidden">
|
||||
{{$content}}{{/content}}
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['jquery'], function($) {
|
||||
require(['theme_boost/popover'], function() {
|
||||
var target = $("#calendar-day-popover-link-{{courseid}}-{{year}}-{{yday}}-{{uniqid}}");
|
||||
target.popover({
|
||||
content: function() {
|
||||
var source = target.next().find("> *:not('.hidden')");
|
||||
var content = $('<div>');
|
||||
|
||||
if (source.length) {
|
||||
content.html(source.clone(false));
|
||||
} else {
|
||||
content.html(target.data('alternate'));
|
||||
}
|
||||
|
||||
return content.html();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
|
||||
@@ -345,3 +345,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.calendarwrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -5852,6 +5852,9 @@ img.iconsmall {
|
||||
min-width: 1024px;
|
||||
}
|
||||
}
|
||||
.calendarwrapper {
|
||||
position: relative;
|
||||
}
|
||||
/* course.less */
|
||||
/* COURSE CONTENT */
|
||||
/* stylelint-disable unit-blacklist */
|
||||
|
||||
@@ -27,18 +27,38 @@
|
||||
"content": "<img class='icon smallicon' src='../../../pix/i/siteevent.svg'>Test site event"
|
||||
}
|
||||
}}
|
||||
<a id="{{uniqid}}" href="{{url}}"
|
||||
data-container="body"
|
||||
data-toggle="popover"
|
||||
data-html="true"
|
||||
data-trigger="hover"
|
||||
data-placement="top"
|
||||
data-title="{{title}}"
|
||||
data-content="{{content}}">{{day}}</a>
|
||||
<a {{!
|
||||
}} href="{{url}}"{{!
|
||||
}} id="calendar-day-popover-link-{{courseid}}-{{year}}-{{yday}}-{{uniqid}}"{{!
|
||||
}} data-container="body"{{!
|
||||
}} data-toggle="popover"{{!
|
||||
}} data-html="true"{{!
|
||||
}} data-trigger="hover"{{!
|
||||
}} data-placement="top"{{!
|
||||
}} data-title="{{$title}}{{title}}{{/title}}"{{!
|
||||
}} data-alternate="{{$nocontent}}{{/nocontent}}"{{!
|
||||
}}>{{$day}}{{day}}{{/day}}</a>
|
||||
<div class="hidden">
|
||||
{{$content}}{{/content}}
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['jquery'], function($) {
|
||||
require(['jquery', 'theme_bootstrapbase/bootstrap'], function($) {
|
||||
require(['theme_bootstrapbase/bootstrap'], function() {
|
||||
$('#{{uniqid}}').popover();
|
||||
var target = $("#calendar-day-popover-link-{{courseid}}-{{year}}-{{yday}}-{{uniqid}}");
|
||||
target.popover({
|
||||
content: function() {
|
||||
var source = target.next().find("> *:not('.hidden')");
|
||||
var content = $('<div>');
|
||||
|
||||
if (source.length) {
|
||||
content.html(source.clone(false));
|
||||
} else {
|
||||
content.html(target.data('alternate'));
|
||||
}
|
||||
|
||||
return content.html();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
{{/js}}
|
||||
|
||||
Reference in New Issue
Block a user