@modernman00/shared-js-lib 1.2.67 → 1.2.68

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.
@@ -1,47 +1,8 @@
1
- import { loginSubmission } from './processAll.js';
1
+ // setupPasswordChange.js
2
2
  import { id } from '../UtilityHtml.js';
3
3
  import { bindEvent, showPassword } from '../Utility.js';
4
4
  import { matchInput } from '../general.js';
5
- import { showError } from '../ShowResponse.js';
6
-
7
-
8
- /**
9
- * Initializes password change functionality with accessibility, validation, and submission logic.
10
- *
11
- * This function sets up:
12
- * - ARIA attributes for accessibility
13
- * - Input matching between password and confirmation fields
14
- * - Max length enforcement
15
- * - Event bindings for submit and password visibility toggle
16
- * - Form submission via `loginSubmission`
17
- *
18
- * @function setupPasswordChange
19
- * @param {Object} [config] - Configuration object for customizing behavior.
20
- * @param {string} [config.buttonId='button'] - ID of the submit button.
21
- * @param {string} [config.passwordId='password'] - ID of the password input field.
22
- * @param {string} [config.confirmId='confirm_password'] - ID of the confirm password input field.
23
- * @param {string} [config.showToggleId='showPassword'] - ID of the toggle button to show/hide password.
24
- * @param {string} [config.errorId='confirm_password_error'] - ID of the element to display mismatch errors.
25
- * @param {string} [config.helpId='password_help'] - ID of the helper text element for password guidance.
26
- * @param {string} [config.route] - API endpoint for password change submission.
27
- * @param {string} [config.redirect] - URL to redirect to after successful password change.
28
- * @param {string} [config.theme='bulma'] - UI theme identifier passed to `loginSubmission`.
29
- * @param {number} [config.maxLength=50] - Maximum allowed length for password fields.
30
- * @param {Object} [config.recaptchaV3=null] - reCAPTCHA v3 configuration ({ siteKey: 'xxx', action: 'CHANGE_PASSWORD' }).
31
- *
32
- * @example
33
- * setupPasswordChange(); // Uses default IDs and routes
34
- *
35
- * @example
36
- * setupPasswordChange({
37
- * buttonId: 'submitBtn',
38
- * passwordId: 'new_password',
39
- * confirmId: 'confirm_new_password',
40
- * route: '/api/change-password',
41
- * redirect: '/dashboard'
42
- * });
43
- */
44
-
5
+ import { createFormHandler } from './createFormHandler.js';
45
6
 
46
7
  export const setupPasswordChange = ({
47
8
  formId = 'changePassword',
@@ -53,57 +14,43 @@ export const setupPasswordChange = ({
53
14
  helpId = 'password_help',
54
15
  route,
55
16
  redirect,
17
+ lengthLimitArray = null, // { id: [...], max: [...] } or null
18
+ optionalFields = [],
56
19
  theme = 'bulma',
57
- maxLength = 50,
58
- recaptchaV3 = null // { siteKey: 'xxx', action: 'CHANGE_PASSWORD' }
20
+ recaptchaAction = 'CHANGE_PASSWORD'
59
21
  } = {}) => {
60
- // Accessibility & input attributes
61
22
  const passwordInput = id(passwordId);
62
23
  const showToggle = id(showToggleId);
63
24
  const helperText = id(helpId);
64
25
 
65
- passwordInput.setAttribute('autocomplete', 'current-password');
66
- showToggle.setAttribute('aria-label', 'Warning: this will display your password on the screen.');
67
- helperText.setAttribute('aria-live', 'polite');
68
- helperText.textContent =
69
- 'Password must be at least 8 characters long, contain at least one uppercase letter, one lowercase letter, one number, and one special character.';
70
-
71
-
72
-
73
- // Length limit object
74
- const lengthLimit = {
75
- maxLength: {
76
- id: [passwordId, confirmId],
77
- max: [maxLength, maxLength]
78
- }
79
- };
80
-
81
- // Submission handler
82
- const handleSubmit = async (e) => {
83
- e.preventDefault();
26
+ if (passwordInput) {
27
+ passwordInput.setAttribute('autocomplete', 'current-password');
28
+ }
84
29
 
85
- let recaptchaToken = null;
86
- // Only run v3 if configured AND grecaptcha is available
87
- if (recaptchaV3?.siteKey && window.grecaptcha && window.grecaptcha.enterprise) {
88
- try {
89
- recaptchaToken = await grecaptcha.enterprise.execute(
90
- recaptchaV3.siteKey,
91
- { action: recaptchaV3.action || 'CHANGE_PASSWORD' });
92
- } catch (err) {
93
- showError(err);
94
- }
95
- }
30
+ if (showToggle) {
31
+ showToggle.setAttribute(
32
+ 'aria-label',
33
+ 'Warning: this will display your password on the screen.'
34
+ );
35
+ }
96
36
 
97
- loginSubmission(formId, route, redirect, theme, lengthLimit, [], recaptchaToken);
37
+ if (helperText) {
38
+ helperText.setAttribute('aria-live', 'polite');
39
+ helperText.textContent =
40
+ 'Password must be at least 8 characters long, contain at least one uppercase letter, one lowercase letter, one number, and one special character.';
41
+ }
98
42
 
99
-
100
- };
101
-
102
- // Bind events
103
- bindEvent({ id: buttonId, handler: handleSubmit });
104
43
  bindEvent({ id: showToggleId, handler: () => showPassword(passwordId) });
105
44
  matchInput(passwordId, confirmId, errorId);
106
- };
107
-
108
-
109
45
 
46
+ createFormHandler({
47
+ formId,
48
+ buttonId,
49
+ route,
50
+ redirect,
51
+ theme,
52
+ lengthLimit: lengthLimitArray,
53
+ optionalFields,
54
+ recaptchaAction
55
+ });
56
+ };
package/AcctMgt/code.js CHANGED
@@ -1,30 +1,6 @@
1
- import { loginSubmission } from './processAll.js';
2
- import { bindEvent } from '../Utility.js';
3
- import { showError } from '../ShowResponse.js';
1
+ // createCodeSubmitHandler.js
2
+ import { createFormHandler } from './createFormHandler.js';
4
3
 
5
- /**
6
- * Creates a reusable form submission handler for code-based forms.
7
- *
8
- * @function createCodeSubmitHandler
9
- * @param {Object} options - Configuration for the handler.
10
- * @param {string} options.formId - ID of the form element.
11
- * @param {string} options.inputId - ID of the input field to validate.
12
- * @param {string} options.buttonId - ID of the submit button.
13
- * @param {string} options.route - API endpoint for submission.
14
- * @param {string} options.redirect - URL to redirect to after success.
15
- * @param {string} [options.theme='bulma'] - UI theme identifier.
16
- * @param {number} [options.maxLength=50] - Max input length.
17
- * @param {Object} [options.recaptchaV3=null] - reCAPTCHA v3 configuration ({ siteKey: 'OUR_ENTERPRISE_SITE_KEYx', action: 'TOKEN' }).
18
- *
19
- * @example
20
- * createCodeSubmitHandler({
21
- * formId: 'codeForm',
22
- * inputId: 'code',
23
- * buttonId: 'button',
24
- * route: appTestRoutes.appTestCode,
25
- * redirect: appTestRoutes.appTestCodeRedirect
26
- * });
27
- */
28
4
  export function createCodeSubmitHandler({
29
5
  formId,
30
6
  inputId = 'code',
@@ -32,46 +8,17 @@ export function createCodeSubmitHandler({
32
8
  route,
33
9
  redirect,
34
10
  theme = 'bulma',
35
- maxLength = 50,
36
- recaptchaV3 = null // { siteKey: 'xxx', action: 'LOGIN' }
11
+ lengthLimitArray = null, // { id: [...], max: [...] } or null
12
+ recaptchaAction = 'SUBMIT'
37
13
  }) {
38
- const handler = async (e) => {
39
- e.preventDefault();
40
-
41
- let recaptchaToken = null;
42
- // Only run v3 if configured AND grecaptcha is available
43
- if (recaptchaV3?.siteKey && window.grecaptcha && window.grecaptcha.enterprise) {
44
- try {
45
- recaptchaToken = await grecaptcha.enterprise.execute(
46
- recaptchaV3.siteKey,
47
- { action: recaptchaV3.action || 'LOGIN' });
48
- } catch (err) {
49
- showError(err);
50
- }
51
- }
52
-
53
- const lengthLimit = {
54
- maxLength: {
55
- id: [inputId],
56
- max: [maxLength]
57
- }
58
- };
59
-
60
- loginSubmission(formId, route, redirect, theme, lengthLimit);
61
- loginSubmission({
62
- 'formId': formId,
63
- 'loginURL': route,
64
- 'redirect': redirect,
65
- 'css': theme,
66
- 'lengthLimit': lengthLimit,
67
- 'optionalFields': [],
68
- 'recaptchaToken':{
69
- siteKey: recaptchaToken,
70
- action: 'LOGIN'
71
- }
72
- })
73
- };
74
-
75
- bindEvent({ id: buttonId, handler });
14
+ createFormHandler({
15
+ formId,
16
+ buttonId,
17
+ route,
18
+ redirect,
19
+ theme,
20
+ lengthLimit: lengthLimitArray,
21
+ optionalFields: [inputId],
22
+ recaptchaAction
23
+ });
76
24
  }
77
-
@@ -0,0 +1,35 @@
1
+ // createFormHandler.js
2
+ import { bindEvent } from '../Utility.js';
3
+ import { recaptchaToken } from './recaptchaToken.js';
4
+ import { loginSubmission } from './processAll.js';
5
+
6
+ export function createFormHandler({
7
+ formId,
8
+ buttonId = 'button',
9
+ route,
10
+ redirect,
11
+ theme = 'bulma',
12
+ lengthLimit = null, // { id: [...], max: [...] } or null
13
+ optionalFields = [], // ['remember_me', 'captcha'] etc.
14
+ recaptchaAction = 'SUBMIT'
15
+ }) {
16
+ const handler = async (e) => {
17
+ e.preventDefault();
18
+
19
+ const token = await recaptchaToken(recaptchaAction);
20
+
21
+ await loginSubmission({
22
+ formId,
23
+ loginURL: route,
24
+ redirect,
25
+ css: theme,
26
+ lengthLimit,
27
+ optionalFields,
28
+ recaptchaToken: token
29
+ ? { token, action: recaptchaAction }
30
+ : null
31
+ });
32
+ };
33
+ // 🔹 This is the click binding you’re referring to
34
+ bindEvent({ id: buttonId, handler });
35
+ }
package/AcctMgt/forgot.js CHANGED
@@ -1,36 +1,6 @@
1
- import { loginSubmission } from './processAll.js';
2
- import { bindEvent } from '../Utility.js';
3
- import { showError } from '../ShowResponse.js';
1
+ // forgotSubmitHandler.js
2
+ import { createFormHandler } from './createFormHandler.js';
4
3
 
5
-
6
- /**
7
- * Creates a reusable form submission handler for email-based forms.
8
- *
9
- * This function:
10
- * - Prevents default form submission
11
- * - Applies max length validation to the email input
12
- * - Submits the form using `loginSubmission` with route and redirect logic
13
- *
14
- * @function createEmailSubmitHandler
15
- * @param {Object} options - Configuration for the handler.
16
- * @param {string} options.formId - ID of the form element.
17
- * @param {string} options.inputId - ID of the email input field.
18
- * @param {string} options.buttonId - ID of the submit button.
19
- * @param {string} options.route - API endpoint for submission.
20
- * @param {string} options.redirect - URL to redirect to after success.
21
- * @param {string} [options.theme='bulma'] - UI theme identifier.
22
- * @param {number} [options.maxLength=50] - Max input length.
23
- * @param {Object} [options.recaptchaV3=null] - reCAPTCHA v3 configuration ({ siteKey: 'OUR_ENTERPRISE_SITE_KEYx', action: 'FORGOT' }).
24
- *
25
- * @example
26
- * createEmailSubmitHandler({
27
- * formId: 'forgotPassword',
28
- * inputId: 'email',
29
- * buttonId: 'button',
30
- * route: appTestRoutes.appTestForgot,
31
- * redirect: appTestRoutes.appTestForgotRedirect
32
- * });
33
- */
34
4
  export function forgotSubmitHandler({
35
5
  formId,
36
6
  inputId = 'email',
@@ -38,35 +8,19 @@ export function forgotSubmitHandler({
38
8
  route,
39
9
  redirect,
40
10
  theme = 'bulma',
41
- maxLength = 50,
42
- recaptchaV3 = null // { siteKey: 'xxx', action: 'LOGIN' }
11
+ lengthLimitArray = null, // { id: [...], max: [...] } or null
12
+ recaptchaAction = 'FORGOT'
43
13
  }) {
44
- const handler = async (e) => {
45
- e.preventDefault();
46
-
47
- let recaptchaToken = null;
48
- // Only run v3 if configured AND grecaptcha is available
49
- if (recaptchaV3?.siteKey && window.grecaptcha && window.grecaptcha.enterprise) {
50
- try {
51
- recaptchaToken = await grecaptcha.enterprise.execute(
52
- recaptchaV3.siteKey,
53
- { action: recaptchaV3.action || 'LOGIN' });
54
- } catch (err) {
55
- showError(err);
56
- }
57
- }
58
-
59
- const lengthLimit = {
60
- maxLength: {
61
- id: [inputId],
62
- max: [maxLength]
63
- }
64
- };
65
-
66
- loginSubmission(formId, route, redirect, theme, lengthLimit);
67
- };
68
-
69
- bindEvent({ id: buttonId, handler });
14
+ createFormHandler({
15
+ formId,
16
+ buttonId,
17
+ route,
18
+ redirect,
19
+ theme,
20
+ lengthLimit: lengthLimitArray,
21
+ optionalFields: [inputId],
22
+ recaptchaAction
23
+ });
70
24
  }
71
25
 
72
26
 
package/AcctMgt/login.js CHANGED
@@ -1,42 +1,8 @@
1
- import { loginSubmission } from './processAll.js';
2
- import { id} from '../UtilityHtml.js';
1
+ // createAdminLoginHandler.js
2
+ import { id } from '../UtilityHtml.js';
3
3
  import { bindEvent, showPassword } from '../Utility.js';
4
- import { showError } from '../ShowResponse.js';
4
+ import { createFormHandler } from './createFormHandler.js';
5
5
 
6
-
7
- /**
8
- * Creates a reusable admin login handler with password visibility and accessibility support.
9
- *
10
- * This function:
11
- * - Binds form submission to `loginSubmission`
12
- * - Applies max length validation to email and password fields
13
- * - Enables password visibility toggle
14
- * - Sets accessibility attributes for screen readers and autocomplete
15
- *
16
- * @function createAdminLoginHandler
17
- * @param {Object} options - Configuration for the login handler.
18
- * @param {string} options.formId - ID of the login form.
19
- * @param {string} options.emailId - ID of the email input field.
20
- * @param {string} options.passwordId - ID of the password input field.
21
- * @param {string} options.buttonId - ID of the submit button.
22
- * @param {string} options.showToggleId - ID of the password visibility toggle button.
23
- * @param {string} options.route - API endpoint for login submission.
24
- * @param {string} options.redirect - URL to redirect to after successful login.
25
- * @param {string} [options.theme='bootstrap'] - UI theme identifier.
26
- * @param {number[]} [options.maxLength=[30, 50]] - Max lengths for password and email respectively.
27
- * @param {Object} [options.recaptchaV3=null] - reCAPTCHA v3 configuration ({ siteKey: 'OUR_ENTERPRISE_SITE_KEY', action: 'LOGIN' }).
28
- *
29
- * @example
30
- * createAdminLoginHandler({
31
- * formId: 'managed',
32
- * emailId: 'email',
33
- * passwordId: 'password',
34
- * buttonId: 'button',
35
- * showToggleId: 'showPassword',
36
- * route: appTestRoutes.appTest,
37
- * redirect: appTestRoutes.redirect
38
- * });
39
- */
40
6
  export function createAdminLoginHandler({
41
7
  formId,
42
8
  emailId = 'email',
@@ -46,43 +12,37 @@ export function createAdminLoginHandler({
46
12
  route,
47
13
  redirect,
48
14
  theme = 'bootstrap',
49
- maxLength = [30, 50],
50
- recaptchaV3 = null // { siteKey: 'xxx', action: 'LOGIN' }
15
+ recaptchaAction = 'LOGIN',
16
+ lengthLimitArray = null,
17
+ optionalFields = []
51
18
  }) {
52
- const handler = async (e) => {
53
- e.preventDefault();
54
-
55
- let recaptchaToken = null;
56
- // Only run v3 if configured AND grecaptcha is available
57
- if (recaptchaV3?.siteKey && window.grecaptcha && window.grecaptcha.enterprise) {
58
- try {
59
- recaptchaToken = await grecaptcha.enterprise.execute(
60
- recaptchaV3.siteKey,
61
- { action: recaptchaV3.action || 'LOGIN' } );
62
- } catch (err) {
63
- showError(err);
64
- }
65
- }
19
+ // Accessibility
20
+ const passwordInput = id(passwordId);
21
+ const toggleLabel = id(showToggleId);
66
22
 
67
- const lengthLimit = {
68
- maxLength: {
69
- id: [passwordId, emailId],
70
- max: maxLength
71
- }
72
- };
23
+ if (passwordInput) {
24
+ passwordInput.setAttribute('autocomplete', 'current-password');
25
+ }
73
26
 
74
- loginSubmission(formId, route, redirect, theme, lengthLimit, [], recaptchaToken);
75
- };
27
+ if (toggleLabel) {
28
+ toggleLabel.setAttribute(
29
+ 'aria-label',
30
+ 'Warning: this will display your password on the screen.'
31
+ );
32
+ }
76
33
 
77
- bindEvent({ id: buttonId, handler });
34
+ // Password visibility toggle
78
35
  bindEvent({ id: showToggleId, handler: () => showPassword(passwordId) });
79
36
 
80
- const passwordInput = id(passwordId);
81
- const toggleLabel = id(showToggleId);
82
-
83
- passwordInput.setAttribute('autocomplete', 'current-password');
84
- toggleLabel.setAttribute(
85
- 'aria-label',
86
- 'Warning: this will display your password on the screen.'
87
- );
37
+ // Core handler
38
+ createFormHandler({
39
+ formId,
40
+ buttonId,
41
+ route,
42
+ redirect,
43
+ theme,
44
+ lengthLimit: lengthLimitArray,
45
+ optionalFields: [emailId, passwordId, ...optionalFields],
46
+ recaptchaAction
47
+ });
88
48
  }
@@ -1,3 +1,4 @@
1
+ // processAll.js
1
2
  'use strict';
2
3
  import { postFormData } from '../Http.js';
3
4
  import { showLoader, clearLoader } from '../Loader.js';
@@ -5,59 +6,49 @@ import { id } from '../UtilityHtml.js';
5
6
  import { showError } from '../ShowResponse.js';
6
7
  import FormHelper from '../FormHelper.js';
7
8
 
8
-
9
- // block the setLoader div
10
-
11
9
  /**
12
- * Handles the submission of the login form and redirects the user.
13
- * @param {string} formId - The ID of the form to submit.
14
- * @param {string} loginURL - The URL to make the POST request to.
15
- * @param {string} redirect - The URL to redirect the user to after the submission is complete.
16
- * @param {string} [css=null] - The CSS class to add to the notification element if the submission is successful.
17
- * @returns {void} yes
18
- * @throws {Error} - If there is an error with the submission
19
- * @param {Object} [options.recaptchaV3=null] - reCAPTCHA v3 configuration ({ siteKey: 'OUR_ENTERPRISE_SITE_KEY', action: 'LOGIN' }).
10
+ * Handles the submission of a form and redirects the user.
20
11
  */
21
- export const loginSubmission = async ({formId, loginURL, redirect, css = null, lengthLimit = null, optionalFields = [], recaptchaToken = null
12
+ export const loginSubmission = async ({
13
+ formId,
14
+ loginURL,
15
+ redirect,
16
+ css = null,
17
+ lengthLimit = null, // { id: [...], max: [...] } or null
18
+ optionalFields = [],
19
+ recaptchaToken = null // { token, action } or null
22
20
  }) => {
23
-
24
21
  try {
25
-
26
22
  const formInput = id(formId);
27
23
 
28
24
  if (!formInput) {
29
25
  throw new Error(`Form ${formId} not found`);
30
- return;
31
26
  }
32
27
 
33
28
  const formInputArr = Array.from(formInput.elements);
34
-
35
29
  const formData = new FormHelper(formInputArr);
36
30
 
37
31
  formData.clearError();
38
32
 
39
33
  if (lengthLimit) {
40
- formData.realTimeCheckLen(lengthLimit.maxLength.id, lengthLimit.maxLength.max);
34
+ formData.realTimeCheckLen(lengthLimit.id, lengthLimit.max);
41
35
  }
42
36
 
43
37
  formData.massValidate(optionalFields, { email: 'email', password: 'password' });
44
38
 
45
- if (formData.result === 1) {
46
-
47
- const notificationId = id(`${formId}_notification`) || formId;
48
-
49
- notificationId.scrollIntoView({ behavior: 'smooth' });
50
-
51
- showLoader();
39
+ if (formData.result !== 1) {
40
+ alert('The form cannot be submitted. Please check the errors');
41
+ return;
42
+ }
52
43
 
53
- localStorage.setItem('redirect', redirect);
44
+ const notificationId = id(`${formId}_notification`) || formId;
45
+ notificationId.scrollIntoView({ behavior: 'smooth' });
54
46
 
55
- await postFormData(loginURL, formId, redirect, css, recaptchaToken);
47
+ showLoader();
48
+ localStorage.setItem('redirect', redirect);
56
49
 
57
- } else {
50
+ await postFormData(loginURL, formId, redirect, css, recaptchaToken);
58
51
 
59
- alert('The form cannot be submitted. Please check the errors');
60
- }
61
52
  } catch (err) {
62
53
  showError(err);
63
54
  } finally {
@@ -0,0 +1,19 @@
1
+ // recaptchaToken.js
2
+ import { showError } from '../ShowResponse.js';
3
+
4
+ export const recaptchaToken = async (action = 'SUBMIT') => {
5
+ let token = null;
6
+
7
+ if (window.RECAPTCHA_SITE_KEY && window.grecaptcha && window.grecaptcha.enterprise) {
8
+ try {
9
+ token = await window.grecaptcha.enterprise.execute(
10
+ window.RECAPTCHA_SITE_KEY,
11
+ { action }
12
+ );
13
+ } catch (err) {
14
+ showError(err);
15
+ }
16
+ }
17
+
18
+ return token;
19
+ };
@@ -1,86 +1,24 @@
1
- import { loginSubmission } from './processAll.js';
2
- import { id } from '../UtilityHtml.js';
3
- import { bindEvent, showPassword } from '../Utility.js';
4
- import { showError } from '../ShowResponse.js';
5
-
6
-
7
- /**
8
- * use this handler to submit forms.
9
- *
10
- * This handler:
11
- * - Binds the submit button to an async login workflow
12
- * - Optionally executes reCAPTCHA v3 (Enterprise) and attaches the token
13
- * - Passes configuration (route, redirect, theme, optional fields, length limits)
14
- * to `loginSubmission`
15
- * - Supports custom UI themes and optional field handling
16
- *
17
- * @function registerHandler
18
- * @param {Object} options - Configuration for the login handler.
19
- * @param {string} options.formId - ID of the login form.
20
- * @param {Object} options.lengthLimitArray - Max-length configuration for form fields.
21
- * @param {string} [options.buttonId='button'] - ID of the submit button.
22
-
23
- * @param {string} options.route - API endpoint for login submission.
24
- * @param {string} options.redirect - URL to redirect to after successful login.
25
- * @param {string} [options.theme='bootstrap'] - UI theme identifier.
26
- * @param {string} [options.recaptchaAction='SUBMIT'] - Action name for reCAPTCHA v3 execution.
27
- * @param {string[]} [options.optionalFields=[]] - Optional form fields to include in submission.
28
- *
29
- * @example
30
- * formHandler({
31
- * formId: 'loginForm',
32
- * lengthLimitArray: { id: ['email', 'password'], max: [30, 50] },
33
- * buttonId: 'loginBtn',
34
- * route: appRoutes.login,
35
- * redirect: appRoutes.dashboard,
36
- * optionalFields: ['remember_me', 'captcha']
37
- * });
38
- */
1
+ // registerHandler.js
2
+ import { createFormHandler } from './createFormHandler.js';
39
3
 
40
4
  export function registerHandler({
41
- formId, lengthLimitArray,
5
+ formId,
42
6
  buttonId = 'button',
43
7
  route,
44
8
  redirect,
45
9
  theme = 'bootstrap',
46
10
  recaptchaAction = 'SUBMIT',
11
+ lengthLimitArray = null,
47
12
  optionalFields = []
48
13
  }) {
49
- const handler = async (e) => {
50
- e.preventDefault();
51
-
52
- let token = null;
53
- // Only run v3 if configured AND grecaptcha is available
54
- if (window.RECAPTCHA_SITE_KEY && window.grecaptcha && window.grecaptcha.enterprise) {
55
- try {
56
- token = await window.grecaptcha.enterprise.execute(
57
- window.RECAPTCHA_SITE_KEY,
58
- { action: recaptchaAction || 'SUBMIT' });
59
- } catch (err) {
60
- showError(err);
61
- }
62
- }
63
-
64
- if (lengthLimitArray) {
65
- const lengthLimit = {
66
- maxLength: lengthLimitArray
67
- };
68
- }
69
-
70
- loginSubmission(
71
- {
72
- 'formId': formId,
73
- 'loginUrl': route,
74
- 'redirect': redirect,
75
- 'lengthLimit': lengthLimitArray,
76
- 'css': theme,
77
- 'optionalFields': optionalFields,
78
- 'recaptchaToken': token
79
- }
80
- );
81
-
82
- return;
83
- }
84
- bindEvent({ id: buttonId, handler });
85
-
86
- };
14
+ createFormHandler({
15
+ formId,
16
+ buttonId,
17
+ route,
18
+ redirect,
19
+ theme,
20
+ lengthLimit: lengthLimitArray,
21
+ optionalFields,
22
+ recaptchaAction
23
+ });
24
+ }
package/AcctMgt/update.js CHANGED
@@ -1,49 +1,22 @@
1
+ // update.js
1
2
  import { id } from '../UtilityHtml.js';
2
3
  import { bindEvent } from '../Utility.js';
3
4
  import { msgException, showError } from '../ShowResponse.js';
4
5
  import axios from 'axios';
5
6
  import { redirectAfterDelay, parseErrorResponse } from '../general.js';
6
- /**
7
- * Creates a reusable form submission handler for update forms.
8
- *
9
- * @function update
10
- * @param {Object} options - Configuration for the handler.
11
- * @param {string} options.formId - ID of the form element.
12
- * @param {string} options.buttonId - ID of the submit button.
13
- * @param {string} options.route - API endpoint for submission.
14
- * @param {string} options.redirect - URL to redirect to after success.
15
- * @param {Object} [options.recaptchaV3=null] - reCAPTCHA v3 configuration ({ siteKey: 'OUR_ENTERPRISE_SITE_KEY', action: 'LOGIN' }).
16
- *
17
- *
18
- * @example
19
- * update({
20
- * formId: 'updateForm',
21
- * buttonId: 'updateButton',
22
- * route: appTestRoutes.appTestUpdate,
23
- * redirect: appTestRoutes.appTestUpdateRedirect
24
- * });
25
- */
7
+ import { recaptchaToken } from './recaptchaToken.js';
8
+
26
9
  export function update({
27
10
  formId,
28
11
  buttonId,
29
12
  route,
30
13
  redirect,
31
- recaptchaV3 = null // { siteKey: 'xxx', action: 'UPDATE_DATA' }
14
+ recaptchaAction = 'SUBMIT'
32
15
  }) {
33
16
  const handler = async (e) => {
34
17
  e.preventDefault();
35
18
 
36
- let recaptchaToken = null;
37
- // Only run v3 if configured AND grecaptcha is available
38
- if (recaptchaV3?.siteKey && window.grecaptcha && window.grecaptcha.enterprise) {
39
- try {
40
- recaptchaToken = await grecaptcha.enterprise.execute(
41
- recaptchaV3.siteKey,
42
- { action: recaptchaV3.action || 'LOGIN' });
43
- } catch (err) {
44
- showError(err);
45
- }
46
- }
19
+ const token = await recaptchaToken(recaptchaAction);
47
20
 
48
21
  const form = id(formId);
49
22
  if (!form) {
@@ -54,9 +27,8 @@ export function update({
54
27
  const formData = new FormData();
55
28
  const inputs = form.querySelectorAll('[name]');
56
29
 
57
- // if recaptcha token is provided, append it
58
- if (recaptchaToken) {
59
- formData.append('recaptchaTokenV3', recaptchaToken);
30
+ if (token) {
31
+ formData.append('recaptchaTokenV3', token);
60
32
  }
61
33
 
62
34
  inputs.forEach(input => {
@@ -64,7 +36,6 @@ export function update({
64
36
  const original = input.getAttribute('data-original');
65
37
  const current = input.type === 'file' ? input.files[0] : input.value;
66
38
 
67
- // Only include changed fields
68
39
  if (input.type === 'file') {
69
40
  if (current) formData.append(name, current);
70
41
  } else if (current !== original) {
@@ -73,32 +44,25 @@ export function update({
73
44
  });
74
45
 
75
46
  try {
76
-
77
47
  const response = await axios.post(route, formData);
78
-
79
48
  const message = response.data.message;
80
49
 
81
50
  const notificationId = id(`${formId}_notification`) || formId;
82
- notificationId.style.display = 'block'
83
-
84
- notificationId.scrollIntoView({ behavior: 'smooth' });
85
-
51
+ notificationId.style.display = 'block';
86
52
  notificationId.innerHTML = message;
87
-
53
+ notificationId.scrollIntoView({ behavior: 'smooth' });
88
54
 
89
55
  if (redirect) {
90
56
  redirectAfterDelay(redirect, 2000);
91
57
  }
92
58
 
93
59
  } catch (error) {
94
- console.log(error);
95
- const ErrorMsg = parseErrorResponse(error);
96
- const notificationId = id(`${formId}_notification`)
97
- notificationId.style.display = 'block'
98
- notificationId.innerHTML = `<li style="color:white; background-color:red">${ErrorMsg}</li>`;
60
+ const errorMsg = parseErrorResponse(error);
61
+ const notificationId = id(`${formId}_notification`);
62
+ notificationId.style.display = 'block';
63
+ notificationId.innerHTML = `<li style="color:white; background-color:red">${errorMsg}</li>`;
99
64
  }
100
65
  };
101
66
 
102
67
  bindEvent({ id: buttonId, handler });
103
68
  }
104
-
@@ -1,3 +1,3 @@
1
1
  <?php
2
- define('APP_VERSION', 'v1.2.66');
2
+ define('APP_VERSION', 'v1.2.67');
3
3
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modernman00/shared-js-lib",
3
- "version": "1.2.67",
3
+ "version": "1.2.68",
4
4
  "description": "Reusable JS utilities for numerous js problems",
5
5
  "homepage": "https://github.com/modernman00/shared-js-lib#readme",
6
6
  "keywords": [