EEC-149: Implement customised routes for problem selections.#103
EEC-149: Implement customised routes for problem selections.#103anjurajanHO wants to merge 19 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Implements a canonical, ordered “problem” sub-journey with dynamic fork routing and deterministic back-link behavior, aiming to make multi-problem selection flows (including edit journeys) progress consistently.
Changes:
- Added canonical problem ordering + utilities to map problem keys ↔ routes and derive owned fields.
- Replaced hardcoded
/problemforks with generated forks based on selected problems and configured order; added behaviors to preserve problem data across edits and to set custom back links. - Updated summary formatting helpers and summary section parsing to support cleaner output.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| utils/problem-utils.js | Adds mapping/order utilities and helpers for selection/field ownership. |
| utils/problem-order.js | Defines canonical ordered list of problem keys → target routes. |
| utils/index.js | Adds joinNonEmpty helper and exports it. |
| utils/build-problem-forks.js | Generates ordered HOF forks for “next selected problem” progression (edit-aware). |
| apps/eec/sections/summary-data-sections.js | Updates summary parsing/formatting for corrected-details (including selected problems). |
| apps/eec/index.js | Integrates new behaviours and generated forks across problem-related steps; adds session clearing on check answers. |
| apps/eec/fields/index.js | Simplifies problem checkbox options definition. |
| apps/eec/behaviours/problem-back-link.js | Adds deterministic back-link logic for the problem sub-journey. |
| apps/eec/behaviours/clear-problem-session.js | Clears problem-related session fields when no problems are selected. |
| apps/eec/behaviours/capture-problem-selection.js | Snapshots/restores problem-owned values across edit submissions to avoid unwanted clearing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| step: '/problem', | ||
| field: 'problem', | ||
| parse: val => Array.isArray(val) ? val.join('\n') : val | ||
| }, |
| const steps = req.form && req.form.options ? req.form.options.steps : null; | ||
| const sessionSteps = toArray(req.sessionModel.get('steps')); | ||
|
|
||
| if (targetRoute && steps && steps[targetRoute] && Array.isArray(steps[targetRoute].fields)) { | ||
| return steps[targetRoute].fields; | ||
| } | ||
|
|
||
| if (targetRoute && steps) { | ||
| const matchingSessionRoute = sessionSteps.find(stepRoute => { | ||
| const route = typeof stepRoute === 'string' ? stepRoute : ''; | ||
| return route === targetRoute | ||
| || route === `${targetRoute}/edit` | ||
| || route.startsWith(`${targetRoute}/edit/`); | ||
| }); | ||
|
|
||
| if (matchingSessionRoute && steps[targetRoute] && Array.isArray(steps[targetRoute].fields)) { | ||
| return steps[targetRoute].fields; | ||
| } | ||
| } |
| return new Intl.DateTimeFormat(config.dateLocales, config.dateFormat).format(dateObj); | ||
| }; | ||
|
|
||
| const joinNonEmpty = (values, separator = ' ') => values.filter(Boolean).join(separator); |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
apps/eec/sections/summary-data-sections.js:39
- The summary currently outputs the raw
problem-*keys (joined with newlines). The translations already contain user-facing labels for these options, so this will display internal identifiers instead of readable text.
{
step: '/problem',
field: 'problem',
parse: val => Array.isArray(val) ? val.join('\n') : val
},
utils/index.js:16
- New
joinNonEmptyutility is used to format summary values but is not covered by the existingtest/unit/utils.test.jssuite. Adding a small set of unit tests would lock in expected behaviour (e.g., trimming/blank handling, separators, non-string values).
const joinNonEmpty = (values, separator = ' ') => values.filter(Boolean).join(separator);
| return new Intl.DateTimeFormat(config.dateLocales, config.dateFormat).format(dateObj); | ||
| }; | ||
|
|
||
| const joinNonEmpty = (values, separator = ' ') => values.filter(Boolean).join(separator); |
| if (steps && selectedProblems.length === 0) { | ||
| getProblemFieldsToClear(steps).forEach(fieldName => { | ||
| req.sessionModel.unset(fieldName); | ||
| }); | ||
|
|
||
| // Keep edit snapshots in sync when no problem journey is selected. | ||
| req.sessionModel.unset('problem-selection-before-edit'); | ||
| req.sessionModel.unset('problem-selection-current-edit'); | ||
| req.sessionModel.unset('problem-values-before-edit'); | ||
| } |
| // Find the next selected problem after the current step. | ||
| // - Non-edit: first later selected problem. | ||
| // - Edit: first later selected problem with missing owned fields. | ||
| const nextSelectedProblem = (req, afterKey = null) => { | ||
| const selected = new Set(getProblemSelection(req)); | ||
| const afterOrder = getProblemOrder(afterKey); | ||
| const editJourney = isEditJourney(req); | ||
|
|
||
| for (const problem of ORDERED_PROBLEM_ORDER) { | ||
| if (problem.order <= afterOrder) { | ||
| continue; | ||
| } | ||
|
|
||
| if (!selected.has(problem.key)) { | ||
| continue; | ||
| } | ||
|
|
||
| if (!editJourney) { | ||
| return problem.target; | ||
| } | ||
|
|
||
| if (problemHasMissingOwnedFields(req, problem.key)) { | ||
| return problem.target; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| }; |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
apps/eec/sections/summary-data-sections.js:39
- The summary currently renders the raw
problemoption keys (e.g.problem-full-name) instead of the translated labels. Since translations exist for these options (andgetLabelalready supports arrays), this will surface internal identifiers to users.
{
step: '/problem',
field: 'problem',
parse: val => Array.isArray(val) ? val.join('\n') : val
},
| problem: { | ||
| mixin: 'checkbox-group', | ||
| validate: ['required'], | ||
| isPageHeading: true, | ||
| options: [ |
| @@ -0,0 +1,89 @@ | |||
| const { PROBLEM_ORDER } = require('./problem-order'); | |||
|
|
|||
| const ORDERED_PROBLEM_ORDER = PROBLEM_ORDER.slice(); | |||
| const isEditJourney = req => { | ||
| const params = req.params || {}; | ||
| return Boolean(params.edit || params.action === 'edit'); | ||
| }; |
…p selected pages in early stages by performing backlink in edit mode.
204fb13 to
ff50f80
Compare
What?
Why?
How?
Testing?
Screenshots (optional)
Anything Else? (optional)
Check list