@modernman00/shared-js-lib 1.2.2
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/Cookie.js +49 -0
- package/CountryCode.js +214 -0
- package/DateTime.js +101 -0
- package/ForgotPassword.js +102 -0
- package/FormHelper.js +268 -0
- package/FormProcessing.js +22 -0
- package/Http.js +150 -0
- package/Loader.js +35 -0
- package/Login.js +43 -0
- package/ShowResponse.js +93 -0
- package/Utility.js +133 -0
- package/UtilityHtml.js +200 -0
- package/index.js +13 -0
- package/package.json +31 -0
- package/theAutoComplete.js +101 -0
package/FormHelper.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
export default class FormHelper {
|
|
3
|
+
constructor(data) {
|
|
4
|
+
if (!Array.isArray(data)) throwError('data must be an array of form elements');
|
|
5
|
+
this.data = data;
|
|
6
|
+
this.error = [];
|
|
7
|
+
this.result = 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
id(x) {
|
|
11
|
+
return document.getElementById(x)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* general validation; check empty status, at least a single input, mobile length, white space
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
getData() {
|
|
19
|
+
return this.data;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Validate a single form field
|
|
25
|
+
* @param {string} value - the value of the field to validate
|
|
26
|
+
* @param {string} [type='general'] - the type of validation to perform. Currently only 'email' is supported
|
|
27
|
+
* @returns {boolean} - true if the field is valid, false otherwise
|
|
28
|
+
*/
|
|
29
|
+
validateField(value, type = 'general') {
|
|
30
|
+
if (type === 'email') {
|
|
31
|
+
const emailRegex = /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-Z0-9]{2,4}$/;
|
|
32
|
+
return emailRegex.test(value);
|
|
33
|
+
}
|
|
34
|
+
return value.trim().length > 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Loop through all the elements in the form and validate each one.
|
|
40
|
+
* If element is empty, add error message to the error array and set result to false
|
|
41
|
+
* If element is not empty, check if it validates according to its type (email or general)
|
|
42
|
+
* If it does not validate, add error message to the error array and set result to false
|
|
43
|
+
* @returns {void}
|
|
44
|
+
*/
|
|
45
|
+
massValidate() {
|
|
46
|
+
const invalidElements = this.data.flatMap(et => et.filter(post => {
|
|
47
|
+
const postName = post.name.replace('_', ' ');
|
|
48
|
+
let errMsg = this.id(`${post.name}_error`);
|
|
49
|
+
|
|
50
|
+
// rid it off the submit and token
|
|
51
|
+
if (['submit', 'button', 'showPassword_id', 'g-recaptcha-response', 'cancel', 'token', 'checkbox_id'].includes(post.name) ||
|
|
52
|
+
['button'].includes(post.id) || ['button'].includes(post.type)) return false;
|
|
53
|
+
|
|
54
|
+
// check if there is no value
|
|
55
|
+
if (['spouseName', 'spouseMobile', 'spouseEmail', 'fatherMobile', 'fatherEmail', 'motherMobile', 'maidenName', 'motherEmail'].includes(post.name)) {
|
|
56
|
+
// post.value is not prpvided if it is not provided
|
|
57
|
+
post.value = post.value === "" ? "Not Provided" : post.value
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (post.value === '' || post.value === 'select') {
|
|
61
|
+
errMsg.innerHTML = `${post.placeholder ?? "*"} cannot be left empty`;
|
|
62
|
+
errMsg.style.color = 'red';
|
|
63
|
+
this.error.push(`${postName.toUpperCase()} cannot be left empty`);
|
|
64
|
+
this.result = false;
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (post.name === 'email' && !this.validateField(post.value, 'email')) {
|
|
69
|
+
errMsg.innerHTML = '* Please enter a valid email';
|
|
70
|
+
errMsg.style.color = 'red';
|
|
71
|
+
this.error.push('<li style="color: red;">Please enter a valid email</li>');
|
|
72
|
+
this.result = false;
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return false;
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
if (invalidElements.length > 0) this.result = false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
emailVal() {
|
|
83
|
+
const emailExp = /^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/;
|
|
84
|
+
let msg = `<li style=color:'red';> Please enter a valid email</li>`
|
|
85
|
+
const email = this.id('email_id').value
|
|
86
|
+
if (email.match(emailExp) === null) {
|
|
87
|
+
this.id('email_error').innerHTML = msg
|
|
88
|
+
this.id('email_error').style.color = "red"
|
|
89
|
+
this.error.push(msg)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Clears all error messages and empties the error array.
|
|
95
|
+
* Sets up event listeners to clear error messages for each input element.
|
|
96
|
+
* Keyup event listener: for non-select inputs
|
|
97
|
+
* Change event listener: for all inputs
|
|
98
|
+
* @returns {void}
|
|
99
|
+
*/
|
|
100
|
+
clearError() {
|
|
101
|
+
this.error = []; // Empty the error array
|
|
102
|
+
|
|
103
|
+
// Function to clear error messages for a given input element
|
|
104
|
+
const clearErrorForElement = (elementName) => {
|
|
105
|
+
const errorElement = this.id(`${elementName}_error`);
|
|
106
|
+
if (errorElement) errorElement.innerHTML = '';
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
this.data.flat().forEach(({ id, name, value }) => {
|
|
110
|
+
if (['submit', 'button', 'token', 'checkbox'].includes(id) || ['token', 'submit'].includes(name)) return;
|
|
111
|
+
|
|
112
|
+
const element = this.id(id);
|
|
113
|
+
if (!element) {
|
|
114
|
+
console.error(`Element with ID '${id}' and post name '${name}' not found.`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Add event listeners to clear errors
|
|
119
|
+
const clearErrorHandler = () => clearErrorForElement(name);
|
|
120
|
+
if (value !== 'select') element.addEventListener('keyup', clearErrorHandler);
|
|
121
|
+
element.addEventListener('change', clearErrorHandler);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Clears the values of all input elements in the form, excluding checkboxes and the submit button
|
|
127
|
+
*/
|
|
128
|
+
clearHtml() {
|
|
129
|
+
this.data.flat().forEach(post => {
|
|
130
|
+
if (!['submit', 'checkbox'].includes(post.name) && post.type !== 'submit') {
|
|
131
|
+
post.value = "";
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Check the length of the input in real time and display an error message if it exceeds the maximum length
|
|
137
|
+
* @param {array of strings} input - the IDs of the input elements to check
|
|
138
|
+
* @param {array of numbers} maxi - the maximum lengths for each input element
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
realTimeCheckLen(input, maxi) {
|
|
142
|
+
input.forEach((id, i) => {
|
|
143
|
+
const theData = this.id(`${id}_id`);
|
|
144
|
+
if (!theData) {
|
|
145
|
+
console.error(`Element with ID '${id}_id' not found`);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const max = maxi[i];
|
|
149
|
+
theData.maxLength = parseInt(max) + 1;
|
|
150
|
+
theData.addEventListener('input', () => {
|
|
151
|
+
const error = this.id(`${id}_error`);
|
|
152
|
+
error.innerHTML = (theData.value.length > max) ? `You have reached the maximum limit` : "";
|
|
153
|
+
this.id(`${id}_help`).style.display = theData.value.length > max ? '' : 'none';
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Match the value of the second input to the value of the first input in real time
|
|
162
|
+
* @param {string} first - the id of the first input
|
|
163
|
+
* @param {string} second - the id of the second input
|
|
164
|
+
*/
|
|
165
|
+
matchInput(first, second) {
|
|
166
|
+
const firstInput = this.id(first + '_id');
|
|
167
|
+
const secondInput = this.id(second + '_id');
|
|
168
|
+
const error = this.id(`${second}_error`);
|
|
169
|
+
|
|
170
|
+
const checkMatch = () => error.innerHTML = (firstInput.value !== secondInput.value) ? 'Your passwords do not match' : "";
|
|
171
|
+
|
|
172
|
+
firstInput.addEventListener('input', checkMatch);
|
|
173
|
+
secondInput.addEventListener('input', checkMatch);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Injects the values in the html array to the elements with the IDs in the idArray
|
|
179
|
+
* @param {array of strings} idArray - the IDs of the elements to inject the values to
|
|
180
|
+
* @param {array of strings} html - the values to inject to the elements
|
|
181
|
+
*/
|
|
182
|
+
injectData(idArray, html) {
|
|
183
|
+
idArray.forEach((id, i) => this.id(id).innerHTML = html[i]);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
*
|
|
188
|
+
* @param {this is an id and its value is for duplication} firstInput
|
|
189
|
+
* @param {* another id that accepts the value of the firstInput} takeFirstInput
|
|
190
|
+
*/
|
|
191
|
+
duplicate(giveInput, takeInput) {
|
|
192
|
+
let giver, taker;
|
|
193
|
+
giver = this.id(giveInput)
|
|
194
|
+
taker = this.id(takeInput)
|
|
195
|
+
giver.addEventListener('keyup', () => {
|
|
196
|
+
taker.value = giver.value;
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Sends a get request to the server as the user types in the specified input element
|
|
205
|
+
* and updates the content of the specified output element with the response from the server
|
|
206
|
+
* @param {string} input - the id of the input element to listen to
|
|
207
|
+
* @param {string} url - the url of the get request to send, the value of the input element will be appended to the end of the url
|
|
208
|
+
* @param {string} outputId - the id of the element to update with the response from the server
|
|
209
|
+
*/
|
|
210
|
+
realTimeServer(input, url, outputId) {
|
|
211
|
+
const theInput = this.id(input)
|
|
212
|
+
const output = this.id(outputId)
|
|
213
|
+
theInput.addEventListener('keyup', async () => {
|
|
214
|
+
const inputVal = theInput.value
|
|
215
|
+
|
|
216
|
+
if (inputVal === "") {
|
|
217
|
+
output.innerHTML = "";
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
const response = await axios.get(`${url}=${inputVal}`)
|
|
223
|
+
output.innerHTML = response.data
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error(error)
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Check if a yes/no radio button is checked and display "checked" in a hidden input field.
|
|
232
|
+
* @param {string} yesId - the id of the yes radio button
|
|
233
|
+
* @param {string} noId - the id of the no radio button
|
|
234
|
+
* @param {string} hiddenInput - the id of the hidden input field to display the result
|
|
235
|
+
*/
|
|
236
|
+
isChecked(yesId, noId, hiddenInput) {
|
|
237
|
+
const checked = () => {
|
|
238
|
+
if (this.id(yesId).checked) {
|
|
239
|
+
alert('check')
|
|
240
|
+
this.id(hiddenInput).innerHTML = 'checked';
|
|
241
|
+
} else if (this.id(noId).checked) {
|
|
242
|
+
this.id(hiddenInput).innerHTML = 'checked';
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
this.id(yesId).addEventListener('click', checked)
|
|
247
|
+
this.id(noId).addEventListener('click', checked)
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
previousAddress() {
|
|
252
|
+
const timeAddy = this.id('time_at_address_id')
|
|
253
|
+
const prevAddy = this.id('previous_address_class')
|
|
254
|
+
const showPrev = () => {
|
|
255
|
+
if (timeAddy.value != '3 years+') {
|
|
256
|
+
prevAddy.style.display = 'block'
|
|
257
|
+
this.id('previous_address_help').innerHTML = "Please enter your full address: House No, Street Name, Town/City and Post Code"
|
|
258
|
+
} else {
|
|
259
|
+
prevAddy.style.display = 'none'
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
}
|
|
263
|
+
timeAddy.addEventListener('change', showPrev)
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { qSelAll, id } from './UtilityHtml.js';
|
|
2
|
+
|
|
3
|
+
export const convertFormData = (formId) => {
|
|
4
|
+
const formInput = qSelAll(formId)
|
|
5
|
+
const formInputArr = Array.from(formInput)
|
|
6
|
+
return new FormHelper(formInputArr)
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Sets up an event listener for the given button element that triggers a file upload click event.
|
|
12
|
+
* Also sets up an event listener for the given input element that displays the name of the selected files.
|
|
13
|
+
* @param {string} uploadBtn - the id of a button element that will trigger the file upload dialog box.
|
|
14
|
+
* @param {string} inputId - the id of the input element with the file type.
|
|
15
|
+
* @param {string} fileName - the id of the element where the selected file names will be displayed.
|
|
16
|
+
*/
|
|
17
|
+
export const showImageFileUploadFn = (uploadBtn, inputId, fileName) => {
|
|
18
|
+
const input = id(inputId);
|
|
19
|
+
const fileNamesEl = id(fileName);
|
|
20
|
+
id(uploadBtn).addEventListener('click', () => input.click());
|
|
21
|
+
input.addEventListener('change', () => fileNamesEl.innerText = Array.from(input.files).map(file => file.name).join(', '));
|
|
22
|
+
};
|
package/Http.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { id, log } from './UtilityHtml.js';
|
|
2
|
+
import { clearLoader } from './Loader.js';
|
|
3
|
+
import axios from 'axios'
|
|
4
|
+
import axiosRetry from 'axios-retry';
|
|
5
|
+
|
|
6
|
+
axiosRetry(axios, { retries: 3 });
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export const postFormData = async (url, formId, redirect = null, css = null) => {
|
|
10
|
+
const notificationForm = `${formId}_notification`;
|
|
11
|
+
const notificationId = id(notificationForm);
|
|
12
|
+
|
|
13
|
+
if (!notificationId) {
|
|
14
|
+
throw new Error('Notification element not found');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Cleanup previous notification styles
|
|
18
|
+
notificationId.style.display = 'none';
|
|
19
|
+
notificationId.className = notificationId.className.replace(/is-danger|is-success|w3-red|w3-green|bg-danger|bg-success/g, '');
|
|
20
|
+
|
|
21
|
+
const form = id(formId);
|
|
22
|
+
if (!form) {
|
|
23
|
+
throw new Error('Form element not found');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const formEntries = new FormData(form);
|
|
27
|
+
formEntries.delete('submit');
|
|
28
|
+
formEntries.delete('checkbox_id');
|
|
29
|
+
|
|
30
|
+
const options = {
|
|
31
|
+
baseURL: '/',
|
|
32
|
+
xsrfCookieName: 'XSRF-TOKEN',
|
|
33
|
+
xsrfHeaderName: 'X-XSRF-TOKEN',
|
|
34
|
+
withCredentials: true,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const response = await axios.post(url, formEntries, options);
|
|
39
|
+
if (!(response.status >= 200 && response.status < 300)) {
|
|
40
|
+
throw new Error(response.data?.message || 'Request failed');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const successClass = getNotificationClassByCSS(css || 'bulma', 'green');
|
|
44
|
+
const { message } = response.data || {};
|
|
45
|
+
const { id: idSetFromHttp, famCode: famCodeSetFromHttp, outcome: dbHttpResult } = typeof message === 'object' ? message : { outcome: message };
|
|
46
|
+
|
|
47
|
+
if (!idSetFromHttp || !dbHttpResult || !famCodeSetFromHttp) {
|
|
48
|
+
throw new Error('Response data is missing required fields');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
sessionStorage.setItem('idSetFromHttp', sessionStorage.getItem('idSetFromHttp') || idSetFromHttp);
|
|
52
|
+
sessionStorage.setItem('famCodeSetFromHttp', sessionStorage.getItem('famCodeSetFromHttp') || famCodeSetFromHttp);
|
|
53
|
+
|
|
54
|
+
processFormDataAction(successClass, dbHttpResult, notificationId);
|
|
55
|
+
|
|
56
|
+
if (redirect) {
|
|
57
|
+
setTimeout(() => window.location.assign(redirect), 2000);
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
const errorClass = getNotificationClassByCSS(css || 'bulma', 'red');
|
|
61
|
+
const errorMessage = error.response?.data?.error || error.request || 'An unknown error occurred';
|
|
62
|
+
processFormDataAction(errorClass, errorMessage, notificationId);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Displays a notification message and handles the loading indicator.
|
|
69
|
+
* @param {string} cssClass - The CSS class to add to the notification element.
|
|
70
|
+
* @param {string} message - The message to display in the notification element.
|
|
71
|
+
* @param {HTMLElement} formNotificationId - The notification element to display the message in.
|
|
72
|
+
* @returns {void}
|
|
73
|
+
*/
|
|
74
|
+
const processFormDataAction = (cssClass, message, formNotificationId) => {
|
|
75
|
+
if (!formNotificationId) {
|
|
76
|
+
return log('Notification element not found');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
formNotificationId.style.display = 'block';
|
|
80
|
+
formNotificationId.classList.add(cssClass);
|
|
81
|
+
|
|
82
|
+
const errorElement = id('error');
|
|
83
|
+
if (errorElement) {
|
|
84
|
+
errorElement.innerHTML = message;
|
|
85
|
+
errorElement.scrollIntoView({ behavior: 'smooth' });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
clearLoader();
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const getNotificationClassByCSS = (css, color) => (css === 'bulma' ? `is-${color}` : color === 'green' ? `${css}-${color}` : `${css}-danger`);
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Fetches data from a specified API endpoint using a GET request.
|
|
96
|
+
*
|
|
97
|
+
* @param {string} URL - The API endpoint to fetch data from.
|
|
98
|
+
* @param {string|null} [token=null] - Optional authorization token for the request.
|
|
99
|
+
* @returns {Promise<Object>} - A promise that resolves with the response data or rejects with an error.
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
export const getApiData = async (URL, token = null) => {
|
|
103
|
+
const headers = {
|
|
104
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
105
|
+
'Content-Type': 'application/json',
|
|
106
|
+
'Accept': 'application/json',
|
|
107
|
+
};
|
|
108
|
+
if (token) {
|
|
109
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const response = await axios.get(URL, { headers });
|
|
114
|
+
return response.data;
|
|
115
|
+
} catch (error) {
|
|
116
|
+
return Promise.reject(error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
export const getMultipleApiData = async (url1, url2, token = null) => {
|
|
122
|
+
const config = {
|
|
123
|
+
headers: {
|
|
124
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
125
|
+
'Content-Type': 'application/json',
|
|
126
|
+
'Accept': 'application/json',
|
|
127
|
+
Authorization: `Bearer ${token}`,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
return await axios.all([axios.get(url1, config), axios.get(url2, config)]).then(axios.spread((res1, res2) => [res1.data, res2.data]));
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const postMultipleApiData = async (url1, url2, formData, token = null) => {
|
|
135
|
+
const config = {
|
|
136
|
+
headers: {
|
|
137
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
'Accept': 'application/json',
|
|
140
|
+
'Authorization': 'Bearer ' + token
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const [res1, res2] = await Promise.all([
|
|
145
|
+
axios.post(url1, formData, config),
|
|
146
|
+
axios.post(url2, formData, config),
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
return [res1.data, res2.data];
|
|
150
|
+
};
|
package/Loader.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const loaderIconBootstrap = () => {
|
|
2
|
+
|
|
3
|
+
return `<div class="spinner-grow text-primary" role="status">
|
|
4
|
+
<span class="sr-only">Loading...</span>
|
|
5
|
+
</div>`
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const loaderIcon = () => {
|
|
9
|
+
|
|
10
|
+
return `<div class="loader"></div>`
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const loaderIconBulma = () => {
|
|
14
|
+
|
|
15
|
+
return `<div class="is-loading"></div>`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const clearLoader = (elementId = 'setLoader', loaderClass = "loader") => {
|
|
19
|
+
const loader = id(elementId);
|
|
20
|
+
if (!loader) {
|
|
21
|
+
throw new Error(`Element not found`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
loader.style.display = "none";
|
|
25
|
+
loader.classList.remove(loaderClass);
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
export const showLoader = (elementId ='setLoader', loaderClass = "loader") => {
|
|
29
|
+
const loader = id(elementId);
|
|
30
|
+
if (!loader) {
|
|
31
|
+
throw new Error(`Element not found`);
|
|
32
|
+
}
|
|
33
|
+
loader.classList.add(loaderClass);
|
|
34
|
+
loader.style.display = "block";
|
|
35
|
+
};
|
package/Login.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { convertFormData } from './FormProcessing.js';
|
|
3
|
+
import { postFormData } from "./Http.js";
|
|
4
|
+
import { showLoader, clearLoader } from './Loader.js';
|
|
5
|
+
import { showError } from "./ShowResponse.js";
|
|
6
|
+
|
|
7
|
+
// block the setLoader div
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Handles the submission of the login form.
|
|
11
|
+
* @param {string} formId - The ID of the form to submit.
|
|
12
|
+
* @param {string} loginURL - The URL to make the POST request to.
|
|
13
|
+
* @param {string} redirect - The URL to redirect the user to after the submission is complete.
|
|
14
|
+
* @param {string} [css=null] - The CSS class to add to the notification element if the submission is successful.
|
|
15
|
+
* @returns {void}
|
|
16
|
+
* @throws {Error} - If there is an error with the submission
|
|
17
|
+
*/
|
|
18
|
+
export const loginSubmission = async (formId, loginURL, redirect, css = null) => {
|
|
19
|
+
const formData = convertFormData(formId);
|
|
20
|
+
formData.clearError();
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
formData.emailVal();
|
|
24
|
+
formData.massValidate();
|
|
25
|
+
|
|
26
|
+
if (!formData.error.length) {
|
|
27
|
+
|
|
28
|
+
showLoader();
|
|
29
|
+
localStorage.setItem('redirect', redirect);
|
|
30
|
+
|
|
31
|
+
await postFormData(loginURL, formId, redirect, css);
|
|
32
|
+
} else {
|
|
33
|
+
alert('The form cannot be submitted. Please check the errors');
|
|
34
|
+
}
|
|
35
|
+
} catch (err) {
|
|
36
|
+
showError(err);
|
|
37
|
+
} finally {
|
|
38
|
+
clearLoader();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
package/ShowResponse.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { id } from './UtilityHtml.js';
|
|
2
|
+
import axios from "axios"
|
|
3
|
+
export const showError = (e) => console.error(`${e.name} at ${e.fileName}:${e.lineNumber} - ${e.message}\n${e.stack}`);
|
|
4
|
+
|
|
5
|
+
export const msgException = (errorMessage) => {
|
|
6
|
+
|
|
7
|
+
throw new Error(errorMessage)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {*} elementId - element id
|
|
14
|
+
* @param {*} addClass either a success or danger class (green or red)
|
|
15
|
+
* @param {*} message - html message to convey success or failure
|
|
16
|
+
* @param {*} timer - timer for the message to disappear- default is 5 secs
|
|
17
|
+
*/
|
|
18
|
+
export const showNotification = (elementId, addClass, message, timer = 5000) => {
|
|
19
|
+
// display the success information for 10sec
|
|
20
|
+
id(`${elementId}`).style.display = "block" // unblock the notification
|
|
21
|
+
id(`${elementId}`).classList.add(addClass) // add the success class
|
|
22
|
+
id(`${elementId}`).innerHTML = message // error element
|
|
23
|
+
id('loader').classList.remove('loader') // remove loader
|
|
24
|
+
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
id(`${elementId}`).style.backgroundColor = ""
|
|
27
|
+
id(`${elementId}`).style.color = ""
|
|
28
|
+
id(`${elementId}`).innerHTML = ""
|
|
29
|
+
}, timer)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @param {*} elementId - element id
|
|
35
|
+
* @returns {Promise<void>}
|
|
36
|
+
* @description This is a function that deletes a notification. It takes in the elementId of the delete button
|
|
37
|
+
* and uses that to get the user ID and the notification ID. It makes a put request to the server to
|
|
38
|
+
* mark the notification as read. If the request is successful, it removes the notification from the page
|
|
39
|
+
* and decrements the notification count by 1. If the request is unsuccessful, it logs an error message.
|
|
40
|
+
*/
|
|
41
|
+
export const deleteNotification = async (elementId) => {
|
|
42
|
+
|
|
43
|
+
// Extract the user ID from the target ID
|
|
44
|
+
const senderId = elementId.replace("deleteNotification", "notificationBar");
|
|
45
|
+
|
|
46
|
+
const elementData = id(elementId)
|
|
47
|
+
const data = elementData.getAttribute("data-id");
|
|
48
|
+
|
|
49
|
+
// change the background of the clicked element
|
|
50
|
+
|
|
51
|
+
const notificationHTML = id(senderId);
|
|
52
|
+
|
|
53
|
+
// Make sure required variables are defined before using them
|
|
54
|
+
if (
|
|
55
|
+
typeof yourId === 'undefined' ||
|
|
56
|
+
typeof famCode === 'undefined'
|
|
57
|
+
) {
|
|
58
|
+
msgException("Required parameters (yourId or famCode) are not defined");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const url = `/removeNotification/${yourId}/${famCode}/${data}`
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
const response = await axios.put(url)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if (response.data.message === "Notification marked as read") {
|
|
68
|
+
|
|
69
|
+
// remove a html element with notificationBar after 2 mins
|
|
70
|
+
notificationHTML.remove()
|
|
71
|
+
|
|
72
|
+
// reduce the notification count as you have deleted the notification
|
|
73
|
+
|
|
74
|
+
const newValues = parseInt(sessionStorage.getItem('notificationCount') - 1)
|
|
75
|
+
id('notification_count').innerHTML = newValues;
|
|
76
|
+
} else {
|
|
77
|
+
msgException("Error removing notification" + " " + response.data.message);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const showResponse = (theId, message, status) => {
|
|
82
|
+
const responseEl = id(theId)
|
|
83
|
+
const col = status ? 'green' : 'red'
|
|
84
|
+
|
|
85
|
+
responseEl.innerHTML = message
|
|
86
|
+
responseEl.style.color = 'green'
|
|
87
|
+
responseEl.style.backgroundColor = col
|
|
88
|
+
responseEl.style.color = 'white';
|
|
89
|
+
setTimeout(() => {
|
|
90
|
+
responseEl.innerHTML = '';
|
|
91
|
+
}, 5000); // Disappear after 5 seconds
|
|
92
|
+
|
|
93
|
+
}
|