ultimate-jekyll-manager 0.0.119 → 0.0.120
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/CLAUDE.md +102 -2
- package/README.md +171 -2
- package/TODO.md +10 -2
- package/_backup/form-manager.backup.js +1020 -0
- package/dist/assets/js/libs/auth/pages.js +64 -136
- package/dist/assets/js/libs/form-manager.js +643 -775
- package/dist/assets/js/pages/account/sections/api-keys.js +37 -52
- package/dist/assets/js/pages/account/sections/connections.js +37 -46
- package/dist/assets/js/pages/account/sections/delete.js +46 -66
- package/dist/assets/js/pages/account/sections/profile.js +37 -56
- package/dist/assets/js/pages/account/sections/security.js +100 -126
- package/dist/assets/js/pages/admin/notifications/new/index.js +72 -157
- package/dist/assets/js/pages/blog/index.js +29 -51
- package/dist/assets/js/pages/contact/index.js +110 -144
- package/dist/assets/js/pages/download/index.js +38 -86
- package/dist/assets/js/pages/oauth2/index.js +17 -17
- package/dist/assets/js/pages/payment/checkout/index.js +23 -36
- package/dist/assets/js/pages/test/libraries/form-manager/index.js +194 -0
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signin.html +2 -2
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html +2 -2
- package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/contact.html +10 -37
- package/dist/defaults/dist/pages/test/libraries/form-manager.html +181 -0
- package/dist/gulp/tasks/serve.js +18 -0
- package/dist/lib/logger.js +1 -1
- package/firebase-debug.log +392 -0
- package/package.json +6 -6
- package/.playwright-mcp/page-2025-10-22T19-11-27-666Z.png +0 -0
- package/.playwright-mcp/page-2025-10-22T19-11-57-357Z.png +0 -0
|
@@ -123,47 +123,31 @@ function trackAddPaymentInfo(product, price, billingCycle, paymentMethod) {
|
|
|
123
123
|
function setupEventListeners() {
|
|
124
124
|
// Initialize FormManager
|
|
125
125
|
formManager = new FormManager('#checkout-form', {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
autoReady: false, // We'll call ready() after initialization
|
|
127
|
+
allowResubmit: false,
|
|
128
|
+
submittingText: 'Processing...',
|
|
129
|
+
submittedText: 'Redirecting...',
|
|
130
130
|
});
|
|
131
131
|
|
|
132
132
|
// Listen for form field changes
|
|
133
|
-
formManager.
|
|
134
|
-
const { fieldName, fieldValue, data } = event.detail;
|
|
135
|
-
|
|
133
|
+
formManager.on('change', ({ name, value }) => {
|
|
136
134
|
// Handle billing cycle changes
|
|
137
|
-
if (
|
|
138
|
-
handleBillingCycleChange(
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
// Handle non-submit button clicks
|
|
143
|
-
formManager.addEventListener('button', (event) => {
|
|
144
|
-
const { action } = event.detail;
|
|
145
|
-
|
|
146
|
-
if (action === 'apply-discount') {
|
|
147
|
-
applyDiscountCode(webManager);
|
|
135
|
+
if (name === 'billing-cycle') {
|
|
136
|
+
handleBillingCycleChange(value, webManager);
|
|
148
137
|
}
|
|
149
138
|
});
|
|
150
139
|
|
|
151
140
|
// Handle form submission
|
|
152
|
-
formManager.
|
|
153
|
-
event.preventDefault();
|
|
154
|
-
|
|
141
|
+
formManager.on('submit', async ({ $submitButton }) => {
|
|
155
142
|
// Get the submit button that was clicked
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
formManager.showError('Please choose a payment method.');
|
|
159
|
-
return;
|
|
143
|
+
if (!$submitButton) {
|
|
144
|
+
throw new Error('Please choose a payment method.');
|
|
160
145
|
}
|
|
161
146
|
|
|
162
147
|
// Check if a payment method was selected
|
|
163
|
-
const paymentMethod = submitButton.getAttribute('data-payment-method');
|
|
148
|
+
const paymentMethod = $submitButton.getAttribute('data-payment-method');
|
|
164
149
|
if (!paymentMethod) {
|
|
165
|
-
|
|
166
|
-
return;
|
|
150
|
+
throw new Error('Invalid payment method selected.');
|
|
167
151
|
}
|
|
168
152
|
|
|
169
153
|
// Set payment method in raw
|
|
@@ -181,6 +165,14 @@ function setupEventListeners() {
|
|
|
181
165
|
await completePurchase();
|
|
182
166
|
});
|
|
183
167
|
|
|
168
|
+
// Setup apply discount button (not part of form submit)
|
|
169
|
+
const $applyDiscountBtn = document.querySelector('[data-action="apply-discount"]');
|
|
170
|
+
if ($applyDiscountBtn) {
|
|
171
|
+
$applyDiscountBtn.addEventListener('click', () => {
|
|
172
|
+
applyDiscountCode(webManager);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
184
176
|
// Switch account link (keep as is - not part of form)
|
|
185
177
|
const $switchAccountLink = document.getElementById('switch-account');
|
|
186
178
|
if ($switchAccountLink) {
|
|
@@ -274,13 +266,8 @@ async function completePurchase() {
|
|
|
274
266
|
} catch (error) {
|
|
275
267
|
console.error('Purchase error:', error);
|
|
276
268
|
|
|
277
|
-
// FormManager
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// Show user-friendly error message
|
|
281
|
-
const errorMessage = error.message || 'There was an error processing your payment. Please try again.';
|
|
282
|
-
|
|
283
|
-
formManager.showError(errorMessage);
|
|
269
|
+
// Re-throw to let FormManager handle error display and state restoration
|
|
270
|
+
throw error;
|
|
284
271
|
}
|
|
285
272
|
}
|
|
286
273
|
|
|
@@ -385,7 +372,7 @@ async function initializeCheckout() {
|
|
|
385
372
|
setupEventListeners();
|
|
386
373
|
|
|
387
374
|
// Set form to ready state
|
|
388
|
-
formManager.
|
|
375
|
+
formManager.ready();
|
|
389
376
|
|
|
390
377
|
// Track begin_checkout event on page load
|
|
391
378
|
const basePrice = raw.product.is_subscription
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FormManager Test Page JavaScript
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Libraries
|
|
6
|
+
import { FormManager } from '__main_assets__/js/libs/form-manager.js';
|
|
7
|
+
|
|
8
|
+
let webManager = null;
|
|
9
|
+
|
|
10
|
+
// Module
|
|
11
|
+
export default (Manager) => {
|
|
12
|
+
return new Promise(async function (resolve) {
|
|
13
|
+
// Shortcuts
|
|
14
|
+
webManager = Manager.webManager;
|
|
15
|
+
|
|
16
|
+
// Initialize when DOM is ready
|
|
17
|
+
await webManager.dom().ready();
|
|
18
|
+
|
|
19
|
+
// Initialize test forms
|
|
20
|
+
initTestFormMain();
|
|
21
|
+
initTestFormValidation();
|
|
22
|
+
initTestFormContact();
|
|
23
|
+
initTestFormManual();
|
|
24
|
+
|
|
25
|
+
// Resolve after initialization
|
|
26
|
+
return resolve();
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Helper: simulate async API call
|
|
31
|
+
function simulateApi(ms = 1000) {
|
|
32
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Test 1: Full Test (success/fail, nested, change events)
|
|
36
|
+
function initTestFormMain() {
|
|
37
|
+
const formManager = new FormManager('#test-form-main');
|
|
38
|
+
const $status = document.getElementById('main-status');
|
|
39
|
+
const $action = document.getElementById('main-action');
|
|
40
|
+
const $output = document.getElementById('main-output');
|
|
41
|
+
|
|
42
|
+
formManager.on('statechange', ({ state }) => {
|
|
43
|
+
$status.textContent = `Status: ${state}`;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
formManager.on('change', ({ name, value, data }) => {
|
|
47
|
+
console.log('[Test 1] Change:', name, '=', value);
|
|
48
|
+
console.log('[Test 1] Full data:', data);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
formManager.on('submit', async ({ data, $submitButton }) => {
|
|
52
|
+
console.log('[Test 1] Submitting:', data);
|
|
53
|
+
console.log('[Test 1] Submit button:', $submitButton?.dataset?.action);
|
|
54
|
+
|
|
55
|
+
// Show action separately
|
|
56
|
+
const action = $submitButton?.dataset?.action || 'unknown';
|
|
57
|
+
$action.textContent = `Action: ${action}`;
|
|
58
|
+
|
|
59
|
+
// Show data
|
|
60
|
+
$output.textContent = JSON.stringify(data, null, 2);
|
|
61
|
+
|
|
62
|
+
await simulateApi(1000);
|
|
63
|
+
|
|
64
|
+
if (data.settings.outcome === 'error') {
|
|
65
|
+
throw new Error('Simulated server error - please try again');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
formManager.showSuccess(`Form ${action === 'draft' ? 'saved as draft' : 'submitted'} successfully!`);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Set Data button - test setData() API
|
|
72
|
+
const $setDataBtn = document.getElementById('main-set-data');
|
|
73
|
+
$setDataBtn.addEventListener('click', () => {
|
|
74
|
+
const testData = {
|
|
75
|
+
user: {
|
|
76
|
+
name: 'John Doe',
|
|
77
|
+
email: 'john@example.com',
|
|
78
|
+
address: {
|
|
79
|
+
city: 'Los Angeles',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
settings: {
|
|
83
|
+
outcome: 'error',
|
|
84
|
+
subscribe: true,
|
|
85
|
+
},
|
|
86
|
+
preferences: {
|
|
87
|
+
notifications: 'important',
|
|
88
|
+
features: {
|
|
89
|
+
darkmode: true,
|
|
90
|
+
analytics: true,
|
|
91
|
+
beta: false,
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
formManager.setData(testData);
|
|
97
|
+
$output.textContent = 'Data set via setData() API - submit to verify';
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Test 2: Validation
|
|
102
|
+
function initTestFormValidation() {
|
|
103
|
+
const formManager = new FormManager('#test-form-validation');
|
|
104
|
+
const $status = document.getElementById('validation-status');
|
|
105
|
+
const $setCorrectBtn = document.getElementById('validation-set-correct');
|
|
106
|
+
|
|
107
|
+
formManager.on('statechange', ({ state }) => {
|
|
108
|
+
$status.textContent = `Status: ${state}`;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Validation event - runs BEFORE submit, use setError to accumulate errors
|
|
112
|
+
formManager.on('validation', ({ data, setError }) => {
|
|
113
|
+
console.log('[Test 2] Validating:', data);
|
|
114
|
+
|
|
115
|
+
// Custom validation (HTML5 validation handles required, email format, etc.)
|
|
116
|
+
// Here we add business logic validation
|
|
117
|
+
|
|
118
|
+
if (data.age && parseInt(data.age) < 18) {
|
|
119
|
+
setError('age', 'You must be 18 or older');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Note: 'required' validation is handled automatically by HTML5 validation
|
|
123
|
+
// We just need to add the 'required' attribute to the HTML inputs
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
formManager.on('submit', async ({ data }) => {
|
|
127
|
+
console.log('[Test 2] Submitting (validation passed):', data);
|
|
128
|
+
|
|
129
|
+
// If we reach here, validation passed
|
|
130
|
+
await simulateApi(500);
|
|
131
|
+
formManager.showSuccess('Validation passed! Form submitted.');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Set Correct button - fills in valid values
|
|
135
|
+
$setCorrectBtn.addEventListener('click', () => {
|
|
136
|
+
formManager.setData({
|
|
137
|
+
name: 'John Doe',
|
|
138
|
+
email: 'john@example.com',
|
|
139
|
+
age: 25,
|
|
140
|
+
terms: true,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Test 3: Contact Form (one-time submit)
|
|
146
|
+
function initTestFormContact() {
|
|
147
|
+
const formManager = new FormManager('#test-form-contact', {
|
|
148
|
+
allowResubmit: false,
|
|
149
|
+
resetOnSuccess: true,
|
|
150
|
+
});
|
|
151
|
+
const $status = document.getElementById('contact-status');
|
|
152
|
+
|
|
153
|
+
formManager.on('statechange', ({ state }) => {
|
|
154
|
+
$status.textContent = `Status: ${state}`;
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
formManager.on('change', ({ name, value, data }) => {
|
|
158
|
+
console.log('[Test 3] Change:', name, '=', value);
|
|
159
|
+
console.log('[Test 3] Full data:', data);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
formManager.on('submit', async ({ data }) => {
|
|
163
|
+
console.log('[Test 3] Submitting:', data);
|
|
164
|
+
await simulateApi(1000);
|
|
165
|
+
formManager.showSuccess('Message sent! Form is now locked.');
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Test 4: Manual Ready
|
|
170
|
+
function initTestFormManual() {
|
|
171
|
+
const formManager = new FormManager('#test-form-manual', { autoReady: false });
|
|
172
|
+
const $status = document.getElementById('manual-status');
|
|
173
|
+
|
|
174
|
+
formManager.on('statechange', ({ state }) => {
|
|
175
|
+
$status.textContent = `Status: ${state}`;
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
formManager.on('change', ({ name, value, data }) => {
|
|
179
|
+
console.log('[Test 4] Change:', name, '=', value);
|
|
180
|
+
console.log('[Test 4] Full data:', data);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
formManager.on('submit', async ({ data }) => {
|
|
184
|
+
console.log('[Test 4] Submitting:', data);
|
|
185
|
+
await simulateApi(1000);
|
|
186
|
+
formManager.showSuccess('Done!');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Simulate async initialization (e.g., loading user data)
|
|
190
|
+
setTimeout(() => {
|
|
191
|
+
console.log('[Test 4] Now ready');
|
|
192
|
+
formManager.ready();
|
|
193
|
+
}, 2000);
|
|
194
|
+
}
|
|
@@ -63,7 +63,7 @@ social_signin:
|
|
|
63
63
|
<label for="email" class="form-label fw-semibold">
|
|
64
64
|
Email <span class="text-danger">*</span>
|
|
65
65
|
</label>
|
|
66
|
-
<input type="email" class="form-control form-control-md" id="email" name="email" placeholder="Enter your email" autocomplete="email" autofocus
|
|
66
|
+
<input type="email" class="form-control form-control-md" id="email" name="email" placeholder="Enter your email" autocomplete="email" autofocus>
|
|
67
67
|
</div>
|
|
68
68
|
|
|
69
69
|
<div class="mb-3 text-start">
|
|
@@ -71,7 +71,7 @@ social_signin:
|
|
|
71
71
|
Password <span class="text-danger">*</span>
|
|
72
72
|
</label>
|
|
73
73
|
<div class="input-group">
|
|
74
|
-
<input type="password" class="form-control form-control-md" id="password" name="password" placeholder="Enter your password" autocomplete="current-password"
|
|
74
|
+
<input type="password" class="form-control form-control-md" id="password" name="password" placeholder="Enter your password" autocomplete="current-password">
|
|
75
75
|
<button class="btn border uj-password-toggle px-3" type="button" aria-label="Toggle password visibility">
|
|
76
76
|
<span class="uj-password-show">{% uj_icon "eye", "fa-fw" %}</span>
|
|
77
77
|
<span class="uj-password-hide d-none">{% uj_icon "eye-slash", "fa-fw" %}</span>
|
|
@@ -73,7 +73,7 @@ social_signup:
|
|
|
73
73
|
<label for="email" class="form-label fw-semibold">
|
|
74
74
|
Email <span class="text-danger">*</span>
|
|
75
75
|
</label>
|
|
76
|
-
<input type="email" class="form-control form-control-md" id="email" name="email" placeholder="Enter your email" autocomplete="email" autofocus
|
|
76
|
+
<input type="email" class="form-control form-control-md" id="email" name="email" placeholder="Enter your email" autocomplete="email" autofocus>
|
|
77
77
|
</div>
|
|
78
78
|
|
|
79
79
|
<div class="mb-3 text-start">
|
|
@@ -81,7 +81,7 @@ social_signup:
|
|
|
81
81
|
Password <span class="text-danger">*</span>
|
|
82
82
|
</label>
|
|
83
83
|
<div class="input-group">
|
|
84
|
-
<input type="password" class="form-control form-control-md" id="password" name="password" placeholder="Create a strong password" autocomplete="new-password"
|
|
84
|
+
<input type="password" class="form-control form-control-md" id="password" name="password" placeholder="Create a strong password" autocomplete="new-password">
|
|
85
85
|
<button class="btn border uj-password-toggle px-3" type="button" aria-label="Toggle password visibility">
|
|
86
86
|
<span class="uj-password-show">{% uj_icon "eye", "fa-fw" %}</span>
|
|
87
87
|
<span class="uj-password-hide d-none">{% uj_icon "eye-slash", "fa-fw" %}</span>
|
|
@@ -178,37 +178,24 @@ faqs:
|
|
|
178
178
|
{% endiftruthy %}
|
|
179
179
|
</div>
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
<div class="alert alert-danger contact-error-alert mb-3 d-none" role="alert"></div>
|
|
183
|
-
|
|
184
|
-
<!-- Success Container -->
|
|
185
|
-
<div class="alert alert-success contact-success-alert mb-3 d-none" role="alert"></div>
|
|
186
|
-
|
|
187
|
-
<form id="contact-form" autocomplete="on" novalidate>
|
|
181
|
+
<form id="contact-form" autocomplete="on">
|
|
188
182
|
<div class="row g-3 mb-4">
|
|
189
183
|
<div class="col-md-6">
|
|
190
|
-
<label for="first_name" class="form-label fw-semibold">
|
|
191
|
-
First Name <span class="text-danger">*</span>
|
|
192
|
-
</label>
|
|
184
|
+
<label for="first_name" class="form-label fw-semibold">First Name <span class="text-danger">*</span></label>
|
|
193
185
|
<input type="text" class="form-control form-control-lg" id="first_name" name="first_name"
|
|
194
186
|
placeholder="Enter your first name"
|
|
195
187
|
autocomplete="given-name"
|
|
196
|
-
data-invalid-field="first_name"
|
|
197
|
-
data-invalid-description="Please enter your first name"
|
|
198
188
|
minlength="2"
|
|
199
189
|
maxlength="50"
|
|
190
|
+
autofocus
|
|
200
191
|
required>
|
|
201
192
|
<div class="invalid-feedback"></div>
|
|
202
193
|
</div>
|
|
203
194
|
<div class="col-md-6">
|
|
204
|
-
<label for="last_name" class="form-label fw-semibold">
|
|
205
|
-
Last Name <span class="text-danger">*</span>
|
|
206
|
-
</label>
|
|
195
|
+
<label for="last_name" class="form-label fw-semibold">Last Name <span class="text-danger">*</span></label>
|
|
207
196
|
<input type="text" class="form-control form-control-lg" id="last_name" name="last_name"
|
|
208
197
|
placeholder="Enter your last name"
|
|
209
198
|
autocomplete="family-name"
|
|
210
|
-
data-invalid-field="last_name"
|
|
211
|
-
data-invalid-description="Please enter your last name"
|
|
212
199
|
minlength="2"
|
|
213
200
|
maxlength="50"
|
|
214
201
|
required>
|
|
@@ -222,14 +209,10 @@ faqs:
|
|
|
222
209
|
</div>
|
|
223
210
|
|
|
224
211
|
<div class="mb-4">
|
|
225
|
-
<label for="email" class="form-label fw-semibold">
|
|
226
|
-
Email Address <span class="text-danger">*</span>
|
|
227
|
-
</label>
|
|
212
|
+
<label for="email" class="form-label fw-semibold">Email Address <span class="text-danger">*</span></label>
|
|
228
213
|
<input type="email" class="form-control form-control-lg" id="email" name="email"
|
|
229
214
|
placeholder="Enter your email address"
|
|
230
215
|
autocomplete="email"
|
|
231
|
-
data-invalid-field="email"
|
|
232
|
-
data-invalid-description="Please enter a valid email address"
|
|
233
216
|
required>
|
|
234
217
|
<div class="invalid-feedback"></div>
|
|
235
218
|
</div>
|
|
@@ -240,17 +223,11 @@ faqs:
|
|
|
240
223
|
placeholder="Enter your company name (optional)"
|
|
241
224
|
autocomplete="organization"
|
|
242
225
|
maxlength="100">
|
|
243
|
-
<div class="invalid-feedback"></div>
|
|
244
226
|
</div>
|
|
245
227
|
|
|
246
228
|
<div class="mb-4">
|
|
247
|
-
<label for="subject" class="form-label fw-semibold">
|
|
248
|
-
|
|
249
|
-
</label>
|
|
250
|
-
<select class="form-select form-select-lg" id="subject" name="subject"
|
|
251
|
-
data-invalid-field="subject"
|
|
252
|
-
data-invalid-description="Please select a subject"
|
|
253
|
-
required>
|
|
229
|
+
<label for="subject" class="form-label fw-semibold">Subject <span class="text-danger">*</span></label>
|
|
230
|
+
<select class="form-select form-select-lg" id="subject" name="subject" required>
|
|
254
231
|
<option value="">Choose a topic...</option>
|
|
255
232
|
<option value="general">General Inquiry</option>
|
|
256
233
|
<option value="support">Technical Support</option>
|
|
@@ -267,13 +244,9 @@ faqs:
|
|
|
267
244
|
</div>
|
|
268
245
|
|
|
269
246
|
<div class="mb-4">
|
|
270
|
-
<label for="message" class="form-label fw-semibold">
|
|
271
|
-
Message <span class="text-danger">*</span>
|
|
272
|
-
</label>
|
|
247
|
+
<label for="message" class="form-label fw-semibold">Message <span class="text-danger">*</span></label>
|
|
273
248
|
<textarea class="form-control form-control-lg" id="message" name="message" rows="3"
|
|
274
249
|
placeholder="Tell us how we can help you..."
|
|
275
|
-
data-invalid-field="message"
|
|
276
|
-
data-invalid-description="Please enter your message"
|
|
277
250
|
minlength="10"
|
|
278
251
|
maxlength="5000"
|
|
279
252
|
required></textarea>
|
|
@@ -281,9 +254,9 @@ faqs:
|
|
|
281
254
|
</div>
|
|
282
255
|
|
|
283
256
|
<div class="d-grid gap-2 d-md-flex justify-content-md-between align-items-center">
|
|
284
|
-
<button type="submit" class="btn btn-primary btn-lg px-5"
|
|
257
|
+
<button type="submit" class="btn btn-primary btn-lg px-5">
|
|
285
258
|
{% uj_icon "paper-plane", "me-2" %}
|
|
286
|
-
|
|
259
|
+
Send Message
|
|
287
260
|
</button>
|
|
288
261
|
<a href="{{ site.url }}" class="btn btn-link">
|
|
289
262
|
{% uj_icon "arrow-left", "me-1" %}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: themes/[ site.theme.id ]/frontend/core/base
|
|
3
|
+
title: FormManager Test
|
|
4
|
+
permalink: /test/libraries/form-manager
|
|
5
|
+
sitemap: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<div class="container py-5">
|
|
9
|
+
<h1 class="mb-4">FormManager Test Page</h1>
|
|
10
|
+
<p class="text-muted mb-5">Testing different configurations of the FormManager library.</p>
|
|
11
|
+
|
|
12
|
+
<div class="row g-4">
|
|
13
|
+
|
|
14
|
+
<!-- Test 1: Full Test (success/fail, nested, change events) -->
|
|
15
|
+
<div class="col-lg-8">
|
|
16
|
+
<div class="card">
|
|
17
|
+
<div class="card-header">
|
|
18
|
+
<h5 class="mb-0">Test 1: Full Test</h5>
|
|
19
|
+
<small class="text-muted">Success/failure toggle, nested dot notation, change events (check console)</small>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="card-body">
|
|
22
|
+
<form id="test-form-main">
|
|
23
|
+
<div class="row">
|
|
24
|
+
<div class="col-md-6">
|
|
25
|
+
<div class="mb-3">
|
|
26
|
+
<label for="main-name" class="form-label">user.name</label>
|
|
27
|
+
<input type="text" class="form-control" id="main-name" name="user.name" value="Ian">
|
|
28
|
+
</div>
|
|
29
|
+
<div class="mb-3">
|
|
30
|
+
<label for="main-email" class="form-label">user.email</label>
|
|
31
|
+
<input type="email" class="form-control" id="main-email" name="user.email" value="ian@example.com">
|
|
32
|
+
</div>
|
|
33
|
+
<div class="mb-3">
|
|
34
|
+
<label for="main-city" class="form-label">user.address.city</label>
|
|
35
|
+
<input type="text" class="form-control" id="main-city" name="user.address.city" value="NYC">
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="col-md-6">
|
|
39
|
+
<div class="mb-3">
|
|
40
|
+
<label for="main-outcome" class="form-label">Simulate Outcome</label>
|
|
41
|
+
<select class="form-select" id="main-outcome" name="settings.outcome">
|
|
42
|
+
<option value="success">Success</option>
|
|
43
|
+
<option value="error">Error (throw Error)</option>
|
|
44
|
+
</select>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="mb-3">
|
|
47
|
+
<label class="form-label d-block">preferences.notifications (radio group)</label>
|
|
48
|
+
<div class="form-check form-check-inline">
|
|
49
|
+
<input type="radio" class="form-check-input" id="notif-all" name="preferences.notifications" value="all" checked>
|
|
50
|
+
<label class="form-check-label" for="notif-all">All</label>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="form-check form-check-inline">
|
|
53
|
+
<input type="radio" class="form-check-input" id="notif-important" name="preferences.notifications" value="important">
|
|
54
|
+
<label class="form-check-label" for="notif-important">Important</label>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="form-check form-check-inline">
|
|
57
|
+
<input type="radio" class="form-check-input" id="notif-none" name="preferences.notifications" value="none">
|
|
58
|
+
<label class="form-check-label" for="notif-none">None</label>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="mb-3">
|
|
62
|
+
<label class="form-label d-block">preferences.features (checkbox group)</label>
|
|
63
|
+
<div class="form-check">
|
|
64
|
+
<input type="checkbox" class="form-check-input" id="feat-darkmode" name="preferences.features" value="darkmode">
|
|
65
|
+
<label class="form-check-label" for="feat-darkmode">Dark Mode</label>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="form-check">
|
|
68
|
+
<input type="checkbox" class="form-check-input" id="feat-analytics" name="preferences.features" value="analytics">
|
|
69
|
+
<label class="form-check-label" for="feat-analytics">Analytics</label>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="form-check">
|
|
72
|
+
<input type="checkbox" class="form-check-input" id="feat-beta" name="preferences.features" value="beta">
|
|
73
|
+
<label class="form-check-label" for="feat-beta">Beta Features</label>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="mb-3 form-check">
|
|
77
|
+
<input type="checkbox" class="form-check-input" id="main-subscribe" name="settings.subscribe">
|
|
78
|
+
<label class="form-check-label" for="main-subscribe">settings.subscribe (single checkbox)</label>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="d-flex gap-2">
|
|
83
|
+
<button type="submit" data-action="save" class="btn btn-primary">Save</button>
|
|
84
|
+
<button type="submit" data-action="draft" class="btn btn-outline-secondary">Save as Draft</button>
|
|
85
|
+
<button type="button" id="main-set-data" class="btn btn-outline-info">Set Data</button>
|
|
86
|
+
</div>
|
|
87
|
+
</form>
|
|
88
|
+
<div class="mt-3 d-flex gap-3">
|
|
89
|
+
<small class="text-muted" id="main-status">Status: ready</small>
|
|
90
|
+
<small class="text-muted" id="main-action">Action: -</small>
|
|
91
|
+
</div>
|
|
92
|
+
<div class="mt-3">
|
|
93
|
+
<pre id="main-output" class="bg-body-secondary p-2 rounded small" style="max-height: 200px; overflow: auto;">Submit to see collected data...</pre>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<!-- Test 2: Validation -->
|
|
100
|
+
<div class="col-lg-4">
|
|
101
|
+
<div class="card">
|
|
102
|
+
<div class="card-header d-flex justify-content-between align-items-start">
|
|
103
|
+
<div>
|
|
104
|
+
<h5 class="mb-0">Test 2: Validation</h5>
|
|
105
|
+
<small class="text-muted">HTML5 + custom validation event</small>
|
|
106
|
+
</div>
|
|
107
|
+
<button type="button" id="validation-set-correct" class="btn btn-sm btn-outline-success">Set Correct</button>
|
|
108
|
+
</div>
|
|
109
|
+
<div class="card-body">
|
|
110
|
+
<form id="test-form-validation">
|
|
111
|
+
<div class="mb-3">
|
|
112
|
+
<label for="validation-name" class="form-label">Name (required)</label>
|
|
113
|
+
<input type="text" class="form-control" id="validation-name" name="name" required>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="mb-3">
|
|
116
|
+
<label for="validation-email" class="form-label">Email (required, valid format)</label>
|
|
117
|
+
<input type="email" class="form-control" id="validation-email" name="email" required>
|
|
118
|
+
</div>
|
|
119
|
+
<div class="mb-3">
|
|
120
|
+
<label for="validation-age" class="form-label">Age (required, must be 18+)</label>
|
|
121
|
+
<input type="number" class="form-control" id="validation-age" name="age" required min="1">
|
|
122
|
+
</div>
|
|
123
|
+
<div class="mb-3 form-check">
|
|
124
|
+
<input type="checkbox" class="form-check-input" id="validation-terms" name="terms" required>
|
|
125
|
+
<label class="form-check-label" for="validation-terms">I agree to the terms (required)</label>
|
|
126
|
+
</div>
|
|
127
|
+
<button type="submit" class="btn btn-primary">Submit</button>
|
|
128
|
+
</form>
|
|
129
|
+
<div class="mt-2">
|
|
130
|
+
<small class="text-muted" id="validation-status">Status: ready</small>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<!-- Test 3: Contact Form (one-time submit, reset on success) -->
|
|
137
|
+
<div class="col-lg-4">
|
|
138
|
+
<div class="card">
|
|
139
|
+
<div class="card-header">
|
|
140
|
+
<h5 class="mb-0">Test 3: Contact Form</h5>
|
|
141
|
+
<small class="text-muted">allowResubmit: false, resetOnSuccess: true</small>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="card-body">
|
|
144
|
+
<form id="test-form-contact">
|
|
145
|
+
<div class="mb-3">
|
|
146
|
+
<label for="contact-message" class="form-label">Message</label>
|
|
147
|
+
<textarea class="form-control" id="contact-message" name="message" rows="2">Hello!</textarea>
|
|
148
|
+
</div>
|
|
149
|
+
<button type="submit" class="btn btn-primary">Send Message</button>
|
|
150
|
+
</form>
|
|
151
|
+
<div class="mt-2">
|
|
152
|
+
<small class="text-muted" id="contact-status">Status: ready</small>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<!-- Test 4: Manual Ready -->
|
|
159
|
+
<div class="col-lg-4">
|
|
160
|
+
<div class="card">
|
|
161
|
+
<div class="card-header">
|
|
162
|
+
<h5 class="mb-0">Test 4: Manual Ready</h5>
|
|
163
|
+
<small class="text-muted">autoReady: false, ready after 2 seconds</small>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="card-body">
|
|
166
|
+
<form id="test-form-manual">
|
|
167
|
+
<div class="mb-3">
|
|
168
|
+
<label for="manual-data" class="form-label">Data</label>
|
|
169
|
+
<input type="text" class="form-control" id="manual-data" name="data">
|
|
170
|
+
</div>
|
|
171
|
+
<button type="submit" class="btn btn-primary">Submit</button>
|
|
172
|
+
</form>
|
|
173
|
+
<div class="mt-2">
|
|
174
|
+
<small class="text-muted" id="manual-status">Status: initializing</small>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
package/dist/gulp/tasks/serve.js
CHANGED
|
@@ -63,6 +63,24 @@ module.exports = async function serve(complete) {
|
|
|
63
63
|
|
|
64
64
|
// Write the config file
|
|
65
65
|
jetpack.write('.temp/_config_browsersync.yml', `url: ${externalUrl}`);
|
|
66
|
+
// jetpack.write('.temp/_config_browsersync.yml', `
|
|
67
|
+
// url: ${externalUrl}
|
|
68
|
+
|
|
69
|
+
// web_manager:
|
|
70
|
+
// firebase:
|
|
71
|
+
// app:
|
|
72
|
+
// config:
|
|
73
|
+
// authDomain: "${new URL(externalUrl).host}"
|
|
74
|
+
// `);
|
|
75
|
+
// jetpack.write('.temp/_config_browsersync.yml', `
|
|
76
|
+
// url: ${externalUrl}
|
|
77
|
+
|
|
78
|
+
// web_manager:
|
|
79
|
+
// firebase:
|
|
80
|
+
// app:
|
|
81
|
+
// config:
|
|
82
|
+
// authDomain: "${new URL(localUrl).host}"
|
|
83
|
+
// `);
|
|
66
84
|
|
|
67
85
|
// Set global variable to access browserSync in other files
|
|
68
86
|
global.browserSync = browserSync;
|
package/dist/lib/logger.js
CHANGED