Skip to content

Commit 5cb84fa

Browse files
Get new image views working
1 parent 0f7a18a commit 5cb84fa

File tree

6 files changed

+262
-83
lines changed

6 files changed

+262
-83
lines changed

app/assets/sass/_misc.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.app-mammogram-image--placeholder {
22
background-color: black;
3-
width: 150px;
4-
height:200px;
3+
width: 75px;
4+
height:100px;
55

66
p {
77
color: white;

app/lib/generators/mammogram-generator.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@ const REPEAT_REASONS = [
1616
'patient movement',
1717
'positioning issue',
1818
'exposure issue',
19-
'breast not fully imaged',
2019
'blurred image',
2120
'technical fault'
2221
]
2322

2423
// Probability settings for repeats
2524
const REPEAT_PROBABILITIES = {
26-
needsRepeat: 0.15, // 15% chance of needing any repeat
25+
needsRepeat: 0.35, // 15% chance of needing any repeat
2726
multipleRepeats: 0.2 // 20% chance of needing more than one repeat if already repeating
2827
}
2928

@@ -63,8 +62,8 @@ const generateViewImages = ({ side, view, accessionBase, startIndex, startTime,
6362
url: generateImageUrl(side, view, `${accessionBase}/${currentIndex}`)
6463
})
6564

66-
// Generate repeats if needed (and if we're in seed mode or randomly need them)
67-
if (needsRepeat && isSeedData) {
65+
// Generate repeats if needed
66+
if (needsRepeat) {
6867
const repeatCount = Math.random() < REPEAT_PROBABILITIES.multipleRepeats ? 2 : 1
6968

7069
for (let i = 0; i < repeatCount; i++) {
@@ -82,6 +81,8 @@ const generateViewImages = ({ side, view, accessionBase, startIndex, startTime,
8281
return {
8382
side,
8483
view,
84+
viewShort: view === 'mediolateral oblique' ? 'MLO' : 'CC',
85+
viewShortWithSide: `${side === 'right' ? 'R' : 'L'}${view === 'mediolateral oblique' ? 'MLO' : 'CC'}`,
8586
images,
8687
isRepeat: needsRepeat && isSeedData,
8788
repeatReason: needsRepeat && isSeedData ? faker.helpers.arrayElement(REPEAT_REASONS) : null

app/lib/utils/objects.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// app/lib/utils/objects.js
2+
3+
const _ = require('lodash')
4+
5+
/**
6+
* Extract all values from an object into a flat array
7+
* @param {Object} obj - The object to extract values from
8+
* @param {Object} [options] - Options for value extraction
9+
* @param {boolean} [options.recursive=false] - Whether to recursively extract values from nested objects
10+
* @param {boolean} [options.includeArrays=true] - Whether to include array values
11+
* @param {boolean} [options.removeEmpty=false] - Whether to remove null/undefined values
12+
* @returns {Array} Array of all values from the object
13+
* @example
14+
* getObjectValues({ name: 'Jane', age: 30 }) // Returns ['Jane', 30]
15+
* getObjectValues({ user: { name: 'Jane' }}, { recursive: true }) // Returns ['Jane']
16+
*/
17+
const getObjectValues = (obj, options = {}) => {
18+
const {
19+
recursive = false,
20+
includeArrays = true,
21+
removeEmpty = false
22+
} = options
23+
24+
if (!obj || typeof obj !== 'object') {
25+
return []
26+
}
27+
28+
// Get initial values
29+
let values = Object.values(obj)
30+
31+
if (recursive) {
32+
values = values.reduce((acc, val) => {
33+
// If value is an object, recursively get its values
34+
if (val && typeof val === 'object' && !Array.isArray(val)) {
35+
return [...acc, ...getObjectValues(val, options)]
36+
}
37+
return [...acc, val]
38+
}, [])
39+
}
40+
41+
// Handle arrays based on options
42+
if (!includeArrays) {
43+
values = values.filter(val => !Array.isArray(val))
44+
}
45+
46+
// Remove empty values if specified
47+
if (removeEmpty) {
48+
values = values.filter(val => val !== null && val !== undefined)
49+
}
50+
51+
return values
52+
}
53+
54+
module.exports = {
55+
getObjectValues
56+
}

app/lib/utils/strings.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// app/lib/utils/strings.js
22

3+
const pluralizeLib = require('pluralize')
4+
5+
36
/**
47
* Convert string to sentence case, removing leading/trailing whitespace
58
* @param {string} input - String to convert
@@ -240,6 +243,28 @@ const formatNhsNumber = (input) => {
240243
// formatNhsNumber(4857773456) // returns '485 777 3456'
241244
// formatNhsNumber('485 777 3456') // returns '485 777 3456'
242245

246+
/**
247+
* Make a word plural based on a count
248+
* @param {string} word - Word to pluralise
249+
* @param {...*} args - Additional arguments (e.g. count) passed to pluralise
250+
* @returns {string} Pluralized word
251+
* @example
252+
* pluralise('cat') // returns 'cats'
253+
* pluralise('cat', 1) // returns 'cat'
254+
* pluralise('cat', '2') // returns 'cats'
255+
*/
256+
const pluralise = (word, ...args) => {
257+
if (!word) return ''
258+
if (typeof word !== 'string') return word
259+
260+
// Convert first arg to number if it looks like one
261+
if (args.length && !isNaN(args[0])) {
262+
args[0] = Number(args[0])
263+
}
264+
265+
return pluralizeLib(word, ...args)
266+
}
267+
243268
module.exports = {
244269
addIndefiniteArticle,
245270
formatCurrency,
@@ -260,4 +285,5 @@ module.exports = {
260285
startsWith,
261286
stringLiteral,
262287
formatPhoneNumber,
288+
pluralise
263289
}

app/routes/events.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// app/routes/events.js
2+
const dayjs = require('dayjs')
3+
24
const { getFullName } = require('../lib/utils/participants')
5+
const { generateMammogramImages } = require('../lib/generators/mammogram-generator')
36

47
/**
58
* Get single event and its related data
@@ -111,7 +114,7 @@ module.exports = router => {
111114
}
112115
})
113116

114-
const MAMMOGRAPHY_VIEWS = ['medical-information', 'record-medical-information', 'ready-for-imaging', 'awaiting-images', 'images', 'imaging', 'confirm', 'screening-complete', 'attended-not-screened-reason']
117+
const MAMMOGRAPHY_VIEWS = ['medical-information', 'record-medical-information', 'ready-for-imaging', 'awaiting-images', 'images', 'confirm', 'screening-complete', 'attended-not-screened-reason']
115118

116119
// Event within clinic context
117120
router.get('/clinics/:clinicId/events/:eventId/:view', (req, res, next) => {
@@ -121,6 +124,35 @@ module.exports = router => {
121124
} else next()
122125
})
123126

127+
// Specific route for imaging view
128+
router.get('/clinics/:clinicId/events/:eventId/imaging', (req, res) => {
129+
const { eventId } = req.params
130+
const event = req.session.data.events.find(e => e.id === eventId)
131+
132+
// If no mammogram data exists, generate it
133+
if (!event.mammogramData) {
134+
const eventIndex = req.session.data.events.findIndex(e => e.id === eventId)
135+
// Set start time to 3 minutes ago to simulate an in-progress screening
136+
const startTime = dayjs().subtract(3, 'minutes').toDate()
137+
const mammogramData = generateMammogramImages({
138+
startTime,
139+
isSeedData: false
140+
})
141+
142+
// Update both session data and locals
143+
const updatedEvent = {
144+
...event,
145+
mammogramData
146+
}
147+
148+
req.session.data.events[eventIndex] = updatedEvent
149+
res.locals.event = updatedEvent
150+
}
151+
152+
res.render('events/mammography/imaging', {})
153+
})
154+
155+
124156
// Handle medical information answer
125157
router.post('/clinics/:clinicId/events/:eventId/medical-information-answer', (req, res) => {
126158
const { clinicId, eventId } = req.params

0 commit comments

Comments
 (0)