From d2cb364e063728cd1bdc9e9f958bfbda8ceb9881 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 11:27:32 +0000 Subject: [PATCH 01/61] Added new routing screens for form creators --- .../question-routes/conditions.html | 129 ++++++++++++++++++ .../question-routes/new-condition-BACKUP.html | 66 +++++++++ .../question-routes/new-condition.html | 51 ++++++- .../question-routes/routes-summary.html | 109 +++++++++++++++ 4 files changed, 352 insertions(+), 3 deletions(-) create mode 100644 app/views/form-designer/question-routes/conditions.html create mode 100644 app/views/form-designer/question-routes/new-condition-BACKUP.html create mode 100644 app/views/form-designer/question-routes/routes-summary.html diff --git a/app/views/form-designer/question-routes/conditions.html b/app/views/form-designer/question-routes/conditions.html new file mode 100644 index 00000000..78044545 --- /dev/null +++ b/app/views/form-designer/question-routes/conditions.html @@ -0,0 +1,129 @@ +{% extends "layout-govuk-forms.html" %} + +{% set pageTitle = 'Add route 1' %} + +{% block pageTitle %} + {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms +{% endblock %} + +{% block beforeContent %} + + Back + +{% endblock %} + +{% block content %} +
+
+
+ + {% if containsErrors %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: errorList + }) }} + {% endif %} + + + {{ 'Question ' + (data.routeStartQuestion or 'X') + '’s routes' }} + +

{{ pageTitle }}

+ + {% set routeStart = '' %} + {% set tempAnswers = [] %} + {% set tempQuestions = [] %} + {% for page in data.pages -%} + {% if (page.pageIndex|int + 1) > data.routeStartQuestion + 1 %} + {% set tempQuestions = (tempQuestions.push(page), tempQuestions) %} + {% endif %} + {% if (page.pageIndex|int + 1) == data.routeStartQuestion %} + {% set routeStart = page['long-title'] %} + {% set tempAnswers = page['item-list'] %} + {% endif %} + {%- endfor %} + + {{ govukSummaryList({ + rows: [ + { + key: { + text: "Question " + (data.routeStartQuestion or 'X') + }, + value: { + text: routeStart or 'Not answered' + }, + actions: { + items: [ + { + href: "new-condition", + text: "Change", + visuallyHiddenText: " question" + } + ] + } + } + ] + }) }} + + {% set errorMessageAnswer = '' %} + {% set errorMessageEnd = '' %} + {% for error in errorList %} + {% if '#route-1-answer' in error.href %} + {% set errorMessageAnswer = error.text %} + {% endif %} + {% if '#route-1-end' in error.href %} + {% set errorMessageEnd = error.text %} + {% endif %} + {% endfor %} + +
+ + {% if containsErrors and errorMessageAnswer -%} +

+ Error: {{ errorMessageAnswer }} +

+ {%- endif %} + +
+ +
+ + {% if containsErrors and errorMessageEnd -%} +

+ Error: {{ errorMessageEnd }} +

+ {%- endif %} + +
+ + {{ govukButton({ + text: "Save and continue" + }) }} + +
+
+
+{% endblock %} + +{% block pageScripts %} + +{% endblock %} \ No newline at end of file diff --git a/app/views/form-designer/question-routes/new-condition-BACKUP.html b/app/views/form-designer/question-routes/new-condition-BACKUP.html new file mode 100644 index 00000000..b5ac3ef8 --- /dev/null +++ b/app/views/form-designer/question-routes/new-condition-BACKUP.html @@ -0,0 +1,66 @@ +{% extends "layout-govuk-forms.html" %} + +{% set pageTitle = 'Add a question route' %} + +{% block pageTitle %} + {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms +{% endblock %} + +{% block beforeContent %} + {% if previousPage and ('your-questions' in previousPage) %} + + Back to your questions + + {% else %} + + Back + + {% endif %} +{% endblock %} + +{% block content %} +
+
+
+ + {% if containsErrors %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: errorList + }) }} + {% endif %} + + {{ data.formTitle or '[formTitle]' }} +

{{ pageTitle }}

+ +

+ You can send people directly to the question or page you want, based on their previous answer. This means they’ll only see questions that are relevant to them. +

+ +

What you need to create a route

+

+ Before you can add a route you’ll need: +

+
    +
  • 2 or more questions
  • +
  • at least one question where people must select a single item from a list of options
  • +
+

+ You can only add one route from each question. +

+ +

+ Go to your questions +

+ +
+
+
+{% endblock %} + +{% block pageScripts %} + +{% endblock %} \ No newline at end of file diff --git a/app/views/form-designer/question-routes/new-condition.html b/app/views/form-designer/question-routes/new-condition.html index b5ac3ef8..0bd6e201 100644 --- a/app/views/form-designer/question-routes/new-condition.html +++ b/app/views/form-designer/question-routes/new-condition.html @@ -1,6 +1,6 @@ {% extends "layout-govuk-forms.html" %} -{% set pageTitle = 'Add a question route' %} +{% set pageTitle = 'Add a route from a question' %} {% block pageTitle %} {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms @@ -34,9 +34,52 @@

{{ pageTitle }}

- You can send people directly to the question or page you want, based on their previous answer. This means they’ll only see questions that are relevant to them. + You can set up a route so if someone selects a specific answer to a question they’ll skip forward to a later question, or the end of the form.

+ {% for page in data.pages -%} + {% set tempQuestions = { + 'name': page['long-title'] + } %} + {%- endfor %} + + {% if data.pages.length >= 2 %} +
+
+ +

+ Which question do you want to add a route from? +

+
+ {% if containsErrors -%} +

+ Error: {{ errorList[0].text }} +

+ {%- endif %} +
+ A route can only start from a question where people select one item from a list. You can only add one route from each question. +
+
+ {% for page in data.pages -%} + {% if page['type'] == 'select' and page['listSettings'].includes('oneOption') and not loop.last %} +
+ + +
+ {% endif %} + {%- endfor %} +
+
+
+ + {{ govukButton({ + text: "Continue" + }) }} + + {% else %} +

What you need to create a route

Before you can add a route you’ll need: @@ -49,8 +92,10 @@

What you need to create a route

You can only add one route from each question.

+ {% endif %} +

- Go to your questions + Back to your questions

diff --git a/app/views/form-designer/question-routes/routes-summary.html b/app/views/form-designer/question-routes/routes-summary.html new file mode 100644 index 00000000..84ea4e66 --- /dev/null +++ b/app/views/form-designer/question-routes/routes-summary.html @@ -0,0 +1,109 @@ +{% extends "layout-govuk-forms.html" %} + +{% set pageTitle = 'Question ' + (data.routeStartQuestion or 'X') + '’s routes' %} + +{% block pageTitle %} + {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms +{% endblock %} + +{% block beforeContent %} + + Back + +{% endblock %} + +{% block content %} +
+
+
+ + {% if containsErrors %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: errorList + }) }} + {% endif %} + + {{ data.formTitle or '[formTitle]' }} +

{{ pageTitle }}

+ + {% set routeStart = '' %} + {% set routeEnd = '' %} + {% for page in data.pages -%} + {% if (page.pageIndex|int + 1) == data.routeStartQuestion %} + {% set routeStart = page['long-title'] %} + {% endif %} + {% if (page.pageIndex|int + 1) == data.route1End %} + {% set routeEnd = (page.pageIndex|int + 1) + ' ' + page['long-title'] %} + {% elif data.route1End === 'cya' %} + {% set routeEnd = data.checkAnswersTitle %} + {% endif %} + {%- endfor %} + + {{ govukSummaryList({ + rows: [ + { + key: { + text: "Question " + (data.routeStartQuestion or 'X') + }, + value: { + text: routeStart or 'Not answered' + } + } + ] + }) }} + + {{ govukSummaryList({ + card: { + title: { + text: "Route 1" + }, + actions: { + items: [ + { + href: "./conditions", + text: "Edit", + visuallyHiddenText: " route 1" + } + ] + } + }, + rows: [ + { + key: { + text: "If answered as" + }, + value: { + text: data.route1Answer or 'Not answered' + } + }, + { + key: { + text: "skip the person to" + }, + value: { + text: routeEnd or 'Not answered' + } + } + ] + }) }} + +

Any other answer

+

+ People who select any other answer will continue to question 5. +

+

+ Back to your questions +

+ +
+
+
+{% endblock %} + +{% block pageScripts %} + +{% endblock %} \ No newline at end of file From a18caee7ea5b58a2f8f7a377342adbf326a34e48 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 11:28:11 +0000 Subject: [PATCH 02/61] Updated session data to match latest page data --- .../returning-session-data-defaults-a11y.js | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index 1928e1a9..41ada837 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -25,44 +25,64 @@ module.exports = { payments: 'no', pages: [ { + pageIndex: '0', + type: 'text', 'long-title': 'What type of animal is your pet?', - 'short-title': 'Animal type', 'hint-text': 'For example a bird, cat, dog.', - type: 'text', - pageIndex: '0' + 'additional-guidance': 'No', + 'questionSaved': 'Yes' }, { - 'long-title': 'What is the name of your pet?', - 'short-title': 'Pet name', + pageIndex: '1', type: 'text', - pageIndex: '1' + 'long-title': 'What is the name of your pet?', + 'additional-guidance': 'No', + 'questionSaved': 'Yes' }, { + pageIndex: '2', + type: 'text', 'long-title': 'Where are you travelling to?', - 'short-title': 'Destination', 'hint-text': 'For example Lisbon, Portugal', - type: 'text', - pageIndex: '2' + 'additional-guidance': 'No', + 'questionSaved': 'Yes' }, { + pageIndex: '3', + type: 'date', 'long-title': 'What date do you travel?', - 'short-title': 'Date', 'hint-text': 'For example 27 3 2007', - type: 'date', - pageIndex: '3' + 'additional-guidance': 'No', + 'questionSaved': 'Yes' }, { + pageIndex: '4', + type: 'text', 'long-title': 'How are you travelling?', - 'short-title': 'Transport type', 'hint-text': 'For example plane, train, car.', - type: 'text', - pageIndex: '4' + 'additional-guidance': 'No', + 'questionSaved': 'Yes' }, { - 'long-title': 'How many pets do you have?', - 'short-title': 'Number of pets', + pageIndex: '5', + type: 'select', + 'long-title': "Which of these countries have you lived in?", + 'item-list': [ + "England", + "Wales" + ], + 'listSettings': [ + "oneOption" + ], + 'additional-guidance': 'No', + 'questionSaved': 'Yes' + }, + { + pageIndex: '6', type: 'number', - pageIndex: '5' + 'long-title': 'How many pets do you have?', + 'additional-guidance': 'No', + 'questionSaved': 'Yes' } ], status: 'Draft', From 9dbd5690ded9c20fb2632390fd6a54711155e299 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 11:28:35 +0000 Subject: [PATCH 03/61] Updated check your answers preview to only show the questions someone has seen --- app/views/form-designer/preview/check-answers.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/form-designer/preview/check-answers.html b/app/views/form-designer/preview/check-answers.html index 892c37c0..4adf57fb 100644 --- a/app/views/form-designer/preview/check-answers.html +++ b/app/views/form-designer/preview/check-answers.html @@ -18,7 +18,7 @@

- {% for page in data.pages -%} + {% for page in data.pagesCYA -%} {% set questionTitle = page["long-title"] or "Page " + page["pageIndex"] %} {% if page['questionOptional'] %} From b62f13d602bf0f5fe6c0862186e6b0043d455344 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 11:29:18 +0000 Subject: [PATCH 04/61] Joined up routing creation screens, with simple errors --- .../form-designer/question-routes/_routes.js | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 app/views/form-designer/question-routes/_routes.js diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js new file mode 100644 index 00000000..79a5db29 --- /dev/null +++ b/app/views/form-designer/question-routes/_routes.js @@ -0,0 +1,86 @@ +const govukPrototypeKit = require('govuk-prototype-kit') +const router = govukPrototypeKit.requests.setupRouter() + +/* CREATING A NEW QUESTION ROUTE +================================ */ + +// Create a new question route - button journeys +router.get('/form-designer/question-routes/route-start', function (req, res) { + const errors = {} + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + var routeStartQuestion = req.session.data.routeStartQuestion + + // If the no question to start the route has been selected, create an error to be displayed to the user + if (!routeStartQuestion?.length) { + errors.routeStartQuestion = { + text: 'Select the question you want your route to start from', + href: "#route-start-question" + } + } + + // Convert the errors into a list, so we can use it in the template + const errorList = Object.values(errors) + // If there are no errors, redirect the user to the next page + // otherwise, show the page again with the errors set + const containsErrors = errorList.length > 0 + if(containsErrors) { + res.render('form-designer/question-routes/new-condition', { errors, errorList, containsErrors }) + } else { + // go to add conditions to the route + res.redirect(`conditions`) + } +}) + +// Create route 1 conditions - button journeys +router.get('/form-designer/question-routes/route-conditions', function (req, res) { + const errors = {} + var { pages, routeStartQuestion, route1Answer, route1End } = req.session.data + + /* + for page in req.session.data.pages + if page.pageIndex === routeStartQuestion + page.push( + routes: { + routeAnswer: route1Answer, + routeEnd: route1End + }) + clear (routeStartQuestion, route1Answer, route1End) + */ + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + if ((parseInt(element.pageIndex, 10) + 1) == routeStartQuestion) { + element.routing = { 'answer': route1Answer, 'skipTo': route1End } + } + } + + // If the ‘is answered as’ input has not been selected, create an error to be displayed to the user + if (!route1Answer?.length) { + errors.route1Answer = { + text: 'Select the answer to base this route on', + href: "#route-1-answer" + } + } + // If the ‘skip the person’ to input has not been selected, create an error to be displayed to the user + if (!route1End?.length) { + errors.route1End = { + text: 'Select the question or page to skip to', + href: "#route-1-end" + } + } + + // Convert the errors into a list, so we can use it in the template + const errorList = Object.values(errors) + // If there are no errors, redirect the user to the next page + // otherwise, show the page again with the errors set + const containsErrors = errorList.length > 0 + if(containsErrors) { + res.render('form-designer/question-routes/conditions', { errors, errorList, containsErrors }) + } else { + // go to question X’s routes summary screen + res.redirect(`routes-summary`) + } +}) + +module.exports = router \ No newline at end of file From 9a334f808a9c410ebd4ce74fab997ecda2219e9e Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 11:29:59 +0000 Subject: [PATCH 05/61] Updated preview routing to create CYA version of pages and to use new routing functionality in previews --- app/routes.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/app/routes.js b/app/routes.js index 5761a4da..89a620f5 100644 --- a/app/routes.js +++ b/app/routes.js @@ -641,17 +641,68 @@ router.get('/form-designer/pages/:pageId/view', function (req, res) { // Routing for new-tab page previews, set to a specific page router.post('/form-designer/preview/:pageId(\\d+)', function (req, res) { + // this is used to check if the user has clicked ‘change’ link on the CYA screen - we add a URL query ‘cya=true’ var cya = req.session.data.cya - req.session.data.cya = undefined + // this clears the temporary URL query so it can be reused on another ‘change’ link + req.session.data.cya = undefined + var pageId = req.params.pageId var pageIndex = parseInt(pageId) const isLastQuestionPage = pageIndex === (req.session.data.pages.length - 1) + var pages = req.session.data.pages + var pageAnswer = req.session.data[pageIndex] + + var pagesCYA = req.session.data.pagesCYA + + if (!pagesCYA) { + pagesCYA = [] + } + + // set variable for the next page, with default + var nextPage = `${pageIndex + 1}` + // for all pages in the form + for (let index = 0; index < pages.length; index++) { + const page = pages[index]; + // get the current page + if (page.pageIndex == pageIndex) { + // if current page has routing attribute + if (page.routing) { + if (page.routing.answer != pageAnswer) { + // if the answer is being changed and doesn’t skip remove the CYA change link function to force user to go through the rest of the journey + cya = 'false' + } + if (page.routing.answer == pageAnswer) { + // override the nextPage to the one in routing + nextPage = page.routing.skipTo + } + } + // check if we are changing an answer + if (cya !== 'true') { + // check current page against pagesCYA array - if it exists don’t add it + var pageExists = 'false'; + for (let andex = 0; andex < pagesCYA.length; andex++) { + const answeredPage = pagesCYA[andex]; + if (answeredPage.pageIndex == page.pageIndex) { + pageExists = 'true' // the page exists + } + } + // ignore existing pages + if (pageExists !== 'true') { + // add this answered question to our check your answers page + pagesCYA.push(page) + } + } + } + } + // set the session data so we can use it + req.session.data.pagesCYA = pagesCYA + // if last question in form OR user clicked on change link from CYA, then go to CYA - if(isLastQuestionPage || cya === 'true') { + if(isLastQuestionPage || nextPage == 'cya' || cya === 'true') { return res.redirect('check-answers') } else { - return res.redirect(`${pageIndex + 1}`) + return res.redirect(nextPage) } }) @@ -1025,4 +1076,7 @@ router.use('/pages', require('./views/form-designer/pages/\_routes')) /* Use the routes file in product-pages for groups and members routes */ router.use('/product-pages', require('./views/product-pages/\_routes')) +/* Use the routes file in question-routes for adding routing and branching to questions */ +router.use('/question-routes', require('./views/form-designer/question-routes/\_routes')) + module.exports = router \ No newline at end of file From c377e26415a730a7cc8e886dd1b915a7c66e2a03 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 15:02:26 +0000 Subject: [PATCH 06/61] Added playback of routes to question list view --- app/views/form-designer/your-questions.html | 26 ++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/app/views/form-designer/your-questions.html b/app/views/form-designer/your-questions.html index 4792bfe4..a25fe6d8 100644 --- a/app/views/form-designer/your-questions.html +++ b/app/views/form-designer/your-questions.html @@ -83,7 +83,6 @@

{{loop.index}} @@ -122,6 +121,31 @@

+
+ Question {{ page["pageIndex"] | int + 1 }}’s routes +
+
+ If “{{ page['long-title'] }}” is answered as “{{ page.routing.answer }}” go to {{ skipPage }} +
+
+ + Edit Question {{loop.index}}. {{questionTitle}} + +
+ + {% endif %} {%- endfor %}

From ed25ae5cf7eb237a7385888c60aa293ae955a36c Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 15:02:50 +0000 Subject: [PATCH 07/61] removed unnecessary file --- .../question-routes/new-condition-BACKUP.html | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 app/views/form-designer/question-routes/new-condition-BACKUP.html diff --git a/app/views/form-designer/question-routes/new-condition-BACKUP.html b/app/views/form-designer/question-routes/new-condition-BACKUP.html deleted file mode 100644 index b5ac3ef8..00000000 --- a/app/views/form-designer/question-routes/new-condition-BACKUP.html +++ /dev/null @@ -1,66 +0,0 @@ -{% extends "layout-govuk-forms.html" %} - -{% set pageTitle = 'Add a question route' %} - -{% block pageTitle %} - {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms -{% endblock %} - -{% block beforeContent %} - {% if previousPage and ('your-questions' in previousPage) %} - - Back to your questions - - {% else %} - - Back - - {% endif %} -{% endblock %} - -{% block content %} -
-
-
- - {% if containsErrors %} - {{ govukErrorSummary({ - titleText: "There is a problem", - errorList: errorList - }) }} - {% endif %} - - {{ data.formTitle or '[formTitle]' }} -

{{ pageTitle }}

- -

- You can send people directly to the question or page you want, based on their previous answer. This means they’ll only see questions that are relevant to them. -

- -

What you need to create a route

-

- Before you can add a route you’ll need: -

-
    -
  • 2 or more questions
  • -
  • at least one question where people must select a single item from a list of options
  • -
-

- You can only add one route from each question. -

- -

- Go to your questions -

- -
-
-
-{% endblock %} - -{% block pageScripts %} - -{% endblock %} \ No newline at end of file From e74d7b28867eceaa62beb7fb479e8025a611a4fe Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 15:03:04 +0000 Subject: [PATCH 08/61] Added new skip to page for testing --- .../question-routes/question-to-skip-to.html | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 app/views/form-designer/question-routes/question-to-skip-to.html diff --git a/app/views/form-designer/question-routes/question-to-skip-to.html b/app/views/form-designer/question-routes/question-to-skip-to.html new file mode 100644 index 00000000..86c7800c --- /dev/null +++ b/app/views/form-designer/question-routes/question-to-skip-to.html @@ -0,0 +1,98 @@ +{% extends "layout-govuk-forms.html" %} + +{% set pageTitle = 'Set question or page to skip to' %} + +{% block pageTitle %} + {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms +{% endblock %} + +{% block beforeContent %} + + Back + +{% endblock %} + +{% block content %} +
+
+
+ + {% if containsErrors %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: errorList + }) }} + {% endif %} + + {{ (data.suggestedQuestion or 'X') + '’s routes: for any other answer' }} +

{{ pageTitle }}

+ + {% set routeStart = '' %} + {% for page in data.pages -%} + {% if (page.pageIndex|int + 1) == data.suggestedQuestion %} + {% set routeStart = page['long-title'] %} + {% endif %} + {%- endfor %} + + {{ govukSummaryList({ + rows: [ + { + key: { + text: "Question " + (data.suggestedQuestion or 'X') + }, + value: { + text: routeStart or 'Not answered' + } + } + ] + }) }} + +
+
+ +

+ Which question or page you want to skip to? +

+
+ {% if containsErrors -%} +

+ Error: {{ errorList[0].text }} +

+ {%- endif %} +
+ This is the next question or page that people who select any other answer will see after [question 4]. +
+
+ {% for page in data.pages -%} + {% if not loop.last %} +
+ + +
+ {% endif %} + {%- endfor %} +
+
+
+ + {{ govukButton({ + text: "Save and continue" + }) }} + +

+ Go to your questions +

+ +
+
+
+{% endblock %} + +{% block pageScripts %} + +{% endblock %} \ No newline at end of file From 005b09766d1fae455d57fe6b837f6ecf25a47759 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 15:03:39 +0000 Subject: [PATCH 09/61] Fixed issues with comparisons --- app/views/form-designer/question-routes/conditions.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/form-designer/question-routes/conditions.html b/app/views/form-designer/question-routes/conditions.html index 78044545..d3084bdf 100644 --- a/app/views/form-designer/question-routes/conditions.html +++ b/app/views/form-designer/question-routes/conditions.html @@ -33,7 +33,7 @@

{{ pageTitle }}

{% set tempAnswers = [] %} {% set tempQuestions = [] %} {% for page in data.pages -%} - {% if (page.pageIndex|int + 1) > data.routeStartQuestion + 1 %} + {% if (page.pageIndex|int + 1) > data.routeStartQuestion|int + 1 %} {% set tempQuestions = (tempQuestions.push(page), tempQuestions) %} {% endif %} {% if (page.pageIndex|int + 1) == data.routeStartQuestion %} From a3479d4acee30ccc5eef83ce9bfd72b43f01aa01 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 15:04:07 +0000 Subject: [PATCH 10/61] Updated summary screen to new content a button/link based journey --- .../question-routes/routes-summary.html | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/app/views/form-designer/question-routes/routes-summary.html b/app/views/form-designer/question-routes/routes-summary.html index 84ea4e66..b87a753e 100644 --- a/app/views/form-designer/question-routes/routes-summary.html +++ b/app/views/form-designer/question-routes/routes-summary.html @@ -15,7 +15,7 @@ {% block content %}
-
+ {% if containsErrors %} {{ govukErrorSummary({ @@ -34,7 +34,7 @@

{{ pageTitle }}

{% set routeStart = page['long-title'] %} {% endif %} {% if (page.pageIndex|int + 1) == data.route1End %} - {% set routeEnd = (page.pageIndex|int + 1) + ' ' + page['long-title'] %} + {% set routeEnd = (page.pageIndex|int + 1) + '. ' + page['long-title'] %} {% elif data.route1End === 'cya' %} {% set routeEnd = data.checkAnswersTitle %} {% endif %} @@ -88,11 +88,24 @@

{{ pageTitle }}

] }) }} -

Any other answer

+

If people select any other answer

- People who select any other answer will continue to question 5. + People who select any other answer will continue to [question 3] and through the rest of the form.

+ You can change this by adding a route from [3, ‘What are the company details?’]. +

+ + {{ govukButton({ + text: "Add a route from [question 3]", + classes: "govuk-button--secondary" + }) }} + +

+ Add a route from a different question +

+ +

Back to your questions

From b4dd3a15c4d35bfcf8131100c9591a699bcb5269 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 13 Mar 2025 15:04:19 +0000 Subject: [PATCH 11/61] New route for new screen added --- .../form-designer/question-routes/_routes.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index 79a5db29..1f4acb8c 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -83,4 +83,22 @@ router.get('/form-designer/question-routes/route-conditions', function (req, res } }) +// Create a secondary route - button journeys +router.get('/form-designer/question-routes/questions-routes', function (req, res) { + var { pages } = req.session.data + // if button pressed + // get the suggested question (based on the route 1 end) + var startQuestion = req.session.data.suggestedQuestion + req.session.data.suggestedQuestion = undefined // reset the suggestedQuestion + // add the first part of routing to the suggested question + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + if ((parseInt(element.pageIndex, 10) + 1) == startQuestion) { + element.routing = { 'noAnswer': 'true' } // add a routing element to the question + } + } + // go to add a secondary route to this question + res.redirect(`question-to-skip-to`) +}) + module.exports = router \ No newline at end of file From 2d92fc851f8778bd869685843680e0247be4b34b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:44:45 +0000 Subject: [PATCH 12/61] Updated to use nunjucks component and fixed non working data items --- .../question-routes/conditions.html | 136 ++++++++++-------- 1 file changed, 76 insertions(+), 60 deletions(-) diff --git a/app/views/form-designer/question-routes/conditions.html b/app/views/form-designer/question-routes/conditions.html index d3084bdf..d0df6071 100644 --- a/app/views/form-designer/question-routes/conditions.html +++ b/app/views/form-designer/question-routes/conditions.html @@ -25,31 +25,18 @@ {% endif %} - {{ 'Question ' + (data.routeStartQuestion or 'X') + '’s routes' }} + {{ 'Question ' + ((pageIndex + 1) or 'X') + '’s routes' }}

{{ pageTitle }}

- {% set routeStart = '' %} - {% set tempAnswers = [] %} - {% set tempQuestions = [] %} - {% for page in data.pages -%} - {% if (page.pageIndex|int + 1) > data.routeStartQuestion|int + 1 %} - {% set tempQuestions = (tempQuestions.push(page), tempQuestions) %} - {% endif %} - {% if (page.pageIndex|int + 1) == data.routeStartQuestion %} - {% set routeStart = page['long-title'] %} - {% set tempAnswers = page['item-list'] %} - {% endif %} - {%- endfor %} - {{ govukSummaryList({ rows: [ { key: { - text: "Question " + (data.routeStartQuestion or 'X') + text: "Question " + ((pageIndex + 1) or 'X') }, value: { - text: routeStart or 'Not answered' + text: pageData['long-title'] or 'Not answered' }, actions: { items: [ @@ -63,54 +50,83 @@

{{ pageTitle }}

} ] }) }} - - {% set errorMessageAnswer = '' %} - {% set errorMessageEnd = '' %} - {% for error in errorList %} - {% if '#route-1-answer' in error.href %} - {% set errorMessageAnswer = error.text %} - {% endif %} - {% if '#route-1-end' in error.href %} - {% set errorMessageEnd = error.text %} + + {# need to get an idea of which page we are trying to skip to so we will hold it in a temporary variable to use for checking if an item in the ‘select’ list has been chosen #} + {% set temp = '' %} + {% for page in data.pages -%} + {% if (page.routing.skipTo) %} + {% set temp = page.routing.skipTo %} {% endif %} {% endfor %} -
- - {% if containsErrors and errorMessageAnswer -%} -

- Error: {{ errorMessageAnswer }} -

- {%- endif %} - -
- -
- - {% if containsErrors and errorMessageEnd -%} -

- Error: {{ errorMessageEnd }} -

- {%- endif %} - -
+ {% endif %} + + {# if this object is is after the route question #} + {% if (page.pageIndex|int) > (pageIndex + 1) %} + {# add all the questions after the route question to our temporary questions list #} + {% set tempQuestions = ( + tempQuestions.push({ + value: page.pageIndex, + text: (page.pageIndex|int + 1) + '. ' + page['long-title'], + selected: true if (temp == page.pageIndex) + }), tempQuestions) + %} + {# we also need to add the CYA page to the list of options #} + {% if loop.last %} + {% set tempQuestions = ( + tempQuestions.push({ + value: 'cya', + text: data.checkAnswersTitle, + selected: true if (temp == 'cya') + }), tempQuestions) + %} + {% endif %} + {% endif %} + {%- endfor %} + + {{ govukSelect({ + id: "route-1-answer", + name: "route1Answer", + label: { + text: "is answered as", + classes: 'govuk-label--s' + }, + items: tempAnswers + }) }} + + {{ govukSelect({ + id: "route-1-end", + name: "route1End", + label: { + text: "skip the person to", + classes: 'govuk-label--s' + }, + items: tempQuestions + }) }} {{ govukButton({ text: "Save and continue" From 58323ef6cd27975e0ff4d7aec53d866611b87797 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:45:42 +0000 Subject: [PATCH 13/61] Added route for any other answer to choose different skip from question than suggested --- .../question-routes/other-answer-route.html | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 app/views/form-designer/question-routes/other-answer-route.html diff --git a/app/views/form-designer/question-routes/other-answer-route.html b/app/views/form-designer/question-routes/other-answer-route.html new file mode 100644 index 00000000..580feb70 --- /dev/null +++ b/app/views/form-designer/question-routes/other-answer-route.html @@ -0,0 +1,84 @@ +{% extends "layout-govuk-forms.html" %} + +{% set pageTitle = 'Which question do you want to add a route from?' %} +{% set pageHint = 'The person will be skipped forward after they’ve answered this question' %} + +{% block pageTitle %} + {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms +{% endblock %} + +{% block beforeContent %} + {% if previousPage and ('your-questions' in previousPage) %} + + Back to your questions + + {% else %} + + Back + + {% endif %} +{% endblock %} + +{% block content %} +
+
+ + + {% if containsErrors %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: errorList + }) }} + {% endif %} + + + {{ 'Question ' + ((pageIndex + 1) or 'X') + '’s routes: for any other answer' }} + + + {% set tempQuestions = [] %} + {% for page in data.pages -%} + {% if (page.pageIndex > (pageIndex|int)) and not loop.last %} + {% set tempQuestions = ( + tempQuestions.push({ + value: page.pageIndex, + text: (page.pageIndex|int + 1) + '. ' + page['long-title'], + checked: true if ('routing' in page) + }), tempQuestions) + %} + {% endif %} + {%- endfor %} + + {{ govukRadios({ + name: "routeQuestion", + fieldset: { + legend: { + text: pageTitle, + isPageHeading: true, + classes: "govuk-fieldset__legend--l" + } + }, + hint: { + text: pageHint + }, + items: tempQuestions + }) }} + + {{ govukButton({ + text: "Continue" + }) }} + +

+ Cancel +

+ + +
+
+{% endblock %} + +{% block pageScripts %} + +{% endblock %} \ No newline at end of file From 1879d74c25610872c63731c022e5515896a7fb59 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:46:35 +0000 Subject: [PATCH 14/61] Changed to nunjucks components. Changed data items so users can make changes --- .../question-routes/question-to-skip-to.html | 84 +++++++++++-------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/app/views/form-designer/question-routes/question-to-skip-to.html b/app/views/form-designer/question-routes/question-to-skip-to.html index 86c7800c..cf3461ba 100644 --- a/app/views/form-designer/question-routes/question-to-skip-to.html +++ b/app/views/form-designer/question-routes/question-to-skip-to.html @@ -1,6 +1,8 @@ {% extends "layout-govuk-forms.html" %} {% set pageTitle = 'Set question or page to skip to' %} +{% set pageQuestion = 'Which question or page you want to skip to?' %} +{% set pageHint = 'This is the next question or page that people who select any other answer will see after question ' + (routeIndex + 1) + '.' %} {% block pageTitle %} {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms @@ -24,12 +26,14 @@ }) }} {% endif %} - {{ (data.suggestedQuestion or 'X') + '’s routes: for any other answer' }} + + {{ 'Question ' + ((pageIndex + 1) or 'X') + '’s routes: for any other answer' }} +

{{ pageTitle }}

{% set routeStart = '' %} {% for page in data.pages -%} - {% if (page.pageIndex|int + 1) == data.suggestedQuestion %} + {% if (page.pageIndex|int) == (routeIndex) %} {% set routeStart = page['long-title'] %} {% endif %} {%- endfor %} @@ -38,7 +42,7 @@

{{ pageTitle }}

rows: [ { key: { - text: "Question " + (data.suggestedQuestion or 'X') + text: "Question " + ((routeIndex + 1) or 'X') }, value: { text: routeStart or 'Not answered' @@ -47,42 +51,56 @@

{{ pageTitle }}

] }) }} -
-
- -

- Which question or page you want to skip to? -

-
- {% if containsErrors -%} -

- Error: {{ errorList[0].text }} -

- {%- endif %} -
- This is the next question or page that people who select any other answer will see after [question 4]. -
-
- {% for page in data.pages -%} - {% if not loop.last %} -
- - -
- {% endif %} - {%- endfor %} -
-
-
+ {# need to get an idea of which page we are trying to skip to so we will hold it in a temporary variable to use for checking if an item in the ‘select’ list has been chosen #} + {% set temp = '' %} + {% for page in data.pages -%} + {% if (page.routing.thenSkipTo) %} + {% set temp = page.routing.thenSkipTo %} + {% endif %} + {% endfor %} + + {% set tempQuestions = [] %} + {% for page in data.pages -%} + {% if (page.pageIndex > (routeIndex + 1)) %} + {% set tempQuestions = ( + tempQuestions.push({ + value: page.pageIndex, + text: (page.pageIndex|int + 1) + '. ' + page['long-title'], + checked: true if (temp == page.pageIndex) + }), tempQuestions) + %} + {% endif %} + {% if loop.last %} + {% set tempQuestions = ( + tempQuestions.push({ + value: 'cya', + text: data.checkAnswersTitle, + checked: true if (temp == 'cya') + }), tempQuestions) + %} + {% endif %} + {%- endfor %} + + {{ govukRadios({ + name: "routeEnd", + fieldset: { + legend: { + text: pageQuestion, + classes: "govuk-fieldset__legend--m" + } + }, + hint: { + text: pageHint + }, + items: tempQuestions + }) }} {{ govukButton({ text: "Save and continue" }) }}

- Go to your questions + Go to your questions

From 8ab131085d9144bafbf165bd576ac19ca932e417 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:47:06 +0000 Subject: [PATCH 15/61] Changed dummy questions so it is quicker to test and develop --- .../returning-session-data-defaults-a11y.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index 41ada837..6e892bee 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -49,31 +49,31 @@ module.exports = { }, { pageIndex: '3', - type: 'date', - 'long-title': 'What date do you travel?', - 'hint-text': 'For example 27 3 2007', + type: 'select', + 'long-title': "Which of these countries have you lived in?", + 'item-list': [ + "England", + "Wales" + ], + 'listSettings': [ + "oneOption" + ], 'additional-guidance': 'No', 'questionSaved': 'Yes' }, { pageIndex: '4', - type: 'text', - 'long-title': 'How are you travelling?', - 'hint-text': 'For example plane, train, car.', + type: 'date', + 'long-title': 'What date do you travel?', + 'hint-text': 'For example 27 3 2007', 'additional-guidance': 'No', 'questionSaved': 'Yes' }, { pageIndex: '5', - type: 'select', - 'long-title': "Which of these countries have you lived in?", - 'item-list': [ - "England", - "Wales" - ], - 'listSettings': [ - "oneOption" - ], + type: 'text', + 'long-title': 'How are you travelling?', + 'hint-text': 'For example plane, train, car.', 'additional-guidance': 'No', 'questionSaved': 'Yes' }, From 4d78b4c2b79c2921b50080bb4ee10139fbecc9dd Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:48:01 +0000 Subject: [PATCH 16/61] Added new route for any other answer playback. Made it easier to use pageData instead of new session item --- .../question-routes/routes-summary.html | 159 ++++++++++++++++-- 1 file changed, 141 insertions(+), 18 deletions(-) diff --git a/app/views/form-designer/question-routes/routes-summary.html b/app/views/form-designer/question-routes/routes-summary.html index b87a753e..c535c256 100644 --- a/app/views/form-designer/question-routes/routes-summary.html +++ b/app/views/form-designer/question-routes/routes-summary.html @@ -1,9 +1,9 @@ {% extends "layout-govuk-forms.html" %} -{% set pageTitle = 'Question ' + (data.routeStartQuestion or 'X') + '’s routes' %} +{% set pageTitle = 'Question ' + ((pageIndex + 1) or 'X') + '’s routes' %} {% block pageTitle %} - {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms + {{ "Error: " if containsErrors }}{{ pageTitle }}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms {% endblock %} {% block beforeContent %} @@ -27,32 +27,43 @@ {{ data.formTitle or '[formTitle]' }}

{{ pageTitle }}

- {% set routeStart = '' %} {% set routeEnd = '' %} + {% set routeEndText = '' %} + {% set countQs = 0 %} + {# loop to get ‘Route 1’ skip to question text to display in the summary card #} {% for page in data.pages -%} - {% if (page.pageIndex|int + 1) == data.routeStartQuestion %} - {% set routeStart = page['long-title'] %} + + {# quick way for us to get if there are enough questions left that a for any other answer route would work or should be offered #} + {% if (page.pageIndex|int+1) > (pageIndex|int+1) %} + {% set countQs = countQs + 1 %} {% endif %} - {% if (page.pageIndex|int + 1) == data.route1End %} - {% set routeEnd = (page.pageIndex|int + 1) + '. ' + page['long-title'] %} - {% elif data.route1End === 'cya' %} - {% set routeEnd = data.checkAnswersTitle %} + + {# set the skip to question content to an existing question from the form #} + {% if (page.pageIndex|int + 1) == (pageData.routing.skipTo|int + 1) %} + {% set routeEndText = (page.pageIndex|int + 1) + '. ' + page['long-title'] %} + {% set routeEnd = (page.pageIndex|int + 1) %} + {# set the skip to content to be check your answers default title #} + {% elif pageData.routing.skipTo === 'cya' %} + {% set routeEndText = data.checkAnswersTitle %} + {% set routeEnd = 'cya' %} {% endif %} {%- endfor %} + {# show the question the routes are associated with #} {{ govukSummaryList({ rows: [ { key: { - text: "Question " + (data.routeStartQuestion or 'X') + text: "Question " + ((pageIndex + 1) or 'X') }, value: { - text: routeStart or 'Not answered' + text: pageData['long-title'] or 'Not answered' } } ] }) }} + {# show the ‘Route 1’ summary card #} {{ govukSummaryList({ card: { title: { @@ -74,7 +85,7 @@

{{ pageTitle }}

text: "If answered as" }, value: { - text: data.route1Answer or 'Not answered' + text: pageData.routing.answer or 'Not answered' } }, { @@ -82,31 +93,143 @@

{{ pageTitle }}

text: "skip the person to" }, value: { - text: routeEnd or 'Not answered' + text: routeEndText or 'Not answered' } } ] }) }} + {# show ‘Route for any other answer’ summary card if one has been added #} + {% if pageData.routing.secondary === 'true' %} + + {# we need a way to get the question that we want to suggest to start the for any other answer route from #} + {% set continueTo = '' %} + {% set thenAfter = '0' %} + {% set thenAfterText = '' %} + {% set skipPersonTo = '' %} + {% for page in data.pages %} + {% if page.pageIndex == (pageData.pageIndex|int + 1) %} + {% set continueTo = (page.pageIndex|int + 1) + '. ' + page['long-title'] %} + {% endif %} + {# find the secondary route in the questions list #} + {% if page.routing and (page.routing.baseQuestion == (pageData.pageIndex)) %} + {% set thenAfter = page.pageIndex|int %} + {% set thenAfterText = (page.pageIndex|int + 1) + '. ' + page['long-title'] %} + {% if page.routing.thenSkipTo == 'cya' %} + {% set skipPersonTo = data.checkAnswersTitle %} + {% else %} + {% set skipPersonTo = (page.routing.thenSkipTo|int + 1) + '. ' + page['long-title'] %} + {% endif %} + {% endif %} + {% endfor %} + + {{ govukSummaryList({ + card: { + title: { + text: "Route for any other answer" + }, + actions: { + items: [ + { + href: "delete-secondary-route", + text: "Delete", + visuallyHiddenText: " route for any other answer" + } + ] + } + }, + rows: [ + { + key: { + text: "Continue to" + }, + value: { + text: continueTo or 'Next question' + } + }, + { + key: { + text: "Then after" + }, + value: { + text: thenAfterText or 'Not answered' + }, + actions: { + items: [ + { + href: thenAfter + "/other-answer-route", + text: "Change", + visuallyHiddenText: " question to skip from" + } + ] + } + }, + { + key: { + text: "skip the person to" + }, + value: { + text: skipPersonTo or 'Not answered' + }, + actions: { + items: [ + { + href: thenAfter + "/question-to-skip-to", + text: "Change", + visuallyHiddenText: " skip the person to" + } + ] + } + } + ] + }) }} + + {{ govukButton({ + text: "Delete all routes", + classes: "govuk-button--warning" + }) }} + + {% else %} + + {# we need a way to get the question that we want to suggest to start the for any other answer route from #} + {% set suggestedQuestion = '' %} + {% set suggestedQuestionText = '' %} + {% for page in data.pages %} + {% if (routeEnd != 'cya') or (countQs >= 2) %} + {% if page.pageIndex == pageData.routing.skipTo|int - 1 %} + {% set suggestedQuestion = (page.pageIndex|int + 1) %} + {% set suggestedQuestionText = (page.pageIndex|int + 1) + ', ‘' + page['long-title'] + '’' %} + {% endif %} + {% endif %} + {% endfor %} +

If people select any other answer

- People who select any other answer will continue to [question 3] and through the rest of the form. + People who select any other answer will continue to question {{ (pageIndex + 2) or 'Y' }} and through the rest of the form.

+ {% if routeEnd != 'cya' %}

- You can change this by adding a route from [3, ‘What are the company details?’]. + You can change this by adding a route from {{ suggestedQuestionText or 'Z, ‘Example question’' }}.

+ {# if not the last question, and the previous question isn’t the last question #} + + + {{ govukButton({ - text: "Add a route from [question 3]", + text: "Add a route from question " + (suggestedQuestion|int or 'Z'), classes: "govuk-button--secondary" }) }}

- Add a route from a different question + Add a route from a different question

+ {% endif %} + + {% endif %}

- Back to your questions + Back to your questions

From 4733206e069d089ec4d2a3c9a95d08bf1037844f Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:48:40 +0000 Subject: [PATCH 17/61] Added route for any other answer to question list view. Also added some comments on code --- app/views/form-designer/your-questions.html | 76 ++++++++++++++------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/app/views/form-designer/your-questions.html b/app/views/form-designer/your-questions.html index a25fe6d8..0b1f5b66 100644 --- a/app/views/form-designer/your-questions.html +++ b/app/views/form-designer/your-questions.html @@ -82,6 +82,7 @@

@@ -121,30 +122,59 @@

+
+ Question {{ page["pageIndex"] | int + 1 }}’s routes +
+
+ If “{{ page['long-title'] }}” is answered as “{{ page.routing.answer }}” go to {{ skipPage }} +
+
+ + Edit question {{ page["pageIndex"] | int + 1 }}’s routes + +
+

{% endif %} -
-
- Question {{ page["pageIndex"] | int + 1 }}’s routes -
-
- If “{{ page['long-title'] }}” is answered as “{{ page.routing.answer }}” go to {{ skipPage }} -
-
- - Edit Question {{loop.index}}. {{questionTitle}} - -
-
+ {# finally we need to add routing not based on an answer if there is any #} + {% if page.routing.noAnswer %} + {% set skipPage = '' %} + {% if page.routing.thenSkipTo == 'cya' %} + {% set skipPage = '“' + data.checkAnswersTitle + '”' %} + {% else %} + {% for otherRoutePage in data.pages %} + {% if (otherRoutePage.pageIndex|int) == (page.routing.thenSkipTo|int) %} + {% set skipPage -%} + {{ otherRoutePage.routing.thenSkipTo|int + 1 }}, “{{ otherRoutePage['long-title'] }}” + {%- endset %} + {% endif %} + {% endfor %} + {% endif %} +
+
+ Question {{ page.routing.baseQuestion | int + 1 }}’s routes +
+
+ After {{ page.pageIndex|int + 1 }}, “{{ page['long-title'] }}” go to {{ skipPage }} +
+
+ + Edit question {{ page.routing.baseQuestion | int + 1 }}’s routes + +
+
{% endif %} {%- endfor %} From 06acc0f4879abf84a91e428c90fed8c5a91a8b96 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:49:29 +0000 Subject: [PATCH 18/61] Added routing to handle multiple routes. (lots of comments to explain code used) --- .../form-designer/question-routes/_routes.js | 263 ++++++++++++++++-- 1 file changed, 238 insertions(+), 25 deletions(-) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index 1f4acb8c..e81d7a1d 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -4,16 +4,36 @@ const router = govukPrototypeKit.requests.setupRouter() /* CREATING A NEW QUESTION ROUTE ================================ */ -// Create a new question route - button journeys -router.get('/form-designer/question-routes/route-start', function (req, res) { - const errors = {} +/* Route 1 */ + +// Render question route start +getStartQuestion = function (req, res) { var pageId = parseInt(req.params.pageId, 10) var pageIndex = pageId var pageData = req.session.data.pages[pageIndex] - var routeStartQuestion = req.session.data.routeStartQuestion + return res.render('form-designer/question-routes/new-condition', { + pageId: pageId, + pageIndex: pageIndex, + pageData: pageData + }) +} +router.get('/form-designer/question-routes/new-condition', getStartQuestion) +router.get('/form-designer/question-routes/:pageId(\\d+)/new-condition', getStartQuestion) + +// Create a new question route - button journey +// this POST also creates our ‘pageId’ to use throughout the editing and creating of routes attached to it +postStartQuestion = function (req, res) { + const errors = {} + var pageId = parseInt(req.params.pageId, 10) + var routeStartQuestion = parseInt(req.session.data.routeStartQuestion, 10) + var pageIndex = routeStartQuestion + + if (pageId) { + pageIndex = pageId + } // If the no question to start the route has been selected, create an error to be displayed to the user - if (!routeStartQuestion?.length) { + if (!routeStartQuestion) { errors.routeStartQuestion = { text: 'Select the question you want your route to start from', href: "#route-start-question" @@ -29,31 +49,62 @@ router.get('/form-designer/question-routes/route-start', function (req, res) { res.render('form-designer/question-routes/new-condition', { errors, errorList, containsErrors }) } else { // go to add conditions to the route - res.redirect(`conditions`) + res.redirect(`${pageIndex}/conditions`) } +} +router.post('/form-designer/question-routes/route-start', postStartQuestion) +router.post('/form-designer/question-routes/:pageId(\\d+)/route-start', postStartQuestion) + +// Render ‘Route 1’ answer and skip to conditions +router.get('/form-designer/question-routes/:pageId(\\d+)/conditions', function (req, res) { + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + return res.render('form-designer/question-routes/conditions', { + pageId: pageId, + pageIndex: pageIndex, + pageData: pageData + }) }) -// Create route 1 conditions - button journeys -router.get('/form-designer/question-routes/route-conditions', function (req, res) { +// Create ‘Route 1’ - button journey +postConditions = function (req, res) { const errors = {} - var { pages, routeStartQuestion, route1Answer, route1End } = req.session.data + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + var { pages, route1Answer, route1End } = req.session.data /* - for page in req.session.data.pages - if page.pageIndex === routeStartQuestion + we need to loop through our forms questions + for page in req.session.data.pages + find if the routeStart is the same as the current page loop + if page.pageIndex === routeStartQuestion + now we need to check if routing already exists on our base question + if page.routing + we just want to update the existing keys + routing.answer = route1Answer + routing.skipTo = route1End + else + we need to create a new key object for routing page.push( - routes: { + routing: { routeAnswer: route1Answer, routeEnd: route1End }) - clear (routeStartQuestion, route1Answer, route1End) + clear (routeStartQuestion, route1Answer, route1End) */ - for (let index = 0; index < pages.length; index++) { - const element = pages[index]; - if ((parseInt(element.pageIndex, 10) + 1) == routeStartQuestion) { - element.routing = { 'answer': route1Answer, 'skipTo': route1End } + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + if ((parseInt(element.pageIndex, 10)) == pageIndex) { + if (element.routing) { + element.routing.answer = route1Answer + element.routing.skipTo = route1End + } else { + element.routing = { 'answer': route1Answer, 'skipTo': route1End } + } } - } + } // If the ‘is answered as’ input has not been selected, create an error to be displayed to the user if (!route1Answer?.length) { @@ -78,27 +129,189 @@ router.get('/form-designer/question-routes/route-conditions', function (req, res if(containsErrors) { res.render('form-designer/question-routes/conditions', { errors, errorList, containsErrors }) } else { + // reset our temporary route session data + req.session.data.routeStartQuestion = undefined + req.session.data.route1Answer = undefined + req.session.data.route1End = undefined // go to question X’s routes summary screen res.redirect(`routes-summary`) } +} +router.post('/form-designer/question-routes/route-conditions', postConditions) +router.post('/form-designer/question-routes/:pageId(\\d+)/route-conditions', postConditions) + + +/* Questions routes summary screen */ + +// Render questions routes summary page +router.get('/form-designer/question-routes/:pageId(\\d+)/routes-summary', function (req, res) { + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + return res.render('form-designer/question-routes/routes-summary', { + pageId: pageId, + pageIndex: pageIndex, + pageData: pageData + }) }) -// Create a secondary route - button journeys -router.get('/form-designer/question-routes/questions-routes', function (req, res) { - var { pages } = req.session.data +// Start a ‘Route for any other answer’ - suggested question - button journey +router.post('/form-designer/question-routes/:pageId(\\d+)/questions-routes', function (req, res) { // if button pressed // get the suggested question (based on the route 1 end) - var startQuestion = req.session.data.suggestedQuestion - req.session.data.suggestedQuestion = undefined // reset the suggestedQuestion + var { pages, suggestedQuestion } = req.session.data + req.session.data.suggestedQuestion = undefined // reset the session data for suggestedQuestion // add the first part of routing to the suggested question for (let index = 0; index < pages.length; index++) { const element = pages[index]; - if ((parseInt(element.pageIndex, 10) + 1) == startQuestion) { + if ((parseInt(element.pageIndex, 10)) == suggestedQuestion) { element.routing = { 'noAnswer': 'true' } // add a routing element to the question } } // go to add a secondary route to this question - res.redirect(`question-to-skip-to`) + res.redirect(`${suggestedQuestion}/question-to-skip-to`) +}) + + +/* For any other answer route */ + +// Render ‘Route for any other answer’ start question +getRouteOtherAnswer = function (req, res) { + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + var routeId = parseInt(req.params.routeQuestion, 10) + var routeData = req.session.data.pages[routeId] + return res.render('form-designer/question-routes/other-answer-route', { + pageId: pageId, + pageIndex: pageIndex, + pageData: pageData, + routeId: routeId, + routeData: routeData + }) +} +router.get('/form-designer/question-routes/:pageId(\\d+)/other-answer-route', getRouteOtherAnswer) +router.get('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/other-answer-route', getRouteOtherAnswer) + +// Start a ‘Route for any other answer’ - custom question - button journey +postRouteOtherAnswerStart = function (req, res) { + const errors = {} + var routeId = parseInt(req.params.routeQuestion, 10) + var routeQuestion = parseInt(req.session.data.routeQuestion, 10) + var { pages } = req.session.data + + /* + we need to check if the routeId (original route question) is the same as the newly chosen one + if routeId !== routeQuestion + we then need to find the routeId page from the form + for page in req.session.data.pages + if page.pageIndex == routeId + finally we can ‘delete’ the routing key object + delete page.routing + */ + if (routeId !== routeQuestion) { + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + // add routing value with end point to the relevant question + if ((parseInt(element.pageIndex, 10)) == routeId) { + delete element.routing + } + } + } + + // If the no question to start the route has been selected, create an error to be displayed to the user + if (!routeQuestion) { + errors.routeQuestion = { + text: 'Select the question you want to add your route from', + href: "#routeQuestion" + } + } + + // Convert the errors into a list, so we can use it in the template + const errorList = Object.values(errors) + // If there are no errors, redirect the user to the next page + // otherwise, show the page again with the errors set + const containsErrors = errorList.length > 0 + if(containsErrors) { + res.render('form-designer/question-routes/other-answer-route', { errors, errorList, containsErrors }) + } else { + if(!routeId) { + // go to add conditions to the route + res.redirect(`${routeQuestion}/question-to-skip-to`) + } else { + // if we are editing an existing ‘route for any other answer’ we need to update the routeQuestion + res.redirect(`../${routeQuestion}/question-to-skip-to`) + } + } +} +router.post('/form-designer/question-routes/:pageId(\\d+)/other-answer-route-start', postRouteOtherAnswerStart) +router.post('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/other-answer-route-start', postRouteOtherAnswerStart) + +// Render ‘Route for any other answer’ end page question +router.get('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/question-to-skip-to', function (req, res) { + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + var routeQuestion = parseInt(req.params.routeQuestion, 10) + var routeIndex = routeQuestion + return res.render('form-designer/question-routes/question-to-skip-to', { + pageId: pageId, + pageIndex: pageIndex, + pageData: pageData, + routeIndex: routeIndex + }) +}) + +// Finish creating ‘Route for any other answer’ - button journey +router.post('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/secondary-skip-end', function (req, res) { + const errors = {} + var { routeEnd, pages } = req.session.data + var routeQuestion = parseInt(req.params.routeQuestion, 10) + var pageId = parseInt(req.params.pageId, 10) + + // If the no question to start the route has been selected, create an error to be displayed to the user + if (!routeEnd?.length) { + errors.routeEnd = { + text: 'Select the question you want to skip the person to', + href: "#routeEnd" + } + } + + /* + now add the routing to the correct question + for page in req.session.data.pages + if page.pageIndex == routeQuestion + page.routing = { 'skipTo': routeEnd } + + clear routeQuestion and routeEnd just before we redirect + */ + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + // add routing value with end point to the relevant question + if ((parseInt(element.pageIndex, 10)) == routeQuestion) { + element.routing = { 'baseQuestion': pageId, 'noAnswer': true, 'thenSkipTo': routeEnd } + } + // we also need to add a value to the routing value of the original question + if ((parseInt(element.pageIndex, 10)) == pageId) { + element.routing.secondary = 'true' + element.routing.secondaryQuestion = element.pageIndex + } + } + + // Convert the errors into a list, so we can use it in the template + const errorList = Object.values(errors) + // If there are no errors, redirect the user to the next page + // otherwise, show the page again with the errors set + const containsErrors = errorList.length > 0 + if(containsErrors) { + res.render('form-designer/question-routes/question-to-skip-to', { errors, errorList, containsErrors }) + } else { + // reset our temporary route session data + req.session.data.routeQuestion = undefined + req.session.data.routeEnd = undefined + // go to back to question routes summary screen + res.redirect(`../routes-summary`) + } }) module.exports = router \ No newline at end of file From b75c4b8900860fc3f7a30c07b14a93c95c6c1e28 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 13:49:52 +0000 Subject: [PATCH 19/61] Added route for any other routing to question order in preview --- app/routes.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/routes.js b/app/routes.js index 89a620f5..241678bf 100644 --- a/app/routes.js +++ b/app/routes.js @@ -661,6 +661,7 @@ router.post('/form-designer/preview/:pageId(\\d+)', function (req, res) { // set variable for the next page, with default var nextPage = `${pageIndex + 1}` + // for all pages in the form for (let index = 0; index < pages.length; index++) { const page = pages[index]; @@ -676,6 +677,10 @@ router.post('/form-designer/preview/:pageId(\\d+)', function (req, res) { // override the nextPage to the one in routing nextPage = page.routing.skipTo } + if (page.routing.thenSkipTo) { + // override the nextPage to the ‘Route for any other answer’ + nextPage = page.routing.thenSkipTo + } } // check if we are changing an answer if (cya !== 'true') { From 6f39acdc7d074b9bccff0765bf7d743414a94e92 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 14:15:32 +0000 Subject: [PATCH 20/61] Added return journey check to add a question route to see if a route exists for the question --- .../form-designer/question-routes/_routes.js | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index e81d7a1d..211a9d0f 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -23,14 +23,10 @@ router.get('/form-designer/question-routes/:pageId(\\d+)/new-condition', getStar // Create a new question route - button journey // this POST also creates our ‘pageId’ to use throughout the editing and creating of routes attached to it postStartQuestion = function (req, res) { - const errors = {} - var pageId = parseInt(req.params.pageId, 10) + const errors = {} var routeStartQuestion = parseInt(req.session.data.routeStartQuestion, 10) var pageIndex = routeStartQuestion - - if (pageId) { - pageIndex = pageId - } + var { pages } = req.session.data // If the no question to start the route has been selected, create an error to be displayed to the user if (!routeStartQuestion) { @@ -40,6 +36,25 @@ postStartQuestion = function (req, res) { } } + /* + set a temporary check variable to hold if the page exists + var yuppityYup = false + we first need to loop through the existing data.pages + for (page in data.pages) + check if the selected page already has a route + if ((page.pageIndex == pageIndex) && (page.routing)) + yuppityYup = true + */ + var yuppityYup = false + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + if ((parseInt(element.pageIndex, 10)) == pageIndex) { + if (element.routing) { + yuppityYup = true + } + } + } + // Convert the errors into a list, so we can use it in the template const errorList = Object.values(errors) // If there are no errors, redirect the user to the next page @@ -48,8 +63,14 @@ postStartQuestion = function (req, res) { if(containsErrors) { res.render('form-designer/question-routes/new-condition', { errors, errorList, containsErrors }) } else { - // go to add conditions to the route - res.redirect(`${pageIndex}/conditions`) + // if selected question already has a route we want to take the user to the question routes summary page + if (yuppityYup) { + // tkae user to question routes summary page + res.redirect(`${pageIndex}/routes-summary`) + } else { + // go to add answer and skip to conditions for the route + res.redirect(`${pageIndex}/conditions`) + } } } router.post('/form-designer/question-routes/route-start', postStartQuestion) From 2b5658086283e0c574ed104828f6d848b8a7133a Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 14:20:27 +0000 Subject: [PATCH 21/61] Changed to use nunjucks component --- .../question-routes/new-condition.html | 60 +++++++++---------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/app/views/form-designer/question-routes/new-condition.html b/app/views/form-designer/question-routes/new-condition.html index 0bd6e201..f9d401e4 100644 --- a/app/views/form-designer/question-routes/new-condition.html +++ b/app/views/form-designer/question-routes/new-condition.html @@ -1,6 +1,8 @@ {% extends "layout-govuk-forms.html" %} {% set pageTitle = 'Add a route from a question' %} +{% set pageQuestion = 'Which question do you want to add a route from?' %} +{% set pageHint = 'A route can only start from a question where people select one item from a list. You can only add one route from each question.' %} {% block pageTitle %} {{ "Error: " if containsErrors }}{{pageTitle}}: {{ data.formTitle or '[formTitle]' }} - GOV.UK Forms @@ -37,42 +39,34 @@

{{ pageTitle }}

You can set up a route so if someone selects a specific answer to a question they’ll skip forward to a later question, or the end of the form.

+ {% if data.pages.length >= 2 %} + + {% set tempQuestions = [] %} {% for page in data.pages -%} - {% set tempQuestions = { - 'name': page['long-title'] - } %} + {% if page['type'] == 'select' and page['listSettings'].includes('oneOption') and not loop.last %} + {% set tempQuestions = ( + tempQuestions.push({ + value: page.pageIndex, + text: (page.pageIndex|int + 1) + '. ' + page['long-title'], + checked: true if data.routeStartQuestion == (page.pageIndex|int + 1) + }), tempQuestions) + %} + {% endif %} {%- endfor %} - {% if data.pages.length >= 2 %} -
-
- -

- Which question do you want to add a route from? -

-
- {% if containsErrors -%} -

- Error: {{ errorList[0].text }} -

- {%- endif %} -
- A route can only start from a question where people select one item from a list. You can only add one route from each question. -
-
- {% for page in data.pages -%} - {% if page['type'] == 'select' and page['listSettings'].includes('oneOption') and not loop.last %} -
- - -
- {% endif %} - {%- endfor %} -
-
-
+ {{ govukRadios({ + name: "routeQuestion", + fieldset: { + legend: { + text: pageQuestion, + classes: "govuk-fieldset__legend--m" + } + }, + hint: { + text: pageHint + }, + items: tempQuestions + }) }} {{ govukButton({ text: "Continue" From 698dd328044c8dfe1ee60c8c2a65699156c9c5f9 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 15:34:39 +0000 Subject: [PATCH 22/61] Fixed bug to allow first question to be the start of a route --- app/views/form-designer/question-routes/_routes.js | 2 +- app/views/form-designer/question-routes/new-condition.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index 211a9d0f..f131727e 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -29,7 +29,7 @@ postStartQuestion = function (req, res) { var { pages } = req.session.data // If the no question to start the route has been selected, create an error to be displayed to the user - if (!routeStartQuestion) { + if (!routeStartQuestion && routeStartQuestion !== 0) { errors.routeStartQuestion = { text: 'Select the question you want your route to start from', href: "#route-start-question" diff --git a/app/views/form-designer/question-routes/new-condition.html b/app/views/form-designer/question-routes/new-condition.html index f9d401e4..e00f39b5 100644 --- a/app/views/form-designer/question-routes/new-condition.html +++ b/app/views/form-designer/question-routes/new-condition.html @@ -55,7 +55,7 @@

{{ pageTitle }}

{%- endfor %} {{ govukRadios({ - name: "routeQuestion", + name: "routeStartQuestion", fieldset: { legend: { text: pageQuestion, From 9d8a85d40654bf5486af4b19fb86c07696d7ae42 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 16:08:53 +0000 Subject: [PATCH 23/61] Updated packages --- package-lock.json | 1820 +++++++++++++++++++++++++++++---------------- 1 file changed, 1161 insertions(+), 659 deletions(-) diff --git a/package-lock.json b/package-lock.json index d91835b2..5866a172 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,9 +23,9 @@ "integrity": "sha512-VGk7dQhtAk9SvlsG5DPawAifRcM+aPHykH595zJomf8Upvn4DIIQfdLEDMHAr3b6d4BPpF5Cho5G5TGhyHXddg==" }, "node_modules/@govuk-prototype-kit/step-by-step": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/step-by-step/-/step-by-step-2.2.2.tgz", - "integrity": "sha512-roFCAexAFP+ip2dIUi7o4QKDLak6nKcTFnMoh9jBEpKjpO6rjoU+xkgY3w9nqTy9rRGBtvIb+LaeoEZ78sd2KA==" + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/step-by-step/-/step-by-step-2.2.3.tgz", + "integrity": "sha512-/UTle5BrANiWlcrgaaJgiOp61qQdKPU4VUuToQH63u10E+G/NK78x370NuxA78lO/NvXAh4gndt6SQdpy7r2+g==" }, "node_modules/@lfdebrux/nunjucks-markdown": { "version": "0.0.1", @@ -67,10 +67,292 @@ "node": ">= 8" } }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "node_modules/@types/concat-stream": { "version": "1.6.1", @@ -80,11 +362,6 @@ "@types/node": "*" } }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, "node_modules/@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", @@ -102,28 +379,23 @@ } }, "node_modules/@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/@types/qs": { - "version": "6.9.10", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", - "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==" + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==" }, "node_modules/a-sync-waterfall": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -244,32 +516,19 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, - "node_modules/axios/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -277,9 +536,9 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/bare-events": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", - "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", "optional": true }, "node_modules/base64-js": { @@ -315,11 +574,14 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { @@ -515,16 +777,25 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -860,22 +1131,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/del": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", @@ -922,6 +1177,18 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/dev-ip": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", @@ -945,9 +1212,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "engines": { "node": ">=12" }, @@ -955,6 +1222,19 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/easy-extender": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", @@ -996,19 +1276,18 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } }, "node_modules/engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "dependencies": { - "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", @@ -1024,9 +1303,9 @@ } }, "node_modules/engine.io-client": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", - "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", @@ -1057,9 +1336,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "engines": { "node": ">=10.0.0" } @@ -1086,12 +1365,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "engines": { "node": ">= 0.4" } @@ -1104,10 +1380,35 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -1139,9 +1440,9 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -1162,7 +1463,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -1177,6 +1478,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express-session": { @@ -1210,14 +1515,6 @@ "node": ">= 0.6" } }, - "node_modules/express/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/express/node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -1290,24 +1587,24 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dependencies": { "reusify": "^1.0.4" } @@ -1354,6 +1651,14 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/finalhandler/node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1374,9 +1679,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -1393,16 +1698,17 @@ } }, "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" } }, "node_modules/forwarded": { @@ -1422,9 +1728,9 @@ } }, "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1469,15 +1775,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1494,10 +1805,23 @@ "node": ">=4" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1544,20 +1868,20 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/govuk-frontend": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.2.0.tgz", - "integrity": "sha512-beD3wztHpkKz6JUpPwnwop1ejb4rTFMPLCutKLCIDmUS4BPpW59ggVUfctsRqHd2Zjw9wxljdRdeIJ8AZFyyTw==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.9.0.tgz", + "integrity": "sha512-8NzmyoDtRFYyHs413DfNPR8Zo6qw6Q02Mruxml/Yfy+EueaOI/JZ4gVM8d0pqzJmTiMcJuHhvxqYEgBRmqeoyA==", "engines": { "node": ">= 4.2.0" } @@ -1586,9 +1910,9 @@ } }, "node_modules/govuk-prototype-kit": { - "version": "13.16.1", - "resolved": "https://registry.npmjs.org/govuk-prototype-kit/-/govuk-prototype-kit-13.16.1.tgz", - "integrity": "sha512-mwqtDMM4we0GCk1HGmFZ0FEtJAncvdDJQHD6To9nK3xnwJ5J1qLhs4iR/pi4hbJlImYsyQK6u+LnMOTRHNAA8w==", + "version": "13.16.2", + "resolved": "https://registry.npmjs.org/govuk-prototype-kit/-/govuk-prototype-kit-13.16.2.tgz", + "integrity": "sha512-pl7fjA66d7hluIembKY8tLdO6HKGhfd9YWZs+KBTmzd4IOLNIeBaS28uF6/NwKxLrPYkA+nDBalOXtKEKkD71A==", "dependencies": { "ansi-colors": "^4.1.3", "body-parser": "^1.20.2", @@ -1614,8 +1938,7 @@ "sync-request": "^6.1.0", "tar-stream": "^3.1.7", "universal-analytics": "^0.5.3", - "uuid": "^9.0.1", - "zlib": "^1.0.5" + "uuid": "^9.0.1" }, "bin": { "govuk-prototype-kit": "bin/cli" @@ -1624,6 +1947,14 @@ "node": "^16.x || ^18.x || >= 20.x" } }, + "node_modules/govuk-prototype-kit/node_modules/govuk-frontend": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.2.0.tgz", + "integrity": "sha512-beD3wztHpkKz6JUpPwnwop1ejb4rTFMPLCutKLCIDmUS4BPpW59ggVUfctsRqHd2Zjw9wxljdRdeIJ8AZFyyTw==", + "engines": { + "node": ">= 4.2.0" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1637,21 +1968,10 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "engines": { "node": ">= 0.4" }, @@ -1659,10 +1979,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { "node": ">= 0.4" }, @@ -1682,9 +2005,9 @@ } }, "node_modules/highlight.js": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", - "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", "engines": { "node": ">=12.0.0" } @@ -1775,9 +2098,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "engines": { "node": ">= 4" } @@ -1807,6 +2130,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2083,17 +2407,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", @@ -2105,6 +2418,14 @@ "node": ">= 12" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2221,10 +2542,16 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "optional": true + }, "node_modules/nodemon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", - "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", @@ -2249,11 +2576,11 @@ } }, "node_modules/nodemon/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2273,9 +2600,9 @@ } }, "node_modules/nodemon/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/nodemon/node_modules/supports-color": { "version": "5.5.0", @@ -2288,20 +2615,6 @@ "node": ">=4" } }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2311,12 +2624,12 @@ } }, "node_modules/notifications-node-client": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/notifications-node-client/-/notifications-node-client-8.0.0.tgz", - "integrity": "sha512-65BxorFYVFOpJ9c2lud/4Ju+Bfn3L/vkih+FuzMhBw1wcOPjwgu4doVH6xO91fHYiAi/0uIx0Mc+NorXeANMHw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/notifications-node-client/-/notifications-node-client-8.2.1.tgz", + "integrity": "sha512-wyZh/NbjN8S2uQX18utYtCyC726BBaGeTc4HeUpdhZv5sYKuaQY94N31v9syh8SzVgehyMzW37y08EePmi+k3Q==", "dependencies": { - "axios": "^1.6.1", - "jsonwebtoken": "^9.0.0" + "axios": "^1.7.2", + "jsonwebtoken": "^9.0.2" }, "engines": { "node": ">=14.17.3", @@ -2356,9 +2669,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "engines": { "node": ">= 0.4" }, @@ -2492,9 +2805,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "node_modules/path-type": { "version": "4.0.0", @@ -2596,11 +2909,6 @@ } ] }, - "node_modules/queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" - }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -2701,9 +3009,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2713,6 +3021,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dependencies": { "glob": "^7.1.3" }, @@ -2759,9 +3068,9 @@ "integrity": "sha512-CiaiuN6gapkdl+cZUr67W6I8jquN4lkak3vtIsIWCl4XIPP8ffsoyN6/+PuGXnQy8Cu8W2y9Xxh31Rq4M6wUug==" }, "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dependencies": { "tslib": "^2.1.0" } @@ -2791,12 +3100,12 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { - "version": "1.72.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.72.0.tgz", - "integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==", + "version": "1.86.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", + "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", + "chokidar": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -2804,20 +3113,46 @@ }, "engines": { "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/sass/node_modules/immutable": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", + "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==" }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" + "node_modules/sass/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "engines": { + "node": ">= 14.18.0" }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "bin": { "semver": "bin/semver.js" }, @@ -2848,14 +3183,6 @@ "node": ">= 0.8.0" } }, - "node_modules/send/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2932,14 +3259,6 @@ "node": ">= 0.8.0" } }, - "node_modules/serve-static/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/serve-static/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2981,22 +3300,6 @@ "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3022,14 +3325,65 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -3063,9 +3417,9 @@ } }, "node_modules/socket.io": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", - "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -3089,11 +3443,11 @@ } }, "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3105,9 +3459,9 @@ } }, "node_modules/socket.io-adapter/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/socket.io-client": { "version": "4.8.1", @@ -3157,11 +3511,11 @@ } }, "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3173,16 +3527,16 @@ } }, "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3194,14 +3548,14 @@ } }, "node_modules/socket.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/source-map-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.1.0.tgz", - "integrity": "sha512-9vC2SfsJzlej6MAaMPLu8HiBSHGdRAJ9hVFYN1ibZoNkeanmDmLUcIrj6G9DGL7XMJ54AKg/G75akXl1/izTOw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "engines": { "node": ">=0.10.0" } @@ -3235,12 +3589,12 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/streamx": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.16.1.tgz", - "integrity": "sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", "dependencies": { - "fast-fifo": "^1.1.0", - "queue-tick": "^1.0.1" + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" }, "optionalDependencies": { "bare-events": "^2.2.0" @@ -3320,6 +3674,14 @@ "streamx": "^2.15.0" } }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/then-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", @@ -3346,6 +3708,21 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" }, + "node_modules/then-request/node_modules/form-data": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz", + "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -3382,20 +3759,17 @@ } }, "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dependencies": { - "nopt": "~1.0.10" - }, + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", "bin": { "nodetouch": "bin/nodetouch.js" } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/type-fest": { "version": "0.21.3", @@ -3426,9 +3800,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "version": "1.0.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", + "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", "funding": [ { "type": "opencollective", @@ -3443,6 +3817,9 @@ "url": "https://github.com/sponsors/faisalman" } ], + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { "node": "*" } @@ -3464,9 +3841,9 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/universal-analytics": { "version": "0.5.3", @@ -3481,11 +3858,11 @@ } }, "node_modules/universal-analytics/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -3497,9 +3874,9 @@ } }, "node_modules/universal-analytics/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/universal-analytics/node_modules/uuid": { "version": "8.3.2", @@ -3634,11 +4011,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -3663,15 +4035,6 @@ "engines": { "node": ">=12" } - }, - "node_modules/zlib": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", - "integrity": "sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w==", - "hasInstallScript": true, - "engines": { - "node": ">=0.2.0" - } } }, "dependencies": { @@ -3681,9 +4044,9 @@ "integrity": "sha512-VGk7dQhtAk9SvlsG5DPawAifRcM+aPHykH595zJomf8Upvn4DIIQfdLEDMHAr3b6d4BPpF5Cho5G5TGhyHXddg==" }, "@govuk-prototype-kit/step-by-step": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/step-by-step/-/step-by-step-2.2.2.tgz", - "integrity": "sha512-roFCAexAFP+ip2dIUi7o4QKDLak6nKcTFnMoh9jBEpKjpO6rjoU+xkgY3w9nqTy9rRGBtvIb+LaeoEZ78sd2KA==" + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/step-by-step/-/step-by-step-2.2.3.tgz", + "integrity": "sha512-/UTle5BrANiWlcrgaaJgiOp61qQdKPU4VUuToQH63u10E+G/NK78x370NuxA78lO/NvXAh4gndt6SQdpy7r2+g==" }, "@lfdebrux/nunjucks-markdown": { "version": "git+ssh://git@github.com/lfdebrux/govuk-prototype-kit-nunjucks-markdown-plugin.git#df9902a173031e5272466adfb129bbdb0acf8e84", @@ -3713,10 +4076,113 @@ "fastq": "^1.6.0" } }, + "@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "optional": true, + "requires": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1", + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + } + }, + "@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "optional": true + }, + "@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "optional": true + }, + "@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "optional": true + }, + "@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "optional": true + }, + "@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "optional": true + }, + "@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "optional": true + }, + "@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "optional": true + }, + "@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "optional": true + }, + "@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "optional": true + }, + "@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "optional": true + }, + "@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "optional": true + }, + "@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "optional": true + }, + "@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "optional": true + }, "@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" }, "@types/concat-stream": { "version": "1.6.1", @@ -3726,11 +4192,6 @@ "@types/node": "*" } }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, "@types/cors": { "version": "2.8.17", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", @@ -3748,28 +4209,23 @@ } }, "@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "22.13.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", + "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", "requires": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "@types/qs": { - "version": "6.9.10", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", - "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==" + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==" }, "a-sync-waterfall": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==" }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -3857,31 +4313,19 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" - }, - "dependencies": { - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } } }, "b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==" }, "balanced-match": { "version": "1.0.2", @@ -3889,9 +4333,9 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "bare-events": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", - "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", "optional": true }, "base64-js": { @@ -3910,9 +4354,9 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==" }, "bl": { "version": "4.1.0", @@ -4073,16 +4517,22 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "requires": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" } }, "caseless": { @@ -4336,16 +4786,6 @@ "clone": "^1.0.2" } }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, "del": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", @@ -4376,6 +4816,12 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "optional": true + }, "dev-ip": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", @@ -4390,9 +4836,19 @@ } }, "dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==" + }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } }, "easy-extender": { "version": "2.3.4", @@ -4429,16 +4885,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" }, "engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz", + "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==", "requires": { - "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", @@ -4466,9 +4921,9 @@ } }, "engine.io-client": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", - "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", "requires": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", @@ -4493,27 +4948,43 @@ } }, "engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==" + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==" }, "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "requires": { - "get-intrinsic": "^1.2.4" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" }, "es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, "escape-html": { "version": "1.0.3", @@ -4536,9 +5007,9 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, "express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -4559,7 +5030,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -4578,11 +5049,6 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" }, - "encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, "finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -4669,21 +5135,21 @@ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" }, "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" } }, "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "requires": { "reusify": "^1.0.4" } @@ -4718,6 +5184,11 @@ "unpipe": "~1.0.0" }, "dependencies": { + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -4734,17 +5205,18 @@ } }, "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" } }, @@ -4759,9 +5231,9 @@ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -4790,15 +5262,20 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" } }, "get-port": { @@ -4806,6 +5283,15 @@ "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==" }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4841,17 +5327,14 @@ } }, "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, "govuk-frontend": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.2.0.tgz", - "integrity": "sha512-beD3wztHpkKz6JUpPwnwop1ejb4rTFMPLCutKLCIDmUS4BPpW59ggVUfctsRqHd2Zjw9wxljdRdeIJ8AZFyyTw==" + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.9.0.tgz", + "integrity": "sha512-8NzmyoDtRFYyHs413DfNPR8Zo6qw6Q02Mruxml/Yfy+EueaOI/JZ4gVM8d0pqzJmTiMcJuHhvxqYEgBRmqeoyA==" }, "govuk-markdown": { "version": "0.4.0", @@ -4870,9 +5353,9 @@ } }, "govuk-prototype-kit": { - "version": "13.16.1", - "resolved": "https://registry.npmjs.org/govuk-prototype-kit/-/govuk-prototype-kit-13.16.1.tgz", - "integrity": "sha512-mwqtDMM4we0GCk1HGmFZ0FEtJAncvdDJQHD6To9nK3xnwJ5J1qLhs4iR/pi4hbJlImYsyQK6u+LnMOTRHNAA8w==", + "version": "13.16.2", + "resolved": "https://registry.npmjs.org/govuk-prototype-kit/-/govuk-prototype-kit-13.16.2.tgz", + "integrity": "sha512-pl7fjA66d7hluIembKY8tLdO6HKGhfd9YWZs+KBTmzd4IOLNIeBaS28uF6/NwKxLrPYkA+nDBalOXtKEKkD71A==", "requires": { "ansi-colors": "^4.1.3", "body-parser": "^1.20.2", @@ -4898,8 +5381,14 @@ "sync-request": "^6.1.0", "tar-stream": "^3.1.7", "universal-analytics": "^0.5.3", - "uuid": "^9.0.1", - "zlib": "^1.0.5" + "uuid": "^9.0.1" + }, + "dependencies": { + "govuk-frontend": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.2.0.tgz", + "integrity": "sha512-beD3wztHpkKz6JUpPwnwop1ejb4rTFMPLCutKLCIDmUS4BPpW59ggVUfctsRqHd2Zjw9wxljdRdeIJ8AZFyyTw==" + } } }, "graceful-fs": { @@ -4912,24 +5401,19 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "has-property-descriptors": { + "has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" + }, + "has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "requires": { - "es-define-property": "^1.0.0" + "has-symbols": "^1.0.3" } }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, "hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -4939,9 +5423,9 @@ } }, "highlight.js": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", - "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==" + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==" }, "http-basic": { "version": "8.1.3", @@ -5005,9 +5489,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==" }, "ignore-by-default": { "version": "1.0.1", @@ -5255,19 +5739,16 @@ "is-unicode-supported": "^0.1.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, "marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==" }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -5348,10 +5829,16 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "optional": true + }, "nodemon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", - "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", + "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", "requires": { "chokidar": "^3.5.2", "debug": "^4", @@ -5366,11 +5853,11 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "has-flag": { @@ -5379,9 +5866,9 @@ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "supports-color": { "version": "5.5.0", @@ -5393,26 +5880,18 @@ } } }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "requires": { - "abbrev": "1" - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "notifications-node-client": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/notifications-node-client/-/notifications-node-client-8.0.0.tgz", - "integrity": "sha512-65BxorFYVFOpJ9c2lud/4Ju+Bfn3L/vkih+FuzMhBw1wcOPjwgu4doVH6xO91fHYiAi/0uIx0Mc+NorXeANMHw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/notifications-node-client/-/notifications-node-client-8.2.1.tgz", + "integrity": "sha512-wyZh/NbjN8S2uQX18utYtCyC726BBaGeTc4HeUpdhZv5sYKuaQY94N31v9syh8SzVgehyMzW37y08EePmi+k3Q==", "requires": { - "axios": "^1.6.1", - "jsonwebtoken": "^9.0.0" + "axios": "^1.7.2", + "jsonwebtoken": "^9.0.2" } }, "nunjucks": { @@ -5431,9 +5910,9 @@ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==" }, "on-finished": { "version": "2.4.1", @@ -5522,9 +6001,9 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "path-type": { "version": "4.0.0", @@ -5590,11 +6069,6 @@ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, - "queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" - }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -5668,9 +6142,9 @@ } }, "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==" }, "rimraf": { "version": "3.0.2", @@ -5699,9 +6173,9 @@ "integrity": "sha512-CiaiuN6gapkdl+cZUr67W6I8jquN4lkak3vtIsIWCl4XIPP8ffsoyN6/+PuGXnQy8Cu8W2y9Xxh31Rq4M6wUug==" }, "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "requires": { "tslib": "^2.1.0" } @@ -5717,29 +6191,40 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass": { - "version": "1.72.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.72.0.tgz", - "integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==", + "version": "1.86.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz", + "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==", "requires": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", + "@parcel/watcher": "^2.4.1", + "chokidar": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "dependencies": { + "chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "requires": { + "readdirp": "^4.0.1" + } + }, "immutable": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", + "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==" + }, + "readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==" } } }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==" }, "send": { "version": "0.19.1", @@ -5761,11 +6246,6 @@ "statuses": "2.0.1" }, "dependencies": { - "encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5831,11 +6311,6 @@ "send": "0.19.0" }, "dependencies": { - "encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5875,19 +6350,6 @@ "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - } - }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -5907,14 +6369,47 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "requires": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" } }, "signal-exit": { @@ -5936,9 +6431,9 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "socket.io": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", - "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -5950,17 +6445,17 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -5974,17 +6469,17 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -6024,24 +6519,24 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, "source-map-js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.1.0.tgz", - "integrity": "sha512-9vC2SfsJzlej6MAaMPLu8HiBSHGdRAJ9hVFYN1ibZoNkeanmDmLUcIrj6G9DGL7XMJ54AKg/G75akXl1/izTOw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, "statuses": { "version": "2.0.1", @@ -6065,13 +6560,13 @@ } }, "streamx": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.16.1.tgz", - "integrity": "sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==", + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", "requires": { "bare-events": "^2.2.0", - "fast-fifo": "^1.1.0", - "queue-tick": "^1.0.1" + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" } }, "string_decoder": { @@ -6136,6 +6631,14 @@ "streamx": "^2.15.0" } }, + "text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "requires": { + "b4a": "^1.6.4" + } + }, "then-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", @@ -6158,6 +6661,18 @@ "version": "8.10.66", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" + }, + "form-data": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz", + "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + } } } }, @@ -6188,17 +6703,14 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "requires": { - "nopt": "~1.0.10" - } + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==" }, "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "type-fest": { "version": "0.21.3", @@ -6220,9 +6732,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==" + "version": "1.0.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", + "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==" }, "uid-safe": { "version": "2.1.5", @@ -6238,9 +6750,9 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "universal-analytics": { "version": "0.5.3", @@ -6252,17 +6764,17 @@ }, "dependencies": { "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "uuid": { "version": "8.3.2", @@ -6348,11 +6860,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -6371,11 +6878,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" - }, - "zlib": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zlib/-/zlib-1.0.5.tgz", - "integrity": "sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w==" } } } From 31bb27498380a387a6922a5ad62dd4062483e769 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 16:15:27 +0000 Subject: [PATCH 24/61] Updates --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5866a172..f06bd426 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "govuk-prototype-kit", "dependencies": { - "@govuk-prototype-kit/common-templates": "1.2.2", + "@govuk-prototype-kit/common-templates": "2.0.1", "@govuk-prototype-kit/step-by-step": "^2.1.0", "@lfdebrux/nunjucks-markdown": "github:lfdebrux/govuk-prototype-kit-nunjucks-markdown-plugin#v0.0.3", "govuk-frontend": "^5.2.0", @@ -18,9 +18,9 @@ } }, "node_modules/@govuk-prototype-kit/common-templates": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/common-templates/-/common-templates-1.2.2.tgz", - "integrity": "sha512-VGk7dQhtAk9SvlsG5DPawAifRcM+aPHykH595zJomf8Upvn4DIIQfdLEDMHAr3b6d4BPpF5Cho5G5TGhyHXddg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/common-templates/-/common-templates-2.0.1.tgz", + "integrity": "sha512-9vIluzHin4yJhMKt97P6bEW7DzCmHtBZZnCWCkFnjCJoI4HwaBwPCu1CzKhMsSoCKCE2DJsGbTu13iuHzCxVJQ==" }, "node_modules/@govuk-prototype-kit/step-by-step": { "version": "2.2.3", @@ -4039,9 +4039,9 @@ }, "dependencies": { "@govuk-prototype-kit/common-templates": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/common-templates/-/common-templates-1.2.2.tgz", - "integrity": "sha512-VGk7dQhtAk9SvlsG5DPawAifRcM+aPHykH595zJomf8Upvn4DIIQfdLEDMHAr3b6d4BPpF5Cho5G5TGhyHXddg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@govuk-prototype-kit/common-templates/-/common-templates-2.0.1.tgz", + "integrity": "sha512-9vIluzHin4yJhMKt97P6bEW7DzCmHtBZZnCWCkFnjCJoI4HwaBwPCu1CzKhMsSoCKCE2DJsGbTu13iuHzCxVJQ==" }, "@govuk-prototype-kit/step-by-step": { "version": "2.2.3", diff --git a/package.json b/package.json index 294c34e9..d6d571d4 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ }, "name": "govuk-prototype-kit", "dependencies": { - "@govuk-prototype-kit/common-templates": "1.2.2", + "@govuk-prototype-kit/common-templates": "2.0.1", "@govuk-prototype-kit/step-by-step": "^2.1.0", "@lfdebrux/nunjucks-markdown": "github:lfdebrux/govuk-prototype-kit-nunjucks-markdown-plugin#v0.0.3", "govuk-frontend": "^5.2.0", From ac9783a9b437e8c728c731e560bd383715683619 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 18 Mar 2025 16:55:52 +0000 Subject: [PATCH 25/61] Fixed showing the wrong uqestion numbers and titles --- app/views/form-designer/question-routes/_routes.js | 4 ++-- .../form-designer/question-routes/routes-summary.html | 8 +++++++- app/views/form-designer/your-questions.html | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index f131727e..b5131de2 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -24,8 +24,8 @@ router.get('/form-designer/question-routes/:pageId(\\d+)/new-condition', getStar // this POST also creates our ‘pageId’ to use throughout the editing and creating of routes attached to it postStartQuestion = function (req, res) { const errors = {} - var routeStartQuestion = parseInt(req.session.data.routeStartQuestion, 10) - var pageIndex = routeStartQuestion + var routeStartQuestion = req.session.data.routeStartQuestion + var pageIndex = parseInt(routeStartQuestion, 10) var { pages } = req.session.data // If the no question to start the route has been selected, create an error to be displayed to the user diff --git a/app/views/form-designer/question-routes/routes-summary.html b/app/views/form-designer/question-routes/routes-summary.html index c535c256..e9571b09 100644 --- a/app/views/form-designer/question-routes/routes-summary.html +++ b/app/views/form-designer/question-routes/routes-summary.html @@ -118,7 +118,13 @@

{{ pageTitle }}

{% if page.routing.thenSkipTo == 'cya' %} {% set skipPersonTo = data.checkAnswersTitle %} {% else %} - {% set skipPersonTo = (page.routing.thenSkipTo|int + 1) + '. ' + page['long-title'] %} + {% for otherRoutePage in data.pages %} + {% if (otherRoutePage.pageIndex|int) == (page.routing.thenSkipTo|int) %} + {% set skipPersonTo -%} + {{ otherRoutePage.pageIndex|int + 1 }}, “{{ otherRoutePage['long-title'] }}” + {%- endset %} + {% endif %} + {% endfor %} {% endif %} {% endif %} {% endfor %} diff --git a/app/views/form-designer/your-questions.html b/app/views/form-designer/your-questions.html index 0b1f5b66..a2b1b560 100644 --- a/app/views/form-designer/your-questions.html +++ b/app/views/form-designer/your-questions.html @@ -157,7 +157,7 @@

{{ pageTitle }}

{% for otherRoutePage in data.pages %} {% if (otherRoutePage.pageIndex|int) == (page.routing.thenSkipTo|int) %} {% set skipPersonTo -%} - {{ otherRoutePage.pageIndex|int + 1 }}, “{{ otherRoutePage['long-title'] }}” + {{ otherRoutePage.pageIndex|int + 1 }}. “{{ otherRoutePage['long-title'] }}” {%- endset %} {% endif %} {% endfor %} From 04e00707ed7f651211597c1c05df37fbc46fd4ff Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:42:57 +0000 Subject: [PATCH 27/61] Hide save and preview button for testing --- app/views/form-designer/pages/check-question.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/form-designer/pages/check-question.html b/app/views/form-designer/pages/check-question.html index aaa04d68..9598cd55 100644 --- a/app/views/form-designer/pages/check-question.html +++ b/app/views/form-designer/pages/check-question.html @@ -299,12 +299,12 @@

Guidance

value: "update" }) }} {# Grey CTA - Save and preview question #} - {{ govukButton({ + {# {{ govukButton({ classes: "govuk-button--secondary", text: "Save and preview", name: "action", value: "savePreview" - }) }} + }) }} #}
{% if editingExistingQuestion === 'Yes' %} From 3d5072d7cdd70134e43a04ae02b1249f979e43bf Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:43:24 +0000 Subject: [PATCH 28/61] Added new are you sure question page when deleting route 1 or all routes --- .../question-routes/are-you-sure.html | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 app/views/form-designer/question-routes/are-you-sure.html diff --git a/app/views/form-designer/question-routes/are-you-sure.html b/app/views/form-designer/question-routes/are-you-sure.html new file mode 100644 index 00000000..6b008e8e --- /dev/null +++ b/app/views/form-designer/question-routes/are-you-sure.html @@ -0,0 +1,69 @@ +{% extends "layout-govuk-forms.html" %} + +{% if data.action == 'deleteRoute1' %} +{% set pageTitle = 'Are you sure you want to delete route 1?' %} +{% else %} +{% set pageTitle = 'Are you sure you want to delete all question ' + ((pageIndex + 1) or 'X') + '’s routes?' %} +{% endif %} + +{% block pageTitle %} + {{ "Error: " if containsErrors }}{{pageTitle}} - GOV.UK Forms +{% endblock %} + +{% block beforeContent %} + Back question {{ ((pageIndex + 1) or 'X') }}’s routes +{% endblock %} + +{% block content %} +
+
+
+ + {% if containsErrors %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: errorList + }) }} + {% endif %} + + {% if pageData.routing.secondary and data.action == 'deleteRoute1' %} + {# only show the ‘important’ notification banner if the form creator is trying to delete ‘route 1’ #} + {{ govukNotificationBanner({ + text: "If you delete this route, the route for any other answer will also be deleted" + }) }} + {% endif %} + + + {{ 'Question ' + ((pageIndex + 1) or 'X') + '’s routes' }} + + {{ govukRadios({ + name: "deleteRoute", + fieldset: { + legend: { + text: pageTitle, + isPageHeading: true, + classes: "govuk-fieldset__legend--l" + } + }, + items: [ + { + value: "Yes", + text: "Yes" + }, + { + value: "No", + text: "No" + } + ], + errorMessage: { text: errors['deleteRoute'].text } if errors['deleteRoute'].text + }) }} + + {{ govukButton({ + text: "Save and continue" + }) }} +
+
+
+ + +{% endblock %} From 985cc605e51e2dbf6975bdf4c089daf15f73db7c Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:43:36 +0000 Subject: [PATCH 29/61] Added new are you sure question page when deleting route for any other answer --- .../delete-secondary-route.html | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 app/views/form-designer/question-routes/delete-secondary-route.html diff --git a/app/views/form-designer/question-routes/delete-secondary-route.html b/app/views/form-designer/question-routes/delete-secondary-route.html new file mode 100644 index 00000000..9ef93266 --- /dev/null +++ b/app/views/form-designer/question-routes/delete-secondary-route.html @@ -0,0 +1,58 @@ +{% extends "layout-govuk-forms.html" %} + +{% set pageTitle = 'Are you sure you want to delete the route for any other answer?' %} + +{% block pageTitle %} + {{ "Error: " if containsErrors }}{{pageTitle}} - GOV.UK Forms +{% endblock %} + +{% block beforeContent %} + Back question {{ ((pageIndex + 1) or 'X') }}’s routes +{% endblock %} + +{% block content %} +
+
+
+ + {% if containsErrors %} + {{ govukErrorSummary({ + titleText: "There is a problem", + errorList: errorList + }) }} + {% endif %} + + + {{ 'Question ' + ((pageIndex + 1) or 'X') + '’s routes' }} + + {{ govukRadios({ + name: "deleteRouteOtherAnswer", + fieldset: { + legend: { + text: pageTitle, + isPageHeading: true, + classes: "govuk-fieldset__legend--l" + } + }, + items: [ + { + value: "Yes", + text: "Yes" + }, + { + value: "No", + text: "No" + } + ], + errorMessage: { text: errors['deleteRouteOtherAnswer'].text } if errors['deleteRouteOtherAnswer'].text + }) }} + + {{ govukButton({ + text: "Save and continue" + }) }} +
+
+
+ + +{% endblock %} From 9b03c119029ea98ad5f97fa095602f465d6f1e1d Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:44:00 +0000 Subject: [PATCH 30/61] Fixed missing inline error --- .../question-routes/new-condition.html | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/app/views/form-designer/question-routes/new-condition.html b/app/views/form-designer/question-routes/new-condition.html index e00f39b5..0245a9a7 100644 --- a/app/views/form-designer/question-routes/new-condition.html +++ b/app/views/form-designer/question-routes/new-condition.html @@ -55,17 +55,18 @@

{{ pageTitle }}

{%- endfor %} {{ govukRadios({ - name: "routeStartQuestion", - fieldset: { - legend: { - text: pageQuestion, - classes: "govuk-fieldset__legend--m" - } - }, - hint: { - text: pageHint - }, - items: tempQuestions + name: "routeStartQuestion", + fieldset: { + legend: { + text: pageQuestion, + classes: "govuk-fieldset__legend--m" + } + }, + hint: { + text: pageHint + }, + items: tempQuestions, + errorMessage: { text: errors['routeStartQuestion'].text } if errors['routeStartQuestion'].text }) }} {{ govukButton({ From 987a09974b1a485c9952f96ec9daecf8d9a606e7 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:45:04 +0000 Subject: [PATCH 31/61] =?UTF-8?q?Fixed=20missing=20inline=20errors.=20Hide?= =?UTF-8?q?=20=E2=80=98change=E2=80=99=20link=20if=20editing=20existing=20?= =?UTF-8?q?route=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question-routes/conditions.html | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/app/views/form-designer/question-routes/conditions.html b/app/views/form-designer/question-routes/conditions.html index d0df6071..e821df81 100644 --- a/app/views/form-designer/question-routes/conditions.html +++ b/app/views/form-designer/question-routes/conditions.html @@ -46,7 +46,7 @@

{{ pageTitle }}

visuallyHiddenText: " question" } ] - } + } if not ((pageData) and (pageData.routing.skipTo) and (pageData.routing.answer)) } ] }) }} @@ -100,8 +100,7 @@

{{ pageTitle }}

{% set tempQuestions = ( tempQuestions.push({ value: 'cya', - text: data.checkAnswersTitle, - selected: true if (temp == 'cya') + text: data.checkAnswersTitle }), tempQuestions) %} {% endif %} @@ -115,7 +114,9 @@

{{ pageTitle }}

text: "is answered as", classes: 'govuk-label--s' }, - items: tempAnswers + value: data['route1Answer'], + items: tempAnswers, + errorMessage: { text: errors['route1Answer'].text } if errors['route1Answer'].text }) }} {{ govukSelect({ @@ -125,12 +126,24 @@

{{ pageTitle }}

text: "skip the person to", classes: 'govuk-label--s' }, - items: tempQuestions + items: tempQuestions, + errorMessage: { text: errors['route1End'].text } if errors['route1End'].text }) }} +
{{ govukButton({ text: "Save and continue" }) }} +
+ + {% if (pageData) and (pageData.routing.skipTo) and (pageData.routing.answer) %} + {{ govukButton({ + text: "Delete route", + classes: "govuk-button--warning", + name: "action", + value: "deleteRoute1" + }) }} + {% endif %} From 30c9eb40911133763d8439fff8f57d630397fa84 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:45:14 +0000 Subject: [PATCH 32/61] Fixed missing inline error --- .../question-routes/other-answer-route.html | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/app/views/form-designer/question-routes/other-answer-route.html b/app/views/form-designer/question-routes/other-answer-route.html index 580feb70..47f28153 100644 --- a/app/views/form-designer/question-routes/other-answer-route.html +++ b/app/views/form-designer/question-routes/other-answer-route.html @@ -49,18 +49,19 @@ {%- endfor %} {{ govukRadios({ - name: "routeQuestion", - fieldset: { - legend: { - text: pageTitle, - isPageHeading: true, - classes: "govuk-fieldset__legend--l" - } - }, - hint: { - text: pageHint - }, - items: tempQuestions + name: "routeQuestion", + fieldset: { + legend: { + text: pageTitle, + isPageHeading: true, + classes: "govuk-fieldset__legend--l" + } + }, + hint: { + text: pageHint + }, + items: tempQuestions, + errorMessage: { text: errors['routeQuestion'].text } if errors['routeQuestion'].text }) }} {{ govukButton({ From 05279a43c5ff508c3b4ede760c2786ab214e5212 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:45:27 +0000 Subject: [PATCH 33/61] Fixed missing inline error --- .../question-routes/question-to-skip-to.html | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/app/views/form-designer/question-routes/question-to-skip-to.html b/app/views/form-designer/question-routes/question-to-skip-to.html index 37ad42ba..865d4d9a 100644 --- a/app/views/form-designer/question-routes/question-to-skip-to.html +++ b/app/views/form-designer/question-routes/question-to-skip-to.html @@ -82,17 +82,18 @@

{{ pageTitle }}

{%- endfor %} {{ govukRadios({ - name: "routeEnd", - fieldset: { - legend: { - text: pageQuestion, - classes: "govuk-fieldset__legend--m" - } - }, - hint: { - text: pageHint - }, - items: tempQuestions + name: "routeEnd", + fieldset: { + legend: { + text: pageQuestion, + classes: "govuk-fieldset__legend--m" + } + }, + hint: { + text: pageHint + }, + items: tempQuestions, + errorMessage: { text: errors['routeEnd'].text } if errors['routeEnd'].text }) }} {{ govukButton({ From 9df51a1e0b864e347701c2d07dd5318f56f831c5 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 10:45:55 +0000 Subject: [PATCH 34/61] Added action value to delete all routes button to use in routing --- app/views/form-designer/question-routes/routes-summary.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/form-designer/question-routes/routes-summary.html b/app/views/form-designer/question-routes/routes-summary.html index 6761e920..9386bcc8 100644 --- a/app/views/form-designer/question-routes/routes-summary.html +++ b/app/views/form-designer/question-routes/routes-summary.html @@ -192,7 +192,9 @@

{{ pageTitle }}

{{ govukButton({ text: "Delete all routes", - classes: "govuk-button--warning" + classes: "govuk-button--warning", + name: "action", + value: "deleteAllRoutes" }) }} {% else %} From 1d2e1ca6139b061249a0999b892ff6ffaff982c5 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 11:15:36 +0000 Subject: [PATCH 35/61] Added routing to allow route deletion --- .../form-designer/question-routes/_routes.js | 348 ++++++++++++++---- 1 file changed, 282 insertions(+), 66 deletions(-) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index b5131de2..0d2a82d6 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -32,7 +32,7 @@ postStartQuestion = function (req, res) { if (!routeStartQuestion && routeStartQuestion !== 0) { errors.routeStartQuestion = { text: 'Select the question you want your route to start from', - href: "#route-start-question" + href: "#routeStartQuestion" } } @@ -94,38 +94,7 @@ postConditions = function (req, res) { var pageId = parseInt(req.params.pageId, 10) var pageIndex = pageId var pageData = req.session.data.pages[pageIndex] - var { pages, route1Answer, route1End } = req.session.data - - /* - we need to loop through our forms questions - for page in req.session.data.pages - find if the routeStart is the same as the current page loop - if page.pageIndex === routeStartQuestion - now we need to check if routing already exists on our base question - if page.routing - we just want to update the existing keys - routing.answer = route1Answer - routing.skipTo = route1End - else - we need to create a new key object for routing - page.push( - routing: { - routeAnswer: route1Answer, - routeEnd: route1End - }) - clear (routeStartQuestion, route1Answer, route1End) - */ - for (let index = 0; index < pages.length; index++) { - const element = pages[index]; - if ((parseInt(element.pageIndex, 10)) == pageIndex) { - if (element.routing) { - element.routing.answer = route1Answer - element.routing.skipTo = route1End - } else { - element.routing = { 'answer': route1Answer, 'skipTo': route1End } - } - } - } + var { pages, route1Answer, route1End, action } = req.session.data // If the ‘is answered as’ input has not been selected, create an error to be displayed to the user if (!route1Answer?.length) { @@ -148,12 +117,55 @@ postConditions = function (req, res) { // otherwise, show the page again with the errors set const containsErrors = errorList.length > 0 if(containsErrors) { - res.render('form-designer/question-routes/conditions', { errors, errorList, containsErrors }) + res.render('form-designer/question-routes/conditions', { errors, errorList, containsErrors, pageId, pageIndex, pageData }) + } else if (action?.length && (action === 'deleteRoute1')) { + // reset our temporary route session data + req.session.data.routeStartQuestion = undefined + req.session.data.route1Answer = undefined + req.session.data.route1End = undefined + // reset action + req.session.data.action = undefined + /* + we need to redirect the user to the are you sure you want to delete this route page, if the user selects yes on that screen we can start deleting the routes + */ + res.redirect(`are-you-sure?action=` + action) } else { + /* + we need to loop through our forms questions + for page in req.session.data.pages + find if the routeStart is the same as the current page loop + if page.pageIndex === routeStartQuestion + now we need to check if routing already exists on our base question + if page.routing + we just want to update the existing keys + routing.answer = route1Answer + routing.skipTo = route1End + else + we need to create a new key object for routing + page.push( + routing: { + routeAnswer: route1Answer, + routeEnd: route1End + }) + clear (routeStartQuestion, route1Answer, route1End) + */ + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + if ((parseInt(element.pageIndex, 10)) == pageIndex) { + if (element.routing) { + element.routing.answer = route1Answer + element.routing.skipTo = route1End + } else { + element.routing = { 'answer': route1Answer, 'skipTo': route1End } + } + } + } // reset our temporary route session data req.session.data.routeStartQuestion = undefined req.session.data.route1Answer = undefined req.session.data.route1End = undefined + // reset action + req.session.data.action = undefined // go to question X’s routes summary screen res.redirect(`routes-summary`) } @@ -178,19 +190,42 @@ router.get('/form-designer/question-routes/:pageId(\\d+)/routes-summary', functi // Start a ‘Route for any other answer’ - suggested question - button journey router.post('/form-designer/question-routes/:pageId(\\d+)/questions-routes', function (req, res) { - // if button pressed - // get the suggested question (based on the route 1 end) - var { pages, suggestedQuestion } = req.session.data - req.session.data.suggestedQuestion = undefined // reset the session data for suggestedQuestion - // add the first part of routing to the suggested question - for (let index = 0; index < pages.length; index++) { - const element = pages[index]; - if ((parseInt(element.pageIndex, 10)) == suggestedQuestion) { - element.routing = { 'noAnswer': 'true' } // add a routing element to the question + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + + // get the suggested question (based on the ‘route 1’ end) + var { pages, suggestedQuestion, action } = req.session.data + + /* + check if delete button is pressed + if action && action == deleteAllRoutes + now we need to find the questions with the route 1 and route for any other answer + and then we can delete these + */ + if (action?.length && (action === 'deleteAllRoutes')) { + // reset action + req.session.data.action = undefined + /* + need to take the user to an are you sure page? + just now it will delete the routes and redirect them to ‘add and edit your questions’ page + */ + // go to form questions list + res.redirect(`are-you-sure`) + } else { + // add the first part of routing to the suggested question + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + if ((parseInt(element.pageIndex, 10)) == suggestedQuestion) { + element.routing = { 'noAnswer': 'true' } // add a routing element to the question + } } + // reset the session data for suggestedQuestion + req.session.data.suggestedQuestion = undefined + // reset action + req.session.data.action = undefined + // go to add a secondary route to this question + res.redirect(`${suggestedQuestion}/question-to-skip-to`) } - // go to add a secondary route to this question - res.redirect(`${suggestedQuestion}/question-to-skip-to`) }) @@ -254,7 +289,7 @@ postRouteOtherAnswerStart = function (req, res) { // otherwise, show the page again with the errors set const containsErrors = errorList.length > 0 if(containsErrors) { - res.render('form-designer/question-routes/other-answer-route', { errors, errorList, containsErrors }) + res.render('form-designer/question-routes/other-answer-route', { errors, errorList, containsErrors, routeId, routeQuestion }) } else { if(!routeId) { // go to add conditions to the route @@ -296,26 +331,26 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/s text: 'Select the question you want to skip the person to', href: "#routeEnd" } - } - - /* - now add the routing to the correct question - for page in req.session.data.pages - if page.pageIndex == routeQuestion - page.routing = { 'skipTo': routeEnd } + } else { + /* + now add the routing to the correct question + for page in req.session.data.pages + if page.pageIndex == routeQuestion + page.routing = { 'skipTo': routeEnd } - clear routeQuestion and routeEnd just before we redirect - */ - for (let index = 0; index < pages.length; index++) { - const element = pages[index]; - // add routing value with end point to the relevant question - if ((parseInt(element.pageIndex, 10)) == routeQuestion) { - element.routing = { 'baseQuestion': pageId, 'noAnswer': true, 'thenSkipTo': routeEnd } - } - // we also need to add a value to the routing value of the original question - if ((parseInt(element.pageIndex, 10)) == pageId) { - element.routing.secondary = 'true' - element.routing.secondaryQuestion = element.pageIndex + clear routeQuestion and routeEnd just before we redirect + */ + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + // add routing value with end point to the relevant question + if ((parseInt(element.pageIndex, 10)) == routeQuestion) { + element.routing = { 'baseQuestion': pageId, 'noAnswer': true, 'thenSkipTo': routeEnd } + } + // we also need to add a value to the routing value of the original question + if ((parseInt(element.pageIndex, 10)) == pageId) { + element.routing.secondary = 'true' + element.routing.secondaryQuestion = routeQuestion + } } } @@ -325,7 +360,7 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/s // otherwise, show the page again with the errors set const containsErrors = errorList.length > 0 if(containsErrors) { - res.render('form-designer/question-routes/question-to-skip-to', { errors, errorList, containsErrors }) + res.render('form-designer/question-routes/question-to-skip-to', { errors, errorList, containsErrors, pageId, routeQuestion }) } else { // reset our temporary route session data req.session.data.routeQuestion = undefined @@ -335,4 +370,185 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/s } }) + +/* Delete route journeys */ + +// Render are you sure you want to delete ‘Route 1’ +router.get('/form-designer/question-routes/:pageId(\\d+)/are-you-sure', function (req, res) { + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + return res.render('form-designer/question-routes/are-you-sure', { + pageId: pageId, + pageIndex: pageIndex, + pageData: pageData + }) +}) + +// Check if we should delete ‘Route 1’ - button journey +router.post('/form-designer/question-routes/:pageId(\\d+)/are-you-sure', function (req, res) { + const errors = {} + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + var { deleteRoute, pages, action } = req.session.data + + // If the ‘skip the person’ to input has not been selected, create an error to be displayed to the user + if (!deleteRoute?.length) { + if (action?.length && (action === 'deleteRoute1')) { + errors.deleteRoute = { + text: 'Select ‘Yes’ if you want to delete route 1', + href: "#deleteRoute" + } + } else { + errors.deleteRoute = { + text: 'Select ‘Yes’ to delete this question’s routes', + href: "#deleteRoute" + } + } + } + + // reset action + req.session.data.action = undefined + + // Convert the errors into a list, so we can use it in the template + const errorList = Object.values(errors) + // If there are no errors, redirect the user to the next page + // otherwise, show the page again with the errors set + const containsErrors = errorList.length > 0 + if(containsErrors) { + res.render('form-designer/question-routes/are-you-sure', { errors, errorList, containsErrors, pageId, pageIndex, pageData }) + } else if (deleteRoute?.length && (deleteRoute === 'Yes')) { + /* + go through all of the forms questions + for page in data.pages + check if question has a secondary route + if pageData.routing.secondary + get the secondary route start question + delete ‘route 1’ + we now need to find the secondary route start question + for page in data.pages + if secondary route start question + delete ‘route for any other answer’ + now we can take the user back to their list of questions + */ + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + var secondaryQuestion = '' + + // get current question + if ((parseInt(element.pageIndex, 10)) == pageIndex) { + // check if question has a secondary route + if (element.routing.secondary) { + // temporarily store the skipTo question in a variable + secondaryQuestion = element.routing.secondaryQuestion + } + // delete the routing + element.routing = undefined + } + + // if there is a secondary route we need to delete this too + if (secondaryQuestion?.length) { + // re-loop through forms questions to find the ‘route for any other answer’ start question + for (let secondaryIndex = 0; secondaryIndex < pages.length; secondaryIndex++) { + const element = pages[secondaryIndex]; + // get secondaryQuestion + if ((parseInt(element.pageIndex, 10)) == (parseInt(secondaryQuestion, 10))) { + // delete the routing + element.routing = undefined + } + } + } + } + // reset temporary page answer + req.session.data.deleteRoute = undefined + // go to question X’s routes summary screen + res.redirect(`../../your-questions`) + } else { + // reset temporary page answer + req.session.data.deleteRoute = undefined + // if we are not deleting the route take the person back to the question routes summary + res.redirect(`routes-summary`) + } +}) + +// Render are you sure you want to delete ‘Route 1’ +router.get('/form-designer/question-routes/:pageId(\\d+)/delete-secondary-route', function (req, res) { + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + return res.render('form-designer/question-routes/delete-secondary-route', { + pageId: pageId, + pageIndex: pageIndex, + pageData: pageData + }) +}) + +// Check if we should delete ‘Route for any other answer’ - button journey +router.post('/form-designer/question-routes/:pageId(\\d+)/delete-secondary-route', function (req, res) { + const errors = {} + var pageId = parseInt(req.params.pageId, 10) + var pageIndex = pageId + var pageData = req.session.data.pages[pageIndex] + var { deleteRouteOtherAnswer, pages } = req.session.data + + // If the ‘skip the person’ to input has not been selected, create an error to be displayed to the user + if (!deleteRouteOtherAnswer?.length) { + errors.deleteRouteOtherAnswer = { + text: 'Select if you want to delete route for any other answer', + href: "#deleteRouteOtherAnswer" + } + } + + // Convert the errors into a list, so we can use it in the template + const errorList = Object.values(errors) + // If there are no errors, redirect the user to the next page + // otherwise, show the page again with the errors set + const containsErrors = errorList.length > 0 + if(containsErrors) { + res.render('form-designer/question-routes/delete-secondary-route', { errors, errorList, containsErrors, pageId, pageIndex, pageData }) + } else if (deleteRouteOtherAnswer?.length && (deleteRouteOtherAnswer === 'Yes')) { + // reset temporary page answer + req.session.data.deleteRouteOtherAnswer = undefined + /* + go through all of the forms questions + for page in data.pages + find this question with route + if page.routing.baseQuestion == pageIndex + delete ‘route for any other answer’ + now we can take the user back to their list of questions + */ + for (let index = 0; index < pages.length; index++) { + const element = pages[index]; + var baseQuestion = '' + + // get current question + if (element.routing && ((parseInt(element.routing.baseQuestion, 10)) == pageIndex)) { + // temporarily store the baseQuestion question in a variable + baseQuestion = element.routing.baseQuestion + // delete the routing + element.routing = undefined + } + + // now find the ‘route 1’ start question + for (let primaryIndex = 0; primaryIndex < pages.length; primaryIndex++) { + const page = pages[primaryIndex]; + // get skipToQuestion + if (page.routing && ((parseInt(page.pageIndex, 10)) == (parseInt(baseQuestion, 10)))) { + // delete the routing + page.routing.secondary = undefined + page.routing.secondaryQuestion = undefined + } + } + } + // go to question X’s routes summary screen + res.redirect(`routes-summary`) + } else { + // reset temporary page answer + req.session.data.deleteRouteOtherAnswer = undefined + // if we are not deleting the route take the person back to the question routes summary + res.redirect(`routes-summary`) + } +}) + module.exports = router \ No newline at end of file From aa64397f9f2a243c1b16a86785255c4f04172c9e Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Tue, 25 Mar 2025 15:51:57 +0000 Subject: [PATCH 36/61] Fix inability to update page question text --- app/views/form-designer/pages/_routes.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/app/views/form-designer/pages/_routes.js b/app/views/form-designer/pages/_routes.js index 85cd15bb..f136b80a 100644 --- a/app/views/form-designer/pages/_routes.js +++ b/app/views/form-designer/pages/_routes.js @@ -414,21 +414,19 @@ router.post('/form-designer/pages/:pageId(\\d+)/edit', function (req, res) { const errors = {}; - if (!pageData['long-title']) { - const title = req.session.data['long-title'] - - // if no question text given, then throw an error - if (!title || !title.length) { - errors['long-title'] = { - text: 'Enter a question', - href: "#long-title" - } - // otherwise add question text to pageData - } else { - pageData['long-title'] = req.session.data['long-title'] + var title = req.session.data['long-title'] + + // if no question text given, then throw an error + if (!title || !title.length) { + errors['long-title'] = { + text: 'Enter a question', + href: "#long-title" } - req.session.data['long-title'] = undefined + // otherwise add question text to pageData + } else { + pageData['long-title'] = req.session.data['long-title'] } + req.session.data['long-title'] = undefined // if hint text is added, add it to pageData if (req.session.data['hint-text']) { From 61182e8b504bede6d68cba99a482c69afb9e6b7a Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Mar 2025 12:03:04 +0000 Subject: [PATCH 37/61] Added successMessage banners to creation and deletion of routing journeys --- .../form-designer/question-routes/_routes.js | 22 +++++++++++++++---- .../question-routes/routes-summary.html | 7 ++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index 0d2a82d6..a10a5735 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -166,6 +166,8 @@ postConditions = function (req, res) { req.session.data.route1End = undefined // reset action req.session.data.action = undefined + // set a success message to declare that ‘route 1’ has been saved + req.session.data.successMessage = "Route 1 has been saved" // go to question X’s routes summary screen res.redirect(`routes-summary`) } @@ -181,10 +183,16 @@ router.get('/form-designer/question-routes/:pageId(\\d+)/routes-summary', functi var pageId = parseInt(req.params.pageId, 10) var pageIndex = pageId var pageData = req.session.data.pages[pageIndex] + + // get success message and then clear session data (so it doesn’t hang around) + var successMessage = req.session.data.successMessage + req.session.data.successMessage = undefined + return res.render('form-designer/question-routes/routes-summary', { pageId: pageId, pageIndex: pageIndex, - pageData: pageData + pageData: pageData, + successMessage }) }) @@ -365,6 +373,8 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/s // reset our temporary route session data req.session.data.routeQuestion = undefined req.session.data.routeEnd = undefined + // set a success message to declare that ‘route for any other answer’ has been saved + req.session.data.successMessage = "Route for any other answer has been saved" // go to back to question routes summary screen res.redirect(`../routes-summary`) } @@ -373,7 +383,7 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/:routeQuestion(\\d+)/s /* Delete route journeys */ -// Render are you sure you want to delete ‘Route 1’ +// Render are you sure you want to delete ‘Route 1’ or all routes router.get('/form-designer/question-routes/:pageId(\\d+)/are-you-sure', function (req, res) { var pageId = parseInt(req.params.pageId, 10) var pageIndex = pageId @@ -448,12 +458,12 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/are-you-sure', functio } // if there is a secondary route we need to delete this too - if (secondaryQuestion?.length) { + if (typeof secondaryQuestion !== 'undefined') { // re-loop through forms questions to find the ‘route for any other answer’ start question for (let secondaryIndex = 0; secondaryIndex < pages.length; secondaryIndex++) { const element = pages[secondaryIndex]; // get secondaryQuestion - if ((parseInt(element.pageIndex, 10)) == (parseInt(secondaryQuestion, 10))) { + if ((parseInt(element.pageIndex, 10)) == secondaryQuestion) { // delete the routing element.routing = undefined } @@ -462,6 +472,8 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/are-you-sure', functio } // reset temporary page answer req.session.data.deleteRoute = undefined + // set a success message to declare that routes have been deleted + req.session.data.successMessage = "Question " + (pageIndex + 1) + "’s routes have been deleted" // go to question X’s routes summary screen res.redirect(`../../your-questions`) } else { @@ -541,6 +553,8 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/delete-secondary-route } } } + // set a success message to declare that ‘route for any other answer’ has been deleted + req.session.data.successMessage = "Route for any other answer has been deleted" // go to question X’s routes summary screen res.redirect(`routes-summary`) } else { diff --git a/app/views/form-designer/question-routes/routes-summary.html b/app/views/form-designer/question-routes/routes-summary.html index 9386bcc8..e0c0ad12 100644 --- a/app/views/form-designer/question-routes/routes-summary.html +++ b/app/views/form-designer/question-routes/routes-summary.html @@ -17,6 +17,13 @@
+ {% if successMessage %} + {{ govukNotificationBanner({ + type: 'success', + text: successMessage + }) }} + {% endif %} + {% if containsErrors %} {{ govukErrorSummary({ titleText: "There is a problem", From 3c11067e15be340ae859adcd31aa953c6dda772b Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Mar 2025 14:56:21 +0000 Subject: [PATCH 38/61] Added default username data attribute --- app/views/form-designer/signon/dashboard.html | 2 +- app/views/layout-govuk-forms.html | 2 +- .../product-pages/group-admin/group.html | 2 +- .../group-admin/grouplanding.html | 2 +- .../group-admin/grouplanding2.html | 2 +- .../group-admin/tasklist-activegroup.html | 808 +++++++----------- .../group-admin/tasklist-trialgroup.html | 552 +++++------- 7 files changed, 516 insertions(+), 854 deletions(-) diff --git a/app/views/form-designer/signon/dashboard.html b/app/views/form-designer/signon/dashboard.html index 085cd8a2..41f24010 100644 --- a/app/views/form-designer/signon/dashboard.html +++ b/app/views/form-designer/signon/dashboard.html @@ -61,7 +61,7 @@
  • - Firstname Lastname + {{ data.defaultUser }}
  • diff --git a/app/views/layout-govuk-forms.html b/app/views/layout-govuk-forms.html index f32d9fd6..0037a05c 100644 --- a/app/views/layout-govuk-forms.html +++ b/app/views/layout-govuk-forms.html @@ -9,7 +9,7 @@ navigationClasses: "govuk-header__navigation--end", navigation: [ { - text: "Firstname Lastname" + text: data.defaultUser }, { href: "/form-designer/signon/sign-in", diff --git a/app/views/product-pages/group-admin/group.html b/app/views/product-pages/group-admin/group.html index 3945adc1..037ad0ba 100644 --- a/app/views/product-pages/group-admin/group.html +++ b/app/views/product-pages/group-admin/group.html @@ -75,7 +75,7 @@

    Trial groups

    - {{ data.createdBy or 'Firstname Lastname' }} + {{ data.createdBy or data.defaultUser }} diff --git a/app/views/product-pages/group-admin/grouplanding.html b/app/views/product-pages/group-admin/grouplanding.html index d4182908..d6f321d7 100644 --- a/app/views/product-pages/group-admin/grouplanding.html +++ b/app/views/product-pages/group-admin/grouplanding.html @@ -64,7 +64,7 @@

    {{ data['groupName'] or 'Your test forms' }}

    {{data['formTitle']}} - Firstname Lastname + {{ data.defaultUser }} {% if data['status'] %} diff --git a/app/views/product-pages/group-admin/grouplanding2.html b/app/views/product-pages/group-admin/grouplanding2.html index de8e2e40..d92eeb61 100644 --- a/app/views/product-pages/group-admin/grouplanding2.html +++ b/app/views/product-pages/group-admin/grouplanding2.html @@ -61,7 +61,7 @@

    {{ data['groupName'] or 'Your test forms' }}

    {{data['formTitle']}} - Firstname Lastname + {{ data.defaultUser }} {% if data['status'] %} diff --git a/app/views/product-pages/group-admin/tasklist-activegroup.html b/app/views/product-pages/group-admin/tasklist-activegroup.html index 52ea31af..1836e634 100644 --- a/app/views/product-pages/group-admin/tasklist-activegroup.html +++ b/app/views/product-pages/group-admin/tasklist-activegroup.html @@ -3,604 +3,434 @@ - Create a form: [formTitle] - GOV.UK Forms - + Create a form: [formTitle] - GOV.UK Forms + - - - - - - - - - - - - + + + + + + + + + + + < script > document.body.className += ' js-enabled' + ( + 'noModule' in HTMLScriptElement.prototype + ? ' govuk-frontend-supported' + : ''); + + + Skip to main content + + - +
    - - - - - - - - - Skip to main content - - - - - +
    +
    +
    - -
    - - Back to your group + [formTitle] +

    Create a form

    +
    +
    Status
    +
    + + Draft + -
    - -
    -
    +
    +
    - +

    + You have completed 0 of 9 tasks. +

    - - [formTitle] -

    Create a form

    +

    + 1. Create your form +

    -
    -
    Status
    -
    - - Draft - +
      -
    -
    + + + + + +

    + + Optional tasks +

    - - + +
  • +

    + 2. + + Set email address for completed forms +

    +
    +
    + + Status + Cannot start yet +
    + + - - +

    + 3. + + Provide privacy and contact details +

    + +

    + 4. + + Make your form live +

    + + + - - - + + + + + -

    - 4. Make your form live -

    + - - - + - - - + - - - + - - - + - - - + - - - + - - - + + + + /* Copy the text from the node */ + navigator + .clipboard + .writeText(range); + } - + // call function from `assets/javascripts/application.js` + // removeSuccessNotification(); + - + \ No newline at end of file diff --git a/app/views/product-pages/group-admin/tasklist-trialgroup.html b/app/views/product-pages/group-admin/tasklist-trialgroup.html index 7f3da4cf..a73d4393 100644 --- a/app/views/product-pages/group-admin/tasklist-trialgroup.html +++ b/app/views/product-pages/group-admin/tasklist-trialgroup.html @@ -1,320 +1,231 @@ - - - - Create a form: [formTitle] - GOV.UK Forms - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to main content - - - - - - - - - -
    - - Back to your group - - -
    - -
    -
    - - - - - [formTitle] -

    Create a form

    - -
    -
    Status
    -
    - - Draft - - -
    -
    - - - -

    - You have completed 0 of 9 tasks. -

    - -

    - 1. Create your form -

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Not yet started + +
    + + + + Not yet started + +
    + + +

    + + Optional tasks +

    + +

    - 2. Set email address for completed forms + 2. + + Set email address for completed forms

    - -
    - Status + + Status Cannot start yet
    - - - - - - - - - - - - - - - - - -

    - 3. Provide privacy and contact details + 3. + + Provide privacy and contact details

    - - - - - - - - - - - - -

    - 4. Make your form live + 4. + + Make your form live

    - - +
    - - - - - - - - - -
    - - - - Back to your group {% else %} - Back to your forms + Back to {{ data.defaultGroup|lower or 'your forms' }} {% endif %} {% endblock %} diff --git a/app/views/form-designer/your-forms.html b/app/views/form-designer/your-forms.html index 29521289..ca5342bc 100644 --- a/app/views/form-designer/your-forms.html +++ b/app/views/form-designer/your-forms.html @@ -1,15 +1,23 @@ {% extends "layout-govuk-forms.html" %} -{% set pageTitle = 'Home' %} +{% set pageTitle = data.defaultGroup %} {% block pageTitle %} - {{pageTitle}} - {{serviceName}} + {{ pageTitle }} - {{ serviceName }} {% endblock %} {% block content %}
    -

    {{serviceName}}

    + Active group +

    {{ pageTitle }}

    + +

    + Change the name of this group +

    +

    + Edit members of this group +

    {{ govukButton({ text: "Create a form", @@ -19,10 +27,11 @@

    {{serviceName}}

    {% if data['formTitle'] %} - + + @@ -31,6 +40,9 @@

    {{serviceName}}

    +
    [departmentName] formsForms in ‘{{ pageTitle }}’
    Form nameCreated by Status
    {{data['formTitle']}} + {{ data.defaultUser }} + {% if data['status'] %} {{govukTag({ From d9acbc3311662d46c9ca476837cb58bbefc7f26d Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Mar 2025 15:19:26 +0000 Subject: [PATCH 41/61] Aligned more closely with development environment --- .../partials/status-draft-form.html | 74 +++++++++++++------ 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/app/views/form-designer/partials/status-draft-form.html b/app/views/form-designer/partials/status-draft-form.html index 55ebafa0..f2422aaf 100644 --- a/app/views/form-designer/partials/status-draft-form.html +++ b/app/views/form-designer/partials/status-draft-form.html @@ -12,7 +12,7 @@

    {{pageTitle}}

    {% if data.pages.length %} -

    +

    Preview this form @@ -20,11 +20,11 @@

    {{pageTitle}}

    {% endif %}

    - You have completed {{sections}} of 9 tasks. + You have completed {{ sections }} of 10 tasks.

    - Create your form + 1. Create your form

    {# SET STATUS OF THE FORM TITLE #} @@ -32,7 +32,7 @@

    {% set formNameStatusText = 'Completed' %} {% else %} {% set formNameStatusTag = 'govuk-tag--blue' %} - {% set formNameStatusText = 'Not yet started' %} + {% set formNameStatusText = 'Not started' %} {% endif %} {% set htmlFormTitle %} {% if data['formTitle'] %} @@ -52,7 +52,7 @@

    {% set questionStatusText = 'In progress' %} {% else %} {% set questionStatusTag = 'govuk-tag--blue' %} - {% set questionStatusText = 'Not yet started' %} + {% set questionStatusText = 'Not started' %} {% endif %} {% set htmlAddedQuestions %} {% if data.isQuestionsComplete === 'yes' %} @@ -72,7 +72,7 @@

    {% set declarationStatusText = 'In progress' %} {% else %} {% set declarationStatusTag = 'govuk-tag--blue' %} - {% set declarationStatusText = 'Not yet started' %} + {% set declarationStatusText = 'Not started' %} {% endif%} {% set htmlDeclaration %} {% if data.isDeclarationComplete === 'yes' %} @@ -89,7 +89,7 @@

    {% set whatHappensNextStatusText = 'Completed' %} {% else %} {% set whatHappensNextStatusTag = 'govuk-tag--blue' %} - {% set whatHappensNextStatusText = 'Not yet started' %} + {% set whatHappensNextStatusText = 'Not started' %} {% endif%} {% set htmlWhatHappensNext %} {% if data.confirmationNext %} @@ -147,11 +147,11 @@

    {% if data.paymentLink %} {% set paymentLinkStatusText = 'Completed' %} {% else %} - {% set paymentLinkStatusTag = 'govuk-task-list__status--cannot-start-yet' %} + {% set paymentLinkStatusTag = 'govuk-tag--grey' %} {% set paymentLinkStatusText = 'Optional' %} {% endif%} -

    Optional tasks

    +

    Optional task

    {{ govukTaskList({ idPrefix: "payment-link", items: [ @@ -161,8 +161,10 @@

    Optional tasks

    }, href: "payment/add-payment-link", status: { - text: paymentLinkStatusText, - classes: paymentLinkStatusTag if not data.paymentLink + tag: { + text: paymentLinkStatusText, + classes: paymentLinkStatusTag if not data.paymentLink + } } } ] @@ -180,7 +182,7 @@

    Optional tasks

    {% endif %} {% if not (data.formsEmail) %} {% set submissionEmailStatusTag = 'govuk-tag--blue' %} - {% set submissionEmailStatusText = 'Not yet started' %} + {% set submissionEmailStatusText = 'Not started' %} {% elif (data.formsEmail and (not data.confirmationCode)) or data.currentFormsEmail %} {% set submissionEmailStatusTag = 'govuk-tag--light-blue' %} {% set submissionEmailStatusText = 'In progress' %} @@ -213,7 +215,7 @@

    Optional tasks

    {% set confirmationCodeStatusHint = '' %} {% elif data.formsEmail and not data.confirmationCode %} {% set confirmationCodeStatusTag = 'govuk-tag--blue' %} - {% set confirmationCodeStatusText = 'Not yet started' %} + {% set confirmationCodeStatusText = 'Not started' %} {% else %} {% set confirmationCodeStatusText = 'Completed' %} {% endif%} @@ -228,7 +230,7 @@

    Optional tasks

    {% endset %}

    - Set email address for completed forms +2. Set up how you get completed forms

    {{ govukTaskList({ idPrefix: "processing-email", @@ -261,6 +263,25 @@

    ] }) }} +

    Optional task

    +{{ govukTaskList({ + idPrefix: "csv-submission", + items: [ + { + title: { + text: "Get completed forms as CSV files" + }, + href: "#", + status: { + tag: { + text: 'Optional', + classes: 'govuk-tag--grey' + } + } + } + ] +}) }} + {# SET STATUS OF PRIVACY INFORMATION #} {# Refactor this logic outside of class attribute #} @@ -268,7 +289,7 @@

    {% set privacyInformationStatusText = 'Completed' %} {% else %} {% set privacyInformationStatusTag = 'govuk-tag--blue' %} - {% set privacyInformationStatusText = 'Not yet started' %} + {% set privacyInformationStatusText = 'Not started' %} {% endif%} {% set htmlPrivacyInformation %} {% if data.privacyInformation %} @@ -286,7 +307,7 @@

    {% set supportDetailsStatusText = 'Completed' %} {% else %} {% set supportDetailsStatusTag = 'govuk-tag--blue' %} - {% set supportDetailsStatusText = 'Not yet started' %} + {% set supportDetailsStatusText = 'Not started' %} {% endif%} {% set htmlSupportDetails %} {% if data.supportDetails %} @@ -299,7 +320,7 @@

    {% endset %}

    - Provide privacy and contact details +3. Provide privacy and contact details

    {{ govukTaskList({ idPrefix: "processing-email", @@ -331,7 +352,7 @@

    {% set formVersionStatusText = 'Completed' %} {% elif sections >= 6 %} {% set formVersionStatusTag = 'govuk-tag--blue' %} - {% set formVersionStatusText = 'Not yet started' %} + {% set formVersionStatusText = 'Not started' %} {% else %} {% set formVersionStatusTag = 'govuk-task-list__status--cannot-start-yet' %} {% set formVersionStatusText = 'Cannot start yet' %} @@ -348,7 +369,7 @@

    {% endset %}

    - Make your form live +4. Make your form live

    {% if data['journey'] and data['journey'] == 'groupAdminTasks' %} @@ -370,15 +391,24 @@

    {% else %} {{ govukTaskList({ - idPrefix: "processing-email", + idPrefix: "make-live", items: [ + { + title: { + text: 'Share a preview of your draft form' + }, + href: '#', + status: { + html: 'Not started' + } + }, { title: { text: "Make your form live" }, hint: { text: formVersionStatusHint - } if sections < 6, + } if formVersionStatusHint !== '' and sections < 6, href: "make-your-form-live" if sections >= 6, status: { html: htmlFormVersion, @@ -393,7 +423,7 @@

    {{ govukButton({ text: "Delete draft form", - classes: "govuk-button--warning govuk-!-margin-top-5", + classes: "govuk-button--warning", name: "action", value: "deleteDraft" }) }} From 97386f2e3603d637c32db72d4fceb00ad53ad0ae Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Mar 2025 17:02:48 +0000 Subject: [PATCH 42/61] Updated back links to align with development --- .../form-designer/pages/check-question.html | 9 +-- .../form-designer/pages/edit-answer-type.html | 7 +- .../pages/edit-select-question.html | 52 +++++++------ .../form-designer/pages/edit-settings.html | 10 +-- app/views/form-designer/pages/edit.html | 73 +++++++++---------- app/views/form-designer/your-form.html | 2 +- 6 files changed, 70 insertions(+), 83 deletions(-) diff --git a/app/views/form-designer/pages/check-question.html b/app/views/form-designer/pages/check-question.html index 9598cd55..a5c67c8c 100644 --- a/app/views/form-designer/pages/check-question.html +++ b/app/views/form-designer/pages/check-question.html @@ -322,15 +322,12 @@

    Guidance

    {% endif %} - {# If we are not sure what the back link is going to don’t show the bottom link #} - {% if previousPageText !== 'Back' %}

    - - {{ previousPageText }} + + Back to your questions

    - {% endif %} - + diff --git a/app/views/form-designer/pages/edit-answer-type.html b/app/views/form-designer/pages/edit-answer-type.html index de8065bf..1f694af7 100644 --- a/app/views/form-designer/pages/edit-answer-type.html +++ b/app/views/form-designer/pages/edit-answer-type.html @@ -110,14 +110,11 @@ value: "editPage" }) }} - {# If we are not sure what the back link is going to don’t show the bottom link #} - {% if previousPageText !== 'Back' %}

    - - {{ previousPageText }} + + Back to your questions

    - {% endif %} diff --git a/app/views/form-designer/pages/edit-select-question.html b/app/views/form-designer/pages/edit-select-question.html index 062b6789..8213d23f 100644 --- a/app/views/form-designer/pages/edit-select-question.html +++ b/app/views/form-designer/pages/edit-select-question.html @@ -2,7 +2,7 @@ {% set pageTitle = "What's your question?" %} -{% set answerType = pageData['type']|capitalize %} +{% set answerType = pageData['type'] | capitalize %} {% if pageData['type'] === 'select' %} {% set answerType = 'Selection from a list' %} @@ -16,7 +16,8 @@ {% endif %} {% block pageTitle %} - {{ "Error: " if containsErrors }}{{ pageTitle }} - GOV.UK Forms + {{ "Error: " if containsErrors }}{{ pageTitle }} + - GOV.UK Forms {% endblock %} {% block beforeContent %} @@ -27,23 +28,23 @@ {% endblock %} {% block content %} -
    -
    - -
    - {% if containsErrors %} +
    +
    + + {% if containsErrors %} {{ govukErrorSummary({ titleText: "There is a problem", errorList: errorList }) }} - {% endif %} + {% endif %} - Question {{ pageId | int + 1 }} + Question + {{ pageId | int + 1 }} - {% set namePrefix = "pages[" + pageIndex + "]" %} + {% set namePrefix = "pages[" + pageIndex + "]" %} - - {{ govukInput({ + + {{ govukInput({ label: { text: pageTitle, classes: "govuk-label--l", @@ -58,18 +59,15 @@ errorMessage: { text: errors['long-title'].text } if errors['long-title'].text }) }} - {{ govukButton({ + {{ govukButton({ text: "Continue" }) }} - - {# If we are not sure what the back link is going to don’t show the bottom link #} - {% if previousPageText !== 'Back' %} -

    - - {{ previousPageText }} - -

    - {% endif %} + +

    + + Back to your questions + +

    @@ -77,8 +75,8 @@ {% endblock %} {% block pageScripts %} - -{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/app/views/form-designer/pages/edit-settings.html b/app/views/form-designer/pages/edit-settings.html index 029f1882..5acb9d81 100644 --- a/app/views/form-designer/pages/edit-settings.html +++ b/app/views/form-designer/pages/edit-settings.html @@ -287,16 +287,12 @@

    {{pageTitle}}

    name: "action", value: "editPage" }) }} - - {# If we are not sure what the back link is going to don’t show the bottom link #} - {% if previousPageText !== 'Back' %} +

    - - {{ previousPageText }} + + Back to your questions

    - {% endif %} -
    diff --git a/app/views/form-designer/pages/edit.html b/app/views/form-designer/pages/edit.html index 8fdde3e7..275f849b 100644 --- a/app/views/form-designer/pages/edit.html +++ b/app/views/form-designer/pages/edit.html @@ -2,7 +2,7 @@ {% set pageTitle = 'Edit question' %} -{% set answerType = pageData['type']|capitalize %} +{% set answerType = pageData['type'] | capitalize %} {% if pageData['type'] === 'personName' %} {% set questionHint = data.personNameQuestionHint %} {% set hintHint = data.personNameHintHint %} @@ -54,7 +54,8 @@ {% endif %} {% block pageTitle %} - {{ "Error: " if containsErrors }}{{ pageTitle }} - GOV.UK Forms + {{ "Error: " if containsErrors }}{{ pageTitle }} + - GOV.UK Forms {% endblock %} {% block beforeContent %} @@ -68,22 +69,23 @@
    -
    + - {% if containsErrors %} - {{ govukErrorSummary({ + {% if containsErrors %} + {{ govukErrorSummary({ titleText: "There is a problem", errorList: errorList }) }} - {% endif %} + {% endif %} - Question {{ pageId | int + 1 }} -

    {{pageTitle}}

    + Question + {{ pageId | int + 1 }} +

    {{pageTitle}}

    - {% set namePrefix = "pages[" + pageIndex + "]" %} + {% set namePrefix = "pages[" + pageIndex + "]" %} - - {{ govukInput({ + + {{ govukInput({ label: { text: "Question text", classes: "govuk-label--m" @@ -97,10 +99,10 @@

    {{pageTitle}}

    errorMessage: { text: errors['long-title'].text } if errors['long-title'].text }) }} -
    +
    - - {{ govukTextarea({ + + {{ govukTextarea({ label: { text: "Hint text (optional)", classes: "govuk-label--m" @@ -113,10 +115,10 @@

    {{pageTitle}}

    value: pageData['hint-text'] }) }} -
    +
    - - {{ govukRadios({ + + {{ govukRadios({ classes: "govuk-radios--inline", name: "additional-guidance", fieldset: { @@ -143,11 +145,11 @@

    {{pageTitle}}

    errorMessage: { text: errors['additional-guidance'].text } if errors['additional-guidance'].text }) }} - - {% if pageData['type'] != 'select' %} -
    + + {% if pageData['type'] != 'select' %} +
    - {{ govukCheckboxes({ + {{ govukCheckboxes({ idPrefix: "questionOptional", name: "questionOptional", fieldset: { @@ -170,22 +172,19 @@

    {{pageTitle}}

    } ] }) }} - {% endif %} + {% endif %} - {{ govukButton({ + {{ govukButton({ text: "Continue", name: "action", value: "editPage" }) }} - - {# If we are not sure what the back link is going to don’t show the bottom link #} - {% if previousPageText !== 'Back' %} -

    - - {{ previousPageText }} - -

    - {% endif %} + +

    + + Back to your questions + +

    @@ -193,8 +192,8 @@

    {{pageTitle}}

    {% endblock %} {% block pageScripts %} - -{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/app/views/form-designer/your-form.html b/app/views/form-designer/your-form.html index c821f243..b020f136 100644 --- a/app/views/form-designer/your-form.html +++ b/app/views/form-designer/your-form.html @@ -12,7 +12,7 @@ {% elif data['journey'] and data['journey'] == 'orgAdminTasks' %} Back to your group {% else %} - Back to {{ data.defaultGroup|lower or 'your forms' }} + Back to {{ data.defaultGroup or 'your forms' }} {% endif %} {% endblock %} From 8cc7f104adb28ef203001b6d059921a6bdc4d842 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Mar 2025 17:03:24 +0000 Subject: [PATCH 43/61] =?UTF-8?q?Reformatted=20default=20session=20data,?= =?UTF-8?q?=20removing=20duplicate=20items=20that=20aren=E2=80=99t=20neede?= =?UTF-8?q?d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../returning-session-data-defaults-a11y.js | 21 +++++---- app/data/returning-session-data-defaults.js | 19 ++++---- app/data/session-data-defaults.js | 45 ++++++++++++++++--- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index 0549be3f..1772b06e 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -18,11 +18,14 @@ Example usage: */ module.exports = { - highestPageId: 6, - action: 'gogogo', - publish: 'GOV.UK', - authentication: 'email', + /* Dummy form settings */ + formTitle: 'Tell us about a complaint or concern', + status: 'Draft', + isQuestionsComplete: 'no', payments: 'no', + + // Form questions + highestPageId: 6, pages: [ { pageIndex: '0', @@ -96,11 +99,7 @@ module.exports = { 'questionSaved': 'Yes' } ], - status: 'Draft', - confirmationTitle: 'Your form has been submitted', - checkAnswersTitle: 'Check your answers before submitting your form', - formTitle: 'Tell us about a complaint or concern', - isQuestionsComplete: 'no', - defaultUser: 'Firstname Ipsum', - defaultGroup: 'Departmental contact forms' + + // Placeholder override + action: 'gogogo' } diff --git a/app/data/returning-session-data-defaults.js b/app/data/returning-session-data-defaults.js index 7bfc19d3..f4417208 100644 --- a/app/data/returning-session-data-defaults.js +++ b/app/data/returning-session-data-defaults.js @@ -18,11 +18,14 @@ Example usage: */ module.exports = { - highestPageId: 6, - action: 'gogogo', - publish: 'GOV.UK', - authentication: 'email', + /* Dummy form settings */ + formTitle: 'Amendment form: redundancy claim for holiday pay', + status: 'Draft', + isQuestionsComplete: 'no', payments: 'no', + + // Form questions + highestPageId: 6, pages: [ { intro: 'This is the intro', @@ -81,9 +84,7 @@ module.exports = { pageIndex: '7' } ], - status: 'Draft', - confirmationTitle: 'Your form has been submitted', - checkAnswersTitle: 'Check your answers before submitting your form', - formTitle: 'Amendment form: redundancy claim for holiday pay', - isQuestionsComplete: 'no' + + // Placeholder override + action: 'gogogo' } diff --git a/app/data/session-data-defaults.js b/app/data/session-data-defaults.js index 95a505bc..779a12a1 100644 --- a/app/data/session-data-defaults.js +++ b/app/data/session-data-defaults.js @@ -19,55 +19,86 @@ Example usage: module.exports = { - // Insert values here + // Account settings + defaultUser: 'Firstname Ipsum', - highestPageId: 0, - action: '', - publish: 'GOV.UK', + // Group settings + defaultGroup: 'Departmental contact forms', + + // Default form data and settings authentication: 'email', payments: 'no', + publish: 'GOV.UK', + + // Placeholders to avoid errors + // Form questions + highestPageId: 0, pages: [], + // Form status status: 'Draft', - confirmationTitle: 'Your form has been submitted', + // Button actions value - used for ‘continue’, ‘save’, ‘delete’ or any other secondary grey button action + action: '', + + /* STATIC CONTENT + ================= */ + + // Check your answers page checkAnswersTitle: 'Check your answers before submitting your form', + // Confirmation page + confirmationTitle: 'Your form has been submitted', + /* Answer type hints and input type content */ + + // Person name personNameQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your name?’', personNameHintHint: 'You can add a short hint to help people answer the question. For example, you might need to ask people to enter their name as it’s written on an official document such as a passport or driving licence.', personNameInputTypeTitle: 'Name fields', + // Company name companyNameQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s the name of the organisation?’', companyNameHintHint: 'You can add a short hint to help people answer the question. For example, you might need to ask people to enter the registered name of their company.', + // Email emailQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your email address?’', emailHintHint: 'You could use hint text to tell people how you’ll use their email address. For example, ‘We’ll only use your email address to contact you about your application.’', + // Telephone phoneQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your phone number?’', phoneHintHint: 'You can add a short hint to help people answer the question. For example, ‘You can provide either a home or mobile phone number.’', + // National Insurance number (NINo) ninoQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your National Insurance number?’', ninoHintHint: 'You can add a short hint to help people answer the question. For example, ‘It’s on your National Insurance card, benefit letter, payslip or P60. For example, QQ 12 34 56 C.’', + // Address addressQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your address?’', addressHintHint: 'You could use hint text to tell people how you’ll use their address. For example, ‘We’ll send your licence to this address.’', addressInputTypeTitle: 'Address type', - dobQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your date of birth?’', - dobHintHint: 'You can add a short hint to help people answer the question. For a date of birth question you could use ‘For example, 27 3 1998’.', + // Date dateQuestionHint: 'Ask the question the way you would in person. For example, ‘What date was your passport issued?’', dateHintHint: 'You can add a short hint to help people answer the question. For a date question you could use ‘For example, 27 3 2007’.', + + // Date of birth (DOB) + dobQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your date of birth?’', + dobHintHint: 'You can add a short hint to help people answer the question. For a date of birth question you could use ‘For example, 27 3 1998’.', dateOfBirthInputTypeTitle: 'Date of birth', + // Selection - radio, checkbox or autocomplete (build only) selectionOneOptionQuestionHint: 'Ask the question the way you would in person. For example, ‘What country do you live in?’', selectionOneOptionHintHint: 'You can add a short hint to help people answer the question. For a question where people can only select one answer you might want to use ‘Select one option’.', selectionMultipleOptionsQuestionHint: 'Ask the question the way you would in person. For example, ‘Which of these countries have you lived in?’', selectionMultipleOptionsHintHint: 'You can add a short hint to help people answer the question. For a question where people can select more than one answer you might want to use ‘Select all that apply’.', + // Number numberQuestionHint: 'Ask the question the way you would in person. For example, ‘How many holiday days do you get a year?’', numberHintHint: 'You can add a short hint to help people answer the question. For example, ‘Do not include bank holidays’.', + // Text - single line textSingleLineQuestionHint: 'Ask the question the way you would in person. For example, ‘What’s your reference number?’', textSingleLineHintHint: 'You can add a short hint to help people answer the question. For example, you could say what format the answer should be in or where to find it.', + // Textarea - multiple line textMultipleLinesQuestionHint: 'Ask the question the way you would in person. For example, ‘Why do you want to apply for this role?’', textMultipleLinesHintHint: 'You can add a short hint to help people answer the question. For example, you could give a bit more detail about the information you need.', textLengthInputTypeTitle: 'Length' From d19e3fc58db12ed877bc4741c1099a83fe2e5838 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Mar 2025 17:03:42 +0000 Subject: [PATCH 44/61] Removed unnecessary router.use --- app/routes.js | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/app/routes.js b/app/routes.js index 241678bf..fe6dd876 100644 --- a/app/routes.js +++ b/app/routes.js @@ -90,36 +90,24 @@ router.use('/form-designer/*', function (req, res, next) { Create a new form ================= */ -// Middleware name your form -router.use('/form-designer/name-your-form', function (req, res, next) { - +// Name your form - GET +router.get('/form-designer/name-your-form', function (req, res) { // get the previous page URL var previousPage = req.session.data.referer // set the default back link var previousPageLink = `your-form` - var previousPageText = 'Back to create a form' + var previousPageText = 'Back to create your form' - if (previousPage) { + // if user is creating a ‘new’ form we should change the back link + if (previousPage?.includes('your-forms')) { // set the GOV.UK Forms home back link - if (previousPage.includes('your-forms')) { - previousPageLink = `your-forms` - previousPageText = 'Back to your forms' - } + previousPageLink = `your-forms` + previousPageText = 'Back to ' + (req.session.data.defaultGroup || 'your forms' ) } - - // make back link available in the view - req.session.data.previousPageLink = previousPageLink - req.session.data.previousPageText = previousPageText - - next(); -}) - -// Name your form - GET -router.get('/form-designer/name-your-form', function (req, res) { return res.render('form-designer/name-your-form', { - previousPageText: req.session.data.previousPageText, - previousPageLink: req.session.data.previousPageLink + previousPageText, + previousPageLink }) }) @@ -144,11 +132,6 @@ router.post('/form-designer/name-your-form', function (req, res) { if(containsErrors) { res.render('form-designer/name-your-form', { errors, errorList, containsErrors }) } else { - - // remove temporary back link details - req.session.data.previousPageLink = undefined - req.session.data.previousPageText = undefined - // set a success message for saving req.session.data.successMessage = 'Your form name has been saved' res.redirect('your-form') From a90d13564d9019c506f6aba7705c037939630807 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 26 Mar 2025 17:06:49 +0000 Subject: [PATCH 45/61] Added descriptions to return default session data --- .../returning-session-data-defaults-a11y.js | 17 +++-------------- app/data/returning-session-data-defaults.js | 16 ++-------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index 1772b06e..cc15af65 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -1,19 +1,8 @@ /* -Provide default values for user session data. These are automatically added -via the `autoStoreData` middleware. Values will only be added to the -session if a value doesn't already exist. This may be useful for testing -journeys where users are returning or logging in to an existing application. - -============================================================================ - -Example usage: - -"full-name": "Sarah Philips", - -"options-chosen": [ "foo", "bar" ] - -============================================================================ +This is the latest version of return data for a dummy form to be used in testing the branching journey: +created 26 March 2025 +testing: week commencing 31 March 2025 */ diff --git a/app/data/returning-session-data-defaults.js b/app/data/returning-session-data-defaults.js index f4417208..1739816f 100644 --- a/app/data/returning-session-data-defaults.js +++ b/app/data/returning-session-data-defaults.js @@ -1,19 +1,7 @@ /* -Provide default values for user session data. These are automatically added -via the `autoStoreData` middleware. Values will only be added to the -session if a value doesn't already exist. This may be useful for testing -journeys where users are returning or logging in to an existing application. - -============================================================================ - -Example usage: - -"full-name": "Sarah Philips", - -"options-chosen": [ "foo", "bar" ] - -============================================================================ +This data is for a dummy form - it was previously used in earlier rounds of testing +Not all the structure of the questions will work and may cause some errors throughout the prototype */ From 9c2665243c52636add361a41ed6bc534a079d713 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 10:59:30 +0000 Subject: [PATCH 46/61] Tiny bit of code simplification --- app/data/returning-session-data-defaults.js | 7 +------ app/routes.js | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/data/returning-session-data-defaults.js b/app/data/returning-session-data-defaults.js index 1739816f..56c30586 100644 --- a/app/data/returning-session-data-defaults.js +++ b/app/data/returning-session-data-defaults.js @@ -9,8 +9,6 @@ module.exports = { /* Dummy form settings */ formTitle: 'Amendment form: redundancy claim for holiday pay', status: 'Draft', - isQuestionsComplete: 'no', - payments: 'no', // Form questions highestPageId: 6, @@ -71,8 +69,5 @@ module.exports = { type: 'number', pageIndex: '7' } - ], - - // Placeholder override - action: 'gogogo' + ] } diff --git a/app/routes.js b/app/routes.js index fe6dd876..376b45a1 100644 --- a/app/routes.js +++ b/app/routes.js @@ -187,8 +187,8 @@ router.get('/form-designer/your-form', function (req, res) { } return res.render('form-designer/your-form', { - successMessage: successMessage, - sections: sections + successMessage, + sections }) }) From 322654c03a2b1e569a8dafdc42600ea9e5eb51d5 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 10:59:55 +0000 Subject: [PATCH 47/61] Update link to default data incase this is easier for testing --- app/views/form-builder-prototypes.html | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/app/views/form-builder-prototypes.html b/app/views/form-builder-prototypes.html index aac8054d..5dacb604 100644 --- a/app/views/form-builder-prototypes.html +++ b/app/views/form-builder-prototypes.html @@ -39,19 +39,11 @@

    Admin prototype


    - Amendment form: redundancy claim for holiday pay return journey (Insolvency Service first form) -

    -

    - - View incomplete form return journey prototype -

    - -

    - Take your pet abroad return journey (testing form) + Tell us about a complaint or concern (testing form)

    - View completed form return journey prototype + View an existing form journey


    From 07b8e88f3ad54691566f2b8d36d5e02e29653d10 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 11:00:21 +0000 Subject: [PATCH 48/61] Started outlining default session data for the different sections on task list --- .../returning-session-data-defaults-a11y.js | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index cc15af65..d3d4d452 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -10,8 +10,23 @@ module.exports = { /* Dummy form settings */ formTitle: 'Tell us about a complaint or concern', status: 'Draft', + + // Form tasks isQuestionsComplete: 'no', - payments: 'no', + // checkAnswersDeclaration + isDeclarationComplete: 'no', + // confirmationNext + isConfirmationComplete: 'no', + // formsEmail + isSubmissionEmailComplete: 'no', + // confirmationCode + isConfirmationCodeComplete: 'no', + // privacyInformation + isPrivacyInformationComplete: 'no', + // supportDetails - emailSupport, phoneSupport, onlineSupportLink, onlineSupportText + isSupportDetailsComplete: 'no', + // makeFormLive + isFormLive: 'no', // Form questions highestPageId: 6, @@ -87,8 +102,5 @@ module.exports = { 'additional-guidance': 'No', 'questionSaved': 'Yes' } - ], - - // Placeholder override - action: 'gogogo' + ] } From 14f5ec23a8147e86ddbd48b9e844c0bb576fb006 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 11:47:55 +0000 Subject: [PATCH 49/61] =?UTF-8?q?Fix=20displaying=20=E2=80=98in=20progress?= =?UTF-8?q?=E2=80=99=20when=20declaration=20not=20started?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/form-designer/partials/status-draft-form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/form-designer/partials/status-draft-form.html b/app/views/form-designer/partials/status-draft-form.html index f2422aaf..5ede1667 100644 --- a/app/views/form-designer/partials/status-draft-form.html +++ b/app/views/form-designer/partials/status-draft-form.html @@ -67,7 +67,7 @@

    {# SET STATUS OF DECLARATION #} {% if data.isDeclarationComplete === 'yes' %} {% set declarationStatusText = 'Completed' %} -{% elif data.isDeclarationComplete === 'no' and data.checkAnswersDeclaration != '' %} +{% elif (data.isDeclarationComplete === 'no') and data.checkAnswersDeclaration %} {% set declarationStatusTag = 'govuk-tag--light-blue' %} {% set declarationStatusText = 'In progress' %} {% else %} From f6e82569892424318c85701796c68eefc4d0299e Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 11:48:16 +0000 Subject: [PATCH 50/61] Added routes section where a route has been added or can be added to a question --- .../form-designer/pages/check-question.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/views/form-designer/pages/check-question.html b/app/views/form-designer/pages/check-question.html index a5c67c8c..a5f23d0f 100644 --- a/app/views/form-designer/pages/check-question.html +++ b/app/views/form-designer/pages/check-question.html @@ -289,6 +289,24 @@

    Guidance

    {% endif %} + {% if (pageData.type === 'select') and ('oneOption' in pageData.listSettings) %} +

    Routes

    +

    + {% if pageData.routing %} + This question has routes: Question {{ pageIndex|int + 1 }}’s routes + {% else %} + If you need people to skip some questions based on their answer to this question, you can add a question route. + {% endif %} +

    +
    + {% elif pageData.routing and (pageData.routing.noAnswer) %} +

    Routes

    +

    + People will skip to question {{ pageData.routing.thenSkipTo|int + 1 }} after this question because of Question {{ pageData.routing.baseQuestion|int + 1 }}’s routes. +

    +
    + {% endif %} +
    From f6a986f043f09cfb083ec4e72354d6791b299785 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 11:48:47 +0000 Subject: [PATCH 51/61] Fixed issue with select item being checked due to incorrect value --- app/views/form-designer/question-routes/conditions.html | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/views/form-designer/question-routes/conditions.html b/app/views/form-designer/question-routes/conditions.html index e821df81..b1e33e7f 100644 --- a/app/views/form-designer/question-routes/conditions.html +++ b/app/views/form-designer/question-routes/conditions.html @@ -78,8 +78,7 @@

    {{ pageTitle }}

    {% set tempAnswers = ( tempAnswers.push({ value: item, - text: item, - selected: true if (page.routing.answer == item) + text: item }), tempAnswers) %} {% endfor %} @@ -91,8 +90,7 @@

    {{ pageTitle }}

    {% set tempQuestions = ( tempQuestions.push({ value: page.pageIndex, - text: (page.pageIndex|int + 1) + '. ' + page['long-title'], - selected: true if (temp == page.pageIndex) + text: (page.pageIndex|int + 1) + '. ' + page['long-title'] }), tempQuestions) %} {# we also need to add the CYA page to the list of options #} @@ -114,7 +112,7 @@

    {{ pageTitle }}

    text: "is answered as", classes: 'govuk-label--s' }, - value: data['route1Answer'], + value: pageData.routing.answer or data['route1Answer'], items: tempAnswers, errorMessage: { text: errors['route1Answer'].text } if errors['route1Answer'].text }) }} @@ -127,6 +125,7 @@

    {{ pageTitle }}

    classes: 'govuk-label--s' }, items: tempQuestions, + value: pageData.routing.skipTo or data['route1End'], errorMessage: { text: errors['route1End'].text } if errors['route1End'].text }) }} From a67fcee2cc49634cc59e9426a2359a2820fc37b3 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 13:34:33 +0000 Subject: [PATCH 52/61] =?UTF-8?q?Added=20routing=20to=20=E2=80=98live?= =?UTF-8?q?=E2=80=99=20form=20questions=20view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../partials/your-questions-live-form.html | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/app/views/form-designer/partials/your-questions-live-form.html b/app/views/form-designer/partials/your-questions-live-form.html index 35496f94..d433936b 100644 --- a/app/views/form-designer/partials/your-questions-live-form.html +++ b/app/views/form-designer/partials/your-questions-live-form.html @@ -177,6 +177,51 @@

    {{ page['long-title'] }}{{ ' (optional)' i
    {{ titleText }}

    {% endif %} + + {# now we can add any route that is based on an answer to the question above #} + {% if page.routing.skipTo %} + {% set skipPage = '' %} + {% if page.routing.skipTo == 'cya' %} + {% set skipPage = '“' + data.checkAnswersTitle + '”' %} + {% else %} + {% for item in data.pages %} + {% if (item.pageIndex|int) == (page.routing.skipTo|int) %} + {% set skipPage -%}{{ page.routing.skipTo|int + 1 }}, “{{ item['long-title'] }}”{%- endset %} + {% endif %} + {% endfor %} + {% endif %} +
    +
    + Routes +
    +
    + If the answer is “{{ page.routing.answer }}” then skip to {{ skipPage }} +
    +
    + {% endif %} + {# finally we need to add routing not based on an answer if there is any #} + {% if page.routing.noAnswer %} + {% set skipPage = '' %} + {% if page.routing.thenSkipTo == 'cya' %} + {% set skipPage = '“' + data.checkAnswersTitle + '”' %} + {% else %} + {% for otherRoutePage in data.pages %} + {% if (otherRoutePage.pageIndex|int) == (page.routing.thenSkipTo|int) %} + {% set skipPage -%} + {{ otherRoutePage.pageIndex|int + 1 }}, “{{ otherRoutePage['long-title'] }}” + {%- endset %} + {% endif %} + {% endfor %} + {% endif %} +
    +
    + Routes +
    +
    + Skip the person to {{ skipPage }} +
    +
    + {% endif %}

    From 124a7ca1b1072d8eabb2feb43b10bbfd1da39039 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 13:35:09 +0000 Subject: [PATCH 53/61] Fixed declaration displaying in progress before it has been started --- app/routes.js | 41 ++++++------------- .../pages/check-answers/edit.html | 9 ++-- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/app/routes.js b/app/routes.js index 376b45a1..26726287 100644 --- a/app/routes.js +++ b/app/routes.js @@ -487,26 +487,17 @@ Managing additional pages in a form // Route used to check Declaration is complete - Check your answers (CYA) router.post('/form-designer/pages/check-answers/edit', function (req, res) { - const action = req.session.data.action - req.session.data.action = undefined - + const errors = {}; var pageId = parseInt(req.params.pageId, 10) var pageIndex = pageId var pageData = req.session.data.pages[pageIndex] + var { checkAnswersDeclaration, isDeclarationComplete } = req.session.data - const errors = {}; - const complete = req.session.data.isDeclarationComplete - const declarationContent = req.session.data.checkAnswersDeclaration - - // content to display in notification banners - var saved = 'Your declaration has been saved' - var savedAndComplete = 'Your declaration has been saved and marked as complete' - - // if no selection made, then throw an error - if (!complete || !complete.length) { - errors['isDeclarationComplete'] = { - text: 'Select yes if you want to mark this task as complete', - href: "#isDeclarationComplete" + // if trying to mark as complete while having too many characters, then throw an error + if ((checkAnswersDeclaration.length > 2000) && (isDeclarationComplete == 'yes')) { + errors['checkAnswersDeclaration'] = { + text: 'The declaration cannot be longer than 2,000 characters', + href: "#check-answers-declaration" } } @@ -516,16 +507,7 @@ router.post('/form-designer/pages/check-answers/edit', function (req, res) { // otherwise, show the page again with the errors set const containsErrors = errorList.length > 0 // If there are errors on the page, redisplay it with the errors - if (action === 'update') { - // set a success message for saving - req.session.data.successMessage = saved - return res.render('form-designer/pages/check-answers/edit', { - pageId: pageId, - pageIndex: pageIndex, - pageData: pageData, - successMessage: saved - }) - } else if(containsErrors) { + if(containsErrors) { return res.render('form-designer/pages/check-answers/edit', { pageId: pageId, pageIndex: pageIndex, @@ -535,13 +517,14 @@ router.post('/form-designer/pages/check-answers/edit', function (req, res) { containsErrors }) } else { - if(complete === 'yes') { + if(isDeclarationComplete === 'yes') { // set a success message for saving - req.session.data.successMessage = savedAndComplete + req.session.data.successMessage = 'Your declaration has been saved and marked as complete' } else { // set a success message for saving - req.session.data.successMessage = saved + req.session.data.successMessage = 'Your declaration has been saved' } + req.session.data.isDeclarationComplete = isDeclarationComplete return res.redirect('../../your-form') } }) diff --git a/app/views/form-designer/pages/check-answers/edit.html b/app/views/form-designer/pages/check-answers/edit.html index c1b5f21a..14e32764 100644 --- a/app/views/form-designer/pages/check-answers/edit.html +++ b/app/views/form-designer/pages/check-answers/edit.html @@ -65,20 +65,21 @@

    Example

    {{ govukCharacterCount({ name: "checkAnswersDeclaration", - id: "checkAnswersDeclaration", + id: "check-answers-declaration", maxlength: 2000, value: data['checkAnswersDeclaration'], label: { text: "Enter a declaration for people to agree to (optional)", classes: "govuk-label--m" - } + }, + errorMessage: { text: errors['checkAnswersDeclaration'].text } if errors['checkAnswersDeclaration'].text }) }} {% if data.status === 'Draft' %} {{ govukRadios({ - classes: "govuk-radios", - idPrefix: "isDeclarationComplete", + idPrefix: "is-declaration-complete", name: "isDeclarationComplete", + classes: "govuk-radios", fieldset: { legend: { text: "Do you want to mark this task as complete?", From 704d1471104e7cd8a137895f28a5e312391ebee3 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 14:06:53 +0000 Subject: [PATCH 54/61] Updated to add missing content --- .../pages/confirmation/edit.html | 80 ++++++++++++------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/app/views/form-designer/pages/confirmation/edit.html b/app/views/form-designer/pages/confirmation/edit.html index fe4c81b9..d0b5cb86 100644 --- a/app/views/form-designer/pages/confirmation/edit.html +++ b/app/views/form-designer/pages/confirmation/edit.html @@ -18,14 +18,6 @@ {% block content %}
    - - {% if successMessage %} - {{ govukNotificationBanner({ - type: 'success', - text: successMessage - }) }} - {% endif %} -
    {% if containsErrors %} @@ -38,14 +30,8 @@ {{ data.formTitle or '[formTitle]' }}

    {{ pageTitle }}

    - {# - Every field id is prefixed with a unique page id. - So we can have separate configurations for every page. - #} - {% set pagePrefix = "p" + pageId + "-" %} -

    - Add some information to tell people what will happen after they've submitted their form, and when - so they know what to expect. + Add some information to tell people what will happen after they’ve submitted their form, and when - so they know what to expect.

    Example

    @@ -58,7 +44,7 @@

    Example

    • - shown to people when they've completed and submitted a form + shown to people when they’ve completed and submitted a form
    • included in an email confirmation, if they choose to receive this @@ -69,19 +55,62 @@

      Example

      The optional email confirmation will also include the contact details you provide for the form, and the date and time of submission. It will not include a copy of their answers.

      + {{ govukInsetText({ + text: "GOV.UK Forms adds a unique reference number to the confirmation page and optional email confirmation. This will also be included in submission emails sent to your processing email address." + }) }} + {{ govukCharacterCount({ - name: "confirmationNext", - id: "confirmationNext", - maxlength: 2000, - value: data['confirmationNext'], + id: "what-happens-next", + name: "whatHappensNext", label: { text: "Enter some information to tell people what will happen next", classes: "govuk-label--m" }, - errorMessage: { text: errors['confirmationNext'].text } if errors['confirmationNext'].text + maxlength: 2000, + value: data['whatHappensNext'], + errorMessage: { text: errors['whatHappensNext'].text } if errors['whatHappensNext'].text }) }} - + {% set formatHelpHTML -%} + {# Links and URLs #} +

      Links and URLs

      +

      + To add a link, use square brackets [ ] around the link text, and round brackets ( ) around the full URL. Make sure there are no spaces between the two sets of brackets. For example: +

      + {{ govukInsetText({ + text: "[Link text](https://www.gov.uk/link-text-url)" + }) }} + {# Bulleted lists #} +

      Bulleted lists

      +

      + To add bullet points, start each item with * (asterisk) or - (dash). Make sure there is one space after the asterisk or dash. +

      +

      + Leave one empty line before adding the first bullet point and another after the last bullet point. For example: +

      + {{ govukInsetText({ + html: "* First bullet point
      + * Second bullet point
      + * Third bullet point" + }) }} + {# Numbered lists #} +

      Numbered lists

      +

      + Use numbers for each list item, followed by a full stop. Make sure there is one space after the full stop. +

      +

      + Leave one empty line before adding the first list item and another after the last list item. For example: +

      + {{ govukInsetText({ + html: "1. First item
      + 2. Second item
      + 3. Third item" + }) }} + {%- endset %} + {{ govukDetails({ + summaryText: "Formatting help", + html: formatHelpHTML + }) }} {{ govukButton({ text: "Save and continue", @@ -93,10 +122,3 @@

      Example

    {% endblock %} - -{% block pageScripts %} - -{% endblock %} From c7ec1c6ad4c6b3f67d93c7f98efdc171e62a9ccd Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 14:07:10 +0000 Subject: [PATCH 55/61] Removed unused/unnecessary code --- app/routes.js | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/app/routes.js b/app/routes.js index 26726287..7a1a70e4 100644 --- a/app/routes.js +++ b/app/routes.js @@ -531,24 +531,14 @@ router.post('/form-designer/pages/check-answers/edit', function (req, res) { // Route used to check What happens next (WHN) content has been added router.post('/form-designer/pages/confirmation/edit', function (req, res) { - const action = req.session.data.action - req.session.data.action = undefined - - var pageId = parseInt(req.params.pageId, 10) - var pageIndex = pageId - var pageData = req.session.data.pages[pageIndex] - const errors = {}; - const whatHappensNext = req.session.data.confirmationNext - - // content to display in notification banners - var saved = 'Your information about what happens next has been saved' + const { whatHappensNext } = req.session.data // if no selection made, then throw an error if (!whatHappensNext || !whatHappensNext.length) { - errors['confirmationNext'] = { + errors['whatHappensNext'] = { text: 'Enter some information about what happens next', - href: "#confirmationNext" + href: "#what-happens-next" } } @@ -559,24 +549,10 @@ router.post('/form-designer/pages/confirmation/edit', function (req, res) { const containsErrors = errorList.length > 0 // If there are errors on the page, redisplay it with the errors if(containsErrors) { - return res.render('form-designer/pages/confirmation/edit', { - pageId: pageId, - pageIndex: pageIndex, - pageData: pageData, - errors, - errorList, - containsErrors - }) - } else if (action === 'update') { - return res.render('form-designer/pages/confirmation/edit', { - pageId: pageId, - pageIndex: pageIndex, - pageData: pageData, - successMessage: saved - }) + return res.render('form-designer/pages/confirmation/edit', { errors, errorList, containsErrors }) } else { // set a success message for saving - req.session.data.successMessage = saved + req.session.data.successMessage = 'Your information about what happens next has been saved' return res.redirect('../../your-form') } }) From 31428b9ef262afd8c15c0f9576450e988baaef04 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 14:08:04 +0000 Subject: [PATCH 56/61] Removed unused/unnecessary code --- .../pages/check-answers/edit.html | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/app/views/form-designer/pages/check-answers/edit.html b/app/views/form-designer/pages/check-answers/edit.html index 14e32764..c026ff15 100644 --- a/app/views/form-designer/pages/check-answers/edit.html +++ b/app/views/form-designer/pages/check-answers/edit.html @@ -18,14 +18,6 @@ {% block content %}
    - - {% if successMessage %} - {{ govukNotificationBanner({ - type: 'success', - text: successMessage - }) }} - {% endif %} - {% if containsErrors %} @@ -106,8 +98,6 @@

    Example

    }) }} {% endif %} - - {{ govukButton({ text: "Save and continue", name: "action", @@ -117,11 +107,4 @@

    Example

    -{% endblock %} - -{% block pageScripts %} - -{% endblock %} +{% endblock %} \ No newline at end of file From 1ed171bc5e42c8a01ff4b25db14e4b541a103554 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 27 Mar 2025 16:17:28 +0000 Subject: [PATCH 57/61] Updated dummy content to match Mural board for testing --- app/data/returning-session-data-defaults-a11y.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index d3d4d452..ab1f279d 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -8,7 +8,7 @@ testing: week commencing 31 March 2025 module.exports = { /* Dummy form settings */ - formTitle: 'Tell us about a complaint or concern', + formTitle: 'Tell us about a complaint, concern or error', status: 'Draft', // Form tasks @@ -34,10 +34,11 @@ module.exports = { { pageIndex: '0', type: 'select', - 'long-title': 'Are you making a complaint or reporting an error?', + 'long-title': 'Which of these do you want to do today?', 'item-list': [ - "Making a complaint", - "Reporting an error" + "Make a complaint", + "Raise a concern", + "Report an error" ], 'listSettings': [ "oneOption" @@ -48,7 +49,7 @@ module.exports = { { pageIndex: '1', type: 'select', - 'long-title': 'What does your complaint relate to?', + 'long-title': 'What does your complaint or concern relate to?', 'item-list': [ "Service", "Access", @@ -65,7 +66,7 @@ module.exports = { pageIndex: '2', type: 'text', input: "multi-line-input", - 'long-title': 'Please give full details of your complaint', + 'long-title': 'Please give full details of your complaint or concern', 'additional-guidance': 'No', 'questionSaved': 'Yes' }, From 109c563d25c1102f2f736e64415198dae857c955 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 28 Mar 2025 17:00:01 +0000 Subject: [PATCH 58/61] Added new questions to dummy form for testing --- .../returning-session-data-defaults-a11y.js | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index ab1f279d..d28a489b 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -29,7 +29,7 @@ module.exports = { isFormLive: 'no', // Form questions - highestPageId: 6, + highestPageId: 7, pages: [ { pageIndex: '0', @@ -72,6 +72,20 @@ module.exports = { }, { pageIndex: '3', + type: 'select', + 'long-title': 'Have you contacted us about this before?', + 'item-list': [ + "Yes", + "No" + ], + 'listSettings': [ + "oneOption" + ], + 'additional-guidance': 'No', + 'questionSaved': 'Yes' + }, + { + pageIndex: '4', type: 'text', input: "single-line-input", 'long-title': 'What were you trying to do when the error happend?', @@ -79,7 +93,7 @@ module.exports = { 'questionSaved': 'Yes' }, { - pageIndex: '4', + pageIndex: '5', type: 'text', input: "multi-line-input", 'long-title': 'Please tell us what happened when the error occurred', @@ -87,7 +101,15 @@ module.exports = { 'questionSaved': 'Yes', }, { - pageIndex: '5', + pageIndex: '6', + type: 'text', + input: "multi-line-input", + 'long-title': 'What did you do, if anything, to work around the error?', + 'additional-guidance': 'No', + 'questionSaved': 'Yes', + }, + { + pageIndex: '7', type: 'select', 'long-title': 'How would you rate your overall experience of using the service?', 'item-list': [ From d7c4901cf8e0099e8bea824a9392b599bc761ff8 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Fri, 28 Mar 2025 17:01:10 +0000 Subject: [PATCH 59/61] Fixed typos and added optional question --- app/data/returning-session-data-defaults-a11y.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index d28a489b..0721d11d 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -98,7 +98,7 @@ module.exports = { input: "multi-line-input", 'long-title': 'Please tell us what happened when the error occurred', 'additional-guidance': 'No', - 'questionSaved': 'Yes', + 'questionSaved': 'Yes' }, { pageIndex: '6', @@ -106,7 +106,10 @@ module.exports = { input: "multi-line-input", 'long-title': 'What did you do, if anything, to work around the error?', 'additional-guidance': 'No', - 'questionSaved': 'Yes', + "questionOptional": [ + "questionOptional" + ], + 'questionSaved': 'Yes' }, { pageIndex: '7', From fe0a6bcc30c049b19f91cdb7747a529a75817dfc Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Wed, 2 Apr 2025 08:54:06 +0100 Subject: [PATCH 60/61] Reordering selection options for testing --- app/data/returning-session-data-defaults-a11y.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/data/returning-session-data-defaults-a11y.js b/app/data/returning-session-data-defaults-a11y.js index 0721d11d..9936d713 100644 --- a/app/data/returning-session-data-defaults-a11y.js +++ b/app/data/returning-session-data-defaults-a11y.js @@ -36,9 +36,9 @@ module.exports = { type: 'select', 'long-title': 'Which of these do you want to do today?', 'item-list': [ + "Report an error", "Make a complaint", - "Raise a concern", - "Report an error" + "Raise a concern" ], 'listSettings': [ "oneOption" From 7ec3d6ad425b71f9fd1c218fc157373ab20f4483 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 3 Apr 2025 09:26:57 +0100 Subject: [PATCH 61/61] Commented out a bit of issue code for testing --- app/views/form-designer/question-routes/_routes.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/form-designer/question-routes/_routes.js b/app/views/form-designer/question-routes/_routes.js index a10a5735..a6493def 100644 --- a/app/views/form-designer/question-routes/_routes.js +++ b/app/views/form-designer/question-routes/_routes.js @@ -221,12 +221,12 @@ router.post('/form-designer/question-routes/:pageId(\\d+)/questions-routes', fun res.redirect(`are-you-sure`) } else { // add the first part of routing to the suggested question - for (let index = 0; index < pages.length; index++) { - const element = pages[index]; - if ((parseInt(element.pageIndex, 10)) == suggestedQuestion) { - element.routing = { 'noAnswer': 'true' } // add a routing element to the question - } - } + // for (let index = 0; index < pages.length; index++) { + // const element = pages[index]; + // if ((parseInt(element.pageIndex, 10)) == suggestedQuestion) { + // element.routing = { 'noAnswer': 'true' } // add a routing element to the question + // } + // } // reset the session data for suggestedQuestion req.session.data.suggestedQuestion = undefined // reset action