Add initial/basic support for "simple" mobile grid filter w/ radio buttons

so far only one such filter is (presumably?) supported..etc.
This commit is contained in:
Lance Edgar 2017-07-10 21:04:56 -05:00
parent 9da7ba21bf
commit f47157102c
10 changed files with 104 additions and 19 deletions

View file

@ -26,6 +26,8 @@ Core Grid Classes
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
import six
from rattail.db.api import get_setting, save_setting from rattail.db.api import get_setting, save_setting
from rattail.util import prettify from rattail.util import prettify
@ -106,7 +108,7 @@ class Grid(object):
""" """
Iterate over all filters available to the grid. Iterate over all filters available to the grid.
""" """
return self.filters.itervalues() return six.itervalues(self.filters)
def iter_active_filters(self): def iter_active_filters(self):
""" """

View file

@ -149,7 +149,7 @@ class GridFilter(object):
setattr(self, key, value) setattr(self, key, value)
def __repr__(self): def __repr__(self):
return "GridFilter({0})".format(repr(self.key)) return "{}({})".format(self.__class__.__name__, repr(self.key))
def get_default_verbs(self): def get_default_verbs(self):
""" """
@ -206,6 +206,18 @@ class GridFilter(object):
return self.value_renderer.render(value=value, **kwargs) return self.value_renderer.render(value=value, **kwargs)
class MobileFilter(GridFilter):
"""
Base class for mobile grid filters.
"""
default_verbs = ['equal']
def __init__(self, key, **kwargs):
kwargs.setdefault('default_active', True)
kwargs.setdefault('default_verb', 'equal')
super(MobileFilter, self).__init__(key, **kwargs)
class AlchemyGridFilter(GridFilter): class AlchemyGridFilter(GridFilter):
""" """
Base class for SQLAlchemy grid filters. Base class for SQLAlchemy grid filters.

View file

@ -26,16 +26,24 @@ Mobile Grids
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
from pyramid.renderers import render
from webhelpers2.html import HTML from webhelpers2.html import HTML
from tailbone.newgrids import AlchemyGrid from tailbone.newgrids import filters, AlchemyGrid
class MobileGrid(AlchemyGrid): class MobileGrid(AlchemyGrid):
""" """
Base class for all mobile grids Base class for all mobile grids
""" """
default_filters = filters.GridFilterSet()
def column_header(self, column): def column_header(self, column):
kwargs = {'c': column.label} kwargs = {'c': column.label}
return HTML.tag('th', **kwargs) return HTML.tag('th', **kwargs)
def render_filters(self, template='/mobile/filters_simple.mako', **kwargs):
context = kwargs
context['request'] = self.request
context['grid'] = self
return render(template, context)

View file

@ -34,3 +34,8 @@
font-weight: bold; font-weight: bold;
margin-top: 1em; margin-top: 1em;
} }
/* make sure space comes between simple filter and "grid" list */
.simple-filter {
margin-bottom: 1.5em;
}

View file

@ -69,6 +69,12 @@ $(document).on('pageshow', function() {
}); });
// handle radio button value change for "simple" grid filter
$(document).on('change', '.simple-filter .ui-radio', function() {
$(this).parents('form:first').submit();
});
// vendor validation for new purchasing batch // vendor validation for new purchasing batch
$(document).on('click', 'form[name="new-purchasing-batch"] input[type="submit"]', function() { $(document).on('click', 'form[name="new-purchasing-batch"] input[type="submit"]', function() {
var $form = $(this).parents('form'); var $form = $(this).parents('form');

View file

@ -0,0 +1,16 @@
## -*- coding: utf-8; -*-
<div class="simple-filter">
${h.form(request.current_route_url(), method='get')}
${h.csrf_token(request)}
% for filtr in grid.iter_filters():
${h.hidden('{}.verb'.format(filtr.key), value=filtr.verb)}
<fieldset data-role="controlgroup" data-type="horizontal">
% for value, label in filtr.iter_choices():
${h.radio(filtr.key, value=value, label=label, checked=value == filtr.value)}
% endfor
</fieldset>
% endfor
${h.end_form()}
</div><!-- simple-filter -->

View file

@ -9,6 +9,10 @@
<%def name="title()">${model_title_plural}</%def> <%def name="title()">${model_title_plural}</%def>
% if grid.filterable:
${grid.render_filters()|n}
% endif
<ul data-role="listview"> <ul data-role="listview">
% for obj in grid.iter_rows(): % for obj in grid.iter_rows():
<li>${grid.listitem.render_readonly()}</li> <li>${grid.listitem.render_readonly()}</li>

View file

@ -7,12 +7,4 @@
${h.link_to("New Receiving Batch", url('mobile.receiving.create'), class_='ui-btn ui-corner-all')} ${h.link_to("New Receiving Batch", url('mobile.receiving.create'), class_='ui-btn ui-corner-all')}
% endif % endif
<fieldset data-role="controlgroup" data-type="horizontal">
${h.radio('receiving-filter', value='pending', label="Pending", checked=True)}
${h.radio('receiving-filter', value='complete', label="Complete", disabled='disabled')}
${h.radio('receiving-filter', value='executed', label="Executed", disabled='disabled')}
${h.radio('receiving-filter', value='all', label="All", disabled='disabled')}
</fieldset>
<br /><br />
${parent.body()} ${parent.body()}

View file

@ -65,6 +65,7 @@ class MasterView(View):
supports_mobile = False supports_mobile = False
mobile_creatable = False mobile_creatable = False
mobile_filterable = False
listing = False listing = False
creating = False creating = False
@ -197,11 +198,19 @@ class MasterView(View):
defaults = { defaults = {
'route_prefix': self.get_route_prefix(), 'route_prefix': self.get_route_prefix(),
'pageable': self.pageable, 'pageable': self.pageable,
'sortable': True, 'sortable': False,
'filterable': self.mobile_filterable,
} }
if self.mobile_filterable:
defaults['filters'] = self.make_mobile_filters()
defaults.update(kwargs) defaults.update(kwargs)
return defaults return defaults
def make_mobile_filters(self):
"""
Returns a set of filters for the mobile grid, if applicable.
"""
def preconfigure_mobile_grid(self, grid): def preconfigure_mobile_grid(self, grid):
""" """
Optionally perform pre-configuration for the mobile grid, to establish Optionally perform pre-configuration for the mobile grid, to establish

View file

@ -33,16 +33,42 @@ import sqlalchemy as sa
from rattail import pod from rattail import pod
from rattail.db import model from rattail.db import model
from rattail.gpc import GPC from rattail.gpc import GPC
from rattail.util import pretty_quantity from rattail.util import pretty_quantity, prettify
import formalchemy as fa import formalchemy as fa
import formencode as fe import formencode as fe
from webhelpers2.html import tags from webhelpers2.html import tags
from tailbone import forms from tailbone import forms, newgrids as grids
from tailbone.views.purchasing import PurchasingBatchView from tailbone.views.purchasing import PurchasingBatchView
class MobileBatchStatusFilter(grids.filters.MobileFilter):
value_choices = ['pending', 'complete', 'executed', 'all']
def filter_equal(self, query, value):
if value == 'pending':
return query.filter(model.PurchaseBatch.executed == None)\
.filter(sa.or_(
model.PurchaseBatch.complete == None,
model.PurchaseBatch.complete == False))
if value == 'complete':
return query.filter(model.PurchaseBatch.executed == None)\
.filter(model.PurchaseBatch.complete == True)
if value == 'executed':
return query.filter(model.PurchaseBatch.executed != None)
return query
def iter_choices(self):
for value in self.value_choices:
yield value, prettify(value)
class ReceivingBatchView(PurchasingBatchView): class ReceivingBatchView(PurchasingBatchView):
""" """
Master view for receiving batches Master view for receiving batches
@ -55,12 +81,21 @@ class ReceivingBatchView(PurchasingBatchView):
rows_deletable = False rows_deletable = False
supports_mobile = True supports_mobile = True
mobile_creatable = True mobile_creatable = True
mobile_filterable = True
mobile_rows_viewable = True mobile_rows_viewable = True
@property @property
def batch_mode(self): def batch_mode(self):
return self.enum.PURCHASE_BATCH_MODE_RECEIVING return self.enum.PURCHASE_BATCH_MODE_RECEIVING
def make_mobile_filters(self):
"""
Returns a set of filters for the mobile grid.
"""
filters = grids.filters.GridFilterSet()
filters['status'] = MobileBatchStatusFilter('status', default_value='pending')
return filters
def mobile_create(self): def mobile_create(self):
""" """
Mobile view for creating a new receiving batch Mobile view for creating a new receiving batch
@ -115,12 +150,8 @@ class ReceivingBatchView(PurchasingBatchView):
return kwargs return kwargs
def get_mobile_data(self, session=None): def get_mobile_data(self, session=None):
# TODO: this hard-codes list view to show Pending only # TODO: this hard-codes the sort by batch ID desc
return super(ReceivingBatchView, self).get_mobile_data(session=session)\ return super(ReceivingBatchView, self).get_mobile_data(session=session)\
.filter(model.PurchaseBatch.executed == None)\
.filter(sa.or_(
model.PurchaseBatch.complete == None,
model.PurchaseBatch.complete == False))\
.order_by(model.PurchaseBatch.id.desc()) .order_by(model.PurchaseBatch.id.desc())
def configure_mobile_grid(self, g): def configure_mobile_grid(self, g):