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
					
				
					 10 changed files with 104 additions and 19 deletions
				
			
		| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue