domma-cms 1.6.59 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4344 -0
- package/README.md +1 -1
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +2 -2
- package/admin/js/lib/draft-owner.js +1 -0
- package/admin/js/lib/effect-defs.js +1 -1
- package/admin/js/lib/effects-builder.js +2 -2
- package/admin/js/lib/page-editor-reference.js +5 -5
- package/admin/js/lib/shortcode-tags.js +1 -1
- package/admin/js/templates/docs/usage-shortcodes.html +39 -0
- package/admin/js/views/user-editor.js +1 -1
- package/docs/DommaFeatures.md +3005 -0
- package/docs/MultiTenant.md +176 -0
- package/docs/api-reference.md +1667 -0
- package/docs/cache.md +96 -0
- package/docs/configuration.md +1811 -0
- package/docs/editions-and-licences.md +190 -0
- package/docs/getting-started.md +201 -0
- package/docs/guides/form-triggers.md +260 -0
- package/docs/guides/mongodb-storage-adapter.md +282 -0
- package/docs/guides/multi-page-forms.md +121 -0
- package/docs/images/scribe-composer.png +0 -0
- package/docs/markdown-shortcodes.md +1738 -0
- package/docs/pentest-report-2026-04-03.md +181 -0
- package/docs/plans/2026-02-28-admin-topbar-login-forms.md +349 -0
- package/docs/plans/2026-02-28-domma-ui-polish.md +286 -0
- package/docs/plans/2026-02-28-reset-seed-fresh-commands.md +520 -0
- package/docs/plans/2026-03-02-cookie-consent-design.md +86 -0
- package/docs/plans/2026-03-02-cookie-consent-plugin.md +453 -0
- package/docs/plans/2026-03-02-tooltip-sweep-and-back-to-top-plugin-design.md +126 -0
- package/docs/plans/2026-03-02-tooltip-sweep-back-to-top.md +427 -0
- package/docs/plans/2026-03-05-cookie-consent-btt-core.md +115 -0
- package/docs/plans/2026-03-05-custom-css-migrate-to-core-design.md +35 -0
- package/docs/plans/2026-03-05-custom-css-migrate-to-core.md +352 -0
- package/docs/plans/2026-03-05-scribe-script-shortcode.md +373 -0
- package/docs/plans/2026-03-05-user-types-design.md +139 -0
- package/docs/plans/2026-03-05-user-types-implementation.md +1035 -0
- package/docs/plans/2026-03-09-page-editor-view-cta-inserts-design.md +78 -0
- package/docs/plans/2026-03-09-page-editor-view-cta-inserts.md +388 -0
- package/docs/plans/2026-03-09-pro-documentation-design.md +80 -0
- package/docs/plans/2026-03-09-pro-documentation.md +1017 -0
- package/docs/plans/2026-06-10-core-project-design.md +240 -0
- package/docs/plugin-development.md +827 -0
- package/docs/recruitment-recipe.md +501 -0
- package/docs/scaffolding.md +312 -0
- package/docs/screenshots/calculator-floating.png +0 -0
- package/docs/screenshots/calculator-standard.png +0 -0
- package/docs/screenshots/email-settings.png +0 -0
- package/docs/screenshots/messages-count.png +0 -0
- package/docs/structure/user-types.md +107 -0
- package/docs/superpowers/plans/2026-05-25-admin-sidebar-via-menus.md +1112 -0
- package/docs/superpowers/plans/2026-06-08-navbar-mobile-drawer-and-menu-enrichment.md +1161 -0
- package/docs/superpowers/plans/2026-06-25-domma-docs-project.md +695 -0
- package/docs/superpowers/plans/2026-06-26-surveys-HANDOFF.md +68 -0
- package/docs/superpowers/plans/2026-06-26-surveys-pro-plugin.md +1902 -0
- package/docs/superpowers/plans/2026-08-19-collection-context-sort-export.md +1577 -0
- package/docs/superpowers/plans/2026-10-09-content-api.md +1192 -0
- package/docs/superpowers/specs/2026-03-12-form-followup-actions-design.md +152 -0
- package/docs/superpowers/specs/2026-03-12-page-editor-form-insert-and-per-page-theme-design.md +115 -0
- package/docs/superpowers/specs/2026-03-17-nav-hidden-items-design.md +85 -0
- package/docs/superpowers/specs/2026-03-19-accordion-insert-design.md +175 -0
- package/docs/superpowers/specs/2026-03-25-static-block-shortcode-design.md +153 -0
- package/docs/superpowers/specs/2026-03-25-text-shortcode-design.md +168 -0
- package/docs/superpowers/specs/2026-04-05-card-builder-design.md +315 -0
- package/docs/superpowers/specs/2026-04-06-insert-builders-design.md +278 -0
- package/docs/superpowers/specs/2026-04-06-layouts-design.md +226 -0
- package/docs/superpowers/specs/2026-04-07-blog-plugin-design.md +300 -0
- package/docs/superpowers/specs/2026-04-07-calendar-plugin-design.md +538 -0
- package/docs/superpowers/specs/2026-04-17-components-area-design.md +368 -0
- package/docs/superpowers/specs/2026-05-02-effects-slideover-overhaul-design.md +193 -0
- package/docs/superpowers/specs/2026-05-06-dashboard-rebuild-design.md +257 -0
- package/docs/superpowers/specs/2026-05-24-menus-design.md +466 -0
- package/docs/superpowers/specs/2026-05-25-admin-sidebar-via-menus-design.md +358 -0
- package/docs/superpowers/specs/2026-05-25-projects-design.md +380 -0
- package/docs/superpowers/specs/2026-06-08-navbar-mobile-drawer-and-menu-enrichment-design.md +292 -0
- package/docs/superpowers/specs/2026-06-08-sidebar-tools-plugins-folders-design.md +59 -0
- package/docs/superpowers/specs/2026-06-25-domma-docs-project-design.md +192 -0
- package/docs/superpowers/specs/2026-06-26-domma-charts-upstream-proposal.md +44 -0
- package/docs/superpowers/specs/2026-06-26-manager-scheduler-upstream-proposal.md +46 -0
- package/docs/superpowers/specs/2026-06-26-surveys-pro-plugin-design.md +206 -0
- package/docs/superpowers/specs/2026-07-02-shortcode-context-menu-design.md +96 -0
- package/docs/superpowers/specs/2026-08-19-collection-context-sort-export-design.md +330 -0
- package/docs/superpowers/specs/2026-09-22-dcms-marketplace-design.md +1150 -0
- package/docs/superpowers/specs/2026-10-09-content-api-design.md +325 -0
- package/docs/superpowers/specs/plans/2026-03-12-form-followup-actions.md +624 -0
- package/docs/superpowers/specs/plans/2026-03-12-page-editor-form-insert-and-per-page-theme.md +125 -0
- package/docs/superpowers/specs/plans/2026-03-17-nav-hidden-items.md +578 -0
- package/docs/superpowers/specs/plans/2026-03-19-accordion-insert.md +635 -0
- package/docs/superpowers/specs/plans/2026-03-25-text-shortcode.md +545 -0
- package/docs/superpowers/specs/plans/2026-04-05-card-builder.md +1970 -0
- package/docs/superpowers/specs/plans/2026-04-06-insert-builders.md +1049 -0
- package/docs/superpowers/specs/plans/2026-04-06-layouts.md +1015 -0
- package/docs/superpowers/specs/plans/2026-04-07-calendar-plugin.md +1526 -0
- package/docs/superpowers/specs/plans/2026-04-08-plugin-monetisation-split.md +242 -0
- package/docs/superpowers/specs/plans/2026-04-17-components-area.md +2038 -0
- package/docs/superpowers/specs/plans/2026-05-02-effects-slideover-overhaul.md +2335 -0
- package/docs/superpowers/specs/plans/2026-05-06-dashboard-rebuild.md +1999 -0
- package/docs/superpowers/specs/plans/2026-05-17-cache-system.md +1436 -0
- package/docs/superpowers/specs/plans/2026-05-24-menus.md +3096 -0
- package/docs/superpowers/specs/plans/2026-05-25-projects.md +2869 -0
- package/docs/superpowers/specs/plans/2026-09-22-marketplace-step2-consolidation.md +505 -0
- package/docs/superpowers/specs/plans/2026-09-22-marketplace-step3-catalogue-and-key.md +154 -0
- package/docs/superpowers/specs/plans/2026-09-22-tools-promotion.md +260 -0
- package/docs/theming.md +320 -0
- package/package.json +2 -2
- package/plugins/_lib/admin/mail/keyboard.js +49 -0
- package/plugins/_lib/admin/mail/reader-view.js +4 -2
- package/public/js/celebrations/core/canvas.js +1 -1
- package/public/js/celebrations/index.js +1 -1
- package/public/js/celebrations/licenses/ABeeZee-Regular-OFL.txt +93 -0
- package/public/js/celebrations/licenses/Allura-Regular-OFL.txt +93 -0
- package/public/js/celebrations/message-attrs.mjs +1 -0
- package/public/js/celebrations/themes/anniversary.js +1 -0
- package/public/js/celebrations/themes/autumn.js +1 -0
- package/public/js/celebrations/themes/birthday.js +1 -0
- package/public/js/celebrations/themes/butterfly-flight.js +1 -0
- package/public/js/celebrations/themes/calendar.js +1 -0
- package/public/js/celebrations/themes/chinese-new-year-dates.js +1 -0
- package/public/js/celebrations/themes/chinese-new-year.js +1 -0
- package/public/js/celebrations/themes/christmas.js +1 -1
- package/public/js/celebrations/themes/easter.js +1 -0
- package/public/js/celebrations/themes/garden-drawing.js +1 -0
- package/public/js/celebrations/themes/garden.js +1 -0
- package/public/js/celebrations/themes/graduation.js +1 -0
- package/public/js/celebrations/themes/greeting.js +1 -0
- package/public/js/celebrations/themes/make-it-rain.js +1 -0
- package/public/js/celebrations/themes/money-rain.js +1 -0
- package/public/js/celebrations/themes/new-year.js +1 -0
- package/public/js/celebrations/themes/occasion-drawing.js +1 -0
- package/public/js/celebrations/themes/occasions.js +1 -0
- package/public/js/celebrations/themes/rain-control.js +1 -0
- package/public/js/celebrations/themes/sparkler-font-data.js +1 -0
- package/public/js/celebrations/themes/sparkler-font.js +1 -0
- package/public/js/celebrations/themes/sparkler-writing.js +1 -0
- package/public/js/celebrations/themes/summer-garden.js +1 -0
- package/public/js/celebrations/themes/winter.js +1 -0
- package/public/js/celebrations/trait-data.mjs +1 -1
- package/public/js/effects.js +1 -1
- package/scripts/build.js +4 -0
- package/server/services/markdown.js +5 -2
- package/server/templates/page.html +1 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Page Editor - View & CTA Insert Pickers Design
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-03-09
|
|
4
|
+
**Status:** Approved
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Add **View** and **CTA** items to the Insert dropdown in the page editor toolbar. Each opens a guided picker dropdown that fetches live data from the API and generates the correct shortcode.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Toolbar Changes
|
|
15
|
+
|
|
16
|
+
Two new items appended to the existing Insert dropdown (`plus-circle`) in `markdown-toolbar.js`:
|
|
17
|
+
|
|
18
|
+
| Label | Icon | Action key |
|
|
19
|
+
|-------|------|------------|
|
|
20
|
+
| View | `eye` | `view` |
|
|
21
|
+
| CTA | `mouse-pointer` | `cta` |
|
|
22
|
+
|
|
23
|
+
Both follow the established picker pattern (`openIconPicker`, `openSpacerPicker`): DOM-built dropdown, positioned below the trigger button, closed on outside click.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## View Picker
|
|
28
|
+
|
|
29
|
+
Fetches `GET /api/views` and presents:
|
|
30
|
+
|
|
31
|
+
1. **View** - `<select>` populated with view slugs + titles from the API
|
|
32
|
+
2. **Display** - `<select>`: Table / Cards / List
|
|
33
|
+
3. **Insert** button → generates:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
[view slug="selected-slug" display="table" /]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If the API returns no views, shows: *"No Views configured yet - create one under Data → Views."*
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## CTA Picker
|
|
44
|
+
|
|
45
|
+
Fetches `GET /api/actions` and presents:
|
|
46
|
+
|
|
47
|
+
1. **Action** - `<select>` populated with action slugs + titles
|
|
48
|
+
2. **Label** - text input (pre-filled with the selected action's trigger label)
|
|
49
|
+
3. **Entry ID** - free-text input (UUID), left blank by default with placeholder `"Paste entry UUID…"`
|
|
50
|
+
4. **Style** - `<select>`: Primary / Secondary / Ghost / Danger
|
|
51
|
+
5. **Icon** - text input (icon name, optional)
|
|
52
|
+
6. **Confirm** - text input (optional confirmation message)
|
|
53
|
+
7. **Insert** button → generates:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
[cta action="selected-action" entry="uuid-or-blank" style="primary" icon="check" confirm="Are you sure?"]Label[/cta]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If no icon or confirm, those attributes are omitted. If entry ID is blank, `entry=""` is inserted so the author knows to fill it in.
|
|
60
|
+
|
|
61
|
+
If the API returns no actions, shows: *"No Actions configured yet - create one under Data → Actions."*
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Wiring
|
|
66
|
+
|
|
67
|
+
`markdown-toolbar.js` exports two new handler hooks: `onView(cb)` and `onCta(cb)`.
|
|
68
|
+
|
|
69
|
+
`page-editor.js` sets these handlers with the API fetch calls (same pattern as the existing `onCollection` handler).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Files
|
|
74
|
+
|
|
75
|
+
| File | Change |
|
|
76
|
+
|------|--------|
|
|
77
|
+
| `admin/js/lib/markdown-toolbar.js` | Add `openViewPicker`, `openCtaPicker`, two Insert items, two handler hooks |
|
|
78
|
+
| `admin/js/views/page-editor.js` | Wire `toolbar.onView()` and `toolbar.onCta()` |
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
# Page Editor View & CTA Insert Pickers Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
4
|
+
|
|
5
|
+
**Goal:** Add View and CTA shortcode insert pickers to the page editor toolbar's Insert dropdown.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Two new items in the existing Insert dropdown call handler callbacks registered by page-editor.js. Each handler opens an `E.modal` with a DOM-built form, fetches the relevant API list, and inserts the generated shortcode via `insertAtCursor`. Exactly mirrors the existing `onCollection` pattern.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Domma admin SPA, `E.modal` (light DOM projection), `insertAtCursor`, `api.views.list()`, `api.actions.list()`.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Key reference points before starting
|
|
14
|
+
|
|
15
|
+
- **Insert dropdown items array** - `admin/js/lib/markdown-toolbar.js` line ~632-641 (inside `buttons` array, the `plus-circle` dropdown `items`)
|
|
16
|
+
- **`handlers` object** - line ~656: `const handlers = {link, image, card, grid, help, effects, collection}`
|
|
17
|
+
- **`executeAction`** - line ~523, the `else if (action === 'collection')` block ends at ~592
|
|
18
|
+
- **Return object** - line ~785, exports `onLink`, `onImage`, `onCard`, `onGrid`, `onHelp`, `onEffects`, `onCollection`
|
|
19
|
+
- **`onCollection` handler in page-editor.js** - line ~740-911, the exact modal pattern to follow
|
|
20
|
+
- **`labelStyle` / `inputStyle`** constants are defined inside `toolbar.onCollection` - redeclare them in each new handler (they are local constants, not exported)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Task 1: Extend markdown-toolbar.js - add View and CTA hooks
|
|
25
|
+
|
|
26
|
+
**Files:**
|
|
27
|
+
- Modify: `admin/js/lib/markdown-toolbar.js`
|
|
28
|
+
|
|
29
|
+
**Step 1: Add `view` and `cta` to the `handlers` object**
|
|
30
|
+
|
|
31
|
+
Find (line ~656):
|
|
32
|
+
```js
|
|
33
|
+
const handlers = {link: null, image: null, card: null, grid: null, help: null, effects: null, collection: null};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Replace with:
|
|
37
|
+
```js
|
|
38
|
+
const handlers = {link: null, image: null, card: null, grid: null, help: null, effects: null, collection: null, view: null, cta: null};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Step 2: Add two items to the Insert dropdown**
|
|
42
|
+
|
|
43
|
+
Find the Insert dropdown items array (the `plus-circle` button object, line ~632):
|
|
44
|
+
```js
|
|
45
|
+
{label: 'Collection', icon: 'database', action: 'collection'},
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Replace with:
|
|
51
|
+
```js
|
|
52
|
+
{label: 'Collection', icon: 'database', action: 'collection'},
|
|
53
|
+
{label: 'View', icon: 'eye', action: 'view'},
|
|
54
|
+
{label: 'CTA Button', icon: 'mouse-pointer', action: 'cta'},
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Step 3: Add `view` and `cta` branches to `executeAction`**
|
|
60
|
+
|
|
61
|
+
Find (immediately after the `collection` block, line ~591-593):
|
|
62
|
+
```js
|
|
63
|
+
} else if (action === 'help') {
|
|
64
|
+
if (handlers.help) handlers.help(ta);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Replace with:
|
|
69
|
+
```js
|
|
70
|
+
} else if (action === 'view') {
|
|
71
|
+
if (handlers.view) handlers.view(ta);
|
|
72
|
+
} else if (action === 'cta') {
|
|
73
|
+
if (handlers.cta) handlers.cta(ta);
|
|
74
|
+
} else if (action === 'help') {
|
|
75
|
+
if (handlers.help) handlers.help(ta);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Step 4: Export `onView` and `onCta` in the return object**
|
|
80
|
+
|
|
81
|
+
Find (line ~805-808):
|
|
82
|
+
```js
|
|
83
|
+
onCollection(cb) {
|
|
84
|
+
handlers.collection = cb;
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Replace with:
|
|
89
|
+
```js
|
|
90
|
+
onCollection(cb) {
|
|
91
|
+
handlers.collection = cb;
|
|
92
|
+
},
|
|
93
|
+
onView(cb) {
|
|
94
|
+
handlers.view = cb;
|
|
95
|
+
},
|
|
96
|
+
onCta(cb) {
|
|
97
|
+
handlers.cta = cb;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Step 5: Verify no syntax errors**
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
cd /home/darryl/src/js/domma-cms && node --check admin/js/lib/markdown-toolbar.js
|
|
105
|
+
```
|
|
106
|
+
Expected: exits 0, no output.
|
|
107
|
+
|
|
108
|
+
**Step 6: Commit**
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
git add admin/js/lib/markdown-toolbar.js
|
|
112
|
+
git commit -m "feat: add view and cta action hooks to editor toolbar"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Task 2: Wire onView handler in page-editor.js
|
|
118
|
+
|
|
119
|
+
**Files:**
|
|
120
|
+
- Modify: `admin/js/views/page-editor.js`
|
|
121
|
+
|
|
122
|
+
**Step 1: Add the `toolbar.onView` handler after the `onCollection` block**
|
|
123
|
+
|
|
124
|
+
Find (line ~911-913):
|
|
125
|
+
```js
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Help callback: open editor reference slideover
|
|
129
|
+
toolbar.onHelp(() => {
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Insert between them:
|
|
133
|
+
```js
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// View picker callback
|
|
137
|
+
toolbar.onView(async (ta) => {
|
|
138
|
+
const views = await api.views.list().catch(() => []);
|
|
139
|
+
|
|
140
|
+
const wrapper = document.createElement('div');
|
|
141
|
+
wrapper.style.cssText = 'padding:1rem;display:flex;flex-direction:column;gap:.75rem;';
|
|
142
|
+
|
|
143
|
+
const labelStyle = 'display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;';
|
|
144
|
+
const inputStyle = 'width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;';
|
|
145
|
+
|
|
146
|
+
// View select
|
|
147
|
+
const viewRow = document.createElement('div');
|
|
148
|
+
const viewLabel = document.createElement('label');
|
|
149
|
+
viewLabel.style.cssText = labelStyle;
|
|
150
|
+
viewLabel.textContent = 'View';
|
|
151
|
+
const viewSelect = document.createElement('select');
|
|
152
|
+
viewSelect.style.cssText = inputStyle;
|
|
153
|
+
if (!views.length) {
|
|
154
|
+
const opt = document.createElement('option');
|
|
155
|
+
opt.value = '';
|
|
156
|
+
opt.textContent = 'No Views configured yet - create one under Data → Views';
|
|
157
|
+
viewSelect.appendChild(opt);
|
|
158
|
+
} else {
|
|
159
|
+
views.forEach(v => {
|
|
160
|
+
const opt = document.createElement('option');
|
|
161
|
+
opt.value = v.slug;
|
|
162
|
+
opt.textContent = v.title || v.slug;
|
|
163
|
+
viewSelect.appendChild(opt);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
viewRow.appendChild(viewLabel);
|
|
167
|
+
viewRow.appendChild(viewSelect);
|
|
168
|
+
wrapper.appendChild(viewRow);
|
|
169
|
+
|
|
170
|
+
// Display mode select
|
|
171
|
+
const dispRow = document.createElement('div');
|
|
172
|
+
const dispLabel = document.createElement('label');
|
|
173
|
+
dispLabel.style.cssText = labelStyle;
|
|
174
|
+
dispLabel.textContent = 'Display';
|
|
175
|
+
const dispSelect = document.createElement('select');
|
|
176
|
+
dispSelect.style.cssText = inputStyle;
|
|
177
|
+
['table', 'cards', 'list'].forEach(d => {
|
|
178
|
+
const opt = document.createElement('option');
|
|
179
|
+
opt.value = d;
|
|
180
|
+
opt.textContent = d.charAt(0).toUpperCase() + d.slice(1);
|
|
181
|
+
dispSelect.appendChild(opt);
|
|
182
|
+
});
|
|
183
|
+
dispRow.appendChild(dispLabel);
|
|
184
|
+
dispRow.appendChild(dispSelect);
|
|
185
|
+
wrapper.appendChild(dispRow);
|
|
186
|
+
|
|
187
|
+
// Insert button
|
|
188
|
+
const insertBtn = document.createElement('button');
|
|
189
|
+
insertBtn.type = 'button';
|
|
190
|
+
insertBtn.className = 'btn btn-primary';
|
|
191
|
+
insertBtn.textContent = 'Insert';
|
|
192
|
+
wrapper.appendChild(insertBtn);
|
|
193
|
+
|
|
194
|
+
const modal = E.modal({title: 'Insert View', size: 'sm'});
|
|
195
|
+
modal.element.appendChild(wrapper);
|
|
196
|
+
modal.open();
|
|
197
|
+
|
|
198
|
+
insertBtn.addEventListener('click', () => {
|
|
199
|
+
const slug = viewSelect.value;
|
|
200
|
+
if (!slug) return;
|
|
201
|
+
const snippet = `[view slug="${slug}" display="${dispSelect.value}" /]`;
|
|
202
|
+
modal.close();
|
|
203
|
+
insertAtCursor(ta, snippet);
|
|
204
|
+
ta.dispatchEvent(new Event('input', {bubbles: true}));
|
|
205
|
+
ta.focus();
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Help callback: open editor reference slideover
|
|
210
|
+
toolbar.onHelp(() => {
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Step 2: Verify no syntax errors**
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
node --check admin/js/views/page-editor.js
|
|
217
|
+
```
|
|
218
|
+
Expected: exits 0.
|
|
219
|
+
|
|
220
|
+
**Step 3: Commit**
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
git add admin/js/views/page-editor.js
|
|
224
|
+
git commit -m "feat: add View shortcode insert picker to page editor toolbar"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Task 3: Wire onCta handler in page-editor.js
|
|
230
|
+
|
|
231
|
+
**Files:**
|
|
232
|
+
- Modify: `admin/js/views/page-editor.js`
|
|
233
|
+
|
|
234
|
+
**Step 1: Add the `toolbar.onCta` handler after the `onView` block**
|
|
235
|
+
|
|
236
|
+
Find (immediately after the view handler's closing `});` and before the help comment):
|
|
237
|
+
```js
|
|
238
|
+
// Help callback: open editor reference slideover
|
|
239
|
+
toolbar.onHelp(() => {
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Insert between them:
|
|
243
|
+
```js
|
|
244
|
+
// CTA picker callback
|
|
245
|
+
toolbar.onCta(async (ta) => {
|
|
246
|
+
const actions = await api.actions.list().catch(() => []);
|
|
247
|
+
|
|
248
|
+
const wrapper = document.createElement('div');
|
|
249
|
+
wrapper.style.cssText = 'padding:1rem;display:flex;flex-direction:column;gap:.75rem;';
|
|
250
|
+
|
|
251
|
+
const labelStyle = 'display:block;font-size:.85em;font-weight:600;margin-bottom:.25rem;color:var(--dm-text-muted,#aaa);text-transform:uppercase;letter-spacing:.05em;';
|
|
252
|
+
const inputStyle = 'width:100%;padding:.4rem .6rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:4px;color:var(--dm-text,#eee);font-size:.9em;';
|
|
253
|
+
|
|
254
|
+
function makeRow(labelText, control) {
|
|
255
|
+
const row = document.createElement('div');
|
|
256
|
+
const lbl = document.createElement('label');
|
|
257
|
+
lbl.style.cssText = labelStyle;
|
|
258
|
+
lbl.textContent = labelText;
|
|
259
|
+
row.appendChild(lbl);
|
|
260
|
+
row.appendChild(control);
|
|
261
|
+
return row;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function makeSelect(options) {
|
|
265
|
+
const sel = document.createElement('select');
|
|
266
|
+
sel.style.cssText = inputStyle;
|
|
267
|
+
options.forEach(([val, text]) => {
|
|
268
|
+
const opt = document.createElement('option');
|
|
269
|
+
opt.value = val;
|
|
270
|
+
opt.textContent = text;
|
|
271
|
+
sel.appendChild(opt);
|
|
272
|
+
});
|
|
273
|
+
return sel;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function makeInput(type, placeholder, value) {
|
|
277
|
+
const inp = document.createElement('input');
|
|
278
|
+
inp.type = type;
|
|
279
|
+
inp.placeholder = placeholder || '';
|
|
280
|
+
inp.value = value || '';
|
|
281
|
+
inp.style.cssText = inputStyle;
|
|
282
|
+
return inp;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Action select
|
|
286
|
+
const actionSelect = makeSelect(
|
|
287
|
+
actions.length
|
|
288
|
+
? actions.map(a => [a.slug, a.title || a.slug])
|
|
289
|
+
: [['', 'No Actions configured yet - create one under Data → Actions']]
|
|
290
|
+
);
|
|
291
|
+
wrapper.appendChild(makeRow('Action', actionSelect));
|
|
292
|
+
|
|
293
|
+
// Label input - pre-fill from selected action's trigger label when available
|
|
294
|
+
const labelInput = makeInput('text', 'Button label', 'Run');
|
|
295
|
+
wrapper.appendChild(makeRow('Label', labelInput));
|
|
296
|
+
|
|
297
|
+
// Auto-fill label when action selection changes
|
|
298
|
+
actionSelect.addEventListener('change', () => {
|
|
299
|
+
const selected = actions.find(a => a.slug === actionSelect.value);
|
|
300
|
+
if (selected?.trigger?.label) labelInput.value = selected.trigger.label;
|
|
301
|
+
});
|
|
302
|
+
// Trigger once on load
|
|
303
|
+
if (actions.length) {
|
|
304
|
+
const first = actions[0];
|
|
305
|
+
if (first?.trigger?.label) labelInput.value = first.trigger.label;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Entry ID input
|
|
309
|
+
const entryInput = makeInput('text', 'Paste entry UUID…', '');
|
|
310
|
+
wrapper.appendChild(makeRow('Entry ID', entryInput));
|
|
311
|
+
|
|
312
|
+
// Style select
|
|
313
|
+
const styleSelect = makeSelect([
|
|
314
|
+
['primary', 'Primary'],
|
|
315
|
+
['secondary', 'Secondary'],
|
|
316
|
+
['ghost', 'Ghost'],
|
|
317
|
+
['danger', 'Danger'],
|
|
318
|
+
]);
|
|
319
|
+
wrapper.appendChild(makeRow('Style', styleSelect));
|
|
320
|
+
|
|
321
|
+
// Icon input
|
|
322
|
+
const iconInput = makeInput('text', 'e.g. check, zap, send (optional)', '');
|
|
323
|
+
wrapper.appendChild(makeRow('Icon', iconInput));
|
|
324
|
+
|
|
325
|
+
// Confirm input
|
|
326
|
+
const confirmInput = makeInput('text', 'Confirmation message (optional)', '');
|
|
327
|
+
wrapper.appendChild(makeRow('Confirm prompt', confirmInput));
|
|
328
|
+
|
|
329
|
+
// Insert button
|
|
330
|
+
const insertBtn = document.createElement('button');
|
|
331
|
+
insertBtn.type = 'button';
|
|
332
|
+
insertBtn.className = 'btn btn-primary';
|
|
333
|
+
insertBtn.textContent = 'Insert';
|
|
334
|
+
wrapper.appendChild(insertBtn);
|
|
335
|
+
|
|
336
|
+
const modal = E.modal({title: 'Insert CTA Button', size: 'sm'});
|
|
337
|
+
modal.element.appendChild(wrapper);
|
|
338
|
+
modal.open();
|
|
339
|
+
|
|
340
|
+
insertBtn.addEventListener('click', () => {
|
|
341
|
+
const action = actionSelect.value;
|
|
342
|
+
if (!action) return;
|
|
343
|
+
const entry = entryInput.value.trim();
|
|
344
|
+
const label = labelInput.value.trim() || 'Run';
|
|
345
|
+
const style = styleSelect.value;
|
|
346
|
+
const icon = iconInput.value.trim();
|
|
347
|
+
const confirm = confirmInput.value.trim();
|
|
348
|
+
|
|
349
|
+
let attrs = `action="${action}" entry="${entry}" style="${style}"`;
|
|
350
|
+
if (icon) attrs += ` icon="${icon}"`;
|
|
351
|
+
if (confirm) attrs += ` confirm="${confirm}"`;
|
|
352
|
+
|
|
353
|
+
const snippet = `[cta ${attrs}]${label}[/cta]`;
|
|
354
|
+
modal.close();
|
|
355
|
+
insertAtCursor(ta, snippet);
|
|
356
|
+
ta.dispatchEvent(new Event('input', {bubbles: true}));
|
|
357
|
+
ta.focus();
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Help callback: open editor reference slideover
|
|
362
|
+
toolbar.onHelp(() => {
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Step 2: Verify no syntax errors**
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
node --check admin/js/views/page-editor.js
|
|
369
|
+
```
|
|
370
|
+
Expected: exits 0.
|
|
371
|
+
|
|
372
|
+
**Step 3: Commit**
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
git add admin/js/views/page-editor.js
|
|
376
|
+
git commit -m "feat: add CTA shortcode insert picker to page editor toolbar"
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Verification checklist
|
|
382
|
+
|
|
383
|
+
1. Open the page editor (`#/pages` → edit any page)
|
|
384
|
+
2. Click the **Insert** toolbar button (plus-circle icon) - dropdown shows: Card, Grid, Badge, Timeline, Spacer, Icon, Collection, **View**, **CTA Button**
|
|
385
|
+
3. Click **View** → modal opens → if Views exist, select shows their titles; pick one, pick display mode, click Insert → `[view slug="..." display="..." /]` inserted at cursor
|
|
386
|
+
4. Click **CTA Button** → modal opens → if Actions exist, select shows them; label auto-fills from action trigger; enter an entry UUID; pick style/icon/confirm; click Insert → `[cta action="..." entry="..." style="..." ...]Label[/cta]` inserted
|
|
387
|
+
5. Both modals close cleanly after Insert; textarea retains focus
|
|
388
|
+
6. With no Views/Actions configured: select shows the "No X configured" message; Insert button produces `[view slug="" ...]` - acceptable, no crash
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Pro Documentation - Design
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-03-09
|
|
4
|
+
**Status:** Approved
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Add a Pro documentation section in two places:
|
|
11
|
+
|
|
12
|
+
1. **Public Resources** - New `/resources/pro/` sub-section with individual pages for Views, Actions, and the CTA shortcode
|
|
13
|
+
2. **Admin sidebar** - New "Pro Documentation" page at `#/pro/docs` with three tabs (Views, Actions, CTA Shortcode)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Public Resources Pro Section
|
|
18
|
+
|
|
19
|
+
### Structure
|
|
20
|
+
|
|
21
|
+
| File | URL | Description |
|
|
22
|
+
|------|-----|-------------|
|
|
23
|
+
| `content/pages/resources/pro/index.md` | `/resources/pro` | Landing page with hero + 3 cards |
|
|
24
|
+
| `content/pages/resources/pro/views.md` | `/resources/pro/views` | Views reference - aggregation pipelines |
|
|
25
|
+
| `content/pages/resources/pro/actions.md` | `/resources/pro/actions` | Actions reference - step types, templates |
|
|
26
|
+
| `content/pages/resources/pro/cta.md` | `/resources/pro/cta` | CTA shortcode - syntax, attributes, collection integration |
|
|
27
|
+
|
|
28
|
+
### Page Pattern
|
|
29
|
+
|
|
30
|
+
Each page follows the existing resources convention:
|
|
31
|
+
- `[hero variant="dark" size="sm" fullwidth="true" twinkle twinkle-count="20" blobs]` at the top
|
|
32
|
+
- A `[badge]Pro[/badge]` + "Requires MongoDB" notice near the top (Views and Actions pages)
|
|
33
|
+
- Content with attribute tables and fenced code block examples
|
|
34
|
+
- `← Back to Pro Features` link at the bottom
|
|
35
|
+
|
|
36
|
+
### Resources Index Update
|
|
37
|
+
|
|
38
|
+
Add a "Pro Features" card to `content/pages/resources/index.md` (the existing 3-column grid), linking to `/resources/pro`.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Admin Pro Docs Panel
|
|
43
|
+
|
|
44
|
+
### Route
|
|
45
|
+
|
|
46
|
+
`#/pro/docs`
|
|
47
|
+
|
|
48
|
+
### Files
|
|
49
|
+
|
|
50
|
+
| File | Purpose |
|
|
51
|
+
|------|---------|
|
|
52
|
+
| `admin/js/views/pro-docs.js` | View module - `{ templateUrl, onMount }` |
|
|
53
|
+
| `admin/js/templates/pro-docs.html` | HTML template with three-tab layout |
|
|
54
|
+
|
|
55
|
+
### Sidebar Entry
|
|
56
|
+
|
|
57
|
+
- Added to the admin sidebar config (in `admin/js/app.js` or wherever `getSidebarConfig` is defined)
|
|
58
|
+
- Section label: **"Pro"**
|
|
59
|
+
- Item label: **"Documentation"**
|
|
60
|
+
- Icon: `zap`
|
|
61
|
+
- Route: `#/pro/docs`
|
|
62
|
+
- Permission gate: visible if user has `views` OR `actions` permission
|
|
63
|
+
|
|
64
|
+
### Tab Content
|
|
65
|
+
|
|
66
|
+
| Tab | Content |
|
|
67
|
+
|-----|---------|
|
|
68
|
+
| **Views** | What Views are; the execute pipeline; allowed `$match`/`$sort`/`$lookup` etc. stages; forbidden stages; template variable reference; worked example pipeline |
|
|
69
|
+
| **Actions** | What Actions are; Phase 1 step types (`updateField`, `deleteEntry`, `moveToCollection`, `webhook`, `email`); template interpolation (`{{entry.data.x}}`, `{{now}}`, `{{user.name}}`); partial execution behaviour |
|
|
70
|
+
| **CTA Shortcode** | Syntax (wrapping + self-closing forms); attribute table; standalone page example; collection integration example (`cta="slug"` on `[collection /]`) |
|
|
71
|
+
|
|
72
|
+
Content is written for **admin users configuring features**, not public readers. Focus on how to set up and use each feature in the admin UI.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Out of Scope
|
|
77
|
+
|
|
78
|
+
- Live demo executions inside the admin docs panel
|
|
79
|
+
- Public site navigation changes (no new navbar items)
|
|
80
|
+
- Plugin or API documentation changes
|