From 98ff71a2ddb179748f0e04978b8f99b9efb91b37 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 10 Jul 2017 22:10:27 -0500 Subject: [PATCH] Add filter support for mobile row grid; plus mark receiving as complete --- tailbone/newgrids/mobile.py | 5 ++ tailbone/templates/mobile/filters_simple.mako | 3 +- tailbone/templates/mobile/grid_complete.mako | 11 +++++ tailbone/templates/mobile/master/index.mako | 10 +--- tailbone/templates/mobile/receiving/view.mako | 21 ++++----- tailbone/views/master.py | 32 +++++++++---- tailbone/views/purchasing/receiving.py | 47 +++++++++++++++++++ 7 files changed, 96 insertions(+), 33 deletions(-) create mode 100644 tailbone/templates/mobile/grid_complete.mako diff --git a/tailbone/newgrids/mobile.py b/tailbone/newgrids/mobile.py index c08453a3..776ce229 100644 --- a/tailbone/newgrids/mobile.py +++ b/tailbone/newgrids/mobile.py @@ -47,3 +47,8 @@ class MobileGrid(AlchemyGrid): context['request'] = self.request context['grid'] = self return render(template, context) + + def render_complete(self, template='/mobile/grid_complete.mako', **kwargs): + context = kwargs + context['grid'] = self + return render(template, context) diff --git a/tailbone/templates/mobile/filters_simple.mako b/tailbone/templates/mobile/filters_simple.mako index d0644e5f..1286d99a 100644 --- a/tailbone/templates/mobile/filters_simple.mako +++ b/tailbone/templates/mobile/filters_simple.mako @@ -1,7 +1,6 @@ ## -*- coding: utf-8; -*-
- ${h.form(request.current_route_url(), method='get')} - ${h.csrf_token(request)} + ${h.form(request.current_route_url(_query=None), method='get')} % for filtr in grid.iter_filters(): ${h.hidden('{}.verb'.format(filtr.key), value=filtr.verb)} diff --git a/tailbone/templates/mobile/grid_complete.mako b/tailbone/templates/mobile/grid_complete.mako new file mode 100644 index 00000000..8fa765bc --- /dev/null +++ b/tailbone/templates/mobile/grid_complete.mako @@ -0,0 +1,11 @@ +## -*- coding: utf-8; -*- + +% if grid.filterable: + ${grid.render_filters()|n} +% endif + + diff --git a/tailbone/templates/mobile/master/index.mako b/tailbone/templates/mobile/master/index.mako index 74b5d7f7..ea2c7034 100644 --- a/tailbone/templates/mobile/master/index.mako +++ b/tailbone/templates/mobile/master/index.mako @@ -9,15 +9,7 @@ <%def name="title()">${model_title_plural} -% if grid.filterable: - ${grid.render_filters()|n} -% endif - - +${grid.render_complete()|n} ## ## diff --git a/tailbone/templates/mobile/receiving/view.mako b/tailbone/templates/mobile/receiving/view.mako index e37a46e3..1ae3691f 100644 --- a/tailbone/templates/mobile/receiving/view.mako +++ b/tailbone/templates/mobile/receiving/view.mako @@ -9,17 +9,12 @@ ${form.render()|n} ${h.text('upc-search', class_='receiving-upc-search', placeholder="Enter UPC", autocomplete='off', **{'data-type': 'search', 'data-url': url('mobile.receiving.lookup', uuid=batch.uuid)})}
-
- ## ${h.radio('receiving-row-filter', value='missing', label="Missing", disabled='disabled')} - ${h.radio('receiving-row-filter', value='incomplete', label="Incomplete", disabled='disabled')} - ${h.radio('receiving-row-filter', value='damaged', label="Damaged", disabled='disabled')} - ${h.radio('receiving-row-filter', value='expired', label="Expired", disabled='disabled')} - ${h.radio('receiving-row-filter', value='all', label="All", checked=True)} -
-

+${grid.render_complete()|n} - +% if not instance.executed and not instance.complete: +

+ ${h.form(request.route_url('mobile.receiving.mark_complete', uuid=instance.uuid))} + ${h.csrf_token(request)} + ${h.hidden('mark-complete', value='true')} + +% endif diff --git a/tailbone/views/master.py b/tailbone/views/master.py index 604d1456..b2c3b242 100644 --- a/tailbone/views/master.py +++ b/tailbone/views/master.py @@ -96,6 +96,7 @@ class MasterView(View): rows_bulk_deletable = False rows_default_pagesize = 20 + mobile_rows_filterable = False mobile_rows_viewable = False @property @@ -206,11 +207,32 @@ class MasterView(View): defaults.update(kwargs) return defaults + def make_mobile_row_grid_kwargs(self, **kwargs): + """ + Must return a dictionary of kwargs to be passed to the factory when + creating new mobile *row* grid instances. + """ + defaults = { + 'route_prefix': self.get_route_prefix(), + 'pageable': self.pageable, + 'sortable': False, + 'filterable': self.mobile_rows_filterable, + } + if self.mobile_rows_filterable: + defaults['filters'] = self.make_mobile_row_filters() + defaults.update(kwargs) + return defaults + def make_mobile_filters(self): """ Returns a set of filters for the mobile grid, if applicable. """ + def make_mobile_row_filters(self): + """ + Returns a set of filters for the mobile row grid, if applicable. + """ + def preconfigure_mobile_grid(self, grid): """ Optionally perform pre-configuration for the mobile grid, to establish @@ -588,14 +610,6 @@ class MasterView(View): def get_mobile_row_data(self, parent): return self.get_row_data(parent) - def make_mobile_row_grid_kwargs(self, **kwargs): - defaults = { - 'pageable': True, - 'sortable': True, - } - defaults.update(kwargs) - return defaults - def make_mobile_row_grid(self, **kwargs): """ Make a new (configured) rows grid instance for mobile. @@ -607,7 +621,7 @@ class MasterView(View): kwargs.setdefault('request', self.request) kwargs.setdefault('model_class', self.model_row_class) kwargs = self.make_mobile_row_grid_kwargs(**kwargs) - factory = self.get_grid_factory() + factory = self.get_mobile_grid_factory() grid = factory(**kwargs) self.configure_mobile_row_grid(grid) grid.load_settings() diff --git a/tailbone/views/purchasing/receiving.py b/tailbone/views/purchasing/receiving.py index dbdcbbe7..56ef0a6c 100644 --- a/tailbone/views/purchasing/receiving.py +++ b/tailbone/views/purchasing/receiving.py @@ -69,6 +69,33 @@ class MobileBatchStatusFilter(grids.filters.MobileFilter): yield value, prettify(value) +class MobileItemStatusFilter(grids.filters.MobileFilter): + + value_choices = ['incomplete', 'damaged', 'expired', 'all'] + + def filter_equal(self, query, value): + + # TODO: is this accurate (enough) ? + if value == 'incomplete': + return query.filter(model.PurchaseBatchRow.status_code != model.PurchaseBatchRow.STATUS_OK) + + if value == 'damaged': + return query.filter(sa.or_( + model.PurchaseBatchRow.cases_damaged != 0, + model.PurchaseBatchRow.units_damaged != 0)) + + if value == 'expired': + return query.filter(sa.or_( + model.PurchaseBatchRow.cases_expired != 0, + model.PurchaseBatchRow.units_expired != 0)) + + return query + + def iter_choices(self): + for value in self.value_choices: + yield value, prettify(value) + + class ReceivingBatchView(PurchasingBatchView): """ Master view for receiving batches @@ -82,6 +109,7 @@ class ReceivingBatchView(PurchasingBatchView): supports_mobile = True mobile_creatable = True mobile_filterable = True + mobile_rows_filterable = True mobile_rows_viewable = True @property @@ -96,6 +124,14 @@ class ReceivingBatchView(PurchasingBatchView): filters['status'] = MobileBatchStatusFilter('status', default_value='pending') return filters + def make_mobile_row_filters(self): + """ + Returns a set of filters for the mobile row grid. + """ + filters = grids.filters.GridFilterSet() + filters['status'] = MobileItemStatusFilter('status', default_value='incomplete') + return filters + def mobile_create(self): """ Mobile view for creating a new receiving batch @@ -289,11 +325,17 @@ class ReceivingBatchView(PurchasingBatchView): row.credits.append(credit) return credit + def mobile_mark_complete(self): + batch = self.get_instance() + batch.complete = True + return self.redirect(self.request.route_url('mobile.{}'.format(self.get_route_prefix()))) + @classmethod def defaults(cls, config): route_prefix = cls.get_route_prefix() url_prefix = cls.get_url_prefix() model_key = cls.get_model_key() + permission_prefix = cls.get_permission_prefix() row_permission_prefix = cls.get_row_permission_prefix() # mobile lookup @@ -301,6 +343,11 @@ class ReceivingBatchView(PurchasingBatchView): config.add_view(cls, attr='mobile_lookup', route_name='mobile.{}.lookup'.format(route_prefix), renderer='json', permission='{}.view'.format(row_permission_prefix)) + # mobile mark complete + config.add_route('mobile.{}.mark_complete'.format(route_prefix), '/mobile{}/{{{}}}/mark-complete'.format(url_prefix, model_key)) + config.add_view(cls, attr='mobile_mark_complete', route_name='mobile.{}.mark_complete'.format(route_prefix), + permission='{}.edit'.format(permission_prefix)) + cls._purchasing_defaults(config) cls._batch_defaults(config) cls._defaults(config)