feat: inherit most logic from wuttaweb, for GridAction

This commit is contained in:
Lance Edgar 2024-08-16 11:56:12 -05:00
parent 09612b1921
commit 1b78bd617c
9 changed files with 65 additions and 61 deletions

View file

@ -38,6 +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 . import filters as gridfilters
from tailbone.db import Session
from tailbone.util import raw_datetime
@ -1801,18 +1802,20 @@ class Grid:
return False
class GridAction(object):
class GridAction(WuttaGridAction):
"""
Represents an action available to a grid. This is used to construct the
'actions' column when rendering the grid.
Represents a "row action" hyperlink within a grid context.
:param key: Key for the action (e.g. ``'edit'``), unique within
the grid.
This is a subclass of
:class:`wuttaweb:wuttaweb.grids.base.GridAction`.
:param label: Label to be displayed for the action. If not set,
will be a capitalized version of ``key``.
.. warning::
: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.
This value will be rendered as-is within the final grid
@ -1824,41 +1827,23 @@ class GridAction(object):
* ``$emit('do-something', props.row)``
"""
def __init__(self, key, label=None, url='#', icon=None, target=None,
link_class=None, click_handler=None):
self.key = key
self.label = label or prettify(key)
self.icon = icon
self.url = url
def __init__(
self,
request,
key,
target=None,
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.link_class = link_class
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):
"""

View file

@ -53,11 +53,11 @@
</${b}-table-column>
% endfor
% if grid.main_actions or grid.more_actions:
% if grid.actions:
<${b}-table-column field="actions"
label="Actions"
v-slot="props">
% for action in grid.main_actions:
% for action in grid.actions:
<a :href="props.row._action_url_${action.key}"
% if action.link_class:
class="${action.link_class}"
@ -68,12 +68,7 @@
@click.prevent="${action.click_handler}"
% endif
>
% if request.use_oruga:
<o-icon icon="${action.icon}" />
% else:
<i class="fas fa-${action.icon}"></i>
% endif
${action.label}
${action.render_icon_and_label()}
</a>
&nbsp;
% endfor

View file

@ -163,13 +163,7 @@
target="${action.target}"
% endif
>
% if request.use_oruga:
<o-icon icon="${action.icon}" />
<span>${action.render_label()|n}</span>
% else:
${action.render_icon()|n}
${action.render_label()|n}
% endif
${action.render_icon_and_label()}
</a>
&nbsp;
% endfor

View file

@ -3220,14 +3220,18 @@ class MasterView(View):
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:
route = '{}.{}'.format(self.get_route_prefix(), key)
url = lambda r, i: self.request.route_url(route, **self.get_action_route_kwargs(r))
if not factory:
factory = grids.GridAction
return factory(key, url=url, **kwargs)
return factory(self.request, key, url=url, **kwargs)
def get_action_route_kwargs(self, obj):
"""

View file

@ -552,7 +552,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(grids.GridAction('view', icon='eye', url=url))
g.main_actions.append(self.make_action('view', icon='eye', url=url))
g.load_settings()
g.set_enum('system', self.enum.TRAINWRECK_SYSTEM)

View file

@ -40,7 +40,7 @@ from webhelpers2.html import tags, HTML
from wuttaweb.util import get_form_data
from tailbone import forms, grids
from tailbone import forms
from tailbone.views.purchasing import PurchasingBatchView
@ -1031,7 +1031,7 @@ class ReceivingBatchView(PurchasingBatchView):
if batch.is_truck_dump_parent():
permission_prefix = self.get_permission_prefix()
if self.request.has_perm('{}.edit_row'.format(permission_prefix)):
transform = grids.GridAction('transform',
transform = self.make_action('transform',
icon='shuffle',
label="Transform to Unit",
url=self.transform_unit_url)

View file

@ -363,7 +363,7 @@ class RoleView(PrincipalMasterView):
if role.users:
users = sorted(role.users, key=lambda u: u.username)
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))
]
kwargs['users'] = grids.Grid(None, users, ['username', 'active'],

View file

@ -137,3 +137,20 @@ class TestGrid(WebTestCase):
# calling again returns same data
data2 = grid.get_vue_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)')

View file

@ -3,6 +3,7 @@
from unittest.mock import patch
from tailbone.views import master as mod
from wuttaweb.grids import GridAction
from tests.util import WebTestCase
@ -24,3 +25,11 @@ class TestMasterView(WebTestCase):
# sanity / coverage check
kw = view.make_form_kwargs(model_instance=setting)
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)