From 871ea84f9662bf33ee424b8510387c6a5e724814 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 20 Dec 2022 19:14:54 -0600 Subject: [PATCH] Add support for "is row checkable" in grids i.e. when grid has checkboxes, some rows maybe shouldn't get one --- tailbone/grids/core.py | 76 +++++++++++++++++++++++++++++ tailbone/templates/grids/buefy.mako | 9 +++- tailbone/views/master.py | 2 + 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/tailbone/grids/core.py b/tailbone/grids/core.py index 2f11f094..54f578ed 100644 --- a/tailbone/grids/core.py +++ b/tailbone/grids/core.py @@ -69,6 +69,74 @@ class Grid(object): """ Core grid class. In sore need of documentation. + .. _Buefy docs: https://buefy.org/documentation/table/ + + .. attribute:: checkable + + Optional callback to determine if a given row is checkable, + i.e. this allows hiding checkbox for certain rows if needed. + + This may be either a Python callable, or string representing a + JS callable. If the latter, according to the `Buefy docs`_: + + .. code-block:: none + + Custom method to verify if a row is checkable, works when is + checkable. + + Function (row: Object) + + In other words this JS callback would be invoked for each data + row in the client-side grid. + + But if a Python callable is used, then it will be invoked for + each row object in the server-side grid. For instance:: + + def checkable(obj): + if obj.some_property == True: + return True + return False + + grid.checkable = checkable + + .. attribute:: check_handler + + Optional JS callback for the ``@check`` event of the underlying + Buefy table component. See the `Buefy docs`_ for more info, + but for convenience they say this (as of writing): + + .. code-block:: none + + Triggers when the checkbox in a row is clicked and/or when + the header checkbox is clicked + + For instance, you might set ``grid.check_handler = + 'rowChecked'`` and then define the handler within your template + (e.g. ``/widgets/index.mako``) like so: + + .. code-block:: none + + <%def name="modify_this_page_vars()"> + ${parent.modify_this_page_vars()} + + + .. attribute:: raw_renderers Dict of "raw" field renderers. See also @@ -117,6 +185,7 @@ class Grid(object): 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, clicking_row_checks_box=False, click_handlers=None, main_actions=[], more_actions=[], delete_speedbump=False, ajax_data_url=None, component='tailbone-grid', @@ -175,6 +244,7 @@ class Grid(object): self.checked = lambda item: False self.check_handler = check_handler self.check_all_handler = check_all_handler + self.checkable = checkable self.clicking_row_checks_box = clicking_row_checks_box self.click_handlers = click_handlers or {} @@ -1365,6 +1435,7 @@ class Grid(object): count = len(raw_data) # iterate over data rows + checkable = self.checkboxes and self.checkable and callable(self.checkable) for i in range(count): rowobj = raw_data[i] @@ -1372,6 +1443,11 @@ class Grid(object): # logic finds it useful row = {'_index': i} + # if grid allows checkboxes, and we have logic to see if + # any given row is checkable, add data for that here + if checkable: + row['_checkable'] = self.checkable(rowobj) + # sometimes we need to include some "raw" data columns in our # result set, even though the column is not displayed as part of # the grid. this can be used for front-end editing of row data for diff --git a/tailbone/templates/grids/buefy.mako b/tailbone/templates/grids/buefy.mako index 47e9a2dc..10c52389 100644 --- a/tailbone/templates/grids/buefy.mako +++ b/tailbone/templates/grids/buefy.mako @@ -192,12 +192,17 @@ % if grid.check_all_handler: @check-all="${grid.check_all_handler}" % endif - ## TODO: definitely will be wanting this... - ## :is-row-checkable="" + % if isinstance(grid.checkable, six.string_types): + :is-row-checkable="${grid.row_checkable}" + % elif grid.checkable: + :is-row-checkable="row => row._checkable" + % endif + % if grid.sortable: :default-sort="[sortField, sortOrder]" backend-sorting @sort="onSort" + % endif :paginated="paginated" :per-page="perPage" diff --git a/tailbone/views/master.py b/tailbone/views/master.py index 3ae2be88..a0d51329 100644 --- a/tailbone/views/master.py +++ b/tailbone/views/master.py @@ -451,6 +451,7 @@ class MasterView(View): 'url': lambda obj: self.get_action_url('view', obj), 'checkboxes': checkboxes, 'checked': self.checked, + 'checkable': self.checkbox, 'clicking_row_checks_box': self.clicking_row_checks_box, 'assume_local_times': self.has_local_times, } @@ -2765,6 +2766,7 @@ class MasterView(View): def get_effective_query(self, session=None, **kwargs): return self.get_effective_data(session=session, **kwargs) + # TODO: should rename to checkable? def checkbox(self, instance): """ Returns a boolean indicating whether ot not a checkbox should be