many improvements to grid, thanks Paolo

This commit is contained in:
mdipierro
2019-02-03 21:24:52 -08:00
parent 7c515f48f6
commit 5e1527a8e2
2 changed files with 39 additions and 29 deletions
+38 -28
View File
@@ -2322,7 +2322,7 @@ class SQLFORM(FORM):
create = wenabled and create create = wenabled and create
editable = wenabled and editable editable = wenabled and editable
deletable = wenabled and deletable deletable = wenabled and deletable
details = details and not groupby details = not groupby and details
rows = None rows = None
# see issue 1980. Basically we can have keywords in get_vars # see issue 1980. Basically we can have keywords in get_vars
@@ -2385,6 +2385,12 @@ class SQLFORM(FORM):
b['args'] = args + b.get('args', []) b['args'] = args + b.get('args', [])
localvars = request.get_vars.copy() localvars = request.get_vars.copy()
localvars.update(b.get('vars', {})) localvars.update(b.get('vars', {}))
# avoid empty keywords in vars
if localvars.get('keywords') == '':
del localvars['keywords']
# avoid propagating order=None in vars
if localvars.get('order') == 'None':
del localvars['order']
b['vars'] = localvars b['vars'] = localvars
b['hash_vars'] = False b['hash_vars'] = False
b['user_signature'] = user_signature b['user_signature'] = user_signature
@@ -2414,7 +2420,7 @@ class SQLFORM(FORM):
def gridbutton(buttonclass='buttonadd', buttontext=T('Add'), def gridbutton(buttonclass='buttonadd', buttontext=T('Add'),
buttonurl=url(args=[]), callback=None, buttonurl=url(args=[]), callback=None,
delete=None, trap=True, noconfirm=None, title=None): delete=None, noconfirm=None, title=None):
if showbuttontext: if showbuttontext:
return A(SPAN(_class=ui.get(buttonclass)), CAT(' '), return A(SPAN(_class=ui.get(buttonclass)), CAT(' '),
SPAN(T(buttontext), _title=title or T(buttontext), SPAN(T(buttontext), _title=title or T(buttontext),
@@ -2645,20 +2651,18 @@ class SQLFORM(FORM):
orderby = fix_orderby(orderby) orderby = fix_orderby(orderby)
# expcolumns start with the visible columns, which
# includes visible virtual fields
expcolumns = [str(f) for f in columns] expcolumns = [str(f) for f in columns]
selectable_columns = [str(f) for f in columns if not isinstance(f, Field.Virtual)] selectable_columns = [str(f) for f in columns if not isinstance(f, Field.Virtual)]
if export_type.endswith('with_hidden_cols'): if export_type.endswith('with_hidden_cols'):
# expcolumns = [] start with the visible columns, which
# includes visible virtual fields
selectable_columns = []
# like expcolumns but excluding virtual
for table in tables: for table in tables:
for field in table: for field in table:
if field.readable and field.tablename in tablenames: if field.readable and field.tablename in tablenames:
if not str(field) in expcolumns: if not str(field) in expcolumns:
expcolumns.append(str(field)) expcolumns.append(str(field))
if not(isinstance(field, Field.Virtual)): if not(isinstance(field, Field.Virtual)):
selectable_columns.append(str(field)) selectable_columns.append(str(field))
# look for virtual fields not displayed (and virtual method # look for virtual fields not displayed (and virtual method
# fields to be added here?) # fields to be added here?)
for (field_name, field) in iteritems(table): for (field_name, field) in iteritems(table):
@@ -2723,7 +2727,7 @@ class SQLFORM(FORM):
if searchable: if searchable:
sfields = reduce(lambda a, b: a + b, sfields = reduce(lambda a, b: a + b,
[[f for f in t if f.readable] for t in tables]) [[f for f in t if f.readable and f.searchable] for t in tables])
if isinstance(search_widget, dict): if isinstance(search_widget, dict):
search_widget = search_widget[tablename] search_widget = search_widget[tablename]
if search_widget == 'default': if search_widget == 'default':
@@ -2732,7 +2736,7 @@ class SQLFORM(FORM):
spanel_id = '%s_query_fields' % prefix spanel_id = '%s_query_fields' % prefix
sfields_id = '%s_query_panel' % prefix sfields_id = '%s_query_panel' % prefix
skeywords_id = '%s_keywords' % prefix skeywords_id = '%s_keywords' % prefix
# hidden fields to presever keywords in url after the submit # hidden fields to preserve keywords in url after the submit
hidden_fields = [INPUT(_type='hidden', _value=v, _name=k) for k, v in request.get_vars.items() if k not in ['keywords', 'page']] hidden_fields = [INPUT(_type='hidden', _value=v, _name=k) for k, v in request.get_vars.items() if k not in ['keywords', 'page']]
search_widget = lambda sfield, url: CAT(FORM( search_widget = lambda sfield, url: CAT(FORM(
INPUT(_name='keywords', _value=keywords, INPUT(_name='keywords', _value=keywords,
@@ -2748,14 +2752,17 @@ class SQLFORM(FORM):
form = search_widget and search_widget(sfields, url()) or '' form = search_widget and search_widget(sfields, url()) or ''
console.append(add) console.append(add)
console.append(form) console.append(form)
try: if keywords:
if callable(searchable): try:
subquery = searchable(sfields, keywords) if callable(searchable):
else: subquery = searchable(sfields, keywords)
subquery = SQLFORM.build_query(sfields, keywords) else:
except RuntimeError: subquery = SQLFORM.build_query(sfields, keywords)
except RuntimeError:
subquery = None
error = T('Invalid query')
else:
subquery = None subquery = None
error = T('Invalid query')
else: else:
subquery = None subquery = None
@@ -2768,12 +2775,15 @@ class SQLFORM(FORM):
error = T('Unsupported query') error = T('Unsupported query')
order = request.vars.order or '' order = request.vars.order or ''
asc_icon, desc_icon = sorter_icons
if sortable: if sortable:
if order and not order == 'None': if order and not order == 'None':
otablename, ofieldname = order.split('~')[-1].split('.', 1) otablename, ofieldname = order.split('~')[-1].split('.', 1)
sort_field = db[otablename][ofieldname] sort_field = db[otablename][ofieldname]
# invert order direction on date/time fields
exception = sort_field.type in ('date', 'datetime', 'time') exception = sort_field.type in ('date', 'datetime', 'time')
if exception: if exception:
desc_icon, asc_icon = sorter_icons
orderby = (order[:1] == '~' and sort_field) or ~sort_field orderby = (order[:1] == '~' and sort_field) or ~sort_field
else: else:
orderby = (order[:1] == '~' and ~sort_field) or sort_field orderby = (order[:1] == '~' and ~sort_field) or sort_field
@@ -2782,30 +2792,30 @@ class SQLFORM(FORM):
if selectable: if selectable:
headcols.append(TH(_class=ui.get('default'))) headcols.append(TH(_class=ui.get('default')))
ordermatch, marker = orderby, '' ordermatch = orderby; marker = ''
if orderby: if orderby:
# if orderby is a single column, remember to put the marker # if orderby is a single column, remember to put the marker
if isinstance(orderby, Expression): if isinstance(orderby, Expression):
if orderby.first and not orderby.second: if orderby.first and not orderby.second:
ordermatch, marker = orderby.first, '~' ordermatch = orderby.first; marker = '~'
ordermatch = marker + str(ordermatch) ordermatch = marker + str(ordermatch)
for field in columns: for field in columns:
if not field.readable: if not field.readable:
continue continue
key = str(field) key = str(field)
header = headers.get(str(field), field.label or key) header = headers.get(key, field.label or key)
if sortable and not isinstance(field, Field.Virtual): if sortable and not isinstance(field, Field.Virtual):
marker = '' marker = ''
if order: if order:
if key == order: if key == order:
key, marker = '~' + order, sorter_icons[0] key = '~' + order; marker = asc_icon
elif key == order[1:]: elif key == order[1:]:
marker = sorter_icons[1] key = 'None'; marker = desc_icon
else: else:
if key == ordermatch: if key == ordermatch:
key, marker = '~' + ordermatch, sorter_icons[0] key = '~' + ordermatch; marker = asc_icon
elif key == ordermatch[1:]: elif key == ordermatch[1:]:
marker = sorter_icons[1] marker = desc_icon
header = A(header, marker, _href=url(vars=dict( header = A(header, marker, _href=url(vars=dict(
keywords=keywords, keywords=keywords,
order=key)), cid=request.cid) order=key)), cid=request.cid)
@@ -3114,7 +3124,7 @@ class SQLFORM(FORM):
link = url2(vars=dict( link = url2(vars=dict(
order=request.vars.order or '', order=request.vars.order or '',
_export_type=k, _export_type=k,
keywords=keywords or '')) keywords=keywords))
export_links.append(A(T(label), _href=link, _title=title, _class='btn btn-default btn-secondary')) export_links.append(A(T(label), _href=link, _title=title, _class='btn btn-default btn-secondary'))
export_menu = \ export_menu = \
DIV(T('Export:'), _class="w2p_export_menu", *export_links) DIV(T('Export:'), _class="w2p_export_menu", *export_links)
@@ -3697,7 +3707,7 @@ class ExporterTSV(ExportClass):
def __init__(self, rows): def __init__(self, rows):
ExportClass.__init__(self, rows) ExportClass.__init__(self, rows)
def export(self): # export TSV with rows.represent def export(self): # export TSV with field.represent
if self.rows: if self.rows:
s = StringIO() s = StringIO()
self.rows.export_to_csv_file(s, represent=True,delimiter='\t',newline='\n') self.rows.export_to_csv_file(s, represent=True,delimiter='\t',newline='\n')
@@ -3714,7 +3724,7 @@ class ExporterTSV_hidden(ExportClass):
def __init__(self, rows): def __init__(self, rows):
ExportClass.__init__(self, rows) ExportClass.__init__(self, rows)
def export(self): # export TSV with rows.represent def export(self):
if self.rows: if self.rows:
s = StringIO() s = StringIO()
self.rows.export_to_csv_file(s,delimiter='\t',newline='\n') self.rows.export_to_csv_file(s,delimiter='\t',newline='\n')
@@ -3732,7 +3742,7 @@ class ExporterCSV(ExportClass):
def __init__(self, rows): def __init__(self, rows):
ExportClass.__init__(self, rows) ExportClass.__init__(self, rows)
def export(self): # export CSV with rows.represent def export(self): # export CSV with field.represent
if self.rows: if self.rows:
s = StringIO() s = StringIO()
self.rows.export_to_csv_file(s, represent=True) self.rows.export_to_csv_file(s, represent=True)