MDL-57975 javascript: add user_date.js

Part of MDL-55611
This commit is contained in:
Ryan Wyllie 2017-02-21 05:32:12 +00:00
parent 9c7ffb80d3
commit b61015cfcd
3 changed files with 237 additions and 1 deletions

1
lib/amd/build/user_date.min.js vendored Normal file
View File

@ -0,0 +1 @@
define(["jquery","core/ajax","core/sessionstorage","core/config"],function(a,b,c,d){var e={},f=function(b){var c=a("html").attr("lang").replace("-","_");return"core_user_date/"+c+"/"+d.usertimezone+"/"+b.timestamp+"/"+b.format},g=function(a){return c.get(a)},h=function(a,b){c.set(a,b)},i=function(a){return"undefined"!=typeof e[a]},j=function(a){return e[a]},k=function(a,b){e[a]=b},l=function(a){var c=a.map(function(a){return{timestamp:a.timestamp,format:a.format}}),e={methodname:"core_get_user_dates",args:{contextid:d.contextid,timestamps:c}};return b.call([e],!0,!0)[0].then(function(b){b.dates.forEach(function(b,c){var d=a[c],e=f(d);h(e,b),d.deferred.resolve(b)})}).fail(function(b){a.forEach(function(a){a.deferred.reject(b)})})},m=function(b){var c=[],d=[];return b.forEach(function(b){var e=f(b);if(i(e))d.push(j(e));else{var h=a.Deferred(),l=g(e);l?h.resolve(l):(b.deferred=h,c.push(b)),k(e,h.promise()),d.push(h.promise())}}),c.length&&l(c),a.when.apply(a,d).then(function(){return 1===arguments.length?[arguments[0]]:Array.apply(null,arguments)})};return{get:m}});

233
lib/amd/src/user_date.js Normal file
View File

@ -0,0 +1,233 @@
// 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/>.
/**
* Fetch and render dates from timestamps.
*
* @module core/user_date
* @package core
* @copyright 2017 Ryan Wyllie <ryan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/ajax', 'core/sessionstorage', 'core/config'],
function($, Ajax, Storage, Config) {
/** @var {object} promisesCache Store all promises we've seen so far. */
var promisesCache = {};
/**
* Generate a cache key for the given request. The request should
* have a timestamp and format key.
*
* @param {object} request
* @return {string}
*/
var getKey = function(request) {
var language = $('html').attr('lang').replace('-', '_');
return 'core_user_date/' +
language + '/' +
Config.usertimezone + '/' +
request.timestamp + '/' +
request.format;
};
/**
* Retrieve a transformed date from the browser's storage.
*
* @param {string} key
* @return {string}
*/
var getFromLocalStorage = function(key) {
return Storage.get(key);
};
/**
* Save the transformed date in the browser's storage.
*
* @param {string} key
* @param {string} value
*/
var addToLocalStorage = function(key, value) {
Storage.set(key, value);
};
/**
* Check if a key is in the module's cache.
*
* @param {string} key
* @return {bool}
*/
var inPromisesCache = function(key) {
return (typeof promisesCache[key] !== 'undefined');
};
/**
* Retrieve a promise from the module's cache.
*
* @param {string} key
* @return {object} jQuery promise
*/
var getFromPromisesCache = function(key) {
return promisesCache[key];
};
/**
* Save the given promise in the module's cache.
*
* @param {string} key
* @param {object} promise
*/
var addToPromisesCache = function(key, promise) {
promisesCache[key] = promise;
};
/**
* Send a request to the server for each of the required timestamp
* and format combinations.
*
* Resolves the date's deferred with the values returned from the
* server and saves the value in local storage.
*
* @param {array} dates
* @return {object} jQuery promise
*/
var loadDatesFromServer = function(dates) {
var args = dates.map(function(data) {
return {
timestamp: data.timestamp,
format: data.format
};
});
var request = {
methodname: 'core_get_user_dates',
args: {
contextid: Config.contextid,
timestamps: args
}
};
return Ajax.call([request], true, true)[0].then(function(results) {
results.dates.forEach(function(value, index) {
var date = dates[index];
var key = getKey(date);
addToLocalStorage(key, value);
date.deferred.resolve(value);
});
})
.fail(function(ex) {
// If we failed to retrieve the dates then reject the date's
// deferred objects to make sure they don't hang.
dates.forEach(function(date) {
date.deferred.reject(ex);
});
});
};
/**
* Takes an array of request objects and returns a promise that
* is resolved with an array of formatted dates.
*
* The values in the returned array will be ordered the same as
* the request array.
*
* This function will check both the module's static promises cache
* and the browser's session storage to see if the user dates have
* already been loaded in order to avoid sending a network request
* if possible.
*
* Only dates not found in either cache will be sent to the server
* for transforming.
*
* A request object must have a timestamp key and a format key.
*
* E.g.
* var request = [
* {
* timestamp: 1293876000,
* format: '%d %B %Y'
* },
* {
* timestamp: 1293876000,
* format: '%A, %d %B %Y, %I:%M %p'
* }
* ];
*
* UserDate.get(request).done(function(dates) {
* console.log(dates[0]); // prints "1 January 2011".
* console.log(dates[1]); // prints "Saturday, 1 January 2011, 10:00 AM".
* });
*
* @param {array} requests
* @return {object} jQuery promise
*/
var get = function(requests) {
var ajaxRequests = [];
var promises = [];
// Loop over each of the requested timestamp/format combos
// and add a promise to the promises array for them.
requests.forEach(function(request) {
var key = getKey(request);
// If we've already got a promise then use it.
if (inPromisesCache(key)) {
promises.push(getFromPromisesCache(key));
} else {
var deferred = $.Deferred();
var cached = getFromLocalStorage(key);
if (cached) {
// If we were able to get the value from session storage
// then we can resolve the deferred with that value. No
// need to ask the server to transform it for us.
deferred.resolve(cached);
} else {
// Add this request to the list of ones we need to load
// from the server. Include the deferred so that it can
// be resolved when the server has responded with the
// transformed values.
request.deferred = deferred;
ajaxRequests.push(request);
}
// Remember this promise for next time so that we can
// bail out early if it is requested again.
addToPromisesCache(key, deferred.promise());
promises.push(deferred.promise());
}
});
// If we have any requests that we couldn't resolve from the caches
// then let's ask the server to get them for us.
if (ajaxRequests.length) {
loadDatesFromServer(ajaxRequests);
}
// Wait for all of the promises to resolve. Some of them may be waiting
// for a response from the server.
return $.when.apply($, promises).then(function() {
// This looks complicated but it's just converting an unknown
// length of arguments into an array for the promise to resolve
// with.
return arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments);
});
};
return {
get: get
};
});

View File

@ -322,7 +322,9 @@ class page_requirements_manager {
'theme' => $page->theme->name,
'jsrev' => $this->get_jsrev(),
'admin' => $CFG->admin,
'svgicons' => $page->theme->use_svg_icons()
'svgicons' => $page->theme->use_svg_icons(),
'usertimezone' => usertimezone(),
'contextid' => $page->context->id,
);
if ($CFG->debugdeveloper) {
$this->M_cfg['developerdebug'] = true;