diff --git a/calendar/amd/build/calendar.min.js b/calendar/amd/build/calendar.min.js
new file mode 100644
index 00000000000..67a1cb2fa98
--- /dev/null
+++ b/calendar/amd/build/calendar.min.js
@@ -0,0 +1 @@
+define(["jquery","core/ajax","core/str","core/templates","core/notification","core/custom_interaction_events","core/modal_factory","core_calendar/summary_modal","core_calendar/calendar_repository"],function(a,b,c,d,e,f,g,h,i){var j={ROOT:"[data-region='calendar']",EVENT_LINK:"[data-action='view-event']"},k=null,l=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a}).fail(e.exception)},m=function(a){var b=i.getEventById(a);return b.then(function(a){return a.event?a.event:void b.fail(e.exception)}).then(function(a){return l(a.eventtype).then(function(b){return a.eventtype=b,a})}).then(function(a){return k.done(function(b){b.setTitle(a.name),b.setBody(d.render("core_calendar/event_summary_body",a)),0==a.caneditevent&&b.setFooter(""),b.show()})})},n=function(b){b=a(b);var c=!1;b.on("click",j.EVENT_LINK,function(b){if(!c){c=!0,b.preventDefault();var d=a(b.target).closest(j.EVENT_LINK),e=d.attr("data-event-id");m(e).done(function(){c=!1})}})};return{init:function(){k=g.create({type:h.TYPE}),n(j.ROOT)}}});
\ No newline at end of file
diff --git a/calendar/amd/build/calendar_repository.min.js b/calendar/amd/build/calendar_repository.min.js
new file mode 100644
index 00000000000..156cad81f20
--- /dev/null
+++ b/calendar/amd/build/calendar_repository.min.js
@@ -0,0 +1 @@
+define(["jquery","core/ajax"],function(a,b){var c=function(a){var c={methodname:"core_calendar_get_calendar_event_by_id",args:{eventid:a}};return b.call([c])[0]};return{getEventById:c}});
\ No newline at end of file
diff --git a/calendar/amd/build/summary_modal.min.js b/calendar/amd/build/summary_modal.min.js
new file mode 100644
index 00000000000..bb8b25a861b
--- /dev/null
+++ b/calendar/amd/build/summary_modal.min.js
@@ -0,0 +1 @@
+define(["jquery","core/notification","core/custom_interaction_events","core/modal","core/modal_registry"],function(a,b,c,d,e){var f=!1,g={EDIT_BUTTON:'[data-action="edit"]',DELETE_BUTTON:'[data-action="delete"]',EVENT_LINK:'[data-action="event-link"]'},h=function(a){d.call(this,a),this.getFooter().find(g.EDIT_BUTTON).length||b.exception({message:"No edit button found"}),this.getFooter().find(g.DELETE_BUTTON).length||b.exception({message:"No delete button found"})};return h.TYPE="core_calendar-event_summary",h.prototype=Object.create(d.prototype),h.prototype.constructor=h,f||(e.register(h.TYPE,h,"core_calendar/event_summary_modal"),f=!0),h});
\ No newline at end of file
diff --git a/calendar/amd/src/calendar.js b/calendar/amd/src/calendar.js
new file mode 100644
index 00000000000..ace33647cb9
--- /dev/null
+++ b/calendar/amd/src/calendar.js
@@ -0,0 +1,117 @@
+// 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 .
+
+/**
+ * A javascript module to calendar events.
+ *
+ * @module core_calendar/calendar
+ * @package core_calendar
+ * @copyright 2017 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/ajax', 'core/str', 'core/templates', 'core/notification', 'core/custom_interaction_events',
+ 'core/modal_factory', 'core_calendar/summary_modal', 'core_calendar/calendar_repository'],
+ function($, Ajax, Str, Templates, Notification, CustomEvents, ModalFactory, SummaryModal, CalendarRepository) {
+
+ var SELECTORS = {
+ ROOT: "[data-region='calendar']",
+ EVENT_LINK: "[data-action='view-event']",
+ };
+
+ var modalPromise = null;
+
+ /**
+ * Get the event type lang string.
+ *
+ * @param {String} eventType The event type.
+ * @return {String} The lang string of the event type.
+ */
+ var getEventType = function(eventType) {
+ var lang = 'type' + eventType;
+ return Str.get_string(lang, 'core_calendar').then(function(langStr) {
+ return langStr;
+ }).fail(Notification.exception);
+ };
+
+ /**
+ * Render the event summary modal.
+ *
+ * @param {Number} eventId The calendar event id.
+ * @return {promise} The summary modal promise.
+ */
+ var renderEventSummaryModal = function(eventId) {
+
+ var promise = CalendarRepository.getEventById(eventId);
+
+ return promise.then(function(result) {
+ if (!result.event) {
+ promise.fail(Notification.exception);
+ } else {
+ return result.event;
+ }
+ }).then(function(eventdata) {
+ return getEventType(eventdata.eventtype).then(function(langStr) {
+ eventdata.eventtype = langStr;
+ return eventdata;
+ });
+ }).then(function(eventdata) {
+ return modalPromise.done(function(modal) {
+ modal.setTitle(eventdata.name);
+ modal.setBody(Templates.render('core_calendar/event_summary_body', eventdata));
+
+ // Hide edit and delete buttons if I don't have permission.
+ if (eventdata.caneditevent == false) {
+ modal.setFooter('');
+ }
+
+ modal.show();
+ });
+ });
+ };
+
+ /**
+ * Register event listeners for the module.
+ *
+ * @param {object} root The root element.
+ */
+ var registerEventListeners = function(root) {
+ root = $(root);
+
+ var loading = false;
+ root.on('click', SELECTORS.EVENT_LINK, function(e) {
+ if (!loading) {
+ loading = true;
+ e.preventDefault();
+
+ var eventElement = $(e.target).closest(SELECTORS.EVENT_LINK);
+ var eventId = eventElement.attr('data-event-id');
+
+ renderEventSummaryModal(eventId).done(function() {
+ loading = false;
+ });
+ }
+ });
+ };
+
+ return {
+ init: function() {
+ modalPromise = ModalFactory.create({
+ type: SummaryModal.TYPE
+ });
+
+ registerEventListeners(SELECTORS.ROOT);
+ }
+ };
+ });
diff --git a/calendar/amd/src/calendar_repository.js b/calendar/amd/src/calendar_repository.js
new file mode 100644
index 00000000000..3e7a68c27d9
--- /dev/null
+++ b/calendar/amd/src/calendar_repository.js
@@ -0,0 +1,50 @@
+// 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 .
+
+/**
+ * A javascript module to handle calendar ajax actions.
+ *
+ * @module core_calendar/calendar_repository
+ * @class repository
+ * @package core_calendar
+ * @copyright 2017 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/ajax'], function($, Ajax) {
+
+
+ /**
+ * Get a calendar event by id.
+ *
+ * @method getEventById
+ * @param {int} eventId The event id.
+ * @return {promise} Resolved with requested calendar event
+ */
+ var getEventById = function(eventId) {
+
+ var request = {
+ methodname: 'core_calendar_get_calendar_event_by_id',
+ args: {
+ eventid: eventId
+ }
+ };
+
+ return Ajax.call([request])[0];
+ };
+
+ return {
+ getEventById: getEventById
+ };
+});
diff --git a/calendar/amd/src/summary_modal.js b/calendar/amd/src/summary_modal.js
new file mode 100644
index 00000000000..a1801f5bcde
--- /dev/null
+++ b/calendar/amd/src/summary_modal.js
@@ -0,0 +1,64 @@
+// 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 .
+
+/**
+ * A javascript module to handle summary modal.
+ *
+ * @module core_calendar/summary_modal
+ * @package core_calendar
+ * @copyright 2017 Simey Lameze
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+define(['jquery', 'core/notification', 'core/custom_interaction_events', 'core/modal', 'core/modal_registry'],
+ function($, Notification, CustomEvents, Modal, ModalRegistry) {
+
+ var registered = false;
+ var SELECTORS = {
+ EDIT_BUTTON: '[data-action="edit"]',
+ DELETE_BUTTON: '[data-action="delete"]',
+ EVENT_LINK: '[data-action="event-link"]'
+ };
+
+ /**
+ * Constructor for the Modal.
+ *
+ * @param {object} root The root jQuery element for the modal
+ */
+ var ModalEventSummary = function(root) {
+ Modal.call(this, root);
+
+ if (!this.getFooter().find(SELECTORS.EDIT_BUTTON).length) {
+ Notification.exception({message: 'No edit button found'});
+ }
+
+ if (!this.getFooter().find(SELECTORS.DELETE_BUTTON).length) {
+ Notification.exception({message: 'No delete button found'});
+ }
+ };
+
+ ModalEventSummary.TYPE = 'core_calendar-event_summary';
+ ModalEventSummary.prototype = Object.create(Modal.prototype);
+ ModalEventSummary.prototype.constructor = ModalEventSummary;
+
+ // Automatically register with the modal registry the first time this module is imported so that you can create modals
+ // of this type using the modal factory.
+ if (!registered) {
+ ModalRegistry.register(ModalEventSummary.TYPE, ModalEventSummary, 'core_calendar/event_summary_modal');
+ registered = true;
+ }
+
+ return ModalEventSummary;
+
+});
\ No newline at end of file
diff --git a/calendar/externallib.php b/calendar/externallib.php
index bf0855be580..fbc7737d395 100644
--- a/calendar/externallib.php
+++ b/calendar/externallib.php
@@ -687,4 +687,77 @@ class core_calendar_external extends external_api {
)
);
}
+
+ /**
+ * Returns description of method parameters.
+ *
+ * @return external_function_parameters
+ */
+ public static function get_calendar_event_by_id_parameters() {
+ return new external_function_parameters(
+ array(
+ 'eventid' => new external_value(PARAM_INT, 'The event id to be retrieved'),
+ )
+ );
+ }
+ /**
+ * Get calendar event by id.
+ *
+ * @param int $eventid The calendar event id to be retrieved.
+ * @return array Array of event details
+ */
+ public static function get_calendar_event_by_id($eventid) {
+ global $CFG;
+ require_once($CFG->dirroot."/calendar/lib.php");
+
+ // Parameter validation.
+ $params = ['eventid' => $eventid];
+ $params = self::validate_parameters(self::get_calendar_event_by_id_parameters(), $params);
+
+ $warnings = array();
+
+ // We need to get events asked for eventids.
+ $event = calendar_get_events_by_id([$eventid]);
+ $eventobj = calendar_event::load($eventid);
+ $event[$eventid]->caneditevent = calendar_edit_event_allowed($eventobj);
+
+ return array('event' => $event[$eventid], 'warnings' => $warnings);
+ }
+
+ /**
+ * Returns description of method result value
+ *
+ * @return external_description
+ */
+ public static function get_calendar_event_by_id_returns() {
+
+ return new external_single_structure(array(
+ 'event' => new external_single_structure(
+ array(
+ 'id' => new external_value(PARAM_INT, 'event id'),
+ 'name' => new external_value(PARAM_TEXT, 'event name'),
+ 'description' => new external_value(PARAM_RAW, 'Description', VALUE_OPTIONAL, null, NULL_ALLOWED),
+ 'format' => new external_format_value('description'),
+ 'courseid' => new external_value(PARAM_INT, 'course id'),
+ 'groupid' => new external_value(PARAM_INT, 'group id'),
+ 'userid' => new external_value(PARAM_INT, 'user id'),
+ 'repeatid' => new external_value(PARAM_INT, 'repeat id'),
+ 'modulename' => new external_value(PARAM_TEXT, 'module name', VALUE_OPTIONAL, null, NULL_ALLOWED),
+ 'instance' => new external_value(PARAM_INT, 'instance id'),
+ 'eventtype' => new external_value(PARAM_TEXT, 'Event type'),
+ 'timestart' => new external_value(PARAM_INT, 'timestart'),
+ 'timeduration' => new external_value(PARAM_INT, 'time duration'),
+ 'visible' => new external_value(PARAM_INT, 'visible'),
+ 'uuid' => new external_value(PARAM_TEXT, 'unique id of ical events', VALUE_OPTIONAL, null, NULL_NOT_ALLOWED),
+ 'sequence' => new external_value(PARAM_INT, 'sequence'),
+ 'timemodified' => new external_value(PARAM_INT, 'time modified'),
+ 'subscriptionid' => new external_value(PARAM_INT, 'Subscription id', VALUE_OPTIONAL, null, NULL_ALLOWED),
+ 'caneditevent' => new external_value(PARAM_BOOL, 'Whether the user can edit the event'),
+ ),
+ 'event'
+ ),
+ 'warnings' => new external_warnings()
+ )
+ );
+ }
}
diff --git a/calendar/renderer.php b/calendar/renderer.php
index 6711693be09..ee450e1724d 100644
--- a/calendar/renderer.php
+++ b/calendar/renderer.php
@@ -38,7 +38,7 @@ class core_calendar_renderer extends plugin_renderer_base {
* @return string
*/
public function start_layout() {
- return html_writer::start_tag('div', array('class'=>'maincalendar'));
+ return html_writer::start_tag('div', ['data-region' => 'calendar', 'class' => 'maincalendar']);
}
/**
@@ -517,7 +517,8 @@ class core_calendar_renderer extends plugin_renderer_base {
];
$eventname = get_string('eventnameandcourse', 'calendar', $eventnameparams);
}
- $link = html_writer::link($dayhref, $eventname);
+ $link = html_writer::link($dayhref, $eventname, ['data-action' => 'view-event',
+ 'data-event-id' => $events[$eventindex]->id]);
$cell->text .= html_writer::tag('li', $link, $attributes);
}
$cell->text .= html_writer::end_tag('ul');
diff --git a/calendar/templates/event_summary_body.mustache b/calendar/templates/event_summary_body.mustache
new file mode 100644
index 00000000000..23946c9668f
--- /dev/null
+++ b/calendar/templates/event_summary_body.mustache
@@ -0,0 +1,37 @@
+{{!
+ 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 core_calendar/event_summary_body
+
+ This template renders the body of calendar events summary modal.
+
+ Example context (json):
+ {
+ "timestart": 1490320388,
+ "description": "An random event description",
+ "eventtype": "open",
+ }
+}}
+
diff --git a/calendar/templates/event_summary_modal.mustache b/calendar/templates/event_summary_modal.mustache
new file mode 100644
index 00000000000..18498d79d43
--- /dev/null
+++ b/calendar/templates/event_summary_modal.mustache
@@ -0,0 +1,32 @@
+{{!
+ 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 core_calendar/event_summary_modal
+
+ This template renders the calendar events summary modal.
+
+ Example context (json):
+ {
+ "title": "Assignment due 1",
+ }
+}}
+{{< core/modal }}
+{{$footer}}
+
+
+{{/footer}}
+{{/ core/modal }}
diff --git a/calendar/view.php b/calendar/view.php
index 18245a50e38..f974ba5bb84 100644
--- a/calendar/view.php
+++ b/calendar/view.php
@@ -176,4 +176,5 @@ if (!empty($CFG->enablecalendarexport)) {
echo $OUTPUT->container_end();
echo html_writer::end_tag('div');
echo $renderer->complete_layout();
+$PAGE->requires->js_call_amd('core_calendar/calendar', 'init');
echo $OUTPUT->footer();
diff --git a/lang/en/calendar.php b/lang/en/calendar.php
index d194188117b..5fca2dcad56 100644
--- a/lang/en/calendar.php
+++ b/lang/en/calendar.php
@@ -108,6 +108,7 @@ $string['eventsrelatedtogroups'] = 'Events related to groups';
$string['eventstarttime'] = 'Start time';
$string['eventstoexport'] = 'Events to export';
$string['eventtime'] = 'Time';
+$string['eventtype'] = 'Event type';
$string['eventview'] = 'Event details';
$string['eventcalendareventcreated'] = 'Calendar event created';
$string['eventcalendareventupdated'] = 'Calendar event updated';
@@ -222,8 +223,11 @@ $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';
$string['typecourse'] = 'Course event';
+$string['typedue'] = 'Due event';
$string['typegroup'] = 'Group event';
+$string['typeopen'] = 'Open event';
$string['typesite'] = 'Site event';
$string['typeuser'] = 'User event';
$string['upcomingevents'] = 'Upcoming events';
@@ -237,6 +241,7 @@ $string['wednesday'] = 'Wednesday';
$string['weekly'] = 'Weekly';
$string['weeknext'] = 'Next week';
$string['weekthis'] = 'This week';
+$string['when'] = 'When';
$string['yesterday'] = 'Yesterday';
$string['youcandeleteallrepeats'] = 'This event is part of a repeating event series. You can delete this event only, or all {$a} events in the series at once.';
diff --git a/lib/db/services.php b/lib/db/services.php
index 65d05049159..373cd06fefc 100644
--- a/lib/db/services.php
+++ b/lib/db/services.php
@@ -115,6 +115,16 @@ $functions = array(
'ajax' => true,
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
+ 'core_calendar_get_calendar_event_by_id' => array(
+ 'classname' => 'core_calendar_external',
+ 'methodname' => 'get_calendar_event_by_id',
+ 'description' => 'Get calendar event by id',
+ 'classpath' => 'calendar/externallib.php',
+ 'type' => 'read',
+ 'capabilities' => 'moodle/calendar:manageentries, moodle/calendar:manageownentries, moodle/calendar:managegroupentries',
+ 'ajax' => true,
+ 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
+ ),
'core_cohort_add_cohort_members' => array(
'classname' => 'core_cohort_external',
'methodname' => 'add_cohort_members',
diff --git a/version.php b/version.php
index fbcc308544e..b4142b0a9e2 100644
--- a/version.php
+++ b/version.php
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
-$version = 2017071001.00; // YYYYMMDD = weekly release date of this DEV branch.
+$version = 2017071001.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.