feat: move "basic" grid pagination logic to wuttaweb
so far only "simple" pagination is supported by wuttaweb, so basically the main feature flag, page size, current page. in this scenario *all* data is written to client-side JSON and Buefy handles the actual pagination. backend pagination coming soon for wuttaweb but for now tailbone still handles all that.
This commit is contained in:
parent
2a0b6da2f9
commit
9da2a148c6
|
@ -31,6 +31,7 @@ import logging
|
|||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
from wuttjamaican.util import UNSPECIFIED
|
||||
from rattail.db.types import GPCType
|
||||
from rattail.util import prettify, pretty_boolean
|
||||
|
||||
|
@ -209,9 +210,6 @@ class Grid(WuttaGrid):
|
|||
sorters={},
|
||||
default_sortkey=None,
|
||||
default_sortdir='asc',
|
||||
pageable=False,
|
||||
default_pagesize=None,
|
||||
default_page=1,
|
||||
checkboxes=False,
|
||||
checked=None,
|
||||
check_handler=None,
|
||||
|
@ -233,7 +231,26 @@ class Grid(WuttaGrid):
|
|||
DeprecationWarning, stacklevel=2)
|
||||
kwargs.setdefault('vue_tagname', kwargs.pop('component'))
|
||||
|
||||
# TODO: pretty sure this should go away?
|
||||
if kwargs.get('pageable'):
|
||||
warnings.warn("component param is deprecated for Grid(); "
|
||||
"please use vue_tagname param instead",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
kwargs.setdefault('paginated', kwargs.pop('pageable'))
|
||||
|
||||
if kwargs.get('default_pagesize'):
|
||||
warnings.warn("default_pagesize param is deprecated for Grid(); "
|
||||
"please use pagesize param instead",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
kwargs.setdefault('pagesize', kwargs.pop('default_pagesize'))
|
||||
|
||||
if kwargs.get('default_page'):
|
||||
warnings.warn("default_page param is deprecated for Grid(); "
|
||||
"please use page param instead",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
kwargs.setdefault('page', kwargs.pop('default_page'))
|
||||
|
||||
# TODO: this should not be needed once all templates correctly
|
||||
# reference grid.vue_component etc.
|
||||
kwargs.setdefault('vue_tagname', 'tailbone-grid')
|
||||
|
||||
kwargs['key'] = key
|
||||
|
@ -272,10 +289,6 @@ class Grid(WuttaGrid):
|
|||
self.default_sortkey = default_sortkey
|
||||
self.default_sortdir = default_sortdir
|
||||
|
||||
self.pageable = pageable
|
||||
self.default_pagesize = default_pagesize
|
||||
self.default_page = default_page
|
||||
|
||||
self.checkboxes = checkboxes
|
||||
self.checked = checked
|
||||
if self.checked is None:
|
||||
|
@ -333,6 +346,16 @@ class Grid(WuttaGrid):
|
|||
DeprecationWarning, stacklevel=2)
|
||||
return self.vue_component
|
||||
|
||||
def get_pageable(self):
|
||||
""" """
|
||||
return self.paginated
|
||||
|
||||
def set_pageable(self, value):
|
||||
""" """
|
||||
self.paginated = value
|
||||
|
||||
pageable = property(get_pageable, set_pageable)
|
||||
|
||||
def hide_column(self, key):
|
||||
"""
|
||||
This *removes* a column from the grid, altogether.
|
||||
|
@ -756,18 +779,61 @@ class Grid(WuttaGrid):
|
|||
keyfunc = lambda v: v[key]
|
||||
return lambda q, d: sorted(q, key=keyfunc, reverse=d == 'desc')
|
||||
|
||||
def get_default_pagesize(self):
|
||||
def get_pagesize_options(self, default=None):
|
||||
""" """
|
||||
# let upstream check config
|
||||
options = super().get_pagesize_options(default=UNSPECIFIED)
|
||||
if options is not UNSPECIFIED:
|
||||
return options
|
||||
|
||||
# fallback to legacy config
|
||||
options = self.config.get_list('tailbone.grid.pagesize_options')
|
||||
if options:
|
||||
warnings.warn("tailbone.grid.pagesize_options setting is deprecated; "
|
||||
"please set wuttaweb.grids.default_pagesize_options instead",
|
||||
DeprecationWarning)
|
||||
options = [int(size) for size in options
|
||||
if size.isdigit()]
|
||||
if options:
|
||||
return options
|
||||
|
||||
if default:
|
||||
return default
|
||||
|
||||
# use upstream default
|
||||
return super().get_pagesize_options()
|
||||
|
||||
def get_pagesize(self, default=None):
|
||||
""" """
|
||||
# let upstream check config
|
||||
pagesize = super().get_pagesize(default=UNSPECIFIED)
|
||||
if pagesize is not UNSPECIFIED:
|
||||
return pagesize
|
||||
|
||||
# fallback to legacy config
|
||||
pagesize = self.config.get_int('tailbone.grid.default_pagesize')
|
||||
if pagesize:
|
||||
warnings.warn("tailbone.grid.default_pagesize setting is deprecated; "
|
||||
"please use wuttaweb.grids.default_pagesize instead",
|
||||
DeprecationWarning)
|
||||
return pagesize
|
||||
|
||||
if default:
|
||||
return default
|
||||
|
||||
# use upstream default
|
||||
return super().get_pagesize()
|
||||
|
||||
def get_default_pagesize(self): # pragma: no cover
|
||||
""" """
|
||||
warnings.warn("Grid.get_default_pagesize() method is deprecated; "
|
||||
"please use Grid.get_pagesize() of Grid.page instead",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
if self.default_pagesize:
|
||||
return self.default_pagesize
|
||||
|
||||
pagesize = self.request.rattail_config.getint('tailbone',
|
||||
'grid.default_pagesize',
|
||||
default=0)
|
||||
if pagesize:
|
||||
return pagesize
|
||||
|
||||
options = self.get_pagesize_options()
|
||||
return options[0]
|
||||
return self.get_pagesize()
|
||||
|
||||
def load_settings(self, store=True):
|
||||
"""
|
||||
|
@ -789,9 +855,9 @@ class Grid(WuttaGrid):
|
|||
settings['sorters.1.dir'] = self.default_sortdir
|
||||
else:
|
||||
settings['sorters.length'] = 0
|
||||
if self.pageable:
|
||||
settings['pagesize'] = self.get_default_pagesize()
|
||||
settings['page'] = self.default_page
|
||||
if self.paginated:
|
||||
settings['pagesize'] = self.pagesize
|
||||
settings['page'] = self.page
|
||||
if self.filterable:
|
||||
for filtr in self.iter_filters():
|
||||
settings['filter.{}.active'.format(filtr.key)] = filtr.default_active
|
||||
|
@ -867,7 +933,7 @@ class Grid(WuttaGrid):
|
|||
'field': settings[f'sorters.{i}.key'],
|
||||
'order': settings[f'sorters.{i}.dir'],
|
||||
})
|
||||
if self.pageable:
|
||||
if self.paginated:
|
||||
self.pagesize = settings['pagesize']
|
||||
self.page = settings['page']
|
||||
|
||||
|
@ -971,7 +1037,7 @@ class Grid(WuttaGrid):
|
|||
merge(f'sorters.{i}.key')
|
||||
merge(f'sorters.{i}.dir')
|
||||
|
||||
if self.pageable:
|
||||
if self.paginated:
|
||||
merge('pagesize', int)
|
||||
merge('page', int)
|
||||
|
||||
|
@ -1154,7 +1220,7 @@ class Grid(WuttaGrid):
|
|||
|
||||
:param settings: Dictionary of initial settings, which is to be updated.
|
||||
"""
|
||||
if not self.pageable:
|
||||
if not self.paginated:
|
||||
return
|
||||
|
||||
pagesize = self.request.GET.get('pagesize')
|
||||
|
@ -1231,7 +1297,7 @@ class Grid(WuttaGrid):
|
|||
persist(f'sorters.{i}.key')
|
||||
persist(f'sorters.{i}.dir')
|
||||
|
||||
if self.pageable:
|
||||
if self.paginated:
|
||||
persist('pagesize')
|
||||
persist('page')
|
||||
|
||||
|
@ -1355,7 +1421,7 @@ class Grid(WuttaGrid):
|
|||
data = self.filter_data(data)
|
||||
if self.sortable:
|
||||
data = self.sort_data(data)
|
||||
if self.pageable:
|
||||
if self.paginated:
|
||||
self.pager = self.paginate_data(data)
|
||||
data = self.pager
|
||||
return data
|
||||
|
@ -1580,18 +1646,6 @@ class Grid(WuttaGrid):
|
|||
return tags.checkbox('checkbox-{}-{}'.format(self.key, self.get_row_key(item)),
|
||||
checked=self.checked(item))
|
||||
|
||||
def get_pagesize_options(self):
|
||||
|
||||
# use values from config, if defined
|
||||
options = self.request.rattail_config.getlist('tailbone', 'grid.pagesize_options')
|
||||
if options:
|
||||
options = [int(size) for size in options
|
||||
if size.isdigit()]
|
||||
if options:
|
||||
return options
|
||||
|
||||
return [5, 10, 20, 50, 100, 200]
|
||||
|
||||
def has_static_data(self):
|
||||
"""
|
||||
Should return ``True`` if the grid data can be considered "static"
|
||||
|
@ -1734,7 +1788,7 @@ class Grid(WuttaGrid):
|
|||
results['checked_rows_code'] = '[{}]'.format(
|
||||
', '.join(['{}[{}]'.format(var, i) for i in checked]))
|
||||
|
||||
if self.pageable and self.pager is not None:
|
||||
if self.paginated and self.pager is not None:
|
||||
results['total_items'] = self.pager.item_count
|
||||
results['per_page'] = self.pager.items_per_page
|
||||
results['page'] = self.pager.page
|
||||
|
|
|
@ -107,12 +107,14 @@
|
|||
@cellclick="cellClick"
|
||||
% endif
|
||||
|
||||
% if grid.paginated:
|
||||
:paginated="paginated"
|
||||
:per-page="perPage"
|
||||
:current-page="currentPage"
|
||||
backend-pagination
|
||||
:total="total"
|
||||
@page-change="onPageChange"
|
||||
% endif
|
||||
|
||||
## TODO: should let grid (or master view) decide how to set these?
|
||||
icon-pack="fas"
|
||||
|
@ -203,7 +205,7 @@
|
|||
<div></div>
|
||||
% endif
|
||||
|
||||
% if getattr(grid, 'pageable', False):
|
||||
% if grid.paginated:
|
||||
<div v-if="firstItem"
|
||||
style="display: flex; gap: 0.5rem; align-items: center;">
|
||||
<span>
|
||||
|
@ -255,12 +257,14 @@
|
|||
checkedRows: ${grid_data['checked_rows_code']|n},
|
||||
% endif
|
||||
|
||||
paginated: ${json.dumps(getattr(grid, 'pageable', False))|n},
|
||||
% if grid.paginated:
|
||||
paginated: ${json.dumps(grid.paginated)|n},
|
||||
total: ${len(grid_data['data']) if static_data else (grid_data['total_items'] if grid_data is not Undefined else 0)},
|
||||
perPage: ${json.dumps(grid.pagesize if getattr(grid, 'pageable', False) else None)|n},
|
||||
currentPage: ${json.dumps(grid.page if getattr(grid, 'pageable', False) else None)|n},
|
||||
firstItem: ${json.dumps(grid_data['first_item'] if getattr(grid, 'pageable', False) else None)|n},
|
||||
lastItem: ${json.dumps(grid_data['last_item'] if getattr(grid, 'pageable', False) else None)|n},
|
||||
perPage: ${json.dumps(grid.pagesize if grid.paginated else None)|n},
|
||||
currentPage: ${json.dumps(grid.page if grid.paginated else None)|n},
|
||||
firstItem: ${json.dumps(grid_data['first_item'] if grid.paginated else None)|n},
|
||||
lastItem: ${json.dumps(grid_data['last_item'] if grid.paginated else None)|n},
|
||||
% endif
|
||||
|
||||
% if getattr(grid, 'sortable', False):
|
||||
|
||||
|
@ -439,7 +443,7 @@
|
|||
params['sort'+i+'dir'] = this.backendSorters[i-1].order
|
||||
}
|
||||
% endif
|
||||
% if getattr(grid, 'pageable', False):
|
||||
% if grid.paginated:
|
||||
params.pagesize = this.perPage
|
||||
params.page = this.currentPage
|
||||
% endif
|
||||
|
|
|
@ -439,7 +439,7 @@ class MasterView(View):
|
|||
'filterable': self.filterable,
|
||||
'use_byte_string_filters': self.use_byte_string_filters,
|
||||
'sortable': self.sortable,
|
||||
'pageable': self.pageable,
|
||||
'paginated': self.pageable,
|
||||
'extra_row_class': self.grid_extra_class,
|
||||
'url': lambda obj: self.get_action_url('view', obj),
|
||||
'checkboxes': checkboxes,
|
||||
|
@ -589,7 +589,7 @@ class MasterView(View):
|
|||
}
|
||||
|
||||
if self.rows_default_pagesize:
|
||||
defaults['default_pagesize'] = self.rows_default_pagesize
|
||||
defaults['pagesize'] = self.rows_default_pagesize
|
||||
|
||||
if self.has_rows and 'actions' not in defaults:
|
||||
actions = []
|
||||
|
|
|
@ -45,6 +45,10 @@ class PersonView(wutta.PersonView):
|
|||
model_class = Person
|
||||
Session = Session
|
||||
|
||||
# TODO: /grids/complete.mako is too aggressive for the
|
||||
# limited support we have in wuttaweb thus far
|
||||
paginated = False
|
||||
|
||||
labels = {
|
||||
'display_name': "Full Name",
|
||||
}
|
||||
|
|
|
@ -19,6 +19,32 @@ class TestGrid(WebTestCase):
|
|||
grid = self.make_grid('foo')
|
||||
self.assertIsInstance(grid, mod.Grid)
|
||||
|
||||
def test_deprecated_params(self):
|
||||
|
||||
# component
|
||||
grid = self.make_grid()
|
||||
self.assertEqual(grid.vue_tagname, 'tailbone-grid')
|
||||
grid = self.make_grid(component='blarg')
|
||||
self.assertEqual(grid.vue_tagname, 'blarg')
|
||||
|
||||
# pageable
|
||||
grid = self.make_grid()
|
||||
self.assertFalse(grid.paginated)
|
||||
grid = self.make_grid(pageable=True)
|
||||
self.assertTrue(grid.paginated)
|
||||
|
||||
# default_pagesize
|
||||
grid = self.make_grid()
|
||||
self.assertEqual(grid.pagesize, 20)
|
||||
grid = self.make_grid(default_pagesize=15)
|
||||
self.assertEqual(grid.pagesize, 15)
|
||||
|
||||
# default_page
|
||||
grid = self.make_grid()
|
||||
self.assertEqual(grid.page, 1)
|
||||
grid = self.make_grid(default_page=42)
|
||||
self.assertEqual(grid.page, 42)
|
||||
|
||||
def test_vue_tagname(self):
|
||||
|
||||
# default
|
||||
|
@ -133,6 +159,66 @@ class TestGrid(WebTestCase):
|
|||
grid.set_action_urls(setting, setting, 0)
|
||||
self.assertEqual(setting['_action_url_view'], '/blarg')
|
||||
|
||||
def test_pageable(self):
|
||||
grid = self.make_grid()
|
||||
self.assertFalse(grid.paginated)
|
||||
grid.pageable = True
|
||||
self.assertTrue(grid.paginated)
|
||||
grid.paginated = False
|
||||
self.assertFalse(grid.pageable)
|
||||
|
||||
def test_get_pagesize_options(self):
|
||||
grid = self.make_grid()
|
||||
|
||||
# default
|
||||
options = grid.get_pagesize_options()
|
||||
self.assertEqual(options, [5, 10, 20, 50, 100, 200])
|
||||
|
||||
# override default
|
||||
options = grid.get_pagesize_options(default=[42])
|
||||
self.assertEqual(options, [42])
|
||||
|
||||
# from legacy config
|
||||
self.config.setdefault('tailbone.grid.pagesize_options', '1 2 3')
|
||||
grid = self.make_grid()
|
||||
options = grid.get_pagesize_options()
|
||||
self.assertEqual(options, [1, 2, 3])
|
||||
|
||||
# from new config
|
||||
self.config.setdefault('wuttaweb.grids.default_pagesize_options', '4, 5, 6')
|
||||
grid = self.make_grid()
|
||||
options = grid.get_pagesize_options()
|
||||
self.assertEqual(options, [4, 5, 6])
|
||||
|
||||
def test_get_pagesize(self):
|
||||
grid = self.make_grid()
|
||||
|
||||
# default
|
||||
size = grid.get_pagesize()
|
||||
self.assertEqual(size, 20)
|
||||
|
||||
# override default
|
||||
size = grid.get_pagesize(default=42)
|
||||
self.assertEqual(size, 42)
|
||||
|
||||
# override default options
|
||||
self.config.setdefault('wuttaweb.grids.default_pagesize_options', '10 15 30')
|
||||
grid = self.make_grid()
|
||||
size = grid.get_pagesize()
|
||||
self.assertEqual(size, 10)
|
||||
|
||||
# from legacy config
|
||||
self.config.setdefault('tailbone.grid.default_pagesize', '12')
|
||||
grid = self.make_grid()
|
||||
size = grid.get_pagesize()
|
||||
self.assertEqual(size, 12)
|
||||
|
||||
# from new config
|
||||
self.config.setdefault('wuttaweb.grids.default_pagesize', '15')
|
||||
grid = self.make_grid()
|
||||
size = grid.get_pagesize()
|
||||
self.assertEqual(size, 15)
|
||||
|
||||
def test_render_vue_tag(self):
|
||||
model = self.app.model
|
||||
|
||||
|
|
Loading…
Reference in a new issue