feat: inherit from wutta base class for Grid
This commit is contained in:
parent
f7641218cb
commit
2a0b6da2f9
|
@ -38,7 +38,7 @@ from pyramid.renderers import render
|
||||||
from webhelpers2.html import HTML, tags
|
from webhelpers2.html import HTML, tags
|
||||||
from paginate_sqlalchemy import SqlalchemyOrmPage
|
from paginate_sqlalchemy import SqlalchemyOrmPage
|
||||||
|
|
||||||
from wuttaweb.grids import GridAction as WuttaGridAction
|
from wuttaweb.grids import Grid as WuttaGrid, GridAction as WuttaGridAction
|
||||||
from . import filters as gridfilters
|
from . import filters as gridfilters
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.util import raw_datetime
|
from tailbone.util import raw_datetime
|
||||||
|
@ -61,7 +61,7 @@ class FieldList(list):
|
||||||
self.insert(i + 1, newfield)
|
self.insert(i + 1, newfield)
|
||||||
|
|
||||||
|
|
||||||
class Grid:
|
class Grid(WuttaGrid):
|
||||||
"""
|
"""
|
||||||
Core grid class. In sore need of documentation.
|
Core grid class. In sore need of documentation.
|
||||||
|
|
||||||
|
@ -186,32 +186,59 @@ class Grid:
|
||||||
grid.row_uuid_getter = fake_uuid
|
grid.row_uuid_getter = fake_uuid
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, key, data, columns=None, width='auto', request=None,
|
def __init__(
|
||||||
model_class=None, model_title=None, model_title_plural=None,
|
self,
|
||||||
enums={}, labels={}, assume_local_times=False, renderers={}, invisible=[],
|
request,
|
||||||
|
key=None,
|
||||||
|
data=None,
|
||||||
|
width='auto',
|
||||||
|
model_title=None,
|
||||||
|
model_title_plural=None,
|
||||||
|
enums={},
|
||||||
|
assume_local_times=False,
|
||||||
|
invisible=[],
|
||||||
raw_renderers={},
|
raw_renderers={},
|
||||||
extra_row_class=None, linked_columns=[], url='#',
|
extra_row_class=None,
|
||||||
joiners={}, filterable=False, filters={}, use_byte_string_filters=False,
|
url='#',
|
||||||
|
joiners={},
|
||||||
|
filterable=False,
|
||||||
|
filters={},
|
||||||
|
use_byte_string_filters=False,
|
||||||
searchable={},
|
searchable={},
|
||||||
sortable=False, sorters={}, default_sortkey=None, default_sortdir='asc',
|
sortable=False,
|
||||||
pageable=False, default_pagesize=None, default_page=1,
|
sorters={},
|
||||||
checkboxes=False, checked=None, check_handler=None, check_all_handler=None,
|
default_sortkey=None,
|
||||||
checkable=None, row_uuid_getter=None,
|
default_sortdir='asc',
|
||||||
clicking_row_checks_box=False, click_handlers=None,
|
pageable=False,
|
||||||
main_actions=[], more_actions=[], delete_speedbump=False,
|
default_pagesize=None,
|
||||||
|
default_page=1,
|
||||||
|
checkboxes=False,
|
||||||
|
checked=None,
|
||||||
|
check_handler=None,
|
||||||
|
check_all_handler=None,
|
||||||
|
checkable=None,
|
||||||
|
row_uuid_getter=None,
|
||||||
|
clicking_row_checks_box=False,
|
||||||
|
click_handlers=None,
|
||||||
|
main_actions=[],
|
||||||
|
more_actions=[],
|
||||||
|
delete_speedbump=False,
|
||||||
ajax_data_url=None,
|
ajax_data_url=None,
|
||||||
vue_tagname=None,
|
|
||||||
expose_direct_link=False,
|
expose_direct_link=False,
|
||||||
**kwargs):
|
**kwargs,
|
||||||
|
):
|
||||||
|
if kwargs.get('component'):
|
||||||
|
warnings.warn("component param is deprecated for Grid(); "
|
||||||
|
"please use vue_tagname param instead",
|
||||||
|
DeprecationWarning, stacklevel=2)
|
||||||
|
kwargs.setdefault('vue_tagname', kwargs.pop('component'))
|
||||||
|
|
||||||
self.key = key
|
# TODO: pretty sure this should go away?
|
||||||
self.data = data
|
kwargs.setdefault('vue_tagname', 'tailbone-grid')
|
||||||
self.columns = FieldList(columns) if columns is not None else None
|
|
||||||
self.width = width
|
kwargs['key'] = key
|
||||||
self.request = request
|
kwargs['data'] = data
|
||||||
self.model_class = model_class
|
super().__init__(request, **kwargs)
|
||||||
if self.model_class and self.columns is None:
|
|
||||||
self.columns = self.make_columns()
|
|
||||||
|
|
||||||
self.model_title = model_title
|
self.model_title = model_title
|
||||||
if not self.model_title and self.model_class and hasattr(self.model_class, 'get_model_title'):
|
if not self.model_title and self.model_class and hasattr(self.model_class, 'get_model_title'):
|
||||||
|
@ -224,15 +251,13 @@ class Grid:
|
||||||
if not self.model_title_plural:
|
if not self.model_title_plural:
|
||||||
self.model_title_plural = '{}s'.format(self.model_title)
|
self.model_title_plural = '{}s'.format(self.model_title)
|
||||||
|
|
||||||
|
self.width = width
|
||||||
self.enums = enums or {}
|
self.enums = enums or {}
|
||||||
|
|
||||||
self.labels = labels or {}
|
|
||||||
self.assume_local_times = assume_local_times
|
self.assume_local_times = assume_local_times
|
||||||
self.renderers = self.make_default_renderers(renderers or {})
|
self.renderers = self.make_default_renderers(self.renderers)
|
||||||
self.raw_renderers = raw_renderers or {}
|
self.raw_renderers = raw_renderers or {}
|
||||||
self.invisible = invisible or []
|
self.invisible = invisible or []
|
||||||
self.extra_row_class = extra_row_class
|
self.extra_row_class = extra_row_class
|
||||||
self.linked_columns = linked_columns or []
|
|
||||||
self.url = url
|
self.url = url
|
||||||
self.joiners = joiners or {}
|
self.joiners = joiners or {}
|
||||||
|
|
||||||
|
@ -263,8 +288,6 @@ class Grid:
|
||||||
|
|
||||||
self.click_handlers = click_handlers or {}
|
self.click_handlers = click_handlers or {}
|
||||||
|
|
||||||
self.main_actions = main_actions or []
|
|
||||||
self.more_actions = more_actions or []
|
|
||||||
self.delete_speedbump = delete_speedbump
|
self.delete_speedbump = delete_speedbump
|
||||||
|
|
||||||
if ajax_data_url:
|
if ajax_data_url:
|
||||||
|
@ -274,29 +297,22 @@ class Grid:
|
||||||
else:
|
else:
|
||||||
self.ajax_data_url = ''
|
self.ajax_data_url = ''
|
||||||
|
|
||||||
# vue_tagname
|
self.main_actions = main_actions or []
|
||||||
self.vue_tagname = vue_tagname
|
if self.main_actions:
|
||||||
if not self.vue_tagname and kwargs.get('component'):
|
warnings.warn("main_actions param is deprecated for Grdi(); "
|
||||||
warnings.warn("component kwarg is deprecated for Grid(); "
|
"please use actions param instead",
|
||||||
"please use vue_tagname param instead",
|
|
||||||
DeprecationWarning, stacklevel=2)
|
DeprecationWarning, stacklevel=2)
|
||||||
self.vue_tagname = kwargs['component']
|
self.actions.extend(self.main_actions)
|
||||||
if not self.vue_tagname:
|
self.more_actions = more_actions or []
|
||||||
self.vue_tagname = 'tailbone-grid'
|
if self.more_actions:
|
||||||
|
warnings.warn("more_actions param is deprecated for Grdi(); "
|
||||||
|
"please use actions param instead",
|
||||||
|
DeprecationWarning, stacklevel=2)
|
||||||
|
self.actions.extend(self.more_actions)
|
||||||
|
|
||||||
self.expose_direct_link = expose_direct_link
|
self.expose_direct_link = expose_direct_link
|
||||||
self._whgrid_kwargs = kwargs
|
self._whgrid_kwargs = kwargs
|
||||||
|
|
||||||
@property
|
|
||||||
def vue_component(self):
|
|
||||||
"""
|
|
||||||
String name for the Vue component, e.g. ``'TailboneGrid'``.
|
|
||||||
|
|
||||||
This is a generated value based on :attr:`vue_tagname`.
|
|
||||||
"""
|
|
||||||
words = self.vue_tagname.split('-')
|
|
||||||
return ''.join([word.capitalize() for word in words])
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def component(self):
|
def component(self):
|
||||||
"""
|
"""
|
||||||
|
@ -317,34 +333,6 @@ class Grid:
|
||||||
DeprecationWarning, stacklevel=2)
|
DeprecationWarning, stacklevel=2)
|
||||||
return self.vue_component
|
return self.vue_component
|
||||||
|
|
||||||
@property
|
|
||||||
def actions(self):
|
|
||||||
""" """
|
|
||||||
actions = []
|
|
||||||
if self.main_actions:
|
|
||||||
actions.extend(self.main_actions)
|
|
||||||
if self.more_actions:
|
|
||||||
actions.extend(self.more_actions)
|
|
||||||
return actions
|
|
||||||
|
|
||||||
def make_columns(self):
|
|
||||||
"""
|
|
||||||
Return a default list of columns, based on :attr:`model_class`.
|
|
||||||
"""
|
|
||||||
if not self.model_class:
|
|
||||||
raise ValueError("Must define model_class to use make_columns()")
|
|
||||||
|
|
||||||
mapper = orm.class_mapper(self.model_class)
|
|
||||||
return [prop.key for prop in mapper.iterate_properties]
|
|
||||||
|
|
||||||
def remove(self, *keys):
|
|
||||||
"""
|
|
||||||
This *removes* some column(s) from the grid, altogether.
|
|
||||||
"""
|
|
||||||
for key in keys:
|
|
||||||
if key in self.columns:
|
|
||||||
self.columns.remove(key)
|
|
||||||
|
|
||||||
def hide_column(self, key):
|
def hide_column(self, key):
|
||||||
"""
|
"""
|
||||||
This *removes* a column from the grid, altogether.
|
This *removes* a column from the grid, altogether.
|
||||||
|
@ -377,9 +365,6 @@ class Grid:
|
||||||
if key in self.invisible:
|
if key in self.invisible:
|
||||||
self.invisible.remove(key)
|
self.invisible.remove(key)
|
||||||
|
|
||||||
def append(self, field):
|
|
||||||
self.columns.append(field)
|
|
||||||
|
|
||||||
def insert_before(self, field, newfield):
|
def insert_before(self, field, newfield):
|
||||||
self.columns.insert_before(field, newfield)
|
self.columns.insert_before(field, newfield)
|
||||||
|
|
||||||
|
@ -430,24 +415,22 @@ class Grid:
|
||||||
self.filters.pop(key, None)
|
self.filters.pop(key, None)
|
||||||
|
|
||||||
def set_label(self, key, label, column_only=False):
|
def set_label(self, key, label, column_only=False):
|
||||||
self.labels[key] = label
|
"""
|
||||||
|
Set/override the label for a column.
|
||||||
|
|
||||||
|
This overrides
|
||||||
|
:meth:`~wuttaweb:wuttaweb.grids.base.Grid.set_label()` to add
|
||||||
|
the following params:
|
||||||
|
|
||||||
|
:param column_only: Boolean indicating whether the label
|
||||||
|
should be applied *only* to the column header (if
|
||||||
|
``True``), vs. applying also to the filter (if ``False``).
|
||||||
|
"""
|
||||||
|
super().set_label(key, label)
|
||||||
|
|
||||||
if not column_only and key in self.filters:
|
if not column_only and key in self.filters:
|
||||||
self.filters[key].label = label
|
self.filters[key].label = label
|
||||||
|
|
||||||
def get_label(self, key):
|
|
||||||
"""
|
|
||||||
Returns the label text for given field key.
|
|
||||||
"""
|
|
||||||
return self.labels.get(key, prettify(key))
|
|
||||||
|
|
||||||
def set_link(self, key, link=True):
|
|
||||||
if link:
|
|
||||||
if key not in self.linked_columns:
|
|
||||||
self.linked_columns.append(key)
|
|
||||||
else: # unlink
|
|
||||||
if self.linked_columns and key in self.linked_columns:
|
|
||||||
self.linked_columns.remove(key)
|
|
||||||
|
|
||||||
def set_click_handler(self, key, handler):
|
def set_click_handler(self, key, handler):
|
||||||
if handler:
|
if handler:
|
||||||
self.click_handlers[key] = handler
|
self.click_handlers[key] = handler
|
||||||
|
@ -457,9 +440,6 @@ class Grid:
|
||||||
def has_click_handler(self, key):
|
def has_click_handler(self, key):
|
||||||
return key in self.click_handlers
|
return key in self.click_handlers
|
||||||
|
|
||||||
def set_renderer(self, key, renderer):
|
|
||||||
self.renderers[key] = renderer
|
|
||||||
|
|
||||||
def set_raw_renderer(self, key, renderer):
|
def set_raw_renderer(self, key, renderer):
|
||||||
"""
|
"""
|
||||||
Set or remove the "raw" renderer for the given field.
|
Set or remove the "raw" renderer for the given field.
|
||||||
|
@ -1450,22 +1430,13 @@ class Grid:
|
||||||
return render(template, context)
|
return render(template, context)
|
||||||
|
|
||||||
def get_view_click_handler(self):
|
def get_view_click_handler(self):
|
||||||
|
""" """
|
||||||
# locate the 'view' action
|
# locate the 'view' action
|
||||||
# TODO: this should be easier, and/or moved elsewhere?
|
# TODO: this should be easier, and/or moved elsewhere?
|
||||||
view = None
|
view = None
|
||||||
for action in self.main_actions:
|
for action in self.actions:
|
||||||
if action.key == 'view':
|
if action.key == 'view':
|
||||||
view = action
|
return action.click_handler
|
||||||
break
|
|
||||||
if not view:
|
|
||||||
for action in self.more_actions:
|
|
||||||
if action.key == 'view':
|
|
||||||
view = action
|
|
||||||
break
|
|
||||||
|
|
||||||
if view:
|
|
||||||
return view.click_handler
|
|
||||||
|
|
||||||
def set_filters_sequence(self, filters, only=False):
|
def set_filters_sequence(self, filters, only=False):
|
||||||
"""
|
"""
|
||||||
|
@ -1561,26 +1532,21 @@ class Grid:
|
||||||
kwargs['form'] = form
|
kwargs['form'] = form
|
||||||
return render(template, kwargs)
|
return render(template, kwargs)
|
||||||
|
|
||||||
def render_actions(self, row, i):
|
def render_actions(self, row, i): # pragma: no cover
|
||||||
"""
|
""" """
|
||||||
Returns the rendered contents of the 'actions' column for a given row.
|
warnings.warn("grid.render_actions() is deprecated!",
|
||||||
"""
|
DeprecationWarning, stacklevel=2)
|
||||||
main_actions = [self.render_action(a, row, i)
|
|
||||||
for a in self.main_actions]
|
actions = [self.render_action(a, row, i)
|
||||||
main_actions = [a for a in main_actions if a]
|
for a in self.actions]
|
||||||
more_actions = [self.render_action(a, row, i)
|
actions = [a for a in actions if a]
|
||||||
for a in self.more_actions]
|
return HTML.literal('').join(actions)
|
||||||
more_actions = [a for a in more_actions if a]
|
|
||||||
if more_actions:
|
def render_action(self, action, row, i): # pragma: no cover
|
||||||
icon = HTML.tag('span', class_='ui-icon ui-icon-carat-1-e')
|
""" """
|
||||||
link = tags.link_to("More" + icon, '#', class_='more')
|
warnings.warn("grid.render_action() is deprecated!",
|
||||||
main_actions.append(HTML.literal(' ') + link + HTML.tag('div', class_='more', c=more_actions))
|
DeprecationWarning, stacklevel=2)
|
||||||
return HTML.literal('').join(main_actions)
|
|
||||||
|
|
||||||
def render_action(self, action, row, i):
|
|
||||||
"""
|
|
||||||
Renders an action menu item (link) for the given row.
|
|
||||||
"""
|
|
||||||
url = action.get_url(row, i)
|
url = action.get_url(row, i)
|
||||||
if url:
|
if url:
|
||||||
kwargs = {'class_': action.key, 'target': action.target}
|
kwargs = {'class_': action.key, 'target': action.target}
|
||||||
|
@ -1786,21 +1752,10 @@ class Grid:
|
||||||
Pre-generate all action URLs for the given data row. Meant for use
|
Pre-generate all action URLs for the given data row. Meant for use
|
||||||
with client-side table, since we can't generate URLs from JS.
|
with client-side table, since we can't generate URLs from JS.
|
||||||
"""
|
"""
|
||||||
for action in (self.main_actions + self.more_actions):
|
for action in self.actions:
|
||||||
url = action.get_url(rowobj, i)
|
url = action.get_url(rowobj, i)
|
||||||
row['_action_url_{}'.format(action.key)] = url
|
row['_action_url_{}'.format(action.key)] = url
|
||||||
|
|
||||||
def is_linked(self, name):
|
|
||||||
"""
|
|
||||||
Should return ``True`` if the given column name is configured to be
|
|
||||||
"linked" (i.e. table cell should contain a link to "view object"),
|
|
||||||
otherwise ``False``.
|
|
||||||
"""
|
|
||||||
if self.linked_columns:
|
|
||||||
if name in self.linked_columns:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class GridAction(WuttaGridAction):
|
class GridAction(WuttaGridAction):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -186,7 +186,9 @@ class BatchMasterView(MasterView):
|
||||||
breakdown = self.make_status_breakdown(batch)
|
breakdown = self.make_status_breakdown(batch)
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory('batch_row_status_breakdown', [],
|
g = factory(self.request,
|
||||||
|
key='batch_row_status_breakdown',
|
||||||
|
data=[],
|
||||||
columns=['title', 'count'])
|
columns=['title', 'count'])
|
||||||
g.set_click_handler('title', "autoFilterStatus(props.row)")
|
g.set_click_handler('title', "autoFilterStatus(props.row)")
|
||||||
kwargs['status_breakdown_data'] = breakdown
|
kwargs['status_breakdown_data'] = breakdown
|
||||||
|
@ -693,7 +695,7 @@ class BatchMasterView(MasterView):
|
||||||
batch = self.get_instance()
|
batch = self.get_instance()
|
||||||
|
|
||||||
# TODO: most of this logic is copied from MasterView, should refactor/merge somehow...
|
# TODO: most of this logic is copied from MasterView, should refactor/merge somehow...
|
||||||
if 'main_actions' not in kwargs:
|
if 'actions' not in kwargs:
|
||||||
actions = []
|
actions = []
|
||||||
|
|
||||||
# view action
|
# view action
|
||||||
|
@ -714,7 +716,7 @@ class BatchMasterView(MasterView):
|
||||||
actions.append(self.make_action('delete', icon='trash', url=self.row_delete_action_url))
|
actions.append(self.make_action('delete', icon='trash', url=self.row_delete_action_url))
|
||||||
kwargs.setdefault('delete_speedbump', self.rows_deletable_speedbump)
|
kwargs.setdefault('delete_speedbump', self.rows_deletable_speedbump)
|
||||||
|
|
||||||
kwargs['main_actions'] = actions
|
kwargs['actions'] = actions
|
||||||
|
|
||||||
return super().make_row_grid_kwargs(**kwargs)
|
return super().make_row_grid_kwargs(**kwargs)
|
||||||
|
|
||||||
|
|
|
@ -195,6 +195,7 @@ class POSBatchView(BatchMasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
|
self.request,
|
||||||
key=f'{route_prefix}.taxes',
|
key=f'{route_prefix}.taxes',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
|
|
|
@ -208,8 +208,7 @@ class CustomerView(MasterView):
|
||||||
url = lambda r, i: self.request.route_url(
|
url = lambda r, i: self.request.route_url(
|
||||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||||
# nb. insert to slot 1, just after normal View action
|
# nb. insert to slot 1, just after normal View action
|
||||||
g.main_actions.insert(1, self.make_action(
|
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||||
'view_raw', url=url, icon='eye'))
|
|
||||||
|
|
||||||
g.set_link('name')
|
g.set_link('name')
|
||||||
g.set_link('person')
|
g.set_link('person')
|
||||||
|
@ -471,7 +470,8 @@ class CustomerView(MasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.people'.format(route_prefix),
|
self.request,
|
||||||
|
key=f'{route_prefix}.people',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'shopper_number',
|
'shopper_number',
|
||||||
|
@ -500,7 +500,8 @@ class CustomerView(MasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.people'.format(route_prefix),
|
self.request,
|
||||||
|
key=f'{route_prefix}.people',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'full_name',
|
'full_name',
|
||||||
|
@ -512,11 +513,11 @@ class CustomerView(MasterView):
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.request.has_perm('people.view'):
|
if self.request.has_perm('people.view'):
|
||||||
g.main_actions.append(self.make_action('view', icon='eye'))
|
g.actions.append(self.make_action('view', icon='eye'))
|
||||||
if self.request.has_perm('people.edit'):
|
if self.request.has_perm('people.edit'):
|
||||||
g.main_actions.append(self.make_action('edit', icon='edit'))
|
g.actions.append(self.make_action('edit', icon='edit'))
|
||||||
if self.people_detachable and self.has_perm('detach_person'):
|
if self.people_detachable and self.has_perm('detach_person'):
|
||||||
g.main_actions.append(self.make_action('detach', icon='minus-circle',
|
g.actions.append(self.make_action('detach', icon='minus-circle',
|
||||||
link_class='has-text-warning',
|
link_class='has-text-warning',
|
||||||
click_handler="$emit('detach-person', props.row._action_url_detach)"))
|
click_handler="$emit('detach-person', props.row._action_url_detach)"))
|
||||||
|
|
||||||
|
|
|
@ -385,6 +385,7 @@ class CustomerOrderItemView(MasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
|
self.request,
|
||||||
key=f'{route_prefix}.events',
|
key=f'{route_prefix}.events',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2023 Lance Edgar
|
# Copyright © 2010-2024 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -29,13 +29,12 @@ import logging
|
||||||
|
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db.model import CustomerOrder, CustomerOrderItem
|
||||||
from rattail.util import pretty_quantity, simple_error
|
from rattail.util import simple_error
|
||||||
from rattail.batch import get_batch_handler
|
from rattail.batch import get_batch_handler
|
||||||
|
|
||||||
from webhelpers2.html import tags, HTML
|
from webhelpers2.html import tags, HTML
|
||||||
|
|
||||||
from tailbone.db import Session
|
|
||||||
from tailbone.views import MasterView
|
from tailbone.views import MasterView
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ class CustomerOrderView(MasterView):
|
||||||
"""
|
"""
|
||||||
Master view for customer orders
|
Master view for customer orders
|
||||||
"""
|
"""
|
||||||
model_class = model.CustomerOrder
|
model_class = CustomerOrder
|
||||||
route_prefix = 'custorders'
|
route_prefix = 'custorders'
|
||||||
editable = False
|
editable = False
|
||||||
configurable = True
|
configurable = True
|
||||||
|
@ -80,7 +79,7 @@ class CustomerOrderView(MasterView):
|
||||||
]
|
]
|
||||||
|
|
||||||
has_rows = True
|
has_rows = True
|
||||||
model_row_class = model.CustomerOrderItem
|
model_row_class = CustomerOrderItem
|
||||||
rows_viewable = False
|
rows_viewable = False
|
||||||
|
|
||||||
row_labels = {
|
row_labels = {
|
||||||
|
@ -116,15 +115,17 @@ class CustomerOrderView(MasterView):
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
super(CustomerOrderView, self).__init__(request)
|
super().__init__(request)
|
||||||
self.batch_handler = self.get_batch_handler()
|
self.batch_handler = self.get_batch_handler()
|
||||||
|
|
||||||
def query(self, session):
|
def query(self, session):
|
||||||
|
model = self.app.model
|
||||||
return session.query(model.CustomerOrder)\
|
return session.query(model.CustomerOrder)\
|
||||||
.options(orm.joinedload(model.CustomerOrder.customer))
|
.options(orm.joinedload(model.CustomerOrder.customer))
|
||||||
|
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super().configure_grid(g)
|
super().configure_grid(g)
|
||||||
|
model = self.app.model
|
||||||
|
|
||||||
# id
|
# id
|
||||||
g.set_link('id')
|
g.set_link('id')
|
||||||
|
@ -163,7 +164,7 @@ class CustomerOrderView(MasterView):
|
||||||
return f"#{order.id} for {order.customer or order.person}"
|
return f"#{order.id} for {order.customer or order.person}"
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(CustomerOrderView, self).configure_form(f)
|
super().configure_form(f)
|
||||||
order = f.model_instance
|
order = f.model_instance
|
||||||
|
|
||||||
f.set_readonly('id')
|
f.set_readonly('id')
|
||||||
|
@ -233,6 +234,7 @@ class CustomerOrderView(MasterView):
|
||||||
class_='has-background-warning')
|
class_='has-background-warning')
|
||||||
|
|
||||||
def get_row_data(self, order):
|
def get_row_data(self, order):
|
||||||
|
model = self.app.model
|
||||||
return self.Session.query(model.CustomerOrderItem)\
|
return self.Session.query(model.CustomerOrderItem)\
|
||||||
.filter(model.CustomerOrderItem.order == order)
|
.filter(model.CustomerOrderItem.order == order)
|
||||||
|
|
||||||
|
@ -240,11 +242,13 @@ class CustomerOrderView(MasterView):
|
||||||
return item.order
|
return item.order
|
||||||
|
|
||||||
def make_row_grid_kwargs(self, **kwargs):
|
def make_row_grid_kwargs(self, **kwargs):
|
||||||
kwargs = super(CustomerOrderView, self).make_row_grid_kwargs(**kwargs)
|
kwargs = super().make_row_grid_kwargs(**kwargs)
|
||||||
|
|
||||||
assert not kwargs['main_actions']
|
actions = kwargs.get('actions', [])
|
||||||
kwargs['main_actions'].append(
|
if not actions:
|
||||||
self.make_action('view', icon='eye', url=self.row_view_action_url))
|
actions.append(self.make_action('view', icon='eye',
|
||||||
|
url=self.row_view_action_url))
|
||||||
|
kwargs['actions'] = actions
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
@ -253,7 +257,7 @@ class CustomerOrderView(MasterView):
|
||||||
return self.request.route_url('custorders.items.view', uuid=item.uuid)
|
return self.request.route_url('custorders.items.view', uuid=item.uuid)
|
||||||
|
|
||||||
def configure_row_grid(self, g):
|
def configure_row_grid(self, g):
|
||||||
super(CustomerOrderView, self).configure_row_grid(g)
|
super().configure_row_grid(g)
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
handler = app.get_batch_handler(
|
handler = app.get_batch_handler(
|
||||||
'custorder',
|
'custorder',
|
||||||
|
@ -423,6 +427,7 @@ class CustomerOrderView(MasterView):
|
||||||
if not user:
|
if not user:
|
||||||
raise RuntimeError("this feature requires a user to be logged in")
|
raise RuntimeError("this feature requires a user to be logged in")
|
||||||
|
|
||||||
|
model = self.app.model
|
||||||
try:
|
try:
|
||||||
# there should be at most *one* new batch per user
|
# there should be at most *one* new batch per user
|
||||||
batch = self.Session.query(model.CustomerOrderBatch)\
|
batch = self.Session.query(model.CustomerOrderBatch)\
|
||||||
|
@ -488,6 +493,7 @@ class CustomerOrderView(MasterView):
|
||||||
if not uuid:
|
if not uuid:
|
||||||
return {'error': "Must specify a customer UUID"}
|
return {'error': "Must specify a customer UUID"}
|
||||||
|
|
||||||
|
model = self.app.model
|
||||||
customer = self.Session.get(model.Customer, uuid)
|
customer = self.Session.get(model.Customer, uuid)
|
||||||
if not customer:
|
if not customer:
|
||||||
return {'error': "Customer not found"}
|
return {'error': "Customer not found"}
|
||||||
|
@ -508,6 +514,7 @@ class CustomerOrderView(MasterView):
|
||||||
return info
|
return info
|
||||||
|
|
||||||
def assign_contact(self, batch, data):
|
def assign_contact(self, batch, data):
|
||||||
|
model = self.app.model
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
# this will either be a Person or Customer UUID
|
# this will either be a Person or Customer UUID
|
||||||
|
@ -662,6 +669,7 @@ class CustomerOrderView(MasterView):
|
||||||
if not uuid:
|
if not uuid:
|
||||||
return {'error': "Must specify a product UUID"}
|
return {'error': "Must specify a product UUID"}
|
||||||
|
|
||||||
|
model = self.app.model
|
||||||
product = self.Session.get(model.Product, uuid)
|
product = self.Session.get(model.Product, uuid)
|
||||||
if not product:
|
if not product:
|
||||||
return {'error': "Product not found"}
|
return {'error': "Product not found"}
|
||||||
|
@ -725,8 +733,7 @@ class CustomerOrderView(MasterView):
|
||||||
return app.render_currency(obj.unit_price)
|
return app.render_currency(obj.unit_price)
|
||||||
|
|
||||||
def normalize_row(self, row):
|
def normalize_row(self, row):
|
||||||
app = self.get_rattail_app()
|
products_handler = self.app.get_products_handler()
|
||||||
products_handler = app.get_products_handler()
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'uuid': row.uuid,
|
'uuid': row.uuid,
|
||||||
|
@ -742,20 +749,20 @@ class CustomerOrderView(MasterView):
|
||||||
'product_size': row.product_size,
|
'product_size': row.product_size,
|
||||||
'product_weighed': row.product_weighed,
|
'product_weighed': row.product_weighed,
|
||||||
|
|
||||||
'case_quantity': pretty_quantity(row.case_quantity),
|
'case_quantity': self.app.render_quantity(row.case_quantity),
|
||||||
'cases_ordered': pretty_quantity(row.cases_ordered),
|
'cases_ordered': self.app.render_quantity(row.cases_ordered),
|
||||||
'units_ordered': pretty_quantity(row.units_ordered),
|
'units_ordered': self.app.render_quantity(row.units_ordered),
|
||||||
'order_quantity': pretty_quantity(row.order_quantity),
|
'order_quantity': self.app.render_quantity(row.order_quantity),
|
||||||
'order_uom': row.order_uom,
|
'order_uom': row.order_uom,
|
||||||
'order_uom_choices': self.uom_choices_for_row(row),
|
'order_uom_choices': self.uom_choices_for_row(row),
|
||||||
'discount_percent': pretty_quantity(row.discount_percent),
|
'discount_percent': self.app.render_quantity(row.discount_percent),
|
||||||
|
|
||||||
'department_display': row.department_name,
|
'department_display': row.department_name,
|
||||||
|
|
||||||
'unit_price': float(row.unit_price) if row.unit_price is not None else None,
|
'unit_price': float(row.unit_price) if row.unit_price is not None else None,
|
||||||
'unit_price_display': self.get_unit_price_display(row),
|
'unit_price_display': self.get_unit_price_display(row),
|
||||||
'total_price': float(row.total_price) if row.total_price is not None else None,
|
'total_price': float(row.total_price) if row.total_price is not None else None,
|
||||||
'total_price_display': app.render_currency(row.total_price),
|
'total_price_display': self.app.render_currency(row.total_price),
|
||||||
|
|
||||||
'status_code': row.status_code,
|
'status_code': row.status_code,
|
||||||
'status_text': row.status_text,
|
'status_text': row.status_text,
|
||||||
|
@ -763,15 +770,15 @@ class CustomerOrderView(MasterView):
|
||||||
|
|
||||||
if row.unit_regular_price:
|
if row.unit_regular_price:
|
||||||
data['unit_regular_price'] = float(row.unit_regular_price)
|
data['unit_regular_price'] = float(row.unit_regular_price)
|
||||||
data['unit_regular_price_display'] = app.render_currency(row.unit_regular_price)
|
data['unit_regular_price_display'] = self.app.render_currency(row.unit_regular_price)
|
||||||
|
|
||||||
if row.unit_sale_price:
|
if row.unit_sale_price:
|
||||||
data['unit_sale_price'] = float(row.unit_sale_price)
|
data['unit_sale_price'] = float(row.unit_sale_price)
|
||||||
data['unit_sale_price_display'] = app.render_currency(row.unit_sale_price)
|
data['unit_sale_price_display'] = self.app.render_currency(row.unit_sale_price)
|
||||||
if row.sale_ends:
|
if row.sale_ends:
|
||||||
sale_ends = app.localtime(row.sale_ends, from_utc=True).date()
|
sale_ends = self.app.localtime(row.sale_ends, from_utc=True).date()
|
||||||
data['sale_ends'] = str(sale_ends)
|
data['sale_ends'] = str(sale_ends)
|
||||||
data['sale_ends_display'] = app.render_date(sale_ends)
|
data['sale_ends_display'] = self.app.render_date(sale_ends)
|
||||||
|
|
||||||
if row.unit_sale_price and row.unit_price == row.unit_sale_price:
|
if row.unit_sale_price and row.unit_price == row.unit_sale_price:
|
||||||
data['pricing_reflects_sale'] = True
|
data['pricing_reflects_sale'] = True
|
||||||
|
@ -808,12 +815,12 @@ class CustomerOrderView(MasterView):
|
||||||
|
|
||||||
case_price = self.batch_handler.get_case_price_for_row(row)
|
case_price = self.batch_handler.get_case_price_for_row(row)
|
||||||
data['case_price'] = float(case_price) if case_price is not None else None
|
data['case_price'] = float(case_price) if case_price is not None else None
|
||||||
data['case_price_display'] = app.render_currency(case_price)
|
data['case_price_display'] = self.app.render_currency(case_price)
|
||||||
|
|
||||||
if self.batch_handler.product_price_may_be_questionable():
|
if self.batch_handler.product_price_may_be_questionable():
|
||||||
data['price_needs_confirmation'] = row.price_needs_confirmation
|
data['price_needs_confirmation'] = row.price_needs_confirmation
|
||||||
|
|
||||||
key = app.get_product_key_field()
|
key = self.app.get_product_key_field()
|
||||||
if key == 'upc':
|
if key == 'upc':
|
||||||
data['product_key'] = data['product_upc_pretty']
|
data['product_key'] = data['product_upc_pretty']
|
||||||
elif key == 'item_id':
|
elif key == 'item_id':
|
||||||
|
@ -837,7 +844,7 @@ class CustomerOrderView(MasterView):
|
||||||
case_qty = unit_qty = '??'
|
case_qty = unit_qty = '??'
|
||||||
else:
|
else:
|
||||||
case_qty = data['case_quantity']
|
case_qty = data['case_quantity']
|
||||||
unit_qty = pretty_quantity(row.order_quantity * row.case_quantity)
|
unit_qty = self.app.render_quantity(row.order_quantity * row.case_quantity)
|
||||||
data.update({
|
data.update({
|
||||||
'order_quantity_display': "{} {} (× {} {} = {} {})".format(
|
'order_quantity_display': "{} {} (× {} {} = {} {})".format(
|
||||||
data['order_quantity'],
|
data['order_quantity'],
|
||||||
|
@ -850,14 +857,14 @@ class CustomerOrderView(MasterView):
|
||||||
else:
|
else:
|
||||||
data.update({
|
data.update({
|
||||||
'order_quantity_display': "{} {}".format(
|
'order_quantity_display': "{} {}".format(
|
||||||
pretty_quantity(row.order_quantity),
|
self.app.render_quantity(row.order_quantity),
|
||||||
self.enum.UNIT_OF_MEASURE[unit_uom]),
|
self.enum.UNIT_OF_MEASURE[unit_uom]),
|
||||||
})
|
})
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def add_item(self, batch, data):
|
def add_item(self, batch, data):
|
||||||
app = self.get_rattail_app()
|
model = self.app.model
|
||||||
|
|
||||||
order_quantity = decimal.Decimal(data.get('order_quantity') or '0')
|
order_quantity = decimal.Decimal(data.get('order_quantity') or '0')
|
||||||
order_uom = data.get('order_uom')
|
order_uom = data.get('order_uom')
|
||||||
|
@ -888,7 +895,7 @@ class CustomerOrderView(MasterView):
|
||||||
pending_info = dict(data['pending_product'])
|
pending_info = dict(data['pending_product'])
|
||||||
|
|
||||||
if 'upc' in pending_info:
|
if 'upc' in pending_info:
|
||||||
pending_info['upc'] = app.make_gpc(pending_info['upc'])
|
pending_info['upc'] = self.app.make_gpc(pending_info['upc'])
|
||||||
|
|
||||||
for field in ('unit_cost', 'regular_price_amount', 'case_size'):
|
for field in ('unit_cost', 'regular_price_amount', 'case_size'):
|
||||||
if field in pending_info:
|
if field in pending_info:
|
||||||
|
@ -917,6 +924,7 @@ class CustomerOrderView(MasterView):
|
||||||
if not uuid:
|
if not uuid:
|
||||||
return {'error': "Must specify a row UUID"}
|
return {'error': "Must specify a row UUID"}
|
||||||
|
|
||||||
|
model = self.app.model
|
||||||
row = self.Session.get(model.CustomerOrderBatchRow, uuid)
|
row = self.Session.get(model.CustomerOrderBatchRow, uuid)
|
||||||
if not row:
|
if not row:
|
||||||
return {'error': "Row not found"}
|
return {'error': "Row not found"}
|
||||||
|
@ -975,6 +983,7 @@ class CustomerOrderView(MasterView):
|
||||||
if not uuid:
|
if not uuid:
|
||||||
return {'error': "Must specify a row UUID"}
|
return {'error': "Must specify a row UUID"}
|
||||||
|
|
||||||
|
model = self.app.model
|
||||||
row = self.Session.get(model.CustomerOrderBatchRow, uuid)
|
row = self.Session.get(model.CustomerOrderBatchRow, uuid)
|
||||||
if not row:
|
if not row:
|
||||||
return {'error': "Row not found"}
|
return {'error': "Row not found"}
|
||||||
|
|
|
@ -128,8 +128,8 @@ class DepartmentView(MasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.employees'.format(route_prefix),
|
self.request,
|
||||||
request=self.request,
|
key=f'{route_prefix}.employees',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'first_name',
|
'first_name',
|
||||||
|
@ -140,9 +140,9 @@ class DepartmentView(MasterView):
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.request.has_perm('employees.view'):
|
if self.request.has_perm('employees.view'):
|
||||||
g.main_actions.append(self.make_action('view', icon='eye'))
|
g.actions.append(self.make_action('view', icon='eye'))
|
||||||
if self.request.has_perm('employees.edit'):
|
if self.request.has_perm('employees.edit'):
|
||||||
g.main_actions.append(self.make_action('edit', icon='edit'))
|
g.actions.append(self.make_action('edit', icon='edit'))
|
||||||
|
|
||||||
return HTML.literal(
|
return HTML.literal(
|
||||||
g.render_table_element(data_prop='employeesData'))
|
g.render_table_element(data_prop='employeesData'))
|
||||||
|
|
|
@ -141,7 +141,7 @@ class EmailSettingView(MasterView):
|
||||||
|
|
||||||
# toggle hidden
|
# toggle hidden
|
||||||
if self.has_perm('configure'):
|
if self.has_perm('configure'):
|
||||||
g.main_actions.append(
|
g.actions.append(
|
||||||
self.make_action('toggle_hidden', url='#', icon='ban',
|
self.make_action('toggle_hidden', url='#', icon='ban',
|
||||||
click_handler='toggleHidden(props.row)',
|
click_handler='toggleHidden(props.row)',
|
||||||
factory=ToggleHidden))
|
factory=ToggleHidden))
|
||||||
|
|
|
@ -167,8 +167,7 @@ class EmployeeView(MasterView):
|
||||||
url = lambda r, i: self.request.route_url(
|
url = lambda r, i: self.request.route_url(
|
||||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||||
# nb. insert to slot 1, just after normal View action
|
# nb. insert to slot 1, just after normal View action
|
||||||
g.main_actions.insert(1, self.make_action(
|
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||||
'view_raw', url=url, icon='eye'))
|
|
||||||
|
|
||||||
def default_view_url(self):
|
def default_view_url(self):
|
||||||
if (self.request.has_perm('people.view_profile')
|
if (self.request.has_perm('people.view_profile')
|
||||||
|
|
|
@ -392,9 +392,8 @@ class MasterView(View):
|
||||||
if columns is None:
|
if columns is None:
|
||||||
columns = self.get_grid_columns()
|
columns = self.get_grid_columns()
|
||||||
|
|
||||||
kwargs.setdefault('request', self.request)
|
|
||||||
kwargs = self.make_grid_kwargs(**kwargs)
|
kwargs = self.make_grid_kwargs(**kwargs)
|
||||||
grid = factory(key, data, columns, **kwargs)
|
grid = factory(self.request, key=key, data=data, columns=columns, **kwargs)
|
||||||
self.configure_grid(grid)
|
self.configure_grid(grid)
|
||||||
grid.load_settings()
|
grid.load_settings()
|
||||||
return grid
|
return grid
|
||||||
|
@ -454,10 +453,26 @@ class MasterView(View):
|
||||||
if self.sortable or self.pageable or self.filterable:
|
if self.sortable or self.pageable or self.filterable:
|
||||||
defaults['expose_direct_link'] = True
|
defaults['expose_direct_link'] = True
|
||||||
|
|
||||||
if 'main_actions' not in kwargs and 'more_actions' not in kwargs:
|
if 'actions' not in kwargs:
|
||||||
main, more = self.get_grid_actions()
|
|
||||||
defaults['main_actions'] = main
|
if 'main_actions' in kwargs:
|
||||||
defaults['more_actions'] = more
|
warnings.warn("main_actions param is deprecated for make_grid_kwargs(); "
|
||||||
|
"please use actions param instead",
|
||||||
|
DeprecationWarning, stacklevel=2)
|
||||||
|
main = kwargs.pop('main_actions')
|
||||||
|
else:
|
||||||
|
main = self.get_main_actions()
|
||||||
|
|
||||||
|
if 'more_actions' in kwargs:
|
||||||
|
warnings.warn("more_actions param is deprecated for make_grid_kwargs(); "
|
||||||
|
"please use actions param instead",
|
||||||
|
DeprecationWarning, stacklevel=2)
|
||||||
|
more = kwargs.pop('more_actions')
|
||||||
|
else:
|
||||||
|
more = self.get_more_actions()
|
||||||
|
|
||||||
|
defaults['actions'] = main + more
|
||||||
|
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
return defaults
|
return defaults
|
||||||
|
|
||||||
|
@ -548,9 +563,8 @@ class MasterView(View):
|
||||||
if columns is None:
|
if columns is None:
|
||||||
columns = self.get_row_grid_columns()
|
columns = self.get_row_grid_columns()
|
||||||
|
|
||||||
kwargs.setdefault('request', self.request)
|
|
||||||
kwargs = self.make_row_grid_kwargs(**kwargs)
|
kwargs = self.make_row_grid_kwargs(**kwargs)
|
||||||
grid = factory(key, data, columns, **kwargs)
|
grid = factory(self.request, key=key, data=data, columns=columns, **kwargs)
|
||||||
self.configure_row_grid(grid)
|
self.configure_row_grid(grid)
|
||||||
grid.load_settings()
|
grid.load_settings()
|
||||||
return grid
|
return grid
|
||||||
|
@ -577,7 +591,7 @@ class MasterView(View):
|
||||||
if self.rows_default_pagesize:
|
if self.rows_default_pagesize:
|
||||||
defaults['default_pagesize'] = self.rows_default_pagesize
|
defaults['default_pagesize'] = self.rows_default_pagesize
|
||||||
|
|
||||||
if self.has_rows and 'main_actions' not in defaults:
|
if self.has_rows and 'actions' not in defaults:
|
||||||
actions = []
|
actions = []
|
||||||
|
|
||||||
# view action
|
# view action
|
||||||
|
@ -595,7 +609,7 @@ class MasterView(View):
|
||||||
actions.append(self.make_action('delete', icon='trash', url=self.row_delete_action_url))
|
actions.append(self.make_action('delete', icon='trash', url=self.row_delete_action_url))
|
||||||
defaults['delete_speedbump'] = self.rows_deletable_speedbump
|
defaults['delete_speedbump'] = self.rows_deletable_speedbump
|
||||||
|
|
||||||
defaults['main_actions'] = actions
|
defaults['actions'] = actions
|
||||||
|
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
return defaults
|
return defaults
|
||||||
|
@ -630,9 +644,8 @@ class MasterView(View):
|
||||||
if columns is None:
|
if columns is None:
|
||||||
columns = self.get_version_grid_columns()
|
columns = self.get_version_grid_columns()
|
||||||
|
|
||||||
kwargs.setdefault('request', self.request)
|
|
||||||
kwargs = self.make_version_grid_kwargs(**kwargs)
|
kwargs = self.make_version_grid_kwargs(**kwargs)
|
||||||
grid = factory(key, data, columns, **kwargs)
|
grid = factory(self.request, key=key, data=data, columns=columns, **kwargs)
|
||||||
self.configure_version_grid(grid)
|
self.configure_version_grid(grid)
|
||||||
grid.load_settings()
|
grid.load_settings()
|
||||||
return grid
|
return grid
|
||||||
|
@ -661,9 +674,9 @@ class MasterView(View):
|
||||||
'pageable': True,
|
'pageable': True,
|
||||||
'url': lambda txn: self.request.route_url(route, uuid=instance.uuid, txnid=txn.id),
|
'url': lambda txn: self.request.route_url(route, uuid=instance.uuid, txnid=txn.id),
|
||||||
}
|
}
|
||||||
if 'main_actions' not in kwargs:
|
if 'actions' not in kwargs:
|
||||||
url = lambda txn, i: self.request.route_url(route, uuid=instance.uuid, txnid=txn.id)
|
url = lambda txn, i: self.request.route_url(route, uuid=instance.uuid, txnid=txn.id)
|
||||||
defaults['main_actions'] = [
|
defaults['actions'] = [
|
||||||
self.make_action('view', icon='eye', url=url),
|
self.make_action('view', icon='eye', url=url),
|
||||||
]
|
]
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
|
@ -1372,7 +1385,7 @@ class MasterView(View):
|
||||||
'sortable': True,
|
'sortable': True,
|
||||||
'default_sortkey': 'changed',
|
'default_sortkey': 'changed',
|
||||||
'default_sortdir': 'desc',
|
'default_sortdir': 'desc',
|
||||||
'main_actions': [
|
'actions': [
|
||||||
self.make_action('view', icon='eye', url='#',
|
self.make_action('view', icon='eye', url='#',
|
||||||
click_handler='viewRevision(props.row)'),
|
click_handler='viewRevision(props.row)'),
|
||||||
self.make_action('view_separate', url=row_url, target='_blank',
|
self.make_action('view_separate', url=row_url, target='_blank',
|
||||||
|
@ -3111,6 +3124,11 @@ class MasterView(View):
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def get_grid_actions(self):
|
def get_grid_actions(self):
|
||||||
|
""" """
|
||||||
|
warnings.warn("get_grid_actions() method is deprecated; "
|
||||||
|
"please use get_main_actions() or get_more_actions() instead",
|
||||||
|
DeprecationWarning, stacklevel=2)
|
||||||
|
|
||||||
main, more = self.get_main_actions(), self.get_more_actions()
|
main, more = self.get_main_actions(), self.get_more_actions()
|
||||||
if len(more) == 1:
|
if len(more) == 1:
|
||||||
main, more = main + more, []
|
main, more = main + more, []
|
||||||
|
|
|
@ -229,8 +229,7 @@ class MemberView(MasterView):
|
||||||
url = lambda r, i: self.request.route_url(
|
url = lambda r, i: self.request.route_url(
|
||||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||||
# nb. insert to slot 1, just after normal View action
|
# nb. insert to slot 1, just after normal View action
|
||||||
g.main_actions.insert(1, self.make_action(
|
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||||
'view_raw', url=url, icon='eye'))
|
|
||||||
|
|
||||||
# equity_total
|
# equity_total
|
||||||
# TODO: should make this configurable
|
# TODO: should make this configurable
|
||||||
|
|
|
@ -175,8 +175,7 @@ class PersonView(MasterView):
|
||||||
url = lambda r, i: self.request.route_url(
|
url = lambda r, i: self.request.route_url(
|
||||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||||
# nb. insert to slot 1, just after normal View action
|
# nb. insert to slot 1, just after normal View action
|
||||||
g.main_actions.insert(1, self.make_action(
|
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||||
'view_raw', url=url, icon='eye'))
|
|
||||||
|
|
||||||
g.set_link('display_name')
|
g.set_link('display_name')
|
||||||
g.set_link('first_name')
|
g.set_link('first_name')
|
||||||
|
@ -522,9 +521,9 @@ class PersonView(MasterView):
|
||||||
data = self.profile_transactions_query(person)
|
data = self.profile_transactions_query(person)
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
f'{route_prefix}.profile.transactions.{person.uuid}',
|
self.request,
|
||||||
data,
|
key=f'{route_prefix}.profile.transactions.{person.uuid}',
|
||||||
request=self.request,
|
data=data,
|
||||||
model_class=model.Transaction,
|
model_class=model.Transaction,
|
||||||
ajax_data_url=self.get_action_url('view_profile_transactions', person),
|
ajax_data_url=self.get_action_url('view_profile_transactions', person),
|
||||||
columns=[
|
columns=[
|
||||||
|
@ -552,7 +551,7 @@ class PersonView(MasterView):
|
||||||
if self.request.has_perm('trainwreck.transactions.view'):
|
if self.request.has_perm('trainwreck.transactions.view'):
|
||||||
url = lambda row, i: self.request.route_url('trainwreck.transactions.view',
|
url = lambda row, i: self.request.route_url('trainwreck.transactions.view',
|
||||||
uuid=row.uuid)
|
uuid=row.uuid)
|
||||||
g.main_actions.append(self.make_action('view', icon='eye', url=url))
|
g.actions.append(self.make_action('view', icon='eye', url=url))
|
||||||
g.load_settings()
|
g.load_settings()
|
||||||
|
|
||||||
g.set_enum('system', self.enum.TRAINWRECK_SYSTEM)
|
g.set_enum('system', self.enum.TRAINWRECK_SYSTEM)
|
||||||
|
@ -1413,9 +1412,9 @@ class PersonView(MasterView):
|
||||||
route_prefix = self.get_route_prefix()
|
route_prefix = self.get_route_prefix()
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
'{}.profile.revisions'.format(route_prefix),
|
self.request,
|
||||||
[], # start with empty data!
|
key=f'{route_prefix}.profile.revisions',
|
||||||
request=self.request,
|
data=[], # start with empty data!
|
||||||
columns=[
|
columns=[
|
||||||
'changed',
|
'changed',
|
||||||
'changed_by',
|
'changed_by',
|
||||||
|
@ -1430,7 +1429,7 @@ class PersonView(MasterView):
|
||||||
'changed_by',
|
'changed_by',
|
||||||
'comment',
|
'comment',
|
||||||
],
|
],
|
||||||
main_actions=[
|
actions=[
|
||||||
self.make_action('view', icon='eye', url='#',
|
self.make_action('view', icon='eye', url='#',
|
||||||
click_handler='viewRevision(props.row)'),
|
click_handler='viewRevision(props.row)'),
|
||||||
],
|
],
|
||||||
|
|
|
@ -110,7 +110,7 @@ class PoserReportView(PoserMasterView):
|
||||||
g.set_searchable('description')
|
g.set_searchable('description')
|
||||||
|
|
||||||
if self.request.has_perm('report_output.create'):
|
if self.request.has_perm('report_output.create'):
|
||||||
g.more_actions.append(self.make_action(
|
g.actions.append(self.make_action(
|
||||||
'generate', icon='arrow-circle-right',
|
'generate', icon='arrow-circle-right',
|
||||||
url=self.get_generate_url))
|
url=self.get_generate_url))
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,11 @@ class PrincipalMasterView(MasterView):
|
||||||
def find_by_perm_make_results_grid(self, principals):
|
def find_by_perm_make_results_grid(self, principals):
|
||||||
route_prefix = self.get_route_prefix()
|
route_prefix = self.get_route_prefix()
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(key=f'{route_prefix}.results',
|
g = factory(self.request,
|
||||||
request=self.request,
|
key=f'{route_prefix}.results',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[],
|
columns=[],
|
||||||
main_actions=[
|
actions=[
|
||||||
self.make_action('view', icon='eye',
|
self.make_action('view', icon='eye',
|
||||||
click_handler='navigateTo(props.row._url)'),
|
click_handler='navigateTo(props.row._url)'),
|
||||||
])
|
])
|
||||||
|
|
|
@ -384,7 +384,7 @@ class ProductView(MasterView):
|
||||||
g.set_filter('report_code_name', model.ReportCode.name)
|
g.set_filter('report_code_name', model.ReportCode.name)
|
||||||
|
|
||||||
if self.expose_label_printing and self.has_perm('print_labels'):
|
if self.expose_label_printing and self.has_perm('print_labels'):
|
||||||
g.more_actions.append(self.make_action(
|
g.actions.append(self.make_action(
|
||||||
'print_label', icon='print', url='#',
|
'print_label', icon='print', url='#',
|
||||||
click_handler='quickLabelPrint(props.row)'))
|
click_handler='quickLabelPrint(props.row)'))
|
||||||
|
|
||||||
|
@ -1197,8 +1197,9 @@ class ProductView(MasterView):
|
||||||
|
|
||||||
# regular price
|
# regular price
|
||||||
data = [] # defer fetching until user asks for it
|
data = [] # defer fetching until user asks for it
|
||||||
grid = grids.Grid('products.regular_price_history', data,
|
grid = grids.Grid(self.request,
|
||||||
request=self.request,
|
key='products.regular_price_history',
|
||||||
|
data=data,
|
||||||
columns=[
|
columns=[
|
||||||
'price',
|
'price',
|
||||||
'since',
|
'since',
|
||||||
|
@ -1211,8 +1212,9 @@ class ProductView(MasterView):
|
||||||
|
|
||||||
# current price
|
# current price
|
||||||
data = [] # defer fetching until user asks for it
|
data = [] # defer fetching until user asks for it
|
||||||
grid = grids.Grid('products.current_price_history', data,
|
grid = grids.Grid(self.request,
|
||||||
request=self.request,
|
key='products.current_price_history',
|
||||||
|
data=data,
|
||||||
columns=[
|
columns=[
|
||||||
'price',
|
'price',
|
||||||
'price_type',
|
'price_type',
|
||||||
|
@ -1229,8 +1231,9 @@ class ProductView(MasterView):
|
||||||
|
|
||||||
# suggested price
|
# suggested price
|
||||||
data = [] # defer fetching until user asks for it
|
data = [] # defer fetching until user asks for it
|
||||||
grid = grids.Grid('products.suggested_price_history', data,
|
grid = grids.Grid(self.request,
|
||||||
request=self.request,
|
key='products.suggested_price_history',
|
||||||
|
data=data,
|
||||||
columns=[
|
columns=[
|
||||||
'price',
|
'price',
|
||||||
'since',
|
'since',
|
||||||
|
@ -1243,8 +1246,9 @@ class ProductView(MasterView):
|
||||||
|
|
||||||
# cost history
|
# cost history
|
||||||
data = [] # defer fetching until user asks for it
|
data = [] # defer fetching until user asks for it
|
||||||
grid = grids.Grid('products.cost_history', data,
|
grid = grids.Grid(self.request,
|
||||||
request=self.request,
|
key='products.cost_history',
|
||||||
|
data=data,
|
||||||
columns=[
|
columns=[
|
||||||
'cost',
|
'cost',
|
||||||
'vendor',
|
'vendor',
|
||||||
|
@ -1335,7 +1339,8 @@ class ProductView(MasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.vendor_sources'.format(route_prefix),
|
self.request,
|
||||||
|
key=f'{route_prefix}.vendor_sources',
|
||||||
data=[],
|
data=[],
|
||||||
columns=columns,
|
columns=columns,
|
||||||
labels={
|
labels={
|
||||||
|
@ -1376,7 +1381,8 @@ class ProductView(MasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.lookup_codes'.format(route_prefix),
|
self.request,
|
||||||
|
key=f'{route_prefix}.lookup_codes',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'sequence',
|
'sequence',
|
||||||
|
|
|
@ -793,8 +793,8 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
|
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.row_credits'.format(route_prefix),
|
self.request,
|
||||||
request=self.request,
|
key=f'{route_prefix}.row_credits',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'credit_type',
|
'credit_type',
|
||||||
|
|
|
@ -774,7 +774,9 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
breakdown = self.make_po_vs_invoice_breakdown(batch)
|
breakdown = self.make_po_vs_invoice_breakdown(batch)
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
|
|
||||||
g = factory('batch_po_vs_invoice_breakdown', [],
|
g = factory(self.request,
|
||||||
|
key='batch_po_vs_invoice_breakdown',
|
||||||
|
data=[],
|
||||||
columns=['title', 'count'])
|
columns=['title', 'count'])
|
||||||
g.set_click_handler('title', "autoFilterPoVsInvoice(props.row)")
|
g.set_click_handler('title', "autoFilterPoVsInvoice(props.row)")
|
||||||
kwargs['po_vs_invoice_breakdown_data'] = breakdown
|
kwargs['po_vs_invoice_breakdown_data'] = breakdown
|
||||||
|
@ -1035,10 +1037,12 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
icon='shuffle',
|
icon='shuffle',
|
||||||
label="Transform to Unit",
|
label="Transform to Unit",
|
||||||
url=self.transform_unit_url)
|
url=self.transform_unit_url)
|
||||||
g.more_actions.append(transform)
|
if g.actions and g.actions[-1].key == 'delete':
|
||||||
if g.main_actions and g.main_actions[-1].key == 'delete':
|
delete = g.actions.pop()
|
||||||
delete = g.main_actions.pop()
|
g.actions.append(transform)
|
||||||
g.more_actions.append(delete)
|
g.actions.append(delete)
|
||||||
|
else:
|
||||||
|
g.actions.append(transform)
|
||||||
|
|
||||||
# truck_dump_status
|
# truck_dump_status
|
||||||
if not batch.is_truck_dump_parent():
|
if not batch.is_truck_dump_parent():
|
||||||
|
@ -1111,7 +1115,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
and self.row_editable(row)):
|
and self.row_editable(row)):
|
||||||
|
|
||||||
# add the Un-Declare action
|
# add the Un-Declare action
|
||||||
g.main_actions.append(self.make_action(
|
g.actions.append(self.make_action(
|
||||||
'remove', label="Un-Declare",
|
'remove', label="Un-Declare",
|
||||||
url='#', icon='trash',
|
url='#', icon='trash',
|
||||||
link_class='has-text-danger',
|
link_class='has-text-danger',
|
||||||
|
|
|
@ -308,7 +308,8 @@ class ReportOutputView(ExportMasterView):
|
||||||
route_prefix = self.get_route_prefix()
|
route_prefix = self.get_route_prefix()
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.params'.format(route_prefix),
|
self.request,
|
||||||
|
key=f'{route_prefix}.params',
|
||||||
data=params,
|
data=params,
|
||||||
columns=['key', 'value'],
|
columns=['key', 'value'],
|
||||||
labels={'key': "Name"},
|
labels={'key': "Name"},
|
||||||
|
@ -705,7 +706,10 @@ class ProblemReportView(MasterView):
|
||||||
return ', '.join(recips)
|
return ', '.join(recips)
|
||||||
|
|
||||||
def render_days(self, report_info, field):
|
def render_days(self, report_info, field):
|
||||||
g = self.get_grid_factory()('days', [],
|
factory = self.get_grid_factory()
|
||||||
|
g = factory(self.request,
|
||||||
|
key='days',
|
||||||
|
data=[],
|
||||||
columns=['weekday_name', 'enabled'],
|
columns=['weekday_name', 'enabled'],
|
||||||
labels={'weekday_name': "Weekday"})
|
labels={'weekday_name': "Weekday"})
|
||||||
return HTML.literal(g.render_table_element(data_prop='weekdaysData'))
|
return HTML.literal(g.render_table_element(data_prop='weekdaysData'))
|
||||||
|
|
|
@ -255,8 +255,8 @@ class RoleView(PrincipalMasterView):
|
||||||
permission_prefix = self.get_permission_prefix()
|
permission_prefix = self.get_permission_prefix()
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.users'.format(route_prefix),
|
self.request,
|
||||||
request=self.request,
|
key=f'{route_prefix}.users',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'full_name',
|
'full_name',
|
||||||
|
@ -269,9 +269,9 @@ class RoleView(PrincipalMasterView):
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.request.has_perm('users.view'):
|
if self.request.has_perm('users.view'):
|
||||||
g.main_actions.append(self.make_action('view', icon='eye'))
|
g.actions.append(self.make_action('view', icon='eye'))
|
||||||
if self.request.has_perm('users.edit'):
|
if self.request.has_perm('users.edit'):
|
||||||
g.main_actions.append(self.make_action('edit', icon='edit'))
|
g.actions.append(self.make_action('edit', icon='edit'))
|
||||||
|
|
||||||
return HTML.literal(
|
return HTML.literal(
|
||||||
g.render_table_element(data_prop='usersData'))
|
g.render_table_element(data_prop='usersData'))
|
||||||
|
@ -366,10 +366,11 @@ class RoleView(PrincipalMasterView):
|
||||||
self.make_action('view', icon='zoomin',
|
self.make_action('view', icon='zoomin',
|
||||||
url=lambda r, i: self.request.route_url('users.view', uuid=r.uuid))
|
url=lambda r, i: self.request.route_url('users.view', uuid=r.uuid))
|
||||||
]
|
]
|
||||||
kwargs['users'] = grids.Grid(None, users, ['username', 'active'],
|
kwargs['users'] = grids.Grid(self.request,
|
||||||
request=self.request,
|
data=users,
|
||||||
|
columns=['username', 'active'],
|
||||||
model_class=model.User,
|
model_class=model.User,
|
||||||
main_actions=actions)
|
actions=actions)
|
||||||
else:
|
else:
|
||||||
kwargs['users'] = None
|
kwargs['users'] = None
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,8 @@ class MasterView(views.MasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.probes'.format(route_prefix),
|
self.request,
|
||||||
request=self.request,
|
key=f'{route_prefix}.probes',
|
||||||
data=[],
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'description',
|
'description',
|
||||||
|
@ -96,7 +96,7 @@ class MasterView(views.MasterView):
|
||||||
'critical_temp_max': "Crit. Max",
|
'critical_temp_max': "Crit. Max",
|
||||||
},
|
},
|
||||||
linked_columns=['description'],
|
linked_columns=['description'],
|
||||||
main_actions=actions,
|
actions=actions,
|
||||||
)
|
)
|
||||||
return HTML.literal(
|
return HTML.literal(
|
||||||
g.render_table_element(data_prop='probesData'))
|
g.render_table_element(data_prop='probesData'))
|
||||||
|
|
|
@ -246,10 +246,10 @@ class TransactionView(MasterView):
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
|
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.custorder_xref_markers'.format(route_prefix),
|
self.request,
|
||||||
|
key=f'{route_prefix}.custorder_xref_markers',
|
||||||
data=[],
|
data=[],
|
||||||
columns=['custorder_xref', 'custorder_item_xref'],
|
columns=['custorder_xref', 'custorder_item_xref'])
|
||||||
request=self.request)
|
|
||||||
|
|
||||||
return HTML.literal(
|
return HTML.literal(
|
||||||
g.render_table_element(data_prop='custorderXrefMarkersData'))
|
g.render_table_element(data_prop='custorderXrefMarkersData'))
|
||||||
|
@ -355,11 +355,11 @@ class TransactionView(MasterView):
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
|
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.discounts'.format(route_prefix),
|
self.request,
|
||||||
|
key=f'{route_prefix}.discounts',
|
||||||
data=[],
|
data=[],
|
||||||
columns=['discount_type', 'description', 'amount'],
|
columns=['discount_type', 'description', 'amount'],
|
||||||
labels={'discount_type': "Type"},
|
labels={'discount_type': "Type"})
|
||||||
request=self.request)
|
|
||||||
|
|
||||||
return HTML.literal(
|
return HTML.literal(
|
||||||
g.render_table_element(data_prop='discountsData'))
|
g.render_table_element(data_prop='discountsData'))
|
||||||
|
|
|
@ -44,9 +44,6 @@ class UserView(PrincipalMasterView):
|
||||||
Master view for the User model.
|
Master view for the User model.
|
||||||
"""
|
"""
|
||||||
model_class = User
|
model_class = User
|
||||||
has_rows = True
|
|
||||||
rows_title = "User Events"
|
|
||||||
model_row_class = UserEvent
|
|
||||||
has_versions = True
|
has_versions = True
|
||||||
touchable = True
|
touchable = True
|
||||||
mergeable = True
|
mergeable = True
|
||||||
|
@ -77,6 +74,11 @@ class UserView(PrincipalMasterView):
|
||||||
'permissions',
|
'permissions',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
has_rows = True
|
||||||
|
model_row_class = UserEvent
|
||||||
|
rows_title = "User Events"
|
||||||
|
rows_viewable = False
|
||||||
|
|
||||||
row_grid_columns = [
|
row_grid_columns = [
|
||||||
'type_code',
|
'type_code',
|
||||||
'occurred',
|
'occurred',
|
||||||
|
@ -297,11 +299,11 @@ class UserView(PrincipalMasterView):
|
||||||
|
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
g = factory(
|
g = factory(
|
||||||
request=self.request,
|
self.request,
|
||||||
key='{}.api_tokens'.format(route_prefix),
|
key=f'{route_prefix}.api_tokens',
|
||||||
data=[],
|
data=[],
|
||||||
columns=['description', 'created'],
|
columns=['description', 'created'],
|
||||||
main_actions=[
|
actions=[
|
||||||
self.make_action('delete', icon='trash',
|
self.make_action('delete', icon='trash',
|
||||||
click_handler="$emit('api-token-delete', props.row)")])
|
click_handler="$emit('api-token-delete', props.row)")])
|
||||||
|
|
||||||
|
@ -514,7 +516,6 @@ class UserView(PrincipalMasterView):
|
||||||
g.set_sort_defaults('occurred', 'desc')
|
g.set_sort_defaults('occurred', 'desc')
|
||||||
g.set_enum('type_code', self.enum.USER_EVENT)
|
g.set_enum('type_code', self.enum.USER_EVENT)
|
||||||
g.set_label('type_code', "Event Type")
|
g.set_label('type_code', "Event Type")
|
||||||
g.main_actions = []
|
|
||||||
|
|
||||||
def get_version_child_classes(self):
|
def get_version_child_classes(self):
|
||||||
model = self.model
|
model = self.model
|
||||||
|
|
|
@ -12,9 +12,8 @@ class TestGrid(WebTestCase):
|
||||||
self.setup_web()
|
self.setup_web()
|
||||||
self.config.setdefault('rattail.web.menus.handler_spec', 'tests.util:NullMenuHandler')
|
self.config.setdefault('rattail.web.menus.handler_spec', 'tests.util:NullMenuHandler')
|
||||||
|
|
||||||
def make_grid(self, key, data=[], **kwargs):
|
def make_grid(self, key=None, data=[], **kwargs):
|
||||||
kwargs.setdefault('request', self.request)
|
return mod.Grid(self.request, key=key, data=data, **kwargs)
|
||||||
return mod.Grid(key, data=data, **kwargs)
|
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
grid = self.make_grid('foo')
|
grid = self.make_grid('foo')
|
||||||
|
@ -90,6 +89,50 @@ class TestGrid(WebTestCase):
|
||||||
grid = self.make_grid('foo', main_actions=['foo'], more_actions=['bar'])
|
grid = self.make_grid('foo', main_actions=['foo'], more_actions=['bar'])
|
||||||
self.assertEqual(grid.actions, ['foo', 'bar'])
|
self.assertEqual(grid.actions, ['foo', 'bar'])
|
||||||
|
|
||||||
|
def test_set_label(self):
|
||||||
|
model = self.app.model
|
||||||
|
grid = self.make_grid(model_class=model.Setting)
|
||||||
|
self.assertEqual(grid.labels, {})
|
||||||
|
|
||||||
|
# basic
|
||||||
|
grid.set_label('name', "NAME COL")
|
||||||
|
self.assertEqual(grid.labels['name'], "NAME COL")
|
||||||
|
|
||||||
|
# can replace label
|
||||||
|
grid.set_label('name', "Different")
|
||||||
|
self.assertEqual(grid.labels['name'], "Different")
|
||||||
|
self.assertEqual(grid.get_label('name'), "Different")
|
||||||
|
|
||||||
|
# can update only column, not filter
|
||||||
|
self.assertEqual(grid.labels, {'name': "Different"})
|
||||||
|
self.assertIn('name', grid.filters)
|
||||||
|
self.assertEqual(grid.filters['name'].label, "Different")
|
||||||
|
grid.set_label('name', "COLUMN ONLY", column_only=True)
|
||||||
|
self.assertEqual(grid.get_label('name'), "COLUMN ONLY")
|
||||||
|
self.assertEqual(grid.filters['name'].label, "Different")
|
||||||
|
|
||||||
|
def test_get_view_click_handler(self):
|
||||||
|
model = self.app.model
|
||||||
|
grid = self.make_grid(model_class=model.Setting)
|
||||||
|
|
||||||
|
grid.actions.append(
|
||||||
|
mod.GridAction(self.request, 'view',
|
||||||
|
click_handler='clickHandler(props.row)'))
|
||||||
|
|
||||||
|
handler = grid.get_view_click_handler()
|
||||||
|
self.assertEqual(handler, 'clickHandler(props.row)')
|
||||||
|
|
||||||
|
def test_set_action_urls(self):
|
||||||
|
model = self.app.model
|
||||||
|
grid = self.make_grid(model_class=model.Setting)
|
||||||
|
|
||||||
|
grid.actions.append(
|
||||||
|
mod.GridAction(self.request, 'view', url='/blarg'))
|
||||||
|
|
||||||
|
setting = {'name': 'foo', 'value': 'bar'}
|
||||||
|
grid.set_action_urls(setting, setting, 0)
|
||||||
|
self.assertEqual(setting['_action_url_view'], '/blarg')
|
||||||
|
|
||||||
def test_render_vue_tag(self):
|
def test_render_vue_tag(self):
|
||||||
model = self.app.model
|
model = self.app.model
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue