Skip to content

Commit

Permalink
Use htmx for POST endpoints
Browse files Browse the repository at this point in the history
Only update the elements that needs to be updated.
  • Loading branch information
stveit committed Dec 5, 2024
1 parent 157f0e8 commit 267f093
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 39 deletions.
7 changes: 4 additions & 3 deletions src/argus/htmx/destination/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from django.urls import path

from .views import destination_list, destination_delete, destination_update
from .views import destination_list, create_htmx, delete_htmx, update_htmx

app_name = "htmx"
urlpatterns = [
path("", destination_list, name="destination-list"),
path("<int:pk>/delete/", destination_delete, name="destination-delete"),
path("<int:pk>/", destination_update, name="destination-update"),
path("htmx-create/", create_htmx, name="htmx-create"),
path("<int:pk>/htmx-delete/", delete_htmx, name="htmx-delete"),
path("<int:pk>/htmx-update/", update_htmx, name="htmx-update"),
]
33 changes: 17 additions & 16 deletions src/argus/htmx/destination/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,58 +11,59 @@
from .forms import DestinationFormCreate, DestinationFormUpdate


@require_http_methods(["GET", "POST"])
@require_http_methods(["GET"])
def destination_list(request):
if request.method == "GET":
return _render_destination_list(request)
elif request.method == "POST":
return destination_create(request)
return _render_destination_list(request)


def destination_create(request) -> HttpResponse:
@require_http_methods(["POST"])
def create_htmx(request) -> HttpResponse:
form = DestinationFormCreate(request.POST or None, request=request)
template = "htmx/destination/_content.html"
if form.is_valid():
form.save()
return _render_destination_list(request)
return _render_destination_list(request, create_form=form)
return _render_destination_list(request, template=template)
return _render_destination_list(request, create_form=form, template=template)


@require_http_methods(["POST"])
def destination_delete(request, pk: int) -> HttpResponse:
def delete_htmx(request, pk: int) -> HttpResponse:
destination = get_object_or_404(request.user.destinations.all(), pk=pk)

template = "htmx/destination/_form_list.html"
try:
medium = api_safely_get_medium_object(destination.media.slug)
medium.raise_if_not_deletable(destination)
except NotificationMedium.NotDeletableError:
error_msg = "This destination cannot be deleted."
return _render_destination_list(request, errors=[error_msg])
return _render_destination_list(request, errors=[error_msg], template=template)
else:
destination.delete()
return _render_destination_list(request)
return _render_destination_list(request, template=template)


@require_http_methods(["POST"])
def destination_update(request, pk: int) -> HttpResponse:
def update_htmx(request, pk: int) -> HttpResponse:
destination = DestinationConfig.objects.get(pk=pk)
form = DestinationFormUpdate(request.POST or None, instance=destination, request=request)
template = "htmx/destination/_form_list.html"
if form.is_valid():
form.save()
return _render_destination_list(request)
return _render_destination_list(request, template=template)

update_forms = _get_update_forms(request.user)
for index, update_form in enumerate(update_forms):
if update_form.instance.pk == pk:
update_forms[index] = form
break
return _render_destination_list(request, update_forms=update_forms)
return _render_destination_list(request, update_forms=update_forms, template=template)


def _render_destination_list(
request,
create_form: Optional[DestinationFormCreate] = None,
update_forms: Optional[Sequence[DestinationFormUpdate]] = None,
errors: Optional[Sequence[str]] = None,
template: str = "htmx/destination/destination_list.html",
) -> HttpResponse:
"""Function to render the destinations page.
Expand All @@ -86,7 +87,7 @@ def _render_destination_list(
"grouped_forms": grouped_forms,
"errors": errors,
}
return render(request, "htmx/destination/destination_list.html", context=context)
return render(request, template, context=context)


def _get_update_forms(user) -> list[DestinationFormUpdate]:
Expand Down
5 changes: 5 additions & 0 deletions src/argus/htmx/templates/htmx/destination/_content.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div id="destination-content">
{% include "htmx/destination/_create_form.html" %}
{% for error in errors %}<p class="text-error">{{ error }}</p>{% endfor %}
{% include "htmx/destination/_form_list.html" %}
</div>
4 changes: 3 additions & 1 deletion src/argus/htmx/templates/htmx/destination/_create_form.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<form action="{% url 'htmx:destination-list' %}" method="post">
<form hx-post="{% url 'htmx:htmx-create' %}"
hx-trigger="submit"
hx-target="#destination-content">
{% csrf_token %}
<fieldset class="p-2 border rounded-box border-primary items-center gap-4 flex items-end">
<legend class="menu-title">Create destination</legend>
Expand Down
5 changes: 3 additions & 2 deletions src/argus/htmx/templates/htmx/destination/_delete_form.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<form action="{% url 'htmx:destination-delete' form.instance.id %}"
method="post">
<form hx-post="{% url 'htmx:htmx-delete' form.instance.id %}"
hx-trigger="submit"
hx-target="#form-list">
{% csrf_token %}
<fieldset class="menu menu-horizontal menu-md items-center gap-4">
<input type="submit" value="Delete" class="btn btn-secondary">
Expand Down
5 changes: 3 additions & 2 deletions src/argus/htmx/templates/htmx/destination/_edit_form.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<form action="{% url 'htmx:destination-update' form.instance.id %}"
method="post"
<form hx-post="{% url 'htmx:htmx-update' form.instance.id %}"
hx-trigger="submit"
hx-target="#form-list"
class="flex flex-nowrap items-center gap-4">
{% csrf_token %}
<fieldset class="flex flex-nowrap items-center gap-4">
Expand Down
15 changes: 15 additions & 0 deletions src/argus/htmx/templates/htmx/destination/_form_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div id="form-list">
{% for media, forms in grouped_forms.items %}
<details class="collapse bg-base-200 collapse-arrow" open="">
<summary class="collapse-title text-xl font-medium">{{ media.name }} ({{ forms|length }})</summary>
<div class="collapse-content">
{% for form in forms %}
<div class="flex w-full h-fit items-center">
{% include "htmx/destination/_edit_form.html" %}
{% include "htmx/destination/_delete_form.html" %}
</div>
{% endfor %}
</div>
</details>
{% endfor %}
</div>
16 changes: 1 addition & 15 deletions src/argus/htmx/templates/htmx/destination/destination_list.html
Original file line number Diff line number Diff line change
@@ -1,18 +1,4 @@
{% extends "htmx/base.html" %}
{% block main %}
{% include "htmx/destination/_create_form.html" %}
{% for error in errors %}<p class="text-error">{{ error }}</p>{% endfor %}
{% for media, forms in grouped_forms.items %}
<details class="collapse bg-base-200 collapse-arrow" open="">
<summary class="collapse-title text-xl font-medium">{{ media.name }} ({{ forms|length }})</summary>
<div class="collapse-content">
{% for form in forms %}
<div class="flex w-full h-fit items-center">
{% include "htmx/destination/_edit_form.html" %}
{% include "htmx/destination/_delete_form.html" %}
</div>
{% endfor %}
</div>
</details>
{% endfor %}
{% include "htmx/destination/_content.html" %}
{% endblock main %}

0 comments on commit 267f093

Please sign in to comment.