diff --git a/AGENTS.md b/AGENTS.md index 591c8fb1..3c3e0789 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,6 +17,13 @@ Django-based radiology education platform. Multi-app, HTMX-driven, PostgreSQL + - Partials must be standalone fragments — no `{% extends %}`. - HTMX detection via `django_htmx` middleware (`request.htmx`). +#### HTMX input +- When using htmx input for autoupdating search/other triggers triggers do not use changed in the hx-trigger. Using input is sufficient. +e.g. instead of + hx-trigger="input changed delay:300ms, focus" +use + hx-trigger="input delay:300ms, focus" + ### API - Django Ninja (not DRF). Routers in `{app}/api.py`, registered in `rad/api.py` at `/api/v1/`. - Use `ModelSchema` with explicit `Meta.fields` lists (avoid `"__all__"` on public endpoints). diff --git a/atlas/templates/atlas/collection_review_start.html b/atlas/templates/atlas/collection_review_start.html index e8575304..6b1b505c 100644 --- a/atlas/templates/atlas/collection_review_start.html +++ b/atlas/templates/atlas/collection_review_start.html @@ -89,48 +89,51 @@ - {% if collection.show_results_sharing_information and sharing_summary %} -
-
Who can see your results
- +
+ {% endif %} + + {% endpartialdef %} {% else %}

diff --git a/atlas/templates/atlas/collection_take_start.html b/atlas/templates/atlas/collection_take_start.html index 34a4ffc5..f377d0fb 100644 --- a/atlas/templates/atlas/collection_take_start.html +++ b/atlas/templates/atlas/collection_take_start.html @@ -91,49 +91,7 @@

- {# ---- Who can see your results ---- #} - {% if collection.show_results_sharing_information and sharing_summary %} -
-
Who can see your results
- -
- {% endif %} + {% include "atlas/collection_review_start.html#sharing-info" %} {% else %}

diff --git a/atlas/templates/atlas/partials/_sharing_panel.html b/atlas/templates/atlas/partials/_sharing_panel.html index 4860f75e..92e07ce1 100644 --- a/atlas/templates/atlas/partials/_sharing_panel.html +++ b/atlas/templates/atlas/partials/_sharing_panel.html @@ -1,10 +1,10 @@ {% load django_htmx %} -{# Sharing panel for a CidUserExam attempt. +{% comment %} Sharing panel for a CidUserExam attempt. Context: cid_user_exam – CidUserExam instance sharing_info – dict from cid_user_exam.get_sharing_info() is_owner – bool: current user is the attempt owner -#} +{% endcomment %}

Result Sharing @@ -107,7 +107,7 @@ name="q" autocomplete="off" hx-get="{% url 'atlas:collection_exam_user_search' cid_user_exam.pk %}" - hx-trigger="input changed delay:300ms, focus" + hx-trigger="input delay:300ms, focus" hx-target="#sharing-search-results-{{ cid_user_exam.pk }}" hx-swap="innerHTML">
diff --git a/atlas/templates/atlas/partials/_sharing_panel_who_can_see.html b/atlas/templates/atlas/partials/_sharing_panel_who_can_see.html new file mode 100644 index 00000000..dd5c4814 --- /dev/null +++ b/atlas/templates/atlas/partials/_sharing_panel_who_can_see.html @@ -0,0 +1,42 @@ +{% if collection.show_results_sharing_information and sharing_summary %} +
+
Who can see your results
+
    +
  • + You + Always visible to you. +
  • + {% for u in sharing_summary.always_visible_to %} +
  • + Author/Marker + {{ u.get_full_name|default:u.username }} + {% if u.email %}<{{ u.email }}>{% endif %} +
  • + {% endfor %} + {% if sharing_summary.supervisor_always %} +
  • + Supervisor + {% if sharing_summary.supervisor %} + {{ sharing_summary.supervisor.get_full_name|default:sharing_summary.supervisor.username }} + (always shared - collection setting) + {% else %} + Your supervisor, if one is linked to your profile (collection setting always on). + {% endif %} +
  • + {% elif sharing_summary.supervisor_opt_in %} +
  • + Supervisor + {% if sharing_summary.supervisor %} + {{ sharing_summary.supervisor.get_full_name|default:sharing_summary.supervisor.username }} + - you can choose to share with them after starting. + {% else %} + You have a supervisor linked but they do not have a login account yet. + {% endif %} +
  • + {% endif %} + {% if not sharing_summary.always_visible_to and not sharing_summary.supervisor_always and not sharing_summary.supervisor_opt_in %} +
  • Only you can see your results for this collection.
  • + {% endif %} +
+
+{% endif %} \ No newline at end of file diff --git a/atlas/templates/atlas/partials/case_search_widget.html b/atlas/templates/atlas/partials/case_search_widget.html index 2041d7d3..69313ad0 100644 --- a/atlas/templates/atlas/partials/case_search_widget.html +++ b/atlas/templates/atlas/partials/case_search_widget.html @@ -12,7 +12,7 @@ hx-get="{% url 'atlas:case_search' %}" hx-include="closest .case-search-widget" hx-target="#{{ target_id }}" - hx-trigger="keyup changed delay:400ms" + hx-trigger="input delay:400ms" autocomplete="off">
diff --git a/todo b/todo index 73af8588..4b9fa516 100644 --- a/todo +++ b/todo @@ -1,80 +1,8 @@ -on the case details page when mananging series clicking on a select button launches the series popup when it shouldn't. +1. the time / date filters on the logs viewing viewer should be labeled and better organised -when building the series / stack description for the dv3d viewer we should take into account the plane and contrast if they are defined on the series model. +2. on the Unused Media Cleanup page we need to shown loading dialogs when the preview unused files and delete unused files buttons are pressed. please also check the recovered space size calculations as it does not match with what actually happens. -when importing cases we currently get the following error: -web-1 | 2026-06-03 20:20:04.612 | ERROR | atlas.views:uploads_import_htmx:3578 - Error during uploads import -web-1 | Traceback (most recent call last): -web-1 | File "/usr/src/app/atlas/views.py", line 3576, in uploads_import_htmx -web-1 | imported = import_dicoms_helper(request, case_id=case_id, dicoms=dicoms) -web-1 | File "/usr/src/app/atlas/api.py", line 280, in import_dicoms_helper -web-1 | series_image.save() -web-1 | File "/usr/src/app/generic/models.py", line 390, in save -web-1 | super().save(*args, **kwargs) # Call the "real" save() method. -web-1 | File "/opt/venv/lib/python3.14/site-packages/django/db/models/base.py", line 874, in save -web-1 | self.save_base( -web-1 | File "/opt/venv/lib/python3.14/site-packages/django/db/models/base.py", line 981, in save_base -web-1 | post_save.send( -web-1 | File "/opt/venv/lib/python3.14/site-packages/django/dispatch/dispatcher.py", line 209, in send -web-1 | response = receiver(signal=self, sender=sender, **named) -web-1 | File "/usr/src/app/atlas/models.py", line 1382, in _populate_case_study_date_on_series_image_save -web-1 | tags = instance.basic_dicom_tags or {} -web-1 | AttributeError: 'SeriesImage' object has no attribute 'basic_dicom_tags' -web-1 | Internal Server Error: /atlas/uploads/import/case/241 - -please add a unit test that demostrates the failure and then fix the bug and confirm that the unit test then passes. - -please also check why when I add the - logger.exception("Error during uploads import") -error in production this does not seem to get shown anywhere. The only log just showed - ERROR 03/Jun/2026 11:52:50 django.request:249 -Internal Server Error: /atlas/uploads/import -the online local settings are -DEBUG = False -INTERNAL_IPS = ["82.69.88.125", "217.155.198.96"] -#SECURE_SSL_REDIRECT = False -#SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'http') -#REMOTE_URL = "http://46.101.13.46:8123" -# -#MEDIA_ROOT = '/home/django/rad/media/' -STATIC_ROOT = '/home/ross/web/static/' - -#EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' -EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" - -if not DEBUG: - LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'formatters': { - 'verbose': { - 'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s", - 'datefmt' : "%d/%b/%Y %H:%M:%S" - }, - 'simple': { - 'format': '%(levelname)s %(message)s' - }, - }, - 'handlers': { - 'file': { - 'level': 'DEBUG', - 'class': 'logging.FileHandler', - 'filename': 'log.txt', - 'formatter': 'verbose' - }, - }, - 'loggers': { - 'django': { - 'handlers':['file'], - 'propagate': True, - 'level':'DEBUG', - }, - 'atlas': { - 'handlers': ['file'], - 'level': 'DEBUG', - }, - #"django.core.mail": {"handlers": ["console"], "level": "DEBUG", "propagate": False}, - #"smtplib": {"handlers": ["console"], "level": "DEBUG", "propagate": False}, - } - } +3. on the series tools page we are able to generate reconstructions of selected series. currently the process works but the created dicoms do not align correctly with the original soruce (in terms of 3d volume space) indicating that there is a bug in the reconstruction code. in an ideal setting we would have an option to define /manually set the reconstruction alignment to generate the reconstructions from to account for scans where the patient is not corrcetly aligned with the x,y,z axis. this would be possible by making use of the crosshairs tools in the cornerstone3d library (https://www.cornerstonejs.org/live-examples/crosshairs) to extend the dv3d viewer in a way that allows setting the desired reconstruction planes, projection (min/max/average) mode and slab thickness. please look at fixing the 3d volume space of the current implemenatation and adding a new advanced page that implements the new dv3d implementation (leavving both in place). +i have added a dicom series into the folder temp/recon that you can use to test if required. +4. search widgets such as case-search-widget should show a loading indicator whilst awaiting htmx responses. \ No newline at end of file