[FIX] HORILLA VIEWS: Active view type in Horilla nav

This commit is contained in:
Horilla
2024-07-29 16:50:00 +05:30
parent 2a546b12ef
commit 2581d2732b
6 changed files with 197 additions and 11 deletions

View File

@@ -1,5 +1,13 @@
from django.contrib import admin
from horilla_views.models import ActiveGroup, ActiveTab, ToggleColumn
from horilla_views import models
admin.site.register([ToggleColumn, ActiveTab, ActiveGroup])
admin.site.register(
[
models.ToggleColumn,
models.ActiveTab,
models.ActiveGroup,
models.SavedFilter,
models.ActiveView,
]
)

View File

@@ -7,6 +7,7 @@ from django.template.loader import render_to_string
from django.utils.safestring import SafeText
from horilla.horilla_middlewares import _thread_locals
from horilla_views import models
class ToggleColumnForm(forms.Form):
@@ -34,3 +35,43 @@ class ToggleColumnForm(forms.Form):
context = {"form": self, "request": self.request}
table_html = render_to_string("generic/as_list.html", context)
return table_html
class SavedFilterForm(forms.ModelForm):
"""
SavedFilterForm
"""
color = forms.CharField(
widget=forms.TextInput(
attrs={
"class": "oh-input w-100",
"type": "color",
"placeholder": "Choose a color",
}
)
)
class Meta:
model = models.SavedFilter
fields = ["title", "is_default", "color"]
def structured(self):
"""
Render the form fields as HTML table rows with Bootstrap styling.
"""
request = getattr(_thread_locals, "request", None)
context = {
"form": self,
"request": request,
}
table_html = render_to_string("common_form.html", context)
return table_html
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
attrs = self.fields["title"].widget.attrs
attrs["class"] = "oh-input w-100"
attrs["placeholder"] = "Saved filter title"
if self.instance.pk:
self.verbose_name = self.instance.title

View File

@@ -50,3 +50,38 @@ class ActiveGroup(HorillaModel):
path = models.CharField(max_length=256)
group_target = models.CharField(max_length=256)
group_by_field = models.CharField(max_length=256)
class SavedFilter(HorillaModel):
"""
SavedFilter
"""
title = models.CharField(max_length=20, null=True)
color = models.CharField(max_length=10, default="")
is_default = models.BooleanField(default=False)
filter = models.TextField()
urlencode = models.TextField(default="")
path = models.CharField(max_length=256)
referrer = models.CharField(max_length=256, default="")
def save(self, *args, **kwargs):
SavedFilter.objects.filter(
is_default=True, path=self.path, created_by=self.created_by
).exclude(id=self.pk).update(is_default=False)
return super().save(*args, **kwargs)
def __str__(self) -> str:
return str(self.title)
class ActiveView(HorillaModel):
"""
This model to store the active view type for HNV
"""
path = models.CharField(max_length=256)
type = models.CharField(max_length=50)
def save(self, *args, **kwargs):
return super().save(*args, **kwargs)

View File

@@ -14,7 +14,7 @@
></ion-icon>
</a>
</div>
<form autocomplete="off" id="filterForm" onsubmit="event.preventDefault()" hx-get="{{search_url}}" hx-replace-url="true" hx-target="{{search_swap_target}}" class="oh-main__titlebar oh-main__titlebar--right">
<form autocomplete="off" id="filterForm" onsubmit="event.preventDefault()" hx-get="{{search_url}}?&referrer={{request.META.HTTP_REFERER}}&{{request.GET.urlencode}}" hx-replace-url="true" hx-target="{{search_swap_target}}" class="oh-main__titlebar oh-main__titlebar--right">
<div class="oh-input-group oh-input__search-group" id="searchGroup">
<ion-icon
name="search-outline"
@@ -73,11 +73,20 @@
{% if view_types %}
<ul class="oh-view-types">
{% for type in view_types %}
<li class="oh-view-type" onclick="$(this).closest('form').attr('hx-get','{{type.url}}');$(this).closest('form').find('#applyFilter').click();
<li class="oh-view-type" data-url="{{type.url}}" data-type="{{type.type}}" hx-get="{% url "active-hnv-view-type" %}?view={{type.type}}&path={{request.path}}" hx-swap="none" onclick="$(this).closest('form').attr('hx-get','{{type.url}}?&referrer={{request.META.HTTP_REFERER}}&{{request.GET.urlencode}}');$(this).closest('form').find('#applyFilter').click();
">
<a class="oh-btn oh-btn--view" {{type.attrs|safe}}
><ion-icon name="{{type.icon}}"></ion-icon
></a>
{% if active_view.type == type.type %}
<script>
$("form#filterForm.oh-main__titlebar oh-main__titlebar--right").attr('hx-get','{{type.url}}?&referrer={{request.META.HTTP_REFERER}}&{{request.GET.urlencode}}');
setTimeout(() => {
$(".oh-view-types .oh-view-type[data-type={{type.type}}]").click()
$(".oh-view-types .oh-view-type[data-type={{type.type}}] a").addClass("oh-btn--view-active")
}, 10);
</script>
{% endif %}
</li>
{% endfor %}
</ul>

View File

@@ -13,4 +13,20 @@ urlpatterns = [
path("active-group", views.ActiveGroup.as_view(), name="cbv-active-group"),
path("reload-field", views.ReloadField.as_view(), name="reload-field"),
path("reload-messages", ReloadMessages.as_view(), name="reload-messages"),
path("saved-filter/", views.SavedFilter.as_view(), name="saved-filter"),
path(
"saved-filter/<int:pk>/",
views.SavedFilter.as_view(),
name="saved-filter-update",
),
path(
"delete-saved-filter/<int:pk>/",
views.DeleteSavedFilter.as_view(),
name="delete-saved-filter",
),
path(
"active-hnv-view-type/",
views.ActiveView.as_view(),
name="active-hnv-view-type",
),
]

View File

@@ -1,17 +1,22 @@
import importlib
from django import forms
from django.contrib import messages
from django.core.cache import cache as CACHE
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.views import View
from horilla_views import models
from horilla_views.cbv_methods import get_short_uuid
from horilla_views.generic.cbv.views import dynamic_create_cache
from horilla_views.cbv_methods import get_short_uuid, login_required
from horilla_views.forms import SavedFilterForm
from horilla_views.generic.cbv.views import HorillaFormView
# Create your views here.
@method_decorator(login_required, name="dispatch")
class ToggleColumn(View):
"""
ToggleColumn
@@ -42,6 +47,7 @@ class ToggleColumn(View):
return HttpResponse("success")
@method_decorator(login_required, name="dispatch")
class ReloadField(View):
"""
ReloadField
@@ -58,17 +64,15 @@ class ReloadField(View):
module = importlib.import_module(module_name)
parent_form = getattr(module, class_name)()
dynamic_cache = dynamic_create_cache.get(
request.session.session_key + reload_field
)
form: forms.ModelForm = dynamic_cache["form"]
dynamic_cache = CACHE.get(request.session.session_key + "cbv" + reload_field)
model: models.HorillaModel = dynamic_cache["model"]
cache_field = dynamic_cache["dynamic_field"]
if cache_field != reload_field:
cache_field = reload_field
field = parent_form.fields[cache_field]
queryset = form._meta.model.objects.all()
queryset = model.objects.all()
queryset = field.queryset
choices = [(instance.id, instance) for instance in queryset]
choices.insert(0, ("", "Select option"))
@@ -91,6 +95,7 @@ class ReloadField(View):
)
@method_decorator(login_required, name="dispatch")
class ActiveTab(View):
def get(self, *args, **kwargs):
"""
@@ -112,6 +117,7 @@ class ActiveTab(View):
return JsonResponse({"message": "Success"})
@method_decorator(login_required, name="dispatch")
class ActiveGroup(View):
def get(self, *args, **kwargs):
"""
@@ -135,3 +141,74 @@ class ActiveGroup(View):
instance.group_target = target
instance.save()
return JsonResponse({"message": "Success"})
@method_decorator(login_required, name="dispatch")
class SavedFilter(HorillaFormView):
"""
SavedFilter
"""
model = models.SavedFilter
form_class = SavedFilterForm
new_display_title = "Save Applied Filter"
template_name = "generic/saved_filter_form.html"
form_disaply_attr = "Blah"
def form_valid(self, form: SavedFilterForm) -> HttpResponse:
referrer = self.request.POST.get("referrer", "")
path = self.request.POST.get("path", "/")
result_dict = {key: value[0] for key, value in self.request.GET.lists()}
if form.is_valid():
instance: models.SavedFilter = form.save(commit=False)
if not instance.pk:
instance.path = path
instance.referrer = referrer
instance.filter = result_dict
instance.urlencode = self.request.GET.urlencode()
instance.save()
messages.success(self.request, "Filter Saved")
return self.HttpResponse()
return super().form_valid(form)
def get_context_data(self, **kwargs) -> dict:
context = super().get_context_data(**kwargs)
referrer = self.request.GET.get("referrer", "")
if referrer:
# Remove the protocol and domain part
referrer = "/" + "/".join(referrer.split("/")[3:])
context["path"] = self.request.GET.get("path", "")
context["referrer"] = referrer
return context
@method_decorator(login_required, name="dispatch")
class DeleteSavedFilter(View):
"""
Delete saved filter
"""
def get(self, *args, **kwargs):
pk = kwargs["pk"]
models.SavedFilter.objects.filter(created_by=self.request.user, pk=pk).delete()
return HttpResponse("")
@method_decorator(login_required, name="dispatch")
class ActiveView(View):
"""
ActiveView CBV
"""
def get(self, *args, **kwargs):
path = self.request.GET["path"]
view_type = self.request.GET["view"]
active_view = models.ActiveView.objects.filter(
path=path, created_by=self.request.user
).first()
active_view = active_view if active_view else models.ActiveView()
active_view.path = path
active_view.type = view_type
active_view.save()
return HttpResponse("")