Commit 94ac9311 authored by Tomáš Peterka's avatar Tomáš Peterka

[renderjs] ListBox field takes default sort into account

- no custom listbox added for testing because FooModule listbox's properties are set dynamically
parent f986a1ad
...@@ -113,7 +113,7 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t ...@@ -113,7 +113,7 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
"required": field.get_value("required"), "required": field.get_value("required"),
# XXX Message can not be converted to json as is # XXX Message can not be converted to json as is
"items": field.get_value("items"), "items": field.get_value("items"),
"first_item": field.get_value("first_item") "first_item": field.get_value("first_item"),
} }
result["default"] = getFieldDefault(traversed_document, field, result["key"], value) result["default"] = getFieldDefault(traversed_document, field, result["key"], value)
elif meta_type == "RadioField": elif meta_type == "RadioField":
...@@ -342,48 +342,30 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t ...@@ -342,48 +342,30 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
} }
result["default"] = getFieldDefault(traversed_document, field, result["key"], value) result["default"] = getFieldDefault(traversed_document, field, result["key"], value)
elif meta_type == "ListBox": elif meta_type == "ListBox":
# XXX Not implemented """Display list of objects with optional search/sort capabilities on columns from catalog."""
column_list = [] _translate = Base_translateString
for tmp in field.get_value("columns"):
column_list.append((tmp[0], Base_translateString(tmp[1]))) column_list = [(name, _translate(title)) for name, title in field.get_value("columns")]
editable_column_list = [] editable_column_list = [(name, _translate(title)) for name, title in field.get_value("editable_columns")]
for tmp in field.get_value('editable_columns'): catalog_column_list = [(name, title)
editable_column_list.append((tmp[0], Base_translateString(tmp[1]))) for name, title in column_list
if sql_catalog.isValidColumn(name)]
sort_column_list_tmp = []
# try to get specified searchable columns and fail back to all searchable columns
for tmp in field.get_value('sort_columns'): search_column_list = [(name, _translate(title))
sort_column_list_tmp.append((tmp[0], Base_translateString(tmp[1]))) for name, title in field.get_value("search_columns")
if sql_catalog.isValidColumn(name)] or catalog_column_list
search_column_list_tmp = []
for tmp in field.get_value('search_columns'): # try to get specified sortable columns and fail back to searchable fields
search_column_list_tmp.append((tmp[0], Base_translateString(tmp[1]))) sort_column_list = [(name, _translate(title))
for name, title in field.get_value("sort_columns")
sort_column_list = [] if sql_catalog.isValidColumn(name)] or search_column_list
search_column_list = []
# requirement: get only sortable/searchable columns which are already displayed in listbox
#only get sortable&searchable column which is already displayed in listbox # see https://lab.nexedi.com/nexedi/erp5/blob/HEAD/product/ERP5Form/ListBox.py#L1004
#see https://lab.nexedi.com/nexedi/erp5/blob/HEAD/product/ERP5Form/ListBox.py#L1004 # implemented in javascript in the end
# see https://lab.nexedi.com/nexedi/erp5/blob/master/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_listbox_js.js#L163
if search_column_list_tmp:
search_column_list = search_column_list_tmp
else:
for grain in column_list:
if sql_catalog.isValidColumn(grain[0]):
search_column_list.append(grain)
if sort_column_list_tmp:
sort_column_list = sort_column_list_tmp
else:
sort_column_list = search_column_list
# XXX
# list_method = getattr(traversed_document, traversed_document.Listbox_getListMethodName(field))
# portal_types = [x[1] for x in field.get_value('portal_types')]
portal_types = field.get_value('portal_types') portal_types = field.get_value('portal_types')
default_params = dict(field.get_value('default_params')) default_params = dict(field.get_value('default_params'))
default_params['ignore_unknown_columns'] = True default_params['ignore_unknown_columns'] = True
...@@ -445,19 +427,18 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t ...@@ -445,19 +427,18 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
result = { result = {
"type": meta_type, "type": meta_type,
"editable": field.get_value("editable"), "editable": field.get_value("editable"),
# "column_list": [x[1] for x in columns],
"column_list": column_list, "column_list": column_list,
"search_column_list": search_column_list, "search_column_list": search_column_list,
"sort" :field.get_value('sort'),
"sort_column_list": sort_column_list, "sort_column_list": sort_column_list,
"editable_column_list": editable_column_list, "editable_column_list": editable_column_list,
"show_anchor": field.get_value("anchor"), "show_anchor": field.get_value("anchor"),
# "line_list": line_list,
"title": Base_translateString(field.get_value("title")), "title": Base_translateString(field.get_value("title")),
"key": key, "key": key,
"portal_type": portal_types, "portal_type": portal_types,
"lines": lines, "lines": lines,
"default_params": default_params, "default_params": default_params,
"list_method": list_method_name "list_method": list_method_name,
} }
if (list_method_custom is not None): if (list_method_custom is not None):
result["list_method_template"] = list_method_custom result["list_method_template"] = list_method_custom
......
...@@ -159,27 +159,35 @@ ...@@ -159,27 +159,35 @@
url_query, url_query,
queue; queue;
//only display which is in listbox's column list /** Transform sort arguments (column_name, sort_direction) to jIO's "ascending" and "descending" **/
if (field_json.sort_column_list.length) { function jioize_sort(column_sort) {
sort_column_list = field_json.sort_column_list.filter(function (n) { if (column_sort[1].toLowerCase().startsWith('asc')) {
for (i = 0; i < field_json.column_list.length; i += 1) { return [column_sort[0], 'ascending'];
if (field_json.column_list[i][0] === n[0] && field_json.column_list[i][1] === n[1]) { }
return true; if (column_sort[1].toLowerCase().startsWith('desc')) {
} return [column_sort[0], 'descending'];
}
return column_sort;
}
/** Check whether item is in outer-scoped field_json.column_list */
function is_in_column_list(item) {
for (i = 0; i < field_json.column_list.length; i += 1) {
if (field_json.column_list[i][0] === item[0] && field_json.column_list[i][1] === item[1]) {
return true;
} }
return false; }
}); return false;
} }
// use only visible columns for sort
if (field_json.sort_column_list.length) {
sort_column_list = field_json.sort_column_list.filter(is_in_column_list);
}
// use only visible columns for search
if (field_json.search_column_list.length) { if (field_json.search_column_list.length) {
search_column_list = field_json.search_column_list.filter(function (n) { search_column_list = field_json.search_column_list.filter(is_in_column_list);
for (i = 0; i < field_json.column_list.length; i += 1) {
if (field_json.column_list[i][0] === n[0] && field_json.column_list[i][1] === n[1]) {
return true;
}
}
return false;
});
} }
search_column_list.push(["searchable_text", "Searchable Text"]); search_column_list.push(["searchable_text", "Searchable Text"]);
...@@ -227,7 +235,9 @@ ...@@ -227,7 +235,9 @@
editable: field_json.editable, editable: field_json.editable,
begin_from: parseInt(result_list[0] || '0', 10) || 0, begin_from: parseInt(result_list[0] || '0', 10) || 0,
sort_list_json: JSON.stringify(result_list[1] || []),
// sorting is either specified in URL per listbox or we take default sorting from JSON's 'sort' attribute
sort_list_json: JSON.stringify(result_list[1] || field_json.sort.map(jioize_sort)),
show_anchor: field_json.show_anchor, show_anchor: field_json.show_anchor,
line_icon: field_json.line_icon, line_icon: field_json.line_icon,
...@@ -310,6 +320,7 @@ ...@@ -310,6 +320,7 @@
(modification_dict.hasOwnProperty('hide_sort')) || (modification_dict.hasOwnProperty('hide_sort')) ||
(modification_dict.hasOwnProperty('hide_class'))) { (modification_dict.hasOwnProperty('hide_class'))) {
// display sorting arrow inside correct columns
sort_list = JSON.parse(gadget.state.sort_list_json); sort_list = JSON.parse(gadget.state.sort_list_json);
column_list = JSON.parse(gadget.state.column_list_json); column_list = JSON.parse(gadget.state.column_list_json);
......
...@@ -236,7 +236,7 @@ ...@@ -236,7 +236,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>958.1409.21281.2338</string> </value> <value> <string>960.53125.56977.8192</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -254,7 +254,7 @@ ...@@ -254,7 +254,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1489590055.78</float> <float>1500458423.03</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testSortDefault</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test RenderJS UI</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test RenderJS UI</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />
<!-- make the listbox to sort by ID DESC which is not natural thus obvious -->
<tr>
<td>open</td>
<td>${base_url}/bar_module/ListBoxZuite_reset?field_sort=id+%7C+DESC</td> <!-- ?field_sort="id | DESC" -->
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>Reset Successfully.</td>
<td></td>
</tr>
<!-- Create Foo objects with IDs 0-9 -->
<tr>
<td>open</td>
<td>${base_url}/foo_module/FooModule_createObjects?start=1&amp;num=5</td>
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>Created Successfully.</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/wait_for_activities" />
<tr>
<td>open</td>
<td>${base_url}/web_site_module/renderjs_runner/#/foo_module</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//th[@data-i18n='ID']</td>
<td></td>
</tr>
<tr>
<td>verifyElementPresent</td>
<td>//th[@data-i18n='ID' and @class='ui-icon ui-icon-arrow-down']</td>
<td></td>
</tr>
<!-- Test whether another sorting condition does keep default sort -->
<tr>
<td>waitForElementPresent</td>
<td>//button[@data-i18n='Sort']</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//button[@data-i18n='Sort']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//div[@class='sort_item_container ui-controlgroup ui-corner_all']/div[1]</td>
<td></td>
</tr>
<!-- make sure the default sort if visible in "sort editor" -->
<tr>
<td>verifyValue</td>
<td>//div[@class='sort_item_container ui-controlgroup ui-corner_all']/div[1]//select[1]</td>
<td>id</td>
</tr>
<tr>
<td>verifyValue</td>
<td>//div[@class='sort_item_container ui-controlgroup ui-corner_all']/div[1]//select[2]</td>
<td>descending</td>
</tr>
<!-- reset sort and our set up value is the only one to sort by -->
<tr>
<td>select</td>
<td>//div[@class='sort_item_container ui-controlgroup ui-corner_all']/div[1]//select[1]</td>
<td>index=1</td> <!-- select title -->
</tr>
<tr>
<td>select</td>
<td>//div[@class='sort_item_container ui-controlgroup ui-corner_all']/div[1]//select[2]</td>
<td>index=1</td> <!-- select descending -->
</tr>
<tr>
<td>click</td>
<td>//button[@class="submit responsive ui-last-child ui-btn ui-btn-icon-left ui-icon-check"]</td>
<td></td>
</tr>
<!-- Wait for the Filters to be applied (maybe not the best way to do that ... but it works) -->
<tr>
<td>waitForElementPresent</td>
<td>//button[@data-i18n="Filter" and @class="responsive ui-btn ui-icon-spinner ui-btn-icon-left ui-first-child ui-last-child ui-disabled ui-icon-spin"]</td>
<td></td>
</tr>
<tr>
<td>waitForElementNotPresent</td>
<td>//button[@data-i18n="Filter" and @class="responsive ui-btn ui-icon-spinner ui-btn-icon-left ui-first-child ui-last-child ui-disabled ui-icon-spin"]</td>
<td></td>
</tr>
<!-- Check that default sort arrow disappeared -->
<tr>
<td>verifyElementNotPresent</td>
<td>//th[@data-i18n='ID' and @class='ui-icon ui-icon-arrow-up']</td>
<td></td>
</tr>
<tr>
<td>verifyElementNotPresent</td>
<td>//th[@data-i18n='ID' and @class='ui-icon ui-icon-arrow-down']</td>
<td></td>
</tr>
<tr>
<td>verifyElementPresent</td>
<td>//th[@data-i18n='Title' and @class='ui-icon ui-icon-arrow-down']</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>
\ 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