@gov-cy/govcy-express-services 1.0.0-alpha.9 → 1.0.0
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 +1024 -74
- package/package.json +9 -3
- package/src/auth/cyLoginAuth.mjs +2 -1
- package/src/index.mjs +9 -5
- package/src/middleware/cyLoginAuth.mjs +3 -1
- package/src/middleware/govcyFileDeleteHandler.mjs +320 -0
- package/src/middleware/{govcyUpload.mjs → govcyFileUpload.mjs} +1 -1
- package/src/middleware/govcyFileViewHandler.mjs +161 -0
- package/src/middleware/govcyPDFRender.mjs +3 -1
- package/src/middleware/govcyPageHandler.mjs +1 -5
- package/src/middleware/govcyPageRender.mjs +10 -0
- package/src/middleware/govcyReviewPageHandler.mjs +4 -1
- package/src/middleware/govcyReviewPostHandler.mjs +1 -1
- package/src/middleware/govcySuccessPageHandler.mjs +2 -3
- package/src/public/js/govcyFiles.js +108 -5
- package/src/resources/govcyResources.mjs +26 -6
- package/src/utils/govcyConstants.mjs +1 -1
- package/src/utils/govcyDataLayer.mjs +192 -14
- package/src/utils/govcyFormHandling.mjs +3 -2
- package/src/utils/govcyHandleFiles.mjs +3 -3
- package/src/utils/govcySubmitData.mjs +162 -109
- package/src/middleware/govcyDeleteFileHandler.mjs +0 -234
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|

|
|
4
4
|
[](https://github.com/gov-cy/govcy-express-services/actions/workflows/unit-test.yml)
|
|
5
5
|
[](https://github.com/gov-cy/govcy-express-services/actions/workflows/tag-and-publish-on-version-change.yml)
|
|
6
|
+
[](coverage-summary.json)
|
|
6
7
|
|
|
7
8
|
> ⚠️ **Warning:**
|
|
8
9
|
> This package is **under active development** and is not a finished product. It is intended for testing, acceptance, integration, and browser testing purposes only.
|
|
@@ -12,10 +13,12 @@
|
|
|
12
13
|
> You are responsible for ensuring your own compliance, security, and quality assurance processes.
|
|
13
14
|
|
|
14
15
|
## 📝 Description
|
|
15
|
-
This project is an Express-based project that dynamically renders online service forms using `@gov-cy/govcy-frontend-renderer
|
|
16
|
+
This project is an Express-based project that dynamically renders online service forms using `@gov-cy/govcy-frontend-renderer`, handles data input, validations, renders a review page and submits the data via a submission API. It is designed for developers building government services in Cyprus, enabling them to manage user authentication, form submissions, and OpenID authentication workflows in a timely manner.
|
|
16
17
|
|
|
17
18
|
The project is designed to support the [Linear structure](https://gov-cy.github.io/govcy-design-system-docs/patterns/service_structure/#variant-1---linear-structure) as described in the [Unified Design System](https://gov-cy.github.io/govcy-design-system-docs/).
|
|
18
19
|
|
|
20
|
+
The APIs used for submission, temporary save and file uploads are not part of this project. The project has been designed to work together with the **DSF Submission plarform** and all API calls are based on the **DSF Submission Platform APIs**. This readme file describes the definition of these APIs if you wish to develop your own for your own government back-end solution. For more details about the DSF Submission Platform [contact the DSF team](https://dsf.dmrid.gov.cy/contact/).
|
|
21
|
+
|
|
19
22
|

|
|
20
23
|
|
|
21
24
|
## Table of contents
|
|
@@ -27,14 +30,15 @@ The project is designed to support the [Linear structure](https://gov-cy.github.
|
|
|
27
30
|
- [✅ Best Practices](#-best-practices)
|
|
28
31
|
- [📦 Full installation guide](#-full-installation-guide)
|
|
29
32
|
- [🛠️ Usage](#%EF%B8%8F-usage)
|
|
30
|
-
- [🧩 Dynamic services
|
|
33
|
+
- [🧩 Dynamic services](#-dynamic-services)
|
|
31
34
|
- [🛡️ Site eligibility checks](#%EF%B8%8F-site-eligibility-checks)
|
|
32
35
|
- [📤 Site submissions](#-site-submissions)
|
|
33
36
|
- [✅ Input validations](#-input-validations)
|
|
34
|
-
- [
|
|
35
|
-
- [💾 Temporary save](#-temporary-save)
|
|
37
|
+
- [🔀 Conditional logic](#-conditional-logic)
|
|
38
|
+
- [💾 Temporary save feature](#-temporary-save-feature)
|
|
39
|
+
- [🗃️ Files uploads feature](#%EF%B8%8F-files-uploads-feature)
|
|
36
40
|
- [🛣️ Routes](#%EF%B8%8F-routes)
|
|
37
|
-
- [👨💻
|
|
41
|
+
- [👨💻 Environment variables](#-environment-variables)
|
|
38
42
|
- [🔒 Security note](#-security-note)
|
|
39
43
|
- [❓ Troubleshooting / FAQ](#-troubleshooting--faq)
|
|
40
44
|
- [🙏 Credits](#-credits)
|
|
@@ -44,7 +48,7 @@ The project is designed to support the [Linear structure](https://gov-cy.github.
|
|
|
44
48
|
|
|
45
49
|
## ✨ Features
|
|
46
50
|
- Dynamic form rendering from JSON templates
|
|
47
|
-
- Support for `textInput`, `textArea`, `select`, `radios`, `checkboxes`, `datePicker`, `dateInput`
|
|
51
|
+
- Support for `textInput`, `textArea`, `select`, `radios`, `checkboxes`, `datePicker`, `dateInput`, `fileInput` elements
|
|
48
52
|
- Support for `conditional radios`
|
|
49
53
|
- Dynamic creation of check your answers page
|
|
50
54
|
- OpenID Connect authentication with CY Login
|
|
@@ -57,6 +61,7 @@ The project is designed to support the [Linear structure](https://gov-cy.github.
|
|
|
57
61
|
- Site level API eligibility checks
|
|
58
62
|
- API integration with retry logic for form submissions.
|
|
59
63
|
- Optional temporary save of in-progress form data via configurable API endpoints
|
|
64
|
+
- Optional file uploads via API endpoints
|
|
60
65
|
|
|
61
66
|
## 📋 Prerequisites
|
|
62
67
|
- Node.js 20+
|
|
@@ -137,9 +142,555 @@ The CY Login tokens are used to also connect with the various APIs through [cyCo
|
|
|
137
142
|
|
|
138
143
|
The CY Login settings are configured in the `secrets/.env` file.
|
|
139
144
|
|
|
140
|
-
### 🧩 Dynamic Services
|
|
145
|
+
### 🧩 Dynamic Services
|
|
141
146
|
Services are rendered dynamically using JSON templates stored in the `/data` folder. All the service configuration, pages, routes, and logic is stored in the JSON files. The service will load `data/:siteId.json` to get the form data when a user visits `/:siteId/:pageUrl`. Checkout the [express-service-shema.json](express-service-shema.json) and the example JSON structure of the **[test.json](data/test.json)** file for more details.
|
|
142
147
|
|
|
148
|
+
Here is an example JSON config:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"site": {
|
|
153
|
+
"id": "test",
|
|
154
|
+
"lang": "el", //<-- Default language
|
|
155
|
+
"languages": [ //<-- Supported languages
|
|
156
|
+
{
|
|
157
|
+
"code": "el",
|
|
158
|
+
"label": "EL",
|
|
159
|
+
"alt": "Ελληνική γλώσσα",
|
|
160
|
+
"href": "?lang=el"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"code": "en",
|
|
164
|
+
"label": "EN",
|
|
165
|
+
"alt": "English language",
|
|
166
|
+
"href": "?lang=en"
|
|
167
|
+
}
|
|
168
|
+
],
|
|
169
|
+
"footerLinks": [ //<-- Links on the footer
|
|
170
|
+
{
|
|
171
|
+
"label": {
|
|
172
|
+
"el": "Δήλωση απορρήτου",
|
|
173
|
+
"en": "Privacy statement",
|
|
174
|
+
"tr": "Privacy statement"
|
|
175
|
+
},
|
|
176
|
+
"href": "test/privacy-statement"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"label": {
|
|
180
|
+
"el": "Cookies",
|
|
181
|
+
"en": "Cookies",
|
|
182
|
+
"tr": "Cookies"
|
|
183
|
+
},
|
|
184
|
+
"href": "test/cookie-policy"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"label": {
|
|
188
|
+
"el": "Προσβασιμότητα",
|
|
189
|
+
"en": "Accessibility",
|
|
190
|
+
"tr": "Accessibility"
|
|
191
|
+
},
|
|
192
|
+
"href": "test/accessibility-statement"
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
"footerIcons": [ //<-- Icons on the footer
|
|
196
|
+
{
|
|
197
|
+
"target": "_blank",
|
|
198
|
+
"src": {
|
|
199
|
+
"el": "https://cdn.jsdelivr.net/gh/gov-cy/govdesign@main/FundedbyEU_NextGeneration_H53-EL.png",
|
|
200
|
+
"en": "https://cdn.jsdelivr.net/gh/gov-cy/govdesign@main/FundedbyEU_NextGeneration_H53-EN.png",
|
|
201
|
+
"tr": "https://cdn.jsdelivr.net/gh/gov-cy/govdesign@main/FundedbyEU_NextGeneration_H53-EN.png"
|
|
202
|
+
},
|
|
203
|
+
"alt": {
|
|
204
|
+
"el": "Χρηματοδοτείται από την ΕΕ Next Generation EU",
|
|
205
|
+
"en": "Funded by the EU Next Generation EU",
|
|
206
|
+
"tr": "Funded by the EU Next Generation EU"
|
|
207
|
+
},
|
|
208
|
+
"href": {
|
|
209
|
+
"el": "https://europa.eu/",
|
|
210
|
+
"en": "https://europa.eu/",
|
|
211
|
+
"tr": "https://europa.eu/"
|
|
212
|
+
},
|
|
213
|
+
"title": {
|
|
214
|
+
"el": "Μετάβαση στην ιστοσελίδα της ΕΕ",
|
|
215
|
+
"en": "Go to EU website",
|
|
216
|
+
"tr": "Go to EU website"
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"target": "_blank",
|
|
221
|
+
"src": {
|
|
222
|
+
"el": "https://cdn.jsdelivr.net/gh/gov-cy/govdesign@main/CYpros%20to%20aurio%20logo%20eng_H53_EL.png",
|
|
223
|
+
"en": "https://cdn.jsdelivr.net/gh/gov-cy/govdesign@main/CYpros%20to%20aurio%20logo%20eng_H53_EN.png",
|
|
224
|
+
"tr": "https://cdn.jsdelivr.net/gh/gov-cy/govdesign@main/CYpros%20to%20aurio%20logo%20eng_H53_EN.png"
|
|
225
|
+
},
|
|
226
|
+
"alt": {
|
|
227
|
+
"el": "Κύπρος το Αύριο, σχέδιο ανάκαμψης και ανθεντικότητας",
|
|
228
|
+
"en": "Cyprus tomorrow, recovery and resilience plan",
|
|
229
|
+
"tr": "Cyprus tomorrow, recovery and resilience plan"
|
|
230
|
+
},
|
|
231
|
+
"href": {
|
|
232
|
+
"el": "http://www.cyprus-tomorrow.gov.cy/",
|
|
233
|
+
"en": "http://www.cyprus-tomorrow.gov.cy/",
|
|
234
|
+
"tr": "http://www.cyprus-tomorrow.gov.cy/"
|
|
235
|
+
},
|
|
236
|
+
"title": {
|
|
237
|
+
"el": "Μετάβαση στην ιστοσελίδα Κύπρος το Αύριο",
|
|
238
|
+
"en": "Go to Cyprus Tomorrow website",
|
|
239
|
+
"tr": "Go to Cyprus Tomorrow website"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
],
|
|
243
|
+
"menu": { //<-- Menu altext
|
|
244
|
+
"el": "Μενού",
|
|
245
|
+
"en": "Menu",
|
|
246
|
+
"tr": "Menu"
|
|
247
|
+
},
|
|
248
|
+
"title": { //<-- Service title (meta)
|
|
249
|
+
"el": "Υπηρεσία τεστ",
|
|
250
|
+
"en": "Test service",
|
|
251
|
+
"tr": ""
|
|
252
|
+
},
|
|
253
|
+
"headerTitle": { // <-- The header title settings
|
|
254
|
+
"title": { //<-- Service title (as it apears in the header)
|
|
255
|
+
"el": "[Το ΟΝΟΜΑ της υπηρεσίας που θα φαίνεται στις φόρμες]",
|
|
256
|
+
"en": "[The NAME of the service as it will appear on forms]",
|
|
257
|
+
"tr": ""
|
|
258
|
+
},
|
|
259
|
+
"href": { // <-- The relative URL of the header title link (for each language)
|
|
260
|
+
"el":"/service-id",
|
|
261
|
+
"en":"/service-id",
|
|
262
|
+
"tr":"/service-id"
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
"description": { //<-- Service description (meta)
|
|
266
|
+
"el": "[Υποβάλετε αίτηση για ...]",
|
|
267
|
+
"en": "[Submit an application ...]",
|
|
268
|
+
"tr": ""
|
|
269
|
+
},
|
|
270
|
+
"url": "https://gov.cy", //<-- URL in (meta, for example `og:url`)
|
|
271
|
+
"cdn": { //<-- CDN URL and integrity
|
|
272
|
+
"dist": "https://cdn.jsdelivr.net/gh/gov-cy/govcy-design-system@3.2.0/dist",
|
|
273
|
+
"cssIntegrity": "sha384-qjx16YXHG+Vq/NVtwU2aDTc7DoLOyaVNuOHrwA3aTrckpM/ycxZoR5dx7ezNJ/Lv",
|
|
274
|
+
"jsIntegrity": "sha384-tqEyCdi3GS4uDXctplAd7ODjiK5fo2Xlqv65e8w/cVvrcBf89tsxXFHXXNiUDyM7"
|
|
275
|
+
},
|
|
276
|
+
"submission_data_version": "1", //<-- Submission data version
|
|
277
|
+
"renderer_version": "1.16.1", //<-- govcy-frontend-renderer version
|
|
278
|
+
"design_systems_version": "3.2.0", //<-- govcy-design-system version
|
|
279
|
+
"homeRedirectPage": { //<-- Home redirect page
|
|
280
|
+
"el": "https://www.gov.cy/service/aitisi-gia-taftotita/",
|
|
281
|
+
"en": "https://www.gov.cy/en/service/issue-an-id-card/",
|
|
282
|
+
"tr": "https://www.gov.cy/en/service/issue-an-id-card/"
|
|
283
|
+
},
|
|
284
|
+
"copyrightText": { //<-- Copyright text
|
|
285
|
+
"el": "Κυπριακή Δημοκρατία, 2025",
|
|
286
|
+
"en": "Republic of Cyprus, 2025",
|
|
287
|
+
"tr": "Republic of Cyprus, 2025"
|
|
288
|
+
},
|
|
289
|
+
"submissionAPIEndpoint": { //<-- Submission API endpoint
|
|
290
|
+
"url": "TEST_SUBMISSION_API_URL",
|
|
291
|
+
"method": "POST",
|
|
292
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
293
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID",
|
|
294
|
+
"dsfgtwApiKey": "TEST_SUBMISSION_DSF_GTW_KEY",
|
|
295
|
+
"response": {
|
|
296
|
+
"errorResponse": {
|
|
297
|
+
"102": {
|
|
298
|
+
"error": "user not administrator",
|
|
299
|
+
"page": "/test/user-not-admin"
|
|
300
|
+
},
|
|
301
|
+
"105": {
|
|
302
|
+
"error": "user not registration",
|
|
303
|
+
"page": "/test/user-not-registered"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
"submissionGetAPIEndpoint": { //<-- Submission GET API endpoint for temporary saving
|
|
309
|
+
"url": "TEST_SUBMISSION_GET_API_URL",
|
|
310
|
+
"method": "GET",
|
|
311
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
312
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID",
|
|
313
|
+
"dsfgtwApiKey": "TEST_SUBMISSION_DSF_GTW_KEY"
|
|
314
|
+
},
|
|
315
|
+
"submissionPutAPIEndpoint": { //<-- Submission PUT API endpoint for temporary saving
|
|
316
|
+
"url": "TEST_SUBMISSION_PUT_API_URL",
|
|
317
|
+
"method": "PUT",
|
|
318
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
319
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID",
|
|
320
|
+
"dsfgtwApiKey": "TEST_SUBMISSION_DSF_GTW_KEY"
|
|
321
|
+
},
|
|
322
|
+
"fileUploadAPIEndpoint": { //<-- File upload API endpoint
|
|
323
|
+
"url": "TEST_UPLOAD_FILE_API_URL",
|
|
324
|
+
"method": "POST",
|
|
325
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
326
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID",
|
|
327
|
+
"dsfgtwApiKey": "TEST_SUBMISSION_DSF_GTW_KEY"
|
|
328
|
+
},
|
|
329
|
+
"fileDownloadAPIEndpoint": { //<-- File download API endpoint
|
|
330
|
+
"url": "TEST_DOWNLOAD_FILE_API_URL",
|
|
331
|
+
"method": "GET",
|
|
332
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
333
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID",
|
|
334
|
+
"dsfgtwApiKey": "TEST_SUBMISSION_DSF_GTW_KEY"
|
|
335
|
+
},
|
|
336
|
+
"fileDeleteAPIEndpoint": { //<-- File delete API endpoint
|
|
337
|
+
"url": "TEST_DELETE_FILE_API_URL",
|
|
338
|
+
"method": "DELETE",
|
|
339
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
340
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID",
|
|
341
|
+
"dsfgtwApiKey": "TEST_SUBMISSION_DSF_GTW_KEY"
|
|
342
|
+
},
|
|
343
|
+
"eligibilityAPIEndpoints": [ //<-- Eligibility API endpoints
|
|
344
|
+
{
|
|
345
|
+
"url": "TEST_ELIGIBILITY_2_API_URL",
|
|
346
|
+
"method": "GET",
|
|
347
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
348
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID",
|
|
349
|
+
"dsfgtwApiKey": "TEST_SUBMISSION_DSF_GTW_KEY",
|
|
350
|
+
"cashingTimeoutMinutes": "60",
|
|
351
|
+
"params": {},
|
|
352
|
+
"response": {
|
|
353
|
+
"errorResponse": {
|
|
354
|
+
"105": {
|
|
355
|
+
"error": "user not registration",
|
|
356
|
+
"page": "/test/user-not-registered"
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
"pages": [ //<-- Pages
|
|
364
|
+
{
|
|
365
|
+
"pageData": { //<-- 1st Page's data (form)
|
|
366
|
+
"url": "index", // Page URL
|
|
367
|
+
"title": { // Page title
|
|
368
|
+
"el": "Επιλογή Εγγάφου",
|
|
369
|
+
"en": "Document selection",
|
|
370
|
+
"tr": ""
|
|
371
|
+
},
|
|
372
|
+
"layout": "layouts/govcyBase.njk", // Page layout
|
|
373
|
+
"mainLayout": "two-third", // Page main layout
|
|
374
|
+
"nextPage": "data-entry-radios" // The next page's URL
|
|
375
|
+
},
|
|
376
|
+
"pageTemplate": { //<-- Page template
|
|
377
|
+
"sections": [ //<-- Page sections
|
|
378
|
+
{
|
|
379
|
+
"name": "main", //<-- Main section
|
|
380
|
+
"elements": [ //<-- Main section elements
|
|
381
|
+
{
|
|
382
|
+
"element": "form", // Form element
|
|
383
|
+
"params": {
|
|
384
|
+
"elements": [ // Elements inside the form
|
|
385
|
+
{
|
|
386
|
+
"element": "checkboxes", // Checkboxes element
|
|
387
|
+
"params": { // Checkboxes parameters
|
|
388
|
+
"id": "certificate_select",
|
|
389
|
+
"name": "certificate_select",
|
|
390
|
+
"legend": {
|
|
391
|
+
"el": "Τι έγγραφα επιθυμείτε να εκδώσετε;",
|
|
392
|
+
"en": "What documents do you wish to issue?"
|
|
393
|
+
},
|
|
394
|
+
"items": [
|
|
395
|
+
{
|
|
396
|
+
"value": "birth",
|
|
397
|
+
"text": {
|
|
398
|
+
"el": "Πιστοποιητικό γέννησης",
|
|
399
|
+
"en": "Birth certificate",
|
|
400
|
+
"tr": ""
|
|
401
|
+
},
|
|
402
|
+
"hint": {
|
|
403
|
+
"el": "Αν η γέννηση έγινε στην Κύπρο ή στο εξωτερικό και έχει ενημερωθεί το μητρώο του Αρχείου Πληθυσμού ",
|
|
404
|
+
"en": "For a birth in Cyprus or abroad which Civil Registry is updated with "
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"value": "permanent_residence",
|
|
409
|
+
"text": {
|
|
410
|
+
"el": "Βεβαίωση μόνιμης διαμονής",
|
|
411
|
+
"en": "Certificate of permanent residence",
|
|
412
|
+
"tr": ""
|
|
413
|
+
},
|
|
414
|
+
"hint": {
|
|
415
|
+
"el": "Για όσους είναι εγγεγραμμένοι στον εκλογικό κατάλογο",
|
|
416
|
+
"en": "For those registered in the electoral list"
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"value": "student_proof_of_origin",
|
|
421
|
+
"text": {
|
|
422
|
+
"el": "Βεβαίωση καταγωγής",
|
|
423
|
+
"en": "Certificate of origin",
|
|
424
|
+
"tr": ""
|
|
425
|
+
},
|
|
426
|
+
"hint": {
|
|
427
|
+
"el": "Για αίτηση σε πανεπιστήμια στην Ελλάδα",
|
|
428
|
+
"en": "To apply to a university in Greece"
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
],
|
|
432
|
+
"isPageHeading": true,
|
|
433
|
+
"hint": {
|
|
434
|
+
"el": "Επιλέξτε ένα ή περισσότερα έγγραφα",
|
|
435
|
+
"en": "Select one or more documents",
|
|
436
|
+
"tr": ""
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
"validations": [ // Checkboxes validations
|
|
440
|
+
{
|
|
441
|
+
"check": "required",
|
|
442
|
+
"params": {
|
|
443
|
+
"checkValue": "",
|
|
444
|
+
"message": {
|
|
445
|
+
"el": "Επιλέξετε ένα ή περισσότερα έγγραφα",
|
|
446
|
+
"en": "Select one or more documents",
|
|
447
|
+
"tr": ""
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
"element": "button",
|
|
455
|
+
"params": {
|
|
456
|
+
"id": "continue",
|
|
457
|
+
"variant": "primary",
|
|
458
|
+
"text": {
|
|
459
|
+
"el": "Συνέχεια",
|
|
460
|
+
"en": "Continue"
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
]
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"pageData": { //<-- 2nd Page's data (form)
|
|
474
|
+
"url": "data-entry-radios",
|
|
475
|
+
"title": {
|
|
476
|
+
"el": "Στοιχεία επικοινωνίας ",
|
|
477
|
+
"en": "Contact details",
|
|
478
|
+
"tr": ""
|
|
479
|
+
},
|
|
480
|
+
"layout": "layouts/govcyBase.njk",
|
|
481
|
+
"mainLayout": "two-third",
|
|
482
|
+
"nextPage": "review"
|
|
483
|
+
},
|
|
484
|
+
"pageTemplate": {
|
|
485
|
+
"sections": [
|
|
486
|
+
{
|
|
487
|
+
"name": "beforeMain",
|
|
488
|
+
"elements": [
|
|
489
|
+
{
|
|
490
|
+
"element": "backLink",
|
|
491
|
+
"params": {}
|
|
492
|
+
}
|
|
493
|
+
]
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
"name": "main",
|
|
497
|
+
"elements": [
|
|
498
|
+
{
|
|
499
|
+
"element": "form",
|
|
500
|
+
"params": {
|
|
501
|
+
"elements": [
|
|
502
|
+
{
|
|
503
|
+
"element": "radios",
|
|
504
|
+
"params": {
|
|
505
|
+
"id": "mobile_select",
|
|
506
|
+
"name": "mobile_select",
|
|
507
|
+
"legend": {
|
|
508
|
+
"el": "Σε ποιο κινητό μπορούμε να επικοινωνήσουμε μαζί σας;",
|
|
509
|
+
"en": "What mobile number can we use to contact you?"
|
|
510
|
+
},
|
|
511
|
+
"items": [
|
|
512
|
+
{
|
|
513
|
+
"value": "mobile",
|
|
514
|
+
"text": {
|
|
515
|
+
"el": "Στο [99 123456]",
|
|
516
|
+
"en": "You can use [99 123456]",
|
|
517
|
+
"tr": ""
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
"value": "other",
|
|
522
|
+
"text": {
|
|
523
|
+
"el": "Θα δώσω άλλο αριθμό",
|
|
524
|
+
"en": "I will give a different number",
|
|
525
|
+
"tr": ""
|
|
526
|
+
},
|
|
527
|
+
"conditionalElements": [
|
|
528
|
+
{
|
|
529
|
+
"element": "fileInput",
|
|
530
|
+
"params": {
|
|
531
|
+
"id": "proof",
|
|
532
|
+
"name": "proof",
|
|
533
|
+
"label": {
|
|
534
|
+
"el": "Αποδεικτικό τηλεφώνου",
|
|
535
|
+
"en": "Telephone proof",
|
|
536
|
+
"tr": ""
|
|
537
|
+
},
|
|
538
|
+
"isPageHeading": false,
|
|
539
|
+
"hint": {
|
|
540
|
+
"el": "PDF, JPG, JPEG, PNG, είναι οι αποδεκτές μορφές",
|
|
541
|
+
"en": "PDF, JPG, JPEG, PNG are the acceptable formats",
|
|
542
|
+
"tr": ""
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
"validations": [
|
|
546
|
+
{
|
|
547
|
+
"check": "required",
|
|
548
|
+
"params": {
|
|
549
|
+
"checkValue": "",
|
|
550
|
+
"message": {
|
|
551
|
+
"el": "Ανεβάστε τον αποδεικτικό τηλεφώνου",
|
|
552
|
+
"en": "Upload the telephone proof",
|
|
553
|
+
"tr": ""
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
]
|
|
558
|
+
}
|
|
559
|
+
]
|
|
560
|
+
}
|
|
561
|
+
],
|
|
562
|
+
"isPageHeading": true
|
|
563
|
+
},
|
|
564
|
+
"validations": [
|
|
565
|
+
{
|
|
566
|
+
"check": "required",
|
|
567
|
+
"params": {
|
|
568
|
+
"checkValue": "",
|
|
569
|
+
"message": {
|
|
570
|
+
"el": "Επιλέξετε αν θέλετε να χρησιμοποιήσετε το τηλέφωνο που φαίνεται εδώ, ή κάποιο άλλο",
|
|
571
|
+
"en": "Choose if you'd like to use the phone number shown here, or a different one",
|
|
572
|
+
"tr": ""
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
]
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
"element": "button",
|
|
580
|
+
"params": {
|
|
581
|
+
"id": "continue",
|
|
582
|
+
"variant": "primary",
|
|
583
|
+
"text": {
|
|
584
|
+
"el": "Συνέχεια",
|
|
585
|
+
"en": "Continue"
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
]
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
]
|
|
593
|
+
}
|
|
594
|
+
]
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
"pageData": { //<-- 3rd Page's data (not a form)
|
|
599
|
+
"url": "user-not-registered",
|
|
600
|
+
"title": {
|
|
601
|
+
"el": "Δεν είστε εγγεγραμμένοι ",
|
|
602
|
+
"en": "You are not an registered",
|
|
603
|
+
"tr": ""
|
|
604
|
+
},
|
|
605
|
+
"layout": "layouts/govcyBase.njk",
|
|
606
|
+
"mainLayout": "two-third"
|
|
607
|
+
},
|
|
608
|
+
"pageTemplate": {
|
|
609
|
+
"sections": [
|
|
610
|
+
{
|
|
611
|
+
"name": "beforeMain",
|
|
612
|
+
"elements": []
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
"name": "main",
|
|
616
|
+
"elements": [
|
|
617
|
+
{
|
|
618
|
+
"element": "textElement",
|
|
619
|
+
"params": {
|
|
620
|
+
"id": "title",
|
|
621
|
+
"type": "h1",
|
|
622
|
+
"text": {
|
|
623
|
+
"el": "Δεν είστε εγγεγραμμένοι",
|
|
624
|
+
"en": "You are not registered"
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
"element": "htmlElement",
|
|
630
|
+
"params": {
|
|
631
|
+
"id": "body",
|
|
632
|
+
"text": {
|
|
633
|
+
"el": "<p>Για να υποβάλετε σε υπηρεσία αυτή, χρειάζεται να είστε εγγεγραμμένοι στο ΧΥΖ.</p>",
|
|
634
|
+
"en": "<p>To submit in this service you need to be registered at XYZ.</p>"
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
]
|
|
639
|
+
}
|
|
640
|
+
]
|
|
641
|
+
}
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
"pageData": { //<-- 4th Page's data (not a form)
|
|
645
|
+
"url": "user-not-admin",
|
|
646
|
+
"title": {
|
|
647
|
+
"el": "Δεν είστε διαχειριστής ",
|
|
648
|
+
"en": "You are not an administrator",
|
|
649
|
+
"tr": ""
|
|
650
|
+
},
|
|
651
|
+
"layout": "layouts/govcyBase.njk",
|
|
652
|
+
"mainLayout": "two-third"
|
|
653
|
+
},
|
|
654
|
+
"pageTemplate": {
|
|
655
|
+
"sections": [
|
|
656
|
+
{
|
|
657
|
+
"name": "beforeMain",
|
|
658
|
+
"elements": []
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
"name": "main",
|
|
662
|
+
"elements": [
|
|
663
|
+
{
|
|
664
|
+
"element": "textElement",
|
|
665
|
+
"params": {
|
|
666
|
+
"id": "title",
|
|
667
|
+
"type": "h1",
|
|
668
|
+
"text": {
|
|
669
|
+
"el": "Δεν είστε διαχειριστής ",
|
|
670
|
+
"en": "You are not an administrator"
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
"element": "htmlElement",
|
|
676
|
+
"params": {
|
|
677
|
+
"id": "body",
|
|
678
|
+
"text": {
|
|
679
|
+
"el": "<p>Για να υποβάλετε σε υπηρεσία αυτή, χρειάζεται να είστε διαχειριστής στο ΧΥΖ.</p>",
|
|
680
|
+
"en": "<p>To submit in this service you need to be an administrator of XYZ.</p>"
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
]
|
|
685
|
+
}
|
|
686
|
+
]
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
]
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
```
|
|
693
|
+
|
|
143
694
|
Here are some details explaining the JSON structure:
|
|
144
695
|
|
|
145
696
|
- `site` object: Contains information about the site, including the site ID, language, and footer links. See [govcy-frontend-renderer](https://github.com/gov-cy/govcy-frontend-renderer/tree/main#site-and-page-meta-data-explained) for more details. Some fields that are only specific to the govcy-express-forms project are the following:
|
|
@@ -155,8 +706,14 @@ Here are some details explaining the JSON structure:
|
|
|
155
706
|
```
|
|
156
707
|
- `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.
|
|
157
708
|
- `submissionAPIEndpoint`: The submission API endpoint, to be used for submitting the form. See more on the [Submission API Endoint](#-site-submissions) section below.
|
|
709
|
+
- `submissionGetAPIEndpoint`: The submission get API endpoint, to be used for getting the submission data. See more on the [temporary save feature](#-temporary-save-feature) section below.
|
|
710
|
+
- `submissionPutAPIEndpoint`: The submission put API endpoint, to be used for temporary saving the submission data. See more on the [temporary save feature](#-temporary-save-feature) section below.
|
|
711
|
+
- `fileUploadAPIEndpoint`: The file upload API endpoint, to be used for uploading files. See more on the [file upload feature](#%EF%B8%8F-files-uploads-feature) section below.
|
|
712
|
+
- `fileDownloadAPIEndpoint`: The file download API endpoint, to be used for downloading files. See more on the [file upload feature](#%EF%B8%8F-files-uploads-feature) section below.
|
|
713
|
+
- `fileDeleteAPIEndpoint`: The file delete API endpoint, to be used for deleting files. See more on the [file upload feature](#%EF%B8%8F-files-uploads-feature) section below.
|
|
158
714
|
- `pages` array: An array of page objects, each representing a page in the site.
|
|
159
715
|
- `pageData` object: Contains the metadata to be rendered on the page. See [govcy-frontend-renderer](https://github.com/gov-cy/govcy-frontend-renderer/tree/main#site-and-page-meta-data-explained) for more details
|
|
716
|
+
- `nextPage`: The URL of the next page to be rendered after the user clicks the `continue` button.
|
|
160
717
|
- `pageTemplate` object: Contains the page template to be rendered on the page. See [govcy-frontend-renderer](https://github.com/gov-cy/govcy-frontend-renderer/tree/main#json-input-template) for more details
|
|
161
718
|
- `elements` array: An array of elements to be rendered on the page. See all supported [govcy-frontend-renderer elements](https://github.com/gov-cy/govcy-frontend-renderer/blob/main/DESIGN_ELEMENTS.md) for more details
|
|
162
719
|
|
|
@@ -211,8 +768,7 @@ Here's an example of a page defined in the JSON file:
|
|
|
211
768
|
"element": "backLink",
|
|
212
769
|
"params": {}
|
|
213
770
|
}
|
|
214
|
-
]
|
|
215
|
-
"params": {}
|
|
771
|
+
]
|
|
216
772
|
},
|
|
217
773
|
{
|
|
218
774
|
"name": "main",
|
|
@@ -297,14 +853,24 @@ Lets break down the JSON config for this page:
|
|
|
297
853
|
- `pageData.nextPage` is the next page to redirect to when the user clicks the `continue` button and all validations pass, in this case it will redirect to `/:siteId/telephone-number`
|
|
298
854
|
- `pageData.conditions` is the array that defines the [conditional logic](#-conditional-logic)
|
|
299
855
|
- **pageTemplate** is the page's template, which is a JSON object that contains the sections and elements of the page. Check out the [govcy-frontend-renderer's documentation](https://github.com/gov-cy/govcy-frontend-renderer/blob/main/README.md) for more details.
|
|
856
|
+
- `sections` is an array of sections, which is an array of elements. Sections allowed: `beforeMain`, `main`, `afterMain`.
|
|
857
|
+
- `elements` is an array of elements for the said section. Seem more details on the [govcy-frontend-renderer's design elements documentation](https://github.com/gov-cy/govcy-frontend-renderer/blob/main/DESIGN_ELEMENTS.md).
|
|
300
858
|
|
|
301
859
|
**Forms vs static content**
|
|
302
860
|
|
|
303
861
|
- If the `pageTemplate` includes a `form` element in the `main` section and `button` element, the system will treat it as form and will:
|
|
304
862
|
- Perform the eligibility checks
|
|
305
863
|
- Display the form
|
|
306
|
-
- Collect the form data
|
|
307
|
-
|
|
864
|
+
- Collect the form data for the following input elements (more details on the [govcy-frontend-renderer's design elements documentation](https://github.com/gov-cy/govcy-frontend-renderer/blob/main/DESIGN_ELEMENTS.md)):
|
|
865
|
+
- `textInput`
|
|
866
|
+
- `textArea`
|
|
867
|
+
- `select`
|
|
868
|
+
- `radios`
|
|
869
|
+
- `checkboxes`
|
|
870
|
+
- `datePicker`
|
|
871
|
+
- `dateInput`
|
|
872
|
+
- `fileInput`: the file upload feature must be enabled to use this element (see more on the [file upload feature](#%EF%B8%8F-files-uploads-feature) section below)
|
|
873
|
+
- Validate the form data (see more on the [Input validations](#-input-validations) section below)
|
|
308
874
|
- Store the form data in the systems data layer
|
|
309
875
|
- Redirect the user to the next page (or `review` page if the user came from the review page)
|
|
310
876
|
- Else if the `pageTemplate` does not include a `form` element in the `main` section, the system will treat it as static content and will:
|
|
@@ -624,14 +1190,14 @@ Accept: text/plain
|
|
|
624
1190
|
Content-Type: application/json
|
|
625
1191
|
|
|
626
1192
|
{
|
|
627
|
-
"
|
|
628
|
-
"
|
|
629
|
-
"
|
|
630
|
-
"
|
|
631
|
-
"
|
|
632
|
-
"
|
|
633
|
-
"
|
|
634
|
-
"
|
|
1193
|
+
"submissionUsername": "username",
|
|
1194
|
+
"submissionEmail": "email@example.com",
|
|
1195
|
+
"submissionData": "{\"index\":{\"certificate_select\":[\"birth\",\"permanent_residence\"]}}",
|
|
1196
|
+
"submissionDataVersion": "1",
|
|
1197
|
+
"printFriendlyData": "[{\"pageUrl\":\"index\",\"pageTitle\":{\"el\":\"Επιλογή Εγγάφου\",\"en\":\"Document selection\",\"tr\":\"\"},\"fields\":[{\"id\":\"certificate_select\",\"name\":\"certificate_select\",\"label\":{\"el\":\"Τι έγγραφα επιθυμείτε να εκδώσετε;\",\"en\":\"What documents do you wish to issue?\"},\"value\":[\"birth\",\"permanent_residence\"],\"valueLabel\":[{\"el\":\"Πιστοποιητικό γέννησης\",\"en\":\"Birth certificate\",\"tr\":\"\"},{\"el\":\"Βεβαίωση μόνιμης διαμονής\",\"en\":\"Certificate of permanent residence\",\"tr\":\"\"}]}]}]",
|
|
1198
|
+
"rendererData": "{\"element\":\"summaryList\",\"params\":{\"items\":[{\"key\":{\"el\":\"Επιλογή Εγγάφου\",\"en\":\"Document selection\",\"tr\":\"\"},\"value\":[{\"element\":\"summaryList\",\"params\":{\"items\":[{\"key\":{\"el\":\"Τι έγγραφα επιθυμείτε να εκδώσετε;\",\"en\":\"What documents do you wish to issue?\"},\"value\":[{\"element\":\"textElement\",\"params\":{\"text\":{\"en\":\"Birth certificate, Certificate of permanent residence\",\"el\":\"Birth certificate, Certificate of permanent residence\",\"tr\":\"Birth certificate, Certificate of permanent residence\"},\"type\":\"span\"}}]}]}}]}]}}",
|
|
1199
|
+
"rendererVersion": "1.14.3",
|
|
1200
|
+
"designSystemsVersion": "3.2.0",
|
|
635
1201
|
"service": "{\"id\":\"test\",\"title\":{\"el\":\"Υπηρεσία τεστ\",\"en\":\"Test service\",\"tr\":\"\"}}"
|
|
636
1202
|
}
|
|
637
1203
|
```
|
|
@@ -682,15 +1248,15 @@ HTTP/1.1 200 OK
|
|
|
682
1248
|
The data is collected from the form elements and the data layer and are sent via the submission API in the following format:
|
|
683
1249
|
|
|
684
1250
|
```json
|
|
685
|
-
|
|
686
|
-
"
|
|
687
|
-
"
|
|
688
|
-
"
|
|
689
|
-
"
|
|
690
|
-
"
|
|
691
|
-
"
|
|
692
|
-
"
|
|
693
|
-
"
|
|
1251
|
+
{
|
|
1252
|
+
"submissionUsername" : "", // User's username
|
|
1253
|
+
"submissionEmail" : "", // User's email
|
|
1254
|
+
"submissionData": "{}", // Raw data as submitted by the user in each page
|
|
1255
|
+
"submissionDataVersion": "",// The submission data version
|
|
1256
|
+
"printFriendlyData": "[]", // Print friendly data
|
|
1257
|
+
"rendererData" :"{}", // Renderer data of the summary list
|
|
1258
|
+
"rendererVersion": "", // The renderer version
|
|
1259
|
+
"designSystemsVersion": "", // The design systems version
|
|
694
1260
|
"service": "{}" // Service info
|
|
695
1261
|
}
|
|
696
1262
|
```
|
|
@@ -701,50 +1267,49 @@ The data is collected from the form elements and the data layer and are sent via
|
|
|
701
1267
|
|
|
702
1268
|
> ℹ️ **Note:**
|
|
703
1269
|
>
|
|
704
|
-
> When sent to the API, the fields `
|
|
1270
|
+
> When sent to the API, the fields `submissionData`, `rendererData`, `printFriendlyData`, and `service` are stringified using `JSON.stringify()`.
|
|
705
1271
|
>
|
|
706
1272
|
> The sample below shows the structure **before** stringification for clarity.
|
|
707
1273
|
|
|
708
1274
|
```json
|
|
709
1275
|
{
|
|
710
|
-
"
|
|
711
|
-
"
|
|
712
|
-
"
|
|
713
|
-
"
|
|
1276
|
+
"submissionUsername": "username", // User's username
|
|
1277
|
+
"submissionEmail": "email@example.com", // User's email
|
|
1278
|
+
"submissionDataVersion": "0.1", // Submission data version
|
|
1279
|
+
"submissionData": { // Submission raw data. Object, will be stringified
|
|
714
1280
|
"index": { // Page level
|
|
715
|
-
"
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
1281
|
+
"id_select": ["id", "arc"], // field level: checkboxes are ALWAYS arrays (may be []); radios/select/text are strings
|
|
1282
|
+
"id_number": "654654",
|
|
1283
|
+
"arc_number": "",
|
|
1284
|
+
"aka": "232323",
|
|
1285
|
+
"evidenceAttachment": // File attachments contains an object with `fileId` and `sha256`
|
|
1286
|
+
{
|
|
1287
|
+
"fileId": "1234567891234567890",
|
|
1288
|
+
"sha256": "123456789012345678901234567890123456789012345678901234567890123456"
|
|
1289
|
+
}
|
|
721
1290
|
},
|
|
722
1291
|
"appointment": {
|
|
723
|
-
"
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
"fileno_orismenou": ""
|
|
733
|
-
}
|
|
1292
|
+
"diorismos": "monimos",
|
|
1293
|
+
"fileno_monimos": "3233",
|
|
1294
|
+
"eidikotita_monimos": "1",
|
|
1295
|
+
"fileno_sumvasiouxos": "",
|
|
1296
|
+
"eidikotita_sumvasiouxos": "",
|
|
1297
|
+
"fileno_aoristou": "",
|
|
1298
|
+
"eidikotita_aoristou": "",
|
|
1299
|
+
"program": "",
|
|
1300
|
+
"fileno_orismenou": ""
|
|
734
1301
|
},
|
|
735
1302
|
"takeover": {
|
|
736
|
-
"
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
"reason": "24324dssf"
|
|
743
|
-
}
|
|
1303
|
+
"date_start_day": "11",
|
|
1304
|
+
"date_start_month": "12",
|
|
1305
|
+
"date_start_year": "2020",
|
|
1306
|
+
"date_on_contract": "date_other",
|
|
1307
|
+
"date_contract": "16/04/2025",
|
|
1308
|
+
"reason": "24324dssf"
|
|
744
1309
|
}
|
|
745
1310
|
},
|
|
746
|
-
"
|
|
747
|
-
"
|
|
1311
|
+
"submissionDataVersion": "1", // Submission data version
|
|
1312
|
+
"rendererData": { // Summary list renderer data ready for rendering . Object, will be stringified
|
|
748
1313
|
"element": "summaryList",
|
|
749
1314
|
"params": {
|
|
750
1315
|
"items": [
|
|
@@ -951,7 +1516,7 @@ The data is collected from the form elements and the data layer and are sent via
|
|
|
951
1516
|
]
|
|
952
1517
|
}
|
|
953
1518
|
},
|
|
954
|
-
"
|
|
1519
|
+
"printFriendlyData": [ // Print friendly data. Object, will be stringified
|
|
955
1520
|
{
|
|
956
1521
|
"pageUrl": "index", // Page URL
|
|
957
1522
|
"pageTitle": { // Page title
|
|
@@ -966,8 +1531,8 @@ The data is collected from the form elements and the data layer and are sent via
|
|
|
966
1531
|
"el": "Ταυτοποίηση",
|
|
967
1532
|
"en": "Identification"
|
|
968
1533
|
},
|
|
969
|
-
"value": ["id", "arc"], // Field value.
|
|
970
|
-
"valueLabel": [ // Field value label
|
|
1534
|
+
"value": ["id", "arc"], // Field value. // field level: checkboxes are ALWAYS arrays (may be []); radios/select/text are strings
|
|
1535
|
+
"valueLabel": [ // Field value label
|
|
971
1536
|
{
|
|
972
1537
|
"el": "Ταυτότητα",
|
|
973
1538
|
"en": "ID",
|
|
@@ -1114,8 +1679,8 @@ The data is collected from the form elements and the data layer and are sent via
|
|
|
1114
1679
|
]
|
|
1115
1680
|
}
|
|
1116
1681
|
],
|
|
1117
|
-
"
|
|
1118
|
-
"
|
|
1682
|
+
"rendererVersion": "1.14.1", // Renderer version
|
|
1683
|
+
"designSystemsVersion": "3.1.0", // Design systems version
|
|
1119
1684
|
"service": { // Service metadata. Object, will be stringified
|
|
1120
1685
|
"id": "takeover",
|
|
1121
1686
|
"title": {
|
|
@@ -1139,6 +1704,7 @@ The project includes input validation for the following elements:
|
|
|
1139
1704
|
- `checkboxes`
|
|
1140
1705
|
- `datePicker`
|
|
1141
1706
|
- `dateInput`
|
|
1707
|
+
- `fileInput` (only required check)
|
|
1142
1708
|
|
|
1143
1709
|
The validation rules for each element are defined in the `"validations` array for each element. The project support the following validations:
|
|
1144
1710
|
|
|
@@ -1194,7 +1760,7 @@ Example:
|
|
|
1194
1760
|
]
|
|
1195
1761
|
```
|
|
1196
1762
|
|
|
1197
|
-
###
|
|
1763
|
+
### 🔀 Conditional logic
|
|
1198
1764
|
|
|
1199
1765
|
The project supports conditional logic on pages. Conditional logic is evaluated using a custom `govcyExpressions.mjs` module, which executes expressions in a safe and scoped context using `new Function`. Only safe data access through the `dataLayer` is allowed. The system uses expressions and session data from the service's [data layer](NOTES.md#data-layer) to decide if a page will be shown or not.
|
|
1200
1766
|
|
|
@@ -1422,12 +1988,12 @@ Explanation:
|
|
|
1422
1988
|
- `[].concat(...)`: safely flattens a string or array into an array.
|
|
1423
1989
|
- `.includes('value1')`: checks if the value is selected.
|
|
1424
1990
|
|
|
1425
|
-
### 💾 Temporary save
|
|
1991
|
+
### 💾 Temporary save feature
|
|
1426
1992
|
|
|
1427
1993
|
The **temporary save** feature allows user progress to be stored in an external API and automatically reloaded on the next visit.
|
|
1428
1994
|
This is useful for long forms or cases where users may leave and return later.
|
|
1429
1995
|
|
|
1430
|
-
#### How to configure temporary save
|
|
1996
|
+
#### How to enable and configure temporary save
|
|
1431
1997
|
To use this feature, configure the config JSON file. In your service’s `site` object, add both a `submissionGetAPIEndpoint` and `submissionPutAPIEndpoint` entry:
|
|
1432
1998
|
|
|
1433
1999
|
```json
|
|
@@ -1464,7 +2030,7 @@ TEST_SUBMISSION_API_SERVICE_ID=123
|
|
|
1464
2030
|
3. If not found, call the PUT endpoint to create a new temporary record.
|
|
1465
2031
|
- **On every form POST**, after successful validation:
|
|
1466
2032
|
- The `submissionPutAPIEndpoint` will fire-and-forget a `PUT` request to update the saved submission with the latest form data.
|
|
1467
|
-
- The payload includes all required submission fields with `
|
|
2033
|
+
- The payload includes all required submission fields with `submissionData` JSON-stringified.
|
|
1468
2034
|
|
|
1469
2035
|
#### `submissionGetAPIEndpoint` `GET` API Request and Response
|
|
1470
2036
|
This API is used to retrieve the saved submission data.
|
|
@@ -1565,7 +2131,7 @@ Accept: text/plain
|
|
|
1565
2131
|
Content-Type: application/json
|
|
1566
2132
|
|
|
1567
2133
|
{
|
|
1568
|
-
"
|
|
2134
|
+
"submissionData" : "{\"index\":{\"formData\":{\"certificate_select\":[\"birth\",\"permanent_residence\"]}},\"data-entry-radios\":{\"formData\":{\"mobile_select\":\"other\",\"mobileTxt\":\"+35799484967\"}}}"
|
|
1569
2135
|
}
|
|
1570
2136
|
```
|
|
1571
2137
|
|
|
@@ -1608,6 +2174,384 @@ HTTP/1.1 401 Unauthorized
|
|
|
1608
2174
|
If these endpoints are not defined in the service JSON, the temporary save/load logic is skipped entirely.
|
|
1609
2175
|
Existing services will continue to work without modification.
|
|
1610
2176
|
|
|
2177
|
+
### 🗃️ Files uploads feature
|
|
2178
|
+
|
|
2179
|
+
The **Files uploads** feature allows user progress to upload, remove and download files. The files will be stored in an external API and automatically reloaded on the next visit.
|
|
2180
|
+
|
|
2181
|
+
#### Pre-requisites for the files uploads feature
|
|
2182
|
+
The [💾 Temporary save feature](#-temporary-save-feature) must be enabled for the file uploads feature to work.
|
|
2183
|
+
|
|
2184
|
+
|
|
2185
|
+
#### How to enable and configure file uploads
|
|
2186
|
+
To use this feature, configure the config JSON file. In your service’s `site` object, add a `fileUploadAPIEndpoint`, `fileDownloadAPIEndpoint`and `fileDeleteAPIEndpoint` entry:
|
|
2187
|
+
|
|
2188
|
+
```json
|
|
2189
|
+
"fileUploadAPIEndpoint": {
|
|
2190
|
+
"url": "TEST_UPLOAD_FILE_API_URL",
|
|
2191
|
+
"method": "POST",
|
|
2192
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
2193
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID"
|
|
2194
|
+
},
|
|
2195
|
+
"fileDownloadAPIEndpoint": {
|
|
2196
|
+
"url": "TEST_DOWNLOAD_FILE_API_URL",
|
|
2197
|
+
"method": "GET",
|
|
2198
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
2199
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID"
|
|
2200
|
+
},
|
|
2201
|
+
"fileDeleteAPIEndpoint": {
|
|
2202
|
+
"url": "TEST_DELETE_FILE_API_URL",
|
|
2203
|
+
"method": "DELETE",
|
|
2204
|
+
"clientKey": "TEST_SUBMISSION_API_CLIENT_KEY",
|
|
2205
|
+
"serviceId": "TEST_SUBMISSION_API_SERVIVE_ID"
|
|
2206
|
+
}
|
|
2207
|
+
```
|
|
2208
|
+
|
|
2209
|
+
These values should point to environment variables that hold your real endpoint URLs and credentials.
|
|
2210
|
+
|
|
2211
|
+
In your `secrets/.env` file (and staging/production configs), define the variables referenced above:
|
|
2212
|
+
|
|
2213
|
+
```dotenv
|
|
2214
|
+
TEST_UPLOAD_FILE_API_URL=https://example.com/api/fileUpload
|
|
2215
|
+
TEST_DOWNLOAD_FILE_API_URL=https://example.com/api/fileDownload
|
|
2216
|
+
TEST_SUBMISSION_API_CLIENT_KEY=12345678901234567890123456789000
|
|
2217
|
+
TEST_SUBMISSION_API_SERVICE_ID=123
|
|
2218
|
+
```
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
#### How to define the file input field in the JSON config
|
|
2222
|
+
The files input field is defined under the `pages[i].pageTemplate.sections["main"].elements[0].elements` array. Basically it must exist in the page template of a page inside a form.
|
|
2223
|
+
|
|
2224
|
+
The element type for files input is `fileInput` (see it's definition in [govcy-frontend-renderer](https://github.com/gov-cy/govcy-frontend-renderer/blob/main/DESIGN_ELEMENTS.md))
|
|
2225
|
+
|
|
2226
|
+
Here is a sample code section of a page definition with a file input field:
|
|
2227
|
+
|
|
2228
|
+
```json
|
|
2229
|
+
{
|
|
2230
|
+
"pageData": {
|
|
2231
|
+
"url": "data-entry-file",
|
|
2232
|
+
"title": {
|
|
2233
|
+
"el": "Λογαριασμός κινήσεως",
|
|
2234
|
+
"en": "Utility bill"
|
|
2235
|
+
},
|
|
2236
|
+
"layout": "layouts/govcyBase.njk",
|
|
2237
|
+
"mainLayout": "two-third",
|
|
2238
|
+
"nextPage": "data-entry-all"
|
|
2239
|
+
},
|
|
2240
|
+
"pageTemplate": {
|
|
2241
|
+
"sections": [
|
|
2242
|
+
{
|
|
2243
|
+
"name": "beforeMain",
|
|
2244
|
+
"elements": [
|
|
2245
|
+
{
|
|
2246
|
+
"element": "backLink",
|
|
2247
|
+
"params": {}
|
|
2248
|
+
}
|
|
2249
|
+
]
|
|
2250
|
+
},
|
|
2251
|
+
{
|
|
2252
|
+
"name": "main",
|
|
2253
|
+
"elements": [
|
|
2254
|
+
{
|
|
2255
|
+
"element": "form",
|
|
2256
|
+
"params": {
|
|
2257
|
+
"elements": [
|
|
2258
|
+
{
|
|
2259
|
+
"element": "fileInput", //<-- this is the file input
|
|
2260
|
+
"params": {
|
|
2261
|
+
"id": "utility",
|
|
2262
|
+
"name": "utility",
|
|
2263
|
+
"label": {
|
|
2264
|
+
"el": "Λογαριασμός κινήσεως",
|
|
2265
|
+
"en": "Utility bill"
|
|
2266
|
+
},
|
|
2267
|
+
"isPageHeading": true,
|
|
2268
|
+
"hint": {
|
|
2269
|
+
"el": "PDF, JPG, JPEG, PNG, είναι οι αποδεκτές μορφές",
|
|
2270
|
+
"en": "PDF, JPG, JPEG, PNG are the acceptable formats"
|
|
2271
|
+
}
|
|
2272
|
+
},
|
|
2273
|
+
"validations": [ //<-- this is the file input validations
|
|
2274
|
+
{
|
|
2275
|
+
"check": "required",
|
|
2276
|
+
"params": {
|
|
2277
|
+
"checkValue": "",
|
|
2278
|
+
"message": {
|
|
2279
|
+
"el": "Ανεβάστε τον λογαριασμό κινήσεως",
|
|
2280
|
+
"en": "Upload the utility bill"
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
]
|
|
2285
|
+
},
|
|
2286
|
+
{
|
|
2287
|
+
"element": "button",
|
|
2288
|
+
"params": {
|
|
2289
|
+
"id": "continue",
|
|
2290
|
+
"variant": "primary",
|
|
2291
|
+
"text": {
|
|
2292
|
+
"el": "Συνέχεια",
|
|
2293
|
+
"en": "Continue"
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
]
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
]
|
|
2301
|
+
}
|
|
2302
|
+
]
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
```
|
|
2306
|
+
|
|
2307
|
+
#### How file uploads works
|
|
2308
|
+
|
|
2309
|
+
- **On a form page with an upload input field**:
|
|
2310
|
+
- **On first load**: the page displays the fileInput field to choose a file.
|
|
2311
|
+
- **On choosing a file**: the file is uploaded to the `fileUploadAPIEndpoint` endpoint.
|
|
2312
|
+
- The `fileUploadAPIEndpoint` validates the input for allowed file types and file size. On validation error an error message is displayed. The following validations are performed:
|
|
2313
|
+
- The fileInput element is defined in the JSON config
|
|
2314
|
+
- API endpoints and environment variables are defined
|
|
2315
|
+
- The page is not skiped because of conditional logic
|
|
2316
|
+
- The file is not empty
|
|
2317
|
+
- The file size must be less than 4MB
|
|
2318
|
+
- The file type must be one of the following: pdf, jpg, jpeg, png
|
|
2319
|
+
- If `fileUploadAPIEndpoint` returns an success, the file is uploaded temporarilly and the `fileView` element is displayed, with links to `View` or `Delete` the file. The file infomation are store in the data layer of the page.
|
|
2320
|
+
- **On a form page after upload**:
|
|
2321
|
+
- The `fileView` element is displayed with links to `View` or `Delete` the file.
|
|
2322
|
+
- **When clinking `view`**:
|
|
2323
|
+
- The file is downloaded using the `fileDownloadAPIEndpoint` and opened in a new tab.
|
|
2324
|
+
- **When clinking `delete`**:
|
|
2325
|
+
- A confimation page is displayed asking the user to confirm the deletion. If the user confirms (clicks `Yes`):
|
|
2326
|
+
- The file is deleted using the `fileDeleteAPIEndpoint`
|
|
2327
|
+
- The file is deleted from the data layer and the `fileView` element is removed from the page.
|
|
2328
|
+
- If the same file is used on another page (with the same `fileId` and `sha256`), they are also removed from the data layer
|
|
2329
|
+
- **On the `review` page after upload**:
|
|
2330
|
+
- The element is displayed with a link to `View file`. A `Change` link is also displayed for the whole page.
|
|
2331
|
+
- **On the `success` page and email after upload**:
|
|
2332
|
+
- The element is displayed with links a marking `File uploaded`.
|
|
2333
|
+
|
|
2334
|
+
|
|
2335
|
+
#### `fileUploadAPIEndpoint` `POST` API Request and Response
|
|
2336
|
+
This API is used to temporarily store the file uploaded by the user. The API connects the file with a temporary saved submission, for the specific user and service. It does not create a connection with the actual field on the specific page, that is done by the `submissionPutAPIEndpoint` API.
|
|
2337
|
+
|
|
2338
|
+
**Request:**
|
|
2339
|
+
|
|
2340
|
+
- **HTTP Method**: POST
|
|
2341
|
+
- **URL**: Resolved from the url property in your config (from the environment variable) concatenated with `/:tag` which defines the type of the file (for example `passport`). For example `https://example.com/api/fileUpload/:tag`
|
|
2342
|
+
- **Headers**:
|
|
2343
|
+
- **Authorization**: `Bearer <access_token>` (form user's cyLogin access token)
|
|
2344
|
+
- **client-key**: `<clientKey>` (from config/env)
|
|
2345
|
+
- **service-id**: `<serviceId>` (from config/env)
|
|
2346
|
+
- **Accept**: `application/json`
|
|
2347
|
+
- **Content-Type**: `multipart/form-data` (typically automatically set when using FormData in the browser)
|
|
2348
|
+
- **Body (multipart/form-data)**: The body the actual file to be uploaded (PDF, JPEG, etc.)
|
|
2349
|
+
|
|
2350
|
+
**Example Request:**
|
|
2351
|
+
|
|
2352
|
+
``` bash
|
|
2353
|
+
curl --location 'https://example.gov.cy/api/v1/files/upload/passport' \
|
|
2354
|
+
--header 'client-key: 12345678901234567890123456789000' \
|
|
2355
|
+
--header 'service-id: 123' \
|
|
2356
|
+
--header 'Authorization: Bearer eyJhbGciOi...' \
|
|
2357
|
+
--form 'file=@"/path/to/file.pdf"'
|
|
2358
|
+
```
|
|
2359
|
+
|
|
2360
|
+
**Response:**
|
|
2361
|
+
|
|
2362
|
+
The API is expected to return a JSON response with the following structure:
|
|
2363
|
+
|
|
2364
|
+
**On success:**
|
|
2365
|
+
|
|
2366
|
+
```http
|
|
2367
|
+
HTTP/1.1 200 OK
|
|
2368
|
+
|
|
2369
|
+
{
|
|
2370
|
+
"ErrorCode": 0,
|
|
2371
|
+
"ErrorMessage": null,
|
|
2372
|
+
"Data": {
|
|
2373
|
+
"fileId": "6899adac8864bf90a90047c3",
|
|
2374
|
+
"fileName": "passport.pdf",
|
|
2375
|
+
"contentType": "application/pdf",
|
|
2376
|
+
"fileSize": 4721123,
|
|
2377
|
+
"sha256": "8adb79e0e782280dad8beb227333a21796b8e01d019ab1e84cfea89a523b0e7d",
|
|
2378
|
+
"description": "passport.pdf",
|
|
2379
|
+
"tag": "passport"
|
|
2380
|
+
},
|
|
2381
|
+
"Succeeded": true
|
|
2382
|
+
}
|
|
2383
|
+
```
|
|
2384
|
+
|
|
2385
|
+
**On failure:**
|
|
2386
|
+
|
|
2387
|
+
```http
|
|
2388
|
+
HTTP/1.1 400
|
|
2389
|
+
|
|
2390
|
+
{
|
|
2391
|
+
"ErrorCode": 400,
|
|
2392
|
+
"ErrorMessage": "SUBMISSION_REQUIRED",
|
|
2393
|
+
"Data": null,
|
|
2394
|
+
"Succeeded": false
|
|
2395
|
+
}
|
|
2396
|
+
```
|
|
2397
|
+
|
|
2398
|
+
#### `fileDownloadAPIEndpoint` `GET` API Request and Response
|
|
2399
|
+
This API is used to download the file uploaded by the user. It returns the file data in Base64.
|
|
2400
|
+
|
|
2401
|
+
**Request:**
|
|
2402
|
+
|
|
2403
|
+
- **HTTP Method**: GET
|
|
2404
|
+
- **URL**: Resolved from the url property in your config (from the environment variable) concatenated with `/:refernceValue/:fileid/:sha256`. For example `https://example.com/api/fileDownload/1234567890/123456789123456/12345678901234567890123`:
|
|
2405
|
+
- `referenceValue` is the `referenceValue` of the file current temporary saved instance (see more [💾 Temporary save feature](#-temporary-save-feature)).
|
|
2406
|
+
- `fileid` is the `fileId` of the file uploaded by the user.
|
|
2407
|
+
- `sha256` is the `sha256` of the file uploaded by the user.
|
|
2408
|
+
- **Headers**:
|
|
2409
|
+
- **Authorization**: `Bearer <access_token>` (form user's cyLogin access token)
|
|
2410
|
+
- **client-key**: `<clientKey>` (from config/env)
|
|
2411
|
+
- **service-id**: `<serviceId>` (from config/env)
|
|
2412
|
+
- **Accept**: `text/plain`
|
|
2413
|
+
|
|
2414
|
+
**Example Request:**
|
|
2415
|
+
|
|
2416
|
+
```http
|
|
2417
|
+
GET fileDownload/1234567890/123456789123456/12345678901234567890123 HTTP/1.1
|
|
2418
|
+
Host: localhost:3002
|
|
2419
|
+
Authorization: Bearer eyJhbGciOi...
|
|
2420
|
+
client-key: 12345678901234567890123456789000
|
|
2421
|
+
service-id: 123
|
|
2422
|
+
Accept: text/plain
|
|
2423
|
+
Content-Type: application/json
|
|
2424
|
+
```
|
|
2425
|
+
|
|
2426
|
+
**Response:**
|
|
2427
|
+
|
|
2428
|
+
The API is expected to return a JSON response with the following structure:
|
|
2429
|
+
|
|
2430
|
+
**When file is found:**
|
|
2431
|
+
|
|
2432
|
+
```http
|
|
2433
|
+
HTTP/1.1 200 OK
|
|
2434
|
+
|
|
2435
|
+
{
|
|
2436
|
+
"ErrorCode": 0,
|
|
2437
|
+
"ErrorMessage": null,
|
|
2438
|
+
"Data": {
|
|
2439
|
+
"fileId": "123456789123456",
|
|
2440
|
+
"fileName": "passport.pdf",
|
|
2441
|
+
"contentType": "application/pdf",
|
|
2442
|
+
"fileSize": 1872,
|
|
2443
|
+
"sha256": "12345678901234567890123456789012345678901234567890123456789012345",
|
|
2444
|
+
"base64": "JVBERi0xLjMKJZOMi54gUm....
|
|
2445
|
+
",
|
|
2446
|
+
"description": null,
|
|
2447
|
+
"uid": null,
|
|
2448
|
+
"tag": "Passport"
|
|
2449
|
+
},
|
|
2450
|
+
"Succeeded": true
|
|
2451
|
+
}
|
|
2452
|
+
```
|
|
2453
|
+
|
|
2454
|
+
**When file is NOT found:**
|
|
2455
|
+
|
|
2456
|
+
```http
|
|
2457
|
+
HTTP/1.1 404 Not Found
|
|
2458
|
+
|
|
2459
|
+
{
|
|
2460
|
+
"ErrorCode": 404,
|
|
2461
|
+
"ErrorMessage": "File not found",
|
|
2462
|
+
"InformationMessage": null,
|
|
2463
|
+
"Data": null,
|
|
2464
|
+
"Succeeded": false
|
|
2465
|
+
}
|
|
2466
|
+
```
|
|
2467
|
+
|
|
2468
|
+
#### `fileDeleteAPIEndpoint` `DELETE` API Request and Response
|
|
2469
|
+
This API is used to delete the file uploaded by the user. It returns the file data in Base64.
|
|
2470
|
+
> ⚠️ **Important note:**
|
|
2471
|
+
> If the same file (same `fileId` and `sha256`) is used for other fields in the same application for the same service and the same user, when deleted it will be removed from all instances in the data layer. A warning will appear in the user's delete confirmation page to warn the users in such cases.
|
|
2472
|
+
|
|
2473
|
+
**Request:**
|
|
2474
|
+
|
|
2475
|
+
- **HTTP Method**: DELETE
|
|
2476
|
+
- **URL**: Resolved from the url property in your config (from the environment variable) concatenated with `/:fileid/:sha256`. For example `https://example.com/api/fileDelete/123456789123456/12345678901234567890123`:
|
|
2477
|
+
- `fileid` is the `fileId` of the file uploaded by the user.
|
|
2478
|
+
- `sha256` is the `sha256` of the file uploaded by the user.
|
|
2479
|
+
- **Headers**:
|
|
2480
|
+
- **Authorization**: `Bearer <access_token>` (form user's cyLogin access token)
|
|
2481
|
+
- **client-key**: `<clientKey>` (from config/env)
|
|
2482
|
+
- **service-id**: `<serviceId>` (from config/env)
|
|
2483
|
+
- **Accept**: `text/plain`
|
|
2484
|
+
|
|
2485
|
+
**Example Request:**
|
|
2486
|
+
|
|
2487
|
+
```http
|
|
2488
|
+
DELETE fileDelete/123456789123456/12345678901234567890123 HTTP/1.1
|
|
2489
|
+
Host: localhost:3002
|
|
2490
|
+
Authorization: Bearer eyJhbGciOi...
|
|
2491
|
+
client-key: 12345678901234567890123456789000
|
|
2492
|
+
service-id: 123
|
|
2493
|
+
Accept: text/plain
|
|
2494
|
+
Content-Type: application/json
|
|
2495
|
+
```
|
|
2496
|
+
|
|
2497
|
+
**Response:**
|
|
2498
|
+
|
|
2499
|
+
The API is expected to return a JSON response with the following structure:
|
|
2500
|
+
|
|
2501
|
+
**When file is found and deleted:**
|
|
2502
|
+
|
|
2503
|
+
```http
|
|
2504
|
+
HTTP/1.1 200 OK
|
|
2505
|
+
|
|
2506
|
+
{
|
|
2507
|
+
"ErrorCode": 0,
|
|
2508
|
+
"ErrorMessage": null,
|
|
2509
|
+
"Succeeded": true
|
|
2510
|
+
}
|
|
2511
|
+
```
|
|
2512
|
+
|
|
2513
|
+
**When file is NOT found:**
|
|
2514
|
+
|
|
2515
|
+
```http
|
|
2516
|
+
HTTP/1.1 404 Not Found
|
|
2517
|
+
|
|
2518
|
+
{
|
|
2519
|
+
"ErrorCode": 404,
|
|
2520
|
+
"ErrorMessage": "File not found",
|
|
2521
|
+
"InformationMessage": null,
|
|
2522
|
+
"Data": null,
|
|
2523
|
+
"Succeeded": false
|
|
2524
|
+
}
|
|
2525
|
+
```
|
|
2526
|
+
|
|
2527
|
+
#### File uploads in the data layer
|
|
2528
|
+
The system uses the `fileId` and `sha256` to identify the file uploaded by the user. The file information are stored in the data layer in the following format:
|
|
2529
|
+
|
|
2530
|
+
```json
|
|
2531
|
+
{
|
|
2532
|
+
"fileId": "1234567891234567890",
|
|
2533
|
+
"sha256": "123456789012345678901234567890123456789012345678901234567890123456"
|
|
2534
|
+
}
|
|
2535
|
+
```
|
|
2536
|
+
|
|
2537
|
+
#### File uploads when submitted
|
|
2538
|
+
When the user submits the service through the submission API endpoint, the system will use the `fileId` and `sha256` to identify the file uploaded by the user. The actuall file is already uploaded via the `fileUploadAPIEndpoint`.
|
|
2539
|
+
|
|
2540
|
+
To help back-end systems recognize the field as a file, the field's element name is concatenated with `Attachment`. For example, if for the field `passport`, the data will be submitted as follows:
|
|
2541
|
+
|
|
2542
|
+
```json
|
|
2543
|
+
{
|
|
2544
|
+
"passportAttachment": {
|
|
2545
|
+
"fileId": "1234567891234567890",
|
|
2546
|
+
"sha256": "123456789012345678901234567890123456789012345678901234567890123456"
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
```
|
|
2550
|
+
|
|
2551
|
+
#### File uploads backward compatibility
|
|
2552
|
+
If these endpoints are not defined in the service JSON, the file upload logic is skipped entirely.
|
|
2553
|
+
Existing services will continue to work without modification.
|
|
2554
|
+
|
|
1611
2555
|
### 🛣️ Routes
|
|
1612
2556
|
The project uses express.js to serve the following routes:
|
|
1613
2557
|
|
|
@@ -1616,16 +2560,18 @@ The project uses express.js to serve the following routes:
|
|
|
1616
2560
|
- **`/:siteId/:pageUrl`**: Requires **cyLogin** authentication for **authorized individual users**. Based on `/data/:siteId.json`, Renders the specified page template. Validates page and saves data to session. If validation fails, errors are displayed with links to the inputs.
|
|
1617
2561
|
- **`/:siteId/review`**: Requires **cyLogin** authentication for **authorized individual users**. Renders the check your answers page template. Validates all pages in the service and submits the data to the configured API endpoint. If validation fails, errors are displayed with links to the relevant pages.
|
|
1618
2562
|
- **`/:siteId/success`**: Requires **cyLogin** authentication for **authorized individual users**. Renders latest successful submission.
|
|
1619
|
-
- **`/:siteId/
|
|
2563
|
+
- **`/:siteId/:pageUrl/view-file/:elementName`**: Requires **cyLogin** authentication for **authorized individual users**. Renders the specified file in a new tab.
|
|
2564
|
+
- **`/:siteId/:pageUrl/delete-file/:elementName`**: Requires **cyLogin** authentication for **authorized individual users**. Renders the delete confirmation page and handles the file delete.
|
|
1620
2565
|
|
|
1621
2566
|
#### Authentication routes:
|
|
1622
2567
|
- **`/signin-oidc`**: CY Login authentication endpoint.
|
|
1623
2568
|
- **`/login`**: Redirect to CY Login login page.
|
|
1624
2569
|
- **`/logout`**: CY Login logout endpoint.
|
|
1625
2570
|
|
|
1626
|
-
|
|
2571
|
+
#### API routes:
|
|
2572
|
+
- **`/apis/:siteId/:pageUrl/upload`**: Uploads a file. Used from the client side JS.
|
|
1627
2573
|
|
|
1628
|
-
### 👨💻
|
|
2574
|
+
### 👨💻 Environment variables
|
|
1629
2575
|
The environment variables are defined in:
|
|
1630
2576
|
- **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`.
|
|
1631
2577
|
- **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:
|
|
@@ -1696,10 +2642,14 @@ TEST_SUBMISSION_API_CLIENT_KEY=12345678901234567890123456789000
|
|
|
1696
2642
|
TEST_SUBMISSION_API_SERVIVE_ID=123
|
|
1697
2643
|
TEST_SUBMISSION_DSF_GTW_KEY=12345678901234567890123456789000
|
|
1698
2644
|
|
|
1699
|
-
# Optional Temporary Save GET and PUT
|
|
2645
|
+
# Optional Temporary Save GET and PUT endpoints (test service)
|
|
1700
2646
|
TEST_SUBMISSION_GET_API_URL=http://localhost:3002/getTempSubmission
|
|
1701
2647
|
TEST_SUBMISSION_PUT_API_URL=http://localhost:3002/save
|
|
1702
2648
|
|
|
2649
|
+
# Optional File Upload and download endpoints (test service)
|
|
2650
|
+
TEST_FILE_UPLOAD_API_URL=http://localhost:3002/fileUpload
|
|
2651
|
+
TEST_FILE_DOWNLOAD_API_URL=http://localhost:3002/fileDownload
|
|
2652
|
+
TEST_FILE_DELETE_API_URL=http://localhost:3002/fileDelete
|
|
1703
2653
|
|
|
1704
2654
|
# Eligibility checks (optional test APIs)
|
|
1705
2655
|
TEST_ELIGIBILITY_1_API_URL=http://localhost:3002/eligibility1
|