@gov-cy/govcy-express-services 1.0.0-alpha.8 → 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 +13 -2
- 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 +3 -6
- 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 +201 -77
- package/src/public/js/govcyForms.js +19 -8
- package/src/resources/govcyResources.mjs +57 -7
- package/src/utils/govcyConstants.mjs +1 -1
- package/src/utils/govcyDataLayer.mjs +192 -14
- package/src/utils/govcyFormHandling.mjs +8 -4
- package/src/utils/govcyHandleFiles.mjs +23 -13
- package/src/utils/govcySubmitData.mjs +162 -109
|
@@ -79,7 +79,10 @@ export function govcyReviewPageHandler() {
|
|
|
79
79
|
//--------- End Handle Validation Errors ---------
|
|
80
80
|
|
|
81
81
|
// Add elements to the main section, the H1, summary list, the submit button and the JS
|
|
82
|
-
mainElements.push(pageH1,
|
|
82
|
+
mainElements.push(pageH1,
|
|
83
|
+
summaryList,
|
|
84
|
+
submitButton
|
|
85
|
+
);
|
|
83
86
|
// Append generated summary list to the page template
|
|
84
87
|
pageTemplate.sections.push({ name: "main", elements: mainElements });
|
|
85
88
|
|
|
@@ -118,7 +118,7 @@ export function govcyReviewPostHandler() {
|
|
|
118
118
|
|
|
119
119
|
//-- Send email to user
|
|
120
120
|
// Generate the email body
|
|
121
|
-
let emailBody = generateSubmitEmail(service, submissionData.
|
|
121
|
+
let emailBody = generateSubmitEmail(service, submissionData.printFriendlyData, referenceNo, req);
|
|
122
122
|
logger.debug("Email generated:", emailBody);
|
|
123
123
|
// Send the email
|
|
124
124
|
sendEmail(service.site.title[service.site.lang],emailBody,[dataLayer.getUser(req.session).email], "eMail").catch(err => {
|
|
@@ -78,7 +78,7 @@ export function govcySuccessPageHandler(isPDF = false) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
let summaryList = submissionData.
|
|
81
|
+
let summaryList = submissionData.rendererData;
|
|
82
82
|
|
|
83
83
|
let mainElements = [];
|
|
84
84
|
// Add elements to the main section
|
|
@@ -87,8 +87,7 @@ export function govcySuccessPageHandler(isPDF = false) {
|
|
|
87
87
|
weHaveSendYouAnEmail,
|
|
88
88
|
pdfLink,
|
|
89
89
|
theDataFromYourRequest,
|
|
90
|
-
summaryList
|
|
91
|
-
govcyResources.staticResources.elements["govcyFormsJs"]
|
|
90
|
+
summaryList
|
|
92
91
|
);
|
|
93
92
|
// Append generated summary list to the page template
|
|
94
93
|
pageTemplate.sections.push({ name: "main", elements: mainElements });
|
|
@@ -1,102 +1,214 @@
|
|
|
1
1
|
// 🔍 Select all file inputs that have the .govcy-file-upload class
|
|
2
2
|
var fileInputs = document.querySelectorAll('input[type="file"].govcy-file-upload');
|
|
3
3
|
|
|
4
|
+
// select overlay and app root elements
|
|
5
|
+
var _govcyOverlay = document.getElementById("govcy--loadingOverlay");
|
|
6
|
+
var _govcyAppRoot = document.getElementById("govcy--body");
|
|
7
|
+
|
|
8
|
+
// Accessibility: Keep track of previously focused element and disabled elements
|
|
9
|
+
var _govcyPrevFocus = null;
|
|
10
|
+
var _govcyDisabledEls = [];
|
|
11
|
+
|
|
4
12
|
// 🔁 Loop over each file input and attach a change event listener
|
|
5
13
|
fileInputs.forEach(function(input) {
|
|
6
14
|
input.addEventListener('change', _uploadFileEventHandler);
|
|
7
15
|
});
|
|
8
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Disables all focusable elements within a given root element
|
|
19
|
+
* @param {*} root The root element whose focusable children will be disabled
|
|
20
|
+
*/
|
|
21
|
+
function disableFocusables(root) {
|
|
22
|
+
var sel = 'a[href],area[href],button,input,select,textarea,iframe,summary,[contenteditable="true"],[tabindex]:not([tabindex="-1"])';
|
|
23
|
+
var nodes = root.querySelectorAll(sel);
|
|
24
|
+
_govcyDisabledEls = [];
|
|
25
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
26
|
+
var el = nodes[i];
|
|
27
|
+
if (_govcyOverlay.contains(el)) continue; // don’t disable overlay itself
|
|
28
|
+
var prev = el.getAttribute('tabindex');
|
|
29
|
+
el.setAttribute('data-prev-tabindex', prev === null ? '' : prev);
|
|
30
|
+
el.setAttribute('tabindex', '-1');
|
|
31
|
+
_govcyDisabledEls.push(el);
|
|
32
|
+
}
|
|
33
|
+
root.setAttribute('aria-hidden', 'true'); // hide from AT on fallback
|
|
34
|
+
root.setAttribute('aria-busy', 'true');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Restores all focusable elements within a given root element
|
|
39
|
+
* @param {*} root The root element whose focusable children will be restored
|
|
40
|
+
*/
|
|
41
|
+
function restoreFocusables(root) {
|
|
42
|
+
for (var i = 0; i < _govcyDisabledEls.length; i++) {
|
|
43
|
+
var el = _govcyDisabledEls[i];
|
|
44
|
+
var prev = el.getAttribute('data-prev-tabindex');
|
|
45
|
+
if (prev === '') el.removeAttribute('tabindex'); else el.setAttribute('tabindex', prev);
|
|
46
|
+
el.removeAttribute('data-prev-tabindex');
|
|
47
|
+
}
|
|
48
|
+
_govcyDisabledEls = [];
|
|
49
|
+
root.removeAttribute('aria-hidden');
|
|
50
|
+
root.removeAttribute('aria-busy');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Traps tab key navigation within the overlay
|
|
55
|
+
* @param {*} e The event
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
function trapTab(e) {
|
|
59
|
+
if (e.key !== 'Tab') return;
|
|
60
|
+
var focusables = _govcyOverlay.querySelectorAll('a[href],button,input,select,textarea,[tabindex]:not([tabindex="-1"])');
|
|
61
|
+
if (focusables.length === 0) { e.preventDefault(); _govcyOverlay.focus(); return; }
|
|
62
|
+
var first = focusables[0], last = focusables[focusables.length - 1];
|
|
63
|
+
if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
|
|
64
|
+
else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Shows the loading spinner overlay and traps focus within it
|
|
69
|
+
*/
|
|
70
|
+
function showLoadingSpinner() {
|
|
71
|
+
_govcyPrevFocus = document.activeElement;
|
|
72
|
+
_govcyOverlay.setAttribute('aria-hidden', 'false');
|
|
73
|
+
_govcyOverlay.setAttribute('tabindex', '-1');
|
|
74
|
+
_govcyOverlay.style.display = 'flex';
|
|
75
|
+
document.documentElement.style.overflow = 'hidden';
|
|
76
|
+
|
|
77
|
+
if ('inert' in HTMLElement.prototype) { // progressive enhancement
|
|
78
|
+
_govcyAppRoot.inert = true;
|
|
79
|
+
} else {
|
|
80
|
+
disableFocusables(_govcyAppRoot);
|
|
81
|
+
document.addEventListener('keydown', trapTab, true);
|
|
82
|
+
}
|
|
83
|
+
_govcyOverlay.focus();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Hides the loading spinner overlay and restores focus to the previously focused element
|
|
88
|
+
*/
|
|
89
|
+
function hideLoadingSpinner() {
|
|
90
|
+
_govcyOverlay.style.display = 'none';
|
|
91
|
+
_govcyOverlay.setAttribute('aria-hidden', 'true');
|
|
92
|
+
document.documentElement.style.overflow = '';
|
|
93
|
+
|
|
94
|
+
if ('inert' in HTMLElement.prototype) {
|
|
95
|
+
_govcyAppRoot.inert = false;
|
|
96
|
+
} else {
|
|
97
|
+
restoreFocusables(_govcyAppRoot);
|
|
98
|
+
document.removeEventListener('keydown', trapTab, true);
|
|
99
|
+
}
|
|
100
|
+
if (_govcyPrevFocus && _govcyPrevFocus.focus) _govcyPrevFocus.focus();
|
|
101
|
+
}
|
|
102
|
+
|
|
9
103
|
|
|
10
104
|
/**
|
|
11
105
|
* Handles the upload of a file event
|
|
12
|
-
*
|
|
106
|
+
*
|
|
13
107
|
* @param {object} event The event
|
|
14
108
|
*/
|
|
15
|
-
|
|
109
|
+
function _uploadFileEventHandler(event) {
|
|
16
110
|
var input = event.target;
|
|
17
111
|
var messages = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
112
|
+
"uploadSuccesful": {
|
|
113
|
+
"el": "Το αρχείο ανεβαστηκε",
|
|
114
|
+
"en": "File uploaded successfully",
|
|
115
|
+
"tr": "File uploaded successfully"
|
|
116
|
+
},
|
|
117
|
+
"uploadFailed": {
|
|
118
|
+
"el": "Αποτυχια ανεβασης",
|
|
119
|
+
"en": "File upload failed",
|
|
120
|
+
"tr": "File upload failed"
|
|
121
|
+
},
|
|
122
|
+
"uploadFailed406": {
|
|
123
|
+
"el": "Το επιλεγμένο αρχείο είναι κενό",
|
|
124
|
+
"en": "The selected file is empty",
|
|
125
|
+
"tr": "The selected file is empty"
|
|
126
|
+
},
|
|
127
|
+
"uploadFailed407": {
|
|
128
|
+
"el": "Το επιλεγμένο αρχείο πρέπει να είναι JPG, JPEG, PNG ή PDF",
|
|
129
|
+
"en": "The selected file must be a JPG, JPEG, PNG or PDF",
|
|
130
|
+
"tr": "The selected file must be a JPG, JPEG, PNG or PDF"
|
|
131
|
+
},
|
|
132
|
+
"uploadFailed408": {
|
|
133
|
+
"el": "Το επιλεγμένο αρχείο πρέπει να είναι JPG, JPEG, PNG ή PDF",
|
|
134
|
+
"en": "The selected file must be a JPG, JPEG, PNG or PDF",
|
|
135
|
+
"tr": "The selected file must be a JPG, JPEG, PNG or PDF"
|
|
136
|
+
},
|
|
137
|
+
"uploadFailed409": {
|
|
138
|
+
"el": "Το επιλεγμένο αρχείο πρέπει να είναι μικρότερο από 4MB",
|
|
139
|
+
"en": "The selected file must be smaller than 4MB",
|
|
140
|
+
"tr": "The selected file must be smaller than 4MB"
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// 🔐 Get the CSRF token from a hidden input field (generated by your backend)
|
|
145
|
+
var csrfEl = document.querySelector('input[type="hidden"][name="_csrf"]');
|
|
146
|
+
var csrfToken = csrfEl ? csrfEl.value : '';
|
|
147
|
+
|
|
148
|
+
// 🔧 Define siteId and pageUrl (you can dynamically extract these later)
|
|
149
|
+
var siteId = window._govcySiteId || "";
|
|
150
|
+
var pageUrl = window._govcyPageUrl || "";
|
|
151
|
+
var lang = window._govcyLang || "el";
|
|
152
|
+
|
|
153
|
+
// 📦 Grab the selected file
|
|
154
|
+
var file = event.target.files[0];
|
|
155
|
+
var elementName = input.name; // Form field's `name` attribute
|
|
156
|
+
var elementId = input.id; // Form field's `id` attribute
|
|
157
|
+
|
|
158
|
+
if (!file) return; // Exit if no file was selected
|
|
159
|
+
|
|
160
|
+
// Show loading spinner
|
|
161
|
+
showLoadingSpinner();
|
|
162
|
+
|
|
163
|
+
// 🧵 Prepare form-data payload for the API
|
|
164
|
+
var formData = new FormData();
|
|
165
|
+
formData.append('file', file); // Attach the actual file
|
|
166
|
+
formData.append('elementName', elementName); // Attach the field name for backend lookup
|
|
167
|
+
|
|
168
|
+
// 🚀 CHANGED: using fetch instead of axios.post
|
|
169
|
+
fetch(`/apis/${siteId}/${pageUrl}/upload`, {
|
|
170
|
+
method: "POST",
|
|
171
|
+
headers: {
|
|
172
|
+
"X-CSRF-Token": csrfToken // 🔐 Pass CSRF token in custom header
|
|
173
|
+
},
|
|
174
|
+
body: formData
|
|
175
|
+
})
|
|
176
|
+
.then(function(response) {
|
|
177
|
+
// 🚀 CHANGED: fetch does not auto-throw on error codes → check manually
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
return response.json().then(function(errData) {
|
|
180
|
+
throw { response: { data: errData } };
|
|
181
|
+
});
|
|
47
182
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
var lang = window._govcyLang || "el";
|
|
57
|
-
// 📦 Grab the selected file
|
|
58
|
-
var file = event.target.files[0];
|
|
59
|
-
var elementName = input.name; // Form field's `name` attribute
|
|
60
|
-
var elementId = input.id; // Form field's `id` attribute
|
|
61
|
-
|
|
62
|
-
if (!file) return; // Exit if no file was selected
|
|
63
|
-
|
|
64
|
-
// 🧵 Prepare form-data payload for the API
|
|
65
|
-
var formData = new FormData();
|
|
66
|
-
formData.append('file', file); // Attach the actual file
|
|
67
|
-
formData.append('elementName', elementName); // Attach the field name for backend lookup
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
// 🚀 Send file to the backend upload API
|
|
71
|
-
var response = await axios.post(`/apis/${siteId}/${pageUrl}/upload`, formData, {
|
|
72
|
-
headers: {
|
|
73
|
-
'X-CSRF-Token': csrfToken // 🔐 Pass CSRF token in custom header
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
var sha256 = response.data.Data.sha256;
|
|
78
|
-
var fileId = response.data.Data.fileId;
|
|
79
|
-
|
|
80
|
-
// 📝 Store returned metadata in hidden fields for submission with the form
|
|
183
|
+
return response.json();
|
|
184
|
+
})
|
|
185
|
+
.then(function(data) {
|
|
186
|
+
// ✅ Success response
|
|
187
|
+
var sha256 = data.Data.sha256;
|
|
188
|
+
var fileId = data.Data.fileId;
|
|
189
|
+
|
|
190
|
+
// 📝 Store returned metadata in hidden fields if needed
|
|
81
191
|
// document.querySelector('[name="' + elementName + 'Attachment[fileId]"]').value = fileId;
|
|
82
192
|
// document.querySelector('[name="' + elementName + 'Attachment[sha256]"]').value = sha256;
|
|
193
|
+
|
|
194
|
+
// Hide loading spinner
|
|
195
|
+
hideLoadingSpinner();
|
|
83
196
|
|
|
84
197
|
// Render the file view
|
|
85
198
|
_renderFileElement("fileView", elementId, elementName, fileId, sha256, null);
|
|
86
|
-
|
|
199
|
+
|
|
87
200
|
// Accessibility: Update ARIA live region with success message
|
|
88
201
|
var statusRegion = document.getElementById('_govcy-upload-status');
|
|
89
202
|
if (statusRegion) {
|
|
90
203
|
setTimeout(function() {
|
|
91
204
|
statusRegion.textContent = messages.uploadSuccesful[lang];
|
|
92
|
-
}, 200)
|
|
205
|
+
}, 200);
|
|
93
206
|
setTimeout(function() {
|
|
94
207
|
statusRegion.textContent = '';
|
|
95
|
-
}, 5000);
|
|
208
|
+
}, 5000);
|
|
96
209
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
} catch (err) {
|
|
210
|
+
})
|
|
211
|
+
.catch(function(err) {
|
|
100
212
|
// ⚠️ Show an error message if upload fails
|
|
101
213
|
var errorMessage = messages.uploadFailed;
|
|
102
214
|
var errorCode = err && err.response && err.response.data && err.response.data.ErrorCode;
|
|
@@ -105,9 +217,11 @@ async function _uploadFileEventHandler(event) {
|
|
|
105
217
|
errorMessage = messages["uploadFailed" + errorCode];
|
|
106
218
|
}
|
|
107
219
|
|
|
220
|
+
// Hide loading spinner
|
|
221
|
+
hideLoadingSpinner();
|
|
108
222
|
// Render the file input with error
|
|
109
|
-
_renderFileElement("fileInput", elementId, elementName, "","", errorMessage);
|
|
110
|
-
|
|
223
|
+
_renderFileElement("fileInput", elementId, elementName, "", "", errorMessage);
|
|
224
|
+
|
|
111
225
|
// Re-bind the file input's change handler
|
|
112
226
|
var newInput = document.getElementById(elementId);
|
|
113
227
|
if (newInput) {
|
|
@@ -116,10 +230,10 @@ async function _uploadFileEventHandler(event) {
|
|
|
116
230
|
|
|
117
231
|
// Accessibility: Focus on the form field
|
|
118
232
|
document.getElementById(elementId)?.focus();
|
|
119
|
-
|
|
120
|
-
}
|
|
233
|
+
});
|
|
121
234
|
}
|
|
122
235
|
|
|
236
|
+
|
|
123
237
|
/**
|
|
124
238
|
* Renders a file element in the DOM
|
|
125
239
|
*
|
|
@@ -131,6 +245,14 @@ async function _uploadFileEventHandler(event) {
|
|
|
131
245
|
* @param {object} errorMessage The error message in all supported languages
|
|
132
246
|
*/
|
|
133
247
|
function _renderFileElement(elementState, elementId, elementName, fileId, sha256, errorMessage) {
|
|
248
|
+
|
|
249
|
+
// Grab the query string part (?foo=bar&route=something)
|
|
250
|
+
var queryString = window.location.search;
|
|
251
|
+
// Parse it
|
|
252
|
+
var params = new URLSearchParams(queryString);
|
|
253
|
+
// Get the "route" value (null if not present)
|
|
254
|
+
var route = params.get("route");
|
|
255
|
+
|
|
134
256
|
// Create an instance of GovcyFrontendRendererBrowser
|
|
135
257
|
var renderer = new GovcyFrontendRendererBrowser();
|
|
136
258
|
var lang = window._govcyLang || "el";
|
|
@@ -141,7 +263,7 @@ function _renderFileElement(elementState, elementId, elementName, fileId, sha256
|
|
|
141
263
|
"lang": lang
|
|
142
264
|
}
|
|
143
265
|
};
|
|
144
|
-
var fileInputMap =
|
|
266
|
+
var fileInputMap = JSON.parse(JSON.stringify(window._govcyFileInputs));
|
|
145
267
|
var fileElement = fileInputMap[elementName];
|
|
146
268
|
fileElement.element = elementState;
|
|
147
269
|
if (errorMessage != null) fileElement.params.error = errorMessage;
|
|
@@ -150,8 +272,10 @@ function _renderFileElement(elementState, elementId, elementName, fileId, sha256
|
|
|
150
272
|
if (elementState == "fileView") {
|
|
151
273
|
fileElement.params.visuallyHiddenText = fileElement.params.label;
|
|
152
274
|
// TODO: Also need to set the `view` and `download` URLs
|
|
153
|
-
fileElement.params.viewHref = "
|
|
154
|
-
fileElement.params.
|
|
275
|
+
fileElement.params.viewHref = "/" + window._govcySiteId + "/" + window._govcyPageUrl + "/view-file/" + elementName;
|
|
276
|
+
fileElement.params.viewTarget = "_blank";
|
|
277
|
+
fileElement.params.deleteHref = "/" + window._govcySiteId + "/" + window._govcyPageUrl + "/delete-file/" + elementName
|
|
278
|
+
+ (route !== null ? "?route=" + encodeURIComponent(route) : "");
|
|
155
279
|
}
|
|
156
280
|
// Construct the JSONTemplate
|
|
157
281
|
var JSONTemplate = {
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
document.addEventListener("DOMContentLoaded", function () {
|
|
2
2
|
// --- Show conditionals for checked radios ---
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
// CHANGED: NodeList.prototype.forEach is not in IE11 → use Array.prototype.forEach.call
|
|
4
|
+
// CHANGED: Arrow function → function
|
|
5
|
+
Array.prototype.forEach.call(
|
|
6
|
+
document.querySelectorAll('.govcy-radio-input[data-aria-controls]:checked'),
|
|
7
|
+
function (radio) { // CHANGED: arrow → function
|
|
8
|
+
// CHANGED: const → var (ES5)
|
|
9
|
+
var targetId = radio.getAttribute('data-aria-controls');
|
|
10
|
+
var targetElement = document.getElementById(targetId);
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
12
|
+
if (targetElement) {
|
|
13
|
+
targetElement.classList.remove('govcy-radio__conditional--hidden');
|
|
14
|
+
}
|
|
9
15
|
}
|
|
10
|
-
|
|
16
|
+
);
|
|
17
|
+
|
|
11
18
|
// --- Disable submit button after form submission ---
|
|
12
|
-
|
|
19
|
+
// CHANGED: NodeList.forEach → Array.prototype.forEach.call
|
|
20
|
+
Array.prototype.forEach.call(document.querySelectorAll('form'), function (form) { // CHANGED
|
|
13
21
|
form.addEventListener('submit', function (e) {
|
|
14
|
-
const
|
|
22
|
+
// CHANGED: const → var (ES5)
|
|
23
|
+
var submitButton = form.querySelector('[type="submit"]');
|
|
15
24
|
if (submitButton) {
|
|
16
25
|
submitButton.disabled = true;
|
|
17
26
|
submitButton.setAttribute('aria-disabled', 'true');
|
|
27
|
+
// (Optional) announce busy state for AT:
|
|
28
|
+
// submitButton.setAttribute('aria-busy', 'true'); // CHANGED: optional a11y improvement
|
|
18
29
|
}
|
|
19
30
|
});
|
|
20
31
|
});
|
|
@@ -6,6 +6,11 @@ export const staticResources = {
|
|
|
6
6
|
el: "Υποβολή",
|
|
7
7
|
tr: "Gönder"
|
|
8
8
|
},
|
|
9
|
+
continue: {
|
|
10
|
+
en: "Continue",
|
|
11
|
+
el: "Συνέχεια",
|
|
12
|
+
tr: "Continue"
|
|
13
|
+
},
|
|
9
14
|
cancel: {
|
|
10
15
|
en: "Cancel",
|
|
11
16
|
el: "Ακύρωση",
|
|
@@ -54,7 +59,7 @@ export const staticResources = {
|
|
|
54
59
|
errorPage403NaturalOnlyPolicyBody: {
|
|
55
60
|
el: "<p>Η πρόσβαση επιτρέπεται μόνο σε φυσικά πρόσωπα με επιβεβαιωμένο προφίλ. <a href=\"/logout\">Αποσυνδεθείτε</a> και δοκιμάστε ξανά αργότερα.</p>",
|
|
56
61
|
en: "<p>Access is only allowed to individuals with a verified profile.<a href=\"/logout\">Sign out</a> and try again later.</p>",
|
|
57
|
-
tr: "<p>Access is only allowed to individuals with a
|
|
62
|
+
tr: "<p>Access is only allowed to individuals with a verified profile.<a href=\"/logout\">Giriş yapmadan</a> sonra tekrar deneyiniz.</p>"
|
|
58
63
|
},
|
|
59
64
|
errorPage500Title: {
|
|
60
65
|
el: "Λυπούμαστε, υπάρχει πρόβλημα με την υπηρεσία",
|
|
@@ -102,14 +107,49 @@ export const staticResources = {
|
|
|
102
107
|
tr: "We have received your request. "
|
|
103
108
|
},
|
|
104
109
|
fileUploaded : {
|
|
105
|
-
en: "File
|
|
106
|
-
el: "Το αρχείο
|
|
107
|
-
tr: "File
|
|
110
|
+
en: "File uploaded",
|
|
111
|
+
el: "Το αρχείο ανεβάστηκε",
|
|
112
|
+
tr: "File uploaded"
|
|
108
113
|
},
|
|
109
114
|
fileNotUploaded : {
|
|
110
115
|
en: "File has not been uploaded. ",
|
|
111
116
|
el: "Το αρχείο δεν ανεβάστηκε. ",
|
|
112
117
|
tr: "File has not been uploaded. "
|
|
118
|
+
},
|
|
119
|
+
fileYouHaveUploaded : {
|
|
120
|
+
en: "You have uploaded the file for \"{{file}}\"",
|
|
121
|
+
el: "Έχετε ανεβάσει το αρχείο \"{{file}}\"",
|
|
122
|
+
tr: "You have uploaded the file for \"{{file}}\""
|
|
123
|
+
},
|
|
124
|
+
deleteFileTitle : {
|
|
125
|
+
en: "Are you sure you want to delete the file \"{{file}}\"? ",
|
|
126
|
+
el: "Σίγουρα θέλετε να διαγράψετε το αρχείο \"{{file}}\";",
|
|
127
|
+
tr: "Are you sure you want to delete the file \"{{file}}\"? "
|
|
128
|
+
},
|
|
129
|
+
deleteYesOption: {
|
|
130
|
+
el:"Ναι, θέλω να διαγράψω το αρχείο",
|
|
131
|
+
en:"Yes, I want to delete this file",
|
|
132
|
+
tr:"Yes, I want to delete this file"
|
|
133
|
+
},
|
|
134
|
+
deleteNoOption: {
|
|
135
|
+
el:"Όχι, δεν θέλω να διαγράψω το αρχείο",
|
|
136
|
+
en:"No, I don't want to delete this file",
|
|
137
|
+
tr:"No, I don't want to delete this file"
|
|
138
|
+
},
|
|
139
|
+
deleteFileValidationError: {
|
|
140
|
+
en: "Select if you want to delete the file",
|
|
141
|
+
el: "Επιλέξτε αν θέλετε να διαγράψετε το αρχείο",
|
|
142
|
+
tr: "Select if you want to delete the file"
|
|
143
|
+
},
|
|
144
|
+
viewFile: {
|
|
145
|
+
en: "View file",
|
|
146
|
+
el: "Προβολή αρχείου",
|
|
147
|
+
tr: "View file"
|
|
148
|
+
},
|
|
149
|
+
deleteSameFileWarning: {
|
|
150
|
+
en: "Υou have uploaded the same file more than once in this application. If you delete it, it will be deleted from all places in the application.",
|
|
151
|
+
el: "Έχετε ανεβάσει το αρχείο αυτό και σε άλλα σημεία της αίτησης. Αν το διαγράψετε, θα διαγραφεί από όλα τα σημεία.",
|
|
152
|
+
tr: "Υou have uploaded the same file more than once in this application. If you delete it, it will be deleted from all places in the application."
|
|
113
153
|
}
|
|
114
154
|
},
|
|
115
155
|
//remderer sections
|
|
@@ -123,9 +163,19 @@ export const staticResources = {
|
|
|
123
163
|
element: "htmlElement",
|
|
124
164
|
params: {
|
|
125
165
|
text: {
|
|
126
|
-
en: `<script src="https://cdn.jsdelivr.net/
|
|
127
|
-
el: `<script src="https://cdn.jsdelivr.net/
|
|
128
|
-
tr: `<script src="https://cdn.jsdelivr.net/
|
|
166
|
+
en: `<script src="https://cdn.jsdelivr.net/gh/gov-cy/govcy-frontend-renderer@v1.22.0/dist/govcyCompiledTemplates.browser.js"></script><script src="https://cdn.jsdelivr.net/gh/gov-cy/govcy-frontend-renderer@v1.22.0/dist/govcyFrontendRenderer.browser.js"></script><script type="module" src="/js/govcyForms.js"></script><script type="module" src="/js/govcyFiles.js"></script>`,
|
|
167
|
+
el: `<script src="https://cdn.jsdelivr.net/gh/gov-cy/govcy-frontend-renderer@v1.22.0/dist/govcyCompiledTemplates.browser.js"></script><script src="https://cdn.jsdelivr.net/gh/gov-cy/govcy-frontend-renderer@v1.22.0/dist/govcyFrontendRenderer.browser.js"></script><script type="module" src="/js/govcyForms.js"></script><script type="module" src="/js/govcyFiles.js"></script>`,
|
|
168
|
+
tr: `<script src="https://cdn.jsdelivr.net/gh/gov-cy/govcy-frontend-renderer@v1.22.0/dist/govcyCompiledTemplates.browser.js"></script><script src="https://cdn.jsdelivr.net/gh/gov-cy/govcy-frontend-renderer@v1.22.0/dist/govcyFrontendRenderer.browser.js"></script><script type="module" src="/js/govcyForms.js"></script><script type="module" src="/js/govcyFiles.js"></script>`
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
govcyLoadingOverlay: {
|
|
173
|
+
element: "htmlElement",
|
|
174
|
+
params: {
|
|
175
|
+
text: {
|
|
176
|
+
en: `<style>.govcy-loadingOverlay{position:fixed;top:0;right:0;bottom:0;left:0;display:none;justify-content:center;align-items:center;background:rgba(255,255,255,.7);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:1050}.govcy-loadingOverlay[aria-hidden="false"]{display:flex}</style><div id="govcy--loadingOverlay" class="govcy-loadingOverlay" aria-hidden="true" role="dialog" aria-modal="true" tabindex="-1"><div class="govcy-loadingOverlay__content" role="status" aria-live="polite"><div class="spinner-border govcy-text-primary" role="status"><span class="govcy-visually-hidden">Loading...</span></div></div></div>`,
|
|
177
|
+
el: `<style>.govcy-loadingOverlay{position:fixed;top:0;right:0;bottom:0;left:0;display:none;justify-content:center;align-items:center;background:rgba(255,255,255,.7);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:1050}.govcy-loadingOverlay[aria-hidden="false"]{display:flex}</style><div id="govcy--loadingOverlay" class="govcy-loadingOverlay" aria-hidden="true" role="dialog" aria-modal="true" tabindex="-1"><div class="govcy-loadingOverlay__content" role="status" aria-live="polite"><div class="spinner-border govcy-text-primary" role="status"><span class="govcy-visually-hidden">Φόρτωση...</span></div></div></div>`,
|
|
178
|
+
tr: `<style>.govcy-loadingOverlay{position:fixed;top:0;right:0;bottom:0;left:0;display:none;justify-content:center;align-items:center;background:rgba(255,255,255,.7);-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);z-index:1050}.govcy-loadingOverlay[aria-hidden="false"]{display:flex}</style><div id="govcy--loadingOverlay" class="govcy-loadingOverlay" aria-hidden="true" role="dialog" aria-modal="true" tabindex="-1"><div class="govcy-loadingOverlay__content" role="status" aria-live="polite"><div class="spinner-border govcy-text-primary" role="status"><span class="govcy-visually-hidden">Loading...</span></div></div></div>`
|
|
129
179
|
}
|
|
130
180
|
}
|
|
131
181
|
},
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
export const ALLOWED_FORM_ELEMENTS = ["textInput", "textArea", "select", "radios", "checkboxes", "datePicker", "dateInput","fileInput","fileView"];
|
|
5
5
|
export const ALLOWED_FILE_MIME_TYPES = ['application/pdf', 'image/jpeg', 'image/png'];
|
|
6
6
|
export const ALLOWED_FILE_EXTENSIONS = ['pdf', 'jpg', 'jpeg', 'png'];
|
|
7
|
-
export const ALLOWED_FILE_SIZE_MB =
|
|
7
|
+
export const ALLOWED_FILE_SIZE_MB = 4; // Maximum file size in MB
|
|
8
8
|
export const ALLOWED_MULTER_FILE_SIZE_MB = 10; // Maximum file size in MB
|