Add case collection update functionality with form handling and template (move from CaseCollection form)

This commit is contained in:
Ross
2025-08-04 12:21:37 +01:00
parent c33e8c0240
commit 0af6b25349
6 changed files with 161 additions and 17 deletions
+18 -1
View File
@@ -992,4 +992,21 @@ class CaseDisplaySetForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Optionally, you can filter queryset for findings/structures/conditions here if needed
# Optionally, you can filter queryset for findings/structures/conditions here if needed
class CaseCollectionUpdateCaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user")
self.collection = kwargs.pop("collection", None)
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = "id-case-form"
self.helper.form_class = "case-form"
self.helper.form_method = "post"
self.helper.form_action = "submit"
self.helper.form_tag = False
self.helper.layout = Layout()
class Meta:
model = CaseCollection
fields = [] # No fields, just for compatibility with UpdateView
@@ -37,7 +37,7 @@
{% csrf_token %}
{{ form }}
<h3>Cases:</h3>
{% comment %} <h3>Cases:</h3>
Add cases here. These can only be added once created (they can also be added to cases on creation). Click and drag to change order.
<input type="button" value="Add More Cases" id="add_more_case">
<input type=button id="case-order-button" title="click and drag to update case order" value="Update case order" />
@@ -54,13 +54,14 @@
</div>
{{ case_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<div id="empty_case_form" style="display:none">
<li class='no_error case-formset'>
{{ case_formset.empty_form }}
</li>
</div>
</div> {% endcomment %}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<script>
$(document).ready(() => {
sortable('.sortable');
@@ -0,0 +1,77 @@
{% extends "atlas/exams.html" %}
{% load crispy_forms_tags %}
{% load static %}
{% block content %}
<h2>Update Cases for Case: {{ object.title }}</h2>
<form method="post" enctype="multipart/form-data" data-bs-theme="dark">
{% csrf_token %}
{% crispy form form.helper %}
{{ case_formset.management_form }}
<div id="case_formset">
{% for form in case_formset %}
<div class="card mb-3 case-form">
<div class="card-body">
{{ form.non_field_errors }}
{{ form.errors }}
{{ form|crispy }}
{% if form.can_delete %}
<div class="form-check mt-2">
{{ form.DELETE }} <label for="{{ form.DELETE.id_for_label }}">Delete</label>
</div>
{% endif %}
</div>
</div>
{% endfor %}
<!-- Empty form template for JS -->
<div id="empty-form" style="display:none;">
<div class="card mb-3 case-form">
<div class="card-body">
{{ case_formset.empty_form|crispy }}
{% if case_formset.empty_form.can_delete %}
<div class="form-check mt-2">
{{ case_formset.empty_form.DELETE }} <label for="{{ case_formset.empty_form.DELETE.id_for_label }}">Delete</label>
</div>
{% endif %}
</div>
</div>
</div>
<button type="button" id="add-case" class="btn btn-secondary mt-2">Add Case</button>
<button type="submit" class="btn btn-primary">Save</button>
{% comment %} <input type=button id="case-order-button" title="click and drag to update case order" value="Update case order" /> {% endcomment %}
</form>
<script>
document.addEventListener("DOMContentLoaded", function() {
const addBtn = document.getElementById("add-case");
const formsetDiv = document.getElementById("case_formset");
const emptyFormDiv = document.getElementById("empty-form");
let totalForms = document.getElementById("id_casedetail_set-TOTAL_FORMS");
addBtn.addEventListener("click", function() {
let formIdx = parseInt(totalForms.value);
let newFormHtml = emptyFormDiv.innerHTML.replace(/__prefix__/g, formIdx);
let tempDiv = document.createElement('div');
tempDiv.innerHTML = newFormHtml;
// Clear the id field value for the new form
let idInput = tempDiv.querySelector('input[name$="-id"]');
if (idInput) {
idInput.value = "";
}
formsetDiv.appendChild(tempDiv.firstElementChild);
totalForms.value = formIdx + 1;
});
document.getElementById("case-order-button").addEventListener("click", function(e) {
const cases = document.querySelectorAll("#case_formset ul");
cases.forEach((el, n) => {
const inputEl = el.querySelector("input[name$='sort_order']");
if (inputEl) {
inputEl.value = n + 1;
}
});
e.preventDefault();
});
});
</script>
{% endblock %}
@@ -1,5 +1,6 @@
{% if request.user.is_authenticated %}
Collection: {{collection.name}}-> <a href="{% url 'atlas:collection_detail' pk=collection.pk %}">Overview</a> /
<a href="{% url 'atlas:collection_case_update' collection.pk %}">Cases</a> /
<a href="{% url 'atlas:collection_history' collection.pk %}">History</a> /
<a href="{% url 'atlas:collection_mark_overview' collection.pk %}">Mark</a> /
<a href="{% url 'atlas:collection_scores_cid' collection.pk %}">Scores</a> /
+5
View File
@@ -101,6 +101,11 @@ urlpatterns = [
views.collection_history,
name="collection_history",
),
path(
"collection/<int:pk>/cases/update",
views.CollectionCaseUpdate.as_view(),
name="collection_case_update",
),
path(
"collection/add_cases",
views.add_cases_to_collection,
+56 -13
View File
@@ -48,6 +48,7 @@ from .forms import (
CaseCollectionAuthorForm,
CaseCollectionCaseFormSet,
CaseCollectionForm,
CaseCollectionUpdateCaseForm,
CaseDetailForm,
CaseDisplaySetForm,
CaseForm,
@@ -1023,19 +1024,19 @@ class CaseCollectionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateVi
def get_context_data(self, **kwargs):
context = super(CaseCollectionUpdate, self).get_context_data(**kwargs)
if self.request.POST:
context["case_formset"] = CaseCollectionCaseFormSet(
self.request.POST,
self.request.FILES,
instance=self.object,
form_kwargs={"user": self.request.user, "collection": self.object},
)
context["case_formset"].full_clean()
else:
context["case_formset"] = CaseCollectionCaseFormSet(
instance=self.object,
form_kwargs={"user": self.request.user, "collection": self.object},
)
#if self.request.POST:
# context["case_formset"] = CaseCollectionCaseFormSet(
# self.request.POST,
# self.request.FILES,
# instance=self.object,
# form_kwargs={"user": self.request.user, "collection": self.object},
# )
# context["case_formset"].full_clean()
#else:
# context["case_formset"] = CaseCollectionCaseFormSet(
# instance=self.object,
# form_kwargs={"user": self.request.user, "collection": self.object},
# )
context["collection"] = context["casecollection"]
return context
@@ -1046,6 +1047,7 @@ class CaseCollectionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateVi
form.instance.author.add(self.request.user.id)
return super().form_valid(form)
context = self.get_context_data(form=form)
case_formset = context["case_formset"]
# logger.debug(formset.is_valid())
@@ -1363,6 +1365,47 @@ class AtlasUpdate(
else:
return super().form_invalid(form)
class CollectionCaseUpdate(
RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView):
model = CaseCollection
form_class = CaseCollectionUpdateCaseForm
template_name = "atlas/casecollection_update_case.html"
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({"user": self.request.user, "collection": self.object})
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.POST:
context["case_formset"] = CaseCollectionCaseFormSet(
self.request.POST,
self.request.FILES,
instance=self.object,
form_kwargs={"user": self.request.user, "collection": self.object},
)
context["case_formset"].full_clean()
else:
context["case_formset"] = CaseCollectionCaseFormSet(
instance=self.object,
form_kwargs={"user": self.request.user, "collection": self.object},
)
context["collection"] = context["casecollection"]
return context
def form_valid(self, form):
context = self.get_context_data(form=form)
case_formset = context["case_formset"]
if case_formset.is_valid():
case_formset.instance = self.object
case_formset.save()
return super().form_valid(form)
else:
return self.form_invalid(form)
class AtlasSeriesUpdate(
RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView
):