feat: add multi-column sorting (frontend or backend) for grids
This commit is contained in:
parent
58f7a862a2
commit
8d6f4ad368
4 changed files with 388 additions and 93 deletions
|
@ -71,10 +71,19 @@ class TestGrid(WebTestCase):
|
|||
sort_defaults=[('name', 'desc')])
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'desc')])
|
||||
|
||||
# sort defaults as list w/ multiple
|
||||
# multi-column defaults
|
||||
grid = self.make_grid(model_class=model.Setting, sortable=True,
|
||||
sort_multiple=True,
|
||||
sort_defaults=[('name', 'desc'), ('value', 'asc')])
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'desc')])
|
||||
self.assertTrue(grid.sort_multiple)
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'desc'),
|
||||
mod.SortInfo('value', 'asc')])
|
||||
|
||||
# multi-column sort disabled for oruga
|
||||
self.request.use_oruga = True
|
||||
grid = self.make_grid(model_class=model.Setting, sortable=True,
|
||||
sort_multiple=True)
|
||||
self.assertFalse(grid.sort_multiple)
|
||||
|
||||
def test_vue_tagname(self):
|
||||
grid = self.make_grid()
|
||||
|
@ -236,7 +245,7 @@ class TestGrid(WebTestCase):
|
|||
|
||||
# can skip the saving step
|
||||
self.request.GET = {'pagesize': '10', 'page': '3'}
|
||||
grid.load_settings(store=False)
|
||||
grid.load_settings(persist=False)
|
||||
self.assertEqual(grid.page, 3)
|
||||
self.assertEqual(self.request.session['grid.foo.page'], 2)
|
||||
|
||||
|
@ -261,7 +270,7 @@ class TestGrid(WebTestCase):
|
|||
|
||||
# can skip the saving step
|
||||
self.request.GET = {'sort1key': 'name', 'sort1dir': 'asc'}
|
||||
grid.load_settings(store=False)
|
||||
grid.load_settings(persist=False)
|
||||
self.assertEqual(grid.active_sorters, [{'key': 'name', 'dir': 'asc'}])
|
||||
self.assertEqual(self.request.session['grid.settings.sorters.length'], 1)
|
||||
self.assertEqual(self.request.session['grid.settings.sorters.1.key'], 'name')
|
||||
|
@ -575,21 +584,21 @@ class TestGrid(WebTestCase):
|
|||
sorted_data = sorter(sample_data, 'asc')
|
||||
self.assertEqual(len(sorted_data), 9)
|
||||
|
||||
# case folding is off by default
|
||||
# case folding is on by default
|
||||
grid = self.make_grid(model_class=model.Setting)
|
||||
sorter = grid.make_sorter('value')
|
||||
sorted_data = sorter(sample_data, 'desc')
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo2', 'value': 'two'})
|
||||
sorted_data = sorter(sample_data, 'asc')
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo1', 'value': 'ONE'})
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo8', 'value': 'eight'})
|
||||
|
||||
# results are different with case folding
|
||||
# results are different with case folding off
|
||||
grid = self.make_grid(model_class=model.Setting)
|
||||
sorter = grid.make_sorter('value', foldcase=True)
|
||||
sorter = grid.make_sorter('value', foldcase=False)
|
||||
sorted_data = sorter(sample_data, 'desc')
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo2', 'value': 'two'})
|
||||
sorted_data = sorter(sample_data, 'asc')
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo8', 'value': 'eight'})
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo1', 'value': 'ONE'})
|
||||
|
||||
def test_set_sorter(self):
|
||||
model = self.app.model
|
||||
|
@ -632,13 +641,38 @@ class TestGrid(WebTestCase):
|
|||
|
||||
def test_set_sort_defaults(self):
|
||||
model = self.app.model
|
||||
|
||||
# basics
|
||||
grid = self.make_grid(model_class=model.Setting, sortable=True)
|
||||
self.assertEqual(grid.sort_defaults, [])
|
||||
grid.set_sort_defaults('name', 'asc')
|
||||
|
||||
# can set just sortkey
|
||||
grid.set_sort_defaults('name')
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'asc')])
|
||||
|
||||
# can set sortkey, sortdir
|
||||
grid.set_sort_defaults('name', 'desc')
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('name', 'desc')])
|
||||
|
||||
# can set sortkey, sortdir as tuple
|
||||
grid.set_sort_defaults(('value', 'asc'))
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('value', 'asc')])
|
||||
|
||||
# can set as list
|
||||
grid.sort_multiple = True
|
||||
grid.set_sort_defaults([('value', 'asc'), ('name', 'desc')])
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('value', 'asc'),
|
||||
mod.SortInfo('name', 'desc')])
|
||||
|
||||
# list is pruned if multi-sort disabled
|
||||
grid.sort_multiple = False
|
||||
grid.set_sort_defaults([('value', 'asc'), ('name', 'desc')])
|
||||
self.assertEqual(grid.sort_defaults, [mod.SortInfo('value', 'asc')])
|
||||
|
||||
# error if any other single arg
|
||||
self.assertRaises(ValueError, grid.set_sort_defaults, 42)
|
||||
|
||||
# error if more than 2 args
|
||||
self.assertRaises(ValueError, grid.set_sort_defaults, 'name', 'asc', 'value', 'desc')
|
||||
|
||||
def test_is_sortable(self):
|
||||
model = self.app.model
|
||||
|
||||
|
@ -701,9 +735,9 @@ class TestGrid(WebTestCase):
|
|||
sample_data = [
|
||||
{'name': 'foo1', 'value': 'ONE'},
|
||||
{'name': 'foo2', 'value': 'two'},
|
||||
{'name': 'foo3', 'value': 'three'},
|
||||
{'name': 'foo4', 'value': 'four'},
|
||||
{'name': 'foo5', 'value': 'five'},
|
||||
{'name': 'foo3', 'value': 'ggg'},
|
||||
{'name': 'foo4', 'value': 'ggg'},
|
||||
{'name': 'foo5', 'value': 'ggg'},
|
||||
{'name': 'foo6', 'value': 'six'},
|
||||
{'name': 'foo7', 'value': 'seven'},
|
||||
{'name': 'foo8', 'value': 'eight'},
|
||||
|
@ -740,15 +774,26 @@ class TestGrid(WebTestCase):
|
|||
self.assertEqual(sorted_data[0]['name'], 'foo1')
|
||||
self.assertEqual(sorted_data[-1]['name'], 'foo9')
|
||||
|
||||
# error if mult-column sort attempted
|
||||
self.assertRaises(NotImplementedError, grid.sort_data, sample_data, sorters=[
|
||||
{'key': 'name', 'dir': 'desc'},
|
||||
{'key': 'value', 'dir': 'asc'},
|
||||
])
|
||||
# multi-column sorting for list data
|
||||
sorted_data = grid.sort_data(sample_data, sorters=[{'key': 'value', 'dir': 'asc'},
|
||||
{'key': 'name', 'dir': 'asc'}])
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo8', 'value': 'eight'})
|
||||
self.assertEqual(dict(sorted_data[1]), {'name': 'foo3', 'value': 'ggg'})
|
||||
self.assertEqual(dict(sorted_data[3]), {'name': 'foo5', 'value': 'ggg'})
|
||||
self.assertEqual(dict(sorted_data[-1]), {'name': 'foo2', 'value': 'two'})
|
||||
|
||||
# multi-column sorting for query
|
||||
sorted_query = grid.sort_data(sample_query, sorters=[{'key': 'value', 'dir': 'asc'},
|
||||
{'key': 'name', 'dir': 'asc'}])
|
||||
self.assertEqual(dict(sorted_data[0]), {'name': 'foo8', 'value': 'eight'})
|
||||
self.assertEqual(dict(sorted_data[1]), {'name': 'foo3', 'value': 'ggg'})
|
||||
self.assertEqual(dict(sorted_data[3]), {'name': 'foo5', 'value': 'ggg'})
|
||||
self.assertEqual(dict(sorted_data[-1]), {'name': 'foo2', 'value': 'two'})
|
||||
|
||||
# cannot sort data if sortfunc is missing for column
|
||||
grid.remove_sorter('name')
|
||||
sorted_data = grid.sort_data(sample_data)
|
||||
sorted_data = grid.sort_data(sample_data, sorters=[{'key': 'value', 'dir': 'asc'},
|
||||
{'key': 'name', 'dir': 'asc'}])
|
||||
# nb. sorted data is in same order as original sample (not sorted)
|
||||
self.assertEqual(sorted_data[0]['name'], 'foo1')
|
||||
self.assertEqual(sorted_data[-1]['name'], 'foo9')
|
||||
|
@ -823,6 +868,24 @@ class TestGrid(WebTestCase):
|
|||
self.assertEqual(first['field'], 'foo')
|
||||
self.assertEqual(first['label'], 'Foo')
|
||||
|
||||
def test_get_vue_active_sorters(self):
|
||||
model = self.app.model
|
||||
|
||||
# empty
|
||||
grid = self.make_grid(key='foo', sortable=True, sort_on_backend=True)
|
||||
grid.load_settings()
|
||||
sorters = grid.get_vue_active_sorters()
|
||||
self.assertEqual(sorters, [])
|
||||
|
||||
# format is different
|
||||
grid = self.make_grid(key='settings', model_class=model.Setting,
|
||||
sortable=True, sort_on_backend=True,
|
||||
sort_defaults='name')
|
||||
grid.load_settings()
|
||||
self.assertEqual(grid.active_sorters, [{'key': 'name', 'dir': 'asc'}])
|
||||
sorters = grid.get_vue_active_sorters()
|
||||
self.assertEqual(sorters, [{'field': 'name', 'order': 'asc'}])
|
||||
|
||||
def test_get_vue_data(self):
|
||||
|
||||
# empty if no columns defined
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue