Commit b54b55dd authored by Romain Courteaud's avatar Romain Courteaud

[erp5_xhtml_style] Do not crash the UI in case of gadget error

parent 48b1447b
/*global window, rJS, RSVP, document*/
/*global window, rJS, RSVP, document, console*/
/*jslint nomen: true, maxlen:80, indent:2*/
(function (window, document, rJS, RSVP) {
(function (window, rJS, RSVP, document, console) {
"use strict";
function promiseEventListener(target, type, useCapture) {
//////////////////////////
// Resolve the promise as soon as the event is triggered
......@@ -27,109 +28,124 @@
return new RSVP.Promise(resolver, canceller);
}
function displayFieldError(error) {
console.warn(error);
// Display the error message in the portal_status location
// As renderJS does not report which element is failing while loading
// a gadget
var error_element = document.getElementById('transition_message');
error_element.textContent = error + '. ' + error_element.textContent;
}
function getGadgetContent(gadget) {
return gadget.getContent()
.push(undefined, function (error) {
// Do not crash if gadget getContent is wrongly implemented,
// ie, UI should work even if one gadget does not
displayFieldError(error);
return {};
});
}
rJS(window)
/////////////////////////////////////////////////////////////////
// ready
/////////////////////////////////////////////////////////////////
// Init local properties
.ready(function (g) {
g.props = {};
.setState({
rejected_dict: {},
field_list: [],
gadget_list: []
})
// Assign the element to a variable
.ready(function (g) {
return g.getElement()
.push(function (element) {
g.props.element = element;
});
.allowPublicAcquisition('reportGadgetDeclarationError',
function (argument_list, scope) {
// Do not crash the UI in case of wrongly configured gadget,
// bad network, loading bug.
this.state.rejected_dict[scope] = null;
return displayFieldError(argument_list[0]);
})
.allowPublicAcquisition('reportServiceError',
function (argument_list) {
// Do not crash the UI in case of gadget service error.
return displayFieldError(argument_list[0]);
})
/////////////////////////////////////////////////////////////////
// declared methods
/////////////////////////////////////////////////////////////////
.declareService(function () {
var g = this,
i,
list_gadget = document.querySelectorAll("[data-gadget-url]"),
all_gadget,
list = [],
gadget_attributes = [],
url,
form = g.props.element.querySelector("form"),
scope,
value,
key,
tmp;
for (i = 0; i < list_gadget.length; i += 1) {
url = list_gadget[i].getAttribute("data-gadget-url");
key = list_gadget[i].getAttribute("data-gadget-editable");
value = list_gadget[i].getAttribute("data-gadget-value");
//renderable
if (url !== undefined && url !== null) {
tmp = {};
scope = list_gadget[i].getAttribute("data-gadget-scope");
list.push(g.getDeclaredGadget(scope));
tmp.sandbox = list_gadget[i].getAttribute("data-gadget-sandbox");
tmp.editable = key;
tmp.key = key;
tmp.value = value;
gadget_attributes.push(tmp);
}
}
// Call render on all gadget fields
var gadget = this,
field_list = [],
i;
return new RSVP.Queue()
.push(function () {
return RSVP.all(list);
})
.push(function (results) {
all_gadget = results;
list = [];
for (i = 0; i < gadget_attributes.length; i += 1) {
if (gadget_attributes[i].sandbox === "iframe") {
list.push(all_gadget[i].getElement());
var field_element_list =
gadget.element.querySelectorAll("[data-gadget-url]"),
field_element,
field_scope,
field_url,
promise_list = [];
for (i = 0; i < field_element_list.length; i += 1) {
field_element = field_element_list[i];
field_url = field_element.getAttribute("data-gadget-url");
field_scope = field_element.getAttribute("data-gadget-scope");
// Renderable
if ((field_url !== undefined) && (field_url !== null) &&
(field_scope !== null) &&
(!gadget.state.rejected_dict.hasOwnProperty(field_scope))) {
field_list.push({
sandbox: field_element.getAttribute("data-gadget-sandbox"),
editable: field_element.getAttribute("data-gadget-editable"),
key: field_element.getAttribute("data-gadget-editable"),
value: field_element.getAttribute("data-gadget-value")
});
promise_list.push(gadget.getDeclaredGadget(field_scope));
}
}
return RSVP.all(list);
gadget.state.field_list = field_list;
return RSVP.all(promise_list);
})
.push(function (elements) {
.push(function (result_list) {
gadget.state.gadget_list = result_list;
var iframe,
j,
sub_element,
sub_value,
sub_key;
list = [];
for (i = 0, j = 0; i < gadget_attributes.length; i += 1) {
if (all_gadget[i].render !== undefined) {
sub_value = gadget_attributes[i].value;
sub_key = gadget_attributes[i].key;
list.push(
all_gadget[i].render(
{
"key": sub_key,
"value": sub_value
}
).push(undefined, function (error) {
/* TODO: Highlight the gadget element with a small colored
sub_key,
promise_list = [];
for (i = 0; i < field_list.length; i += 1) {
if (result_list[i].render !== undefined) {
sub_value = field_list[i].value;
sub_key = field_list[i].key;
promise_list.push(
result_list[i].render({key: sub_key, value: sub_value})
.push(undefined, displayFieldError)
/* XXX Highlight the gadget element with a small colored
* error message. Clicking on the element could unroll
* more information like the traceback. */
console.log(error);
})
);
}
if (gadget_attributes[i].sandbox === "iframe") {
iframe = elements[j].querySelector('iframe');
if (field_list[i].sandbox === "iframe") {
sub_element = result_list[i].element;
iframe = sub_element.querySelector('iframe');
//xxx input field
elements[j].parentNode.style.width = "100%";
elements[j].parentNode.style.height = "100%";
sub_element.parentNode.style.width = "100%";
sub_element.parentNode.style.height = "100%";
//xxx section div
elements[j].style.width = "100%";
elements[j].style.height = "100%";
sub_element.style.width = "100%";
sub_element.style.height = "100%";
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.allowFullscreen = true;
j += 1;
}
}
return RSVP.all(list);
return RSVP.all(promise_list);
});
})
.push(function () {
.declareService(function () {
/*Do not use ajax call but submit an hidden form.
So in this way, we can use form submit mecanisme
provided by browser.
......@@ -142,28 +158,37 @@
submit/image button.
After all, submit the form manually again.
*/
var input_images =
g.props.element.querySelectorAll("input[type='image']"),
input_submits =
g.props.element.querySelectorAll("button[type='submit']");
list = [];
if (input_images.length || input_submits.length) {
list.push(promiseEventListener(g.props.element, "submit", false));
for (i = 0; i < input_images.length; i += 1) {
list.push(promiseEventListener(input_images[i], "click", false));
}
for (i = 0; i < input_submits.length; i += 1) {
list.push(promiseEventListener(input_submits[i], "click", false));
}
return RSVP.any(list);
}
return promiseEventListener(g.props.element, "submit", false);
var context = this,
form = this.element.querySelector("form");
return new RSVP.Queue()
.push(function () {
var image_list = context.element
.querySelectorAll("input[type='image']"),
submit_list = context.element
.querySelectorAll("button[type='submit']"),
i,
promise_list = [];
promise_list.push(promiseEventListener(context.element, "submit",
false));
for (i = 0; i < image_list.length; i += 1) {
promise_list.push(promiseEventListener(image_list[i], "click",
false));
}
for (i = 0; i < submit_list.length; i += 1) {
promise_list.push(promiseEventListener(submit_list[i], "click",
false));
}
return RSVP.any(promise_list);
})
.push(function (evt) {
var input,
hidden_button,
target;
list = [];
target,
i,
promise_list = [];
if (evt.type === "click") {
input = document.createElement("input");
input.setAttribute("type", "hidden");
......@@ -171,34 +196,34 @@
input.setAttribute("name", target.getAttribute("name"));
form.appendChild(input);
} else {
hidden_button = g.props.element.querySelector(".hidden_button");
hidden_button = context.element.querySelector(".hidden_button");
hidden_button.setAttribute("type", "hidden");
}
for (i = 0; i < all_gadget.length; i += 1) {
if (all_gadget[i].getContent !== undefined &&
gadget_attributes[i].editable !== null) {
list.push(all_gadget[i].getContent());
for (i = 0; i < context.state.gadget_list.length; i += 1) {
if (context.state.gadget_list[i].getContent !== undefined &&
context.state.field_list[i].editable !== null) {
promise_list.push(getGadgetContent(context.state.gadget_list[i]));
}
}
return RSVP.all(list);
return RSVP.all(promise_list);
})
.push(function (all_content) {
.push(function (content_list) {
var input,
i,
name;
for (i = 0; i < all_content.length; i += 1) {
for (name in all_content[i]) {
if (all_content[i].hasOwnProperty(name)) {
for (i = 0; i < content_list.length; i += 1) {
for (name in content_list[i]) {
if (content_list[i].hasOwnProperty(name)) {
input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", name);
input.setAttribute("value", all_content[i][name]);
input.setAttribute("value", content_list[i][name]);
form.appendChild(input);
}
}
}
})
.push(function () {
form.submit();
return form.submit();
});
});
}(window, document, rJS, RSVP));
\ No newline at end of file
}(window, rJS, RSVP, document, console));
\ No newline at end of file
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