Skip to content

Commit 04fb165

Browse files
Image reading v1.5 updates (#56)
* Simplify normal details page * Update recall page * Update annotation and recall pages * Add clinic codes * Clean up symptoms display * Add forward-link component * Refactor reading ui * Move partial mammography lower * Randomisation work, elements of multiple reads * Add decorateAttributes, copied from DfE Register * Work on recall for assessment pages * Make symptoms card consistent
1 parent f5358d2 commit 04fb165

30 files changed

+1226
-592
lines changed

app/assets/sass/_misc.scss

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@
1111
}
1212
}
1313

14+
.app-image-two-up {
15+
display: flex;
16+
justify-content: space-between;
17+
margin-bottom: 20px;
18+
19+
img {
20+
width: 48%;
21+
}
22+
}
23+
24+
.app-position-relative {
25+
position: relative;
26+
}
27+
28+
.app-align-right {
29+
float: right;
30+
* {
31+
text-align: right;
32+
}
33+
}
34+
1435
.app-suppress-link-styles * {
1536
text-decoration: none;
1637
color: $nhsuk-secondary-text-color;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
////
2+
/// Back link component
3+
///
4+
/// 1. Allow space for the arrow.
5+
/// 2. Align the icon with the start of the back link.
6+
/// 3. Align the icon with the middle of the text.
7+
/// 4. Make back link same height as breadcrumb.
8+
///
9+
/// @group components
10+
////
11+
12+
.app-forward-link {
13+
margin-top: nhsuk-spacing(3);
14+
line-height: 1; // [5]
15+
16+
@include mq($from: tablet) {
17+
margin-top: nhsuk-spacing(4);
18+
}
19+
}
20+
21+
.app-forward-link__link {
22+
@include nhsuk-typography-responsive(16);
23+
@include nhsuk-link-style-default;
24+
25+
background: none;
26+
border: 0;
27+
cursor: pointer;
28+
display: inline-block;
29+
padding: 0 16px 0 0; // [1]
30+
position: relative;
31+
text-decoration: none;
32+
33+
.nhsuk-icon__chevron-right {
34+
height: 24px;
35+
right: -8px; // [2]
36+
position: absolute;
37+
top: -1px; // [3]
38+
width: 24px;
39+
40+
@include mq($from: tablet) {
41+
top: 0; // [3]
42+
}
43+
}
44+
45+
&:visited {
46+
color: $nhsuk-link-color;
47+
}
48+
49+
&:hover {
50+
color: $nhsuk-link-hover-color;
51+
text-decoration: underline;
52+
53+
.nhsuk-icon__chevron-right {
54+
fill: $nhsuk-link-hover-color;
55+
}
56+
}
57+
58+
&:focus {
59+
.nhsuk-icon__chevron-right {
60+
fill: $nhsuk-focus-text-color;
61+
}
62+
}
63+
}

app/assets/sass/main.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
@import 'components/header-organisation';
1010
@import 'components/secondary-navigation';
1111
@import 'components/count';
12+
@import 'components/forward-link';
1213
@import 'components/notification-banner';
1314
@import 'components/status';
1415
@import 'components/reading';

app/filters/form-attributes.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// app/filters/form-attributes.js
2+
3+
const _ = require('lodash')
4+
5+
/**
6+
* Decorate attributes
7+
* Add name, value, id, idPrefix and checked attributes to NHSUK form components
8+
* Generate the attributes based on the application ID and the section they're in
9+
*
10+
* @param {Object} originalObject - The original component configuration
11+
* @param {Object} data - The data object to extract values from
12+
* @param {string} path - Path to the data property (e.g. "data.nationality")
13+
* @returns {Object} The decorated component configuration
14+
*
15+
* @example
16+
* {{ nhsukCheckboxes({
17+
* fieldset: {
18+
* legend: {
19+
* text: "Nationality",
20+
* classes: "nhsuk-fieldset__legend--s"
21+
* }
22+
* },
23+
* items: [
24+
* {
25+
* text: "British"
26+
* },
27+
* {
28+
* text: "Irish"
29+
* },
30+
* {
31+
* text: "Other"
32+
* }
33+
* ]
34+
* } | decorateAttributes(data, "data.nationality"))}}
35+
*/
36+
const decorateAttributes = (originalObject, data, path) => {
37+
// Deep clone to avoid modifying the original object
38+
const obj = _.cloneDeep(originalObject)
39+
40+
// Map dot or bracket notation to path parts
41+
const pathParts = _.toPath(path)
42+
43+
// Strip 'data' prefix if present
44+
let dataPath = [...pathParts]
45+
if (pathParts[0] === 'data') {
46+
dataPath = dataPath.slice(1)
47+
}
48+
49+
// Get the stored value from data
50+
const storedValue = _.get(data, dataPath)
51+
52+
if (obj.items !== undefined) {
53+
obj.items = obj.items.map(item => {
54+
// Skip dividers
55+
if (item.divider) return item
56+
57+
// Set default value to text if not provided
58+
if (typeof item.value === 'undefined') {
59+
item.value = item.text
60+
}
61+
62+
// Default checked/selected states when no data exists
63+
let checked = item.checked
64+
let selected = item.selected
65+
66+
// Only process if we have a stored value to compare against
67+
if (storedValue !== undefined) {
68+
// For array values (like checkboxes)
69+
if (Array.isArray(storedValue)) {
70+
if (storedValue.includes(item.value)) {
71+
checked = 'checked'
72+
selected = 'selected'
73+
} else {
74+
// Clear any default checked state when we have data
75+
checked = ''
76+
selected = ''
77+
}
78+
} else {
79+
// For single values (like radios)
80+
if (storedValue === item.value) {
81+
checked = 'checked'
82+
selected = 'selected'
83+
} else {
84+
// Clear any default checked state when we have data
85+
checked = ''
86+
selected = ''
87+
}
88+
}
89+
}
90+
91+
// Assign the computed values
92+
item.checked = checked
93+
item.selected = selected
94+
95+
return item
96+
})
97+
98+
// Set idPrefix if not already defined
99+
obj.idPrefix = obj.idPrefix || pathParts.join('-')
100+
} else {
101+
// For non-array components (like text inputs),
102+
// set the value if not already defined
103+
if (typeof obj.value === 'undefined') {
104+
obj.value = storedValue
105+
}
106+
}
107+
108+
// Set id and name attributes if not already defined
109+
obj.id = obj.id || pathParts.join('-')
110+
obj.name = obj.name || pathParts.map(s => `[${s}]`).join('')
111+
console.log("Object name:", obj.name)
112+
return obj
113+
}
114+
115+
module.exports = {
116+
decorateAttributes
117+
}

app/lib/generators/clinic-generator.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ const determineClinicType = (location, breastScreeningUnit) => {
2929
})
3030
}
3131

32+
const generateClinicCode = () => {
33+
// Example format: AB123 where AB is one of an array.
34+
const prefixOptions = ['CH', 'MU', 'WS',]
35+
const suffix = faker.number.int({ min: 100, max: 999 })
36+
return `${faker.helpers.arrayElement(prefixOptions)}${suffix}`
37+
}
38+
3239
const generateTimeSlots = (date, sessionTimes, clinicType) => {
3340
const { slotDurationMinutes } = config.clinics
3441
const today = dayjs().startOf('day')
@@ -151,6 +158,7 @@ const generateClinic = (date, location, breastScreeningUnit, sessionTimes, overr
151158

152159
return {
153160
id: generateId(),
161+
clinicCode: generateClinicCode(),
154162
date: date.toISOString().split('T')[0],
155163
breastScreeningUnitId: breastScreeningUnit.id,
156164
locationType: location.type,

0 commit comments

Comments
 (0)