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 {object} _context for _callback
* @param {function} _fail_callback function(_xml)
* @return Promise
*/
export function et2_loadXMLFromURL(_url, _callback, _context, _fail_callback) {
if (typeof _context == "undefined") {
@ -36,7 +37,7 @@ export function et2_loadXMLFromURL(_url, _callback, _context, _fail_callback) {
if (typeof win == "undefined") {
win = egw.top;
}
win.jQuery.ajax({
return win.jQuery.ajax({
// we add the full url (protocol and domain) as sometimes just the path
// gives a CSP error interpreting it as file:///path
// (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',
dataType: 'xml',
success: function (_data, _status, _xmlhttp) {
_callback.call(_context, _data.documentElement);
if (typeof _callback === 'function') {
_callback.call(_context, _data.documentElement);
}
},
error: function (_xmlhttp, _err) {
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);
}
}

View File

@ -20,8 +20,9 @@ import {egw} from "../jsapi/egw_global";
* @param {function} _callback function(_xml)
* @param {object} _context for _callback
* @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")
{
@ -43,7 +44,7 @@ export function et2_loadXMLFromURL(_url : string, _callback : Function, _context
{
win = egw.top;
}
win.jQuery.ajax({
return win.jQuery.ajax({
// we add the full url (protocol and domain) as sometimes just the path
// gives a CSP error interpreting it as file:///path
// (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',
dataType: 'xml',
success: function(_data, _status, _xmlhttp){
_callback.call(_context, _data.documentElement);
if (typeof _callback === 'function') {
_callback.call(_context, _data.documentElement);
}
},
error: function(_xmlhttp, _err) {
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);
}
}

View File

@ -327,7 +327,8 @@ export class etemplate2 {
* @param {function} _callback called after template is loaded
* @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 {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) {
let app = _app || window.app;
@ -383,7 +384,7 @@ export class etemplate2 {
if (appname) {
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);
}).then(() => {
this.clear();
@ -538,8 +539,11 @@ export class etemplate2 {
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
et2_loadXMLFromURL(_url, function (_xmldoc) {
return et2_loadXMLFromURL(_url, function (_xmldoc) {
// Scan for templates and store them
for (let i = 0; i < _xmldoc.childNodes.length; i++) {
const template = _xmldoc.childNodes[i];
@ -551,9 +555,6 @@ export class etemplate2 {
}
_load.apply(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
this._DOMContainer.id = this.uniqueId = data.DOMNodeID;
// @ts-ignore
this.load(data.name, data.url, data.data);
return true;
return this.load(data.name, data.url, data.data);
}
else {
// Not etemplate
@ -1034,8 +1034,7 @@ export class etemplate2 {
uniqueId = data.DOMNodeID.replace('.', '-') + '-' + data['open_target'];
}
const et2 = new etemplate2(node, data.menuaction, uniqueId);
et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']);
return true;
return et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']);
}
else {
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 {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 {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?)
{
@ -572,7 +573,7 @@ export class etemplate2
if (appname) {
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);
}).then(() => {
this.clear();
@ -774,8 +775,12 @@ export class etemplate2
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
et2_loadXMLFromURL(_url, function (_xmldoc)
return et2_loadXMLFromURL(_url, function (_xmldoc)
{
// Scan for templates and store them
@ -788,10 +793,6 @@ export class etemplate2
}
_load.apply(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
this._DOMContainer.id = this.uniqueId = data.DOMNodeID;
// @ts-ignore
this.load(data.name, data.url, data.data);
return true;
return this.load(data.name, data.url, data.data);
}
else
{
@ -1411,8 +1411,7 @@ export class etemplate2
uniqueId = data.DOMNodeID.replace('.', '-') + '-' + data['open_target'];
}
const et2 = new etemplate2(node, data.menuaction, uniqueId);
et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']);
return true;
return et2.load(data.name, data.url, data.data, null, null, null, data['fw-target']);
}
else
{

View File

@ -19,12 +19,13 @@
*/
import './egw_core.js';
import './egw_utils.js';
import {etemplate2} from "../etemplate/etemplate2";
/**
* Module sending json requests
*
* @param {string} _app application name object is instanciated for
* @param {object} _wnd window object is instanciated for
* @param {string} _app application name object is instantiated for
* @param {object} _wnd window object is instantiated for
*/
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;
}
// 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
var only_data = (data.response.length > 0);
@ -328,7 +340,7 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
try {
// Get a reference to the plugin
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")
{
@ -345,10 +357,15 @@ egw.extend('json', egw.MODULE_WND_LOCAL, function(_app, _wnd)
}
}
// Call the plugin callback
plugin.callback.call(
const promise = plugin.callback.call(
plugin.context ? plugin.context : this.context,
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) {
var msg = e.message ? e.message : e + '';
var stack = e.stack ? "\n-- Stack trace --\n" + e.stack : "";