@gov-cy/govcy-express-services 0.1.1
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/LICENSE +21 -0
- package/README.md +1157 -0
- package/package.json +72 -0
- package/src/auth/cyLoginAuth.mjs +123 -0
- package/src/index.mjs +188 -0
- package/src/middleware/cyLoginAuth.mjs +131 -0
- package/src/middleware/govcyConfigSiteData.mjs +38 -0
- package/src/middleware/govcyCsrf.mjs +36 -0
- package/src/middleware/govcyFormsPostHandler.mjs +83 -0
- package/src/middleware/govcyHeadersControl.mjs +22 -0
- package/src/middleware/govcyHttpErrorHandler.mjs +63 -0
- package/src/middleware/govcyLanguageMiddleware.mjs +19 -0
- package/src/middleware/govcyLogger.mjs +15 -0
- package/src/middleware/govcyManifestHandler.mjs +46 -0
- package/src/middleware/govcyPDFRender.mjs +30 -0
- package/src/middleware/govcyPageHandler.mjs +110 -0
- package/src/middleware/govcyPageRender.mjs +14 -0
- package/src/middleware/govcyRequestTimer.mjs +29 -0
- package/src/middleware/govcyReviewPageHandler.mjs +102 -0
- package/src/middleware/govcyReviewPostHandler.mjs +147 -0
- package/src/middleware/govcyRoutePageHandler.mjs +37 -0
- package/src/middleware/govcyServiceEligibilityHandler.mjs +101 -0
- package/src/middleware/govcySessionData.mjs +9 -0
- package/src/middleware/govcySuccessPageHandler.mjs +112 -0
- package/src/public/img/Certificate_A4.svg +30 -0
- package/src/public/js/govcyForms.js +21 -0
- package/src/resources/govcyResources.mjs +430 -0
- package/src/standalone.mjs +7 -0
- package/src/utils/govcyApiRequest.mjs +114 -0
- package/src/utils/govcyConstants.mjs +4 -0
- package/src/utils/govcyDataLayer.mjs +311 -0
- package/src/utils/govcyEnvVariables.mjs +45 -0
- package/src/utils/govcyFormHandling.mjs +148 -0
- package/src/utils/govcyLoadConfigData.mjs +135 -0
- package/src/utils/govcyLogger.mjs +30 -0
- package/src/utils/govcyNotification.mjs +85 -0
- package/src/utils/govcyPdfMaker.mjs +27 -0
- package/src/utils/govcyReviewSummary.mjs +205 -0
- package/src/utils/govcySubmitData.mjs +530 -0
- package/src/utils/govcyUtils.mjs +13 -0
- package/src/utils/govcyValidator.mjs +352 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
|
|
2
|
+
import * as govcyResources from "../resources/govcyResources.mjs";
|
|
3
|
+
import * as dataLayer from "./govcyDataLayer.mjs";
|
|
4
|
+
import { DSFEmailRenderer } from '@gov-cy/dsf-email-templates';
|
|
5
|
+
import { ALLOWED_FORM_ELEMENTS } from "./govcyConstants.mjs";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Prepares the submission data for the service, including raw data, print-friendly data, and renderer data.
|
|
9
|
+
*
|
|
10
|
+
* @param {object} req The request object containing session data
|
|
11
|
+
* @param {string} siteId The site ID
|
|
12
|
+
* @param {object} service The service object containing site and page data
|
|
13
|
+
* @returns {object} The submission data object containing raw data, print-friendly data, and renderer data
|
|
14
|
+
*/
|
|
15
|
+
export function prepareSubmissionData(req, siteId, service) {
|
|
16
|
+
// Get the raw data from the session store
|
|
17
|
+
const rawData = dataLayer.getSiteInputData(req.session, siteId);
|
|
18
|
+
|
|
19
|
+
// Get the print-friendly data from the session store
|
|
20
|
+
const printFriendlyData = preparePrintFriendlyData(req, siteId, service);
|
|
21
|
+
|
|
22
|
+
// Get the renderer data from the session store
|
|
23
|
+
const reviewSummaryList = generateReviewSummary(printFriendlyData, req, siteId, false);
|
|
24
|
+
|
|
25
|
+
// Prepare the submission data object
|
|
26
|
+
return {
|
|
27
|
+
submission_username: dataLayer.getUser(req.session).name,
|
|
28
|
+
submission_email: dataLayer.getUser(req.session).email,
|
|
29
|
+
submission_data: rawData, // Raw data as submitted by the user in each page
|
|
30
|
+
submission_data_version: service.site?.submission_data_version || "", // The submission data version
|
|
31
|
+
print_friendly_data: printFriendlyData, // Print-friendly data
|
|
32
|
+
renderer_data: reviewSummaryList, // Renderer data of the summary list
|
|
33
|
+
renderer_version: service.site?.renderer_version || "", // The renderer version
|
|
34
|
+
design_systems_version: service.site?.design_systems_version || "", // The design systems version
|
|
35
|
+
service: { // Service info
|
|
36
|
+
id: service.site.id, // Service ID
|
|
37
|
+
title: service.site.title // Service title multilingual object
|
|
38
|
+
},
|
|
39
|
+
referenceNumber: "", // Reference number
|
|
40
|
+
// timestamp: new Date().toISOString(), // Timestamp `new Date().toISOString();`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Prepares the submission data for the API, stringifying all relevant fields.
|
|
46
|
+
*
|
|
47
|
+
* @param {object} data data prepared by `prepareSubmissionData`
|
|
48
|
+
* @returns {object} The API-ready submission data object with all fields as strings
|
|
49
|
+
*/
|
|
50
|
+
export function prepareSubmissionDataAPI(data) {
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
submission_username: String(data.submission_username ?? ""),
|
|
54
|
+
submission_email: String(data.submission_email ?? ""),
|
|
55
|
+
submission_data: JSON.stringify(data.submission_data ?? {}),
|
|
56
|
+
submission_data_version: String(data.submission_data_version ?? ""),
|
|
57
|
+
print_friendly_data: JSON.stringify(data.print_friendly_data ?? []),
|
|
58
|
+
renderer_data: JSON.stringify(data.renderer_data ?? {}),
|
|
59
|
+
renderer_version: String(data.renderer_version ?? ""),
|
|
60
|
+
design_systems_version: String(data.design_systems_version ?? ""),
|
|
61
|
+
service: JSON.stringify(data.service ?? {})
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Prepares the print-friendly data for the service, including page data and field labels.
|
|
67
|
+
*
|
|
68
|
+
* @param {object} req The request object containing session data
|
|
69
|
+
* @param {string} siteId The site ID
|
|
70
|
+
* @param {object} service The service object containing site and page data
|
|
71
|
+
* @returns The print-friendly data for the service, including page data and field labels.
|
|
72
|
+
*/
|
|
73
|
+
export function preparePrintFriendlyData(req, siteId, service) {
|
|
74
|
+
const submissionData = [];
|
|
75
|
+
|
|
76
|
+
const allowedElements = ALLOWED_FORM_ELEMENTS;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Helper function to retrieve date raw input.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} pageUrl The page URL
|
|
82
|
+
* @param {string} name The name of the form element
|
|
83
|
+
* @returns {string} The raw date input in ISO format (YYYY-MM-DD) or an empty string if not found
|
|
84
|
+
*/
|
|
85
|
+
function getDateInputISO(pageUrl, name) {
|
|
86
|
+
const day = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_day`);
|
|
87
|
+
const month = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_month`);
|
|
88
|
+
const year = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_year`);
|
|
89
|
+
if (!day || !month || !year) return "";
|
|
90
|
+
|
|
91
|
+
// Pad day and month with leading zero if needed
|
|
92
|
+
const paddedDay = String(day).padStart(2, "0");
|
|
93
|
+
const paddedMonth = String(month).padStart(2, "0");
|
|
94
|
+
|
|
95
|
+
return `${year}-${paddedMonth}-${paddedDay}`; // ISO format: YYYY-MM-DD
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Helper function to retrieve date input in DMY format.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} pageUrl The page URL
|
|
102
|
+
* @param {string} name The name of the form element
|
|
103
|
+
* @returns {string} The raw date input in DMY format (DD/MM/YYYY) or an empty string if not found
|
|
104
|
+
*/
|
|
105
|
+
function getDateInputDMY(pageUrl, name) {
|
|
106
|
+
const day = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_day`);
|
|
107
|
+
const month = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_month`);
|
|
108
|
+
const year = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_year`);
|
|
109
|
+
if (!day || !month || !year) return "";
|
|
110
|
+
return `${day}/${month}/${year}`; // EU format: DD/MM/YYYY
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Helper function to create a field object.
|
|
115
|
+
*
|
|
116
|
+
* @param {object} formElement The form element object
|
|
117
|
+
* @param {string} value The value of the form element
|
|
118
|
+
* @param {object} valueLabel The label of the form element
|
|
119
|
+
* @returns {object} The field object containing id, label, value, and valueLabel
|
|
120
|
+
*/
|
|
121
|
+
function createFieldObject(formElement, value, valueLabel) {
|
|
122
|
+
return {
|
|
123
|
+
id: formElement.params?.id || "",
|
|
124
|
+
name: formElement.params?.name || "",
|
|
125
|
+
label: formElement.params.label
|
|
126
|
+
|| formElement.params.legend
|
|
127
|
+
|| govcyResources.getSameMultilingualObject(service.site.languages, formElement.params.name),
|
|
128
|
+
value: value,
|
|
129
|
+
valueLabel: valueLabel
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Helper function to retrieve the value of a form element from the session.
|
|
135
|
+
*
|
|
136
|
+
* @param {object} formElement The form element object
|
|
137
|
+
* @param {string} pageUrl The page URL
|
|
138
|
+
* @returns {string} The value of the form element from the session or an empty string if not found
|
|
139
|
+
*/
|
|
140
|
+
function getValue(formElement, pageUrl) {
|
|
141
|
+
// handle raw value
|
|
142
|
+
let value = ""
|
|
143
|
+
if (formElement.element === "dateInput") {
|
|
144
|
+
value = getDateInputISO(pageUrl, formElement.params.name);
|
|
145
|
+
} else {
|
|
146
|
+
value = dataLayer.getFormDataValue(req.session, siteId, pageUrl, formElement.params.name);
|
|
147
|
+
}
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Helper function to get the label of a form element based on its value and type.
|
|
153
|
+
*
|
|
154
|
+
* @param {object} formElement The form element object
|
|
155
|
+
* @param {string} value The value of the form element
|
|
156
|
+
* @param {string} pageUrl The page URL
|
|
157
|
+
* @returns {object} The label of the form element based on the value and element type
|
|
158
|
+
*/
|
|
159
|
+
function getValueLabel(formElement, value, pageUrl) {
|
|
160
|
+
//handle checkboxes label
|
|
161
|
+
if (formElement.element === "checkboxes") {
|
|
162
|
+
if (Array.isArray(value)) {
|
|
163
|
+
// loop through each value and find the corresponding item
|
|
164
|
+
return value.map(v => {
|
|
165
|
+
// find the item
|
|
166
|
+
const item = formElement.params.items.find(i => i.value === v);
|
|
167
|
+
return item?.text || govcyResources.getSameMultilingualObject(service.site.languages, "");
|
|
168
|
+
});
|
|
169
|
+
} else if (typeof value === "string") {
|
|
170
|
+
const matchedItem = formElement.params.items.find(item => item.value === value);
|
|
171
|
+
if (matchedItem) {
|
|
172
|
+
return matchedItem.text;
|
|
173
|
+
} else {
|
|
174
|
+
return govcyResources.getSameMultilingualObject(service.site.languages, "")
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// handle radios and select labels
|
|
180
|
+
if (formElement.element === "radios" || formElement.element === "select") {
|
|
181
|
+
const item = formElement.params.items.find(i => i.value === value);
|
|
182
|
+
return item?.text || govcyResources.getSameMultilingualObject(service.site.languages, "");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// handle dateInput
|
|
186
|
+
if (formElement.element === "dateInput") {
|
|
187
|
+
const formattedDate = getDateInputDMY(pageUrl, formElement.params.name);
|
|
188
|
+
return govcyResources.getSameMultilingualObject(service.site.languages, formattedDate);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// textInput, textArea, etc.
|
|
192
|
+
return govcyResources.getSameMultilingualObject(service.site.languages, value);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// loop through each page in the service
|
|
196
|
+
// and extract the form data from the session
|
|
197
|
+
for (const page of service.pages) {
|
|
198
|
+
const fields = [];
|
|
199
|
+
// const currentPageUrl = page.pageData.url;
|
|
200
|
+
|
|
201
|
+
// find the form element in the page template
|
|
202
|
+
for (const section of page.pageTemplate.sections || []) {
|
|
203
|
+
for (const element of section.elements || []) {
|
|
204
|
+
if (element.element !== "form") continue;
|
|
205
|
+
|
|
206
|
+
// loop through each form element and get the data from the session
|
|
207
|
+
for (const formElement of element.params.elements || []) {
|
|
208
|
+
if (!allowedElements.includes(formElement.element)) continue;
|
|
209
|
+
|
|
210
|
+
// handle raw value
|
|
211
|
+
let rawValue = getValue(formElement, page.pageData.url);
|
|
212
|
+
|
|
213
|
+
//create the field object and push it to the fields array
|
|
214
|
+
// value of the field is handled by getValueLabel function
|
|
215
|
+
const field = createFieldObject(formElement, rawValue, getValueLabel(formElement, rawValue, page.pageData.url));
|
|
216
|
+
fields.push(field);
|
|
217
|
+
|
|
218
|
+
// Handle conditional elements (only for radios for now)
|
|
219
|
+
if (formElement.element === "radios") {
|
|
220
|
+
//find the selected radio based on the raw value
|
|
221
|
+
const selectedRadio = formElement.params.items.find(i => i.value === rawValue);
|
|
222
|
+
//check if the selected radio has conditional elements
|
|
223
|
+
if (selectedRadio?.conditionalElements) {
|
|
224
|
+
//loop through each conditional element and get the data
|
|
225
|
+
for (const condEl of selectedRadio.conditionalElements) {
|
|
226
|
+
if (!allowedElements.includes(condEl.element)) continue;
|
|
227
|
+
|
|
228
|
+
// handle raw value
|
|
229
|
+
let condValue = getValue(condEl, page.pageData.url);
|
|
230
|
+
|
|
231
|
+
//create the field object and push it to the fields array
|
|
232
|
+
// value of the field is handled by getValueLabel function
|
|
233
|
+
const field = createFieldObject(condEl, condValue, getValueLabel(condEl, condValue, page.pageData.url));
|
|
234
|
+
fields.push(field);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (fields.length > 0) {
|
|
243
|
+
submissionData.push({
|
|
244
|
+
pageUrl: page.pageData.url,
|
|
245
|
+
pageTitle: page.pageData.title,
|
|
246
|
+
fields
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return submissionData ;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//------------------------------- Helper Functions -------------------------------//
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Helper function to get the item value of checkboxes based on the selected value.
|
|
258
|
+
* @param {object} valueLabel the value
|
|
259
|
+
* @param {string} lang the language
|
|
260
|
+
* @returns {string} the item value of checkboxes
|
|
261
|
+
*/
|
|
262
|
+
function getSubmissionValueLabelString(valueLabel, lang, fallbackLang = "en") {
|
|
263
|
+
if (!valueLabel) return "";
|
|
264
|
+
|
|
265
|
+
// Helper to get the desired language string or fallback
|
|
266
|
+
const getText = (obj) =>
|
|
267
|
+
obj?.[lang]?.trim() || obj?.[fallbackLang]?.trim() || "";
|
|
268
|
+
|
|
269
|
+
// Case 1: Array of multilingual objects
|
|
270
|
+
if (Array.isArray(valueLabel)) {
|
|
271
|
+
return valueLabel
|
|
272
|
+
.map(getText) // get lang/fallback string for each item
|
|
273
|
+
.filter(Boolean) // remove empty strings
|
|
274
|
+
.join(", "); // join with comma
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Case 2: Single multilingual object
|
|
278
|
+
if (typeof valueLabel === "object") {
|
|
279
|
+
return getText(valueLabel);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Graceful fallback
|
|
283
|
+
return "";
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//------------------------------- Review Summary -------------------------------//
|
|
287
|
+
/**
|
|
288
|
+
* Generates a review summary for the submission data, ready to be rendered.
|
|
289
|
+
*
|
|
290
|
+
* @param {object} submissionData The submission data object containing page data and fields
|
|
291
|
+
* @param {object} req The request object containing global language and session data
|
|
292
|
+
* @param {string} siteId The site ID
|
|
293
|
+
* @param {boolean} showChangeLinks Flag to show change links or not
|
|
294
|
+
* @returns {object} The review summary to be rendered by the renderer
|
|
295
|
+
*/
|
|
296
|
+
export function generateReviewSummary(submissionData, req, siteId, showChangeLinks = true) {
|
|
297
|
+
// Base summary list structure
|
|
298
|
+
let summaryList = { element: "summaryList", params: { items: [] } };
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Helper function to create a summary list item.
|
|
302
|
+
* @param {object} key the key of multilingual object
|
|
303
|
+
* @param {string} value the value
|
|
304
|
+
* @returns {object} the summary list item
|
|
305
|
+
*/
|
|
306
|
+
function createSummaryListItem(key, value) {
|
|
307
|
+
return {
|
|
308
|
+
"key": key,
|
|
309
|
+
"value": [
|
|
310
|
+
{
|
|
311
|
+
"element": "textElement",
|
|
312
|
+
"params": {
|
|
313
|
+
"text": { "en": value, "el": value, "tr": value },
|
|
314
|
+
"type": "span"
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
// Loop through each page in the submission data
|
|
325
|
+
for (const page of submissionData) {
|
|
326
|
+
// Get the page URL, title, and fields
|
|
327
|
+
const { pageUrl, pageTitle, fields } = page;
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
let summaryListInner = { element: "summaryList", params: { items: [] } };
|
|
331
|
+
|
|
332
|
+
// loop through each field and add it to the summary entry
|
|
333
|
+
for (const field of fields) {
|
|
334
|
+
const label = field.label;
|
|
335
|
+
const valueLabel = getSubmissionValueLabelString(field.valueLabel, req.globalLang);
|
|
336
|
+
// add the field to the summary entry
|
|
337
|
+
summaryListInner.params.items.push(createSummaryListItem(label, valueLabel));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Add inner summary list to the main summary list
|
|
341
|
+
let outerSummaryList = {
|
|
342
|
+
"key": pageTitle,
|
|
343
|
+
"value": [summaryListInner],
|
|
344
|
+
"actions": [ //add change link
|
|
345
|
+
{
|
|
346
|
+
text: govcyResources.staticResources.text.change,
|
|
347
|
+
classes: govcyResources.staticResources.other.noPrintClass,
|
|
348
|
+
href: govcyResources.constructPageUrl(siteId, pageUrl, "review"),
|
|
349
|
+
visuallyHiddenText: pageTitle
|
|
350
|
+
}
|
|
351
|
+
]
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// If showChangeLinks is false, remove the change link
|
|
355
|
+
if (!showChangeLinks) {
|
|
356
|
+
delete outerSummaryList.actions;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
//push to the main summary list
|
|
360
|
+
summaryList.params.items.push(outerSummaryList);
|
|
361
|
+
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return summaryList;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
//------------------------------- Email Generation -------------------------------//
|
|
369
|
+
/**
|
|
370
|
+
* Generates an email HTML body for the submission data, ready to be sent.
|
|
371
|
+
*
|
|
372
|
+
* @param {object} service The service object
|
|
373
|
+
* @param {object} submissionData The submission data object containing page data and fields
|
|
374
|
+
* @param {string} submissionId The submission id
|
|
375
|
+
* @param {object} req The request object containing global language and session data
|
|
376
|
+
* @returns {string} The email HTML body
|
|
377
|
+
*/
|
|
378
|
+
export function generateSubmitEmail(service, submissionData, submissionId, req) {
|
|
379
|
+
let body = [];
|
|
380
|
+
|
|
381
|
+
//check if there is submission Id
|
|
382
|
+
if (submissionId) {
|
|
383
|
+
// Add success message to the body
|
|
384
|
+
body.push(
|
|
385
|
+
{
|
|
386
|
+
component: "bodySuccess",
|
|
387
|
+
params: {
|
|
388
|
+
title: govcyResources.getLocalizeContent(govcyResources.staticResources.text.submissionSuccessTitle, req.globalLang),
|
|
389
|
+
body: `${govcyResources.getLocalizeContent(govcyResources.staticResources.text.yourSubmissionId, req.globalLang)} ${submissionId}`
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Add data title to the body
|
|
396
|
+
body.push(
|
|
397
|
+
{
|
|
398
|
+
component: "bodyParagraph",
|
|
399
|
+
body: govcyResources.getLocalizeContent(govcyResources.staticResources.text.theDataFromYourRequest, req.globalLang)
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
// For each page in the submission data
|
|
404
|
+
for (const page of submissionData) {
|
|
405
|
+
// Get the page URL, title, and fields
|
|
406
|
+
const { pageUrl, pageTitle, fields } = page;
|
|
407
|
+
|
|
408
|
+
// Add data title to the body
|
|
409
|
+
body.push(
|
|
410
|
+
{
|
|
411
|
+
component: "bodyHeading",
|
|
412
|
+
params: {"headingLevel":2},
|
|
413
|
+
body: govcyResources.getLocalizeContent(pageTitle, req.globalLang)
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
let dataUl = [];
|
|
418
|
+
// loop through each field and add it to the summary entry
|
|
419
|
+
for (const field of fields) {
|
|
420
|
+
const label = govcyResources.getLocalizeContent(field.label, req.globalLang);
|
|
421
|
+
const valueLabel = getSubmissionValueLabelString(field.valueLabel, req.globalLang);
|
|
422
|
+
dataUl.push({key: label, value: valueLabel});
|
|
423
|
+
}
|
|
424
|
+
// add data to the body
|
|
425
|
+
body.push(
|
|
426
|
+
{
|
|
427
|
+
component: "bodyKeyValue",
|
|
428
|
+
params: {type:"ul", items: dataUl},
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
let emailObject = govcyResources.getEmailObject(
|
|
434
|
+
service.site.title,
|
|
435
|
+
govcyResources.staticResources.text.emailSubmissionPreHeader,
|
|
436
|
+
service.site.title,
|
|
437
|
+
dataLayer.getUser(req.session).name,
|
|
438
|
+
body,
|
|
439
|
+
service.site.title,
|
|
440
|
+
req.globalLang
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
// Create an instance of DSFEmailRenderer
|
|
444
|
+
const emailRenderer = new DSFEmailRenderer();
|
|
445
|
+
return emailRenderer.renderFromJson(emailObject);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
/*
|
|
451
|
+
{
|
|
452
|
+
"bank-details": {
|
|
453
|
+
"formData": {
|
|
454
|
+
"AccountName": "asd",
|
|
455
|
+
"Iban": "CY12 0020 0123 0000 0001 2345 6789",
|
|
456
|
+
"Swift": "BANKCY2NXXX",
|
|
457
|
+
"_csrf": "sjknv79rxjgv0uggo0d5312vzgz37jsh"
|
|
458
|
+
}
|
|
459
|
+
},
|
|
460
|
+
"answer-bank-boc": {
|
|
461
|
+
"formData": {
|
|
462
|
+
"Objection": "Object",
|
|
463
|
+
"country": "Azerbaijan",
|
|
464
|
+
"ObjectionReason": "ObjectionReasonCode1",
|
|
465
|
+
"ObjectionExplanation": "asdsa",
|
|
466
|
+
"DepositsBOCAttachment": "",
|
|
467
|
+
"_csrf": "sjknv79rxjgv0uggo0d5312vzgz37jsh"
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
"bank-settlement": {
|
|
471
|
+
"formData": {
|
|
472
|
+
"ReceiveSettlementExplanation": "",
|
|
473
|
+
"ReceiveSettlementDate_day": "",
|
|
474
|
+
"ReceiveSettlementDate_month": "",
|
|
475
|
+
"ReceiveSettlementDate_year": "",
|
|
476
|
+
"ReceiveSettlement": "no",
|
|
477
|
+
"_csrf": "sjknv79rxjgv0uggo0d5312vzgz37jsh"
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
[
|
|
485
|
+
{
|
|
486
|
+
pageUrl: "personal-details",
|
|
487
|
+
pageTitle: { en: "Personal data", el: "Προσωπικά στοιχεία" }, // from pageData.title in correct language
|
|
488
|
+
fields: [
|
|
489
|
+
[
|
|
490
|
+
{
|
|
491
|
+
id: "firstName",
|
|
492
|
+
label: { en: "First Name", el: "Όνομα" },
|
|
493
|
+
value: "John", // The actual user input value
|
|
494
|
+
valueLabel: { en: "John", el: "John" } // Same label as the value for text inputs
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
id: "lastName",
|
|
498
|
+
label: { en: "Last Name", el: "Επίθετο" },
|
|
499
|
+
value: "Doe", // The actual user input value
|
|
500
|
+
valueLabel: { en: "Doe", el: "Doe" } // Same label as the value for text inputs
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
id: "gender",
|
|
504
|
+
label: { en: "Gender", el: "Φύλο" },
|
|
505
|
+
value: "m", // The actual value ("male")
|
|
506
|
+
valueLabel: { en: "Male", el: "Άντρας" } // The corresponding label for "male"
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
id: "languages",
|
|
510
|
+
label: { en: "Languages", el: "Γλώσσες" },
|
|
511
|
+
value: ["en", "el"], // The selected values ["en", "el"]
|
|
512
|
+
valueLabel: [
|
|
513
|
+
{ en: "English", el: "Αγγλικά" }, // Labels corresponding to "en" and "el"
|
|
514
|
+
{ en: "Greek", el: "Ελληνικά" }
|
|
515
|
+
]
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
id: "birthDate",
|
|
519
|
+
label: { en: "Birth Date", el: "Ημερομηνία Γέννησης" },
|
|
520
|
+
value: "1990-01-13", // The actual value based on user input
|
|
521
|
+
valueLabel: "13/1/1990" // Date inputs label will be conveted to D/M/YYYY
|
|
522
|
+
}
|
|
523
|
+
]
|
|
524
|
+
},
|
|
525
|
+
...
|
|
526
|
+
]
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
*/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper function to handle errors in middleware.
|
|
3
|
+
* Creates an error object and passes it to the next middleware.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} message - The error message.
|
|
6
|
+
* @param {number} status - The HTTP status code.
|
|
7
|
+
* @param {function} next - The Express `next` function.
|
|
8
|
+
*/
|
|
9
|
+
export function handleMiddlewareError(message, status, next) {
|
|
10
|
+
const error = new Error(message);
|
|
11
|
+
error.status = status;
|
|
12
|
+
return next(error);
|
|
13
|
+
}
|