improve case management

This commit is contained in:
Ross
2025-04-28 15:45:02 +01:00
parent a13be87077
commit 5e578ca2b0
7 changed files with 83 additions and 13 deletions
+9
View File
@@ -533,6 +533,15 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
return size
def check_user_can_edit(self, user):
if user.is_superuser:
return True
if self.author.filter(id=user.id).exists():
return True
return False
+16 -1
View File
@@ -248,14 +248,29 @@
</ul>
<b>Diagnostic certainty:</b> {{case.get_diagnostic_certainty_display}}<br />
<b>Collections:</b>
{% if can_edit %}
<button
hx-get="{% url 'atlas:case_collection_form' case.pk %}"
hx-target="#collection-form">
Add collection</button>
{% endif %}
<div id="collection-form"></div>
<ul>
{% for collection in case.casecollection_set.all %}
<li><a href="{% url 'atlas:collection_detail' pk=collection.pk %}">{{collection.name}}</a></li>
<li id="collection-{{ collection.pk }}">
<a href="{% url 'atlas:collection_detail' pk=collection.pk %}">{{ collection.name }}</a>
{% if can_edit %}
<button
class="btn btn-danger btn-sm remove-button"
hx-post="{% url 'atlas:remove_case_from_collection' case.pk collection.pk %}"
hx-target="#collection-{{ collection.pk }}"
hx-swap="outerHTML"
hx-confirm="Are you sure you want to remove this case from the collection?">
Remove
</button>
{% endif %}
</li>
{% endfor %}
</ul>
</p>
@@ -218,7 +218,7 @@
<div>
{% if collection.self_review %}
<p>
<a href="{% url 'atlas:add_self_review' cid_user_exam.id case.id %}"><button>Add self review</button></a>
<a target="_blank" title="Add self review, this will open in a new page / tab" href="{% url 'atlas:add_self_review' cid_user_exam.id case.id %}"><button type="button">Add self review</button></a>
</p>
{% if self_review %}
<h4>Self Feedback</h4>
@@ -8,6 +8,7 @@
Adding self feedback for {{user_exam.exam}}/{{case}}
</div>
This form allows you to record your own feedback for the question / case. This can take the form of a note or a ranking (1-5) of your findings and interpretation.
<form class="highlight" action="" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
+5
View File
@@ -249,6 +249,11 @@ urlpatterns = [
views.use_dates_as_descriptions,
name="use_dates_as_descriptions",
),
path(
"case/<int:case_pk>/collection/<int:collection_pk>/remove/",
views.remove_case_from_collection,
name="remove_case_from_collection",
),
path(
"series/<int:pk>/dicom_json",
views.series_dicom_json,
+43 -10
View File
@@ -7,6 +7,7 @@ from django.db.models.query import QuerySet
from django.shortcuts import render, get_object_or_404, redirect
from django import forms
from django.utils import timezone
from django.views.decorators.http import require_POST
# from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required, user_passes_test
@@ -122,7 +123,7 @@ from .tasks import push_case_to_cimar_task
from django_tables2 import SingleTableView, SingleTableMixin
from django_filters.views import FilterView
#from autocomplete import HTMXAutoComplete
# from autocomplete import HTMXAutoComplete
from .decorators import (
@@ -200,14 +201,26 @@ def case_detail(request, pk):
# if request.user not in atlas.author.all():
# raise PermissionDenied
can_edit = case.check_user_can_edit(request.user)
# logging.debug(atlas.subspecialty.first().name.all())
return render(request, "atlas/case_detail.html", {"case": case, "cimar_sid":request.user.userprofile.cimar_sid})
return render(
request,
"atlas/case_detail.html",
{
"case": case,
"cimar_sid": request.user.userprofile.cimar_sid,
"can_edit": can_edit,
},
)
@login_required
@user_is_author_or_atlas_series_checker_or_atlas_marker_or_open_access
def series_thumbnail_fail(request, pk):
return series_thumbnail(request, pk=pk, fail_loudly=True)
@login_required
@user_is_author_or_atlas_series_checker_or_atlas_marker_or_open_access
def series_thumbnail(request, pk, fail_loudly=False):
@@ -962,7 +975,7 @@ class AtlasCreateBase(RevisionMixin, LoginRequiredMixin):
form.instance.author.add(self.request.user.id)
# Check Cimar Case
#CimarAPI().get_study_by_uuid(self.object.cimar_uuid)
# CimarAPI().get_study_by_uuid(self.object.cimar_uuid)
context = self.get_context_data(form=form)
series_formset = context["series_formset"]
@@ -1128,6 +1141,7 @@ def add_collection_to_case_form(request, case_id):
# pk = self.kwargs["pk"]
# return reverse("atlas:case_detail", kwargs={"pk": pk})
class AtlasClone(AtlasCreateBase, AuthorOrCheckerRequiredMixin, CreateView):
"""Clones a existing atlas"""
@@ -1153,8 +1167,10 @@ class AtlasClone(AtlasCreateBase, AuthorOrCheckerRequiredMixin, CreateView):
initial_data = model_to_dict(old_object, exclude=["id", "previous_case"])
return initial_data
class AtlasCloneNext(AtlasClone):
"""Extends AtlasClone to set the previous_case field to the case being cloned"""
def get_initial(self):
initial_data = super().get_initial()
initial_data["previous_case"] = self.kwargs["pk"]
@@ -1673,7 +1689,9 @@ def collection_history_user(request, exam_id: int, user_pk: int):
print(user)
print(casedetails)
user_answers = [(casedetail, casedetail.get_user_answers(user)) for casedetail in casedetails]
user_answers = [
(casedetail, casedetail.get_user_answers(user)) for casedetail in casedetails
]
return render(
request,
@@ -1701,7 +1719,6 @@ def collection_take_start(request, pk):
valid_user = collection.check_logged_in_user(request)
# for now we only allow registered users....
if not valid_user:
raise PermissionDenied
@@ -2399,7 +2416,7 @@ def collection_case_view(request, pk, case_number):
"previous": previous,
"next": next,
"answer": answer,
"cimar_sid":request.user.userprofile.cimar_sid
"cimar_sid": request.user.userprofile.cimar_sid,
},
)
@@ -2429,7 +2446,6 @@ def collection_case_dicom_json(request, exam_id, case_id):
return JsonResponse(case_detail.case.get_case_dicom_json(priors=priors))
def case_dicom_json(request, pk):
case = get_object_or_404(Case, pk=pk)
@@ -2925,19 +2941,25 @@ def collection_question_schemas(request, exam_id: int):
},
)
def collection_reset_answers_user_list(request, exam_id: int):
if request.htmx:
collection = get_object_or_404(CaseCollection, pk=exam_id)
cid_users = collection.cid_users.all()
if cid_users:
return render(request, "atlas/collection_reset_answers_user_list.html", {"collection": collection, "cid_users": cid_users})
return render(
request,
"atlas/collection_reset_answers_user_list.html",
{"collection": collection, "cid_users": cid_users},
)
else:
return HttpResponse("No user answers.")
else:
raise Http404("Invalid request")
def collection_reset_answers_user(request, exam_id: int, user_id: int):
if request.htmx:
collection = get_object_or_404(CaseCollection, pk=exam_id)
@@ -2958,6 +2980,7 @@ def collection_reset_answers_user(request, exam_id: int, user_id: int):
else:
raise Http404("Invalid request")
def collection_reset_answers(request, exam_id: int):
if request.htmx:
collection = get_object_or_404(CaseCollection, pk=exam_id)
@@ -2983,8 +3006,8 @@ def collection_reset_answers(request, exam_id: int):
else:
raise Http404("Invalid request")
def push_case_to_cimar(request, case_id):
def push_case_to_cimar(request, case_id):
push_case_to_cimar_task.delay(case_id=case_id)
return HttpResponse("Push started")
@@ -3000,7 +3023,6 @@ def push_case_to_cimar(request, case_id):
for image in series.images.all():
data = api.upload_dicom(image.image.path, study_uid=study_uid)
cimar_uuid = api.get_study_by_study_uid(data["study_uid"])["uuid"]
case.cimar_uuid = cimar_uuid
@@ -3012,3 +3034,14 @@ def push_case_to_cimar(request, case_id):
cimar_case.refresh_study()
return HttpResponse("Success")
@require_POST
def remove_case_from_collection(request, case_pk, collection_pk):
case = get_object_or_404(Case, pk=case_pk)
collection = get_object_or_404(CaseCollection, pk=collection_pk)
# Remove the case from the collection
collection.cases.remove(case)
return HttpResponse(f"Case removed from collection: {collection.name}")
+8 -1
View File
@@ -1337,4 +1337,11 @@ span#user-id {
.marking-link:hover {
color: #3282b8;
text-decoration: underline;
}
}
.remove-button {
opacity: 20%;
}
.remove-button:hover {
opacity: 100%;
}