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:
parent
9da7ba21bf
commit
f47157102c
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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');
|
||||||
|
|
16
tailbone/templates/mobile/filters_simple.mako
Normal file
16
tailbone/templates/mobile/filters_simple.mako
Normal 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 -->
|
|
@ -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>
|
||||||
|
|
|
@ -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()}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in a new issue