More code reuse + inline form rendering

This commit is contained in:
Tobias Kunze 2025-03-20 08:58:05 +01:00
parent b36ebcf5ff
commit eae01c74c7
2 changed files with 49 additions and 52 deletions

View file

@ -1,9 +1,14 @@
from servala.frontend.forms.renderers import InlineFormRenderer
class HtmxMixin:
"""
Form mixin that retains only a single field when specified.
Useful when sending single fields with htmx.
"""
default_renderer = InlineFormRenderer
def __init__(self, *args, **kwargs):
self.single_field = kwargs.pop("single_field", None)

View file

@ -12,68 +12,60 @@
</div>
{% endblock %}
{% partialdef user-email %}
<tr>
<th>{% translate "E-mail" %}</th>
<td>{{ request.user.email }}</td>
<td>
<button class="btn btn-sm btn-primary"
hx-get="{% url 'frontend:profile' %}?fragment=user-email-edit"
hx-target="closest tr"
hx-swap="outerHTML">{% translate "Edit" %}</button>
</td>
</tr>
<td>
{{ request.user.email }}
<button class="btn btn-primary"
hx-get="{% url 'frontend:profile' %}?fragment=user-email-edit"
hx-target="closest td"
hx-swap="outerHTML">{% translate "Edit" %}</button>
</td>
{% endpartialdef user-email %}
{% partialdef user-company %}
<tr>
<th>{% translate "Company" %}</th>
<td>{{ request.user.company|default_if_none:"" }}</td>
<td>
<button class="btn btn-sm btn-primary"
hx-get="{% url 'frontend:profile' %}?fragment=user-company-edit"
hx-target="closest tr"
hx-swap="outerHTML">{% translate "Edit" %}</button>
</td>
</tr>
<td>
{{ request.user.company|default_if_none:"" }}
<button class="btn btn-primary"
hx-get="{% url 'frontend:profile' %}?fragment=user-company-edit"
hx-target="closest td"
hx-swap="outerHTML">{% translate "Edit" %}</button>
</td>
{% endpartialdef user-company %}
{% partialdef user-email-edit %}
<tr>
<th>{% translate "E-mail" %}</th>
<td colspan="2">
<form hx-target="closest tr"
hx-swap="outerHTML"
hx-post="{{ request.url }}">
{{ form.email }}
<td>
<form hx-target="closest td"
hx-swap="outerHTML"
hx-post="{{ request.url }}">
<div class="d-flex align-items-baseline">
{{ form.email.as_field_group }}
<input type="hidden" name="hx-single-field" value="email">
<input type="hidden" name="fragment" value="user-email">
<button type="submit" class="btn btn-primary">{% translate "Save" %}</button>
<button type="submit" class="btn btn-primary mx-1">{% translate "Save" %}</button>
<button type="button"
class="btn btn-secondary"
hx-get="{{ request.path }}?fragment=user-email"
hx-target="closest tr"
hx-target="closest td"
hx-swap="outerHTML">{% translate "Cancel" %}</button>
</form>
</td>
</tr>
</div>
</form>
</td>
{% endpartialdef %}
{% partialdef user-company-edit %}
<tr>
<th>{% translate "Company" %}</th>
<td colspan="2">
<form hx-target="closest tr"
hx-swap="outerHTML"
hx-post="{{ request.url }}">
{{ form.company }}
<td>
<form hx-target="closest td"
hx-swap="outerHTML"
hx-post="{{ request.url }}">
<div class="d-flex align-items-baseline">
{{ form.company.as_field_group }}
<input type="hidden" name="hx-single-field" value="company">
<input type="hidden" name="fragment" value="user-company">
<button type="submit" class="btn btn-primary">{% translate "Save" %}</button>
<button type="submit" class="btn mx-1 btn-primary">{% translate "Save" %}</button>
<button type="button"
class="btn btn-secondary"
hx-get="{{ request.path }}?fragment=user-company"
hx-target="closest tr"
hx-target="closest td"
hx-swap="outerHTML">{% translate "Cancel" %}</button>
</form>
</td>
</tr>
</div>
</form>
</td>
{% endpartialdef %}
{% block content %}
<section>
@ -88,18 +80,18 @@
<div class="table-responsive">
<table class="table table-lg">
<tbody>
{% partial user-email %}
<tr>
<th>{% translate "First name" %}</th>
<td>{{ request.user.first_name }}</td>
<td></td>
<th class="w-25">{% translate "Name" %}</th>
<td>{{ request.user.first_name }} {{ request.user.last_name }}</td>
</tr>
<tr>
<th>{% translate "Last name" %}</th>
<td>{{ request.user.last_name }}</td>
<td></td>
<th class="w-25">{% translate "E-mail" %}</th>
{% partial user-email %}
</tr>
<tr>
<th class="w-25">{% translate "Company" %}</th>
{% partial user-company %}
</tr>
{% partial user-company %}
</tbody>
</table>
</div>