Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
527 changes: 527 additions & 0 deletions AGENTS.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-smartbase-admin"
version = "2.0.9"
version = "2.0.10b2"
description = ""
authors = ["SmartBase <info@smartbase.sk>"]
readme = "README.md"
Expand Down
7 changes: 6 additions & 1 deletion src/django_smartbase_admin/actions/admin_action_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
TABLE_PARAMS_FULL_TEXT_SEARCH,
TABLE_PARAMS_SELECTED_FILTER_TYPE,
ADVANCED_FILTER_DATA_NAME,
PARENT_FILTER_DATA_NAME,
IGNORE_LIST_SELECTION,
MODIFIER_OBJECT_ID,
SB_ADMIN_AJAX_NOTIFICATIONS_KEY,
Expand Down Expand Up @@ -198,6 +199,7 @@ def get_template_data(self):
"TABLE_PARAMS_SELECTED_FILTER_TYPE": TABLE_PARAMS_SELECTED_FILTER_TYPE,
"FILTER_DATA_NAME": FILTER_DATA_NAME,
"ADVANCED_FILTER_DATA_NAME": ADVANCED_FILTER_DATA_NAME,
"PARENT_FILTER_DATA_NAME": PARENT_FILTER_DATA_NAME,
"BASE_PARAMS_NAME": BASE_PARAMS_NAME,
"TABLE_PARAMS_PAGE_NAME": TABLE_PARAMS_PAGE_NAME,
"TABLE_PARAMS_SORT_NAME": TABLE_PARAMS_SORT_NAME,
Expand Down Expand Up @@ -303,7 +305,10 @@ def get_filter_from_request(self):
self.threadsafe_request, self.column_fields, self.filter_data
)
advanced_filters = QueryBuilderService.get_filters_for_list_action(self)
return base_filters & advanced_filters
extra_filters = self.view.get_extra_filter_from_request(
self.threadsafe_request, self
)
return base_filters & advanced_filters & extra_filters

def get_search_fields(self, request):
search_fields_definition = self.view.get_search_fields(request)
Expand Down
5 changes: 4 additions & 1 deletion src/django_smartbase_admin/engine/admin_base_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from django.contrib import messages
from django.contrib.admin.actions import delete_selected
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.db.models import F
from django.db.models import F, Q
from django.http import HttpResponse, JsonResponse, HttpRequest, Http404
from django.shortcuts import redirect
from django.template.response import TemplateResponse
Expand Down Expand Up @@ -673,6 +673,9 @@ class SBAdminBaseListView(SBAdminBaseView):
def get_list_view_media(self, request):
return forms.Media(js=("sb_admin/dist/table.js",))

def get_extra_filter_from_request(self, request, list_action):
return Q()

@classmethod
def _postgres_unaccent_extension_available(cls) -> bool:
from django.conf import settings
Expand Down
1 change: 1 addition & 0 deletions src/django_smartbase_admin/engine/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class FilterVersions(Enum):
TABLE_UPDATE_ROW_DATA_EVENT_NAME = "SBAdminUpdateRowData"
FILTER_DATA_NAME = "filterData"
ADVANCED_FILTER_DATA_NAME = "advancedFilterData"
PARENT_FILTER_DATA_NAME = "parentFilterData"
BASE_PARAMS_NAME = "params"
AUTOCOMPLETE_SEARCH_NAME = "__search_term__"
AUTOCOMPLETE_FORWARD_NAME = "__forward_data__"
Expand Down
107 changes: 101 additions & 6 deletions src/django_smartbase_admin/engine/dashboard.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
from copy import copy
from datetime import timedelta

from django import forms
from django.core.cache import cache
from django.core.exceptions import ImproperlyConfigured
from django.db import models
from django.db.models import QuerySet
from django.db.models.functions import TruncMonth, TruncDay, TruncWeek, TruncYear
from django.db.models import Q, QuerySet
from django.db.models.functions import TruncDay, TruncMonth, TruncWeek, TruncYear
from django.http import JsonResponse
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from django_smartbase_admin.actions.admin_action_list import SBAdminListAction
from django_smartbase_admin.engine.actions import sbadmin_action
from django_smartbase_admin.engine.admin_base_view import SBAdminBaseListView
from django_smartbase_admin.engine.admin_view import SBAdminView
from django_smartbase_admin.engine.const import OBJECT_ID_PLACEHOLDER
from django_smartbase_admin.engine.const import (
OBJECT_ID_PLACEHOLDER,
PARENT_FILTER_DATA_NAME,
)
from django_smartbase_admin.engine.field import SBAdminField
from django_smartbase_admin.engine.filter_widgets import (
DateFilterWidget,
Expand Down Expand Up @@ -75,6 +78,12 @@ def init_widget_static(self, configuration):
filter.init_field_static(self, configuration)
for setting in self.get_settings():
setting.init_field_static(self, configuration)
for index, sub_widget in enumerate(self.get_sub_widgets()):
sub_widget.init_sub_widget_dynamic(str(index), self)
sub_widget.init_widget_static(configuration)
sub_widget_id = sub_widget.get_id()
if sub_widget_id:
configuration.view_map[sub_widget_id] = sub_widget

def get_id(self):
return self.widget_id
Expand All @@ -90,6 +99,11 @@ def get_ajax_url(self, request=None):
"action_get_data", object_id=self.get_parent_instance_id(request)
)

def get_filter_form_id(self):
if self.parent_view is not None:
return f"{self.parent_view.get_id()}-filter-form"
return f"{self.get_id()}-filter-form"

def get_parent_instance_id(self, request):
request_data = getattr(request, "request_data", None)
return getattr(request_data, "object_id", None)
Expand Down Expand Up @@ -119,15 +133,21 @@ def action_get_data(self, request, modifier, object_id=None):
return JsonResponse(data={"data": self.get_cached_data(request)})

def get_widget_context_data(self, request):
return {
parent_group_widget = self.get_parent_group_widget()
context = {
"widget_id": self.get_id(),
"widget_name": self.name,
"ajax_url": self.get_ajax_url(request),
"filters": self.get_filters(),
"settings": self.get_settings(),
"sub_widgets": self.get_sub_widgets(),
"request": request,
"filter_form_id": self.get_filter_form_id(),
}
if parent_group_widget:
context["parent_widget_id"] = parent_group_widget.get_id()
else:
context["ajax_url"] = self.get_ajax_url(request)
return context

def get_sub_widgets(self):
return self.widget_views if self.widget_views is not None else self.sub_widgets
Expand Down Expand Up @@ -188,6 +208,38 @@ def get_active_sub_widget(self, request):
return sub_widget
return next(iter(sub_widgets), None)

def init_sub_widget_dynamic(self, sub_widget_id, parent_view):
self.widget_id = sub_widget_id
self.view_id = sub_widget_id
self.parent_view = parent_view

def get_parent_group_widget(self):
parent_view = self.parent_view
if parent_view is not None and isinstance(
parent_view, SBAdminDashboardGroupWidget
):
return parent_view
return None

def init_view_dynamic(self, request, request_data=None, **kwargs):
result = super().init_view_dynamic(request, request_data, **kwargs)
for sub_widget in self.get_sub_widgets():
sub_widget.init_view_dynamic(request, request_data, **kwargs)
return result


class SBAdminDashboardGroupWidget(SBAdminDashboardWidget):
template_name = "sb_admin/dashboard/group_widget.html"
media = forms.Media(js=("sb_admin/dist/dashboard_group.js",))

def get_data(self, request):
return {
"sub_widget": {
sub_widget.get_id(): sub_widget.get_data(request)
Comment thread
mihalikv marked this conversation as resolved.
for sub_widget in self.get_sub_widgets()
}
}


class SBAdminChartAggregateSubWidget(object):
title = None
Expand Down Expand Up @@ -253,6 +305,33 @@ def init_view_dynamic(self, request, request_data=None, **kwargs):
pass


class SBAdminDashboardHtmlWidget(SBAdminDashboardWidget):
template_name = "sb_admin/dashboard/html_widget.html"
content_template_name = None

def get_html_context_data(self, request):
return {}

def get_html(self, request):
if self.content_template_name is None:
raise ImproperlyConfigured(
f"{self.__class__.__name__} must define content_template_name."
)
return render_to_string(
self.content_template_name,
self.get_html_context_data(request),
request=request,
)

def get_data(self, request):
return {"html": self.get_html(request)}

def get_widget_context_data(self, request):
context = super().get_widget_context_data(request)
context["html"] = self.get_html(request)
return context


class SBAdminDashboardChartWidget(SBAdminDashboardWidget):
template_name = "sb_admin/dashboard/chart_widget.html"
media = forms.Media(js=("sb_admin/dist/chart.js",))
Expand Down Expand Up @@ -715,6 +794,17 @@ def get_queryset(self, request=None):
qs = super().get_queryset(request)
return self._filter_queryset_by_parent_request(request, qs)

def get_extra_filter_from_request(self, request, list_action):
return self.get_filter_from_dashboard_filter(
request, list_action.params.get(PARENT_FILTER_DATA_NAME, {})
)

def get_filter_from_dashboard_filter(self, request, dashboard_filter_data):
return Q()

def get_data(self, request):
return {}

def init_view_dynamic(self, request, request_data=None, **kwargs):
super().init_view_dynamic(request, request_data, **kwargs)
self.init_fields_cache(
Expand All @@ -740,6 +830,9 @@ def get_tabulator_header_template_name(self, request) -> str:

def get_tabulator_definition(self, request):
tabulator_definition = super().get_tabulator_definition(request)
parent_group_widget = self.get_parent_group_widget()
if parent_group_widget:
tabulator_definition["parentWidgetId"] = parent_group_widget.get_id()
tabulator_definition["stickyHeaderAndFooter"] = False
tabulator_definition["modules"] = [
"viewsModule",
Expand All @@ -748,6 +841,8 @@ def get_tabulator_definition(self, request):
"filterModule",
"columnDisplayModule",
]
if parent_group_widget:
tabulator_definition["modules"].append("dashboardParentFilterModule")
return tabulator_definition


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const entries = {
main: './src/django_smartbase_admin/static/sb_admin/src/js/main.js',
table: './src/django_smartbase_admin/static/sb_admin/src/js/table.js',
chart: './src/django_smartbase_admin/static/sb_admin/src/js/chart.js',
dashboard_group: './src/django_smartbase_admin/static/sb_admin/src/js/dashboard_group.js',
calendar: './src/django_smartbase_admin/static/sb_admin/src/js/calendar.js',
main_style: './src/django_smartbase_admin/static/sb_admin/src/css/style.css',
translations: './src/django_smartbase_admin/static/sb_admin/src/js/translations.js',
Expand Down
Loading
Loading