From 82ad02d6c11877940ef62a0fe0e3ac6a34f53f6b Mon Sep 17 00:00:00 2001 From: Roque Porchetto <roque.porchetto@nexedi.com> Date: Tue, 23 Jan 2024 16:57:39 +0000 Subject: [PATCH] erp5_officejs: more dev framework flexibility and fixes - allow custom app configurator - render listbox form field extra configuration - fix date format rendering - allow configuration form fields to have extra js code - allow to customize listbox column styles - allow to customize listbox jio_alldocs - fix custom view handling - fix gadget field rendering - allow dev user to set custom header options - truncate long string fields - add custom submit gadget option - improve renderjs_extra - update graph gadget --- .../gadget_field_graph_dygraph_js.js | 35 +++- .../gadget_field_graph_dygraph_js.xml | 8 +- .../gadget_officejs_common_util_js.js | 4 +- .../gadget_officejs_common_util_js.xml | 6 +- ...ejs_controller_page_local_controller_js.js | 8 +- ...js_controller_page_local_controller_js.xml | 6 +- .../gadget_officejs_erp5_ojs_panel_js.js | 1 + .../gadget_officejs_erp5_ojs_panel_js.xml | 6 +- .../gadget_officejs_form_view_js.js | 177 +++++++++++++----- .../gadget_officejs_form_view_js.xml | 6 +- ...gadget_officejs_page_action_officejs_js.js | 1 + ...adget_officejs_page_action_officejs_js.xml | 6 +- 12 files changed, 197 insertions(+), 67 deletions(-) diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.js index 1455d8a372..1f2bcad9d3 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.js @@ -124,6 +124,39 @@ return graph_data_and_parameter; }; + var formatGraphDict = function (input_dict) { + var i, j, key, series = [], label_list = ['x'], point_list = [], serie_length, point; + for (i = 0; i < input_dict.data.length; i = i + 1) { + for (key of Object.keys(input_dict.data[i].value_dict)) { + serie_length = input_dict.data[i].value_dict[key].length; + if (key == 0) { + if (series.length === 0) { + series.push(input_dict.data[i].value_dict[key]); //x + } + } else { + series.push(input_dict.data[i].value_dict[key]); //yi + } + } + label_list.push(input_dict.data[i].title); + } + for (i = 0; i < serie_length; i = i + 1) { + point = []; + for (j = 0; j < series.length; j = j + 1) { + point.push(series[j][i]); + } + point_list.push(point); + } + var dygraph_dict = { + dygraph_data: point_list, + dygraph_parameter_dict: { + labels: label_list, + drawPoints : true, + pointSize : 1, + } + }; + return dygraph_dict; + }; + ///////////////////////////////////////////////////////////////// // some methods ///////////////////////////////////////////////////////////////// @@ -162,7 +195,7 @@ graph_data_and_parameter; container = gadget.element.querySelector(".graph-content"); - graph_data_and_parameter = getGraphDataAndParameterFromConfiguration(modification_dict.value); + graph_data_and_parameter = formatGraphDict(modification_dict.value); gadget.property_dict.graph = new Dygraph(container, graph_data_and_parameter.dygraph_data, graph_data_and_parameter.dygraph_parameter_dict); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.xml index 2f4231d9b7..de8506dbd6 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.xml +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_field_graph_dygraph_js.xml @@ -228,7 +228,7 @@ </item> <item> <key> <string>actor</string> </key> - <value> <string>superseb</string> </value> + <value> <unicode>zope</unicode> </value> </item> <item> <key> <string>comment</string> </key> @@ -242,7 +242,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>961.22065.145.58026</string> </value> + <value> <string>1016.32471.45294.12919</string> </value> </item> <item> <key> <string>state</string> </key> @@ -262,8 +262,8 @@ </tuple> <state> <tuple> - <float>1502453287.3</float> - <string>GMT+2</string> + <float>1715371703.99</float> + <string>UTC</string> </tuple> </state> </object> diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.js index 20e0b1c9ba..d34f195bbe 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.js @@ -165,9 +165,7 @@ parent_portal_type: portal_type }; if (view_categorie_list.includes(action_settings.action_type)) { - if (app_view === action_settings.action) { - action_settings.page = "ojs_local_controller"; - } + action_settings.page = "ojs_local_controller"; action_info_dict.view_list[action_settings.action] = action_settings; } else { diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.xml index 646ed3f6e5..bae397d3c4 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.xml +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_common_util_js.xml @@ -244,7 +244,7 @@ </item> <item> <key> <string>actor</string> </key> - <value> <string>zope</string> </value> + <value> <unicode>zope</unicode> </value> </item> <item> <key> <string>comment</string> </key> @@ -258,7 +258,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>987.1958.49484.49100</string> </value> + <value> <string>1015.45953.43925.42052</string> </value> </item> <item> <key> <string>state</string> </key> @@ -278,7 +278,7 @@ </tuple> <state> <tuple> - <float>1601668696.35</float> + <float>1712334861.52</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.js index c94bf4fd44..c2d6918f85 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.js @@ -31,6 +31,7 @@ app_action_list, form_definition, current_version, + configurator, index; current_version = window.location.href.replace(window.location.hash, ""); index = current_version.indexOf(window.location.host) + @@ -40,18 +41,20 @@ "app_view_reference", "parent_portal_type", 'default_view_reference', - 'app_actions']) + 'app_actions', + 'app_configurator']) .push(function (setting_list) { app_view = options.action || setting_list[1]; parent_portal_type = setting_list[2]; default_view = setting_list[3]; app_action_list = setting_list[4]; + configurator = setting_list[5] || 'ojs_configurator'; if (setting_list[0] !== current_version) { //if app version has changed, force storage selection return gadget.redirect({ 'command': 'display', 'options': { - 'page': 'ojs_configurator', + 'page': configurator, 'auto_repair': true } }); @@ -121,6 +124,7 @@ var fragment = document.createElement('div'), gadget = this, view_gadget_url = "gadget_officejs_form_view.html", + //TODO: this should be a list, not only one custom view custom_gadget_url = gadget.state.form_definition.portal_type_dict .custom_view_gadget; while (this.element.firstChild) { diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.xml index 1155a0d840..1dd8943a9c 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.xml +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_controller_page_local_controller_js.xml @@ -222,7 +222,7 @@ </item> <item> <key> <string>actor</string> </key> - <value> <string>zope</string> </value> + <value> <unicode>zope</unicode> </value> </item> <item> <key> <string>comment</string> </key> @@ -236,7 +236,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>1005.39859.38086.29457</string> </value> + <value> <string>1015.46091.52896.5922</string> </value> </item> <item> <key> <string>state</string> </key> @@ -256,7 +256,7 @@ </tuple> <state> <tuple> - <float>1673426666.06</float> + <float>1712343165.23</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.js index 0423e1bc25..e058d9e734 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.js @@ -22,6 +22,7 @@ .getElementById("panel-template-body-desktop") .innerHTML); + //TODO this is the same in action_officejs page, move to common function getElementList(gadget, element_list) { var i = 0, element_info_list = [], diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.xml index b71e77a57f..dede447253 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.xml +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_erp5_ojs_panel_js.xml @@ -219,7 +219,7 @@ </item> <item> <key> <string>actor</string> </key> - <value> <string>zope</string> </value> + <value> <unicode>zope</unicode> </value> </item> <item> <key> <string>comment</string> </key> @@ -233,7 +233,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>1001.57742.17876.27579</string> </value> + <value> <string>1014.1943.59170.64648</string> </value> </item> <item> <key> <string>state</string> </key> @@ -253,7 +253,7 @@ </tuple> <state> <tuple> - <float>1658943108.94</float> + <float>1713536268.81</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.js index 660fc9d402..e6a115766e 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.js @@ -1,11 +1,14 @@ -/*global document, window, rJS, RSVP, Blob, URL, jIO, ensureArray, console */ +/*global document, window, rJS, RSVP, Blob, URL, jIO, ensureArray, console, escape */ /*jslint nomen: true, indent: 2, maxerr: 10, maxlen: 80 */ -(function (document, window, rJS, RSVP, Blob, URL, jIO, ensureArray, console) { +(function (document, window, rJS, RSVP, Blob, URL, jIO, ensureArray, console, escape) { "use strict"; - function renderField(field_id, field_definition, - context_document, data, blob_type, content_editable) { - var key, raw_value, override, final_value, item_list, result = {}; + var MAX_LENGTH = 100; + + function renderField(field_id, field_definition, context_document, + data, blob_type, content_editable, gadget) { + var key, raw_value, override, final_value, item_list, result = {}, i, + extra_query, param_name, doc_key; for (key in field_definition.values) { if (field_definition.values.hasOwnProperty(key)) { // order to get the final value (based on Field.py get_value) @@ -50,11 +53,42 @@ result.type = "EditorField"; } } + if (field_definition.type == "ListBox") { + if (field_definition.values.default_params) { + for (i = 0; i < field_definition.values.default_params.length; i += 1) { + param_name = field_definition.values.default_params[i][0]; + doc_key = field_definition.values.default_params[i][1]; + if (context_document.hasOwnProperty(doc_key) && + context_document[doc_key]) { + extra_query = ` AND ${param_name}:"${context_document[doc_key]}"`; + result.query += escape(extra_query); + } + } + } + } + if (field_definition.type == "GadgetField") { + var context_dict = {}, renderjs_extra, rjs_extra_parsed; + Object.assign(context_dict, gadget.state.doc); + context_dict.jio_key = gadget.state.options.jio_key; + if (field_definition.values.renderjs_extra && + !Array.isArray(field_definition.values.renderjs_extra)) { + rjs_extra_parsed = JSON.parse(field_definition.values.renderjs_extra); + } + renderjs_extra = Object.assign({}, context_dict, rjs_extra_parsed); + field_definition.values.renderjs_extra = JSON.stringify(renderjs_extra); + result.renderjs_extra = JSON.stringify(renderjs_extra); + } + if (field_definition.values.extra) { + eval(field_definition.values.extra); + } + if (field_definition.values.style_columns) { + gadget.state.style_columns = field_definition.values.style_columns; + } return result; } function renderForm(form_definition, context_document, data, blob_type, - content_editable) { + content_editable, gadget) { var i, j, field_list, field_info, my_element, element_id, rendered_field, raw_properties = form_definition.fields_raw_properties, form_json = { @@ -79,7 +113,7 @@ field_info = raw_properties[my_element]; rendered_field = renderField(element_id, field_info, context_document, data, blob_type, - content_editable); + content_editable, gadget); form_json.erp5_document._embedded._view[my_element] = rendered_field; } @@ -129,42 +163,77 @@ .declareAcquiredMethod("updateHeader", "updateHeader") .declareAcquiredMethod("getUrlForList", "getUrlForList") .declareAcquiredMethod("jio_allDocs", "jio_allDocs") + .declareAcquiredMethod("jio_get", "jio_get") .declareAcquiredMethod("jio_getAttachment", "jio_getAttachment") .declareAcquiredMethod("jio_putAttachment", "jio_putAttachment") .declareAcquiredMethod("notifySubmitting", "notifySubmitting") .declareAcquiredMethod("notifySubmitted", 'notifySubmitted') - // XXX Hardcoded for modification_date rendering + // Format date rendering .allowPublicAcquisition("jio_allDocs", function (param_list) { var gadget = this; + if (gadget.state.style_columns && + gadget.state.style_columns[0][0] === 'jio_allDocs') { + return new RSVP.Queue() + .push(function () { + return gadget.declareGadget(gadget.state.style_columns[0][1]); + }) + .push(function (jio_alldocs) { + return jio_alldocs.jio_allDocs(param_list, gadget); + }) + .push(function (result) { + if (result) { + return result; + } else { + return gadget.jio_allDocs(param_list[0]); + } + }); + } return gadget.jio_allDocs(param_list[0]) .push(function (result) { - var i, date, len = result.data.total_rows; + function truncate(str, n) { + return (str.length > n) ? str.slice(0, n - 1) + '...' : str; + } + var i, date, len = result.data.total_rows, date_key_array; for (i = 0; i < len; i += 1) { - if (result.data.rows[i].value.hasOwnProperty("modification_date")) { - date = new Date(result.data.rows[i].value.modification_date); - result.data.rows[i].value.modification_date = { - field_gadget_param: { - allow_empty_time: 0, - ampm_time_style: 0, - css_class: "date_field", - date_only: 0, - description: "The Date", - editable: 0, - hidden: 0, - hidden_day_is_last_day: 0, - "default": date.toUTCString(), - key: "modification_date", - required: 0, - timezone_style: 0, - title: "Modification Date", - type: "DateTimeField" - } - }; - result.data.rows[i].value["listbox_uid:list"] = { - key: "listbox_uid:list", - value: 2713 - }; + // truncate long strings + for (var key in result.data.rows[i].value) { + result.data.rows[i].value[key] = + truncate(result.data.rows[i].value[key], MAX_LENGTH); + } + // render dates with proper format + date_key_array = Object.keys( + result.data.rows[i].value).filter((k) => k.includes("date") || + k.includes("Date")); + date_key_array.forEach((date_key) => { + if (result.data.rows[i].value.hasOwnProperty(date_key)) { + date = new Date(result.data.rows[i].value[date_key]); + result.data.rows[i].value[date_key] = { + field_gadget_param: { + allow_empty_time: 0, + ampm_time_style: 0, + css_class: "date_field", + date_only: 0, + description: "The Date", + editable: 0, + hidden: 0, + hidden_day_is_last_day: 0, + "default": date.toUTCString(), + key: "date", + required: 0, + timezone_style: 0, + title: "Date", + type: "DateTimeField" + } + }; + result.data.rows[i].value["listbox_uid:list"] = { + key: "listbox_uid:list", + value: 2713 + }; + } + }); + if (gadget.state.style_columns) { + eval(gadget.state.style_columns[0][0]); } } return result; @@ -184,6 +253,13 @@ .declareMethod("triggerSubmit", function (argument_list) { var gadget = this, child_gadget, content_dict; + if (gadget.state.form_definition.portal_type_dict.custom_submit) { + return gadget.declareGadget(gadget.state.form_definition + .portal_type_dict.custom_submit) + .push(function (submit_gadget) { + return submit_gadget.handle_submit(argument_list, gadget.state); + }); + } return gadget.getDeclaredGadget('erp5_pt_gadget') .push(function (result) { child_gadget = result; @@ -250,7 +326,7 @@ } form_json = renderForm(gadget.state.form_definition, gadget.state.doc, gadget.state.data, gadget.state.blob_type, - content_editable); + content_editable, gadget); while (gadget.element.firstChild) { gadget.element.removeChild(gadget.element.firstChild); } @@ -267,13 +343,14 @@ .declareMethod("renderSubGadget", function (options, subgadget, form_json) { var gadget = this, erp5_document = form_json.erp5_document, portal_type_dict = form_json.form_definition.portal_type_dict, - page_title; + page_title = '', header_dict; if (options.doc && options.doc.title) { page_title = options.doc.title; } else if (options.doc && options.doc.header_title) { page_title = options.doc.header_title; - } else { - page_title = portal_type_dict.title; + } + if (portal_type_dict.title) { + page_title = portal_type_dict.title + page_title; } return subgadget.render({ jio_key: options.jio_key, @@ -288,7 +365,9 @@ // render the header .push(function () { var url_for_parameter_list = [ - {command: 'change', options: {page: "tab"}}, + {command: 'change', options: {page: "action_officejs", + jio_key: options.jio_key, + portal_type: options.portal_type}}, {command: 'change', options: {page: "action_officejs", jio_key: options.jio_key, portal_type: options.portal_type}}, @@ -316,7 +395,7 @@ return gadget.getUrlForList(url_for_parameter_list); }) .push(function (url_list) { - var header_dict = { "page_title": page_title }; + header_dict = { "page_title": page_title }; if (options.form_type === 'dialog') { //TODO: find correct url header_dict.cancel_url = url_list[6]; @@ -335,7 +414,9 @@ if (portal_type_dict.has_more_views) { header_dict.tab_url = url_list[0]; } - header_dict.save_action = portal_type_dict.editable === 1; + if (portal_type_dict.editable === 1) { + header_dict.save_action = true; + } if (portal_type_dict.has_more_actions || portal_type_dict.has_more_views) { header_dict.actions_url = url_list[1]; @@ -353,8 +434,20 @@ } } } - return gadget.updateHeader(header_dict); + return gadget.declareGadget(portal_type_dict.custom_header); + }) + .push(function (header_gadget) { + return header_gadget.getOptions(portal_type_dict, options, header_dict); + }, function (error) { + if (!portal_type_dict.custom_header) { + return header_dict; + } else { + throw error; + } + }) + .push(function (header_options) { + return gadget.updateHeader(header_options); }); }); -}(document, window, rJS, RSVP, Blob, URL, jIO, ensureArray, console)); +}(document, window, rJS, RSVP, Blob, URL, jIO, ensureArray, console, escape)); diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.xml index 4c3be0ba49..6374926051 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.xml +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_form_view_js.xml @@ -244,7 +244,7 @@ </item> <item> <key> <string>actor</string> </key> - <value> <string>zope</string> </value> + <value> <unicode>zope</unicode> </value> </item> <item> <key> <string>comment</string> </key> @@ -258,7 +258,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>991.25773.59047.44168</string> </value> + <value> <string>1016.46538.50454.1467</string> </value> </item> <item> <key> <string>state</string> </key> @@ -278,7 +278,7 @@ </tuple> <state> <tuple> - <float>1672736671.72</float> + <float>1716222503.85</float> <string>UTC</string> </tuple> </state> diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.js b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.js index 0a503cb2ef..7448d1806b 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.js +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.js @@ -36,6 +36,7 @@ ); } + //TODO this is the same in ojs_panel, move to common function getHTMLElementList(gadget, element_list) { var i = 0, element_info_list = [], diff --git a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.xml b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.xml index bce0c9f164..50f23e7d95 100644 --- a/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.xml +++ b/bt5/erp5_officejs/PathTemplateItem/web_page_module/gadget_officejs_page_action_officejs_js.xml @@ -222,7 +222,7 @@ </item> <item> <key> <string>actor</string> </key> - <value> <string>zope</string> </value> + <value> <unicode>zope</unicode> </value> </item> <item> <key> <string>comment</string> </key> @@ -236,7 +236,7 @@ </item> <item> <key> <string>serial</string> </key> - <value> <string>979.63524.32203.29269</string> </value> + <value> <string>1015.45957.31009.8925</string> </value> </item> <item> <key> <string>state</string> </key> @@ -256,7 +256,7 @@ </tuple> <state> <tuple> - <float>1574423701.42</float> + <float>1713536281.01</float> <string>UTC</string> </tuple> </state> -- 2.30.9