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(),
name="organization.details",
),
path(
"services/",
views.OrganizationServicesView.as_view(),
name="organization.services",
),
path(
"",
views.OrganizationDashboardView.as_view(),

View file

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

View file

@ -57,3 +57,29 @@ class HtmxUpdateView(AutoPermissionRequiredMixin, UpdateView):
if self.is_htmx and self._get_fragment():
return self.get(self.request, *self.args, **self.kwargs)
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.utils.functional import cached_property
from django.views.generic import CreateView, DetailView
from rules.contrib.views import AutoPermissionRequiredMixin
from servala.core.models import Organization
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):
@ -20,22 +19,6 @@ class OrganizationCreateView(AutoPermissionRequiredMixin, CreateView):
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(
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()
})
}
})
})
})