@defra/forms-engine-plugin 4.0.25 → 4.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.server/server/plugins/engine/components/HiddenField.d.ts +21 -0
- package/.server/server/plugins/engine/components/HiddenField.js +50 -0
- package/.server/server/plugins/engine/components/HiddenField.js.map +1 -0
- package/.server/server/plugins/engine/components/helpers/components.d.ts +1 -1
- package/.server/server/plugins/engine/components/helpers/components.js +3 -0
- package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
- package/.server/server/plugins/engine/components/index.d.ts +1 -0
- package/.server/server/plugins/engine/components/index.js +1 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -1
- package/.server/server/plugins/engine/helpers.js +2 -1
- package/.server/server/plugins/engine/helpers.js.map +1 -1
- package/.server/server/plugins/engine/models/FormModel.d.ts +2 -0
- package/.server/server/plugins/engine/models/FormModel.js +2 -0
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/PageController.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/PageController.js +2 -8
- package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +7 -0
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js +8 -2
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +2 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/state.d.ts +11 -0
- package/.server/server/plugins/engine/pageControllers/helpers/state.js +66 -0
- package/.server/server/plugins/engine/pageControllers/helpers/state.js.map +1 -0
- package/.server/server/plugins/engine/routes/index.js +2 -1
- package/.server/server/plugins/engine/routes/index.js.map +1 -1
- package/.server/server/plugins/engine/services/formsService.d.ts +6 -0
- package/.server/server/plugins/engine/services/formsService.js +10 -0
- package/.server/server/plugins/engine/services/formsService.js.map +1 -1
- package/.server/server/plugins/engine/services/formsService.test.js +14 -0
- package/.server/server/plugins/engine/services/formsService.test.js.map +1 -0
- package/.server/server/plugins/engine/types.d.ts +4 -0
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/views/components/hiddenfield.html +3 -0
- package/.server/server/plugins/engine/views/confirmation.html +5 -0
- package/.server/server/plugins/engine/views/partials/form.html +9 -1
- package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
- package/.server/server/services/cacheService.d.ts +3 -7
- package/.server/server/services/cacheService.js.map +1 -1
- package/.server/server/types.d.ts +1 -0
- package/.server/server/types.js.map +1 -1
- package/.server/server/utils/file-form-service.d.ts +6 -0
- package/.server/server/utils/file-form-service.js +22 -1
- package/.server/server/utils/file-form-service.js.map +1 -1
- package/.server/server/utils/file-form-service.test.js +86 -0
- package/.server/server/utils/file-form-service.test.js.map +1 -0
- package/package.json +2 -2
- package/src/server/plugins/engine/components/HiddenField.test.ts +188 -0
- package/src/server/plugins/engine/components/HiddenField.ts +68 -0
- package/src/server/plugins/engine/components/helpers/components.ts +5 -0
- package/src/server/plugins/engine/components/helpers/helpers.test.ts +17 -0
- package/src/server/plugins/engine/components/index.ts +1 -0
- package/src/server/plugins/engine/helpers.ts +2 -1
- package/src/server/plugins/engine/models/FormModel.ts +3 -0
- package/src/server/plugins/engine/pageControllers/PageController.test.ts +4 -11
- package/src/server/plugins/engine/pageControllers/PageController.ts +1 -9
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +7 -0
- package/src/server/plugins/engine/pageControllers/StatusPageController.ts +9 -2
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +5 -1
- package/src/server/plugins/engine/pageControllers/helpers/state.test.ts +221 -0
- package/src/server/plugins/engine/pageControllers/helpers/state.ts +93 -0
- package/src/server/plugins/engine/routes/index.test.ts +24 -11
- package/src/server/plugins/engine/routes/index.ts +1 -1
- package/src/server/plugins/engine/services/formsService.js +10 -0
- package/src/server/plugins/engine/services/formsService.test.js +21 -0
- package/src/server/plugins/engine/types.ts +5 -0
- package/src/server/plugins/engine/views/components/hiddenfield.html +3 -0
- package/src/server/plugins/engine/views/confirmation.html +5 -0
- package/src/server/plugins/engine/views/partials/form.html +9 -1
- package/src/server/services/cacheService.ts +3 -2
- package/src/server/types.ts +1 -0
- package/src/server/utils/file-form-service.js +27 -1
- package/src/server/utils/file-form-service.test.js +114 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { ComponentType, type HiddenFieldComponent } from '@defra/forms-model'
|
|
2
|
+
|
|
3
|
+
import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
|
|
4
|
+
import {
|
|
5
|
+
getAnswer,
|
|
6
|
+
type Field
|
|
7
|
+
} from '~/src/server/plugins/engine/components/helpers/components.js'
|
|
8
|
+
import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
|
|
9
|
+
import definition from '~/test/form/definitions/blank.js'
|
|
10
|
+
import { getFormData, getFormState } from '~/test/helpers/component-helpers.js'
|
|
11
|
+
|
|
12
|
+
describe('HiddenField', () => {
|
|
13
|
+
let model: FormModel
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
model = new FormModel(definition, {
|
|
17
|
+
basePath: 'test'
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
describe('Defaults', () => {
|
|
22
|
+
let def: HiddenFieldComponent
|
|
23
|
+
let collection: ComponentCollection
|
|
24
|
+
let field: Field
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
def = {
|
|
28
|
+
title: 'Hidden field',
|
|
29
|
+
name: 'myComponent',
|
|
30
|
+
type: ComponentType.HiddenField,
|
|
31
|
+
options: {}
|
|
32
|
+
} satisfies HiddenFieldComponent
|
|
33
|
+
|
|
34
|
+
collection = new ComponentCollection([def], { model })
|
|
35
|
+
field = collection.fields[0]
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('Schema', () => {
|
|
39
|
+
it('uses component title as label as default', () => {
|
|
40
|
+
const { formSchema } = collection
|
|
41
|
+
const { keys } = formSchema.describe()
|
|
42
|
+
|
|
43
|
+
expect(keys).toHaveProperty(
|
|
44
|
+
'myComponent',
|
|
45
|
+
expect.objectContaining({
|
|
46
|
+
flags: expect.objectContaining({
|
|
47
|
+
label: 'Hidden field'
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('uses component name as keys', () => {
|
|
54
|
+
const { formSchema } = collection
|
|
55
|
+
const { keys } = formSchema.describe()
|
|
56
|
+
|
|
57
|
+
expect(field.keys).toEqual(['myComponent'])
|
|
58
|
+
expect(field.collection).toBeUndefined()
|
|
59
|
+
|
|
60
|
+
for (const key of field.keys) {
|
|
61
|
+
expect(keys).toHaveProperty(key)
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('is required by default', () => {
|
|
66
|
+
const { formSchema } = collection
|
|
67
|
+
const { keys } = formSchema.describe()
|
|
68
|
+
|
|
69
|
+
expect(keys).toHaveProperty(
|
|
70
|
+
'myComponent',
|
|
71
|
+
expect.objectContaining({
|
|
72
|
+
flags: expect.objectContaining({
|
|
73
|
+
presence: 'required'
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
})
|
|
78
|
+
it('accepts valid values', () => {
|
|
79
|
+
const result1 = collection.validate(getFormData('Hidden value'))
|
|
80
|
+
const result2 = collection.validate(getFormData('Hidden value 2'))
|
|
81
|
+
|
|
82
|
+
expect(result1.errors).toBeUndefined()
|
|
83
|
+
expect(result2.errors).toBeUndefined()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('adds errors for empty value', () => {
|
|
87
|
+
const result = collection.validate(getFormData(''))
|
|
88
|
+
|
|
89
|
+
expect(result.errors).toEqual([
|
|
90
|
+
expect.objectContaining({
|
|
91
|
+
text: 'Enter hidden field'
|
|
92
|
+
})
|
|
93
|
+
])
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('adds errors for invalid values', () => {
|
|
97
|
+
const result1 = collection.validate(getFormData(['invalid']))
|
|
98
|
+
const result2 = collection.validate(
|
|
99
|
+
// @ts-expect-error - Allow invalid param for test
|
|
100
|
+
getFormData({ unknown: 'invalid' })
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
expect(result1.errors).toBeTruthy()
|
|
104
|
+
expect(result2.errors).toBeTruthy()
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
describe('State', () => {
|
|
109
|
+
it('returns text from state', () => {
|
|
110
|
+
const state1 = getFormState('Hidden field')
|
|
111
|
+
const state2 = getFormState(null)
|
|
112
|
+
|
|
113
|
+
const answer1 = getAnswer(field, state1)
|
|
114
|
+
const answer2 = getAnswer(field, state2)
|
|
115
|
+
|
|
116
|
+
expect(answer1).toBe('Hidden field')
|
|
117
|
+
expect(answer2).toBe('')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('returns payload from state', () => {
|
|
121
|
+
const state1 = getFormState('Hidden field')
|
|
122
|
+
const state2 = getFormState(null)
|
|
123
|
+
|
|
124
|
+
const payload1 = field.getFormDataFromState(state1)
|
|
125
|
+
const payload2 = field.getFormDataFromState(state2)
|
|
126
|
+
|
|
127
|
+
expect(payload1).toEqual(getFormData('Hidden field'))
|
|
128
|
+
expect(payload2).toEqual(getFormData())
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('returns value from state', () => {
|
|
132
|
+
const state1 = getFormState('Hidden field')
|
|
133
|
+
const state2 = getFormState(null)
|
|
134
|
+
|
|
135
|
+
const value1 = field.getFormValueFromState(state1)
|
|
136
|
+
const value2 = field.getFormValueFromState(state2)
|
|
137
|
+
|
|
138
|
+
expect(value1).toBe('Hidden field')
|
|
139
|
+
expect(value2).toBeUndefined()
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('returns context for conditions and form submission', () => {
|
|
143
|
+
const state1 = getFormState('Hidden field')
|
|
144
|
+
const state2 = getFormState(null)
|
|
145
|
+
|
|
146
|
+
const value1 = field.getContextValueFromState(state1)
|
|
147
|
+
const value2 = field.getContextValueFromState(state2)
|
|
148
|
+
|
|
149
|
+
expect(value1).toBe('Hidden field')
|
|
150
|
+
expect(value2).toBeNull()
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('returns state from payload', () => {
|
|
154
|
+
const payload1 = getFormData('Hidden field')
|
|
155
|
+
const payload2 = getFormData()
|
|
156
|
+
|
|
157
|
+
const value1 = field.getStateFromValidForm(payload1)
|
|
158
|
+
const value2 = field.getStateFromValidForm(payload2)
|
|
159
|
+
|
|
160
|
+
expect(value1).toEqual(getFormState('Hidden field'))
|
|
161
|
+
expect(value2).toEqual(getFormState(null))
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
describe('View model', () => {
|
|
166
|
+
it('sets Nunjucks component defaults', () => {
|
|
167
|
+
const viewModel = field.getViewModel(getFormData('Hidden field'))
|
|
168
|
+
|
|
169
|
+
expect(viewModel).toEqual(
|
|
170
|
+
expect.objectContaining({
|
|
171
|
+
label: { text: def.title },
|
|
172
|
+
name: 'myComponent',
|
|
173
|
+
id: 'myComponent',
|
|
174
|
+
value: 'Hidden field'
|
|
175
|
+
})
|
|
176
|
+
)
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
describe('AllPossibleErrors', () => {
|
|
181
|
+
it('should return errors', () => {
|
|
182
|
+
const errors = field.getAllPossibleErrors()
|
|
183
|
+
expect(errors.baseErrors).not.toBeEmpty()
|
|
184
|
+
expect(errors.advancedSettingsErrors).toBeEmpty()
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type HiddenFieldComponent,
|
|
3
|
+
type TextFieldComponent
|
|
4
|
+
} from '@defra/forms-model'
|
|
5
|
+
import joi, { type StringSchema } from 'joi'
|
|
6
|
+
|
|
7
|
+
import { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'
|
|
8
|
+
import { TextField } from '~/src/server/plugins/engine/components/TextField.js'
|
|
9
|
+
import { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'
|
|
10
|
+
import {
|
|
11
|
+
type ErrorMessageTemplateList,
|
|
12
|
+
type FormState,
|
|
13
|
+
type FormStateValue,
|
|
14
|
+
type FormSubmissionState
|
|
15
|
+
} from '~/src/server/plugins/engine/types.js'
|
|
16
|
+
|
|
17
|
+
export class HiddenField extends FormComponent {
|
|
18
|
+
declare formSchema: StringSchema
|
|
19
|
+
declare stateSchema: StringSchema
|
|
20
|
+
declare schema: TextFieldComponent['schema']
|
|
21
|
+
declare options: TextFieldComponent['options']
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
def: HiddenFieldComponent,
|
|
25
|
+
props: ConstructorParameters<typeof FormComponent>[1]
|
|
26
|
+
) {
|
|
27
|
+
super(def, props)
|
|
28
|
+
|
|
29
|
+
const { options } = def
|
|
30
|
+
|
|
31
|
+
let formSchema = joi.string().trim().label(this.label).required()
|
|
32
|
+
|
|
33
|
+
if (options.required === false) {
|
|
34
|
+
formSchema = formSchema.allow('')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.formSchema = formSchema.default('')
|
|
38
|
+
this.stateSchema = formSchema.default(null).allow(null)
|
|
39
|
+
this.schema = {}
|
|
40
|
+
this.options = {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getFormValueFromState(state: FormSubmissionState) {
|
|
44
|
+
const { name } = this
|
|
45
|
+
return this.getFormValue(state[name])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
isValue(value?: FormStateValue | FormState): value is string {
|
|
49
|
+
return TextField.isText(value)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* For error preview page that shows all possible errors on a component
|
|
54
|
+
*/
|
|
55
|
+
getAllPossibleErrors(): ErrorMessageTemplateList {
|
|
56
|
+
return HiddenField.getAllPossibleErrors()
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Static version of getAllPossibleErrors that doesn't require a component instance.
|
|
61
|
+
*/
|
|
62
|
+
static getAllPossibleErrors(): ErrorMessageTemplateList {
|
|
63
|
+
return {
|
|
64
|
+
baseErrors: [{ type: 'required', template: messageTemplate.required }],
|
|
65
|
+
advancedSettingsErrors: []
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -34,6 +34,7 @@ export type Field = InstanceType<
|
|
|
34
34
|
| typeof Components.TextField
|
|
35
35
|
| typeof Components.UkAddressField
|
|
36
36
|
| typeof Components.FileUploadField
|
|
37
|
+
| typeof Components.HiddenField
|
|
37
38
|
>
|
|
38
39
|
|
|
39
40
|
// Guidance component instances only
|
|
@@ -186,6 +187,10 @@ export function createComponent(
|
|
|
186
187
|
case ComponentType.LatLongField:
|
|
187
188
|
component = new Components.LatLongField(def, options)
|
|
188
189
|
break
|
|
190
|
+
|
|
191
|
+
case ComponentType.HiddenField:
|
|
192
|
+
component = new Components.HiddenField(def, options)
|
|
193
|
+
break
|
|
189
194
|
}
|
|
190
195
|
|
|
191
196
|
if (typeof component === 'undefined') {
|
|
@@ -2,6 +2,7 @@ import { ComponentType, type ComponentDef } from '@defra/forms-model'
|
|
|
2
2
|
|
|
3
3
|
import { ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'
|
|
4
4
|
import { EastingNorthingField } from '~/src/server/plugins/engine/components/EastingNorthingField.js'
|
|
5
|
+
import { HiddenField } from '~/src/server/plugins/engine/components/HiddenField.js'
|
|
5
6
|
import { LatLongField } from '~/src/server/plugins/engine/components/LatLongField.js'
|
|
6
7
|
import { NationalGridFieldNumberField } from '~/src/server/plugins/engine/components/NationalGridFieldNumberField.js'
|
|
7
8
|
import { OsGridRefField } from '~/src/server/plugins/engine/components/OsGridRefField.js'
|
|
@@ -96,6 +97,22 @@ describe('helpers tests', () => {
|
|
|
96
97
|
expect(component.name).toBe('testField')
|
|
97
98
|
expect(component.title).toBe('Test National Grid')
|
|
98
99
|
})
|
|
100
|
+
|
|
101
|
+
test('should create HiddenField component', () => {
|
|
102
|
+
const component = createComponent(
|
|
103
|
+
{
|
|
104
|
+
type: ComponentType.HiddenField,
|
|
105
|
+
name: 'hiddenField',
|
|
106
|
+
title: 'Hidden field',
|
|
107
|
+
options: {}
|
|
108
|
+
},
|
|
109
|
+
{ model: formModel }
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
expect(component).toBeInstanceOf(HiddenField)
|
|
113
|
+
expect(component.name).toBe('hiddenField')
|
|
114
|
+
expect(component.title).toBe('Hidden field')
|
|
115
|
+
})
|
|
99
116
|
})
|
|
100
117
|
|
|
101
118
|
describe('ComponentBase tests', () => {
|
|
@@ -28,3 +28,4 @@ export { EastingNorthingField } from '~/src/server/plugins/engine/components/Eas
|
|
|
28
28
|
export { OsGridRefField } from '~/src/server/plugins/engine/components/OsGridRefField.js'
|
|
29
29
|
export { NationalGridFieldNumberField } from '~/src/server/plugins/engine/components/NationalGridFieldNumberField.js'
|
|
30
30
|
export { LatLongField } from '~/src/server/plugins/engine/components/LatLongField.js'
|
|
31
|
+
export { HiddenField } from '~/src/server/plugins/engine/components/HiddenField.js'
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from '~/src/server/plugins/engine/components/helpers/components.js'
|
|
23
23
|
import { type FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
|
|
24
24
|
import { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'
|
|
25
|
+
import { stripParam } from '~/src/server/plugins/engine/pageControllers/helpers/state.js'
|
|
25
26
|
import {
|
|
26
27
|
type AnyFormRequest,
|
|
27
28
|
type FormContext,
|
|
@@ -133,7 +134,7 @@ export function proceed(
|
|
|
133
134
|
const response =
|
|
134
135
|
isReturnAllowed && isPathRelative(returnUrl)
|
|
135
136
|
? h.redirect(returnUrl)
|
|
136
|
-
: h.redirect(redirectPath(nextUrl))
|
|
137
|
+
: h.redirect(redirectPath(nextUrl, stripParam(query, 'returnUrl')))
|
|
137
138
|
|
|
138
139
|
// Redirect POST to GET to avoid resubmission
|
|
139
140
|
return method === 'post'
|
|
@@ -74,6 +74,7 @@ export class FormModel {
|
|
|
74
74
|
lists: FormDefinition['lists']
|
|
75
75
|
sections: FormDefinition['sections'] = []
|
|
76
76
|
name: string
|
|
77
|
+
formId: string
|
|
77
78
|
values: FormDefinition
|
|
78
79
|
basePath: string
|
|
79
80
|
versionNumber?: number
|
|
@@ -100,6 +101,7 @@ export class FormModel {
|
|
|
100
101
|
basePath: string
|
|
101
102
|
versionNumber?: number
|
|
102
103
|
ordnanceSurveyApiKey?: string
|
|
104
|
+
formId?: string
|
|
103
105
|
},
|
|
104
106
|
services: Services = defaultServices,
|
|
105
107
|
controllers?: Record<string, typeof PageController>
|
|
@@ -152,6 +154,7 @@ export class FormModel {
|
|
|
152
154
|
this.lists = def.lists
|
|
153
155
|
this.sections = def.sections
|
|
154
156
|
this.name = def.name ?? ''
|
|
157
|
+
this.formId = options.formId ?? ''
|
|
155
158
|
this.values = result.value
|
|
156
159
|
this.basePath = options.basePath
|
|
157
160
|
this.versionNumber = options.versionNumber
|
|
@@ -24,7 +24,8 @@ describe('PageController', () => {
|
|
|
24
24
|
const page2 = pages[1]
|
|
25
25
|
|
|
26
26
|
model = new FormModel(definition, {
|
|
27
|
-
basePath: testBasePath
|
|
27
|
+
basePath: testBasePath,
|
|
28
|
+
formId: 'form-id'
|
|
28
29
|
})
|
|
29
30
|
|
|
30
31
|
controller1 = new PageController(model, page1)
|
|
@@ -61,18 +62,10 @@ describe('PageController', () => {
|
|
|
61
62
|
})
|
|
62
63
|
})
|
|
63
64
|
|
|
64
|
-
it('returns feedback link
|
|
65
|
-
expect(controller1).toHaveProperty('feedbackLink', undefined)
|
|
66
|
-
|
|
67
|
-
const emailAddress = 'test@feedback.cat'
|
|
68
|
-
|
|
69
|
-
model.def.feedback = {
|
|
70
|
-
emailAddress
|
|
71
|
-
}
|
|
72
|
-
|
|
65
|
+
it('returns feedback link default', () => {
|
|
73
66
|
expect(controller1).toHaveProperty(
|
|
74
67
|
'feedbackLink',
|
|
75
|
-
|
|
68
|
+
'/form/feedback?formId=form-id'
|
|
76
69
|
)
|
|
77
70
|
})
|
|
78
71
|
|
|
@@ -10,7 +10,6 @@ import { type Lifecycle, type RouteOptions, type Server } from '@hapi/hapi'
|
|
|
10
10
|
|
|
11
11
|
import { type ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
|
|
12
12
|
import {
|
|
13
|
-
encodeUrl,
|
|
14
13
|
getSaveAndExitHelpers,
|
|
15
14
|
getStartPath,
|
|
16
15
|
normalisePath
|
|
@@ -119,14 +118,7 @@ export class PageController {
|
|
|
119
118
|
}
|
|
120
119
|
|
|
121
120
|
get feedbackLink() {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// setting the feedbackLink to undefined here for feedback forms prevents the feedback link from being shown
|
|
125
|
-
const feedbackLink = def.feedback?.emailAddress
|
|
126
|
-
? `mailto:${def.feedback.emailAddress}`
|
|
127
|
-
: def.feedback?.url
|
|
128
|
-
|
|
129
|
-
return encodeUrl(feedbackLink)
|
|
121
|
+
return `/form/feedback?formId=${this.model.formId}`
|
|
130
122
|
}
|
|
131
123
|
|
|
132
124
|
get phaseTag() {
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
} from '~/src/server/plugins/engine/helpers.js'
|
|
29
29
|
import { type FormModel } from '~/src/server/plugins/engine/models/index.js'
|
|
30
30
|
import { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'
|
|
31
|
+
import { prefillStateFromQueryParameters } from '~/src/server/plugins/engine/pageControllers/helpers/state.js'
|
|
31
32
|
import {
|
|
32
33
|
type AnyFormRequest,
|
|
33
34
|
type FormContext,
|
|
@@ -403,6 +404,12 @@ export class QuestionPageController extends PageController {
|
|
|
403
404
|
const { collection, model, viewName } = this
|
|
404
405
|
const { evaluationState } = context
|
|
405
406
|
|
|
407
|
+
// Copy any URL params into the form state (if not already done so)
|
|
408
|
+
if (await prefillStateFromQueryParameters(request, this)) {
|
|
409
|
+
// Forward to same page without query string
|
|
410
|
+
return h.redirect(`${request.url.origin}${request.url.pathname}`)
|
|
411
|
+
}
|
|
412
|
+
|
|
406
413
|
const viewModel = this.getViewModel(request, context)
|
|
407
414
|
viewModel.errors = collection.getViewErrors(viewModel.errors)
|
|
408
415
|
|
|
@@ -41,13 +41,20 @@ export class StatusPageController extends QuestionPageController {
|
|
|
41
41
|
|
|
42
42
|
const slug = request.params.slug
|
|
43
43
|
const { formsService } = this.model.services
|
|
44
|
-
const { getFormMetadata } = formsService
|
|
44
|
+
const { getFormMetadata, getFormMetadataById } = formsService
|
|
45
45
|
|
|
46
46
|
const { submissionGuidance } = await getFormMetadata(slug)
|
|
47
47
|
|
|
48
|
+
// Re-read form name if overriding display (for example, in a feedback form)
|
|
49
|
+
const storedFormId = confirmationState.formId
|
|
50
|
+
const formName = storedFormId
|
|
51
|
+
? (await getFormMetadataById(storedFormId)).title
|
|
52
|
+
: undefined
|
|
53
|
+
|
|
48
54
|
return h.view(viewName, {
|
|
49
55
|
...viewModel,
|
|
50
|
-
submissionGuidance
|
|
56
|
+
submissionGuidance,
|
|
57
|
+
formName
|
|
51
58
|
})
|
|
52
59
|
}
|
|
53
60
|
}
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from '~/src/server/plugins/engine/models/types.js'
|
|
26
26
|
import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
|
|
27
27
|
import {
|
|
28
|
+
type FormConfirmationState,
|
|
28
29
|
type FormContext,
|
|
29
30
|
type FormContextRequest,
|
|
30
31
|
type FormSubmissionState
|
|
@@ -152,7 +153,10 @@ export class SummaryPageController extends QuestionPageController {
|
|
|
152
153
|
)
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
await cacheService.setConfirmationState(request, {
|
|
156
|
+
await cacheService.setConfirmationState(request, {
|
|
157
|
+
confirmed: true,
|
|
158
|
+
formId: context.state.formId
|
|
159
|
+
} as FormConfirmationState)
|
|
156
160
|
|
|
157
161
|
// Clear all form data
|
|
158
162
|
await cacheService.clearState(request)
|