Merge branch 'MDL-59671-master' of git://github.com/lameze/moodle

This commit is contained in:
Andrew Nicols
2017-08-08 11:46:51 +08:00
10 changed files with 119 additions and 73 deletions
+1 -1
View File
@@ -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"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m={ROOT:"[data-region='calendar']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']"},n=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},o=function(a){return c.get_string("subsource","core_calendar",a).then(function(b){return a.url?'<a href="'+a.url+'">'+b+"</a>":b})},p=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=n(d.eventtype);if(d.displayeventsource){d.subscription=JSON.parse(d.subscription);var f={url:d.subscription.url,name:d.subscription.name},g=o(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)};return a.caneditevent||(b.footer=""),h.create(b)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},q=function(a){var b=a.find(m.NEW_EVENT_BUTTON),c=b.attr("data-context-id");return h.create({type:i.TYPE,large:!0,templateContext:{contextid:c}},b)},r=function(b,c){var d=a("body");d.on(l.created,function(){window.location.reload()}),d.on(l.deleted,function(){window.location.reload()}),d.on(l.updated,function(){window.location.reload()}),c.then(function(a){d.on(l.editEvent,function(b,c){a.setEventId(c),a.show()})})},s=function(){var b=a(m.ROOT);a(m.EVENT_LINK).click(function(b){b.preventDefault();var c=a(this).attr("data-event-id");p(c)});var c=q(b);r(b,c)};return{init:function(){s()}}});
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"],function(a,b,c,d,e,f,g,h,i,j,k,l){var m={ROOT:"[data-region='calendar']",EVENT_LINK:"[data-action='view-event']",NEW_EVENT_BUTTON:"[data-action='new-event-button']"},n=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},o=function(a){return c.get_string("subsource","core_calendar",a).then(function(b){return a.url?'<a href="'+a.url+'">'+b+"</a>":b})},p=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=n(d.eventtype);if(d.displayeventsource){d.subscription=JSON.parse(d.subscription);var f={url:d.subscription.url,name:d.subscription.name},g=o(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}};return h.create(b)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},q=function(a){var b=a.find(m.NEW_EVENT_BUTTON),c=b.attr("data-context-id");return h.create({type:i.TYPE,large:!0,templateContext:{contextid:c}},b)},r=function(b,c){var d=a("body");d.on(l.created,function(){window.location.reload()}),d.on(l.deleted,function(){window.location.reload()}),d.on(l.updated,function(){window.location.reload()}),d.on(l.editActionEvent,function(a,b){window.location.assign(b)}),c.then(function(a){d.on(l.editEvent,function(b,c){a.setEventId(c),a.show()})})},s=function(){var b=a(m.ROOT);a(m.EVENT_LINK).click(function(b){b.preventDefault();var c=a(this).attr("data-event-id");p(c)});var c=q(b);r(b,c)};return{init:function(){s()}}});
+1 -1
View File
@@ -1 +1 @@
define([],function(){return{created:"calendar-events:created",deleted:"calendar-events:deleted",updated:"calendar-events:updated",editEvent:"calendar-events:edit_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"}});
+1 -1
View File
@@ -1 +1 @@
define(["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/repository","core_calendar/events"],function(a,b,c,d,e,f,g,h,i,j){var k=!1,l={ROOT:"[data-region='summary-modal-container']",EDIT_BUTTON:'[data-action="edit"]',DELETE_BUTTON:'[data-action="delete"]'},m=function(a){e.call(this,a),this.getEditButton().length||c.exception({message:"No edit button found"}),this.getDeleteButton().length||c.exception({message:"No delete button found"})};return m.TYPE="core_calendar-event_summary",m.prototype=Object.create(e.prototype),m.prototype.constructor=m,m.prototype.getEditButton=function(){return"undefined"==typeof this.editButton&&(this.editButton=this.getFooter().find(l.EDIT_BUTTON)),this.editButton},m.prototype.getDeleteButton=function(){return"undefined"==typeof this.deleteButton&&(this.deleteButton=this.getFooter().find(l.DELETE_BUTTON)),this.deleteButton},m.prototype.getEventId=function(){return this.getBody().find(l.ROOT).attr("data-event-id")},m.prototype.registerEventListeners=function(){e.prototype.registerEventListeners.call(this);var f=g.create({type:g.types.CONFIRM},this.getDeleteButton()).then(function(b){return b.getRoot().on(h.yes,function(){var b=this.getEventId();i.deleteEvent(b).then(function(){a("body").trigger(j.deleted,[b]),this.hide()}.bind(this))["catch"](c.exception)}.bind(this)),b}.bind(this));this.getRoot().on(h.bodyRendered,function(){var a=this.getBody().find(l.ROOT).attr("data-event-title");f.then(function(c){c.setBody(b.get_string("confirmeventdelete","core_calendar",a))})}.bind(this)),d.define(this.getEditButton(),[d.events.activate]),this.getEditButton().on(d.events.activate,function(b,c){a("body").trigger(j.editEvent,[this.getEventId()]),this.hide(),b.preventDefault(),b.stopPropagation(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()}.bind(this))},k||(f.register(m.TYPE,m,"core_calendar/event_summary_modal"),k=!0),m});
define(["jquery","core/str","core/notification","core/custom_interaction_events","core/modal","core/modal_registry","core/modal_factory","core/modal_events","core_calendar/repository","core_calendar/events"],function(a,b,c,d,e,f,g,h,i,j){var k=!1,l={ROOT:"[data-region='summary-modal-container']",EDIT_BUTTON:'[data-action="edit"]',DELETE_BUTTON:'[data-action="delete"]'},m=function(a){e.call(this,a)};return m.TYPE="core_calendar-event_summary",m.prototype=Object.create(e.prototype),m.prototype.constructor=m,m.prototype.getEditButton=function(){return"undefined"==typeof this.editButton&&(this.editButton=this.getFooter().find(l.EDIT_BUTTON)),this.editButton},m.prototype.getDeleteButton=function(){return"undefined"==typeof this.deleteButton&&(this.deleteButton=this.getFooter().find(l.DELETE_BUTTON)),this.deleteButton},m.prototype.getEventId=function(){return this.getBody().find(l.ROOT).attr("data-event-id")},m.prototype.getEditUrl=function(){return this.getBody().find(l.ROOT).attr("data-edit-url")},m.prototype.isActionEvent=function(){return"true"==this.getBody().find(l.ROOT).attr("data-action-event")},m.prototype.registerEventListeners=function(){e.prototype.registerEventListeners.call(this);var f=g.create({type:g.types.CONFIRM},this.getDeleteButton()).then(function(b){return b.getRoot().on(h.yes,function(){var b=this.getEventId();i.deleteEvent(b).then(function(){a("body").trigger(j.deleted,[b]),this.hide()}.bind(this))["catch"](c.exception)}.bind(this)),b}.bind(this));this.getRoot().on(h.bodyRendered,function(){var a=this.getBody().find(l.ROOT).attr("data-event-title");f.then(function(c){c.setBody(b.get_string("confirmeventdelete","core_calendar",a))})}.bind(this)),d.define(this.getEditButton(),[d.events.activate]),this.getEditButton().on(d.events.activate,function(b,c){this.isActionEvent()?a("body").trigger(j.editActionEvent,[this.getEditUrl()]):a("body").trigger(j.editEvent,[this.getEventId()]),this.hide(),b.preventDefault(),b.stopPropagation(),c.originalEvent.preventDefault(),c.originalEvent.stopPropagation()}.bind(this))},k||(f.register(m.TYPE,m,"core_calendar/event_summary_modal"),k=!0),m});
+10 -4
View File
@@ -130,11 +130,13 @@ define([
var modalParams = {
title: eventData.name,
type: SummaryModal.TYPE,
body: Templates.render('core_calendar/event_summary_body', eventData)
body: Templates.render('core_calendar/event_summary_body', eventData),
templateContext: {
canedit: eventData.canedit,
candelete: eventData.candelete
}
};
if (!eventData.caneditevent) {
modalParams.footer = '';
}
// Create the modal.
return ModalFactory.create(modalParams);
@@ -196,6 +198,10 @@ define([
body.on(CalendarEvents.updated, function() {
window.location.reload();
});
body.on(CalendarEvents.editActionEvent, function(e, url) {
// Action events needs to be edit directly on the course module.
window.location.assign(url);
});
eventFormModalPromise.then(function(modal) {
// When something within the calendar tells us the user wants
+2 -1
View File
@@ -27,6 +27,7 @@ define([], function() {
created: 'calendar-events:created',
deleted: 'calendar-events:deleted',
updated: 'calendar-events:updated',
editEvent: 'calendar-events:edit_event'
editEvent: 'calendar-events:edit_event',
editActionEvent: 'calendar-events:edit_action_event'
};
});
+30 -11
View File
@@ -41,14 +41,6 @@ define(['jquery', 'core/str', 'core/notification', 'core/custom_interaction_even
*/
var ModalEventSummary = function(root) {
Modal.call(this, root);
if (!this.getEditButton().length) {
Notification.exception({message: 'No edit button found'});
}
if (!this.getDeleteButton().length) {
Notification.exception({message: 'No delete button found'});
}
};
ModalEventSummary.TYPE = 'core_calendar-event_summary';
@@ -97,6 +89,26 @@ define(['jquery', 'core/str', 'core/notification', 'core/custom_interaction_even
return this.getBody().find(SELECTORS.ROOT).attr('data-event-id');
};
/**
* Get the url for the event being shown in this modal.
*
* @method getEventUrl
* @return {String}
*/
ModalEventSummary.prototype.getEditUrl = function() {
return this.getBody().find(SELECTORS.ROOT).attr('data-edit-url');
};
/**
* Is this an action event.
*
* @method getEventUrl
* @return {String}
*/
ModalEventSummary.prototype.isActionEvent = function() {
return (this.getBody().find(SELECTORS.ROOT).attr('data-action-event') == 'true');
};
/**
* Set up all of the event handling for the modal.
*
@@ -140,9 +152,16 @@ define(['jquery', 'core/str', 'core/notification', 'core/custom_interaction_even
]);
this.getEditButton().on(CustomEvents.events.activate, function(e, data) {
// When the edit button is clicked we fire an event for the calendar UI to handle.
// We don't care how the UI chooses to handle it.
$('body').trigger(CalendarEvents.editEvent, [this.getEventId()]);
if (this.isActionEvent()) {
// Action events cannot be edited on the event form and must be redirected to the module UI.
$('body').trigger(CalendarEvents.editActionEvent, [this.getEditUrl()]);
} else {
// When the edit button is clicked we fire an event for the calendar UI to handle.
// We don't care how the UI chooses to handle it.
$('body').trigger(CalendarEvents.editEvent, [this.getEventId()]);
}
// There is nothing else for us to do so let's hide.
this.hide();
+46 -1
View File
@@ -26,9 +26,12 @@ namespace core_calendar\external;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . "/calendar/lib.php");
use \core\external\exporter;
use \core_calendar\local\event\entities\event_interface;
use \core_calendar\local\event\entities\action_event_interface;
use \core_calendar\local\event\container;
use \core_course\external\course_summary_exporter;
use \renderer_base;
@@ -154,6 +157,10 @@ class event_exporter extends exporter {
protected static function define_other_properties() {
return [
'url' => ['type' => PARAM_URL],
'editurl' => [
'type' => PARAM_URL,
'optional' => true
],
'icon' => [
'type' => event_icon_exporter::read_properties_definition(),
],
@@ -164,7 +171,17 @@ class event_exporter extends exporter {
'course' => [
'type' => course_summary_exporter::read_properties_definition(),
'optional' => true,
]
],
'canedit' => ['type' => PARAM_BOOL],
'displayeventsource' => ['type' => PARAM_BOOL],
'subscription' => [
'type' => PARAM_RAW,
'optional' => true,
'default' => null,
'null' => NULL_ALLOWED
],
'isactionevent' => ['type' => PARAM_BOOL],
'candelete' => ['type' => PARAM_BOOL]
];
}
@@ -177,11 +194,21 @@ class event_exporter extends exporter {
protected function get_other_values(renderer_base $output) {
$values = [];
$event = $this->event;
$legacyevent = container::get_event_mapper()->from_event_to_legacy_event($event);
$context = $this->related['context'];
$values['isactionevent'] = false;
if ($moduleproxy = $event->get_course_module()) {
$modulename = $moduleproxy->get('modname');
$moduleid = $moduleproxy->get('id');
$url = new \moodle_url(sprintf('/mod/%s/view.php', $modulename), ['id' => $moduleid]);
$values['isactionevent'] = true;
// Build edit event url for action events.
$params = array('update' => $moduleid, 'return' => true, 'sesskey' => sesskey());
$editurl = new \moodle_url('/course/mod.php', $params);
$values['editurl'] = $editurl->out(false);
} else {
// TODO MDL-58866 We do not have any way to find urls for events outside of course modules.
global $CFG;
@@ -208,6 +235,24 @@ class event_exporter extends exporter {
$values['course'] = $coursesummaryexporter->export($output);
}
$values['canedit'] = calendar_edit_event_allowed($legacyevent);
$values['candelete'] = (!$values['isactionevent'] && $values['canedit']);
// Handle event subscription.
$values['subscription'] = null;
$values['displayeventsource'] = false;
if (!empty($legacyevent->subscriptionid)) {
$subscription = calendar_get_subscription($legacyevent->subscriptionid);
if (!empty($subscription) && $CFG->calendar_showicalsource) {
$values['displayeventsource'] = true;
$subscriptiondata = new \stdClass();
if (!empty($subscription->url)) {
$subscriptiondata->url = $subscription->url;
}
$subscriptiondata->name = $subscription->name;
$values['subscription'] = json_encode($subscriptiondata);
}
}
return $values;
}
+20 -50
View File
@@ -712,37 +712,32 @@ class core_calendar_external extends external_api {
* @return array Array of event details
*/
public static function get_calendar_event_by_id($eventid) {
global $CFG;
global $CFG, $PAGE, $USER;
require_once($CFG->dirroot."/calendar/lib.php");
// Parameter validation.
$params = ['eventid' => $eventid];
$params = self::validate_parameters(self::get_calendar_event_by_id_parameters(), $params);
self::validate_parameters(self::get_calendar_event_by_id_parameters(), $params);
$context = \context_user::instance($USER->id);
self::validate_context($context);
$warnings = array();
// We need to get events asked for eventids.
$event = calendar_get_events_by_id([$eventid]);
$eventobj = calendar_event::load($eventid);
list($event[$eventid]->description, $event[$eventid]->format) = $eventobj->format_external_text();
$event[$eventid]->caneditevent = calendar_edit_event_allowed($eventobj);
$legacyevent = calendar_event::load($eventid);
$legacyevent->count_repeats();
$event[$eventid]->subscription = null;
$event[$eventid]->displayeventsource = false;
if (!empty($event[$eventid]->subscriptionid)) {
$subscription = calendar_get_subscription($event[$eventid]->subscriptionid);
if (!empty($subscription) && $CFG->calendar_showicalsource) {
$event[$eventid]->displayeventsource = true;
$subscriptiondata = new stdClass();
if (!empty($subscription->url)) {
$subscriptiondata->url = $subscription->url;
}
$subscriptiondata->name = $subscription->name;
$event[$eventid]->subscription = json_encode($subscriptiondata);
}
}
$eventmapper = event_container::get_event_mapper();
$event = $eventmapper->from_legacy_event_to_event($legacyevent);
return array('event' => $event[$eventid], 'warnings' => $warnings);
$cache = new events_related_objects_cache([$event]);
$relatedobjects = [
'context' => $cache->get_context($event),
'course' => $cache->get_course($event),
];
$exporter = new event_exporter($event, $relatedobjects);
$renderer = $PAGE->get_renderer('core_calendar');
return array('event' => $exporter->export($renderer), 'warnings' => $warnings);
}
/**
@@ -751,35 +746,10 @@ class core_calendar_external extends external_api {
* @return external_description
*/
public static function get_calendar_event_by_id_returns() {
$eventstructure = event_exporter::get_read_structure();
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),
'subscription' => new external_value(PARAM_RAW, 'Subscription object serialized', VALUE_OPTIONAL,
null, NULL_ALLOWED),
'caneditevent' => new external_value(PARAM_BOOL, 'Whether the user can edit the event'),
'displayeventsource' => new external_value(PARAM_BOOL, 'Whether the source should be displayed'),
),
'event'
),
'event' => $eventstructure,
'warnings' => new external_warnings()
)
);
@@ -26,7 +26,8 @@
"eventtype": "open"
}
}}
<div data-region="summary-modal-container" data-event-id="{{id}}" data-event-title="{{name}}">
<div data-region="summary-modal-container" data-event-id="{{id}}" data-event-title="{{name}}"
data-action-event="{{isactionevent}}" data-edit-url="{{editurl}}">
<h4>{{#str}} when, core_calendar {{/str}}</h4>
{{#userdate}} {{timestart}}, {{#str}} strftimerecentfull {{/str}} {{/userdate}}
<br>
@@ -26,7 +26,11 @@
}}
{{< core/modal }}
{{$footer}}
<button type="button" class="btn btn-secondary" data-action="delete">{{#str}} delete {{/str}}</button>
<button type="button" class="btn btn-primary" data-action="edit">{{#str}} edit {{/str}}</button>
{{#canedit}}
{{#candelete}}
<button type="button" class="btn btn-secondary" data-action="delete">{{#str}} delete {{/str}}</button>
{{/candelete}}
<button type="button" class="btn btn-primary" data-action="edit">{{#str}} edit {{/str}}</button>
{{/canedit}}
{{/footer}}
{{/ core/modal }}