Commit de972081 authored by Julien Muchembled's avatar Julien Muchembled

listbox: sorting by CAST type (float)

Only 'float' supported for the moment. This should cover the case of integers.

Example of 'Sortable Columns' value in a ListBox:

  id | float
  title |

Since there's a fallback to 'Searchable Columns' when 'Sortable Columns' is
empty, the cast type can also be specified there, in order to avoid duplication.
parent d22b6502
...@@ -237,13 +237,9 @@ ...@@ -237,13 +237,9 @@
<string>Default</string> <string>Default</string>
<string>default</string> <string>default</string>
</tuple> </tuple>
<tuple>
<string>Alphabetical</string>
<string>CHAR</string>
</tuple>
<tuple> <tuple>
<string>Numerical</string> <string>Numerical</string>
<string>SIGNED</string> <string>float</string>
</tuple> </tuple>
</list> </list>
</value> </value>
...@@ -276,19 +272,13 @@ ...@@ -276,19 +272,13 @@
</record> </record>
<record id="2" aka="AAAAAAAAAAI="> <record id="2" aka="AAAAAAAAAAI=">
<pickle> <pickle>
<tuple> <global name="TALESMethod" module="Products.Formulator.TALESField"/>
<tuple>
<string>Products.Formulator.TALESField</string>
<string>TALESMethod</string>
</tuple>
<none/>
</tuple>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>python: [(here.Base_translateString(\'Default Sort\'), \'\'),(here.Base_translateString(\'Alphabetical\'), \'CHAR\'), (here.Base_translateString(\'Numerical\'), \'SIGNED\')]</string> </value> <value> <string>python: [(here.Base_translateString(k), v) for k,v in field.get_orig_value("sort_columns")]</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -956,23 +956,37 @@ class ListBoxRenderer: ...@@ -956,23 +956,37 @@ class ListBoxRenderer:
getPageNavigationMode = getPageNavigationTemplate getPageNavigationMode = getPageNavigationTemplate
@lazyMethod @lazyMethod
def getSearchColumnIdSet(self): def getSearchColumnDict(self):
"""Return the set of the ids of the search columns. Fall back to the catalog schema, if not defined. """Return search columns
The dict values are useful when getSortColumnDict falls back on this value.
Fall back to the catalog schema, if not defined.
""" """
search_columns = self.field.get_value('search_columns') search_columns = self.field.get_value('search_columns')
if search_columns: if search_columns:
return {c[0] for c in search_columns} return dict(search_columns)
isValidColumn = self.getCatalogTool().getSQLCatalog().isValidColumn isValidColumn = self.getCatalogTool().getSQLCatalog().isValidColumn
return {id for id, title in self.getAllColumnList() if isValidColumn(id)} return {id: '' for id, _ in self.getAllColumnList() if isValidColumn(id)}
@lazyMethod @lazyMethod
def getSortColumnIdSet(self): def getSortColumnDict(self):
"""Return the set of the ids of the sort columns. Fall back to search column ids, if not defined. """Return sort columns with their cast types as dict values
Cast types are prefixed by ':' for convenience.
Fall back to search columns, if not defined.
""" """
sort_columns = self.field.get_value('sort_columns') sort_dict = {}
if sort_columns: for c, cast in (self.field.get_value('sort_columns') or
return {c[0] for c in sort_columns} self.getSearchColumnDict().iteritems()):
return self.getSearchColumnIdSet() if cast == 'float':
sort_dict[c] = ':' + cast
else:
if cast:
warn('Each line of the "Sortable Columns" field property must be'
' in the form "<column_id> | <cast_type>", where <cast_type>'
" is one of ('', 'float').", DeprecationWarning)
sort_dict[c] = ''
return sort_dict
@lazyMethod @lazyMethod
def getEditableColumnIdSet(self): def getEditableColumnIdSet(self):
...@@ -1034,8 +1048,8 @@ class ListBoxRenderer: ...@@ -1034,8 +1048,8 @@ class ListBoxRenderer:
selection.edit(default_sort_on = self.getDefaultSortColumnList()) selection.edit(default_sort_on = self.getDefaultSortColumnList())
# Filter out non-sortable items. # Filter out non-sortable items.
sort_column_id_set = self.getSortColumnIdSet() sort_column_dict = self.getSortColumnDict()
sort_list = [c for c in selection.sort_on if c[0] in sort_column_id_set] sort_list = [c for c in selection.sort_on if c[0] in sort_column_dict]
if len(selection.sort_on) != len(sort_list): if len(selection.sort_on) != len(sort_list):
selection.sort_on = sort_list selection.sort_on = sort_list
...@@ -1557,17 +1571,18 @@ class ListBoxRenderer: ...@@ -1557,17 +1571,18 @@ class ListBoxRenderer:
set to None, otherwise to a string. set to None, otherwise to a string.
""" """
sort_list = self.getSelectionTool().getSelectionSortOrder(self.getSelectionName()) sort_list = self.getSelectionTool().getSelectionSortOrder(self.getSelectionName())
sort_dict = {} # sort_item can be couple or a triplet
for sort_item in sort_list: sort_dict = {sort_item[0]: sort_item[1] for sort_item in sort_list}
sort_dict[sort_item[0]] = sort_item[1] # sort_item can be couple or a triplet sort_column_dict = self.getSortColumnDict()
sort_column_id_set = self.getSortColumnIdSet()
value_list = [] value_list = []
for c in self.getSelectedColumnList(): for c in self.getSelectedColumnList():
if c[0] in sort_column_id_set: column_id = c[0]
value_list.append((c[0], c[1], sort_dict.get(c[0]))) as_type = sort_column_dict.get(column_id)
else: if as_type is None:
value_list.append((None, c[1], None)) value_list.append((None, c[1], None))
else:
value_list.append((column_id + as_type, c[1], sort_dict.get(column_id)))
return value_list return value_list
...@@ -1576,7 +1591,7 @@ class ListBoxRenderer: ...@@ -1576,7 +1591,7 @@ class ListBoxRenderer:
If a column is not searchable, the alias is set to None, otherwise to a string. If a search field is not present, If a column is not searchable, the alias is set to None, otherwise to a string. If a search field is not present,
it is set to None. it is set to None.
""" """
search_column_id_set = self.getSearchColumnIdSet() search_column_id_set = self.getSearchColumnDict()
if param_dict is None: if param_dict is None:
param_dict = self.getParamDict() param_dict = self.getParamDict()
...@@ -2575,8 +2590,8 @@ class ListBoxHTMLRenderer(ListBoxRenderer): ...@@ -2575,8 +2590,8 @@ class ListBoxHTMLRenderer(ListBoxRenderer):
for original_listbox_argument in listbox_arguments_list: for original_listbox_argument in listbox_arguments_list:
listbox_argument = original_listbox_argument.replace('%s_' %field_id, '', 1) listbox_argument = original_listbox_argument.replace('%s_' %field_id, '', 1)
listbox_argument_value = form_dict.get(original_listbox_argument, None) listbox_argument_value = form_dict.get(original_listbox_argument, None)
if listbox_argument in list(self.getSearchColumnIdSet()) and \ if listbox_argument in self.getSearchColumnDict() and \
listbox_argument_value not in (None,): listbox_argument_value is not None:
update_selection = True update_selection = True
listbox_kw[listbox_argument] = listbox_argument_value listbox_kw[listbox_argument] = listbox_argument_value
if update_selection: if update_selection:
......
...@@ -553,17 +553,26 @@ class SelectionTool( BaseTool, SimpleItem ): ...@@ -553,17 +553,26 @@ class SelectionTool( BaseTool, SimpleItem ):
listbox_id, sort_on = form["setSelectionQuickSortOrder"].split(".", 1) listbox_id, sort_on = form["setSelectionQuickSortOrder"].split(".", 1)
# Sort order can be specified in sort_on. # Sort order can be specified in sort_on.
forced_sort_order = None if sort_on.endswith(':asc'):
if sort_on is not None: order = 'ascending'
if sort_on.endswith(':asc'): sort_on = sort_on[:-4]
forced_sort_order = 'ascending' elif sort_on.endswith(':desc'):
sort_on = sort_on[:-4] order = 'descending'
elif sort_on.endswith(':desc'): sort_on = sort_on[:-5]
forced_sort_order = 'descending' elif sort_on.endswith(':none'):
sort_on = sort_on[:-5] order = 'none'
elif sort_on.endswith(':none'): sort_on = sort_on[:-5]
forced_sort_order = 'none' else:
sort_on = sort_on[:-5] order = None
# ... as well as cast type
i = sort_on.find(':')
if i < 0:
as_type = None
else:
as_type = sort_on[i+1:]
if as_type != 'float':
return
sort_on = sort_on[:i]
if REQUEST is not None: if REQUEST is not None:
if listbox_id is not None: if listbox_id is not None:
...@@ -574,33 +583,23 @@ class SelectionTool( BaseTool, SimpleItem ): ...@@ -574,33 +583,23 @@ class SelectionTool( BaseTool, SimpleItem ):
selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) selection = self.getSelectionFor(selection_name, REQUEST=REQUEST)
if selection is not None: if selection is not None:
if forced_sort_order is not None: if order is not None:
if forced_sort_order == 'none':
temporary_new_sort_on = []
else:
temporary_new_sort_on = [(sort_on, forced_sort_order)]
# Allow user to sort by multiple columns # Allow user to sort by multiple columns
new_sort_on = [s new_sort_on = [s for s in selection.sort_on if s[0] != sort_on]
for s in self.getSelectionSortOrder(selection_name) if order != 'none':
if s[0]!=sort_on] new_sort_on.append((sort_on, order, as_type) if as_type else
new_sort_on.extend(temporary_new_sort_on) (sort_on, order))
else: else:
current_sort_on = self.getSelectionSortOrder(selection_name)
# We must first switch from asc to desc and vice-versa if sort_order exists # We must first switch from asc to desc and vice-versa if sort_order exists
# in selection # in selection
n = 0 order = 'ascending'
for current in current_sort_on: for current in selection.sort_on:
if current[0] == sort_on: if current[0] == sort_on:
n = 1 if current[1] == order:
if current[1] == 'ascending': order = 'descending'
new_sort_on = [(sort_on, 'descending')] break
break new_sort_on = ((sort_on, order, as_type) if as_type else
else: (sort_on, order),)
new_sort_on = [(sort_on,'ascending')]
break
# And if no one exists, we just set sort
if n == 0:
new_sort_on = [(sort_on, 'ascending')]
selection.edit(sort_on=new_sort_on) selection.edit(sort_on=new_sort_on)
if REQUEST is not None: if REQUEST is not None:
......
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