Commit 14354bad authored by Roque's avatar Roque

erp5_officejs: refactoring in new officejs approach

- reorginize and extend app setting and customization
- each portal type has its own setting dictionary
- handling blob types in document render and submit
- remove hardcoded app configuration manifest
- allow custom view in controller
- common configurations refactored
- handle_action handles notify submit and redirect base on custom action
return
- controller default page forces storage sync if app version changes
- fix 401 login redirect in storage selection
- general code refactoring and cleanup
parent 2947b9d1
......@@ -91,6 +91,30 @@
}));
}
function getFormInfo(form_definition) {
var child_gadget_url,
form_type,
action_category = form_definition.action_type;
switch (action_category) {
case 'object_list':
form_type = 'list';
child_gadget_url = 'gadget_erp5_pt_form_list.html';
break;
case 'object_dialog':
form_type = 'dialog';
child_gadget_url = 'gadget_erp5_pt_form_dialog.html';
break;
case 'object_jio_js_script':
form_type = 'dialog';
child_gadget_url = 'gadget_erp5_pt_form_dialog.html';
break;
default:
form_type = 'page';
child_gadget_url = 'gadget_erp5_pt_form_view_editable.html';
}
return [form_type, child_gadget_url];
}
rJS(window)
/////////////////////////////////////////////////////////////////
// Acquired methods
......@@ -175,46 +199,72 @@
});
})
.declareMethod("getFormInfo", function (form_definition) {
var child_gadget_url,
form_type,
action_category = form_definition.action_type;
switch (action_category) {
case 'object_list':
form_type = 'list';
child_gadget_url = 'gadget_erp5_pt_form_list.html';
break;
case 'object_dialog':
form_type = 'dialog';
child_gadget_url = 'gadget_erp5_pt_form_dialog.html';
break;
case 'object_jio_js_script':
form_type = 'dialog';
child_gadget_url = 'gadget_erp5_pt_form_dialog.html';
break;
default:
form_type = 'page';
child_gadget_url = 'gadget_erp5_pt_form_view_editable.html';
}
return [form_type, child_gadget_url];
.declareMethod("getDialogFormDefinition", function (form_name, category) {
var gadget = this,
form_definition,
form_info;
return gadget.getSetting('portal_skin_folder')
.push(function (portal_skin_folder) {
return gadget.jio_get("portal_skins/" + portal_skin_folder + "/" +
form_name);
})
.push(function (form_result) {
form_definition = form_result.raw_dict._embedded._view
._embedded.form_definition;
form_definition.fields_raw_properties = form_result.raw_dict._embedded
._view.my_fields_raw_properties["default"];
form_definition._actions = form_result.raw_dict._embedded
._view._actions;
form_definition.group_list = form_result.raw_dict.group_list;
form_definition.title = form_result.raw_dict.title;
form_definition.portal_type_dict = {};
form_definition.action_type = category;
form_info = getFormInfo(form_definition);
form_definition.form_type = form_info[0];
form_definition.child_gadget_url = form_info[1];
return form_definition;
});
})
.declareMethod("getFormDefinition", function (portal_type,
action_reference) {
var gadget = this,
query = buildSearchQuery(portal_type, action_reference),
portal_type_dict_setting = portal_type.replace(/ /g, '_')
.toLowerCase() + "_dict",
portal_type_dict = {},
action_type,
action_title,
form_definition,
portal_skin_folder,
app_allowed_sub_types,
form_info,
error;
return gadget.getSetting("portal_skin_folder")
.push(function (result) {
if (!result) {
return RSVP.Queue()
.push(function () {
return RSVP.all([
gadget.getSetting(portal_type_dict_setting),
gadget.getSetting("portal_skin_folder"),
gadget.getSetting("app_allowed_sub_types")
]);
})
.push(function (result_list) {
app_allowed_sub_types = result_list[2];
if (!result_list[1]) {
throw new Error("Missing site configuration 'portal_skin_folder'");
}
result = "portal_skins/" + result;
portal_skin_folder = result;
portal_skin_folder = "portal_skins/" + result_list[1];
if (result_list[0]) {
try {
portal_type_dict = window.JSON.parse(result_list[0]);
} catch (e) {
if (e instanceof SyntaxError) {
throw new Error("Bad JSON dict in configuration setting '" +
portal_type_dict_setting + "'");
}
throw e;
}
}
return gadget.jio_allDocs({query: query});
})
.push(function (data) {
......@@ -244,7 +294,8 @@
._view._actions;
//[PATCH] if custom action and anonymous
// get _actions field from fields_raw_properties
if ("_actions" in form_definition.fields_raw_properties) {
if (form_definition.fields_raw_properties
.hasOwnProperty("_actions")) {
if (!form_definition._actions &&
action_type === "object_jio_js_script") {
form_definition._actions = form_definition
......@@ -254,28 +305,29 @@
}
form_definition.group_list = form_result.raw_dict.group_list;
form_definition.action_type = action_type;
form_info = getFormInfo(form_definition);
form_definition.form_type = form_info[0];
form_definition.child_gadget_url = form_info[1];
form_definition.title = action_title;
return gadget.getSetting("app_allowed_sub_types");
})
.push(function (allowed_sub_types_setting) {
return formatSettingList(allowed_sub_types_setting, portal_type);
form_definition.portal_type_dict = portal_type_dict;
return formatSettingList(app_allowed_sub_types, portal_type);
})
.push(function (allowed_sub_types_pairs) {
var allowed_sub_types = allowed_sub_types_pairs.map(function (pair) {
return pair[1];
});
form_definition.allowed_sub_types_list = allowed_sub_types;
form_definition.new_content_dialog_form = portal_type_dict
.new_content_dialog_form;
form_definition.new_content_category = portal_type_dict
.new_content_category;
return gadget.getViewAndActionDict(portal_type);
})
.push(function (action_view_dict) {
form_definition.has_more_views =
form_definition.portal_type_dict.has_more_views =
Object.keys(action_view_dict.view_list).length > 1;
form_definition.has_more_actions =
form_definition.portal_type_dict.has_more_actions =
Object.keys(action_view_dict.action_list).length > 0;
return gadget.getSetting('hide_header_add_button');
})
.push(function (hide_add_button_setting) {
form_definition.hide_add_button = hide_add_button_setting === "1";
return form_definition;
});
});
......
......@@ -269,7 +269,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>977.16294.5398.40106</string> </value>
<value> <string>978.26807.33358.5717</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -287,7 +287,7 @@
</tuple>
<state>
<tuple>
<float>1563811574.1</float>
<float>1568651276.38</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -10,6 +10,7 @@
/////////////////////////////////////////////////////////////////
.declareAcquiredMethod("jio_get", "jio_get")
.declareAcquiredMethod("jio_put", "jio_put")
.declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("getSetting", "getSetting")
.declareAcquiredMethod("notifySubmitted", 'notifySubmitted')
.declareAcquiredMethod("notifySubmitting", "notifySubmitting")
......@@ -20,28 +21,38 @@
.declareMethod("render", function (options) {
var gadget = this,
default_view,
app_view,
form_definition,
gadget_util,
jio_document,
portal_type,
front_page;
return RSVP.Queue()
current_version,
index;
current_version = window.location.href.replace(window.location.hash, "");
index = current_version.indexOf(window.location.host) +
window.location.host.length;
current_version = current_version.substr(index);
return gadget.getSetting("migration_version")
.push(function (migration_version) {
if (migration_version !== current_version) {
//if app version has changed, force storage sync
return gadget.redirect({
'command': 'display',
'options': {
'page': 'ojs_sync',
'auto_repair': true
}
});
}
})
.push(function () {
return RSVP.all([
gadget.declareGadget("gadget_officejs_common_util.html"),
gadget.getSetting('app_view_reference'),
gadget.getSetting('default_view_reference'),
gadget.getSetting('documents_editable')
gadget.getSetting('app_view_reference')
]);
})
.push(function (result_list) {
gadget_util = result_list[0];
app_view = options.action || result_list[1];
default_view = result_list[2];
options.editable = ((result_list[3] == "1") ?
true : options.editable);
return gadget.jio_get(options.jio_key);
})
.push(function (result) {
......@@ -64,46 +75,38 @@
} else {
portal_type = parent_portal_type;
}
front_page = portal_type === parent_portal_type;
return gadget_util.getFormDefinition(portal_type, app_view);
})
.push(function (result) {
return result;
}, function (error) {
if (error.status_code === 400) {
return gadget_util.getFormDefinition(portal_type, default_view);
}
throw error;
})
.push(function (result) {
form_definition = result;
return gadget_util.getFormInfo(form_definition);
})
.push(function (form_info) {
var form_type = form_info[0],
child_gadget_url = form_info[1];
.push(function (form_definition) {
return gadget.changeState({
jio_key: options.jio_key,
doc: jio_document,
portal_type: portal_type,
child_gadget_url: child_gadget_url,
child_gadget_url: form_definition.child_gadget_url,
form_definition: form_definition,
form_type: form_type,
editable: options.editable,
view: options.view || default_view,
front_page: front_page
form_type: form_definition.form_type,
view: options.view || app_view
});
});
})
.onStateChange(function () {
var fragment = document.createElement('div'),
gadget = this;
gadget = this,
view_gadget_url = "gadget_officejs_form_view.html",
custom_gadget_url = gadget.state.form_definition.portal_type_dict
.custom_view_gadget;
while (this.element.firstChild) {
this.element.removeChild(this.element.firstChild);
}
this.element.appendChild(fragment);
return gadget.declareGadget("gadget_officejs_form_view.html",
if (custom_gadget_url) {
view_gadget_url = custom_gadget_url;
}
gadget.element.appendChild(fragment);
return gadget.declareGadget(view_gadget_url,
{element: fragment, scope: 'form_view'})
.push(function (form_view_gadget) {
return form_view_gadget.render(gadget.state);
......
......@@ -228,7 +228,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>977.8828.48212.64904</string> </value>
<value> <string>978.36723.12245.1757</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -246,7 +246,7 @@
</tuple>
<state>
<tuple>
<float>1563366536.83</float>
<float>1568969561.34</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -269,7 +269,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>977.6084.46638.22954</string> </value>
<value> <string>978.32380.21754.21845</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -287,7 +287,7 @@
</tuple>
<state>
<tuple>
<float>1563366620.2</float>
<float>1568708910.31</float>
<string>UTC</string>
</tuple>
</state>
......
/*global window, window, rJS, jIO, RSVP, document, URLSearchParams, UriTemplate, atob, console */
/*global window, window, rJS, jIO, RSVP, UriTemplate, atob, console */
/*jslint indent: 2, maxerr: 10, maxlen: 80 */
(function (window, rJS, jIO, RSVP, document, URLSearchParams, UriTemplate, atob,
(function (window, rJS, jIO, RSVP, UriTemplate, atob,
console) {
"use strict";
......@@ -30,7 +30,7 @@
command: 'raw',
options: {
url: UriTemplate.parse(regexp.exec(login_page)[1])
.expand({came_from: came_from})
.expand({came_from: came_from})
}
});
});
......@@ -112,13 +112,11 @@
.declareAcquiredMethod('getUrlFor', 'getUrlFor')
.declareMethod('createJio', function (jio_options) {
var appcache_storage,
var gadget = this,
appcache_storage,
hateoas_section,
hateoas_section_and_view,
origin_url = window.location.href,
hateoas_section = "./hateoas_appcache/",
hateoas_section_and_view = hateoas_section + "definition_view/",
// TODO manifest should come from gadget.props.cache_file
// add script in html body
manifest = "gadget_officejs_text_editor.configuration",
jio_appchache_options = {
type: "replicate",
parallel_operation_attachment_amount: 10,
......@@ -143,7 +141,7 @@
type: "saferepair",
sub_storage: {
type: "appcache",
manifest: manifest
manifest: ""
}
}
},
......@@ -153,7 +151,8 @@
return;
}
jio_appchache_options.local_sub_storage = JSON.parse(
JSON.stringify(jio_options));
JSON.stringify(jio_options)
);
jio_options = {
type: 'dateupdater',
sub_storage: jio_options,
......@@ -164,7 +163,17 @@
} catch (error) {
this.state_parameter_dict.jio_storage = undefined;
}
return this.getSetting("jio_storage_name")
return gadget.getSetting("app_configuration")
.push(function (app_configuration) {
jio_appchache_options.remote_sub_storage.sub_storage.manifest =
app_configuration;
return gadget.getSetting("hateoas_appcache");
})
.push(function (hateoas_appcache) {
hateoas_section = "./" + hateoas_appcache + "/";
hateoas_section_and_view = hateoas_section + "definition_view/";
return gadget.getSetting("jio_storage_name");
})
.push(function (jio_storage_name) {
if (jio_storage_name === undefined) { return; }
appcache_storage = jIO.createJIO(jio_appchache_options);
......@@ -178,18 +187,21 @@
.push(function () {
return appcache_storage.allAttachments(origin_url)
.push(function (attachment_dict) {
var id, base64, promise_list = [], i = 0;
var id, promise_list = [], i = 0;
for (id in attachment_dict) {
if (attachment_dict.hasOwnProperty(id)) {
if (id.startsWith(hateoas_section)) {
promise_list.push(
appcache_storage
.getAttachment(origin_url, id,
{"format": "json"}));
.getAttachment(origin_url, id,
{"format": "json"}
)
);
} else {
promise_list.push(
appcache_storage
.getAttachment(origin_url, id));
.getAttachment(origin_url, id)
);
}
configuration_ids_list[i] = id;
i += 1;
......@@ -198,7 +210,7 @@
return RSVP.all(promise_list);
})
.push(function (content_list) {
var i, id, parser, urlParams, content, promise_list = [];
var i, id, content, promise_list = [];
for (i = 0; i < content_list.length; i += 1) {
id = configuration_ids_list[i];
if (id.startsWith(hateoas_section)) {
......@@ -224,11 +236,13 @@
console.log("Error while appcache-local " +
"storage synchronization");
if (error && error.currentTarget &&
error.currentTarget.status === "401") {
error.currentTarget.status === 401) {
console.log("Unauthorized access to storage," +
"sync cancelled");
gadget.state_parameter_dict.jio_storage_name = "ERP5";
return;
}
console.log(error);
throw error;
});
});
......@@ -265,5 +279,5 @@
return wrapJioCall(this, 'repair', arguments);
});
}(window, rJS, jIO, RSVP, document, URLSearchParams, UriTemplate, atob,
}(window, rJS, jIO, RSVP, UriTemplate, atob,
console));
\ No newline at end of file
......@@ -234,7 +234,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>976.64179.23426.41403</string> </value>
<value> <string>978.6623.19198.10018</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -252,7 +252,7 @@
</tuple>
<state>
<tuple>
<float>1563367274.51</float>
<float>1567499774.35</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -8,7 +8,6 @@
// Acquired methods
/////////////////////////////////////////////////////////////////
.declareAcquiredMethod("jio_get", "jio_get")
.declareAcquiredMethod("getSetting", "getSetting")
.declareAcquiredMethod("redirect", "redirect")
.declareAcquiredMethod("jio_post", "jio_post")
......@@ -16,32 +15,13 @@
// declared methods
/////////////////////////////////////////////////////////////////
.declareMethod("createDocument", function (portal_type,
parent_portal_type) {
var gadget = this,
doc = {
title: "Untitled Document",
portal_type: portal_type,
parent_relative_url: parent_portal_type
};
return gadget.jio_post(doc)
.push(function (id) {
return gadget.redirect({
command: 'display',
options: {
jio_key: id,
editable: true
}
});
});
})
.declareMethod("render", function (options) {
var gadget = this,
allowed_sub_types_list = options.allowed_sub_types_list.split(","),
parent_portal_type = options.portal_type,
dialog_form = options.new_content_dialog_form,
dialog_category = options.new_content_category,
portal_type,
form_definition,
document_title;
return gadget.jio_get(options.jio_key)
.push(function (document) {
......@@ -53,32 +33,32 @@
})
.push(function (portal_type_result) {
portal_type = portal_type_result;
return gadget.getSetting("new_content_action");
})
.push(function (new_content_action) {
if (!new_content_action) {
throw new Error("Missing site configuration 'new_content_action'");
if (dialog_form) {
return gadget.declareGadget("gadget_officejs_common_util.html")
.push(function (gadget_util) {
return gadget_util.getDialogFormDefinition(dialog_form,
dialog_category);
})
.push(function (form_definition) {
return gadget.changeState({
doc: { header_title: form_definition.title || document_title,
portal_type: allowed_sub_types_list },
//TODO this should be a portal_dict setting and not global
parent_portal_type: parent_portal_type,
action_options: options,
child_gadget_url: form_definition.child_gadget_url,
form_type: form_definition.form_type,
form_definition: form_definition,
view: "view",
show_dialog: true
});
});
}
return gadget.jio_get(new_content_action);
})
.push(function (form_result) {
form_definition = form_result.raw_dict._embedded._view
._embedded.form_definition;
form_definition.fields_raw_properties = form_result.raw_dict._embedded
._view.my_fields_raw_properties["default"];
form_definition._actions = form_result.raw_dict._embedded
._view._actions;
form_definition.group_list = form_result.raw_dict.group_list;
form_definition.title = "Create Document";
return gadget.changeState({
doc: { title: document_title, portal_type: allowed_sub_types_list },
doc: { header_title: document_title,
portal_type: allowed_sub_types_list },
parent_portal_type: parent_portal_type,
action_options: options,
child_gadget_url: 'gadget_erp5_pt_form_dialog.html',
form_type: 'dialog',
form_definition: form_definition,
view: "view",
show_dialog: allowed_sub_types_list.length > 1
show_dialog: false
});
});
})
......@@ -96,21 +76,57 @@
.push(function (form_view_gadget) {
return form_view_gadget.render(gadget.state);
});
}
// if no form, skip dialog assuming there is only one portal type
return gadget.createDocument(gadget.state.doc.portal_type[0],
gadget.state.parent_portal_type
.replace(/ /g, '_').toLowerCase());
})
.declareMethod("createDocument", function (portal_type,
parent_portal_type,
content) {
var gadget = this,
doc = {};
if (!content) {
doc.portal_type = portal_type;
doc.parent_relative_url = parent_portal_type;
} else {
// if there is only one sub portal type
// skip create document dialog rendering
return gadget.createDocument(gadget.state.doc.portal_type[0],
gadget.state.parent_portal_type
.replace(/ /g, '_').toLowerCase());
doc = content;
}
if (!doc.title) {
doc.title = "Untitled document";
}
return gadget.jio_post(doc)
.push(function (id) {
return gadget.redirect({
command: 'display',
options: {
jio_key: id,
editable: true
}
});
});
})
.declareMethod("triggerSubmit", function () {
return this.element.querySelector('button[type="submit"]').click();
})
.allowPublicAcquisition('submitContent', function (options) {
var gadget = this,
content_dict = options[2];
return gadget.createDocument(content_dict.portal_type,
if (!content_dict.portal_type) {
content_dict.portal_type = gadget.state.doc.portal_type[0];
}
if (!content_dict.parent_relative_url) {
content_dict.parent_relative_url = gadget.state.parent_portal_type
.replace(/ /g, '_').toLowerCase();
}
return gadget.createDocument(gadget.state.doc.portal_type[0],
gadget.state.parent_portal_type
.replace(/ /g, '_').toLowerCase());
.replace(/ /g, '_').toLowerCase(),
content_dict);
});