Skip to content

Commit aa71d7e

Browse files
mihalikvoko-vac
andauthored
Dev nshp2 (#132)
* row actions * row actions * row actions * row actions * row actions * feat: added fitDataStretchGrow layout and widthGrow support for Tabulator * feat: added fitDataStretchGrow layout and widthGrow support for Tabulator * Update translation files for multiple languages * chore: bump version to 1.1.13b2 and update nested plugin for improved sorting with Subquery * chore: bump version to 1.1.13b2 and update nested plugin for improved sorting with Subquery * fix: update nested plugin to use Max aggregation to prevent duplication of rows * feat: replace fitDataStretchGrow with fitDataFillAvailableSpace in Tabulator layouts * style: update CSS classes for row action buttons to improve styling consistency * chore: bump version to 1.1.13 in pyproject.toml --------- Co-authored-by: oko-vac <oko-vac@users.noreply.github.com>
1 parent 613c19c commit aa71d7e

34 files changed

Lines changed: 1353 additions & 128 deletions

File tree

AGENTS.md

Lines changed: 242 additions & 48 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "django-smartbase-admin"
3-
version = "1.1.12"
3+
version = "1.1.13"
44
description = ""
55
authors = ["SmartBase <info@smartbase.sk>"]
66
readme = "README.md"

src/django_smartbase_admin/actions/admin_action_list.py

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
TABLE_PARAMS_SELECTED_FILTER_TYPE,
3636
ADVANCED_FILTER_DATA_NAME,
3737
IGNORE_LIST_SELECTION,
38+
MODIFIER_OBJECT_ID,
3839
)
3940
from django_smartbase_admin.services.views import SBAdminViewService
4041
from django_smartbase_admin.utils import import_with_injection
@@ -176,6 +177,23 @@ def get_template_data(self):
176177
}
177178

178179
columns, id_column_name = self.get_tabulator_columns_add_id_column_if_missing()
180+
row_actions = self.view.get_sbadmin_row_actions_processed(
181+
self.threadsafe_request
182+
)
183+
if row_actions:
184+
columns.append(
185+
{
186+
"field": "_row_actions",
187+
"title": "",
188+
"headerSort": False,
189+
"frozen": True,
190+
"sbadminKeepDataWidth": True,
191+
"sbadminSystemColumn": True,
192+
"hozAlign": "right",
193+
"formatter": "sbadminRowActionsFormatter",
194+
"cssClass": "row-actions-cell",
195+
}
196+
)
179197
tabulator_definition = (
180198
self.tabulator_definition
181199
or self.view.get_tabulator_definition(self.threadsafe_request)
@@ -184,8 +202,10 @@ def get_template_data(self):
184202
tabulator_definition["tableIdColumnName"] = id_column_name
185203
tabulator_definition["constants"] = constants
186204

187-
list_actions = self.list_actions or self.view._get_sbadmin_list_actions(
188-
self.threadsafe_request
205+
list_actions = (
206+
self.view.process_list_actions(self.threadsafe_request, self.list_actions)
207+
if self.list_actions is not None
208+
else self.view.get_sbadmin_list_actions_processed(self.threadsafe_request)
189209
)
190210

191211
context_data.update(
@@ -207,9 +227,7 @@ def get_template_data(self):
207227
"search_field_placeholder": self.view.get_search_field_placeholder(
208228
self.threadsafe_request
209229
),
210-
"list_actions": self.view.process_actions(
211-
self.threadsafe_request, list_actions
212-
),
230+
"list_actions": list_actions,
213231
"list_selection_actions": self.view.get_sbadmin_list_selection_actions_grouped(
214232
self.threadsafe_request
215233
),
@@ -456,6 +474,9 @@ def get_data(self, page_num=None, page_size=None, additional_filter=None):
456474
data=data,
457475
)
458476

477+
raw_rows_by_pk = {row[self.get_pk_field().name]: dict(row) for row in data}
478+
self.inject_row_actions(data, raw_rows_by_pk=raw_rows_by_pk)
479+
459480
return {
460481
"last_page": math.ceil(total_count / page_size),
461482
"data": data,
@@ -490,6 +511,48 @@ def process_final_data(self, final_data: list[dict[str, Any]]) -> None:
490511
value = escape(value)
491512
row[field_key] = value
492513

514+
def inject_row_actions(
515+
self, final_data: list[dict[str, Any]], raw_rows_by_pk: dict | None = None
516+
) -> None:
517+
actions = self.view.get_sbadmin_row_actions_processed(self.threadsafe_request)
518+
if not actions:
519+
return
520+
pk_field = self.get_pk_field().name
521+
for row in final_data:
522+
obj_id = row.get(pk_field)
523+
raw_row = (raw_rows_by_pk or {}).get(obj_id)
524+
row["_row_actions"] = [
525+
descriptor
526+
for action in actions
527+
if (
528+
descriptor := self._materialize_row_action(
529+
action, row, obj_id, raw_row=raw_row
530+
)
531+
)
532+
is not None
533+
]
534+
535+
def _materialize_row_action(
536+
self, action, row: dict[str, Any], obj_id: Any, raw_row=None
537+
) -> dict[str, Any] | None:
538+
action_row = raw_row or row
539+
if not action.is_enabled(action_row):
540+
return None
541+
542+
url = action.url
543+
if url and MODIFIER_OBJECT_ID in url:
544+
url = url.replace(MODIFIER_OBJECT_ID, str(obj_id))
545+
546+
return {
547+
"url": url,
548+
"title": str(action.get_title(action_row) or ""),
549+
"icon": action.get_icon(action_row),
550+
"css_class": action.get_css_class(action_row) or "",
551+
"open_in_modal": bool(action.open_in_modal),
552+
"is_method_action": bool(action.action_id) and not action.open_in_modal,
553+
"open_in_new_tab": bool(action.open_in_new_tab),
554+
}
555+
493556
def get_json_data(self):
494557
return self.get_data()
495558

src/django_smartbase_admin/admin/admin_base.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@
5454
)
5555
from django_smartbase_admin.engine.actions import SBAdminCustomAction
5656
from django_smartbase_admin.services.thread_local import SBAdminThreadLocalService
57-
from django_smartbase_admin.utils import FormFieldsetMixin, is_modal
57+
from django_smartbase_admin.utils import (
58+
FormFieldsetMixin,
59+
is_modal,
60+
render_notifications,
61+
)
5862

5963
parler_enabled = None
6064
try:
@@ -146,6 +150,7 @@
146150
OBJECT_ID_PLACEHOLDER,
147151
TRANSLATIONS_SELECTED_LANGUAGES,
148152
ROW_CLASS_FIELD,
153+
TABLE_RELOAD_DATA_EVENT_NAME,
149154
)
150155
from django_smartbase_admin.services.translations import SBAdminTranslationsService
151156
from django_smartbase_admin.services.views import SBAdminViewService
@@ -1033,6 +1038,16 @@ def get_modal_save_response(cls, request, obj):
10331038
trigger_client_event(response, "hideModal", {"elt": "sb-admin-modal"})
10341039
return response
10351040

1041+
def build_action_response(
1042+
self, request, *, reload_table=True, hide_modal=False
1043+
) -> HttpResponse:
1044+
response = HttpResponse(render_notifications(request))
1045+
if hide_modal:
1046+
trigger_client_event(response, "hideModal", {})
1047+
if reload_table:
1048+
trigger_client_event(response, TABLE_RELOAD_DATA_EVENT_NAME, {})
1049+
return response
1050+
10361051
def response_add(self, request, obj, post_url_continue=None):
10371052
if is_modal(request):
10381053
return self.get_modal_save_response(request, obj)
@@ -1111,6 +1126,11 @@ def get_queryset(self, request=None) -> QuerySet:
11111126
def get_sbadmin_inline_list_actions(self, request) -> list:
11121127
return [*(self.sbadmin_inline_list_actions or [])]
11131128

1129+
def get_sbadmin_inline_list_actions_processed(self, request) -> list:
1130+
return self.process_inline_actions(
1131+
request, self.get_sbadmin_inline_list_actions(request)
1132+
)
1133+
11141134
def get_action_url(self, action, modifier="template") -> str:
11151135
return reverse(
11161136
"sb_admin:sb_admin_base",
@@ -1126,6 +1146,9 @@ def register_autocomplete_views(self, request) -> None:
11261146
form_class = self.get_formset(request, None).form
11271147
self.initialize_form_class(form_class, request)
11281148
form_class()
1149+
self.register_action_autocomplete_views(
1150+
request, self.get_sbadmin_inline_list_actions_processed(request)
1151+
)
11291152

11301153
def get_parent_instance_from_request(self):
11311154
# Try to get parent instance from request referrer
@@ -1170,7 +1193,9 @@ def get_context_data(self, request) -> dict[str, Any]:
11701193
self.opts.model_name,
11711194
)
11721195
context_data = {
1173-
"inline_list_actions": self.get_sbadmin_inline_list_actions(request),
1196+
"inline_list_actions": self.get_sbadmin_inline_list_actions_processed(
1197+
request
1198+
),
11741199
"is_sortable_active": is_sortable_active,
11751200
"add_url": add_url,
11761201
}

0 commit comments

Comments
 (0)