@gov-cy/govcy-express-services 0.2.11 β 0.2.13
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/README.md
CHANGED
|
@@ -151,7 +151,6 @@ Here are some details explaining the JSON structure:
|
|
|
151
151
|
"en": "https://www.gov.cy/en/service/issue-an-id-card/"
|
|
152
152
|
}
|
|
153
153
|
```
|
|
154
|
-
- `matomo `: The Matomo web analytics configuration details.
|
|
155
154
|
- `eligibilityAPIEndpoints` : An array of API endpoints, to be used for service eligibility. See more on the [Eligibility API Endoints](#%EF%B8%8F-site-eligibility-checks) section below.
|
|
156
155
|
- `submissionAPIEndpoint`: The submission API endpoint, to be used for submitting the form. See more on the [Submission API Endoint](#-site-submissions) section below.
|
|
157
156
|
- `pages` array: An array of page objects, each representing a page in the site.
|
|
@@ -1431,10 +1430,15 @@ The project uses express.js to serve the following routes:
|
|
|
1431
1430
|
Absolutely! Hereβs a **ready-to-paste Troubleshooting / FAQ section** you can add near the end of your README, just before Credits or Developer notes.
|
|
1432
1431
|
|
|
1433
1432
|
### π¨βπ» Enviromental variables
|
|
1434
|
-
The environment variables
|
|
1433
|
+
The environment variables are defined in:
|
|
1434
|
+
- **Secret environment variables**: These are secret variables and MUSR NOT be saved in version control. The are saved locally in the `secrets/.env` file and they control the server configuration, authentication, integrations, and development behavior. These variables vary depending on the environment and are defined through the deployment prosses for `staging` and `production`.
|
|
1435
|
+
- **Non secret environment variables**: These are non secret enviromentat variables and can be saved in version control. These are stored in the root folder of the project:
|
|
1436
|
+
- `.env.development` for local development
|
|
1437
|
+
- `.env.staging` for staging
|
|
1438
|
+
- `.env.production` for production
|
|
1435
1439
|
|
|
1436
|
-
####
|
|
1437
|
-
The following environment variables are used to configure the server:
|
|
1440
|
+
#### Secret environment variables
|
|
1441
|
+
The following secret environment variables are used to configure the server:
|
|
1438
1442
|
|
|
1439
1443
|
```dotenv
|
|
1440
1444
|
# π Session
|
|
@@ -1454,12 +1458,9 @@ DEBUG=true
|
|
|
1454
1458
|
ALLOW_SELF_SIGNED_CERTIFICATES=false
|
|
1455
1459
|
# Allow self-signed SSL certs (e.g. for local development). Set to false in production.
|
|
1456
1460
|
|
|
1457
|
-
|
|
1458
|
-
|
|
1461
|
+
# -----------------------------------------------
|
|
1459
1462
|
#### CY Login environment variables
|
|
1460
|
-
The following environment variables are used to configure CY Login authentication:
|
|
1461
|
-
|
|
1462
|
-
```dotenv
|
|
1463
|
+
# The following environment variables are used to configure CY Login authentication:
|
|
1463
1464
|
CYLOGIN_ISSUER_URL=https://aztest.cyprus.gov.cy/cylogin/core/.well-known/openid-configuration
|
|
1464
1465
|
# The OIDC issuer URL for discovery.
|
|
1465
1466
|
|
|
@@ -1478,12 +1479,10 @@ CYLOGIN_CODE_CHALLENGE_METHOD=S256
|
|
|
1478
1479
|
|
|
1479
1480
|
CYLOGIN_POST_LOGOUR_REIDRECT_URI=https://localhost:44319/
|
|
1480
1481
|
# Where to redirect users after logout.
|
|
1481
|
-
```
|
|
1482
1482
|
|
|
1483
|
+
# -----------------------------------------------
|
|
1483
1484
|
#### DSF API Gateway environment variables
|
|
1484
|
-
The following environment variables are used to configure the DSF API Gateway. The DSF API Gateway is used to send notifications to the NotificationEngine API.
|
|
1485
|
-
|
|
1486
|
-
```dotenv
|
|
1485
|
+
# The following environment variables are used to configure the DSF API Gateway. The DSF API Gateway is used to send notifications to the NotificationEngine API.
|
|
1487
1486
|
DSF_API_GTW_CLIENT_ID=your-DSF-API-gateway-client-id
|
|
1488
1487
|
DSF_API_GTW_SECRET=your-DSF-API-gateway-secret
|
|
1489
1488
|
DSF_API_GTW_SERVICE_ID=your-DSF-API-gateway-service-id
|
|
@@ -1491,12 +1490,10 @@ DSF_API_GTW_SERVICE_ID=your-DSF-API-gateway-service-id
|
|
|
1491
1490
|
|
|
1492
1491
|
DSF_API_GTW_NOTIFICATION_API_URL=https://127.0.0.1/api/v1/NotificationEngine/simple-message
|
|
1493
1492
|
# URL for the NotificationEngine API.
|
|
1494
|
-
```
|
|
1495
1493
|
|
|
1494
|
+
#-----------------------------------------------
|
|
1496
1495
|
#### Service API environmental variables
|
|
1497
|
-
The following environment variables are used to configure the services (they are referenced in the JSON config file):
|
|
1498
|
-
|
|
1499
|
-
```dotenv
|
|
1496
|
+
# The following environment variables are used to configure the services (they are referenced in the JSON config file):
|
|
1500
1497
|
# Submission endpoint (test service)
|
|
1501
1498
|
TEST_SUBMISSION_API_URL=http://localhost:3002/submission
|
|
1502
1499
|
TEST_SUBMISSION_API_CLIENT_KEY=12345678901234567890123456789000
|
|
@@ -1507,6 +1504,14 @@ TEST_SUBMISSION_DSF_GTW_KEY=12345678901234567890123456789000
|
|
|
1507
1504
|
TEST_ELIGIBILITY_1_API_URL=http://localhost:3002/eligibility1
|
|
1508
1505
|
TEST_ELIGIBILITY_2_API_URL=http://localhost:3002/eligibility2
|
|
1509
1506
|
```
|
|
1507
|
+
#### Non secret environment variables
|
|
1508
|
+
The following non-secret environment variables are used to configure the server defined in `.env.development` for local development, `.env.staging` for staging, and `.env.production` for production.:
|
|
1509
|
+
|
|
1510
|
+
```dotenv
|
|
1511
|
+
#### Matomo web analytics environment variables
|
|
1512
|
+
MATOMO_SITE_ID=51
|
|
1513
|
+
MATOMO_URL=//wp.matomo.dits.dmrid.gov.cy
|
|
1514
|
+
```
|
|
1510
1515
|
|
|
1511
1516
|
## π Security note
|
|
1512
1517
|
- Always set a strong, random `SESSION_SECRET` in your `secrets/.env` file. Never commit secrets or credentials to version control.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gov-cy/govcy-express-services",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"description": "An Express-based system that dynamically renders services using @gov-cy/govcy-frontend-renderer and posts data to a submission API.",
|
|
5
5
|
"author": "DMRID - DSF Team",
|
|
6
6
|
"license": "MIT",
|
|
@@ -85,6 +85,8 @@ export function govcyReviewPostHandler() {
|
|
|
85
85
|
// Prepare submission data for API
|
|
86
86
|
const submissionDataAPI = prepareSubmissionDataAPI(submissionData);
|
|
87
87
|
|
|
88
|
+
logger.debug("Prepared submission data for API:", submissionDataAPI);
|
|
89
|
+
|
|
88
90
|
// Call the API to submit the data
|
|
89
91
|
const response = await govcyApiRequest(
|
|
90
92
|
"post", // Use POST method
|
|
@@ -6,12 +6,19 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import * as dotenv from 'dotenv';
|
|
9
|
+
import fs from 'fs';
|
|
9
10
|
import { dirname, join } from 'path';
|
|
10
11
|
|
|
11
12
|
// Load environment variables from .env file
|
|
12
13
|
let envFilePath = join(process.cwd(),'secrets', '.env');
|
|
13
14
|
dotenv.config({ path: envFilePath });
|
|
14
15
|
|
|
16
|
+
// Load additional environment variables from .env.{{environment}}
|
|
17
|
+
let configPathEnv = join(process.cwd(),'.env.' + whatsIsMyEnvironment());
|
|
18
|
+
if (fs.existsSync(configPathEnv)) {
|
|
19
|
+
dotenv.config({ path: configPathEnv, override: false }); // don't override existing vars from secrets
|
|
20
|
+
}
|
|
21
|
+
//:todo, when loading the service, change `matomo.url` and `matomo.siteId` to the service's values
|
|
15
22
|
/**
|
|
16
23
|
* Check if the current environment is production
|
|
17
24
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
|
-
import { whatsIsMyEnvironment } from './govcyEnvVariables.mjs';
|
|
9
|
+
import { whatsIsMyEnvironment, getEnvVariable} from './govcyEnvVariables.mjs';
|
|
10
10
|
import { logger } from "./govcyLogger.mjs";
|
|
11
11
|
|
|
12
12
|
|
|
@@ -76,6 +76,11 @@ export function getServiceConfigData(siteId,lang) {
|
|
|
76
76
|
//Handle TESTING banner: check if staging and set isTesting
|
|
77
77
|
serviceCopy.site.isTesting = (whatsIsMyEnvironment() === "staging");
|
|
78
78
|
|
|
79
|
+
//Handle matomo: Set Matomo URL and siteId
|
|
80
|
+
serviceCopy.site.matomo = {
|
|
81
|
+
url: getEnvVariable('MATOMO_URL', 'https://wp.matomo.dits.dmrid.gov.cy/'),
|
|
82
|
+
siteId: getEnvVariable('MATOMO_SITE_ID', '50')
|
|
83
|
+
};
|
|
79
84
|
// Add manifest path
|
|
80
85
|
serviceCopy.site.manifest = `/${siteId}/manifest.json`;
|
|
81
86
|
|
|
@@ -4,6 +4,7 @@ import * as dataLayer from "./govcyDataLayer.mjs";
|
|
|
4
4
|
import { DSFEmailRenderer } from '@gov-cy/dsf-email-templates';
|
|
5
5
|
import { ALLOWED_FORM_ELEMENTS } from "./govcyConstants.mjs";
|
|
6
6
|
import { evaluatePageConditions } from "./govcyExpressions.mjs";
|
|
7
|
+
import { logger } from "./govcyLogger.mjs";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Prepares the submission data for the service, including raw data, print-friendly data, and renderer data.
|
|
@@ -19,17 +20,78 @@ export function prepareSubmissionData(req, siteId, service) {
|
|
|
19
20
|
|
|
20
21
|
// ----- Conditional logic comes here
|
|
21
22
|
// Filter site input data based on active pages only
|
|
22
|
-
const rawData = {};
|
|
23
|
+
// const rawData = {};
|
|
24
|
+
// for (const page of service.pages) {
|
|
25
|
+
// const shouldInclude = evaluatePageConditions(page, req.session, siteId, req).result === true;
|
|
26
|
+
// if (shouldInclude) {
|
|
27
|
+
// const pageUrl = page.pageData.url;
|
|
28
|
+
// const formData = dataLayer.getPageData(req.session, siteId, pageUrl);
|
|
29
|
+
// if (formData && Object.keys(formData).length > 0) {
|
|
30
|
+
// rawData[pageUrl] = { formData };
|
|
31
|
+
// }
|
|
32
|
+
// }
|
|
33
|
+
// }
|
|
34
|
+
|
|
35
|
+
// ----- consistent data model for submission_data (CONFIG-BASED)
|
|
36
|
+
const submissionData = {};
|
|
37
|
+
|
|
38
|
+
// Loop through every page in the service definition
|
|
23
39
|
for (const page of service.pages) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
const pageUrl = page.pageData.url || "";
|
|
41
|
+
|
|
42
|
+
// Find the <form> element in the page
|
|
43
|
+
let formElement = null;
|
|
44
|
+
for (const section of page.pageTemplate.sections || []) {
|
|
45
|
+
formElement = section.elements.find(el => el.element === "form");
|
|
46
|
+
if (formElement) break;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!formElement) continue; // β Skip pages without a <form> element
|
|
50
|
+
|
|
51
|
+
submissionData[pageUrl] = { formData: {} }; // β
Now initialize only if a form is present
|
|
52
|
+
|
|
53
|
+
// Traverse the form elements inside the form
|
|
54
|
+
for (const element of formElement.params.elements || []) {
|
|
55
|
+
const elType = element.element;
|
|
56
|
+
|
|
57
|
+
// β
Skip non-input elements like buttons
|
|
58
|
+
if (!ALLOWED_FORM_ELEMENTS.includes(elType)) continue;
|
|
59
|
+
|
|
60
|
+
const elId = element.params?.id || element.params?.name;
|
|
61
|
+
if (!elId) continue; // β Skip elements with no id/name
|
|
62
|
+
|
|
63
|
+
// π’ Use helper to get session value (or "" fallback if missing)
|
|
64
|
+
const value = getValue(element, pageUrl, req, siteId) ?? "";
|
|
65
|
+
|
|
66
|
+
// Store in submissionData
|
|
67
|
+
submissionData[pageUrl].formData[elId] = value;
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
// π If radios with conditionalElements, walk ALL options
|
|
71
|
+
if (elType === "radios" && Array.isArray(element.params?.items)) {
|
|
72
|
+
for (const radioItem of element.params.items) {
|
|
73
|
+
const condEls = radioItem.conditionalElements;
|
|
74
|
+
if (!Array.isArray(condEls)) continue;
|
|
75
|
+
|
|
76
|
+
for (const condElement of condEls) {
|
|
77
|
+
const condType = condElement.element;
|
|
78
|
+
if (!ALLOWED_FORM_ELEMENTS.includes(condType)) continue;
|
|
79
|
+
|
|
80
|
+
const condId = condElement.params?.id || condElement.params?.name;
|
|
81
|
+
if (!condId) continue;
|
|
82
|
+
|
|
83
|
+
// Again: read from session or fallback to ""
|
|
84
|
+
const condValue = getValue(condElement, pageUrl, req, siteId) ?? "";
|
|
85
|
+
|
|
86
|
+
// Store even if the field was not visible to user
|
|
87
|
+
submissionData[pageUrl].formData[condId] = condValue;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
30
91
|
}
|
|
31
92
|
}
|
|
32
|
-
|
|
93
|
+
logger.debug("Submission Data prepared:", submissionData);
|
|
94
|
+
// ----- END config-based stable submission_data block
|
|
33
95
|
|
|
34
96
|
// Get the print-friendly data from the session store
|
|
35
97
|
const printFriendlyData = preparePrintFriendlyData(req, siteId, service);
|
|
@@ -40,7 +102,7 @@ export function prepareSubmissionData(req, siteId, service) {
|
|
|
40
102
|
return {
|
|
41
103
|
submission_username: dataLayer.getUser(req.session).name,
|
|
42
104
|
submission_email: dataLayer.getUser(req.session).email,
|
|
43
|
-
submission_data:
|
|
105
|
+
submission_data: submissionData, // Raw data as submitted by the user in each page
|
|
44
106
|
submission_data_version: service.site?.submission_data_version || "", // The submission data version
|
|
45
107
|
print_friendly_data: printFriendlyData, // Print-friendly data
|
|
46
108
|
renderer_data: reviewSummaryList, // Renderer data of the summary list
|
|
@@ -89,123 +151,6 @@ export function preparePrintFriendlyData(req, siteId, service) {
|
|
|
89
151
|
|
|
90
152
|
const allowedElements = ALLOWED_FORM_ELEMENTS;
|
|
91
153
|
|
|
92
|
-
/**
|
|
93
|
-
* Helper function to retrieve date raw input.
|
|
94
|
-
*
|
|
95
|
-
* @param {string} pageUrl The page URL
|
|
96
|
-
* @param {string} name The name of the form element
|
|
97
|
-
* @returns {string} The raw date input in ISO format (YYYY-MM-DD) or an empty string if not found
|
|
98
|
-
*/
|
|
99
|
-
function getDateInputISO(pageUrl, name) {
|
|
100
|
-
const day = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_day`);
|
|
101
|
-
const month = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_month`);
|
|
102
|
-
const year = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_year`);
|
|
103
|
-
if (!day || !month || !year) return "";
|
|
104
|
-
|
|
105
|
-
// Pad day and month with leading zero if needed
|
|
106
|
-
const paddedDay = String(day).padStart(2, "0");
|
|
107
|
-
const paddedMonth = String(month).padStart(2, "0");
|
|
108
|
-
|
|
109
|
-
return `${year}-${paddedMonth}-${paddedDay}`; // ISO format: YYYY-MM-DD
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Helper function to retrieve date input in DMY format.
|
|
114
|
-
*
|
|
115
|
-
* @param {string} pageUrl The page URL
|
|
116
|
-
* @param {string} name The name of the form element
|
|
117
|
-
* @returns {string} The raw date input in DMY format (DD/MM/YYYY) or an empty string if not found
|
|
118
|
-
*/
|
|
119
|
-
function getDateInputDMY(pageUrl, name) {
|
|
120
|
-
const day = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_day`);
|
|
121
|
-
const month = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_month`);
|
|
122
|
-
const year = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_year`);
|
|
123
|
-
if (!day || !month || !year) return "";
|
|
124
|
-
return `${day}/${month}/${year}`; // EU format: DD/MM/YYYY
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Helper function to create a field object.
|
|
129
|
-
*
|
|
130
|
-
* @param {object} formElement The form element object
|
|
131
|
-
* @param {string} value The value of the form element
|
|
132
|
-
* @param {object} valueLabel The label of the form element
|
|
133
|
-
* @returns {object} The field object containing id, label, value, and valueLabel
|
|
134
|
-
*/
|
|
135
|
-
function createFieldObject(formElement, value, valueLabel) {
|
|
136
|
-
return {
|
|
137
|
-
id: formElement.params?.id || "",
|
|
138
|
-
name: formElement.params?.name || "",
|
|
139
|
-
label: formElement.params.label
|
|
140
|
-
|| formElement.params.legend
|
|
141
|
-
|| govcyResources.getSameMultilingualObject(service.site.languages, formElement.params.name),
|
|
142
|
-
value: value,
|
|
143
|
-
valueLabel: valueLabel
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Helper function to retrieve the value of a form element from the session.
|
|
149
|
-
*
|
|
150
|
-
* @param {object} formElement The form element object
|
|
151
|
-
* @param {string} pageUrl The page URL
|
|
152
|
-
* @returns {string} The value of the form element from the session or an empty string if not found
|
|
153
|
-
*/
|
|
154
|
-
function getValue(formElement, pageUrl) {
|
|
155
|
-
// handle raw value
|
|
156
|
-
let value = ""
|
|
157
|
-
if (formElement.element === "dateInput") {
|
|
158
|
-
value = getDateInputISO(pageUrl, formElement.params.name);
|
|
159
|
-
} else {
|
|
160
|
-
value = dataLayer.getFormDataValue(req.session, siteId, pageUrl, formElement.params.name);
|
|
161
|
-
}
|
|
162
|
-
return value;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Helper function to get the label of a form element based on its value and type.
|
|
167
|
-
*
|
|
168
|
-
* @param {object} formElement The form element object
|
|
169
|
-
* @param {string} value The value of the form element
|
|
170
|
-
* @param {string} pageUrl The page URL
|
|
171
|
-
* @returns {object} The label of the form element based on the value and element type
|
|
172
|
-
*/
|
|
173
|
-
function getValueLabel(formElement, value, pageUrl) {
|
|
174
|
-
//handle checkboxes label
|
|
175
|
-
if (formElement.element === "checkboxes") {
|
|
176
|
-
if (Array.isArray(value)) {
|
|
177
|
-
// loop through each value and find the corresponding item
|
|
178
|
-
return value.map(v => {
|
|
179
|
-
// find the item
|
|
180
|
-
const item = formElement.params.items.find(i => i.value === v);
|
|
181
|
-
return item?.text || govcyResources.getSameMultilingualObject(service.site.languages, "");
|
|
182
|
-
});
|
|
183
|
-
} else if (typeof value === "string") {
|
|
184
|
-
const matchedItem = formElement.params.items.find(item => item.value === value);
|
|
185
|
-
if (matchedItem) {
|
|
186
|
-
return matchedItem.text;
|
|
187
|
-
} else {
|
|
188
|
-
return govcyResources.getSameMultilingualObject(service.site.languages, "")
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// handle radios and select labels
|
|
194
|
-
if (formElement.element === "radios" || formElement.element === "select") {
|
|
195
|
-
const item = formElement.params.items.find(i => i.value === value);
|
|
196
|
-
return item?.text || govcyResources.getSameMultilingualObject(service.site.languages, "");
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// handle dateInput
|
|
200
|
-
if (formElement.element === "dateInput") {
|
|
201
|
-
const formattedDate = getDateInputDMY(pageUrl, formElement.params.name);
|
|
202
|
-
return govcyResources.getSameMultilingualObject(service.site.languages, formattedDate);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// textInput, textArea, etc.
|
|
206
|
-
return govcyResources.getSameMultilingualObject(service.site.languages, value);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
154
|
// loop through each page in the service
|
|
210
155
|
// and extract the form data from the session
|
|
211
156
|
for (const page of service.pages) {
|
|
@@ -228,11 +173,11 @@ export function preparePrintFriendlyData(req, siteId, service) {
|
|
|
228
173
|
if (!allowedElements.includes(formElement.element)) continue;
|
|
229
174
|
|
|
230
175
|
// handle raw value
|
|
231
|
-
let rawValue = getValue(formElement, page.pageData.url);
|
|
176
|
+
let rawValue = getValue(formElement, page.pageData.url, req, siteId);
|
|
232
177
|
|
|
233
178
|
//create the field object and push it to the fields array
|
|
234
179
|
// value of the field is handled by getValueLabel function
|
|
235
|
-
const field = createFieldObject(formElement, rawValue, getValueLabel(formElement, rawValue, page.pageData.url));
|
|
180
|
+
const field = createFieldObject(formElement, rawValue, getValueLabel(formElement, rawValue, page.pageData.url, req, siteId, service), service);
|
|
236
181
|
fields.push(field);
|
|
237
182
|
|
|
238
183
|
// Handle conditional elements (only for radios for now)
|
|
@@ -246,11 +191,11 @@ export function preparePrintFriendlyData(req, siteId, service) {
|
|
|
246
191
|
if (!allowedElements.includes(condEl.element)) continue;
|
|
247
192
|
|
|
248
193
|
// handle raw value
|
|
249
|
-
let condValue = getValue(condEl, page.pageData.url);
|
|
194
|
+
let condValue = getValue(condEl, page.pageData.url, req, siteId);
|
|
250
195
|
|
|
251
196
|
//create the field object and push it to the fields array
|
|
252
197
|
// value of the field is handled by getValueLabel function
|
|
253
|
-
const field = createFieldObject(condEl, condValue, getValueLabel(condEl, condValue, page.pageData.url));
|
|
198
|
+
const field = createFieldObject(condEl, condValue, getValueLabel(condEl, condValue, page.pageData.url, req, siteId, service), service);
|
|
254
199
|
fields.push(field);
|
|
255
200
|
}
|
|
256
201
|
}
|
|
@@ -272,6 +217,132 @@ export function preparePrintFriendlyData(req, siteId, service) {
|
|
|
272
217
|
}
|
|
273
218
|
|
|
274
219
|
//------------------------------- Helper Functions -------------------------------//
|
|
220
|
+
/**
|
|
221
|
+
* Helper function to retrieve date raw input.
|
|
222
|
+
*
|
|
223
|
+
* @param {string} pageUrl The page URL
|
|
224
|
+
* @param {string} name The name of the form element
|
|
225
|
+
* @param {object} req The request object
|
|
226
|
+
* @param {string} siteId The site ID
|
|
227
|
+
* @returns {string} The raw date input in ISO format (YYYY-MM-DD) or an empty string if not found
|
|
228
|
+
*/
|
|
229
|
+
function getDateInputISO(pageUrl, name, req, siteId) {
|
|
230
|
+
const day = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_day`);
|
|
231
|
+
const month = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_month`);
|
|
232
|
+
const year = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_year`);
|
|
233
|
+
if (!day || !month || !year) return "";
|
|
234
|
+
|
|
235
|
+
// Pad day and month with leading zero if needed
|
|
236
|
+
const paddedDay = String(day).padStart(2, "0");
|
|
237
|
+
const paddedMonth = String(month).padStart(2, "0");
|
|
238
|
+
|
|
239
|
+
return `${year}-${paddedMonth}-${paddedDay}`; // ISO format: YYYY-MM-DD
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Helper function to retrieve date input in DMY format.
|
|
244
|
+
*
|
|
245
|
+
* @param {string} pageUrl The page URL
|
|
246
|
+
* @param {string} name The name of the form element
|
|
247
|
+
* @param {object} req The request object
|
|
248
|
+
* @param {string} siteId The site ID
|
|
249
|
+
* @returns {string} The raw date input in DMY format (DD/MM/YYYY) or an empty string if not found
|
|
250
|
+
*/
|
|
251
|
+
function getDateInputDMY(pageUrl, name, req, siteId) {
|
|
252
|
+
const day = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_day`);
|
|
253
|
+
const month = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_month`);
|
|
254
|
+
const year = dataLayer.getFormDataValue(req.session, siteId, pageUrl, `${name}_year`);
|
|
255
|
+
if (!day || !month || !year) return "";
|
|
256
|
+
return `${day}/${month}/${year}`; // EU format: DD/MM/YYYY
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Helper function to create a field object.
|
|
261
|
+
*
|
|
262
|
+
* @param {object} formElement The form element object
|
|
263
|
+
* @param {string} value The value of the form element
|
|
264
|
+
* @param {object} valueLabel The label of the form element
|
|
265
|
+
* @param {object} service The service object
|
|
266
|
+
* @returns {object} The field object containing id, label, value, and valueLabel
|
|
267
|
+
*/
|
|
268
|
+
function createFieldObject(formElement, value, valueLabel, service) {
|
|
269
|
+
return {
|
|
270
|
+
id: formElement.params?.id || "",
|
|
271
|
+
name: formElement.params?.name || "",
|
|
272
|
+
label: formElement.params.label
|
|
273
|
+
|| formElement.params.legend
|
|
274
|
+
|| govcyResources.getSameMultilingualObject(service.site.languages, formElement.params.name),
|
|
275
|
+
value: value,
|
|
276
|
+
valueLabel: valueLabel
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Helper function to retrieve the value of a form element from the session.
|
|
282
|
+
*
|
|
283
|
+
* @param {object} formElement The form element object
|
|
284
|
+
* @param {string} pageUrl The page URL
|
|
285
|
+
* @param {object} req The request object
|
|
286
|
+
* @param {string} siteId The site ID
|
|
287
|
+
* @returns {string} The value of the form element from the session or an empty string if not found
|
|
288
|
+
*/
|
|
289
|
+
function getValue(formElement, pageUrl, req, siteId) {
|
|
290
|
+
// handle raw value
|
|
291
|
+
let value = ""
|
|
292
|
+
if (formElement.element === "dateInput") {
|
|
293
|
+
value = getDateInputISO(pageUrl, formElement.params.name, req, siteId);
|
|
294
|
+
} else {
|
|
295
|
+
value = dataLayer.getFormDataValue(req.session, siteId, pageUrl, formElement.params.name);
|
|
296
|
+
}
|
|
297
|
+
return value;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Helper function to get the label of a form element based on its value and type.
|
|
302
|
+
*
|
|
303
|
+
* @param {object} formElement The form element object
|
|
304
|
+
* @param {string} value The value of the form element
|
|
305
|
+
* @param {string} pageUrl The page URL
|
|
306
|
+
* @param {object} req The request object
|
|
307
|
+
* @param {string} siteId The site ID
|
|
308
|
+
* @param {object} service The service object
|
|
309
|
+
* @returns {object} The label of the form element based on the value and element type
|
|
310
|
+
*/
|
|
311
|
+
function getValueLabel(formElement, value, pageUrl, req, siteId, service) {
|
|
312
|
+
//handle checkboxes label
|
|
313
|
+
if (formElement.element === "checkboxes") {
|
|
314
|
+
if (Array.isArray(value)) {
|
|
315
|
+
// loop through each value and find the corresponding item
|
|
316
|
+
return value.map(v => {
|
|
317
|
+
// find the item
|
|
318
|
+
const item = formElement.params.items.find(i => i.value === v);
|
|
319
|
+
return item?.text || govcyResources.getSameMultilingualObject(service.site.languages, "");
|
|
320
|
+
});
|
|
321
|
+
} else if (typeof value === "string") {
|
|
322
|
+
const matchedItem = formElement.params.items.find(item => item.value === value);
|
|
323
|
+
if (matchedItem) {
|
|
324
|
+
return matchedItem.text;
|
|
325
|
+
} else {
|
|
326
|
+
return govcyResources.getSameMultilingualObject(service.site.languages, "")
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// handle radios and select labels
|
|
332
|
+
if (formElement.element === "radios" || formElement.element === "select") {
|
|
333
|
+
const item = formElement.params.items.find(i => i.value === value);
|
|
334
|
+
return item?.text || govcyResources.getSameMultilingualObject(service.site.languages, "");
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// handle dateInput
|
|
338
|
+
if (formElement.element === "dateInput") {
|
|
339
|
+
const formattedDate = getDateInputDMY(pageUrl, formElement.params.name, req, siteId);
|
|
340
|
+
return govcyResources.getSameMultilingualObject(service.site.languages, formattedDate);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// textInput, textArea, etc.
|
|
344
|
+
return govcyResources.getSameMultilingualObject(service.site.languages, value);
|
|
345
|
+
}
|
|
275
346
|
|
|
276
347
|
/**
|
|
277
348
|
* Helper function to get the item value of checkboxes based on the selected value.
|