Refactor grid filters to use colander/deform
This commit is contained in:
		
							parent
							
								
									f636b98cb3
								
							
						
					
					
						commit
						d9ff59afda
					
				
					 4 changed files with 57 additions and 54 deletions
				
			
		|  | @ -898,11 +898,13 @@ class Grid(object): | |||
|             data['{}.verb'.format(filtr.key)] = filtr.verb | ||||
|             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['grid'] = self | ||||
|         kwargs['form'] = gridfilters.GridFiltersFormRenderer(form) | ||||
|         kwargs['form'] = form | ||||
|         return render(template, kwargs) | ||||
| 
 | ||||
|     def render_actions(self, row, i): | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2017 Lance Edgar | ||||
| #  Copyright © 2010-2018 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
|  | @ -38,10 +38,11 @@ from rattail.core import UNSPECIFIED | |||
| from rattail.time import localtime, make_utc | ||||
| from rattail.util import prettify | ||||
| 
 | ||||
| from pyramid_simpleform import Form | ||||
| from pyramid_simpleform.renderers import FormRenderer | ||||
| import colander | ||||
| from webhelpers2.html import HTML, tags | ||||
| 
 | ||||
| from tailbone import forms | ||||
| 
 | ||||
| 
 | ||||
| log = logging.getLogger(__name__) | ||||
| 
 | ||||
|  | @ -736,58 +737,33 @@ class GridFilterSet(OrderedDict): | |||
|     """ | ||||
| 
 | ||||
| 
 | ||||
| class GridFiltersForm(Form): | ||||
| class GridFiltersForm(forms.Form): | ||||
|     """ | ||||
|     Form for grid filters. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, request, filters, *args, **kwargs): | ||||
|         super(GridFiltersForm, self).__init__(request, *args, **kwargs) | ||||
|     def __init__(self, filters, **kwargs): | ||||
|         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): | ||||
|         return self.filters.itervalues() | ||||
| 
 | ||||
| 
 | ||||
| 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) | ||||
|         return self.filters.values() | ||||
| 
 | ||||
|     def filter_verb(self, filtr): | ||||
|         """ | ||||
|         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] | ||||
|         hide_values = [v for v in filtr.valueless_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', | ||||
|             'data-hide-value-for': ' '.join(hide_values)}) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										29
									
								
								tailbone/static/js/jquery.ui.tailbone.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								tailbone/static/js/jquery.ui.tailbone.js
									
										
									
									
										vendored
									
									
								
							|  | @ -27,6 +27,11 @@ | |||
| 
 | ||||
|             // 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
 | ||||
|             if (this.element.find('tr.header td.checkbox :checkbox').length) { | ||||
|                 this.element.on('click', 'tr.header td.checkbox :checkbox', function() { | ||||
|  | @ -81,7 +86,7 @@ | |||
|         }, | ||||
| 
 | ||||
|         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?
 | ||||
|  | @ -89,9 +94,21 @@ | |||
|             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() { | ||||
|             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')); | ||||
|             }); | ||||
|             return uuids; | ||||
|  | @ -273,6 +290,14 @@ | |||
|                 } | ||||
|             } | ||||
|             return count; | ||||
|         }, | ||||
| 
 | ||||
|         all_uuids: function() { | ||||
|             return this.grid.gridcore('all_uuids'); | ||||
|         }, | ||||
| 
 | ||||
|         selected_uuids: function() { | ||||
|             return this.grid.gridcore('selected_uuids'); | ||||
|         } | ||||
| 
 | ||||
|     }); | ||||
|  |  | |||
|  | @ -1,15 +1,15 @@ | |||
| ## -*- coding: utf-8 -*- | ||||
| ## -*- coding: utf-8; -*- | ||||
| <div class="newfilters"> | ||||
| 
 | ||||
|   ${form.begin(method='get')} | ||||
|     <input type="hidden" name="reset-to-default-filters" value="false" /> | ||||
|     <input type="hidden" name="save-current-filters-as-defaults" value="false" /> | ||||
|   ${h.form(form.action_url, method='get')} | ||||
|     ${h.hidden('reset-to-default-filters', value='false')} | ||||
|     ${h.hidden('save-current-filters-as-defaults', value='false')} | ||||
| 
 | ||||
|     <fieldset> | ||||
|       <legend>Filters</legend> | ||||
|       % 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}> | ||||
|             ${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> | ||||
|             <div class="inputs"> | ||||
|               ${form.filter_verb(filtr)} | ||||
|  | @ -20,19 +20,19 @@ | |||
|     </fieldset> | ||||
| 
 | ||||
|     <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"> | ||||
|         <option value="">Add a Filter</option> | ||||
|         % for filtr in form.iter_filters(): | ||||
|             <option value="${filtr.key}"${' disabled="disabled"' if filtr.active else ''|n}>${filtr.label}</option> | ||||
|         % endfor | ||||
|       </select> | ||||
|       ${form.tag('button', type='button', id='default-filters', c="Default View")} | ||||
|       ${form.tag('button', type='button', id='clear-filters', c="No Filters")} | ||||
|       <button type="button" id="default-filters">Default View</button> | ||||
|       <button type="button" id="clear-filters">No Filters</button> | ||||
|       % 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 | ||||
|     </div> | ||||
| 
 | ||||
|   ${form.end()} | ||||
|   ${h.end_form()} | ||||
| </div><!-- newfilters --> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar