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 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 tailbone.db import Session
|
||||
from tailbone.util import raw_datetime
|
||||
|
@ -61,7 +61,7 @@ class FieldList(list):
|
|||
self.insert(i + 1, newfield)
|
||||
|
||||
|
||||
class Grid:
|
||||
class Grid(WuttaGrid):
|
||||
"""
|
||||
Core grid class. In sore need of documentation.
|
||||
|
||||
|
@ -186,32 +186,59 @@ class Grid:
|
|||
grid.row_uuid_getter = fake_uuid
|
||||
"""
|
||||
|
||||
def __init__(self, key, data, columns=None, width='auto', request=None,
|
||||
model_class=None, model_title=None, model_title_plural=None,
|
||||
enums={}, labels={}, assume_local_times=False, renderers={}, invisible=[],
|
||||
raw_renderers={},
|
||||
extra_row_class=None, linked_columns=[], url='#',
|
||||
joiners={}, filterable=False, filters={}, use_byte_string_filters=False,
|
||||
searchable={},
|
||||
sortable=False, sorters={}, default_sortkey=None, default_sortdir='asc',
|
||||
pageable=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,
|
||||
vue_tagname=None,
|
||||
expose_direct_link=False,
|
||||
**kwargs):
|
||||
def __init__(
|
||||
self,
|
||||
request,
|
||||
key=None,
|
||||
data=None,
|
||||
width='auto',
|
||||
model_title=None,
|
||||
model_title_plural=None,
|
||||
enums={},
|
||||
assume_local_times=False,
|
||||
invisible=[],
|
||||
raw_renderers={},
|
||||
extra_row_class=None,
|
||||
url='#',
|
||||
joiners={},
|
||||
filterable=False,
|
||||
filters={},
|
||||
use_byte_string_filters=False,
|
||||
searchable={},
|
||||
sortable=False,
|
||||
sorters={},
|
||||
default_sortkey=None,
|
||||
default_sortdir='asc',
|
||||
pageable=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,
|
||||
expose_direct_link=False,
|
||||
**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
|
||||
self.data = data
|
||||
self.columns = FieldList(columns) if columns is not None else None
|
||||
self.width = width
|
||||
self.request = request
|
||||
self.model_class = model_class
|
||||
if self.model_class and self.columns is None:
|
||||
self.columns = self.make_columns()
|
||||
# TODO: pretty sure this should go away?
|
||||
kwargs.setdefault('vue_tagname', 'tailbone-grid')
|
||||
|
||||
kwargs['key'] = key
|
||||
kwargs['data'] = data
|
||||
super().__init__(request, **kwargs)
|
||||
|
||||
self.model_title = 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:
|
||||
self.model_title_plural = '{}s'.format(self.model_title)
|
||||
|
||||
self.width = width
|
||||
self.enums = enums or {}
|
||||
|
||||
self.labels = labels or {}
|
||||
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.invisible = invisible or []
|
||||
self.extra_row_class = extra_row_class
|
||||
self.linked_columns = linked_columns or []
|
||||
self.url = url
|
||||
self.joiners = joiners or {}
|
||||
|
||||
|
@ -263,8 +288,6 @@ class Grid:
|
|||
|
||||
self.click_handlers = click_handlers or {}
|
||||
|
||||
self.main_actions = main_actions or []
|
||||
self.more_actions = more_actions or []
|
||||
self.delete_speedbump = delete_speedbump
|
||||
|
||||
if ajax_data_url:
|
||||
|
@ -274,29 +297,22 @@ class Grid:
|
|||
else:
|
||||
self.ajax_data_url = ''
|
||||
|
||||
# vue_tagname
|
||||
self.vue_tagname = vue_tagname
|
||||
if not self.vue_tagname and kwargs.get('component'):
|
||||
warnings.warn("component kwarg is deprecated for Grid(); "
|
||||
"please use vue_tagname param instead",
|
||||
self.main_actions = main_actions or []
|
||||
if self.main_actions:
|
||||
warnings.warn("main_actions param is deprecated for Grdi(); "
|
||||
"please use actions param instead",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
self.vue_tagname = kwargs['component']
|
||||
if not self.vue_tagname:
|
||||
self.vue_tagname = 'tailbone-grid'
|
||||
self.actions.extend(self.main_actions)
|
||||
self.more_actions = more_actions or []
|
||||
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._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
|
||||
def component(self):
|
||||
"""
|
||||
|
@ -317,34 +333,6 @@ class Grid:
|
|||
DeprecationWarning, stacklevel=2)
|
||||
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):
|
||||
"""
|
||||
This *removes* a column from the grid, altogether.
|
||||
|
@ -377,9 +365,6 @@ class Grid:
|
|||
if key in self.invisible:
|
||||
self.invisible.remove(key)
|
||||
|
||||
def append(self, field):
|
||||
self.columns.append(field)
|
||||
|
||||
def insert_before(self, field, newfield):
|
||||
self.columns.insert_before(field, newfield)
|
||||
|
||||
|
@ -430,24 +415,22 @@ class Grid:
|
|||
self.filters.pop(key, None)
|
||||
|
||||
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:
|
||||
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):
|
||||
if handler:
|
||||
self.click_handlers[key] = handler
|
||||
|
@ -457,9 +440,6 @@ class Grid:
|
|||
def has_click_handler(self, key):
|
||||
return key in self.click_handlers
|
||||
|
||||
def set_renderer(self, key, renderer):
|
||||
self.renderers[key] = renderer
|
||||
|
||||
def set_raw_renderer(self, key, renderer):
|
||||
"""
|
||||
Set or remove the "raw" renderer for the given field.
|
||||
|
@ -1450,22 +1430,13 @@ class Grid:
|
|||
return render(template, context)
|
||||
|
||||
def get_view_click_handler(self):
|
||||
|
||||
""" """
|
||||
# locate the 'view' action
|
||||
# TODO: this should be easier, and/or moved elsewhere?
|
||||
view = None
|
||||
for action in self.main_actions:
|
||||
for action in self.actions:
|
||||
if action.key == 'view':
|
||||
view = action
|
||||
break
|
||||
if not view:
|
||||
for action in self.more_actions:
|
||||
if action.key == 'view':
|
||||
view = action
|
||||
break
|
||||
|
||||
if view:
|
||||
return view.click_handler
|
||||
return action.click_handler
|
||||
|
||||
def set_filters_sequence(self, filters, only=False):
|
||||
"""
|
||||
|
@ -1561,26 +1532,21 @@ class Grid:
|
|||
kwargs['form'] = form
|
||||
return render(template, kwargs)
|
||||
|
||||
def render_actions(self, row, i):
|
||||
"""
|
||||
Returns the rendered contents of the 'actions' column for a given row.
|
||||
"""
|
||||
main_actions = [self.render_action(a, row, i)
|
||||
for a in self.main_actions]
|
||||
main_actions = [a for a in main_actions if a]
|
||||
more_actions = [self.render_action(a, row, i)
|
||||
for a in self.more_actions]
|
||||
more_actions = [a for a in more_actions if a]
|
||||
if more_actions:
|
||||
icon = HTML.tag('span', class_='ui-icon ui-icon-carat-1-e')
|
||||
link = tags.link_to("More" + icon, '#', class_='more')
|
||||
main_actions.append(HTML.literal(' ') + link + HTML.tag('div', class_='more', c=more_actions))
|
||||
return HTML.literal('').join(main_actions)
|
||||
def render_actions(self, row, i): # pragma: no cover
|
||||
""" """
|
||||
warnings.warn("grid.render_actions() is deprecated!",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
actions = [self.render_action(a, row, i)
|
||||
for a in self.actions]
|
||||
actions = [a for a in actions if a]
|
||||
return HTML.literal('').join(actions)
|
||||
|
||||
def render_action(self, action, row, i): # pragma: no cover
|
||||
""" """
|
||||
warnings.warn("grid.render_action() is deprecated!",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
def render_action(self, action, row, i):
|
||||
"""
|
||||
Renders an action menu item (link) for the given row.
|
||||
"""
|
||||
url = action.get_url(row, i)
|
||||
if url:
|
||||
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
|
||||
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)
|
||||
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):
|
||||
"""
|
||||
|
|
|
@ -186,7 +186,9 @@ class BatchMasterView(MasterView):
|
|||
breakdown = self.make_status_breakdown(batch)
|
||||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory('batch_row_status_breakdown', [],
|
||||
g = factory(self.request,
|
||||
key='batch_row_status_breakdown',
|
||||
data=[],
|
||||
columns=['title', 'count'])
|
||||
g.set_click_handler('title', "autoFilterStatus(props.row)")
|
||||
kwargs['status_breakdown_data'] = breakdown
|
||||
|
@ -693,7 +695,7 @@ class BatchMasterView(MasterView):
|
|||
batch = self.get_instance()
|
||||
|
||||
# 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 = []
|
||||
|
||||
# view action
|
||||
|
@ -714,7 +716,7 @@ class BatchMasterView(MasterView):
|
|||
actions.append(self.make_action('delete', icon='trash', url=self.row_delete_action_url))
|
||||
kwargs.setdefault('delete_speedbump', self.rows_deletable_speedbump)
|
||||
|
||||
kwargs['main_actions'] = actions
|
||||
kwargs['actions'] = actions
|
||||
|
||||
return super().make_row_grid_kwargs(**kwargs)
|
||||
|
||||
|
|
|
@ -195,6 +195,7 @@ class POSBatchView(BatchMasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
self.request,
|
||||
key=f'{route_prefix}.taxes',
|
||||
data=[],
|
||||
columns=[
|
||||
|
|
|
@ -208,8 +208,7 @@ class CustomerView(MasterView):
|
|||
url = lambda r, i: self.request.route_url(
|
||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||
# nb. insert to slot 1, just after normal View action
|
||||
g.main_actions.insert(1, self.make_action(
|
||||
'view_raw', url=url, icon='eye'))
|
||||
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||
|
||||
g.set_link('name')
|
||||
g.set_link('person')
|
||||
|
@ -471,7 +470,8 @@ class CustomerView(MasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.people'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.people',
|
||||
data=[],
|
||||
columns=[
|
||||
'shopper_number',
|
||||
|
@ -500,7 +500,8 @@ class CustomerView(MasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.people'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.people',
|
||||
data=[],
|
||||
columns=[
|
||||
'full_name',
|
||||
|
@ -512,13 +513,13 @@ class CustomerView(MasterView):
|
|||
)
|
||||
|
||||
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'):
|
||||
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'):
|
||||
g.main_actions.append(self.make_action('detach', icon='minus-circle',
|
||||
link_class='has-text-warning',
|
||||
click_handler="$emit('detach-person', props.row._action_url_detach)"))
|
||||
g.actions.append(self.make_action('detach', icon='minus-circle',
|
||||
link_class='has-text-warning',
|
||||
click_handler="$emit('detach-person', props.row._action_url_detach)"))
|
||||
|
||||
return HTML.literal(
|
||||
g.render_table_element(data_prop='peopleData'))
|
||||
|
|
|
@ -385,6 +385,7 @@ class CustomerOrderItemView(MasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
self.request,
|
||||
key=f'{route_prefix}.events',
|
||||
data=[],
|
||||
columns=[
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2023 Lance Edgar
|
||||
# Copyright © 2010-2024 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -29,13 +29,12 @@ import logging
|
|||
|
||||
from sqlalchemy import orm
|
||||
|
||||
from rattail.db import model
|
||||
from rattail.util import pretty_quantity, simple_error
|
||||
from rattail.db.model import CustomerOrder, CustomerOrderItem
|
||||
from rattail.util import simple_error
|
||||
from rattail.batch import get_batch_handler
|
||||
|
||||
from webhelpers2.html import tags, HTML
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
|
@ -46,7 +45,7 @@ class CustomerOrderView(MasterView):
|
|||
"""
|
||||
Master view for customer orders
|
||||
"""
|
||||
model_class = model.CustomerOrder
|
||||
model_class = CustomerOrder
|
||||
route_prefix = 'custorders'
|
||||
editable = False
|
||||
configurable = True
|
||||
|
@ -80,7 +79,7 @@ class CustomerOrderView(MasterView):
|
|||
]
|
||||
|
||||
has_rows = True
|
||||
model_row_class = model.CustomerOrderItem
|
||||
model_row_class = CustomerOrderItem
|
||||
rows_viewable = False
|
||||
|
||||
row_labels = {
|
||||
|
@ -116,15 +115,17 @@ class CustomerOrderView(MasterView):
|
|||
]
|
||||
|
||||
def __init__(self, request):
|
||||
super(CustomerOrderView, self).__init__(request)
|
||||
super().__init__(request)
|
||||
self.batch_handler = self.get_batch_handler()
|
||||
|
||||
def query(self, session):
|
||||
model = self.app.model
|
||||
return session.query(model.CustomerOrder)\
|
||||
.options(orm.joinedload(model.CustomerOrder.customer))
|
||||
|
||||
def configure_grid(self, g):
|
||||
super().configure_grid(g)
|
||||
model = self.app.model
|
||||
|
||||
# id
|
||||
g.set_link('id')
|
||||
|
@ -163,7 +164,7 @@ class CustomerOrderView(MasterView):
|
|||
return f"#{order.id} for {order.customer or order.person}"
|
||||
|
||||
def configure_form(self, f):
|
||||
super(CustomerOrderView, self).configure_form(f)
|
||||
super().configure_form(f)
|
||||
order = f.model_instance
|
||||
|
||||
f.set_readonly('id')
|
||||
|
@ -233,6 +234,7 @@ class CustomerOrderView(MasterView):
|
|||
class_='has-background-warning')
|
||||
|
||||
def get_row_data(self, order):
|
||||
model = self.app.model
|
||||
return self.Session.query(model.CustomerOrderItem)\
|
||||
.filter(model.CustomerOrderItem.order == order)
|
||||
|
||||
|
@ -240,11 +242,13 @@ class CustomerOrderView(MasterView):
|
|||
return item.order
|
||||
|
||||
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']
|
||||
kwargs['main_actions'].append(
|
||||
self.make_action('view', icon='eye', url=self.row_view_action_url))
|
||||
actions = kwargs.get('actions', [])
|
||||
if not actions:
|
||||
actions.append(self.make_action('view', icon='eye',
|
||||
url=self.row_view_action_url))
|
||||
kwargs['actions'] = actions
|
||||
|
||||
return kwargs
|
||||
|
||||
|
@ -253,7 +257,7 @@ class CustomerOrderView(MasterView):
|
|||
return self.request.route_url('custorders.items.view', uuid=item.uuid)
|
||||
|
||||
def configure_row_grid(self, g):
|
||||
super(CustomerOrderView, self).configure_row_grid(g)
|
||||
super().configure_row_grid(g)
|
||||
app = self.get_rattail_app()
|
||||
handler = app.get_batch_handler(
|
||||
'custorder',
|
||||
|
@ -423,6 +427,7 @@ class CustomerOrderView(MasterView):
|
|||
if not user:
|
||||
raise RuntimeError("this feature requires a user to be logged in")
|
||||
|
||||
model = self.app.model
|
||||
try:
|
||||
# there should be at most *one* new batch per user
|
||||
batch = self.Session.query(model.CustomerOrderBatch)\
|
||||
|
@ -488,6 +493,7 @@ class CustomerOrderView(MasterView):
|
|||
if not uuid:
|
||||
return {'error': "Must specify a customer UUID"}
|
||||
|
||||
model = self.app.model
|
||||
customer = self.Session.get(model.Customer, uuid)
|
||||
if not customer:
|
||||
return {'error': "Customer not found"}
|
||||
|
@ -508,6 +514,7 @@ class CustomerOrderView(MasterView):
|
|||
return info
|
||||
|
||||
def assign_contact(self, batch, data):
|
||||
model = self.app.model
|
||||
kwargs = {}
|
||||
|
||||
# this will either be a Person or Customer UUID
|
||||
|
@ -662,6 +669,7 @@ class CustomerOrderView(MasterView):
|
|||
if not uuid:
|
||||
return {'error': "Must specify a product UUID"}
|
||||
|
||||
model = self.app.model
|
||||
product = self.Session.get(model.Product, uuid)
|
||||
if not product:
|
||||
return {'error': "Product not found"}
|
||||
|
@ -725,8 +733,7 @@ class CustomerOrderView(MasterView):
|
|||
return app.render_currency(obj.unit_price)
|
||||
|
||||
def normalize_row(self, row):
|
||||
app = self.get_rattail_app()
|
||||
products_handler = app.get_products_handler()
|
||||
products_handler = self.app.get_products_handler()
|
||||
|
||||
data = {
|
||||
'uuid': row.uuid,
|
||||
|
@ -742,20 +749,20 @@ class CustomerOrderView(MasterView):
|
|||
'product_size': row.product_size,
|
||||
'product_weighed': row.product_weighed,
|
||||
|
||||
'case_quantity': pretty_quantity(row.case_quantity),
|
||||
'cases_ordered': pretty_quantity(row.cases_ordered),
|
||||
'units_ordered': pretty_quantity(row.units_ordered),
|
||||
'order_quantity': pretty_quantity(row.order_quantity),
|
||||
'case_quantity': self.app.render_quantity(row.case_quantity),
|
||||
'cases_ordered': self.app.render_quantity(row.cases_ordered),
|
||||
'units_ordered': self.app.render_quantity(row.units_ordered),
|
||||
'order_quantity': self.app.render_quantity(row.order_quantity),
|
||||
'order_uom': row.order_uom,
|
||||
'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,
|
||||
|
||||
'unit_price': float(row.unit_price) if row.unit_price is not None else None,
|
||||
'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_display': app.render_currency(row.total_price),
|
||||
'total_price_display': self.app.render_currency(row.total_price),
|
||||
|
||||
'status_code': row.status_code,
|
||||
'status_text': row.status_text,
|
||||
|
@ -763,15 +770,15 @@ class CustomerOrderView(MasterView):
|
|||
|
||||
if 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:
|
||||
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:
|
||||
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_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:
|
||||
data['pricing_reflects_sale'] = True
|
||||
|
@ -808,12 +815,12 @@ class CustomerOrderView(MasterView):
|
|||
|
||||
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_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():
|
||||
data['price_needs_confirmation'] = row.price_needs_confirmation
|
||||
|
||||
key = app.get_product_key_field()
|
||||
key = self.app.get_product_key_field()
|
||||
if key == 'upc':
|
||||
data['product_key'] = data['product_upc_pretty']
|
||||
elif key == 'item_id':
|
||||
|
@ -837,7 +844,7 @@ class CustomerOrderView(MasterView):
|
|||
case_qty = unit_qty = '??'
|
||||
else:
|
||||
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({
|
||||
'order_quantity_display': "{} {} (× {} {} = {} {})".format(
|
||||
data['order_quantity'],
|
||||
|
@ -850,14 +857,14 @@ class CustomerOrderView(MasterView):
|
|||
else:
|
||||
data.update({
|
||||
'order_quantity_display': "{} {}".format(
|
||||
pretty_quantity(row.order_quantity),
|
||||
self.app.render_quantity(row.order_quantity),
|
||||
self.enum.UNIT_OF_MEASURE[unit_uom]),
|
||||
})
|
||||
|
||||
return 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_uom = data.get('order_uom')
|
||||
|
@ -888,7 +895,7 @@ class CustomerOrderView(MasterView):
|
|||
pending_info = dict(data['pending_product'])
|
||||
|
||||
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'):
|
||||
if field in pending_info:
|
||||
|
@ -917,6 +924,7 @@ class CustomerOrderView(MasterView):
|
|||
if not uuid:
|
||||
return {'error': "Must specify a row UUID"}
|
||||
|
||||
model = self.app.model
|
||||
row = self.Session.get(model.CustomerOrderBatchRow, uuid)
|
||||
if not row:
|
||||
return {'error': "Row not found"}
|
||||
|
@ -975,6 +983,7 @@ class CustomerOrderView(MasterView):
|
|||
if not uuid:
|
||||
return {'error': "Must specify a row UUID"}
|
||||
|
||||
model = self.app.model
|
||||
row = self.Session.get(model.CustomerOrderBatchRow, uuid)
|
||||
if not row:
|
||||
return {'error': "Row not found"}
|
||||
|
|
|
@ -128,8 +128,8 @@ class DepartmentView(MasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.employees'.format(route_prefix),
|
||||
request=self.request,
|
||||
self.request,
|
||||
key=f'{route_prefix}.employees',
|
||||
data=[],
|
||||
columns=[
|
||||
'first_name',
|
||||
|
@ -140,9 +140,9 @@ class DepartmentView(MasterView):
|
|||
)
|
||||
|
||||
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'):
|
||||
g.main_actions.append(self.make_action('edit', icon='edit'))
|
||||
g.actions.append(self.make_action('edit', icon='edit'))
|
||||
|
||||
return HTML.literal(
|
||||
g.render_table_element(data_prop='employeesData'))
|
||||
|
|
|
@ -141,7 +141,7 @@ class EmailSettingView(MasterView):
|
|||
|
||||
# toggle hidden
|
||||
if self.has_perm('configure'):
|
||||
g.main_actions.append(
|
||||
g.actions.append(
|
||||
self.make_action('toggle_hidden', url='#', icon='ban',
|
||||
click_handler='toggleHidden(props.row)',
|
||||
factory=ToggleHidden))
|
||||
|
|
|
@ -167,8 +167,7 @@ class EmployeeView(MasterView):
|
|||
url = lambda r, i: self.request.route_url(
|
||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||
# nb. insert to slot 1, just after normal View action
|
||||
g.main_actions.insert(1, self.make_action(
|
||||
'view_raw', url=url, icon='eye'))
|
||||
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||
|
||||
def default_view_url(self):
|
||||
if (self.request.has_perm('people.view_profile')
|
||||
|
|
|
@ -392,9 +392,8 @@ class MasterView(View):
|
|||
if columns is None:
|
||||
columns = self.get_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
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)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
@ -454,10 +453,26 @@ class MasterView(View):
|
|||
if self.sortable or self.pageable or self.filterable:
|
||||
defaults['expose_direct_link'] = True
|
||||
|
||||
if 'main_actions' not in kwargs and 'more_actions' not in kwargs:
|
||||
main, more = self.get_grid_actions()
|
||||
defaults['main_actions'] = main
|
||||
defaults['more_actions'] = more
|
||||
if 'actions' not in kwargs:
|
||||
|
||||
if 'main_actions' in kwargs:
|
||||
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)
|
||||
return defaults
|
||||
|
||||
|
@ -548,9 +563,8 @@ class MasterView(View):
|
|||
if columns is None:
|
||||
columns = self.get_row_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
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)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
@ -577,7 +591,7 @@ class MasterView(View):
|
|||
if 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 = []
|
||||
|
||||
# view action
|
||||
|
@ -595,7 +609,7 @@ class MasterView(View):
|
|||
actions.append(self.make_action('delete', icon='trash', url=self.row_delete_action_url))
|
||||
defaults['delete_speedbump'] = self.rows_deletable_speedbump
|
||||
|
||||
defaults['main_actions'] = actions
|
||||
defaults['actions'] = actions
|
||||
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
@ -630,9 +644,8 @@ class MasterView(View):
|
|||
if columns is None:
|
||||
columns = self.get_version_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
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)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
@ -661,9 +674,9 @@ class MasterView(View):
|
|||
'pageable': True,
|
||||
'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)
|
||||
defaults['main_actions'] = [
|
||||
defaults['actions'] = [
|
||||
self.make_action('view', icon='eye', url=url),
|
||||
]
|
||||
defaults.update(kwargs)
|
||||
|
@ -1372,7 +1385,7 @@ class MasterView(View):
|
|||
'sortable': True,
|
||||
'default_sortkey': 'changed',
|
||||
'default_sortdir': 'desc',
|
||||
'main_actions': [
|
||||
'actions': [
|
||||
self.make_action('view', icon='eye', url='#',
|
||||
click_handler='viewRevision(props.row)'),
|
||||
self.make_action('view_separate', url=row_url, target='_blank',
|
||||
|
@ -3111,6 +3124,11 @@ class MasterView(View):
|
|||
return key
|
||||
|
||||
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()
|
||||
if len(more) == 1:
|
||||
main, more = main + more, []
|
||||
|
|
|
@ -229,8 +229,7 @@ class MemberView(MasterView):
|
|||
url = lambda r, i: self.request.route_url(
|
||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||
# nb. insert to slot 1, just after normal View action
|
||||
g.main_actions.insert(1, self.make_action(
|
||||
'view_raw', url=url, icon='eye'))
|
||||
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||
|
||||
# equity_total
|
||||
# TODO: should make this configurable
|
||||
|
|
|
@ -175,8 +175,7 @@ class PersonView(MasterView):
|
|||
url = lambda r, i: self.request.route_url(
|
||||
f'{route_prefix}.view', **self.get_action_route_kwargs(r))
|
||||
# nb. insert to slot 1, just after normal View action
|
||||
g.main_actions.insert(1, self.make_action(
|
||||
'view_raw', url=url, icon='eye'))
|
||||
g.actions.insert(1, self.make_action('view_raw', url=url, icon='eye'))
|
||||
|
||||
g.set_link('display_name')
|
||||
g.set_link('first_name')
|
||||
|
@ -522,9 +521,9 @@ class PersonView(MasterView):
|
|||
data = self.profile_transactions_query(person)
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
f'{route_prefix}.profile.transactions.{person.uuid}',
|
||||
data,
|
||||
request=self.request,
|
||||
self.request,
|
||||
key=f'{route_prefix}.profile.transactions.{person.uuid}',
|
||||
data=data,
|
||||
model_class=model.Transaction,
|
||||
ajax_data_url=self.get_action_url('view_profile_transactions', person),
|
||||
columns=[
|
||||
|
@ -552,7 +551,7 @@ class PersonView(MasterView):
|
|||
if self.request.has_perm('trainwreck.transactions.view'):
|
||||
url = lambda row, i: self.request.route_url('trainwreck.transactions.view',
|
||||
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.set_enum('system', self.enum.TRAINWRECK_SYSTEM)
|
||||
|
@ -1413,9 +1412,9 @@ class PersonView(MasterView):
|
|||
route_prefix = self.get_route_prefix()
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
'{}.profile.revisions'.format(route_prefix),
|
||||
[], # start with empty data!
|
||||
request=self.request,
|
||||
self.request,
|
||||
key=f'{route_prefix}.profile.revisions',
|
||||
data=[], # start with empty data!
|
||||
columns=[
|
||||
'changed',
|
||||
'changed_by',
|
||||
|
@ -1430,7 +1429,7 @@ class PersonView(MasterView):
|
|||
'changed_by',
|
||||
'comment',
|
||||
],
|
||||
main_actions=[
|
||||
actions=[
|
||||
self.make_action('view', icon='eye', url='#',
|
||||
click_handler='viewRevision(props.row)'),
|
||||
],
|
||||
|
|
|
@ -110,7 +110,7 @@ class PoserReportView(PoserMasterView):
|
|||
g.set_searchable('description')
|
||||
|
||||
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',
|
||||
url=self.get_generate_url))
|
||||
|
||||
|
|
|
@ -124,11 +124,11 @@ class PrincipalMasterView(MasterView):
|
|||
def find_by_perm_make_results_grid(self, principals):
|
||||
route_prefix = self.get_route_prefix()
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(key=f'{route_prefix}.results',
|
||||
request=self.request,
|
||||
g = factory(self.request,
|
||||
key=f'{route_prefix}.results',
|
||||
data=[],
|
||||
columns=[],
|
||||
main_actions=[
|
||||
actions=[
|
||||
self.make_action('view', icon='eye',
|
||||
click_handler='navigateTo(props.row._url)'),
|
||||
])
|
||||
|
|
|
@ -384,7 +384,7 @@ class ProductView(MasterView):
|
|||
g.set_filter('report_code_name', model.ReportCode.name)
|
||||
|
||||
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='#',
|
||||
click_handler='quickLabelPrint(props.row)'))
|
||||
|
||||
|
@ -1197,8 +1197,9 @@ class ProductView(MasterView):
|
|||
|
||||
# regular price
|
||||
data = [] # defer fetching until user asks for it
|
||||
grid = grids.Grid('products.regular_price_history', data,
|
||||
request=self.request,
|
||||
grid = grids.Grid(self.request,
|
||||
key='products.regular_price_history',
|
||||
data=data,
|
||||
columns=[
|
||||
'price',
|
||||
'since',
|
||||
|
@ -1211,8 +1212,9 @@ class ProductView(MasterView):
|
|||
|
||||
# current price
|
||||
data = [] # defer fetching until user asks for it
|
||||
grid = grids.Grid('products.current_price_history', data,
|
||||
request=self.request,
|
||||
grid = grids.Grid(self.request,
|
||||
key='products.current_price_history',
|
||||
data=data,
|
||||
columns=[
|
||||
'price',
|
||||
'price_type',
|
||||
|
@ -1229,8 +1231,9 @@ class ProductView(MasterView):
|
|||
|
||||
# suggested price
|
||||
data = [] # defer fetching until user asks for it
|
||||
grid = grids.Grid('products.suggested_price_history', data,
|
||||
request=self.request,
|
||||
grid = grids.Grid(self.request,
|
||||
key='products.suggested_price_history',
|
||||
data=data,
|
||||
columns=[
|
||||
'price',
|
||||
'since',
|
||||
|
@ -1243,8 +1246,9 @@ class ProductView(MasterView):
|
|||
|
||||
# cost history
|
||||
data = [] # defer fetching until user asks for it
|
||||
grid = grids.Grid('products.cost_history', data,
|
||||
request=self.request,
|
||||
grid = grids.Grid(self.request,
|
||||
key='products.cost_history',
|
||||
data=data,
|
||||
columns=[
|
||||
'cost',
|
||||
'vendor',
|
||||
|
@ -1335,7 +1339,8 @@ class ProductView(MasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.vendor_sources'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.vendor_sources',
|
||||
data=[],
|
||||
columns=columns,
|
||||
labels={
|
||||
|
@ -1376,7 +1381,8 @@ class ProductView(MasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.lookup_codes'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.lookup_codes',
|
||||
data=[],
|
||||
columns=[
|
||||
'sequence',
|
||||
|
|
|
@ -793,8 +793,8 @@ class PurchasingBatchView(BatchMasterView):
|
|||
factory = self.get_grid_factory()
|
||||
|
||||
g = factory(
|
||||
key='{}.row_credits'.format(route_prefix),
|
||||
request=self.request,
|
||||
self.request,
|
||||
key=f'{route_prefix}.row_credits',
|
||||
data=[],
|
||||
columns=[
|
||||
'credit_type',
|
||||
|
|
|
@ -774,8 +774,10 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
breakdown = self.make_po_vs_invoice_breakdown(batch)
|
||||
factory = self.get_grid_factory()
|
||||
|
||||
g = factory('batch_po_vs_invoice_breakdown', [],
|
||||
columns=['title', 'count'])
|
||||
g = factory(self.request,
|
||||
key='batch_po_vs_invoice_breakdown',
|
||||
data=[],
|
||||
columns=['title', 'count'])
|
||||
g.set_click_handler('title', "autoFilterPoVsInvoice(props.row)")
|
||||
kwargs['po_vs_invoice_breakdown_data'] = breakdown
|
||||
kwargs['po_vs_invoice_breakdown_grid'] = HTML.literal(
|
||||
|
@ -1035,10 +1037,12 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
icon='shuffle',
|
||||
label="Transform to Unit",
|
||||
url=self.transform_unit_url)
|
||||
g.more_actions.append(transform)
|
||||
if g.main_actions and g.main_actions[-1].key == 'delete':
|
||||
delete = g.main_actions.pop()
|
||||
g.more_actions.append(delete)
|
||||
if g.actions and g.actions[-1].key == 'delete':
|
||||
delete = g.actions.pop()
|
||||
g.actions.append(transform)
|
||||
g.actions.append(delete)
|
||||
else:
|
||||
g.actions.append(transform)
|
||||
|
||||
# truck_dump_status
|
||||
if not batch.is_truck_dump_parent():
|
||||
|
@ -1111,7 +1115,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
and self.row_editable(row)):
|
||||
|
||||
# add the Un-Declare action
|
||||
g.main_actions.append(self.make_action(
|
||||
g.actions.append(self.make_action(
|
||||
'remove', label="Un-Declare",
|
||||
url='#', icon='trash',
|
||||
link_class='has-text-danger',
|
||||
|
|
|
@ -308,7 +308,8 @@ class ReportOutputView(ExportMasterView):
|
|||
route_prefix = self.get_route_prefix()
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.params'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.params',
|
||||
data=params,
|
||||
columns=['key', 'value'],
|
||||
labels={'key': "Name"},
|
||||
|
@ -705,9 +706,12 @@ class ProblemReportView(MasterView):
|
|||
return ', '.join(recips)
|
||||
|
||||
def render_days(self, report_info, field):
|
||||
g = self.get_grid_factory()('days', [],
|
||||
columns=['weekday_name', 'enabled'],
|
||||
labels={'weekday_name': "Weekday"})
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(self.request,
|
||||
key='days',
|
||||
data=[],
|
||||
columns=['weekday_name', 'enabled'],
|
||||
labels={'weekday_name': "Weekday"})
|
||||
return HTML.literal(g.render_table_element(data_prop='weekdaysData'))
|
||||
|
||||
def template_kwargs_view(self, **kwargs):
|
||||
|
|
|
@ -255,8 +255,8 @@ class RoleView(PrincipalMasterView):
|
|||
permission_prefix = self.get_permission_prefix()
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.users'.format(route_prefix),
|
||||
request=self.request,
|
||||
self.request,
|
||||
key=f'{route_prefix}.users',
|
||||
data=[],
|
||||
columns=[
|
||||
'full_name',
|
||||
|
@ -269,9 +269,9 @@ class RoleView(PrincipalMasterView):
|
|||
)
|
||||
|
||||
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'):
|
||||
g.main_actions.append(self.make_action('edit', icon='edit'))
|
||||
g.actions.append(self.make_action('edit', icon='edit'))
|
||||
|
||||
return HTML.literal(
|
||||
g.render_table_element(data_prop='usersData'))
|
||||
|
@ -366,10 +366,11 @@ class RoleView(PrincipalMasterView):
|
|||
self.make_action('view', icon='zoomin',
|
||||
url=lambda r, i: self.request.route_url('users.view', uuid=r.uuid))
|
||||
]
|
||||
kwargs['users'] = grids.Grid(None, users, ['username', 'active'],
|
||||
request=self.request,
|
||||
kwargs['users'] = grids.Grid(self.request,
|
||||
data=users,
|
||||
columns=['username', 'active'],
|
||||
model_class=model.User,
|
||||
main_actions=actions)
|
||||
actions=actions)
|
||||
else:
|
||||
kwargs['users'] = None
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ class MasterView(views.MasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
key='{}.probes'.format(route_prefix),
|
||||
request=self.request,
|
||||
self.request,
|
||||
key=f'{route_prefix}.probes',
|
||||
data=[],
|
||||
columns=[
|
||||
'description',
|
||||
|
@ -96,7 +96,7 @@ class MasterView(views.MasterView):
|
|||
'critical_temp_max': "Crit. Max",
|
||||
},
|
||||
linked_columns=['description'],
|
||||
main_actions=actions,
|
||||
actions=actions,
|
||||
)
|
||||
return HTML.literal(
|
||||
g.render_table_element(data_prop='probesData'))
|
||||
|
|
|
@ -246,10 +246,10 @@ class TransactionView(MasterView):
|
|||
factory = self.get_grid_factory()
|
||||
|
||||
g = factory(
|
||||
key='{}.custorder_xref_markers'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.custorder_xref_markers',
|
||||
data=[],
|
||||
columns=['custorder_xref', 'custorder_item_xref'],
|
||||
request=self.request)
|
||||
columns=['custorder_xref', 'custorder_item_xref'])
|
||||
|
||||
return HTML.literal(
|
||||
g.render_table_element(data_prop='custorderXrefMarkersData'))
|
||||
|
@ -355,11 +355,11 @@ class TransactionView(MasterView):
|
|||
factory = self.get_grid_factory()
|
||||
|
||||
g = factory(
|
||||
key='{}.discounts'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.discounts',
|
||||
data=[],
|
||||
columns=['discount_type', 'description', 'amount'],
|
||||
labels={'discount_type': "Type"},
|
||||
request=self.request)
|
||||
labels={'discount_type': "Type"})
|
||||
|
||||
return HTML.literal(
|
||||
g.render_table_element(data_prop='discountsData'))
|
||||
|
|
|
@ -44,9 +44,6 @@ class UserView(PrincipalMasterView):
|
|||
Master view for the User model.
|
||||
"""
|
||||
model_class = User
|
||||
has_rows = True
|
||||
rows_title = "User Events"
|
||||
model_row_class = UserEvent
|
||||
has_versions = True
|
||||
touchable = True
|
||||
mergeable = True
|
||||
|
@ -77,6 +74,11 @@ class UserView(PrincipalMasterView):
|
|||
'permissions',
|
||||
]
|
||||
|
||||
has_rows = True
|
||||
model_row_class = UserEvent
|
||||
rows_title = "User Events"
|
||||
rows_viewable = False
|
||||
|
||||
row_grid_columns = [
|
||||
'type_code',
|
||||
'occurred',
|
||||
|
@ -297,11 +299,11 @@ class UserView(PrincipalMasterView):
|
|||
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
request=self.request,
|
||||
key='{}.api_tokens'.format(route_prefix),
|
||||
self.request,
|
||||
key=f'{route_prefix}.api_tokens',
|
||||
data=[],
|
||||
columns=['description', 'created'],
|
||||
main_actions=[
|
||||
actions=[
|
||||
self.make_action('delete', icon='trash',
|
||||
click_handler="$emit('api-token-delete', props.row)")])
|
||||
|
||||
|
@ -514,7 +516,6 @@ class UserView(PrincipalMasterView):
|
|||
g.set_sort_defaults('occurred', 'desc')
|
||||
g.set_enum('type_code', self.enum.USER_EVENT)
|
||||
g.set_label('type_code', "Event Type")
|
||||
g.main_actions = []
|
||||
|
||||
def get_version_child_classes(self):
|
||||
model = self.model
|
||||
|
|
|
@ -12,9 +12,8 @@ class TestGrid(WebTestCase):
|
|||
self.setup_web()
|
||||
self.config.setdefault('rattail.web.menus.handler_spec', 'tests.util:NullMenuHandler')
|
||||
|
||||
def make_grid(self, key, data=[], **kwargs):
|
||||
kwargs.setdefault('request', self.request)
|
||||
return mod.Grid(key, data=data, **kwargs)
|
||||
def make_grid(self, key=None, data=[], **kwargs):
|
||||
return mod.Grid(self.request, key=key, data=data, **kwargs)
|
||||
|
||||
def test_basic(self):
|
||||
grid = self.make_grid('foo')
|
||||
|
@ -90,6 +89,50 @@ class TestGrid(WebTestCase):
|
|||
grid = self.make_grid('foo', main_actions=['foo'], more_actions=['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):
|
||||
model = self.app.model
|
||||
|
||||
|
|
Loading…
Reference in a new issue