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
package/CLAUDE.md
CHANGED
|
@@ -597,19 +597,119 @@ const response = await authorizedFetch(url, options);
|
|
|
597
597
|
|
|
598
598
|
#### FormManager Library
|
|
599
599
|
|
|
600
|
-
|
|
600
|
+
Lightweight form state management library with built-in validation, state machine, and event system.
|
|
601
601
|
|
|
602
602
|
**Import:**
|
|
603
603
|
```javascript
|
|
604
604
|
import { FormManager } from '__main_assets__/js/libs/form-manager.js';
|
|
605
605
|
```
|
|
606
606
|
|
|
607
|
-
**Usage:**
|
|
607
|
+
**Basic Usage:**
|
|
608
608
|
```javascript
|
|
609
609
|
const formManager = new FormManager('#my-form', options);
|
|
610
|
+
|
|
611
|
+
formManager.on('submit', async ({ data, $submitButton }) => {
|
|
612
|
+
const response = await fetch('/api', { body: JSON.stringify(data) });
|
|
613
|
+
if (!response.ok) throw new Error('Failed');
|
|
614
|
+
formManager.showSuccess('Form submitted!');
|
|
615
|
+
});
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
**State Machine:**
|
|
619
|
+
```
|
|
620
|
+
initializing → ready ⇄ submitting → ready (or submitted)
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
**Configuration Options:**
|
|
624
|
+
```javascript
|
|
625
|
+
{
|
|
626
|
+
autoReady: true, // Auto-transition to initialState when DOM ready
|
|
627
|
+
initialState: 'ready', // State after autoReady fires
|
|
628
|
+
allowResubmit: true, // Allow resubmission after success (false = 'submitted' state)
|
|
629
|
+
resetOnSuccess: false, // Clear form fields after successful submission
|
|
630
|
+
warnOnUnsavedChanges: false, // Warn user before leaving with unsaved changes
|
|
631
|
+
submittingText: 'Processing...', // Text shown on submit button during submission
|
|
632
|
+
submittedText: 'Processed!' // Text shown on submit button after success (when allowResubmit: false)
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
**Events:**
|
|
637
|
+
|
|
638
|
+
| Event | Payload | Description |
|
|
639
|
+
|-------|---------|-------------|
|
|
640
|
+
| `submit` | `{ data, $submitButton }` | Form submission (throw error to show failure) |
|
|
641
|
+
| `validation` | `{ data, setError }` | Custom validation before submit |
|
|
642
|
+
| `change` | `{ field, name, value, data }` | Field value changed |
|
|
643
|
+
| `statechange` | `{ state, previousState }` | State transition |
|
|
644
|
+
|
|
645
|
+
**Validation System:**
|
|
646
|
+
|
|
647
|
+
FormManager runs validation automatically before `submit`:
|
|
648
|
+
1. **HTML5 validation** - Checks `required`, `minlength`, `maxlength`, `min`, `max`, `pattern`, `type="email"`, `type="url"`
|
|
649
|
+
2. **Custom validation** - Use `validation` event for business logic
|
|
650
|
+
|
|
651
|
+
```javascript
|
|
652
|
+
fm.on('validation', ({ data, setError }) => {
|
|
653
|
+
if (data.age && parseInt(data.age) < 18) {
|
|
654
|
+
setError('age', 'You must be 18 or older');
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
Errors display with Bootstrap's `is-invalid` class and `.invalid-feedback` elements.
|
|
660
|
+
|
|
661
|
+
**Autofocus:**
|
|
662
|
+
|
|
663
|
+
When the form transitions to `ready` state, FormManager automatically focuses the field with the `autofocus` attribute (if present and not disabled).
|
|
664
|
+
|
|
665
|
+
**Methods:**
|
|
666
|
+
|
|
667
|
+
| Method | Description |
|
|
668
|
+
|--------|-------------|
|
|
669
|
+
| `on(event, callback)` | Register event listener (chainable) |
|
|
670
|
+
| `ready()` | Transition to ready state |
|
|
671
|
+
| `getData()` | Get form data as nested object (supports dot notation) |
|
|
672
|
+
| `setData(obj)` | Set form values from nested object |
|
|
673
|
+
| `showSuccess(msg)` | Show success notification |
|
|
674
|
+
| `showError(msg)` | Show error notification |
|
|
675
|
+
| `reset()` | Reset form and go to ready state |
|
|
676
|
+
| `isDirty()` | Check if form has unsaved changes |
|
|
677
|
+
| `setDirty(bool)` | Set dirty state |
|
|
678
|
+
| `clearFieldErrors()` | Clear all field validation errors |
|
|
679
|
+
| `throwFieldErrors({ field: msg })` | Set and display field errors, throw error |
|
|
680
|
+
|
|
681
|
+
**Nested Field Names (Dot Notation):**
|
|
682
|
+
|
|
683
|
+
Use dot notation in field names for nested data:
|
|
684
|
+
```html
|
|
685
|
+
<input name="user.address.city" value="NYC">
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
Results in:
|
|
689
|
+
```javascript
|
|
690
|
+
{ user: { address: { city: 'NYC' } } }
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
**Checkbox Handling:**
|
|
694
|
+
- **Single checkbox:** Returns `true`/`false`
|
|
695
|
+
- **Checkbox group (same name):** Returns object `{ value1: true, value2: false }`
|
|
696
|
+
|
|
697
|
+
**Multiple Submit Buttons:**
|
|
698
|
+
|
|
699
|
+
Access the clicked button via `$submitButton`:
|
|
700
|
+
```html
|
|
701
|
+
<button type="submit" data-action="save">Save</button>
|
|
702
|
+
<button type="submit" data-action="draft">Save Draft</button>
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
```javascript
|
|
706
|
+
fm.on('submit', async ({ data, $submitButton }) => {
|
|
707
|
+
const action = $submitButton?.dataset?.action; // 'save' or 'draft'
|
|
708
|
+
});
|
|
610
709
|
```
|
|
611
710
|
|
|
612
711
|
**Reference:** `src/assets/js/libs/form-manager.js`
|
|
712
|
+
**Test Page:** `src/assets/js/pages/test/libraries/form-manager/index.js`
|
|
613
713
|
**Example:** `src/assets/js/pages/contact/index.js`
|
|
614
714
|
|
|
615
715
|
## Analytics & Tracking
|
package/README.md
CHANGED
|
@@ -381,14 +381,183 @@ const response = await authorizedFetch(serverApiURL, {
|
|
|
381
381
|
|
|
382
382
|
#### FormManager Library
|
|
383
383
|
|
|
384
|
-
|
|
384
|
+
Lightweight form state management library with built-in validation, state machine, and event system.
|
|
385
385
|
|
|
386
386
|
**Import:**
|
|
387
387
|
```javascript
|
|
388
388
|
import { FormManager } from '__main_assets__/js/libs/form-manager.js';
|
|
389
389
|
```
|
|
390
390
|
|
|
391
|
-
**
|
|
391
|
+
**Basic Usage:**
|
|
392
|
+
```javascript
|
|
393
|
+
const formManager = new FormManager('#my-form', {
|
|
394
|
+
allowResubmit: true, // Allow form to be submitted again after success
|
|
395
|
+
resetOnSuccess: false, // Don't clear fields after success
|
|
396
|
+
warnOnUnsavedChanges: false // Don't warn on page leave
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Handle form submission
|
|
400
|
+
formManager.on('submit', async ({ data, $submitButton }) => {
|
|
401
|
+
const response = await fetch('/api/submit', {
|
|
402
|
+
method: 'POST',
|
|
403
|
+
body: JSON.stringify(data)
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
if (!response.ok) {
|
|
407
|
+
throw new Error('Submission failed');
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
formManager.showSuccess('Form submitted successfully!');
|
|
411
|
+
});
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**State Machine:**
|
|
415
|
+
```
|
|
416
|
+
initializing → ready ⇄ submitting → ready (or submitted)
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Events:**
|
|
420
|
+
|
|
421
|
+
| Event | Payload | Description |
|
|
422
|
+
|-------|---------|-------------|
|
|
423
|
+
| `submit` | `{ data, $submitButton }` | Form submission. Throw an error to show failure message. |
|
|
424
|
+
| `validation` | `{ data, setError }` | Custom validation before submit. Use `setError(fieldName, message)` to add errors. |
|
|
425
|
+
| `change` | `{ field, name, value, data }` | Called when any field value changes. |
|
|
426
|
+
| `statechange` | `{ state, previousState }` | Called when form state changes. |
|
|
427
|
+
|
|
428
|
+
**Validation:**
|
|
429
|
+
|
|
430
|
+
FormManager runs validation automatically before the `submit` event:
|
|
431
|
+
|
|
432
|
+
1. **HTML5 Validation** - Automatically checks `required`, `minlength`, `maxlength`, `min`, `max`, `pattern`, `type="email"`, `type="url"`
|
|
433
|
+
2. **Custom Validation** - Use the `validation` event for business logic
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
formManager.on('validation', ({ data, setError }) => {
|
|
437
|
+
// Custom validation runs AFTER HTML5 validation
|
|
438
|
+
if (data.age && parseInt(data.age) < 18) {
|
|
439
|
+
setError('age', 'You must be 18 or older');
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (data.password !== data.confirmPassword) {
|
|
443
|
+
setError('confirmPassword', 'Passwords do not match');
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Validation errors are displayed using Bootstrap's `is-invalid` class and `.invalid-feedback` elements. The first field with an error is automatically focused.
|
|
449
|
+
|
|
450
|
+
**Autofocus:**
|
|
451
|
+
|
|
452
|
+
When the form transitions to `ready` state, FormManager automatically focuses any field with the `autofocus` attribute:
|
|
453
|
+
|
|
454
|
+
```html
|
|
455
|
+
<input type="text" name="email" autofocus>
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
**Methods:**
|
|
459
|
+
|
|
460
|
+
| Method | Description |
|
|
461
|
+
|--------|-------------|
|
|
462
|
+
| `on(event, callback)` | Register event listener (chainable) |
|
|
463
|
+
| `ready()` | Manually transition to ready state (for `autoReady: false`) |
|
|
464
|
+
| `getData()` | Get form data as nested object |
|
|
465
|
+
| `setData(obj)` | Populate form from a nested object |
|
|
466
|
+
| `showSuccess(msg)` | Show success notification |
|
|
467
|
+
| `showError(msg)` | Show error notification |
|
|
468
|
+
| `reset()` | Reset form and state |
|
|
469
|
+
| `isDirty()` | Check if form has unsaved changes |
|
|
470
|
+
| `clearFieldErrors()` | Clear all validation error displays |
|
|
471
|
+
| `throwFieldErrors({ field: msg })` | Set errors and throw (for use in submit handler) |
|
|
472
|
+
|
|
473
|
+
**Nested Field Names (Dot Notation):**
|
|
474
|
+
|
|
475
|
+
Use dot notation in field `name` attributes for nested data structures:
|
|
476
|
+
|
|
477
|
+
```html
|
|
478
|
+
<input name="user.name" value="John">
|
|
479
|
+
<input name="user.address.city" value="NYC">
|
|
480
|
+
<input name="user.address.zip" value="10001">
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Produces:
|
|
484
|
+
```javascript
|
|
485
|
+
{
|
|
486
|
+
user: {
|
|
487
|
+
name: 'John',
|
|
488
|
+
address: {
|
|
489
|
+
city: 'NYC',
|
|
490
|
+
zip: '10001'
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
**Checkbox Handling:**
|
|
497
|
+
|
|
498
|
+
- **Single checkbox:** Returns `true` or `false`
|
|
499
|
+
- **Checkbox group (multiple with same name):** Returns object with each value as key
|
|
500
|
+
|
|
501
|
+
```html
|
|
502
|
+
<!-- Single checkbox -->
|
|
503
|
+
<input type="checkbox" name="subscribe" checked>
|
|
504
|
+
<!-- Result: { subscribe: true } -->
|
|
505
|
+
|
|
506
|
+
<!-- Checkbox group -->
|
|
507
|
+
<input type="checkbox" name="features" value="darkmode" checked>
|
|
508
|
+
<input type="checkbox" name="features" value="analytics">
|
|
509
|
+
<input type="checkbox" name="features" value="beta" checked>
|
|
510
|
+
<!-- Result: { features: { darkmode: true, analytics: false, beta: true } } -->
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**Multiple Submit Buttons:**
|
|
514
|
+
|
|
515
|
+
Access the clicked submit button to handle different actions:
|
|
516
|
+
|
|
517
|
+
```html
|
|
518
|
+
<button type="submit" data-action="save">Save</button>
|
|
519
|
+
<button type="submit" data-action="draft">Save as Draft</button>
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
```javascript
|
|
523
|
+
formManager.on('submit', async ({ data, $submitButton }) => {
|
|
524
|
+
const action = $submitButton?.dataset?.action;
|
|
525
|
+
|
|
526
|
+
if (action === 'draft') {
|
|
527
|
+
await saveDraft(data);
|
|
528
|
+
formManager.showSuccess('Draft saved!');
|
|
529
|
+
} else {
|
|
530
|
+
await saveAndPublish(data);
|
|
531
|
+
formManager.showSuccess('Published!');
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**Manual Ready Mode:**
|
|
537
|
+
|
|
538
|
+
For forms that need async initialization (e.g., loading data from API):
|
|
539
|
+
|
|
540
|
+
```javascript
|
|
541
|
+
const formManager = new FormManager('#my-form', { autoReady: false });
|
|
542
|
+
|
|
543
|
+
// Load data, then mark ready
|
|
544
|
+
const userData = await fetchUserData();
|
|
545
|
+
formManager.setData(userData);
|
|
546
|
+
formManager.ready(); // Now form is interactive
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
**Configuration Options:**
|
|
550
|
+
|
|
551
|
+
| Option | Default | Description |
|
|
552
|
+
|--------|---------|-------------|
|
|
553
|
+
| `autoReady` | `true` | Auto-transition to ready when DOM is ready |
|
|
554
|
+
| `initialState` | `'ready'` | State after autoReady fires |
|
|
555
|
+
| `allowResubmit` | `true` | Allow form resubmission after success |
|
|
556
|
+
| `resetOnSuccess` | `false` | Clear fields after successful submission |
|
|
557
|
+
| `warnOnUnsavedChanges` | `false` | Show browser warning when leaving with unsaved changes |
|
|
558
|
+
| `submittingText` | `'Processing...'` | Text shown on submit button during submission |
|
|
559
|
+
|
|
560
|
+
**Test Page:** Navigate to `/test/libraries/form-manager` to see FormManager in action with various configurations.
|
|
392
561
|
|
|
393
562
|
### Icons
|
|
394
563
|
* Fontawesome
|
package/TODO.md
CHANGED
|
@@ -6,6 +6,10 @@ NEW TODO
|
|
|
6
6
|
- FIx formmanager .getData() it keeps returning an empty object, make it work flawlessyly
|
|
7
7
|
- It keeps testing whether there is a "." every time it reads or writes. just call the getNested and setNested functions and then check for the DOT inside those functions
|
|
8
8
|
- form manager should NOT submit if the button that was clicked is disabled (class or attribute)
|
|
9
|
+
- script that adds some helpful classes to the body or attributes to html maybe like
|
|
10
|
+
* data-device="mobile|tablet|desktop"
|
|
11
|
+
* data-browser="chrome|safari|firefox|edge|opera|other"
|
|
12
|
+
* data-os="windows|macos|linux|android|ios|other"
|
|
9
13
|
|
|
10
14
|
Make an admin dashboard backend
|
|
11
15
|
|
|
@@ -94,8 +98,12 @@ REMAKE main/misc/embed-manager.html in UJ
|
|
|
94
98
|
REMAKE the dashboard one in UJ
|
|
95
99
|
FINISH redirec.js in UJ
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
# Fix notifications
|
|
102
|
+
* UJ 2.0 for a while was making a DUPLICATE notifaction in users/{uid}/notifications/{token} AND in notifications/{token}
|
|
103
|
+
* We can SAFELY DELETE the users/{uid}/notifications collection
|
|
104
|
+
* EX: https://console.firebase.google.com/project/replyify-app/firestore/databases/-default-/data/~2Fnotifications~2Fsubscriptions~2Fall
|
|
105
|
+
* Also, there are residual notifications/subscriptions/all/{token} that need to be MIGRATED to the new format
|
|
106
|
+
* EX: https://console.firebase.google.com/project/replyify-app/firestore/databases/-default-/data/~2Fnotifications~2Fsubscriptions~2Fall~2FczUMa9wW0n3FnjpKCL5Wet:APA91bFD9YpwBqtn0i6qVabxiNl1uqIl3Ka1ObNM9CWT5NjzjnlTnyCA7e0G3Y3GGzIEcJUPoDLnGBRP3xBob99EiWItKtOuWP3Sqb906zBYJGFENIyQOJIUw43tizN5lCSq6ICgVJsZ
|
|
99
107
|
|
|
100
108
|
|
|
101
109
|
FIX THE settings like
|