From 7dda3ad4ecf1d1ced615b0039506db45c371d49f Mon Sep 17 00:00:00 2001 From: Ed Horsford Date: Wed, 28 Jan 2026 17:51:10 +0000 Subject: [PATCH 1/7] Refactor opinion page and add thumbnails --- app/assets/sass/components/_reading.scss | 117 +++++++++++++++ app/config.js | 3 + app/views/reading/workflow/opinion.html | 175 ++++++++++++++++++----- 3 files changed, 262 insertions(+), 33 deletions(-) diff --git a/app/assets/sass/components/_reading.scss b/app/assets/sass/components/_reading.scss index c3ad4d90..9d7f578c 100644 --- a/app/assets/sass/components/_reading.scss +++ b/app/assets/sass/components/_reading.scss @@ -11,6 +11,123 @@ padding: 10px; } +// Mammogram thumbnail grid for reading pages +.app-mammogram-thumbnails { + display: inline-grid; + grid-template-columns: auto auto; + gap: 8px; +} + +.app-mammogram-thumbnail--right { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 8px; +} + +.app-mammogram-thumbnail--left { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; +} + +// Individual image wrapper (contains image + label) +.app-mammogram-thumbnail__image-wrapper { + position: relative; + display: inline-block; + // Fixed dimensions for consistent sizing + width: 120px; + height: 150px; + background-color: #000; +} + +.app-mammogram-thumbnail__image { + width: 100%; + height: 100%; + object-fit: contain; + display: block; + cursor: zoom-in; +} + +// Right breast images align right top (inwards), left breast align left top (inwards) +.app-mammogram-thumbnail--right .app-mammogram-thumbnail__image { + object-position: right top; +} + +.app-mammogram-thumbnail--left .app-mammogram-thumbnail__image { + object-position: left top; +} + +.app-mammogram-thumbnail__label { + position: absolute; + top: 4px; + background-color: nhsuk-colour("blue"); + color: #fff; + padding: 2px 6px; + font-size: 11px; + font-weight: 600; + z-index: 1; +} + +// Labels align to outer edge - right breast labels on left, left breast labels on right +.app-mammogram-thumbnail--right .app-mammogram-thumbnail__label { + left: 4px; +} + +.app-mammogram-thumbnail--left .app-mammogram-thumbnail__label { + right: 4px; +} + +// Missing image placeholder +.app-mammogram-thumbnail__missing { + width: 100%; + height: 100%; + border: 2px dashed nhsuk-colour("grey-2"); + background-color: nhsuk-colour("grey-5"); + display: flex; + align-items: center; + justify-content: center; + box-sizing: border-box; +} + +.app-mammogram-thumbnail__missing-text { + font-size: 12px; + color: nhsuk-colour("grey-2"); +} + +// Zoom overlay for thumbnails +.app-mammogram-zoom { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.95); + z-index: 9999; + display: flex; + align-items: center; + justify-content: center; + cursor: zoom-out; +} + +.app-mammogram-zoom__image { + max-width: 95%; + max-height: 95%; + object-fit: contain; +} + +.app-mammogram-zoom__label { + position: absolute; + top: 16px; + left: 16px; + background-color: nhsuk-colour("blue"); + color: #fff; + padding: 8px 16px; + font-size: 14px; + font-weight: 600; +} + .app-reading-status { background-color: nhsuk-shade(nhsuk-colour("blue"), 40%); color: $nhsuk-reverse-text-colour; diff --git a/app/config.js b/app/config.js index 31634362..be27a258 100644 --- a/app/config.js +++ b/app/config.js @@ -45,6 +45,9 @@ module.exports = { urgentThreshold: 10, // 10 days and over priorityThreshold: 7, // 7 days and over mammogramImageSource: 'diagrams', // 'diagrams' or 'real' + // View order for mammogram display: 'cc-first' or 'mlo-first' + // Right breast views always on left, left breast views on right + mammogramViewOrder: 'cc-first', // Distribution of image set tags (must sum to 1.0) // These are the base weights - they get adjusted based on event context // (symptoms, imperfect images, etc.) diff --git a/app/views/reading/workflow/opinion.html b/app/views/reading/workflow/opinion.html index 94a2dd83..8004f522 100644 --- a/app/views/reading/workflow/opinion.html +++ b/app/views/reading/workflow/opinion.html @@ -3,7 +3,7 @@ {% extends 'layout-reading.html' %} -{% set pageHeading = "Review images" %} +{% set pageHeading = participant | getFullName %} {% set gridColumn = "none" %} {% set showWorkflowNav = true %} @@ -27,14 +27,35 @@ {% set opinionHeading = "Update review" %} {% endif %} + {# Get mammogram images for thumbnails #} + {% set mammogramImages = getImagesForEvent(eventId, "diagrams", { event: event }) %} + + {# View order from config - determines if CC or MLO comes first #} + {# Right breast views on left, left breast views on right #} + {% if data.config.reading.mammogramViewOrder == 'mlo-first' %} + {% set viewOrder = [ + { key: 'rmlo', label: 'RMLO', side: 'right' }, + { key: 'lmlo', label: 'LMLO', side: 'left' }, + { key: 'rcc', label: 'RCC', side: 'right' }, + { key: 'lcc', label: 'LCC', side: 'left' } + ] %} + {% else %} + {% set viewOrder = [ + { key: 'rcc', label: 'RCC', side: 'right' }, + { key: 'lcc', label: 'LCC', side: 'left' }, + { key: 'rmlo', label: 'RMLO', side: 'right' }, + { key: 'lmlo', label: 'LMLO', side: 'left' } + ] %} + {% endif %} + {# Page header with status tags #}
- {{ participant | getFullName }} + {{ opinionHeading }}

- {{ opinionHeading }} + {{ participant | getFullName }}

@@ -98,18 +119,83 @@

- {# Opinion form #} + {# Image notes - moved above opinion section #} + {% include "_includes/reading/image-warnings.njk" %} + + {# Opinion form with thumbnails #} {% set questionText = "What is your opinion of these images?" %} + {# Count total images #} + {% set imageCount = 0 %} + {% for view in viewOrder %} + {% set allPaths = mammogramImages.allPaths[view.key] if mammogramImages and mammogramImages.allPaths else null %} + {% if allPaths %} + {% if allPaths is string %} + {% set imageCount = imageCount + 1 %} + {% else %} + {% set imageCount = imageCount + allPaths | length %} + {% endif %} + {% endif %} + {% endfor %} +
{# Hidden field to track previous result for change detection #} - {% if hasExistingOpinion %} - {# Show radios when updating an existing or in-progress result #} -
-
+
+ {# Left column: Mammogram thumbnails #} +
+

Image thumbnails ({{ imageCount }})

+
+ {% for view in viewOrder %} +
+ {% set allPaths = mammogramImages.allPaths[view.key] if mammogramImages and mammogramImages.allPaths else null %} + + {% if allPaths %} + {# Handle both single path (string) and multiple paths (array) #} + {% if allPaths is string %} +
+ {{ view.label }} + {{ view.label }} view +
+ {% else %} + {# Multiple images - each with its own wrapper and label #} + {% for imagePath in allPaths %} +
+ {{ view.label }} + {{ view.label }} view ({{ loop.index }} of {{ loop.length }}) +
+ {% endfor %} + {% endif %} + {% else %} + {# Missing image placeholder #} +
+ {{ view.label }} +
+ No image +
+
+ {% endif %} +
+ {% endfor %} +
+
+ + {# Right column: Opinion buttons/radios #} +
+ {% if hasExistingOpinion %} + {# Show radios when updating an existing or in-progress result #} {{ radios({ name: "imageReadingTemp[result]", fieldset: { @@ -145,20 +231,12 @@

{{ button({ text: "Update opinion" }) }} -

-
- {% else %} - {# Show buttons for initial assessment #} -
-
-

{{ questionText }}

-
-
+ {% else %} + {# Show buttons for initial assessment - vertically stacked #} +

{{ questionText }}

-
-
-
+
{% if hasSymptoms %} {{ button({ text: "Normal, and add details", @@ -174,26 +252,24 @@

{{ questionText }}

classes: "app-button-full-width nhsuk-u-margin-bottom-3" }) }} -

+

{% endif %}
-
-
-
+ +
{{ button({ text: "Technical recall", value: "technical_recall", name: "imageReadingTemp[result]", - classes: "nhsuk-button--secondary app-button-full-width" + classes: "nhsuk-button--secondary app-button-full-width nhsuk-u-margin-bottom-3" }) }}
-
-
-
+ +
{{ button({ text: "Recall for assessment", value: "recall_for_assessment", @@ -201,12 +277,10 @@

{{ questionText }}

classes: "nhsuk-button--warning app-button-full-width" }) }}
-
-
- {% endif %} - - {% include "_includes/reading/image-warnings.njk" %} + {% endif %} +
+
@@ -228,3 +302,38 @@

{{ questionText }}

}) }} {% endblock %} + +{% block pageScripts %} + +{% endblock %} From 8afeb7dda2aea1923cdbcbe716a331dcce056950 Mon Sep 17 00:00:00 2001 From: Ed Horsford Date: Wed, 28 Jan 2026 17:54:16 +0000 Subject: [PATCH 2/7] Clean up image alignment --- app/assets/sass/components/_reading.scss | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/app/assets/sass/components/_reading.scss b/app/assets/sass/components/_reading.scss index 9d7f578c..376bbfef 100644 --- a/app/assets/sass/components/_reading.scss +++ b/app/assets/sass/components/_reading.scss @@ -35,28 +35,29 @@ // Individual image wrapper (contains image + label) .app-mammogram-thumbnail__image-wrapper { position: relative; - display: inline-block; // Fixed dimensions for consistent sizing width: 120px; height: 150px; background-color: #000; + // Use flexbox for image alignment + display: flex; + align-items: flex-start; } -.app-mammogram-thumbnail__image { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - cursor: zoom-in; +// Right breast images align right (inwards), left breast align left (inwards) +.app-mammogram-thumbnail--right .app-mammogram-thumbnail__image-wrapper { + justify-content: flex-end; } -// Right breast images align right top (inwards), left breast align left top (inwards) -.app-mammogram-thumbnail--right .app-mammogram-thumbnail__image { - object-position: right top; +.app-mammogram-thumbnail--left .app-mammogram-thumbnail__image-wrapper { + justify-content: flex-start; } -.app-mammogram-thumbnail--left .app-mammogram-thumbnail__image { - object-position: left top; +.app-mammogram-thumbnail__image { + max-width: 100%; + max-height: 100%; + display: block; + cursor: zoom-in; } .app-mammogram-thumbnail__label { From ac052c77ac721cc4faf80e53bff7d3ac45b91833 Mon Sep 17 00:00:00 2001 From: Ed Horsford Date: Mon, 2 Feb 2026 11:20:07 +0000 Subject: [PATCH 3/7] Move image stuff below --- app/views/_includes/reading/image-warnings.njk | 2 +- app/views/reading/workflow/opinion.html | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/views/_includes/reading/image-warnings.njk b/app/views/_includes/reading/image-warnings.njk index c03e831b..132f74f1 100644 --- a/app/views/_includes/reading/image-warnings.njk +++ b/app/views/_includes/reading/image-warnings.njk @@ -91,7 +91,7 @@
{{ insetText({ html: warningsHtml, - classes: "nhsuk-u-margin-top-6" + classes: "" }) }}
diff --git a/app/views/reading/workflow/opinion.html b/app/views/reading/workflow/opinion.html index 8004f522..81414190 100644 --- a/app/views/reading/workflow/opinion.html +++ b/app/views/reading/workflow/opinion.html @@ -119,8 +119,7 @@

- {# Image notes - moved above opinion section #} - {% include "_includes/reading/image-warnings.njk" %} + {# Opinion form with thumbnails #} {% set questionText = "What is your opinion of these images?" %} @@ -284,6 +283,9 @@

{{ questionText }}

+ {# Image notes - moved above opinion section #} + {% include "_includes/reading/image-warnings.njk" %} + {# Medical summary #} {#
#} From 04d807089df3dc09bc055f58d94afef34af4b5b1 Mon Sep 17 00:00:00 2001 From: Ed Horsford Date: Mon, 2 Feb 2026 11:25:49 +0000 Subject: [PATCH 4/7] Disable zoom --- app/assets/sass/components/_reading.scss | 4 ++-- app/views/reading/workflow/opinion.html | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/assets/sass/components/_reading.scss b/app/assets/sass/components/_reading.scss index 376bbfef..f61cdea4 100644 --- a/app/assets/sass/components/_reading.scss +++ b/app/assets/sass/components/_reading.scss @@ -57,7 +57,7 @@ max-width: 100%; max-height: 100%; display: block; - cursor: zoom-in; + cursor: default; } .app-mammogram-thumbnail__label { @@ -109,7 +109,7 @@ display: flex; align-items: center; justify-content: center; - cursor: zoom-out; + cursor: default; } .app-mammogram-zoom__image { diff --git a/app/views/reading/workflow/opinion.html b/app/views/reading/workflow/opinion.html index 81414190..924e40ce 100644 --- a/app/views/reading/workflow/opinion.html +++ b/app/views/reading/workflow/opinion.html @@ -144,7 +144,7 @@

{# Left column: Mammogram thumbnails #} -
+

Image thumbnails ({{ imageCount }})

{% for view in viewOrder %} @@ -309,6 +309,13 @@

{{ questionText }}