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