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): def __init__(self, *args, **kwargs):
super().__init__(*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 %} {% csrf_token %}
{{ form }} {{ 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. 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" 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" /> <input type=button id="case-order-button" title="click and drag to update case order" value="Update case order" />
@@ -54,13 +54,14 @@
</div> </div>
{{ case_formset.management_form }} {{ case_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form> </form>
<div id="empty_case_form" style="display:none"> <div id="empty_case_form" style="display:none">
<li class='no_error case-formset'> <li class='no_error case-formset'>
{{ case_formset.empty_form }} {{ case_formset.empty_form }}
</li> </li>
</div> </div> {% endcomment %}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<script> <script>
$(document).ready(() => { $(document).ready(() => {
sortable('.sortable'); 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 %} {% if request.user.is_authenticated %}
Collection: {{collection.name}}-> <a href="{% url 'atlas:collection_detail' pk=collection.pk %}">Overview</a> / 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_history' collection.pk %}">History</a> /
<a href="{% url 'atlas:collection_mark_overview' collection.pk %}">Mark</a> / <a href="{% url 'atlas:collection_mark_overview' collection.pk %}">Mark</a> /
<a href="{% url 'atlas:collection_scores_cid' collection.pk %}">Scores</a> / <a href="{% url 'atlas:collection_scores_cid' collection.pk %}">Scores</a> /
+5
View File
@@ -101,6 +101,11 @@ urlpatterns = [
views.collection_history, views.collection_history,
name="collection_history", name="collection_history",
), ),
path(
"collection/<int:pk>/cases/update",
views.CollectionCaseUpdate.as_view(),
name="collection_case_update",
),
path( path(
"collection/add_cases", "collection/add_cases",
views.add_cases_to_collection, views.add_cases_to_collection,
+56 -13
View File
@@ -48,6 +48,7 @@ from .forms import (
CaseCollectionAuthorForm, CaseCollectionAuthorForm,
CaseCollectionCaseFormSet, CaseCollectionCaseFormSet,
CaseCollectionForm, CaseCollectionForm,
CaseCollectionUpdateCaseForm,
CaseDetailForm, CaseDetailForm,
CaseDisplaySetForm, CaseDisplaySetForm,
CaseForm, CaseForm,
@@ -1023,19 +1024,19 @@ class CaseCollectionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateVi
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(CaseCollectionUpdate, self).get_context_data(**kwargs) context = super(CaseCollectionUpdate, self).get_context_data(**kwargs)
if self.request.POST: #if self.request.POST:
context["case_formset"] = CaseCollectionCaseFormSet( # context["case_formset"] = CaseCollectionCaseFormSet(
self.request.POST, # self.request.POST,
self.request.FILES, # self.request.FILES,
instance=self.object, # instance=self.object,
form_kwargs={"user": self.request.user, "collection": self.object}, # form_kwargs={"user": self.request.user, "collection": self.object},
) # )
context["case_formset"].full_clean() # context["case_formset"].full_clean()
else: #else:
context["case_formset"] = CaseCollectionCaseFormSet( # context["case_formset"] = CaseCollectionCaseFormSet(
instance=self.object, # instance=self.object,
form_kwargs={"user": self.request.user, "collection": self.object}, # form_kwargs={"user": self.request.user, "collection": self.object},
) # )
context["collection"] = context["casecollection"] context["collection"] = context["casecollection"]
return context return context
@@ -1046,6 +1047,7 @@ class CaseCollectionUpdate(RevisionMixin, AuthorOrCheckerRequiredMixin, UpdateVi
form.instance.author.add(self.request.user.id) form.instance.author.add(self.request.user.id)
return super().form_valid(form)
context = self.get_context_data(form=form) context = self.get_context_data(form=form)
case_formset = context["case_formset"] case_formset = context["case_formset"]
# logger.debug(formset.is_valid()) # logger.debug(formset.is_valid())
@@ -1363,6 +1365,47 @@ class AtlasUpdate(
else: else:
return super().form_invalid(form) 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( class AtlasSeriesUpdate(
RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView
): ):