feat: inherit most logic from wuttaweb, for GridAction
This commit is contained in:
parent
09612b1921
commit
1b78bd617c
|
@ -38,6 +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 . 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
|
||||||
|
@ -1801,18 +1802,20 @@ class Grid:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class GridAction(object):
|
class GridAction(WuttaGridAction):
|
||||||
"""
|
"""
|
||||||
Represents an action available to a grid. This is used to construct the
|
Represents a "row action" hyperlink within a grid context.
|
||||||
'actions' column when rendering the grid.
|
|
||||||
|
|
||||||
:param key: Key for the action (e.g. ``'edit'``), unique within
|
This is a subclass of
|
||||||
the grid.
|
:class:`wuttaweb:wuttaweb.grids.base.GridAction`.
|
||||||
|
|
||||||
:param label: Label to be displayed for the action. If not set,
|
.. warning::
|
||||||
will be a capitalized version of ``key``.
|
|
||||||
|
|
||||||
:param icon: Icon name for the action.
|
This class remains for now, to retain compatibility with
|
||||||
|
existing code. But at some point the WuttaWeb class will
|
||||||
|
supersede this one entirely.
|
||||||
|
|
||||||
|
:param target: HTML "target" attribute for the ``<a>`` tag.
|
||||||
|
|
||||||
:param click_handler: Optional JS click handler for the action.
|
:param click_handler: Optional JS click handler for the action.
|
||||||
This value will be rendered as-is within the final grid
|
This value will be rendered as-is within the final grid
|
||||||
|
@ -1824,41 +1827,23 @@ class GridAction(object):
|
||||||
* ``$emit('do-something', props.row)``
|
* ``$emit('do-something', props.row)``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, key, label=None, url='#', icon=None, target=None,
|
def __init__(
|
||||||
link_class=None, click_handler=None):
|
self,
|
||||||
self.key = key
|
request,
|
||||||
self.label = label or prettify(key)
|
key,
|
||||||
self.icon = icon
|
target=None,
|
||||||
self.url = url
|
click_handler=None,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
# TODO: previously url default was '#' - but i don't think we
|
||||||
|
# need that anymore? guess we'll see..
|
||||||
|
#kwargs.setdefault('url', '#')
|
||||||
|
|
||||||
|
super().__init__(request, key, **kwargs)
|
||||||
|
|
||||||
self.target = target
|
self.target = target
|
||||||
self.link_class = link_class
|
|
||||||
self.click_handler = click_handler
|
self.click_handler = click_handler
|
||||||
|
|
||||||
def get_url(self, row, i):
|
|
||||||
"""
|
|
||||||
Returns an action URL for the given row.
|
|
||||||
"""
|
|
||||||
if callable(self.url):
|
|
||||||
return self.url(row, i)
|
|
||||||
return self.url
|
|
||||||
|
|
||||||
def render_icon(self):
|
|
||||||
"""
|
|
||||||
Render the HTML snippet for the action link icon.
|
|
||||||
"""
|
|
||||||
return HTML.tag('i', class_='fas fa-{}'.format(self.icon))
|
|
||||||
|
|
||||||
def render_label(self):
|
|
||||||
"""
|
|
||||||
Render the label "text" within the actions column of a grid
|
|
||||||
row. Most actions have a static label that never varies, but
|
|
||||||
you can override this to add e.g. HTML content. Note that the
|
|
||||||
return value will be treated / rendered as HTML whether or not
|
|
||||||
it contains any, so perhaps be careful that it is trusted
|
|
||||||
content.
|
|
||||||
"""
|
|
||||||
return self.label
|
|
||||||
|
|
||||||
|
|
||||||
class URLMaker(object):
|
class URLMaker(object):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -53,11 +53,11 @@
|
||||||
</${b}-table-column>
|
</${b}-table-column>
|
||||||
% endfor
|
% endfor
|
||||||
|
|
||||||
% if grid.main_actions or grid.more_actions:
|
% if grid.actions:
|
||||||
<${b}-table-column field="actions"
|
<${b}-table-column field="actions"
|
||||||
label="Actions"
|
label="Actions"
|
||||||
v-slot="props">
|
v-slot="props">
|
||||||
% for action in grid.main_actions:
|
% for action in grid.actions:
|
||||||
<a :href="props.row._action_url_${action.key}"
|
<a :href="props.row._action_url_${action.key}"
|
||||||
% if action.link_class:
|
% if action.link_class:
|
||||||
class="${action.link_class}"
|
class="${action.link_class}"
|
||||||
|
@ -68,12 +68,7 @@
|
||||||
@click.prevent="${action.click_handler}"
|
@click.prevent="${action.click_handler}"
|
||||||
% endif
|
% endif
|
||||||
>
|
>
|
||||||
% if request.use_oruga:
|
${action.render_icon_and_label()}
|
||||||
<o-icon icon="${action.icon}" />
|
|
||||||
% else:
|
|
||||||
<i class="fas fa-${action.icon}"></i>
|
|
||||||
% endif
|
|
||||||
${action.label}
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
% endfor
|
% endfor
|
||||||
|
|
|
@ -163,13 +163,7 @@
|
||||||
target="${action.target}"
|
target="${action.target}"
|
||||||
% endif
|
% endif
|
||||||
>
|
>
|
||||||
% if request.use_oruga:
|
${action.render_icon_and_label()}
|
||||||
<o-icon icon="${action.icon}" />
|
|
||||||
<span>${action.render_label()|n}</span>
|
|
||||||
% else:
|
|
||||||
${action.render_icon()|n}
|
|
||||||
${action.render_label()|n}
|
|
||||||
% endif
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
% endfor
|
% endfor
|
||||||
|
|
|
@ -3220,14 +3220,18 @@ class MasterView(View):
|
||||||
|
|
||||||
def make_action(self, key, url=None, factory=None, **kwargs):
|
def make_action(self, key, url=None, factory=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Make a new :class:`GridAction` instance for the current grid.
|
Make and return a new :class:`~tailbone.grids.core.GridAction`
|
||||||
|
instance.
|
||||||
|
|
||||||
|
This can be called to make actions for any grid, not just the
|
||||||
|
one from :meth:`index()`.
|
||||||
"""
|
"""
|
||||||
if url is None:
|
if url is None:
|
||||||
route = '{}.{}'.format(self.get_route_prefix(), key)
|
route = '{}.{}'.format(self.get_route_prefix(), key)
|
||||||
url = lambda r, i: self.request.route_url(route, **self.get_action_route_kwargs(r))
|
url = lambda r, i: self.request.route_url(route, **self.get_action_route_kwargs(r))
|
||||||
if not factory:
|
if not factory:
|
||||||
factory = grids.GridAction
|
factory = grids.GridAction
|
||||||
return factory(key, url=url, **kwargs)
|
return factory(self.request, key, url=url, **kwargs)
|
||||||
|
|
||||||
def get_action_route_kwargs(self, obj):
|
def get_action_route_kwargs(self, obj):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -552,7 +552,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(grids.GridAction('view', icon='eye', url=url))
|
g.main_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)
|
||||||
|
|
|
@ -40,7 +40,7 @@ from webhelpers2.html import tags, HTML
|
||||||
|
|
||||||
from wuttaweb.util import get_form_data
|
from wuttaweb.util import get_form_data
|
||||||
|
|
||||||
from tailbone import forms, grids
|
from tailbone import forms
|
||||||
from tailbone.views.purchasing import PurchasingBatchView
|
from tailbone.views.purchasing import PurchasingBatchView
|
||||||
|
|
||||||
|
|
||||||
|
@ -1031,7 +1031,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
if batch.is_truck_dump_parent():
|
if batch.is_truck_dump_parent():
|
||||||
permission_prefix = self.get_permission_prefix()
|
permission_prefix = self.get_permission_prefix()
|
||||||
if self.request.has_perm('{}.edit_row'.format(permission_prefix)):
|
if self.request.has_perm('{}.edit_row'.format(permission_prefix)):
|
||||||
transform = grids.GridAction('transform',
|
transform = self.make_action('transform',
|
||||||
icon='shuffle',
|
icon='shuffle',
|
||||||
label="Transform to Unit",
|
label="Transform to Unit",
|
||||||
url=self.transform_unit_url)
|
url=self.transform_unit_url)
|
||||||
|
|
|
@ -363,7 +363,7 @@ class RoleView(PrincipalMasterView):
|
||||||
if role.users:
|
if role.users:
|
||||||
users = sorted(role.users, key=lambda u: u.username)
|
users = sorted(role.users, key=lambda u: u.username)
|
||||||
actions = [
|
actions = [
|
||||||
grids.GridAction('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(None, users, ['username', 'active'],
|
||||||
|
|
|
@ -137,3 +137,20 @@ class TestGrid(WebTestCase):
|
||||||
# calling again returns same data
|
# calling again returns same data
|
||||||
data2 = grid.get_vue_data()
|
data2 = grid.get_vue_data()
|
||||||
self.assertIs(data2, data)
|
self.assertIs(data2, data)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGridAction(WebTestCase):
|
||||||
|
|
||||||
|
def test_constructor(self):
|
||||||
|
|
||||||
|
# null by default
|
||||||
|
action = mod.GridAction(self.request, 'view')
|
||||||
|
self.assertIsNone(action.target)
|
||||||
|
self.assertIsNone(action.click_handler)
|
||||||
|
|
||||||
|
# but can set them
|
||||||
|
action = mod.GridAction(self.request, 'view',
|
||||||
|
target='_blank',
|
||||||
|
click_handler='doSomething(props.row)')
|
||||||
|
self.assertEqual(action.target, '_blank')
|
||||||
|
self.assertEqual(action.click_handler, 'doSomething(props.row)')
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from tailbone.views import master as mod
|
from tailbone.views import master as mod
|
||||||
|
from wuttaweb.grids import GridAction
|
||||||
from tests.util import WebTestCase
|
from tests.util import WebTestCase
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,3 +25,11 @@ class TestMasterView(WebTestCase):
|
||||||
# sanity / coverage check
|
# sanity / coverage check
|
||||||
kw = view.make_form_kwargs(model_instance=setting)
|
kw = view.make_form_kwargs(model_instance=setting)
|
||||||
self.assertIsNotNone(kw['action_url'])
|
self.assertIsNotNone(kw['action_url'])
|
||||||
|
|
||||||
|
def test_make_action(self):
|
||||||
|
model = self.app.model
|
||||||
|
with patch.multiple(mod.MasterView, create=True,
|
||||||
|
model_class=model.Setting):
|
||||||
|
view = self.make_view()
|
||||||
|
action = view.make_action('view')
|
||||||
|
self.assertIsInstance(action, GridAction)
|
||||||
|
|
Loading…
Reference in a new issue