Merge branch 'MDL-59936-master' of git://github.com/andrewnicols/moodle

This commit is contained in:
Jun Pataleta
2017-10-30 14:34:58 +13:00
14 changed files with 225 additions and 25 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","core_calendar/view_manager","core_calendar/crud","core_calendar/selectors"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p={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",TODAY:".today"},q=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},r=function(a){k.getEventById(a).then(function(b){if(!b.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+a);var c=b.event;return q(c.eventtype).then(function(a){return c.eventtype=a,c})}).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)},s=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(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(p.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(p.LOADING_ICON);if(g.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(p.LOADING_ICON);f.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},t=function(b,c){var d=a("body");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,s),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(c,d){var e=b.find(o.wrapper);a.setEventId(d),a.setContextId(e.data("contextId")),a.show()})}).fail(e.exception)},u=function(b){b.on("click",p.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null,e=c.closest(p.EVENT_LINK);d=e.length?e.data("eventId"):c.find(p.EVENT_LINK).data("eventId"),r(d)}),b.on("change",o.elements.courseSelector,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d,null).then(function(){return b.find(o.elements.courseSelector).val(d)}).fail(e.exception)});var c=n.registerEventFormModal(b);t(b,c),b.on("click",p.DAY,function(b){var d=a(b.target);if(!d.is(p.VIEW_DAY_LINK)){var f=a(this).attr("data-new-event-timestamp");c.then(function(a){var b=d.closest(o.wrapper);a.setCourseId(b.data("courseid"));var c=b.data("categoryid");"undefined"!=typeof c&&a.setCategoryId(c),a.setContextId(b.data("contextId")),a.setStartTime(f),a.show()}).fail(e.exception),b.preventDefault()}})};return{init:function(b){b=a(b),m.init(b),u(b)}}});
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","core_calendar/crud","core_calendar/selectors"],function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o){var p={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",TODAY:".today"},q=function(a){var b="type"+a;return c.get_string(b,"core_calendar").then(function(a){return a})},r=function(a){switch(a){case"user":return"calendar_event_user";case"site":return"calendar_event_site";case"group":return"calendar_event_group";case"category":return"calendar_event_category";case"course":return"calendar_event_course";default:return"calendar_event_course"}},s=function(a){var b="";k.getEventById(a).then(function(c){if(!c.event)throw new Error("Error encountered while trying to fetch calendar event with ID: "+a);var d=c.event;return b=r(d.eventtype),q(d.eventtype).then(function(a){return d.eventtype=a,d})}).then(function(a){var c={title:a.name,type:j.TYPE,body:d.render("core_calendar/event_summary_body",a),templateContext:{canedit:a.canedit,candelete:a.candelete,headerclasses:b,isactionevent:a.isactionevent,url:a.url}};return h.create(c)}).done(function(a){a.getRoot().on(g.hidden,function(){a.destroy()}),a.show()}).fail(e.exception)},t=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(p.DAY_CONTENT).addClass("hidden"),d.appendNodeContents(g,a,b),f&&(f.find(p.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(p.LOADING_ICON);if(g.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(a,"",""),f){var b=f.find(p.LOADING_ICON);f.find(p.DAY_CONTENT).removeClass("hidden"),d.replaceNode(b,"","")}}).fail(e.exception)},u=function(b,c){var d=a("body");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,t),d.on(l.eventMoved,function(){m.reloadCurrentMonth(b)}),c.then(function(a){d.on(l.editEvent,function(c,d){var e=b.find(o.wrapper);a.setEventId(d),a.setContextId(e.data("contextId")),a.show()})}).fail(e.exception)},v=function(b){b.on("click",p.EVENT_ITEM,function(b){b.preventDefault(),b.stopPropagation();var c=a(b.target),d=null,e=c.closest(p.EVENT_LINK);d=e.length?e.data("eventId"):c.find(p.EVENT_LINK).data("eventId"),s(d)}),b.on("change",o.elements.courseSelector,function(){var c=a(this),d=c.val();m.reloadCurrentMonth(b,d,null).then(function(){return b.find(o.elements.courseSelector).val(d)}).fail(e.exception)});var c=n.registerEventFormModal(b);u(b,c),b.on("click",p.DAY,function(b){var d=a(b.target);if(!d.is(p.VIEW_DAY_LINK)){var f=a(this).attr("data-new-event-timestamp");c.then(function(a){var b=d.closest(o.wrapper);a.setCourseId(b.data("courseid"));var c=b.data("categoryid");"undefined"!=typeof c&&a.setCategoryId(c),a.setContextId(b.data("contextId")),a.setStartTime(f),a.show()}).fail(e.exception),b.preventDefault()}})};return{init:function(b){b=a(b),m.init(b),v(b)}}});
+27
View File
@@ -86,18 +86,44 @@ define([
});
};
/**
* Get the CSS class to apply for the given event type.
*
* @param {String} eventType The calendar event type
* @return {String}
*/
var getEventTypeClassFromType = function(eventType) {
switch (eventType) {
case 'user':
return 'calendar_event_user';
case 'site':
return 'calendar_event_site';
case 'group':
return 'calendar_event_group';
case 'category':
return 'calendar_event_category';
case 'course':
return 'calendar_event_course';
default:
return 'calendar_event_course';
}
};
/**
* Render the event summary modal.
*
* @param {Number} eventId The calendar event id.
*/
var renderEventSummaryModal = function(eventId) {
var typeClass = '';
// Calendar repository promise.
CalendarRepository.getEventById(eventId).then(function(getEventResponse) {
if (!getEventResponse.event) {
throw new Error('Error encountered while trying to fetch calendar event with ID: ' + eventId);
}
var eventData = getEventResponse.event;
typeClass = getEventTypeClassFromType(eventData.eventtype);
return getEventType(eventData.eventtype).then(function(eventType) {
eventData.eventtype = eventType;
@@ -112,6 +138,7 @@ define([
templateContext: {
canedit: eventData.canedit,
candelete: eventData.candelete,
headerclasses: typeClass,
isactionevent: eventData.isactionevent,
url: eventData.url
}
+53 -20
View File
@@ -37,24 +37,57 @@
}} data-action-event="{{isactionevent}}"{{!
}} data-edit-url="{{editurl}}"{{!
}}>
<h4>{{#str}} when, core_calendar {{/str}}</h4>
{{#userdate}} {{timestart}}, {{#str}} strftimerecentfull {{/str}} {{/userdate}}
<br>
{{#description}}
<h4>{{#str}} description {{/str}}</h4>
{{{description}}}
{{/description}}
<h4>{{#str}} eventtype, core_calendar {{/str}}</h4>
{{eventtype}}
{{#iscategoryevent}}
<div>{{{category.nestedname}}}</div>
{{/iscategoryevent}}
{{#iscourseevent}}
<div><a href="{{url}}">{{course.fullname}}</a></div>
{{/iscourseevent}}
{{> core_calendar/event_subscription}}
{{#groupname}}
<div><a href="{{url}}">{{{course.fullname}}}</a></div>
<div>{{{groupname}}}</div>
{{/groupname}}
<div class="container-fluid">
<div class="row">
<div class="col-xs-1">{{#pix}} i/calendareventtime, core, {{#str}} when, core_calendar {{/str}} {{/pix}}</div>
<div class="col-xs-11">{{#userdate}} {{timestart}}, {{#str}} strftimerecentfull {{/str}} {{/userdate}}</div>
</div>
<div class="row m-t-1">
<div class="col-xs-1">{{#pix}} i/calendar, core, {{#str}} eventtype, core_calendar {{/str}} {{/pix}}</div>
<div class="col-xs-11">{{eventtype}}</div>
</div>
{{#description}}
<div class="row m-t-1">
<div class="col-xs-1">{{#pix}} i/calendareventdescription, core, {{#str}} description {{/str}} {{/pix}}</div>
<div class="col-xs-11">{{{.}}}</div>
</div>
{{/description}}
{{#iscategoryevent}}
<div class="row m-t-1">
<div class="col-xs-1">{{#pix}} i/categoryevent, core, {{#str}} category {{/str}} {{/pix}}</div>
<div class="col-xs-11">{{{category.nestedname}}}</div>
</div>
{{/iscategoryevent}}
{{#iscourseevent}}
<div class="row m-t-1">
<div class="col-xs-1">{{#pix}} i/courseevent, core, {{#str}} course {{/str}} {{/pix}}</div>
<div class="col-xs-11"><a href="{{url}}">{{{course.fullname}}}</a></div>
</div>
{{/iscourseevent}}
{{#groupname}}
<div class="row m-t-1">
<div class="col-xs-1">{{#pix}} i/courseevent, core, {{#str}} course {{/str}} {{/pix}}</div>
<div class="col-xs-11"><a href="{{url}}">{{{course.fullname}}}</a></div>
</div>
<div class="row m-t-1">
<div class="col-xs-1">{{#pix}} i/groupevent, core, {{#str}} group {{/str}} {{/pix}}</div>
<div class="col-xs-11">{{{groupname}}}</div>
</div>
{{/groupname}}
{{#subscription}}
{{#displayeventsource}}
<div class="row m-t-1">
<div class="col-xs-1">{{#pix}} i/rss, core, {{#str}} eventsource, core_calendar {{/str}} {{/pix}}</div>
<div class="col-xs-11">
{{#url}}
<a href="{{url}}">{{#str}}subscriptionsource, core_calendar, {{name}}{{/str}}</a>
{{/url}}
{{^url}}
<p>{{#str}}subscriptionsource, core_calendar, {{name}}{{/str}}</p>
{{/url}}
</div>
</div>
{{/displayeventsource}}
{{/subscription}}
</div>
</div>
+1
View File
@@ -108,6 +108,7 @@ $string['eventrepeat'] = 'Repeats';
$string['eventsall'] = 'All events';
$string['eventsdeleted'] = 'Events deleted';
$string['eventsimported'] = 'Events imported: {$a}';
$string['eventsource'] = 'Event source';
$string['eventsupdated'] = 'Events updated: {$a}';
$string['eventsfor'] = '{$a} events';
$string['eventskey'] = 'Events key';
+1 -1
View File
File diff suppressed because one or more lines are too long
+39 -1
View File
@@ -358,7 +358,8 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
};
/**
* Set the modal footer element.
* Set the modal footer element. The footer element is made visible, if it
* isn't already.
*
* This method is overloaded to take either a string
* value for the body or a jQuery promise that is resolved with HTML and Javascript
@@ -368,6 +369,9 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
* @param {(string|object)} value The footer string or jQuery promise
*/
Modal.prototype.setFooter = function(value) {
// Make sure the footer is visible.
this.showFooter();
var footer = this.getFooter();
if (typeof value === 'string') {
@@ -396,6 +400,34 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
}
};
/**
* Check if the footer has any content in it.
*
* @method hasFooterContent
* @return {bool}
*/
Modal.prototype.hasFooterContent = function() {
return this.getFooter().children().length ? true : false;
};
/**
* Hide the footer element.
*
* @method hideFooter
*/
Modal.prototype.hideFooter = function() {
this.getFooter().addClass('hidden');
};
/**
* Show the footer element.
*
* @method showFooter
*/
Modal.prototype.showFooter = function() {
this.getFooter().removeClass('hidden');
};
/**
* Mark the modal as a large modal.
*
@@ -508,6 +540,12 @@ define(['jquery', 'core/templates', 'core/notification', 'core/key_codes',
return;
}
if (this.hasFooterContent()) {
this.showFooter();
} else {
this.hideFooter();
}
if (!this.isAttached) {
this.attachToDOM();
}
@@ -195,6 +195,8 @@ class icon_system_fontawesome extends icon_system_font {
'core:i/badge' => 'fa-shield',
'core:i/calc' => 'fa-calculator',
'core:i/calendar' => 'fa-calendar',
'core:i/calendareventdescription' => 'fa-align-left',
'core:i/calendareventtime' => 'fa-clock-o',
'core:i/caution' => 'fa-exclamation text-warning',
'core:i/checked' => 'fa-check',
'core:i/checkpermissions' => 'fa-unlock-alt',
+1 -1
View File
@@ -45,7 +45,7 @@
data-region="modal"
aria-labelledby="{{uniqid}}-modal-title"
role="document">
<div class="modal-header" data-region="header">
<div class="modal-header {{$headerclasses}}{{headerclasses}}{{/headerclasses}}" data-region="header">
<button type="button" class="close" data-action="hide" title="{{#str}} closebuttontitle {{/str}}"></button>
{{$header}}
<h3 id="{{uniqid}}-modal-title" data-region="title" tabindex="0">
Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

+3
View File
@@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 -1 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M0 12h16v2H0v-2zm10-3H0v2h10V9zM0 8h16V6H0v2zm10-5H0v2h10V3zm6-1V0H0v2h16z" fill="#999"/></svg>

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

+3
View File
@@ -0,0 +1,3 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M11.9 13.4c.3-.2.5-.4.8-.7 1.3-1.3 2-2.9 2-4.8s-.7-3.4-2-4.8c-1.3-1.3-2.9-2-4.8-2s-3.4.7-4.8 2c-1.3 1.3-2 2.9-2 4.8s.7 3.4 2 4.8c.3.3.5.5.8.7l-.8 1.8c-.1.2 0 .5.2.7.2.1.5 0 .7-.2l.9-1.7c.9.5 2 .7 3.1.7s2.2-.2 3.1-.7l.8 1.7c.1.2.4.4.7.2.2-.1.4-.4.2-.7l-.9-1.8zm-3.9.3c-1.6 0-2.9-.5-4-1.7-1.1-1.1-1.7-2.4-1.7-4S2.8 5.1 4 4c1.1-1.1 2.4-1.7 4-1.7s2.9.5 4 1.7c1.1 1.1 1.7 2.4 1.7 4s-.5 2.9-1.7 4c-1.1 1.2-2.4 1.7-4 1.7zm0-6l2.6 2.1-.7.8-2.8-2.2c-.1-.1-.2-.2-.2-.4V4.6H8v3.1zm3.2-6.2L12 0c1.8.9 3.1 2.2 4 4l-1.5.8c-.7-1.5-1.8-2.6-3.3-3.3zM1.5 4.8L0 4C.9 2.2 2.2.9 4 0l.8 1.5c-1.5.7-2.6 1.8-3.3 3.3z" fill="#999"/></svg>

After

Width:  |  Height:  |  Size: 917 B

+1 -1
View File
@@ -43,7 +43,7 @@
<div class="modal moodle-has-zindex" data-region="modal-container" aria-hidden="true" role="dialog">
<div class="modal-dialog {{$classes}}{{/classes}}" role="document" data-region="modal" aria-labelledby="{{uniqid}}-modal-title">
<div class="modal-content">
<div class="modal-header" data-region="header">
<div class="modal-header {{$headerclasses}}{{headerclasses}}{{/headerclasses}}" data-region="header">
<button type="button" class="close" data-action="hide" aria-label={{#quote}}{{#str}}closebuttontitle{{/str}}{{/quote}}>
<span aria-hidden="true">&times;</span>
</button>
@@ -0,0 +1,93 @@
{{!
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 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": "User",
"source": "Ical imported",
"groupname": "Group 1"
}
}}
<div{{!
}} data-region="summary-modal-container"{{!
}} data-event-id="{{id}}"{{!
}} data-event-title="{{name}}"{{!
}} data-event-count="{{eventcount}}"{{!
}} data-event-="{{repeatid}}"{{!
}} data-action-event="{{isactionevent}}"{{!
}} data-edit-url="{{editurl}}"{{!
}}>
<div class="container-fluid">
<div class="row-fluid">
<div class="span1">{{#pix}} i/calendareventtime, core, {{#str}} when, core_calendar {{/str}} {{/pix}}</div>
<div class="span11">{{#userdate}} {{timestart}}, {{#str}} strftimerecentfull {{/str}} {{/userdate}}</div>
</div>
<div class="row-fluid m-t-1">
<div class="span1">{{#pix}} i/calendar, core, {{#str}} eventtype, core_calendar {{/str}} {{/pix}}</div>
<div class="span11">{{eventtype}}</div>
</div>
{{#description}}
<div class="row-fluid m-t-1">
<div class="span1">{{#pix}} i/calendareventdescription, core, {{#str}} description {{/str}} {{/pix}}</div>
<div class="span11">{{{.}}}</div>
</div>
{{/description}}
{{#iscategoryevent}}
<div class="row-fluid m-t-1">
<div class="span1">{{#pix}} i/categoryevent, core, {{#str}} category {{/str}} {{/pix}}</div>
<div class="span11">{{{category.nestedname}}}</div>
</div>
{{/iscategoryevent}}
{{#iscourseevent}}
<div class="row-fluid m-t-1">
<div class="span1">{{#pix}} i/courseevent, core, {{#str}} course {{/str}} {{/pix}}</div>
<div class="span11"><a href="{{url}}">{{{course.fullname}}}</a></div>
</div>
{{/iscourseevent}}
{{#groupname}}
<div class="row-fluid m-t-1">
<div class="span1">{{#pix}} i/courseevent, core, {{#str}} course {{/str}} {{/pix}}</div>
<div class="span11"><a href="{{url}}">{{{course.fullname}}}</a></div>
</div>
<div class="row-fluid m-t-1">
<div class="span1">{{#pix}} i/groupevent, core, {{#str}} group {{/str}} {{/pix}}</div>
<div class="span11">{{{groupname}}}</div>
</div>
{{/groupname}}
{{#subscription}}
{{#displayeventsource}}
<div class="row-fluid m-t-1">
<div class="span1">{{#pix}} i/rss, core, {{#str}} eventsource, core_calendar {{/str}} {{/pix}}</div>
<div class="span11">
{{#url}}
<a href="{{url}}">{{#str}}subscriptionsource, core_calendar, {{name}}{{/str}}</a>
{{/url}}
{{^url}}
<p>{{#str}}subscriptionsource, core_calendar, {{name}}{{/str}}</p>
{{/url}}
</div>
</div>
{{/displayeventsource}}
{{/subscription}}
</div>
</div>