Refactor grid filters to use colander/deform

This commit is contained in:
Lance Edgar 2018-02-12 12:15:07 -06:00
parent f636b98cb3
commit d9ff59afda
4 changed files with 57 additions and 54 deletions

View file

@ -898,11 +898,13 @@ class Grid(object):
data['{}.verb'.format(filtr.key)] = filtr.verb data['{}.verb'.format(filtr.key)] = filtr.verb
data[filtr.key] = filtr.value data[filtr.key] = filtr.value
form = gridfilters.GridFiltersForm(self.request, self.filters, defaults=data) form = gridfilters.GridFiltersForm(self.filters,
request=self.request,
defaults=data)
kwargs['request'] = self.request kwargs['request'] = self.request
kwargs['grid'] = self kwargs['grid'] = self
kwargs['form'] = gridfilters.GridFiltersFormRenderer(form) kwargs['form'] = form
return render(template, kwargs) return render(template, kwargs)
def render_actions(self, row, i): def render_actions(self, row, i):

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2017 Lance Edgar # Copyright © 2010-2018 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -38,10 +38,11 @@ from rattail.core import UNSPECIFIED
from rattail.time import localtime, make_utc from rattail.time import localtime, make_utc
from rattail.util import prettify from rattail.util import prettify
from pyramid_simpleform import Form import colander
from pyramid_simpleform.renderers import FormRenderer
from webhelpers2.html import HTML, tags from webhelpers2.html import HTML, tags
from tailbone import forms
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -736,58 +737,33 @@ class GridFilterSet(OrderedDict):
""" """
class GridFiltersForm(Form): class GridFiltersForm(forms.Form):
""" """
Form for grid filters. Form for grid filters.
""" """
def __init__(self, request, filters, *args, **kwargs): def __init__(self, filters, **kwargs):
super(GridFiltersForm, self).__init__(request, *args, **kwargs)
self.filters = filters self.filters = filters
if 'schema' not in kwargs:
schema = colander.Schema()
for key, filtr in self.filters.items():
node = colander.SchemaNode(colander.String(), name=key)
schema.add(node)
kwargs['schema'] = schema
super(GridFiltersForm, self).__init__(**kwargs)
def iter_filters(self): def iter_filters(self):
return self.filters.itervalues() return self.filters.values()
class GridFiltersFormRenderer(FormRenderer):
"""
Renderer for :class:`GridFiltersForm` instances.
"""
@property
def filters(self):
return self.form.filters
def iter_filters(self):
return self.form.iter_filters()
def tag(self, *args, **kwargs):
"""
Convenience method which passes all args to the
:meth:`webhelpers2:webhelpers2.html.builder.HTMLBuilder.tag()` method.
"""
return HTML.tag(*args, **kwargs)
# TODO: This seems hacky..?
def checkbox(self, name, checked=None, **kwargs):
"""
Custom checkbox implementation.
"""
if name.endswith('-active'):
return tags.checkbox(name, checked=checked, **kwargs)
if checked is None:
checked = False
return super(GridFiltersFormRenderer, self).checkbox(name, checked=checked, **kwargs)
def filter_verb(self, filtr): def filter_verb(self, filtr):
""" """
Render the verb selection dropdown for the given filter. Render the verb selection dropdown for the given filter.
""" """
options = [(v, filtr.verb_labels.get(v, "unknown verb '{0}'".format(v))) options = [tags.Option(filtr.verb_labels.get(v, "unknown verb '{}'".format(v)), v)
for v in filtr.verbs] for v in filtr.verbs]
hide_values = [v for v in filtr.valueless_verbs hide_values = [v for v in filtr.valueless_verbs
if v in filtr.verbs] if v in filtr.verbs]
return self.select('{0}.verb'.format(filtr.key), options, **{ return tags.select('{}.verb'.format(filtr.key), filtr.verb, options, **{
'class_': 'verb', 'class_': 'verb',
'data-hide-value-for': ' '.join(hide_values)}) 'data-hide-value-for': ' '.join(hide_values)})

View file

@ -27,6 +27,11 @@
// do some extra stuff for grids with checkboxes // do some extra stuff for grids with checkboxes
// mark rows selected on page load, as needed
this.element.find('tr:not(.header) td.checkbox :checkbox:checked').each(function() {
$(this).parents('tr:first').addClass('selected');
});
// (un-)check all rows when clicking check-all box in header // (un-)check all rows when clicking check-all box in header
if (this.element.find('tr.header td.checkbox :checkbox').length) { if (this.element.find('tr.header td.checkbox :checkbox').length) {
this.element.on('click', 'tr.header td.checkbox :checkbox', function() { this.element.on('click', 'tr.header td.checkbox :checkbox', function() {
@ -81,7 +86,7 @@
}, },
count_selected: function() { count_selected: function() {
return this.element.find('tr:not(.header) td.checkbox input:checked').length; return this.element.find('tr:not(.header) td.checkbox :checkbox:checked').length;
}, },
// TODO: deprecate / remove this? // TODO: deprecate / remove this?
@ -89,9 +94,21 @@
return this.count_selected(); return this.count_selected();
}, },
selected_rows: function() {
return this.element.find('tr:not(.header) td.checkbox :checkbox:checked').parents('tr:first');
},
all_uuids: function() {
var uuids = [];
this.element.find('tr:not(.header)').each(function() {
uuids.push($(this).data('uuid'));
});
return uuids;
},
selected_uuids: function() { selected_uuids: function() {
var uuids = []; var uuids = [];
this.element.find('tr:not(.header) td.checkbox input:checked').each(function() { this.element.find('tr:not(.header) td.checkbox :checkbox:checked').each(function() {
uuids.push($(this).parents('tr:first').data('uuid')); uuids.push($(this).parents('tr:first').data('uuid'));
}); });
return uuids; return uuids;
@ -273,6 +290,14 @@
} }
} }
return count; return count;
},
all_uuids: function() {
return this.grid.gridcore('all_uuids');
},
selected_uuids: function() {
return this.grid.gridcore('selected_uuids');
} }
}); });

View file

@ -1,15 +1,15 @@
## -*- coding: utf-8 -*- ## -*- coding: utf-8; -*-
<div class="newfilters"> <div class="newfilters">
${form.begin(method='get')} ${h.form(form.action_url, method='get')}
<input type="hidden" name="reset-to-default-filters" value="false" /> ${h.hidden('reset-to-default-filters', value='false')}
<input type="hidden" name="save-current-filters-as-defaults" value="false" /> ${h.hidden('save-current-filters-as-defaults', value='false')}
<fieldset> <fieldset>
<legend>Filters</legend> <legend>Filters</legend>
% for filtr in form.iter_filters(): % for filtr in form.iter_filters():
<div class="filter" id="filter-${filtr.key}" data-key="${filtr.key}"${' style="display: none;"' if not filtr.active else ''|n}> <div class="filter" id="filter-${filtr.key}" data-key="${filtr.key}"${' style="display: none;"' if not filtr.active else ''|n}>
${form.checkbox('{0}-active'.format(filtr.key), class_='active', id='filter-active-{0}'.format(filtr.key), checked=filtr.active)} ${h.checkbox('{}-active'.format(filtr.key), class_='active', id='filter-active-{}'.format(filtr.key), checked=filtr.active)}
<label for="filter-active-${filtr.key}">${filtr.label}</label> <label for="filter-active-${filtr.key}">${filtr.label}</label>
<div class="inputs"> <div class="inputs">
${form.filter_verb(filtr)} ${form.filter_verb(filtr)}
@ -20,19 +20,19 @@
</fieldset> </fieldset>
<div class="buttons"> <div class="buttons">
${form.tag('button', type='submit', id='apply-filters', c="Apply Filters")} <button type="submit" id="apply-filters">Apply Filters</button>
<select id="add-filter"> <select id="add-filter">
<option value="">Add a Filter</option> <option value="">Add a Filter</option>
% for filtr in form.iter_filters(): % for filtr in form.iter_filters():
<option value="${filtr.key}"${' disabled="disabled"' if filtr.active else ''|n}>${filtr.label}</option> <option value="${filtr.key}"${' disabled="disabled"' if filtr.active else ''|n}>${filtr.label}</option>
% endfor % endfor
</select> </select>
${form.tag('button', type='button', id='default-filters', c="Default View")} <button type="button" id="default-filters">Default View</button>
${form.tag('button', type='button', id='clear-filters', c="No Filters")} <button type="button" id="clear-filters">No Filters</button>
% if allow_save_defaults and request.user: % if allow_save_defaults and request.user:
${form.tag('button', type='button', id='save-defaults', c="Save Defaults")} <button type="button" id="save-defaults">Save Defaults</button>
% endif % endif
</div> </div>
${form.end()} ${h.end_form()}
</div><!-- newfilters --> </div><!-- newfilters -->