defer calls to app.* after et2_load is finished

changing et2_load egw_json plugin to return a promise for that
This commit is contained in:
Ralf Becker 2021-06-11 09:05:57 +02:00
parent 81c4df47f2
commit e18832e110
5 changed files with 53 additions and 33 deletions

View File

@ -18,6 +18,7 @@ import { egw } from "../jsapi/egw_global";
* @param {function} _callback function(_xml) * @param {function} _callback function(_xml)
* @param {object} _context for _callback * @param {object} _context for _callback
* @param {function} _fail_callback function(_xml) * @param {function} _fail_callback function(_xml)
* @return Promise
*/ */
export function et2_loadXMLFromURL(_url, _callback, _context, _fail_callback) { export function et2_loadXMLFromURL(_url, _callback, _context, _fail_callback) {
if (typeof _context == "undefined") { if (typeof _context == "undefined") {
@ -36,7 +37,7 @@ export function et2_loadXMLFromURL(_url, _callback, _context, _fail_callback) {
if (typeof win == "undefined") { if (typeof win == "undefined") {
win = egw.top; win = egw.top;
} }
win.jQuery.ajax({ return win.jQuery.ajax({
// we add the full url (protocol and domain) as sometimes just the path // we add the full url (protocol and domain) as sometimes just the path
// gives a CSP error interpreting it as file:///path // gives a CSP error interpreting it as file:///path
// (if there are a enough 404 errors in html content ...) // (if there are a enough 404 errors in html content ...)
@ -45,11 +46,13 @@ export function et2_loadXMLFromURL(_url, _callback, _context, _fail_callback) {
type: 'GET', type: 'GET',
dataType: 'xml', dataType: 'xml',
success: function (_data, _status, _xmlhttp) { success: function (_data, _status, _xmlhttp) {
if (typeof _callback === 'function') {
_callback.call(_context, _data.documentElement); _callback.call(_context, _data.documentElement);
}
}, },
error: function (_xmlhttp, _err) { error: function (_xmlhttp, _err) {
egw().debug('error', 'Loading eTemplate from ' + _url + ' failed! ' + _xmlhttp.status + ' ' + _xmlhttp.statusText); egw().debug('error', 'Loading eTemplate from ' + _url + ' failed! ' + _xmlhttp.status + ' ' + _xmlhttp.statusText);
if (typeof _fail_callback !== 'undefined') { if (typeof _fail_callback === 'function') {
_fail_callback.call(_context, _err); _fail_callback.call(_context, _err);
} }
} }

View File

@ -20,8 +20,9 @@ import {egw} from "../jsapi/egw_global";
* @param {function} _callback function(_xml) * @param {function} _callback function(_xml)
* @param {object} _context for _callback * @param {object} _context for _callback
* @param {function} _fail_callback function(_xml) * @param {function} _fail_callback function(_xml)
* @return Promise
*/ */
export function et2_loadXMLFromURL(_url : string, _callback : Function, _context : object, _fail_callback? : Function) export function et2_loadXMLFromURL(_url : string, _callback? : Function, _context? : object, _fail_callback? : Function)
{ {
if (typeof _context == "undefined") if (typeof _context == "undefined")
{ {
@ -43,7 +44,7 @@ export function et2_loadXMLFromURL(_url : string, _callback : Function, _context
{ {
win = egw.top; win = egw.top;
} }
win.jQuery.ajax({ return win.jQuery.ajax({
// we add the full url (protocol and domain) as sometimes just the path // we add the full url (protocol and domain) as sometimes just the path
// gives a CSP error interpreting it as file:///path // gives a CSP error interpreting it as file:///path
// (if there are a enough 404 errors in html content ...) // (if there are a enough 404 errors in html content ...)
@ -52,12 +53,13 @@ export function et2_loadXMLFromURL(_url : string, _callback : Function, _context
type: 'GET', type: 'GET',
dataType: 'xml', dataType: 'xml',
success: function(_data, _status, _xmlhttp){ success: function(_data, _status, _xmlhttp){
if (typeof _callback === 'function') {
_callback.call(_context, _data.documentElement); _callback.call(_context, _data.documentElement);
}
}, },
error: function(_xmlhttp, _err) { error: function(_xmlhttp, _err) {
egw().debug('error', 'Loading eTemplate from '+_url+' failed! '+_xmlhttp.status+' '+_xmlhttp.statusText); egw().debug('error', 'Loading eTemplate from '+_url+' failed! '+_xmlhttp.status+' '+_xmlhttp.statusText);
if(typeof _fail_callback !== 'undefined') if(typeof _fail_callback === 'function') {
{
_fail_callback.call(_context, _err); _fail_callback.call(_context, _err);
} }
} }

View File

@ -327,7 +327,8 @@ export class etemplate2 {
* @param {function} _callback called after template is loaded * @param {function} _callback called after template is loaded
* @param {object} _app local app object * @param {object} _app local app object
* @param {boolean} _no_et2_ready true: do not send et2_ready, used by et2_dialog to not overwrite app.js et2 object * @param {boolean} _no_et2_ready true: do not send et2_ready, used by et2_dialog to not overwrite app.js et2 object
* @param {string} _open_target flag of string to distinguishe between tab target and normal app object * @param {string} _open_target flag of string to distinguish between tab target and normal app object
* @return Promise
*/ */
load(_name, _url, _data, _callback, _app, _no_et2_ready, _open_target) { load(_name, _url, _data, _callback, _app, _no_et2_ready, _open_target) {
let app = _app || window.app; let app = _app || window.app;
@ -383,7 +384,7 @@ export class etemplate2 {
if (appname) { if (appname) {
promisses.push(egw(currentapp, window).includeJS('/' + appname + '/js/app.js', undefined, undefined, egw.webserverUrl)); promisses.push(egw(currentapp, window).includeJS('/' + appname + '/js/app.js', undefined, undefined, egw.webserverUrl));
} }
Promise.all(promisses).catch((err) => { return Promise.all(promisses).catch((err) => {
console.log("et2.load(): error loading lang-files and app.js: " + err.message); console.log("et2.load(): error loading lang-files and app.js: " + err.message);
}).then(() => { }).then(() => {
this.clear(); this.clear();
@ -538,8 +539,11 @@ export class etemplate2 {
throw e; throw e;
} }
} }
// Split the given data into array manager objects and pass those to the
// widget container - do this here because file is loaded async
this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
// Asynchronously load the XET file // Asynchronously load the XET file
et2_loadXMLFromURL(_url, function (_xmldoc) { return et2_loadXMLFromURL(_url, function (_xmldoc) {
// Scan for templates and store them // Scan for templates and store them
for (let i = 0; i < _xmldoc.childNodes.length; i++) { for (let i = 0; i < _xmldoc.childNodes.length; i++) {
const template = _xmldoc.childNodes[i]; const template = _xmldoc.childNodes[i];
@ -551,9 +555,6 @@ export class etemplate2 {
} }
_load.apply(this, []); _load.apply(this, []);
}, this); }, this);
// Split the given data into array manager objects and pass those to the
// widget container - do this here because file is loaded async
this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
}); });
} }
/** /**
@ -1015,8 +1016,7 @@ export class etemplate2 {
// set id in case serverside returned a different template // set id in case serverside returned a different template
this._DOMContainer.id = this.uniqueId = data.DOMNodeID; this._DOMContainer.id = this.uniqueId = data.DOMNodeID;
// @ts-ignore // @ts-ignore
this.load(data.name, data.url, data.data); return this.load(data.name, data.url, data.data);
return true;
} }
else { else {
// Not etemplate // Not etemplate
@ -1034,8 +1034,7 @@ export class etemplate2 {
uniqueId = data.DOMNodeID.replace('.', '-') + '-' + data['open_target']; uniqueId = data.DOMNodeID.replace('.', '-') + '-' + data['open_target'];
} }
const et2 = new etemplate2(node, data.menuaction, uniqueId); const et2 = new etemplate2(node, data.menuaction, uniqueId);
et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']); return et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']);
return true;
} }
else { else {
egw.debug("error", "Could not find target node %s", data.DOMNodeId); egw.debug("error", "Could not find target node %s", data.DOMNodeId);

View File

@ -501,7 +501,8 @@ export class etemplate2
* @param {function} _callback called after template is loaded * @param {function} _callback called after template is loaded
* @param {object} _app local app object * @param {object} _app local app object
* @param {boolean} _no_et2_ready true: do not send et2_ready, used by et2_dialog to not overwrite app.js et2 object * @param {boolean} _no_et2_ready true: do not send et2_ready, used by et2_dialog to not overwrite app.js et2 object
* @param {string} _open_target flag of string to distinguishe between tab target and normal app object * @param {string} _open_target flag of string to distinguish between tab target and normal app object
* @return Promise
*/ */
load(_name, _url, _data, _callback?, _app?, _no_et2_ready?, _open_target?) load(_name, _url, _data, _callback?, _app?, _no_et2_ready?, _open_target?)
{ {
@ -572,7 +573,7 @@ export class etemplate2
if (appname) { if (appname) {
promisses.push(egw(currentapp, window).includeJS('/'+appname+'/js/app.js', undefined, undefined, egw.webserverUrl)); promisses.push(egw(currentapp, window).includeJS('/'+appname+'/js/app.js', undefined, undefined, egw.webserverUrl));
} }
Promise.all(promisses).catch((err) => { return Promise.all(promisses).catch((err) => {
console.log("et2.load(): error loading lang-files and app.js: "+err.message); console.log("et2.load(): error loading lang-files and app.js: "+err.message);
}).then(() => { }).then(() => {
this.clear(); this.clear();
@ -774,8 +775,12 @@ export class etemplate2
throw e; throw e;
} }
} }
// Split the given data into array manager objects and pass those to the
// widget container - do this here because file is loaded async
this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
// Asynchronously load the XET file // Asynchronously load the XET file
et2_loadXMLFromURL(_url, function (_xmldoc) return et2_loadXMLFromURL(_url, function (_xmldoc)
{ {
// Scan for templates and store them // Scan for templates and store them
@ -788,10 +793,6 @@ export class etemplate2
} }
_load.apply(this, []); _load.apply(this, []);
}, this); }, this);
// Split the given data into array manager objects and pass those to the
// widget container - do this here because file is loaded async
this._widgetContainer.setArrayMgrs(this._createArrayManagers(_data));
}); });
} }
@ -1389,8 +1390,7 @@ export class etemplate2
// set id in case serverside returned a different template // set id in case serverside returned a different template
this._DOMContainer.id = this.uniqueId = data.DOMNodeID; this._DOMContainer.id = this.uniqueId = data.DOMNodeID;
// @ts-ignore // @ts-ignore
this.load(data.name, data.url, data.data); return this.load(data.name, data.url, data.data);
return true;
} }
else else
{ {
@ -1411,8 +1411,7 @@ export class etemplate2
uniqueId = data.DOMNodeID.replace('.', '-') + '-' + data['open_target']; uniqueId = data.DOMNodeID.replace('.', '-') + '-' + data['open_target'];
} }
const et2 = new etemplate2(node, data.menuaction, uniqueId); const et2 = new etemplate2(node, data.menuaction, uniqueId);
et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']); return et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']);
return true;
} }
else else
{ {

View File

@ -19,12 +19,13 @@
*/ */
import './egw_core.js'; import './egw_core.js';
import './egw_utils.js'; import './egw_utils.js';
import {etemplate2} from "../etemplate/etemplate2";
/** /**
* Module sending json requests * Module sending json requests
* *
* @param {string} _app application name object is instanciated for * @param {string} _app application name object is instantiated for
* @param {object} _wnd window object is instanciated for * @param {object} _wnd window object is instantiated for
*/ */
egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd) egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
{ {
@ -308,6 +309,17 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
return; return;
} }
// defer apply's for app.* after et2_load is finished
let apply_app = [];
if (data.response.filter((res) => res.type === 'et2_load').length)
{
apply_app = data.response.filter((res) => res.type === 'apply' && res.data.func.substr(0, 4) === 'app.');
if (apply_app.length)
{
data.response = data.response.filter((res) => !(res.type === 'apply' && res.data.func.substr(0, 4) === 'app.'));
}
}
// Flag for only data response - don't call callback if only data // Flag for only data response - don't call callback if only data
var only_data = (data.response.length > 0); var only_data = (data.response.length > 0);
@ -328,7 +340,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
try { try {
// Get a reference to the plugin // Get a reference to the plugin
var plugin = handler_level[res.type][j]; var plugin = handler_level[res.type][j];
if (res.type.match(/et2_load/)) if (res.type === 'et2_load')
{ {
if (egw.preference('show_generation_time', 'common', false) == "1") if (egw.preference('show_generation_time', 'common', false) == "1")
{ {
@ -345,10 +357,15 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
} }
} }
// Call the plugin callback // Call the plugin callback
plugin.callback.call( const promise = plugin.callback.call(
plugin.context ? plugin.context : this.context, plugin.context ? plugin.context : this.context,
res.type, res, this res.type, res, this
); );
// defer apply_app's after et2_load is finished (it returns a promise for that)
if (res.type === 'et2_load' && apply_app.length && typeof promise.then === 'function')
{
promise.then(() => this.handleResponse({response: apply_app}));
}
} catch(e) { } catch(e) {
var msg = e.message ? e.message : e + ''; var msg = e.message ? e.message : e + '';
var stack = e.stack ? "\n-- Stack trace --\n" + e.stack : ""; var stack = e.stack ? "\n-- Stack trace --\n" + e.stack : "";