shorts might now be functional?

This commit is contained in:
Ross
2025-04-28 12:15:31 +01:00
parent 405b17776f
commit 06e66ad52c
18 changed files with 901 additions and 234 deletions
+10
View File
@@ -1327,4 +1327,14 @@ a, a:link {
span#user-id {
opacity: 50%;
float: right;
}
.marking-link {
color: #8600789e;
text-decoration: none;
text-transform: uppercase;
}
.marking-link:hover {
color: #3282b8;
text-decoration: underline;
}
+138 -55
View File
@@ -7,7 +7,12 @@ from atlas.models import CaseCollection, CidReportAnswer, Case as AtlasCase
from generic.decorators import user_is_cid_user_manager
from generic.filters import UserUserFilter
from generic.tables import UserUserTable
from generic.views import CidManagerRequiredMixin, RedirectMixin, get_question_and_content_type, get_user_exams
from generic.views import (
CidManagerRequiredMixin,
RedirectMixin,
get_question_and_content_type,
get_user_exams,
)
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
from django.shortcuts import render, get_object_or_404, redirect
from django.views.decorators.csrf import csrf_exempt
@@ -63,10 +68,19 @@ from sbas.models import Exam as SbasExam
from anatomy.views import GenericExamViews as AnatomyExamViews
from rapids.views import GenericExamViews as RapidsExamsViews
from longs.views import GenericExamViews as LongsExamViews
from shorts.views import GenericExamViews as ShortsExamsViews
from longs.views import GenericExamViews as LongsExamsViews
from generic.forms import QuestionNoteForm
from generic.models import CidUser, CimarCase, ExamCollection, QuestionNote, Supervisor, UserGrades, UserProfile
from generic.models import (
CidUser,
CimarCase,
ExamCollection,
QuestionNote,
Supervisor,
UserGrades,
UserProfile,
)
from django_filters.views import FilterView
@@ -82,31 +96,44 @@ from loguru import logger
import psutil
def feedback_checker(user):
return user.groups.filter(name="feedback_checker").exists()
@user_passes_test(lambda u: u.is_superuser)
def server(request):
return render(request, "server.html")
@user_is_cid_user_manager
def people(request):
return render(request, "people.html", {})
@login_required
def profile(request):
user = request.user
return render(request, "profile.html", {"user": user})
def index(request):
collections = []
if request.user.is_authenticated:
collections = ExamCollection.objects.filter(archive=False, author=request.user)
rcr_assessor = request.user.groups.filter(Q(name="rcr_radiology_assessor") | Q(name="rcr_oncology_assessor")| Q(name="rcr_assessor")).exists()
return render(request, "index.html", {"rcr_assessor": rcr_assessor, "collections": collections})
rcr_assessor = request.user.groups.filter(
Q(name="rcr_radiology_assessor")
| Q(name="rcr_oncology_assessor")
| Q(name="rcr_assessor")
).exists()
return render(
request,
"index.html",
{"rcr_assessor": rcr_assessor, "collections": collections},
)
@user_is_cid_user_manager
def account_profile(request, slug):
@@ -151,6 +178,7 @@ def cid_results(request, cid):
},
)
@user_passes_test(lambda u: u.is_superuser)
def user_scores_admin(request, user_id):
try:
@@ -283,11 +311,15 @@ def active_exams(request, cid=None, passcode=None, based=True):
rapid_exams = RapidsExamsViews.active_exams(
request, False, cid=cid, passcode=passcode
)
long_exams = LongsExamViews.active_exams(request, False, cid=cid, passcode=passcode)
short_exams = ShortsExamsViews.active_exams(
request, False, cid=cid, passcode=passcode
)
long_exams = LongsExamsViews.active_exams(request, False, cid=cid, passcode=passcode)
exams = []
exams.extend(anatomy_exams)
exams.extend(rapid_exams)
exams.extend(short_exams)
exams.extend(long_exams)
active_exams["exams"] = exams
@@ -318,7 +350,10 @@ def exam_submit(request):
elif exam_type == "rapid":
return RapidsExamsViews.post_exam_answers(request)
elif exam_type == "long":
return LongsExamViews.post_exam_answers(request)
return LongsExamsViews.post_exam_answers(request)
elif exam_type == "short":
return ShortsExamsViews.post_exam_answers(request)
return JsonResponse({"success": False, "error": "Invalid exam type"})
except ObjectDoesNotExist:
return JsonResponse({"success": False, "error": "Invalid data"})
@@ -512,12 +547,14 @@ def view_feedback(request):
def privacy_view(request):
return render(request, "privacy.html")
def cimar(request):
if "link_id" in request.GET:
link_id = request.GET["link_id"]
return render(request, "cimar.html", {"link_id": link_id})
return render(request, "cimar.html")
def about_view(request):
return render(request, "about.html")
@@ -528,12 +565,17 @@ def stats(request):
anatomy_exam_count = AnatomyExam.objects.filter(archive=False).count()
anatomy_question_count = AnatomyQuestion.objects.filter().count()
return render(request, "stats.html"
, {"collection_count": collection_count,
"case_count": case_count,
"anatomy_exam_count": anatomy_exam_count,
"anatomy_question_count": anatomy_question_count
})
return render(
request,
"stats.html",
{
"collection_count": collection_count,
"case_count": case_count,
"anatomy_exam_count": anatomy_exam_count,
"anatomy_question_count": anatomy_question_count,
},
)
# HTTP Error 400
def page_not_found(request, exception):
@@ -545,7 +587,6 @@ def page_not_found(request, exception):
def page_forbidden(request, exception):
response = render(request, "403.html", context={"exception": exception})
response.status_code = 403
@@ -575,11 +616,11 @@ class UserListTableView(CidManagerRequiredMixin, SingleTableMixin, FilterView):
filterset_class = UserUserFilter
#table_pagination = {"per_page": 5}
# table_pagination = {"per_page": 5}
def get_paginate_by(self, table_data) -> int | None:
return 100
#return super().get_paginate_by(table_data)
# return super().get_paginate_by(table_data)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@@ -620,7 +661,12 @@ class DeleteUserView(CidManagerRequiredMixin, DeleteView):
class UpdateUserView(CidManagerRequiredMixin, UpdateView):
model = User
fields = ["first_name", "last_name", "email", "is_active"] # Keep listing whatever fields
fields = [
"first_name",
"last_name",
"email",
"is_active",
] # Keep listing whatever fields
# the combined UserProfile and User exposes.
template_name = "user_update.html"
slug_field = "username"
@@ -649,21 +695,31 @@ class UpdateUserProfileAdminView(CidManagerRequiredMixin, UpdateView):
# No need for reverse_lazy here, because it's called inside the method
return reverse(view_name, kwargs={"slug": self.object.username})
class UpdateUserProfileView(UpdateView):
model = UserProfile
fields = [
"supervisor",
"grade",
"registration_number",
#"peninsula_trainee",
# "peninsula_trainee",
] # Keep listing whatever fields
template_name = "user_update_profile.html"
slug_field = "user__username"
slug_url_kwarg = "slug"
def dispatch(self, request, *args, **kwargs):
if request.user.is_superuser or request.user.groups.filter(name="cid_user_manager").exists():
self.fields = ["supervisor", "grade", "registration_number", "site", "peninsula_trainee"]
if (
request.user.is_superuser
or request.user.groups.filter(name="cid_user_manager").exists()
):
self.fields = [
"supervisor",
"grade",
"registration_number",
"site",
"peninsula_trainee",
]
# Check permissions for the request.user here
elif request.user != self.get_object().user:
raise Http404
@@ -680,18 +736,22 @@ class UpdateUserProfileView(UpdateView):
form = context["form"]
if "supervisor" in form.fields:
#form.fields["supervisor"].queryset = Supervisor.objects.all()
# form.fields["supervisor"].queryset = Supervisor.objects.all()
form.fields["supervisor"] = forms.ModelChoiceField(
Supervisor.objects.all().order_by("name"), required=False, widget=autocomplete.ModelSelect2(url='generic:supervisor-autocomplete')
)
Supervisor.objects.all().order_by("name"),
required=False,
widget=autocomplete.ModelSelect2(url="generic:supervisor-autocomplete"),
)
return context
def get_success_url(self):
if "redirect" in self.request.GET:
return self.request.GET["redirect"]
if self.request.user.is_superuser or self.request.user.groups.filter(name="cid_user_manager").exists():
if (
self.request.user.is_superuser
or self.request.user.groups.filter(name="cid_user_manager").exists()
):
view_name = "account_profile"
# No need for reverse_lazy here, because it's called inside the method
return reverse(view_name, kwargs={"slug": self.object.username})
@@ -699,7 +759,6 @@ class UpdateUserProfileView(UpdateView):
return reverse("profile")
# class UpdateUser(TemplateView):
#
# user_form_class = UserForm
@@ -747,12 +806,12 @@ def accounts_check_users(request):
return
@user_is_cid_user_manager
def accounts_bulk_create_check(request):
if not request.method == "POST":
return HttpResponse("Invalid request")
user = {}
user["email"] = request.POST.get("email")
@@ -791,10 +850,12 @@ def accounts_bulk_create_check(request):
errors.append("Supervisor name does not match")
if errors:
return HttpResponse(format_html("<span class='error'>{}</span>", "<br/>".join(errors)))
return HttpResponse(
format_html("<span class='error'>{}</span>", "<br/>".join(errors))
)
return HttpResponse(format_html("<span class='info'>{}</span>", "<br/>".join(info)))
@user_is_cid_user_manager
def accounts_bulk_create(request):
@@ -864,7 +925,7 @@ def accounts_bulk_create(request):
except Exception as error:
error_text = (
error_text
+ f"<p>Error creating user: { user['email'] }<br/>{error}</p>"
+ f"<p>Error creating user: {user['email']}<br/>{error}</p>"
)
# No need to try and create a profile if we can't create a user
continue
@@ -899,7 +960,7 @@ def accounts_bulk_create(request):
new_user.delete()
error_text = (
error_text
+ f"<p>Error creating user profile: { user['email'] }<br/>{error} (user not created)</p>"
+ f"<p>Error creating user profile: {user['email']}<br/>{error} (user not created)</p>"
)
except Exception as error:
@@ -939,34 +1000,42 @@ def request_cid_details(request):
def cimar_study_dicom_json(request, uuid="c9417b53-87aa-4c40-aca0-3fa34c225536"):
with CimarAPI(request.user.userprofile.cimar_sid) as api:
print(api.sid)
#studies = api.list_studies()
#test_study = studies["studies"][0]
# studies = api.list_studies()
# test_study = studies["studies"][0]
#schema = api.get_study_schema(test_study)
# schema = api.get_study_schema(test_study)
schema = api.get_study_schema_by_uuid("c9417b53-87aa-4c40-aca0-3fa34c225536")
return JsonResponse(api.get_study_dicom_json(schema))
def cimar_study_viewer(request, uuid="c9417b53-87aa-4c40-aca0-3fa34c225536"):
case = get_object_or_404(CimarCase, uuid=uuid)
viewer_link = case.viewer_link + f"?sid={request.user.userprofile.cimar_sid}"
return render(request, "cimar_embed.html", {"viewer_link": viewer_link})
def cimar_study_viewer(request, uuid="c9417b53-87aa-4c40-aca0-3fa34c225536"):
case = get_object_or_404(CimarCase, uuid=uuid)
viewer_link = case.viewer_link + f"?sid={request.user.userprofile.cimar_sid}"
return render(request, "cimar_embed.html", {"viewer_link": viewer_link})
def cimar_study_viewer_embed(request, uuid="c9417b53-87aa-4c40-aca0-3fa34c225536"):
case = get_object_or_404(CimarCase, uuid=uuid)
viewer_link = case.viewer_link + f"?sid={request.user.userprofile.cimar_sid}"
return render(request, "cimar_embed.html#embed", {"viewer_link": viewer_link})
case = get_object_or_404(CimarCase, uuid=uuid)
viewer_link = case.viewer_link + f"?sid={request.user.userprofile.cimar_sid}"
return render(request, "cimar_embed.html#embed", {"viewer_link": viewer_link})
def cimar_study_series_block(request, uuid):
case = get_object_or_404(CimarCase, uuid=uuid)
return render(
request,
"cimar_series.html",
{
"series_data": case.series_data["series"],
"cimar_sid": request.user.userprofile.cimar_sid,
},
)
case = get_object_or_404(CimarCase, uuid=uuid)
return render(request, "cimar_series.html", {"series_data": case.series_data["series"], "cimar_sid": request.user.userprofile.cimar_sid})
def cimar_status(request):
login_status = CimarAPI(request.user.userprofile.cimar_sid).check_login_status()
@@ -974,20 +1043,26 @@ def cimar_status(request):
if login_status:
return HttpResponse("")
else:
return render(request, "cimar_login.html#login-block", {"login_status": login_status, "cimar_sid": request.user.userprofile.cimar_sid})
return render(
request,
"cimar_login.html#login-block",
{
"login_status": login_status,
"cimar_sid": request.user.userprofile.cimar_sid,
},
)
def cimar_logout(request):
CimarAPI(request.user.userprofile.cimar_sid).logout()
return HttpResponse("Logged out")
def cimar_login(request):
def cimar_login(request):
if request.htmx:
username = request.POST.get("username")
password = request.POST.get("password")
if not username and not password:
return HttpResponse("Please fill in login details")
@@ -999,12 +1074,20 @@ def cimar_login(request):
except InvalidCredentials:
return HttpResponse("Invalid login details")
return HttpResponse("Logged in")
else:
try:
login_status = CimarAPI(request.user.userprofile.cimar_sid).check_login_status()
login_status = CimarAPI(
request.user.userprofile.cimar_sid
).check_login_status()
except NoSession:
login_status = False
return render(request, "cimar_login.html", {"login_status": login_status, "cimar_sid": request.user.userprofile.cimar_sid})
return render(
request,
"cimar_login.html",
{
"login_status": login_status,
"cimar_sid": request.user.userprofile.cimar_sid,
},
)