diff --git a/atlas/templates/atlas/index.html b/atlas/templates/atlas/index.html
index c616633b..ee9f269b 100644
--- a/atlas/templates/atlas/index.html
+++ b/atlas/templates/atlas/index.html
@@ -29,6 +29,14 @@
+
+
diff --git a/atlas/templates/atlas/partials/_user_collections.html b/atlas/templates/atlas/partials/_user_collections.html
new file mode 100644
index 00000000..9d2141ea
--- /dev/null
+++ b/atlas/templates/atlas/partials/_user_collections.html
@@ -0,0 +1,46 @@
+{% comment %}Partial listing of a user's collections for HTMX swaps{% endcomment %}
+
+
+
+
Your collections
+
+
Available to start
+
+ {% for collection in available_collections %}
+ -
+ {{ collection.name }}
+ {% if collection.description %} — {{ collection.description }}{% endif %}
+
+ {% empty %}
+ - No collections available to start.
+ {% endfor %}
+
+
+
In progress
+
+ {% for collection in in_progress_collections %}
+ -
+ {{ collection.name }}
+ In progress
+ {% if collection.description %} — {{ collection.description }}{% endif %}
+
+ {% empty %}
+ - No in-progress collections.
+ {% endfor %}
+
+
+
Finished
+
+ {% for collection in finished_collections %}
+ -
+ {{ collection.name }}
+ Completed
+ {% if collection.description %} — {{ collection.description }}{% endif %}
+
+ {% empty %}
+ - No finished collections.
+ {% endfor %}
+
+
+
+
diff --git a/atlas/templates/atlas/user_collections.html b/atlas/templates/atlas/user_collections.html
index 13df6cd5..4db4221c 100644
--- a/atlas/templates/atlas/user_collections.html
+++ b/atlas/templates/atlas/user_collections.html
@@ -3,51 +3,12 @@
{% block content %}
Collections
- The following collections are available for you to view / take. If you received a directly link to a collection it will not appear here unless you have started it.
+
+ The following collections are available for you to view / take. If you received a direct
+ link to a collection it will not appear here unless you have started it.
+
-
-
Available to start
-
- {% for collection in available_collections %}
- -
- {{ collection.name }}
- {% if collection.description %}
- — {{ collection.description }}
- {% endif %}
-
- {% empty %}
- - No collections available to start.
- {% endfor %}
-
-
-
In progress
-
- {% for collection in in_progress_collections %}
- -
- {{ collection.name }}
- In progress
- {% if collection.description %}
- — {{ collection.description }}
- {% endif %}
-
- {% empty %}
- - No in-progress collections.
- {% endfor %}
-
-
-
Finished
-
- {% for collection in finished_collections %}
- -
- {{ collection.name }}
- Completed
- {% if collection.description %}
- — {{ collection.description }}
- {% endif %}
-
- {% empty %}
- - No finished collections.
- {% endfor %}
-
+ {# Reuse the HTMX-friendly partial so the same markup is used for full-page and HTMX responses #}
+ {% include 'atlas/partials/_user_collections.html' %}
{% endblock %}
diff --git a/atlas/views.py b/atlas/views.py
index 5abd3eaa..0c913aae 100755
--- a/atlas/views.py
+++ b/atlas/views.py
@@ -1131,15 +1131,25 @@ def user_collections(request):
# Finished (completed)
finished_qs = CaseCollection.objects.filter(pk__in=list(finished_ids)).order_by("name")
- return render(
- request,
- "atlas/user_collections.html",
- {
- "available_collections": available_qs,
- "in_progress_collections": in_progress_qs,
- "finished_collections": finished_qs,
- },
- )
+ context = {
+ "available_collections": available_qs,
+ "in_progress_collections": in_progress_qs,
+ "finished_collections": finished_qs,
+ }
+
+ # If called via HTMX return a small fragment suitable for swapping
+ # into the index page. Otherwise render the full page.
+ is_htmx = getattr(request, "htmx", False) or request.headers.get("HX-Request", "").lower() == "true"
+ if is_htmx:
+ html = render_to_string("atlas/partials/_user_collections.html", context, request=request)
+ return HttpResponse(html)
+
+ return render(request, "atlas/user_collections.html", context)
+
+
+ # Note: keep the above full-page render for normal requests. If this
+ # endpoint is called by HTMX we prefer returning a small fragment so it
+ # can be swapped into the index page without duplicating layout.
@login_required
def collection_options(request):