Remove all "old-style" (aka. version 1) grids

This commit is contained in:
Lance Edgar 2017-07-06 00:28:01 -05:00
parent 0befc46070
commit 62fa0f9fcb
19 changed files with 32 additions and 1604 deletions

View file

@ -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):

View file

@ -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)

View file

@ -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.

View file

@ -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):

View file

@ -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

View file

@ -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'),
]

View file

@ -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']

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)