Commit c544623c authored by Romain Courteaud's avatar Romain Courteaud

[erp5_web_renderjs_ui] Launcher: prevent concurrent loading for the same gadget

Do not prevent different gadget to be loaded in parallel
parent 6cea93ba
...@@ -35,33 +35,45 @@ ...@@ -35,33 +35,45 @@
gadget.props.panel_argument_list = {}; gadget.props.panel_argument_list = {};
} }
function route(my_root_gadget, my_scope, my_method, argument_list) { function executeRouteMethod(my_gadget, my_method, argument_list) {
return my_root_gadget.getDeclaredGadget(my_scope) // Execute a method on a gadget
.push(undefined, function (error) {
if (error instanceof rJS.ScopeError) {
var element = my_root_gadget
.element
.querySelector("[data-gadget-scope='" +
my_scope + "']");
if (element !== null) {
return my_root_gadget.declareGadget(
element.getAttribute('data-gadget-async-url'),
{
scope: my_scope,
element: element
}
);
}
}
throw error;
})
.push(function (my_gadget) {
if (argument_list) { if (argument_list) {
return my_gadget[my_method].apply(my_gadget, argument_list); return my_gadget[my_method].apply(my_gadget, argument_list);
} }
return my_gadget[my_method](); return my_gadget[my_method]();
}
function route(my_root_gadget, my_scope, my_method, argument_list) {
// If the gadget already has been declared, execute the method
// No need to care about concurrency at this point.
// This should be handled by the gadget itself if needed
if (my_root_gadget.props.is_declared_gadget_dict[my_scope]) {
return my_root_gadget.getDeclaredGadget(my_scope)
.push(function (my_gadget) {
return executeRouteMethod(my_gadget, my_method, argument_list);
}); });
} }
// declare the gadget and run the method
var method;
if (my_scope === 'notification') {
method = my_root_gadget.declareAndExecuteNotificationGadget;
} else if (my_scope === 'translation_gadget') {
method = my_root_gadget.declareAndExecuteTranslationGadget;
} else if (my_scope === 'header') {
method = my_root_gadget.declareAndExecuteHeaderGadget;
} else if (my_scope === 'panel') {
method = my_root_gadget.declareAndExecutePanelGadget;
} else if (my_scope === 'editor_panel') {
method = my_root_gadget.declareAndExecuteEditorPanelGadget;
} else {
throw new Error('Unknown gadget scope: ' + my_scope);
}
return method.apply(my_root_gadget, [
my_scope,
my_method,
argument_list
]);
}
function updateHeader(gadget) { function updateHeader(gadget) {
return route(gadget, "header", 'notifySubmitted') return route(gadget, "header", 'notifySubmitted')
...@@ -166,7 +178,71 @@ ...@@ -166,7 +178,71 @@
////////////////////////////////////////// //////////////////////////////////////////
// Page rendering // Page rendering
////////////////////////////////////////// //////////////////////////////////////////
function declareAndExecuteRouteMethod(my_scope, my_method,
argument_list) {
// Must be called in a mutex protected method only
// The idea is to prevent loading the same gadget twice thanks to the mutex
var my_root_gadget = this,
my_gadget,
element;
// If a previous mutex method was running, no need to redeclare the gadget
if (my_root_gadget.props.is_declared_gadget_dict[my_scope]) {
return my_root_gadget.getDeclaredGadget(my_scope)
.push(function (my_gadget) {
return executeRouteMethod(my_gadget, my_method, argument_list);
});
}
element = my_root_gadget.element
.querySelector("[data-gadget-scope='" +
my_scope + "']");
return my_root_gadget.declareGadget(
element.getAttribute('data-gadget-async-url'),
{scope: my_scope}
)
.push(function (result) {
my_gadget = result;
return executeRouteMethod(my_gadget, my_method, argument_list);
})
.push(function (result) {
// Wait for the method to be finished before adding the gadget to the
// DOM. This reduces the panel flickering on slow machines
element.parentNode.replaceChild(my_gadget.element, element);
my_root_gadget.props.is_declared_gadget_dict[my_scope] = true;
return result;
});
}
rJS(window) rJS(window)
// Add mutex protected defered gadget loader.
// Multiple mutex are needed, to not prevent concurrent loading on
// different gadgets
.declareMethod(
'declareAndExecuteNotificationGadget',
declareAndExecuteRouteMethod,
{mutex: 'declareAndExecuteNotificationGadget'}
)
.declareMethod(
'declareAndExecuteTranslationGadget',
declareAndExecuteRouteMethod,
{mutex: 'declareAndExecuteTranslationGadget'}
)
.declareMethod(
'declareAndExecuteHeaderGadget',
declareAndExecuteRouteMethod,
{mutex: 'declareAndExecuteHeaderGadget'}
)
.declareMethod(
'declareAndExecutePanelGadget',
declareAndExecuteRouteMethod,
{mutex: 'declareAndExecutePanelGadget'}
)
.declareMethod(
'declareAndExecuteEditorPanelGadget',
declareAndExecuteRouteMethod,
{mutex: 'declareAndExecuteEditorPanelGadget'}
)
.setState({ .setState({
panel_visible: false, panel_visible: false,
setting_id: "setting/" + document.head.querySelector( setting_id: "setting/" + document.head.querySelector(
...@@ -178,7 +254,12 @@ ...@@ -178,7 +254,12 @@
setting_gadget, setting_gadget,
setting; setting;
this.props = { this.props = {
content_element: this.element.querySelector('.gadget-content') content_element: this.element.querySelector('.gadget-content'),
is_declared_gadget_dict: {
setting_gadget: true,
router: true,
jio_gadget: true
}
}; };
// Configure setting storage // Configure setting storage
return gadget.getDeclaredGadget("setting_gadget") return gadget.getDeclaredGadget("setting_gadget")
......
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>971.17819.63775.64836</string> </value> <value> <string>971.53509.42083.38280</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1540990953.44</float> <float>1542969999.44</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment