Remove all "old-style" (aka. version 1) grids
This commit is contained in:
		
							parent
							
								
									0befc46070
								
							
						
					
					
						commit
						62fa0f9fcb
					
				
					 19 changed files with 32 additions and 1604 deletions
				
			
		|  | @ -32,9 +32,6 @@ from .master import MasterView | |||
| # TODO: deprecate / remove some of this | ||||
| from .autocomplete import AutocompleteView | ||||
| from .crud import CrudView | ||||
| from .grids import ( | ||||
|     GridView, AlchemyGridView, SortableAlchemyGridView, | ||||
|     PagedAlchemyGridView, SearchableAlchemyGridView) | ||||
| 
 | ||||
| 
 | ||||
| def includeme(config): | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # -*- coding: utf-8; -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2016 Lance Edgar | ||||
| #  Copyright © 2010-2017 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
|  | @ -29,5 +29,5 @@ from __future__ import unicode_literals, absolute_import | |||
| from .core import BatchMasterView, FileBatchMasterView | ||||
| 
 | ||||
| # TODO: deprecate / remove this | ||||
| from .core import (BaseGrid, BatchGrid, FileBatchGrid, BaseCrud, BatchCrud, FileBatchCrud, | ||||
|                    StatusRenderer, BatchRowGrid, ProductBatchRowGrid, BatchRowCrud, defaults) | ||||
| from .core import (BaseCrud, BatchCrud, FileBatchCrud, | ||||
|                    StatusRenderer, BatchRowCrud, defaults) | ||||
|  |  | |||
|  | @ -51,9 +51,8 @@ from webhelpers.html import HTML, tags | |||
| 
 | ||||
| from tailbone import forms, newgrids as grids | ||||
| from tailbone.db import Session | ||||
| from tailbone.views import MasterView, SearchableAlchemyGridView, CrudView | ||||
| from tailbone.views import MasterView, CrudView | ||||
| from tailbone.forms.renderers.batch import FileFieldRenderer | ||||
| from tailbone.grids.search import BooleanSearchFilter, EnumSearchFilter | ||||
| from tailbone.progress import SessionProgress | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1137,264 +1136,6 @@ class FileBatchMasterView(BatchMasterView): | |||
|                                        "Download existing {} data file".format(model_title)) | ||||
| 
 | ||||
| 
 | ||||
| class BaseGrid(SearchableAlchemyGridView): | ||||
|     """ | ||||
|     Base view for batch and batch row grid views.  You should not derive from | ||||
|     this class, but :class:`BatchGrid` or :class:`BatchRowGrid` instead. | ||||
|     """ | ||||
| 
 | ||||
|     @property | ||||
|     def config_prefix(self): | ||||
|         """ | ||||
|         Config prefix for the grid view.  This is used to keep track of current | ||||
|         filtering and sorting, within the user's session.  Derived classes may | ||||
|         override this. | ||||
|         """ | ||||
|         return self.mapped_class.__name__.lower() | ||||
| 
 | ||||
|     @property | ||||
|     def permission_prefix(self): | ||||
|         """ | ||||
|         Permission prefix for the grid view.  This is used to automatically | ||||
|         protect certain views common to all batches.  Derived classes can | ||||
|         override this. | ||||
|         """ | ||||
|         return self.route_prefix | ||||
| 
 | ||||
|     def join_map_extras(self): | ||||
|         """ | ||||
|         Derived classes can override this.  The value returned will be used to | ||||
|         supplement the default join map. | ||||
|         """ | ||||
|         return {} | ||||
| 
 | ||||
|     def filter_map_extras(self): | ||||
|         """ | ||||
|         Derived classes can override this.  The value returned will be used to | ||||
|         supplement the default filter map. | ||||
|         """ | ||||
|         return {} | ||||
| 
 | ||||
|     def make_filter_map(self, **kwargs): | ||||
|         """ | ||||
|         Make a filter map by combining kwargs from the base class, with extras | ||||
|         supplied by a derived class. | ||||
|         """ | ||||
|         extras = self.filter_map_extras() | ||||
|         exact = extras.pop('exact', None) | ||||
|         if exact: | ||||
|             kwargs.setdefault('exact', []).extend(exact) | ||||
|         ilike = extras.pop('ilike', None) | ||||
|         if ilike: | ||||
|             kwargs.setdefault('ilike', []).extend(ilike) | ||||
|         kwargs.update(extras) | ||||
|         return super(BaseGrid, self).make_filter_map(**kwargs) | ||||
| 
 | ||||
|     def filter_config_extras(self): | ||||
|         """ | ||||
|         Derived classes can override this.  The value returned will be used to | ||||
|         supplement the default filter config. | ||||
|         """ | ||||
|         return {} | ||||
| 
 | ||||
|     def sort_map_extras(self): | ||||
|         """ | ||||
|         Derived classes can override this.  The value returned will be used to | ||||
|         supplement the default sort map. | ||||
|         """ | ||||
|         return {} | ||||
| 
 | ||||
|     def _configure_grid(self, grid): | ||||
|         """ | ||||
|         Internal method for configuring the grid.  This is meant only for base | ||||
|         classes; derived classes should not need to override it. | ||||
|         """ | ||||
| 
 | ||||
|     def configure_grid(self, grid): | ||||
|         """ | ||||
|         Derived classes can override this.  Customizes a grid which has already | ||||
|         been created with defaults by the base class. | ||||
|         """ | ||||
| 
 | ||||
| 
 | ||||
| class BatchGrid(BaseGrid): | ||||
|     """ | ||||
|     Base grid view for batches, which can be filtered and sorted. | ||||
|     """ | ||||
| 
 | ||||
|     @property | ||||
|     def batch_class(self): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     @property | ||||
|     def mapped_class(self): | ||||
|         return self.batch_class | ||||
| 
 | ||||
|     @property | ||||
|     def batch_display(self): | ||||
|         """ | ||||
|         Singular display text for the batch type, e.g. "Vendor Invoice". | ||||
|         Override this as necessary. | ||||
|         """ | ||||
|         return self.batch_class.__name__ | ||||
| 
 | ||||
|     @property | ||||
|     def batch_display_plural(self): | ||||
|         """ | ||||
|         Plural display text for the batch type, e.g. "Vendor Invoices". | ||||
|         Override this as necessary. | ||||
|         """ | ||||
|         return "{0}s".format(self.batch_display) | ||||
| 
 | ||||
|     def join_map(self): | ||||
|         """ | ||||
|         Provides the default join map for batch grid views.  Derived classes | ||||
|         should *not* override this, but :meth:`join_map_extras()` instead. | ||||
|         """ | ||||
|         map_ = { | ||||
|             'created_by': | ||||
|                 lambda q: q.join(model.User, model.User.uuid == self.batch_class.created_by_uuid), | ||||
|             'executed_by': | ||||
|                 lambda q: q.outerjoin(model.User, model.User.uuid == self.batch_class.executed_by_uuid), | ||||
|             } | ||||
|         map_.update(self.join_map_extras()) | ||||
|         return map_ | ||||
| 
 | ||||
|     def filter_map(self): | ||||
|         """ | ||||
|         Provides the default filter map for batch grid views.  Derived classes | ||||
|         should *not* override this, but :meth:`filter_map_extras()` instead. | ||||
|         """ | ||||
| 
 | ||||
|         def executed_is(q, v): | ||||
|             if v == 'True': | ||||
|                 return q.filter(self.batch_class.executed != None) | ||||
|             else: | ||||
|                 return q.filter(self.batch_class.executed == None) | ||||
| 
 | ||||
|         def executed_nt(q, v): | ||||
|             if v == 'True': | ||||
|                 return q.filter(self.batch_class.executed == None) | ||||
|             else: | ||||
|                 return q.filter(self.batch_class.executed != None) | ||||
| 
 | ||||
|         return self.make_filter_map( | ||||
|             executed={'is': executed_is, 'nt': executed_nt}) | ||||
| 
 | ||||
|     def filter_config(self): | ||||
|         """ | ||||
|         Provides the default filter config for batch grid views.  Derived | ||||
|         classes should *not* override this, but :meth:`filter_config_extras()` | ||||
|         instead. | ||||
|         """ | ||||
|         defaults = self.filter_config_extras() | ||||
|         config = self.make_filter_config( | ||||
|             filter_factory_executed=BooleanSearchFilter, | ||||
|             filter_type_executed='is', | ||||
|             executed=False, | ||||
|             include_filter_executed=True) | ||||
|         defaults.update(config) | ||||
|         return defaults | ||||
| 
 | ||||
|     def sort_map(self): | ||||
|         """ | ||||
|         Provides the default sort map for batch grid views.  Derived classes | ||||
|         should *not* override this, but :meth:`sort_map_extras()` instead. | ||||
|         """ | ||||
|         map_ = self.make_sort_map( | ||||
|             created_by=self.sorter(model.User.username), | ||||
|             executed_by=self.sorter(model.User.username)) | ||||
|         map_.update(self.sort_map_extras()) | ||||
|         return map_ | ||||
| 
 | ||||
|     def sort_config(self): | ||||
|         """ | ||||
|         Provides the default sort config for batch grid views.  Derived classes | ||||
|         may override this. | ||||
|         """ | ||||
|         return self.make_sort_config(sort='created', dir='desc') | ||||
| 
 | ||||
|     def grid(self): | ||||
|         """ | ||||
|         Creates the grid for the view.  Derived classes should *not* override | ||||
|         this, but :meth:`configure_grid()` instead. | ||||
|         """ | ||||
|         g = self.make_grid() | ||||
|         g.created_by.set(renderer=forms.renderers.UserFieldRenderer) | ||||
|         g.cognized_by.set(renderer=forms.renderers.UserFieldRenderer) | ||||
|         g.executed_by.set(renderer=forms.renderers.UserFieldRenderer) | ||||
|         self._configure_grid(g) | ||||
|         self.configure_grid(g) | ||||
|         if self.request.has_perm('{0}.view'.format(self.permission_prefix)): | ||||
|             g.viewable = True | ||||
|             g.view_route_name = '{0}.view'.format(self.route_prefix) | ||||
|         if self.request.has_perm('{0}.edit'.format(self.permission_prefix)): | ||||
|             g.editable = True | ||||
|             g.edit_route_name = '{0}.edit'.format(self.route_prefix) | ||||
|         if self.request.has_perm('{0}.delete'.format(self.permission_prefix)): | ||||
|             g.deletable = True | ||||
|             g.delete_route_name = '{0}.delete'.format(self.route_prefix) | ||||
|         return g | ||||
| 
 | ||||
|     def _configure_grid(self, grid): | ||||
|         grid.created_by.set(label="Created by") | ||||
|         grid.executed_by.set(label="Executed by") | ||||
| 
 | ||||
|     def configure_grid(self, grid): | ||||
|         """ | ||||
|         Derived classes can override this.  Customizes a grid which has already | ||||
|         been created with defaults by the base class. | ||||
|         """ | ||||
|         g = grid | ||||
|         g.configure( | ||||
|             include=[ | ||||
|                 g.created, | ||||
|                 g.created_by, | ||||
|                 g.executed, | ||||
|                 g.executed_by, | ||||
|                 ], | ||||
|             readonly=True) | ||||
| 
 | ||||
|     def render_kwargs(self): | ||||
|         """ | ||||
|         Add some things to the template context: batch type display name, route | ||||
|         and permission prefixes. | ||||
|         """ | ||||
|         return { | ||||
|             'batch_display': self.batch_display, | ||||
|             'batch_display_plural': self.batch_display_plural, | ||||
|             'route_prefix': self.route_prefix, | ||||
|             'permission_prefix': self.permission_prefix, | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
| class FileBatchGrid(BatchGrid): | ||||
|     """ | ||||
|     Base grid view for batches, which involve primarily a file upload. | ||||
|     """ | ||||
| 
 | ||||
|     def _configure_grid(self, g): | ||||
|         super(FileBatchGrid, self)._configure_grid(g) | ||||
|         g.created.set(label="Uploaded") | ||||
|         g.created_by.set(label="Uploaded by") | ||||
| 
 | ||||
|     def configure_grid(self, grid): | ||||
|         """ | ||||
|         Derived classes can override this.  Customizes a grid which has already | ||||
|         been created with defaults by the base class. | ||||
|         """ | ||||
|         g = grid | ||||
|         g.configure( | ||||
|             include=[ | ||||
|                 g.created, | ||||
|                 g.created_by, | ||||
|                 g.filename, | ||||
|                 g.executed, | ||||
|                 g.executed_by, | ||||
|                 ], | ||||
|             readonly=True) | ||||
| 
 | ||||
| 
 | ||||
| class BaseCrud(CrudView): | ||||
|     """ | ||||
|     Base CRUD view for batches and batch rows. | ||||
|  | @ -2000,173 +1741,6 @@ class StatusRenderer(forms.renderers.EnumFieldRenderer): | |||
|         return status_code_text | ||||
| 
 | ||||
| 
 | ||||
| class BatchRowGrid(BaseGrid): | ||||
|     """ | ||||
|     Base grid view for batch rows, which can be filtered and sorted.  Also it | ||||
|     can delete all rows matching the current list view query. | ||||
|     """ | ||||
| 
 | ||||
|     @property | ||||
|     def row_class(self): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     @property | ||||
|     def mapped_class(self): | ||||
|         return self.row_class | ||||
| 
 | ||||
|     @property | ||||
|     def config_prefix(self): | ||||
|         """ | ||||
|         Config prefix for the grid view.  This is used to keep track of current | ||||
|         filtering and sorting, within the user's session.  Derived classes may | ||||
|         override this. | ||||
|         """ | ||||
|         return '{0}.{1}'.format(self.mapped_class.__name__.lower(), | ||||
|                                 self.request.matchdict['uuid']) | ||||
| 
 | ||||
|     @property | ||||
|     def batch_class(self): | ||||
|         """ | ||||
|         Model class of the batch to which the rows belong. | ||||
|         """ | ||||
|         return self.row_class.__batch_class__ | ||||
| 
 | ||||
|     @property | ||||
|     def batch_display(self): | ||||
|         """ | ||||
|         Singular display text for the batch type, e.g. "Vendor Invoice". | ||||
|         Override this as necessary. | ||||
|         """ | ||||
|         return self.batch_class.__name__ | ||||
| 
 | ||||
|     def current_batch(self): | ||||
|         """ | ||||
|         Return the current batch, based on the UUID within the URL. | ||||
|         """ | ||||
|         return Session.query(self.batch_class).get(self.request.matchdict['uuid']) | ||||
| 
 | ||||
|     def modify_query(self, q): | ||||
|         q = super(BatchRowGrid, self).modify_query(q) | ||||
|         q = q.filter(self.row_class.batch == self.current_batch()) | ||||
|         q = q.filter(self.row_class.removed == False) | ||||
|         return q | ||||
| 
 | ||||
|     def join_map(self): | ||||
|         """ | ||||
|         Provides the default join map for batch row grid views.  Derived | ||||
|         classes should *not* override this, but :meth:`join_map_extras()` | ||||
|         instead. | ||||
|         """ | ||||
|         return self.join_map_extras() | ||||
| 
 | ||||
|     def filter_map(self): | ||||
|         """ | ||||
|         Provides the default filter map for batch row grid views.  Derived | ||||
|         classes should *not* override this, but :meth:`filter_map_extras()` | ||||
|         instead. | ||||
|         """ | ||||
|         return self.make_filter_map(exact=['status_code']) | ||||
| 
 | ||||
|     def filter_config(self): | ||||
|         """ | ||||
|         Provides the default filter config for batch grid views.  Derived | ||||
|         classes should *not* override this, but :meth:`filter_config_extras()` | ||||
|         instead. | ||||
|         """ | ||||
|         kwargs = {'filter_label_status_code': "Status", | ||||
|                   'filter_factory_status_code': EnumSearchFilter(self.row_class.STATUS)} | ||||
|         kwargs.update(self.filter_config_extras()) | ||||
|         return self.make_filter_config(**kwargs) | ||||
| 
 | ||||
|     def sort_map(self): | ||||
|         """ | ||||
|         Provides the default sort map for batch grid views.  Derived classes | ||||
|         should *not* override this, but :meth:`sort_map_extras()` instead. | ||||
|         """ | ||||
|         map_ = self.make_sort_map() | ||||
|         map_.update(self.sort_map_extras()) | ||||
|         return map_ | ||||
| 
 | ||||
|     def sort_config(self): | ||||
|         """ | ||||
|         Provides the default sort config for batch grid views.  Derived classes | ||||
|         may override this. | ||||
|         """ | ||||
|         return self.make_sort_config(sort='sequence', dir='asc') | ||||
| 
 | ||||
|     def grid(self): | ||||
|         """ | ||||
|         Creates the grid for the view.  Derived classes should *not* override | ||||
|         this, but :meth:`configure_grid()` instead. | ||||
|         """ | ||||
|         g = self.make_grid() | ||||
|         g.extra_row_class = self.tr_class | ||||
|         g.sequence.set(label="Seq.") | ||||
|         g.status_code.set(label="Status", renderer=StatusRenderer(self.row_class.STATUS)) | ||||
|         self._configure_grid(g) | ||||
|         self.configure_grid(g) | ||||
| 
 | ||||
|         batch = self.current_batch() | ||||
|         g.viewable = True | ||||
|         g.view_route_name = '{0}.row.view'.format(self.route_prefix) | ||||
|         # TODO: Fix this check for edit mode. | ||||
|         edit_mode = self.request.referrer.endswith('/edit') | ||||
|         if edit_mode and not batch.executed and self.request.has_perm('{0}.edit'.format(self.permission_prefix)): | ||||
|             # g.editable = True | ||||
|             # g.edit_route_name = '{0}.rows.edit'.format(self.route_prefix) | ||||
|             g.deletable = True | ||||
|             g.delete_route_name = '{0}.rows.delete'.format(self.route_prefix) | ||||
|         return g | ||||
| 
 | ||||
|     def tr_class(self, row, i): | ||||
|         pass | ||||
| 
 | ||||
|     def render_kwargs(self): | ||||
|         """ | ||||
|         Add the current batch and route prefix to the template context. | ||||
|         """ | ||||
|         return {'batch': self.current_batch(), | ||||
|                 'route_prefix': self.route_prefix} | ||||
| 
 | ||||
|     def bulk_delete(self): | ||||
|         """ | ||||
|         "Delete" all rows matching the current row grid view query.  This sets | ||||
|         the ``removed`` flag on the rows but does not truly delete them. | ||||
|         """ | ||||
|         self.query().update({'removed': True}, synchronize_session=False) | ||||
|         return httpexceptions.HTTPFound(location=self.request.route_url('{}.view'.format(self.route_prefix), | ||||
|                                                                         uuid=self.request.matchdict['uuid'])) | ||||
| 
 | ||||
| 
 | ||||
| class ProductBatchRowGrid(BatchRowGrid): | ||||
|     """ | ||||
|     Base grid view for batch rows which deal directly with products. | ||||
|     """ | ||||
| 
 | ||||
|     def filter_map(self): | ||||
|         """ | ||||
|         Provides the default filter map for batch row grid views.  Derived | ||||
|         classes should *not* override this, but :meth:`filter_map_extras()` | ||||
|         instead. | ||||
|         """ | ||||
|         return self.make_filter_map(exact=['status_code'], | ||||
|                                     ilike=['brand_name', 'description', 'size'], | ||||
|                                     upc=self.filter_gpc(self.row_class.upc)) | ||||
| 
 | ||||
|     def filter_config(self): | ||||
|         """ | ||||
|         Provides the default filter config for batch grid views.  Derived | ||||
|         classes should *not* override this, but :meth:`filter_config_extras()` | ||||
|         instead. | ||||
|         """ | ||||
|         kwargs = {'filter_label_status_code': "Status", | ||||
|                   'filter_factory_status_code': EnumSearchFilter(self.row_class.STATUS), | ||||
|                   'filter_label_upc': "UPC", | ||||
|                   'filter_label_brand_name': "Brand"} | ||||
|         kwargs.update(self.filter_config_extras()) | ||||
|         return self.make_filter_config(**kwargs) | ||||
| 
 | ||||
| 
 | ||||
| class BatchRowCrud(BaseCrud): | ||||
|     """ | ||||
|     Base CRUD view for batch rows. | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # -*- coding: utf-8; -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
|  | @ -33,7 +33,6 @@ from rattail.db import model | |||
| from tailbone import forms | ||||
| from tailbone.db import Session | ||||
| from tailbone.views import MasterView | ||||
| from tailbone.newgrids.filters import ChoiceValueRenderer | ||||
| 
 | ||||
| 
 | ||||
| class CustomerOrdersView(MasterView): | ||||
|  |  | |||
|  | @ -28,8 +28,8 @@ from __future__ import unicode_literals, absolute_import | |||
| 
 | ||||
| from rattail.db import model | ||||
| 
 | ||||
| from tailbone import newgrids as grids | ||||
| from tailbone.views import MasterView, AutocompleteView | ||||
| from tailbone.newgrids import AlchemyGrid, GridAction | ||||
| 
 | ||||
| 
 | ||||
| class DepartmentsView(MasterView): | ||||
|  | @ -67,11 +67,11 @@ class DepartmentsView(MasterView): | |||
|             # shouldn't need a key for this one, for instance (no settings | ||||
|             # required), but there is plenty of room for improvement here. | ||||
|             employees = sorted(department.employees, key=unicode) | ||||
|             employees = AlchemyGrid('departments.employees', self.request, data=employees, model_class=model.Employee, | ||||
|                                       main_actions=[ | ||||
|                                           GridAction('view', icon='zoomin', | ||||
|                                                      url=lambda r, i: self.request.route_url('employees.view', uuid=r.uuid)), | ||||
|                                       ]) | ||||
|             employees = grids.AlchemyGrid('departments.employees', self.request, data=employees, model_class=model.Employee, | ||||
|                                           main_actions=[ | ||||
|                                               grids.GridAction('view', icon='zoomin', | ||||
|                                                                url=lambda r, i: self.request.route_url('employees.view', uuid=r.uuid)), | ||||
|                                           ]) | ||||
|             employees.configure(include=[employees.display_name], readonly=True) | ||||
|             kwargs['employees'] = employees | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,13 +34,12 @@ from rattail import mail | |||
| from rattail.db import api | ||||
| from rattail.config import parse_list | ||||
| 
 | ||||
| from tailbone import forms | ||||
| from tailbone import forms, newgrids as grids | ||||
| from tailbone.db import Session | ||||
| from tailbone.views import MasterView, View | ||||
| from tailbone.newgrids import Grid, GridColumn | ||||
| 
 | ||||
| 
 | ||||
| class BoolGridColumn(GridColumn): | ||||
| class BoolGridColumn(grids.GridColumn): | ||||
| 
 | ||||
|     def render(self, value): | ||||
|         if value is None: | ||||
|  | @ -48,7 +47,7 @@ class BoolGridColumn(GridColumn): | |||
|         return 'Yes' if value else 'No' | ||||
| 
 | ||||
| 
 | ||||
| class EmailListGridColumn(GridColumn): | ||||
| class EmailListGridColumn(grids.GridColumn): | ||||
| 
 | ||||
|     def render(self, value): | ||||
|         if not value: | ||||
|  | @ -77,7 +76,7 @@ class ProfilesView(MasterView): | |||
|     model_key = 'key' | ||||
|     url_prefix = '/email/profiles' | ||||
| 
 | ||||
|     grid_factory = Grid | ||||
|     grid_factory = grids.Grid | ||||
|     filterable = False | ||||
|     pageable = False | ||||
| 
 | ||||
|  | @ -115,9 +114,9 @@ class ProfilesView(MasterView): | |||
| 
 | ||||
|     def configure_grid(self, g): | ||||
|         g.columns = [ | ||||
|             GridColumn('key'), | ||||
|             GridColumn('prefix'), | ||||
|             GridColumn('subject'), | ||||
|             grids.GridColumn('key'), | ||||
|             grids.GridColumn('prefix'), | ||||
|             grids.GridColumn('subject'), | ||||
|             EmailListGridColumn('to'), | ||||
|             BoolGridColumn('enabled'), | ||||
|         ] | ||||
|  |  | |||
|  | @ -32,11 +32,9 @@ from rattail.db import model | |||
| 
 | ||||
| import formalchemy as fa | ||||
| 
 | ||||
| from tailbone import forms | ||||
| from tailbone import forms, newgrids as grids | ||||
| from tailbone.db import Session | ||||
| from tailbone.views import MasterView, AutocompleteView | ||||
| from tailbone.newgrids import AlchemyGrid, GridAction | ||||
| from tailbone.newgrids.filters import EnumValueRenderer | ||||
| 
 | ||||
| 
 | ||||
| class EmployeesView(MasterView): | ||||
|  | @ -67,7 +65,7 @@ class EmployeesView(MasterView): | |||
|             g.filters['status'].default_active = True | ||||
|             g.filters['status'].default_verb = 'equal' | ||||
|             g.filters['status'].default_value = self.enum.EMPLOYEE_STATUS_CURRENT | ||||
|             g.filters['status'].set_value_renderer(EnumValueRenderer(self.enum.EMPLOYEE_STATUS)) | ||||
|             g.filters['status'].set_value_renderer(grids.filters.EnumValueRenderer(self.enum.EMPLOYEE_STATUS)) | ||||
|         else: | ||||
|             del g.filters['id'] | ||||
|             del g.filters['status'] | ||||
|  |  | |||
|  | @ -1,32 +0,0 @@ | |||
| #!/usr/bin/env python | ||||
| # -*- coding: utf-8  -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2012 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
| #  Rattail is free software: you can redistribute it and/or modify it under the | ||||
| #  terms of the GNU Affero General Public License as published by the Free | ||||
| #  Software Foundation, either version 3 of the License, or (at your option) | ||||
| #  any later version. | ||||
| # | ||||
| #  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| #  FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for | ||||
| #  more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU Affero General Public License | ||||
| #  along with Rattail.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| ################################################################################ | ||||
| 
 | ||||
| """ | ||||
| Grid Views | ||||
| """ | ||||
| 
 | ||||
| from tailbone.views.grids.core import GridView | ||||
| from tailbone.views.grids.alchemy import ( | ||||
|     AlchemyGridView, SortableAlchemyGridView, | ||||
|     PagedAlchemyGridView, SearchableAlchemyGridView) | ||||
|  | @ -1,192 +0,0 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2014 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
| #  Rattail is free software: you can redistribute it and/or modify it under the | ||||
| #  terms of the GNU Affero General Public License as published by the Free | ||||
| #  Software Foundation, either version 3 of the License, or (at your option) | ||||
| #  any later version. | ||||
| # | ||||
| #  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| #  FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for | ||||
| #  more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU Affero General Public License | ||||
| #  along with Rattail.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| ################################################################################ | ||||
| 
 | ||||
| """ | ||||
| FormAlchemy Grid Views | ||||
| """ | ||||
| 
 | ||||
| from webhelpers import paginate | ||||
| 
 | ||||
| from .core import GridView | ||||
| from ... import grids | ||||
| from ...db import Session | ||||
| 
 | ||||
| 
 | ||||
| __all__ = ['AlchemyGridView', 'SortableAlchemyGridView', | ||||
|            'PagedAlchemyGridView', 'SearchableAlchemyGridView'] | ||||
| 
 | ||||
| 
 | ||||
| class AlchemyGridView(GridView): | ||||
| 
 | ||||
|     def make_query(self, session=Session): | ||||
|         query = session.query(self.mapped_class) | ||||
|         return self.modify_query(query) | ||||
| 
 | ||||
|     def modify_query(self, query): | ||||
|         return query | ||||
| 
 | ||||
|     def query(self): | ||||
|         return self.make_query() | ||||
| 
 | ||||
|     def make_grid(self, **kwargs): | ||||
|         self.update_grid_kwargs(kwargs) | ||||
|         return grids.AlchemyGrid( | ||||
|             self.request, self.mapped_class, self._data, **kwargs) | ||||
| 
 | ||||
|     def grid(self): | ||||
|         return self.make_grid() | ||||
| 
 | ||||
|     def __call__(self): | ||||
|         self._data = self.query() | ||||
|         grid = self.grid() | ||||
|         return self.render_grid(grid) | ||||
| 
 | ||||
| 
 | ||||
| class SortableAlchemyGridView(AlchemyGridView): | ||||
| 
 | ||||
|     sort = None | ||||
|     full = True | ||||
| 
 | ||||
|     @property | ||||
|     def config_prefix(self): | ||||
|         raise NotImplementedError | ||||
| 
 | ||||
|     def join_map(self): | ||||
|         return {} | ||||
| 
 | ||||
|     def make_sort_map(self, *args, **kwargs): | ||||
|         return grids.util.get_sort_map( | ||||
|             self.mapped_class, names=args or None, **kwargs) | ||||
| 
 | ||||
|     def sorter(self, field): | ||||
|         return grids.util.sorter(field) | ||||
| 
 | ||||
|     def sort_map(self): | ||||
|         return self.make_sort_map() | ||||
| 
 | ||||
|     def make_sort_config(self, **kwargs): | ||||
|         return grids.util.get_sort_config( | ||||
|             self.config_prefix, self.request, **kwargs) | ||||
| 
 | ||||
|     def sort_config(self): | ||||
|         return self.make_sort_config(sort=self.sort) | ||||
| 
 | ||||
|     def modify_query(self, query): | ||||
|         return grids.util.sort_query( | ||||
|             query, self._sort_config, self.sort_map(), self.join_map()) | ||||
| 
 | ||||
|     def make_grid(self, **kwargs): | ||||
|         self.update_grid_kwargs(kwargs) | ||||
|         return grids.AlchemyGrid( | ||||
|             self.request, self.mapped_class, self._data, | ||||
|             sort_map=self.sort_map(), config=self._sort_config, **kwargs) | ||||
| 
 | ||||
|     def grid(self): | ||||
|         return self.make_grid() | ||||
| 
 | ||||
|     def __call__(self): | ||||
|         self._sort_config = self.sort_config() | ||||
|         self._data = self.query() | ||||
|         grid = self.grid() | ||||
|         return self.render_grid(grid) | ||||
| 
 | ||||
| 
 | ||||
| class PagedAlchemyGridView(SortableAlchemyGridView): | ||||
| 
 | ||||
|     def make_pager(self): | ||||
|         config = self._sort_config | ||||
|         query = self.query() | ||||
|         return paginate.Page( | ||||
|             query, item_count=query.count(), | ||||
|             items_per_page=int(config['per_page']), | ||||
|             page=int(config['page']), | ||||
|             url=paginate.PageURL_WebOb(self.request)) | ||||
| 
 | ||||
|     def __call__(self): | ||||
|         self._sort_config = self.sort_config() | ||||
|         self._data = self.make_pager() | ||||
|         grid = self.grid() | ||||
|         grid.pager = self._data | ||||
|         return self.render_grid(grid) | ||||
| 
 | ||||
| 
 | ||||
| class SearchableAlchemyGridView(PagedAlchemyGridView): | ||||
| 
 | ||||
|     def filter_exact(self, field): | ||||
|         return grids.search.filter_exact(field) | ||||
| 
 | ||||
|     def filter_ilike(self, field): | ||||
|         return grids.search.filter_ilike(field) | ||||
| 
 | ||||
|     def filter_int(self, field): | ||||
|         return grids.search.filter_int(field) | ||||
| 
 | ||||
|     def filter_soundex(self, field): | ||||
|         return grids.search.filter_soundex(field) | ||||
| 
 | ||||
|     def filter_ilike_and_soundex(self, field): | ||||
|         return grids.search.filter_ilike_and_soundex(field) | ||||
| 
 | ||||
|     def filter_gpc(self, field): | ||||
|         return grids.search.filter_gpc(field) | ||||
| 
 | ||||
|     def make_filter_map(self, **kwargs): | ||||
|         return grids.search.get_filter_map(self.mapped_class, **kwargs) | ||||
| 
 | ||||
|     def filter_map(self): | ||||
|         return self.make_filter_map() | ||||
| 
 | ||||
|     def make_filter_config(self, **kwargs): | ||||
|         return grids.search.get_filter_config( | ||||
|             self.config_prefix, self.request, self.filter_map(), **kwargs) | ||||
| 
 | ||||
|     def filter_config(self): | ||||
|         return self.make_filter_config() | ||||
| 
 | ||||
|     def make_search_form(self): | ||||
|         return grids.search.get_search_form( | ||||
|             self.request, self.filter_map(), self._filter_config) | ||||
| 
 | ||||
|     def search_form(self): | ||||
|         return self.make_search_form() | ||||
| 
 | ||||
|     def modify_query(self, query): | ||||
|         join_map = self.join_map() | ||||
|         if not hasattr(self, '_filter_config'): | ||||
|             self._filter_config = self.filter_config() | ||||
|         query = grids.search.filter_query( | ||||
|             query, self._filter_config, self.filter_map(), join_map) | ||||
|         if hasattr(self, '_sort_config'): | ||||
|             self._sort_config['joins'] = self._filter_config['joins'] | ||||
|             query = grids.util.sort_query( | ||||
|                 query, self._sort_config, self.sort_map(), join_map) | ||||
|         return query | ||||
| 
 | ||||
|     def __call__(self): | ||||
|         self._filter_config = self.filter_config() | ||||
|         search = self.search_form() | ||||
|         self._sort_config = self.sort_config() | ||||
|         self._data = self.make_pager() | ||||
|         grid = self.grid() | ||||
|         grid.pager = self._data | ||||
|         return self.render_grid(grid, search) | ||||
|  | @ -1,72 +0,0 @@ | |||
| #!/usr/bin/env python | ||||
| # -*- coding: utf-8  -*- | ||||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2012 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
| #  Rattail is free software: you can redistribute it and/or modify it under the | ||||
| #  terms of the GNU Affero General Public License as published by the Free | ||||
| #  Software Foundation, either version 3 of the License, or (at your option) | ||||
| #  any later version. | ||||
| # | ||||
| #  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
| #  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||||
| #  FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for | ||||
| #  more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU Affero General Public License | ||||
| #  along with Rattail.  If not, see <http://www.gnu.org/licenses/>. | ||||
| # | ||||
| ################################################################################ | ||||
| 
 | ||||
| """ | ||||
| Core Grid View | ||||
| """ | ||||
| 
 | ||||
| from .. import View | ||||
| from ... import grids | ||||
| 
 | ||||
| 
 | ||||
| __all__ = ['GridView'] | ||||
| 
 | ||||
| 
 | ||||
| class GridView(View): | ||||
| 
 | ||||
|     route_name = None | ||||
|     route_url = None | ||||
|     renderer = None | ||||
|     permission = None | ||||
| 
 | ||||
|     full = False | ||||
|     checkboxes = False | ||||
|     deletable = False | ||||
| 
 | ||||
|     partial_only = False | ||||
| 
 | ||||
|     def update_grid_kwargs(self, kwargs): | ||||
|         kwargs.setdefault('full', self.full) | ||||
|         kwargs.setdefault('checkboxes', self.checkboxes) | ||||
|         kwargs.setdefault('deletable', self.deletable) | ||||
|         kwargs.setdefault('partial_only', self.partial_only) | ||||
| 
 | ||||
|     def make_grid(self, **kwargs): | ||||
|         self.update_grid_kwargs(kwargs) | ||||
|         return grids.Grid(self.request, **kwargs) | ||||
| 
 | ||||
|     def grid(self): | ||||
|         return self.make_grid() | ||||
| 
 | ||||
|     def render_kwargs(self): | ||||
|         return {} | ||||
| 
 | ||||
|     def render_grid(self, grid, search=None, **kwargs): | ||||
|         kwargs = self.render_kwargs() | ||||
|         kwargs['search_form'] = search | ||||
|         return grids.util.render_grid(grid, **kwargs) | ||||
| 
 | ||||
|     def __call__(self): | ||||
|         grid = self.grid() | ||||
|         return self.render_grid(grid) | ||||
|  | @ -35,7 +35,7 @@ from rattail.time import localtime | |||
| import formalchemy as fa | ||||
| from pyramid import httpexceptions | ||||
| 
 | ||||
| from tailbone import forms, newgrids as grids | ||||
| from tailbone import forms | ||||
| from tailbone.views.batch import BatchMasterView | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -35,10 +35,9 @@ import formalchemy as fa | |||
| from formalchemy.fields import IntegerFieldRenderer | ||||
| from webhelpers.html import HTML, tags | ||||
| 
 | ||||
| from tailbone import forms | ||||
| from tailbone import forms, newgrids as grids | ||||
| from tailbone.db import Session | ||||
| from tailbone.views.principal import PrincipalMasterView | ||||
| from tailbone.newgrids import AlchemyGrid, GridAction | ||||
| 
 | ||||
| 
 | ||||
| class RolesView(PrincipalMasterView): | ||||
|  | @ -86,11 +85,11 @@ class RolesView(PrincipalMasterView): | |||
|             # for this one, for instance (no settings required), but there is | ||||
|             # plenty of room for improvement here. | ||||
|             users = sorted(role.users, key=lambda u: u.username) | ||||
|             users = AlchemyGrid('roles.users', self.request, data=users, model_class=model.User, | ||||
|                                 main_actions=[ | ||||
|                                     GridAction('view', icon='zoomin', | ||||
|                                                url=lambda r, i: self.request.route_url('users.view', uuid=r.uuid)), | ||||
|                                 ]) | ||||
|             users = grids.AlchemyGrid('roles.users', self.request, data=users, model_class=model.User, | ||||
|                                       main_actions=[ | ||||
|                                           grids.GridAction('view', icon='zoomin', | ||||
|                                                            url=lambda r, i: self.request.route_url('users.view', uuid=r.uuid)), | ||||
|                                       ]) | ||||
|             users.configure(include=[users.username], readonly=True) | ||||
|             kwargs['users'] = users | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,8 +26,8 @@ Views with info about the underlying Rattail tables | |||
| 
 | ||||
| from __future__ import unicode_literals, absolute_import | ||||
| 
 | ||||
| from tailbone import newgrids as grids | ||||
| from tailbone.views import MasterView | ||||
| from tailbone.newgrids import Grid, GridColumn | ||||
| 
 | ||||
| 
 | ||||
| class TablesView(MasterView): | ||||
|  | @ -41,7 +41,7 @@ class TablesView(MasterView): | |||
|     editable = False | ||||
|     deletable = False | ||||
|     viewable = False | ||||
|     grid_factory = Grid | ||||
|     grid_factory = grids.Grid | ||||
|     filterable = False | ||||
|     pageable = False | ||||
| 
 | ||||
|  | @ -59,8 +59,8 @@ class TablesView(MasterView): | |||
| 
 | ||||
|     def configure_grid(self, g): | ||||
|         g.columns = [ | ||||
|             GridColumn('name'), | ||||
|             GridColumn('row_count'), | ||||
|             grids.GridColumn('name'), | ||||
|             grids.GridColumn('row_count'), | ||||
|         ] | ||||
| 
 | ||||
|         g.sorters['name'] = g.make_sorter('name', foldcase=True) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar