1
0
Fork 0
mirror of synced 2024-07-06 23:21:05 +12:00
appwrite/public/scripts/views/service.js

260 lines
11 KiB
JavaScript
Raw Normal View History

2019-05-09 18:54:39 +12:00
(function (window) {
"use strict";
2019-05-09 20:01:51 +12:00
window.ls.container.get('view').add(
2019-05-09 18:54:39 +12:00
{
selector: 'data-service',
2019-05-12 23:20:51 +12:00
repeat: false,
2019-08-07 22:46:51 +12:00
controller: function(element, view, container, form, alerts, expression, window, router) {
let action = element.dataset['service'];
let service = element.dataset['name'] || action;
2019-05-09 18:54:39 +12:00
let event = element.dataset['event']; // load, click, change, submit
let confirm = element.dataset['confirm'] || ''; // Free text
let loading = element.dataset['loading'] || ''; // Free text
let loaderId = null;
let scope = element.dataset['scope'] || 'sdk'; // Free text
let debug = !!(element.dataset['debug']); // Free text
2019-08-08 01:02:14 +12:00
let success = (element.dataset['success'] || '');
let failure = (element.dataset['failure'] || '');
2019-08-07 22:46:51 +12:00
2019-08-08 01:02:14 +12:00
success = (success && success != '') ? success.trim().split(',') : [];
failure = (failure && failure != '') ? failure.trim().split(',') : [];
2019-05-09 18:54:39 +12:00
if (debug) console.log('%c[service init]: ' + action + ' (' + service + ')', 'color:red');
2019-08-07 22:46:51 +12:00
let callbacks = {
'reset': function () {
return function () {
if ('FORM' === element.tagName) {
return element.reset();
}
throw new Error('This callback is only valid for forms');
}
},
2019-08-07 23:44:40 +12:00
'alert': function (text) {
2019-08-07 22:46:51 +12:00
return function (alerts) {
2019-08-08 08:35:20 +12:00
alerts.add({ text: text, class: 'success' }, 3000);
2019-08-07 22:46:51 +12:00
}
},
2019-08-08 06:10:53 +12:00
'redirect': function (url) {
2019-08-07 22:46:51 +12:00
return function (router) {
2019-08-08 06:10:53 +12:00
router.change(url || '/');
2019-08-07 22:46:51 +12:00
}
},
'reload': function () {
return function (router) {
router.reload();
}
},
2019-08-08 06:10:53 +12:00
'trigger': function (events) {
return function (document) {
events = events.trim().split(',');
2019-08-07 22:46:51 +12:00
2019-08-08 06:10:53 +12:00
for (let i = 0; i < events.length; i++) {
if ('' === events[i]) {
continue;
}
if (debug) console.log('%c[event triggered]: ' + events[i], 'color:green');
2019-08-07 22:46:51 +12:00
2019-08-08 06:10:53 +12:00
document.dispatchEvent(new CustomEvent(events[i]));
}
}
}
2019-08-07 22:46:51 +12:00
};
2019-05-09 18:54:39 +12:00
2019-08-07 22:46:51 +12:00
/**
* Original Solution From:
* @see https://stackoverflow.com/a/41322698/2299554
* Notice: this version add support for $ sign in arg name.
*
* Retrieve a function's parameter names and default values
* Notes:
* - parameters with default values will not show up in transpiler code (Babel) because the parameter is removed from the function.
* - does NOT support inline arrow functions as default values
* to clarify: ( name = "string", add = defaultAddFunction ) - is ok
* ( name = "string", add = ( a )=> a + 1 ) - is NOT ok
* - does NOT support default string value that are appended with a non-standard ( word characters or $ ) variable name
* to clarify: ( name = "string" + b ) - is ok
* ( name = "string" + $b ) - is ok
* ( name = "string" + b + "!" ) - is ok
* ( name = "string" + λ ) - is NOT ok
* @param {function} func
* @returns {Array} - An array of the given function's parameter [key, default value] pairs.
*/
let getParams = function getParams(func) {
2019-08-07 19:02:12 +12:00
const REGEX_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
const REGEX_FUNCTION_PARAMS = /(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;
const REGEX_PARAMETERS_VALUES = /\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;
2019-08-07 22:46:51 +12:00
let functionAsString = func.toString();
let params = [];
let match;
2019-08-07 19:02:12 +12:00
2019-08-07 22:46:51 +12:00
functionAsString = functionAsString.replace(REGEX_COMMENTS, '');
functionAsString = functionAsString.match(REGEX_FUNCTION_PARAMS)[1];
if (functionAsString.charAt(0) === '(') {
functionAsString = functionAsString.slice(1, -1);
}
2019-08-07 19:02:12 +12:00
2019-08-07 22:46:51 +12:00
while (match = REGEX_PARAMETERS_VALUES.exec(functionAsString)) {
//params.push([match[1], match[2]]); // with default values
params.push(match[1]); // only with arg name
2019-08-07 19:02:12 +12:00
}
2019-08-07 22:46:51 +12:00
return params;
}
let resolve = function(target, prefix = 'param', data = {}) {
2019-08-08 01:02:14 +12:00
if (!target) {
return function() {};
}
2019-08-07 19:02:12 +12:00
let args = getParams(target);
2019-05-09 18:54:39 +12:00
if (debug) console.log('%c[form data]: ', 'color:green', data);
return target.apply(target, args.map(function(value) {
let result = null;
if(!value) {
return null;
}
/**
* 1. Get from element data-param-* (expression supported)
* 2. Get from element data-param-state-*
* 3. Get from element form object-*
*/
2019-08-07 23:44:40 +12:00
if(element.dataset[prefix + value.charAt(0).toUpperCase() + value.slice(1)]) {
result = expression.parse(element.dataset[prefix + value.charAt(0).toUpperCase() + value.slice(1)]);
2019-05-09 18:54:39 +12:00
}
if(data[value]) {
result = data[value];
}
if(!result) {
result = '';
}
if (debug) console.log('%c[param resolved]: (' + service + ') ' + value + '=' + result, 'color:#808080');
2019-08-08 01:02:14 +12:00
2019-05-09 18:54:39 +12:00
return result;
}));
};
let exec = function(event) {
2019-05-13 01:03:30 +12:00
element.$lsSkip = true;
2019-05-09 18:54:39 +12:00
if (debug) console.log('%c[executed]: ' + scope + '.' + action, 'color:yellow', event, element, document.body.contains(element));
if(!document.body.contains(element)) {
element = undefined;
return false;
}
if(event) {
event.preventDefault();
}
if(confirm) {
if (window.confirm(confirm) !== true) {
return false;
}
}
if(loading) {
2019-08-08 08:35:20 +12:00
loaderId = alerts.add({text: loading, class: ''}, 0);
2019-05-09 18:54:39 +12:00
}
let method = container.path(scope + '.' + action);
if(!method) {
throw new Error('Method "' + scope + '.' + action + '" not found');
}
2019-08-07 22:46:51 +12:00
let result = resolve(method, 'param', ('FORM' === element.tagName) ? form.toJson(element) : {});
2019-05-09 18:54:39 +12:00
if(!result) {
return;
}
result
.then(function (data) {
if(loaderId !== null) { // Remove loader if needed
alerts.remove(loaderId);
}
2019-08-06 17:25:54 +12:00
2019-05-09 18:54:39 +12:00
if(!element) {
return;
}
2019-08-06 17:25:54 +12:00
2019-08-08 01:02:14 +12:00
container.set(service.replace('.', '-'), data, true, true);
2019-08-08 06:10:53 +12:00
2019-08-08 01:02:14 +12:00
if (debug) console.log('%cservice ready: "' + service.replace('.', '-') + '"', 'color:green');
if (debug) console.log('%cservice:', 'color:blue', container.get(service.replace('.', '-')));
2019-05-13 01:03:30 +12:00
2019-08-08 01:02:14 +12:00
for (let i = 0; i < success.length; i++) { // Trigger success callbacks
container.resolve(resolve(callbacks[success[i]], 'successParam' + success[i].charAt(0).toUpperCase() + success[i].slice(1), {}));
2019-08-07 22:46:51 +12:00
}
2019-05-13 01:03:30 +12:00
element.$lsSkip = false;
view.render(element);
2019-05-09 18:54:39 +12:00
}, function (exception) {
if(loaderId !== null) { // Remove loader if needed
alerts.remove(loaderId);
}
if(!element) {
return;
}
2019-08-08 01:02:14 +12:00
for (let i = 0; i < failure.length; i++) { // Trigger success callbacks
container.resolve(resolve(callbacks[failure[i]], 'failureParam' + failure[i].charAt(0).toUpperCase() + failure[i].slice(1), {}));
2019-08-07 22:46:51 +12:00
}
element.$lsSkip = false;
view.render(element);
2019-05-09 18:54:39 +12:00
});
};
let events = event.trim().split(',');
for (let y = 0; y < events.length; y++) {
if ('' === events[y]) {
continue;
}
switch (events[y].trim()) {
case 'load':
exec();
break;
case 'none':
break;
case 'click':
case 'change':
case 'keypress':
case 'keydown':
case 'keyup':
case 'input':
case 'submit':
element.addEventListener(events[y], exec);
break;
default:
2019-05-14 21:02:51 +12:00
document.addEventListener(events[y], exec);
2019-05-09 18:54:39 +12:00
}
if (debug) console.log('%cregistered: "' + events[y].trim() + '" (' + service + ')', 'color:blue');
}
}
}
);
})(window);