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";
......@@ -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"}));
{"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'");
}
return gadget.jio_get(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_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";
.push(function (form_definition) {
return gadget.changeState({
doc: { title: document_title, portal_type: allowed_sub_types_list },
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: 'gadget_erp5_pt_form_dialog.html',
form_type: 'dialog',
child_gadget_url: form_definition.child_gadget_url,
form_type: form_definition.form_type,
form_definition: form_definition,
view: "view",
show_dialog: allowed_sub_types_list.length > 1
show_dialog: true
});
});
}
return gadget.changeState({
doc: { header_title: document_title,
portal_type: allowed_sub_types_list },
parent_portal_type: parent_portal_type,
show_dialog: false
});
});
})
......@@ -96,21 +76,57 @@
.push(function (form_view_gadget) {
return form_view_gadget.render(gadget.state);
});
} else {
// if there is only one sub portal type
// skip create document dialog rendering
}
// 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 {
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);
});
}(window, document, rJS));
\ No newline at end of file
......@@ -228,7 +228,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>977.1486.37580.56729</string> </value>
<value> <string>978.12359.56087.21111</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -246,7 +246,7 @@
</tuple>
<state>
<tuple>
<float>1562923143.55</float>
<float>1567507688.29</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -34,14 +34,13 @@
})
.declareMethod("render", function (options) {
var gadget = this, action_reference, gadget_util, form_definition;
var gadget = this, action_reference;
return RSVP.Queue()
.push(function () {
return RSVP.all([
gadget.getUrlParameter('portal_type'),
gadget.getUrlParameter('parent_relative_url'),
gadget.getUrlParameter("action"),
gadget.declareGadget("gadget_officejs_common_util.html")
gadget.getUrlParameter("action")
]);
})
.push(function (result) {
......@@ -50,18 +49,13 @@
options.parent_relative_url = result[1];
}
action_reference = result[2];
gadget_util = result[3];
return gadget.getActionFormDefinition(action_reference);
})
.push(function (result) {
form_definition = result;
return gadget_util.getFormInfo(form_definition);
})
.push(function (form_info) {
.push(function (form_definition) {
var fragment = document.createElement('div'),
action_gadget_url,
form_type = form_info[0],
child_gadget_url = form_info[1],
form_type = form_definition.form_type,
child_gadget_url = form_definition.child_gadget_url,
//an action form must have a GadgetField called
//"gadget_field_new_action_js_script"
//this gadget will point the custom action gadget
......@@ -90,16 +84,24 @@
element: fragment
})
.push(function (action_gadget) {
options.form_definition = form_definition;
return action_gadget.preRenderDocument(options);
})
.push(function (doc) {
state_options.doc = doc;
state_options.action_gadget_url = action_gadget_url;
return gadget.changeState(state_options);
}, function (error) {
if (error.status === 404) {
return gadget.notifySubmitted({
message: "Error in action",
status: "error"
});
} else {
return gadget.changeState(state_options);
}
throw error;
});
}
return gadget.changeState(state_options);
});
})
......@@ -129,38 +131,41 @@
//target_url = options[1],
content_dict = options[2],
fragment = document.createElement('div'),
jio_key;
submit_dict;
if (gadget.state.valid_action) {
return gadget.notifySubmitting()
.push(function () {
gadget.element.appendChild(fragment);
return gadget.declareGadget(gadget.state.action_gadget_url, {
scope: "action_field",
element: fragment
});
})
.push(function (action_gadget) {
return action_gadget.handleSubmit(content_dict, gadget.state);
})
.push(function (id) {
jio_key = id;
return gadget.notifySubmitting();
})
.push(function () {
return gadget.notifySubmitted({message: 'Data Updated',
status: 'success'});
.push(function (submit_result) {
submit_dict = submit_result;
//submit_dict must contain:
//notify: options_dict for notifySubmitted
//redirect: options_dict for redirect
return gadget.notifySubmitted(submit_dict.notify);
})
.push(function () {
return gadget.redirect({
command: 'display',
options: {
jio_key: jio_key,
editable: gadget.state.view === "edit"
}
return gadget.redirect(submit_dict.redirect);
}, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
return gadget.notifySubmitted({
message: "Action Failed",
status: "error"
});
}
throw error;
});
} else {
}
return gadget.notifySubmitted(
{message: 'Could not perform this action: configuration error',
status: 'fail'});
}
});
}(window, document, rJS, RSVP));
......@@ -269,7 +269,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>977.6150.49752.57668</string> </value>
<value> <string>978.31411.12952.38502</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -287,7 +287,7 @@
</tuple>
<state>
<tuple>
<float>1563205637.32</float>
<float>1568651040.61</float>
<string>UTC</string>
</tuple>
</state>
......
......@@ -3,6 +3,10 @@
<skin_folder>erp5_hal_json_style</skin_folder>
<skin_selection>AppCache</skin_selection>
</skin_folder_selection>
<skin_folder_selection>
<skin_folder>erp5_officejs_common</skin_folder>
<skin_selection>AppCache,Hal,RJS,RedirectAssist,View</skin_selection>
</skin_folder_selection>
<skin_folder_selection>
<skin_folder>erp5_text_editor</skin_folder>
<skin_selection>AppCache,Hal,RJS,RedirectAssist,View</skin_selection>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>business_template_skin_layer_priority</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>float</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>business_template_skin_layer_priority</string> </key>
<value> <float>42.0</float> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_officejs_common</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
erp5_hal_json_style | AppCache
erp5_officejs_common | AppCache
erp5_officejs_common | Hal
erp5_officejs_common | RJS
erp5_officejs_common | RedirectAssist
erp5_officejs_common | View
  • @rporchetto is it really needed to explicitely put the skin folder in so many skin selections? If it needs to be available in all of them, isn't it simpler to not define any?

  • Fixed. All explicit skin registrations where dropped.

Please register or sign in to reply
erp5_text_editor | AppCache
erp5_text_editor | Hal
erp5_text_editor | RJS
......
erp5_officejs_common
erp5_text_editor
erp5_web_officejs_ui
\ 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