diff --git a/atlas/models.py b/atlas/models.py index ce53544c..3c0b146c 100644 --- a/atlas/models.py +++ b/atlas/models.py @@ -502,54 +502,6 @@ class CaseCollection(ExamCollectionGenericBase): def __str__(self) -> str: return self.name - def get_author_objects(self): - """Returns a comma seperated text list of authors""" - authors = [i for i in self.author.all()] - return authors - - def check_cid_user(self, cid, passcode, request=None): - if request is not None and request.user.is_superuser: - return True - - if self.valid_cid_users.exists(): - user = self.valid_cid_users.filter(cid=cid).first() - - if not user or user.passcode != passcode: - return False - - return True - - def get_or_create_cid_user_exam(self, cid_user, start_time=None): - content_type = ContentType.objects.get_for_model(self) - c = CidUserExam.objects.filter( - content_type=content_type, object_id=self.pk, cid_user=cid_user - ).first() - if c: - return c - - if start_time is None: - start_time = timezone.now() - new = CidUserExam( - content_type=content_type, - object_id=self.pk, - cid_user=cid_user, - start_time=start_time, - ) - new.save() - return new - - def get_cid_user_exams(self, cid_user=None): - content_type = ContentType.objects.get_for_model(self) - if cid_user is None: - return CidUserExam.objects.filter( - content_type=content_type, - object_id=self.pk, - ) - else: - return CidUserExam.objects.filter( - content_type=content_type, object_id=self.pk, cid_user=cid_user - ) - class CaseDetail(models.Model): case = models.ForeignKey(Case, on_delete=models.CASCADE) diff --git a/atlas/templates/atlas/case_display_block.html b/atlas/templates/atlas/case_display_block.html index 16f86495..5f009bfe 100755 --- a/atlas/templates/atlas/case_display_block.html +++ b/atlas/templates/atlas/case_display_block.html @@ -28,13 +28,15 @@ {% for series in case.series.all %} - Series {{ forloop.counter }}: + Series {{ forloop.counter }}:
{{series.get_block}} - +
+ Popup +
{% endfor %} diff --git a/atlas/templates/atlas/series_viewer.html b/atlas/templates/atlas/series_viewer.html index a6146afe..61aafaf8 100755 --- a/atlas/templates/atlas/series_viewer.html +++ b/atlas/templates/atlas/series_viewer.html @@ -39,7 +39,7 @@ {% for finding in series.findings.all %}
+ data-viewportjson={{finding.viewport_json}} data-findingid={{finding.id}}>Click to view Finding(s): {% for f in finding.findings.all %}{{f.get_link}}{% endfor %}
Structure(s): {% for s in finding.structures.all %}{{s.get_link}}{% endfor %}
@@ -58,18 +58,24 @@ Image info
Anonymise dicoms
+ title="Anonymise dicom images">Anonymise dicoms
Order dicoms by slice location Order dicoms by instance number + title="orders dicom by instance number">Order dicoms by instance number Order dicoms by SeriesInstanceUID + title="orders dicom by instance number">Order dicoms by SeriesInstanceUID Order by uploaded filename + title="orders dicom by uploaded filename">Order by uploaded filename
{% for image in series.images.all %} - {{image.image.url}}, pos: {{image.position}}, {{image.upload_filename}} [{{image.image.size|filesizeformat}}]
+ {{image.image.url}}, pos: {{image.position}}, {{image.upload_filename}} + + + {% if image.image %} + [{{image.image.size|filesizeformat}}] + {% endif %} +
{% comment %} {{image.get_dicom_info|safe}}
{% endcomment %} {% endfor %} @@ -159,13 +165,13 @@ viewport_json: JSON.stringify(c.viewport), findings: JSON.stringify($('#finding-form select[name="findings"]').find(":selected") .map((i, el) => { - return $(el).val() - }).toArray()), + return $(el).val() + }).toArray()), structures: JSON.stringify($('#finding-form select[name="structures"]').find( ":selected") .map((i, el) => { - return $(el).val() - }).toArray()), + return $(el).val() + }).toArray()), csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(), action: 'post' }, diff --git a/generic/models.py b/generic/models.py index 5e53503c..d9624ccc 100644 --- a/generic/models.py +++ b/generic/models.py @@ -116,6 +116,7 @@ class QuestionBase(models.Model): """If this makes sense in the question/answer context override""" return None + class SeriesImageBase(models.Model): position = models.IntegerField(default=0) upload_filename = models.CharField(max_length=255, blank=True) @@ -206,9 +207,9 @@ class SeriesBase(models.Model): thumbnailer = get_thumbnailer(img) thumbnail = thumbnailer["exam-list"] except InvalidImageFormatError: - return format_html('', img), len( - images - ) + return format_html( + '', img + ), len(images) return format_html('', thumbnail), len(images) def get_thumbnail_link(self): @@ -216,21 +217,30 @@ class SeriesBase(models.Model): "{}", self.get_absolute_url(), self.get_thumbnail()[0] ) - def get_block(self): + def get_block(self, series_number: None | int = None): examination = self.get_examination_full() thumb, image_number = self.get_thumbnail() + + series_html = "" + if series_number is not None: + series_html = format_html( + "Series {}
", + series_number, + ) + return format_html( - """ + """{} + {}
{}
Images: {}
""", + series_html, examination, thumb, image_number, ) - def order_by_upload_filename(self): images = self.images.all() @@ -311,12 +321,14 @@ class SeriesBase(models.Model): except pydicom.errors.InvalidDicomError: pass + class ExamCollectionGenericBase(models.Model): """Holds functions that relate to both case and other exams e.g. user management """ + # Is this actually used? cid_users = GenericRelation("generic.CidUserExam") @@ -429,6 +441,7 @@ class ExamCollectionGenericBase(models.Model): content_type=content_type, object_id=self.pk, user_user=user_user ) + class ExamBase(ExamCollectionGenericBase): name = models.CharField(max_length=200, help_text="Name of the exam") # exam_questions = SortedManyToManyField(Long, related_name="exams", blank="true") @@ -490,7 +503,6 @@ class ExamBase(ExamCollectionGenericBase): user_scores = models.JSONField(default=dict) - exam_results_emailed = models.DateTimeField(default=None, null=True) class Meta: @@ -547,7 +559,6 @@ class ExamBase(ExamCollectionGenericBase): def get_question_index(self, question): return list(self.exam_questions.all()).index(question) - def get_cid_user_score(self, cid_user): c = "c/" + str(cid_user) if c in self.user_scores: diff --git a/generic/views.py b/generic/views.py index 68467d69..f905d949 100644 --- a/generic/views.py +++ b/generic/views.py @@ -87,6 +87,7 @@ from django.db.models import Case, When from django.conf import settings from datetime import datetime +from django.utils import timezone import os import string import random @@ -1626,7 +1627,7 @@ class ExamViews(View, LoginRequiredMixin): return redirect(url) return JsonResponse(exam_json_cache) - time = datetime.now() + time = timezone.now() exam.exam_json_id += 1 @@ -1672,7 +1673,7 @@ class ExamViews(View, LoginRequiredMixin): if not exam.check_cid_user(cid, passcode, request, user_id): raise Http404("No available exam") - time = datetime.now() + time = timezone.now() exam_json = exam.get_exam_json(based=False) exam_json["generated"] = time.isoformat() diff --git a/rad/static/css/anatomy.css b/rad/static/css/anatomy.css index 39daa622..c2f1b4d1 100644 --- a/rad/static/css/anatomy.css +++ b/rad/static/css/anatomy.css @@ -571,12 +571,21 @@ td.user-answer-score-2.rapid-ans::after { font-size: small; } +.series-block a { + text-decoration: none; + color: unset; +} + .series-block-image-number-count { text-decoration: underline; } + .series-block-popup-link { - font-size: small; - color: darkblue + font-size: smaller; +} +.series-block-popup-link a { + color: rgb(0, 153, 255); + opacity: 50%; } .series-block img { @@ -820,6 +829,10 @@ input { border-radius: 0px; } +.select2-results__option { + background-color: #05668d; +} + .select2-search__field { background-color: #05668d; color: darkblue;