Build raw service list view, refactor mixins

This commit is contained in:
Tobias Kunze 2025-03-21 15:37:23 +01:00 committed by Tobias Brunner
parent f0e34c2419
commit 8484fef8f2
No known key found for this signature in database
6 changed files with 98 additions and 18 deletions

View file

@ -0,0 +1,39 @@
{% extends "frontend/base.html" %}
{% load i18n static %}
{% block html_title %}
{% block page_title %}
{% translate "Services" %}
{% endblock page_title %}
{% endblock html_title %}
{% block card_content %}
<form class="search-form" auto-submit>
{{ filter_form }}
</form>
{% for service in services %}
<div class="col-12 col-md-6 col-lg-4 mb-4">
<div class="card h-100">
<div class="card-content">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
{% if service.logo %}
<img src="{{ service.logo.url }}"
alt="{{ service.name }}"
class="me-3"
style="max-width: 48px;
max-height: 48px">
{% endif %}
<h5 class="card-title mb-0">{{ service.name }}</h5>
</div>
{% if service.description %}<p class="card-text">{{ service.description }}</p>{% endif %}
</div>
<div class="card-footer d-flex justify-content-end">
<a href="#" class="btn btn-primary">{% translate "View Details" %}</a>
</div>
</div>
</div>
</div>
{% empty %}
<p>{% translate "No services found." %}</p>
{% endfor %}
<script src="{% static "js/autosubmit.js" %}" defer></script>
{% endblock card_content %}

View file

@ -20,6 +20,11 @@ urlpatterns = [
views.OrganizationUpdateView.as_view(), views.OrganizationUpdateView.as_view(),
name="organization.details", name="organization.details",
), ),
path(
"services/",
views.OrganizationServicesView.as_view(),
name="organization.services",
),
path( path(
"", "",
views.OrganizationDashboardView.as_view(), views.OrganizationDashboardView.as_view(),

View file

@ -5,6 +5,7 @@ from .organization import (
OrganizationDashboardView, OrganizationDashboardView,
OrganizationUpdateView, OrganizationUpdateView,
) )
from .service import OrganizationServicesView
__all__ = [ __all__ = [
"IndexView", "IndexView",
@ -12,5 +13,6 @@ __all__ = [
"OrganizationCreateView", "OrganizationCreateView",
"OrganizationDashboardView", "OrganizationDashboardView",
"OrganizationUpdateView", "OrganizationUpdateView",
"OrganizationServicesView",
"ProfileView", "ProfileView",
] ]

View file

@ -57,3 +57,29 @@ class HtmxUpdateView(AutoPermissionRequiredMixin, UpdateView):
if self.is_htmx and self._get_fragment(): if self.is_htmx and self._get_fragment():
return self.get(self.request, *self.args, **self.kwargs) return self.get(self.request, *self.args, **self.kwargs)
return result return result
class OrganizationViewMixin(PermissionRequiredMixin):
model = Organization
context_object_name = "organization"
permission_required = "core.view_organization"
@cached_property
def organization(self):
return self.request.organization
def get_object(self):
return self.organization
@cached_property
def object(self):
return self.get_object()
def get_permission_object(self):
return self.organization
def has_permission(self):
return (
self.request.user.has_perm("core.view_organization", self.organization)
and super().has_permission()
)

View file

@ -1,11 +1,10 @@
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.functional import cached_property
from django.views.generic import CreateView, DetailView from django.views.generic import CreateView, DetailView
from rules.contrib.views import AutoPermissionRequiredMixin from rules.contrib.views import AutoPermissionRequiredMixin
from servala.core.models import Organization from servala.core.models import Organization
from servala.frontend.forms import OrganizationForm from servala.frontend.forms import OrganizationForm
from servala.frontend.views.mixins import HtmxUpdateView from servala.frontend.views.mixins import HtmxUpdateView, OrganizationViewMixin
class OrganizationCreateView(AutoPermissionRequiredMixin, CreateView): class OrganizationCreateView(AutoPermissionRequiredMixin, CreateView):
@ -20,22 +19,6 @@ class OrganizationCreateView(AutoPermissionRequiredMixin, CreateView):
return redirect(instance.urls.base) return redirect(instance.urls.base)
class OrganizationViewMixin:
model = Organization
context_object_name = "organization"
@cached_property
def organization(self):
return self.request.organization
def get_object(self):
return self.organization
@cached_property
def object(self):
return self.get_object()
class OrganizationDashboardView( class OrganizationDashboardView(
AutoPermissionRequiredMixin, OrganizationViewMixin, DetailView AutoPermissionRequiredMixin, OrganizationViewMixin, DetailView
): ):

View file

@ -0,0 +1,25 @@
/**
* Auto-submit functionality for forms
*
* This script looks for forms with the 'auto-submit' attribute
* and automatically submits them when any input, select, or textarea
* within the form changes, useful for search/filter forms.
*/
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('form[auto-submit]').forEach(form => {
const formElements = form.querySelectorAll('input, select, textarea')
formElements.forEach(element => {
if (element.type === 'checkbox' || element.type === 'radio') {
element.addEventListener('change', () => {
form.submit()
})
}
else if (element.tagName.toLowerCase() === 'select') {
element.addEventListener('change', () => {
form.submit()
})
}
})
})
})