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
"required": field.get_value("required"),
# XXX Message can not be converted to json as is
"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)
elif meta_type == "RadioField":
......@@ -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)
elif meta_type == "ListBox":
# XXX Not implemented
column_list = []
for tmp in field.get_value("columns"):
column_list.append((tmp[0], Base_translateString(tmp[1])))
editable_column_list = []
for tmp in field.get_value('editable_columns'):
editable_column_list.append((tmp[0], Base_translateString(tmp[1])))
sort_column_list_tmp = []
for tmp in field.get_value('sort_columns'):
sort_column_list_tmp.append((tmp[0], Base_translateString(tmp[1])))
search_column_list_tmp = []
for tmp in field.get_value('search_columns'):
search_column_list_tmp.append((tmp[0], Base_translateString(tmp[1])))
sort_column_list = []
search_column_list = []
#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
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)
"""Display list of objects with optional search/sort capabilities on columns from catalog."""
_translate = Base_translateString
column_list = [(name, _translate(title)) for name, title in field.get_value("columns")]
editable_column_list = [(name, _translate(title)) for name, title in field.get_value("editable_columns")]
catalog_column_list = [(name, title)
for name, title in column_list
if sql_catalog.isValidColumn(name)]
# try to get specified searchable columns and fail back to all searchable columns
search_column_list = [(name, _translate(title))
for name, title in field.get_value("search_columns")
if sql_catalog.isValidColumn(name)] or catalog_column_list
# try to get specified sortable columns and fail back to searchable fields
sort_column_list = [(name, _translate(title))
for name, title in field.get_value("sort_columns")
if sql_catalog.isValidColumn(name)] or search_column_list
# requirement: get only sortable/searchable columns which are already displayed in listbox
# 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 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')
default_params = dict(field.get_value('default_params'))
default_params['ignore_unknown_columns'] = True
......@@ -445,19 +427,18 @@ def renderField(traversed_document, field, form_relative_url, value=None, meta_t
result = {
"type": meta_type,
"editable": field.get_value("editable"),
# "column_list": [x[1] for x in columns],
"column_list": column_list,
"search_column_list": search_column_list,
"sort" :field.get_value('sort'),
"sort_column_list": sort_column_list,
"editable_column_list": editable_column_list,
"show_anchor": field.get_value("anchor"),
# "line_list": line_list,
"title": Base_translateString(field.get_value("title")),
"key": key,
"portal_type": portal_types,
"lines": lines,
"default_params": default_params,
"list_method": list_method_name
"list_method": list_method_name,
}
if (list_method_custom is not None):
result["list_method_template"] = list_method_custom
......
......@@ -159,27 +159,35 @@
url_query,
queue;
//only display which is in listbox's column list
if (field_json.sort_column_list.length) {
sort_column_list = field_json.sort_column_list.filter(function (n) {
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;
/** Transform sort arguments (column_name, sort_direction) to jIO's "ascending" and "descending" **/
function jioize_sort(column_sort) {
if (column_sort[1].toLowerCase().startsWith('asc')) {
return [column_sort[0], 'ascending'];
}
if (column_sort[1].toLowerCase().startsWith('desc')) {
return [column_sort[0], 'descending'];
}
return false;
});
return column_sort;
}
if (field_json.search_column_list.length) {
search_column_list = field_json.search_column_list.filter(function (n) {
/** 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] === n[0] && field_json.column_list[i][1] === n[1]) {
if (field_json.column_list[i][0] === item[0] && field_json.column_list[i][1] === item[1]) {
return true;
}
}
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) {
search_column_list = field_json.search_column_list.filter(is_in_column_list);
}
search_column_list.push(["searchable_text", "Searchable Text"]);
......@@ -227,7 +235,9 @@
editable: field_json.editable,
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,
line_icon: field_json.line_icon,
......@@ -310,6 +320,7 @@
(modification_dict.hasOwnProperty('hide_sort')) ||
(modification_dict.hasOwnProperty('hide_class'))) {
// display sorting arrow inside correct columns
sort_list = JSON.parse(gadget.state.sort_list_json);
column_list = JSON.parse(gadget.state.column_list_json);
......
......@@ -236,7 +236,7 @@
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>958.1409.21281.2338</string> </value>
<value> <string>960.53125.56977.8192</string> </value>
</item>
<item>
<key> <string>state</string> </key>
......@@ -254,7 +254,7 @@
</tuple>
<state>
<tuple>
<float>1489590055.78</float>
<float>1500458423.03</float>
<string>UTC</string>
</tuple>
</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