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,624 @@
|
|
|
1
|
+
# Form Follow-Up: Success States & Action Triggers - Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or
|
|
4
|
+
> superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
5
|
+
|
|
6
|
+
**Goal:** Wire CMS Actions to auto-execute on form submission, add configurable success redirect, and document the full
|
|
7
|
+
flow with a tutorial and example page.
|
|
8
|
+
|
|
9
|
+
**Architecture:** Two new optional fields (`settings.actionSlug`, `settings.successRedirect`) in each form's JSON. The
|
|
10
|
+
server-side submission pipeline executes the named Action after storing the entry (non-fatal, try/catch). The client
|
|
11
|
+
reads the `redirect` field from the response and either redirects or shows the inline success message.
|
|
12
|
+
|
|
13
|
+
**Tech Stack:** Fastify (ESM), Node.js file-based forms, Domma public site JS (`H.post`, `F.render`), static HTML
|
|
14
|
+
templates for admin docs/tutorials.
|
|
15
|
+
|
|
16
|
+
**Spec:** `docs/superpowers/specs/2026-03-12-form-followup-actions-design.md`
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Chunk 1: Server - action trigger + redirect response
|
|
21
|
+
|
|
22
|
+
### Task 1: Add executeAction import and trigger to form submission
|
|
23
|
+
|
|
24
|
+
**Files:**
|
|
25
|
+
|
|
26
|
+
- Modify: `server/routes/api/forms.js`
|
|
27
|
+
|
|
28
|
+
The submission handler lives at `POST /forms/submit/:slug` (line 312). The webhook block ends around line 428 with a
|
|
29
|
+
`fastify.log.warn`. Add the action execution block immediately after it, then update the return value to include
|
|
30
|
+
`redirect`.
|
|
31
|
+
|
|
32
|
+
- [ ] **Step 1: Add import for executeAction**
|
|
33
|
+
|
|
34
|
+
At the top of `server/routes/api/forms.js`, add `executeAction` to the imports from collections. It actually lives in
|
|
35
|
+
`server/services/actions.js`. Add a new import line after the existing imports:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import {executeAction} from '../../services/actions.js';
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- [ ] **Step 2: Add action execution block after the webhook block**
|
|
42
|
+
|
|
43
|
+
Locate this line in the submission handler (around line 428):
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
// Webhook action
|
|
47
|
+
const webhookAction = form.actions?.webhook;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
After the entire webhook try/catch block (which ends around line 429), insert:
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
// CMS Action trigger
|
|
54
|
+
const actionSlug = form.settings?.actionSlug;
|
|
55
|
+
if (actionSlug && entry) {
|
|
56
|
+
try {
|
|
57
|
+
await executeAction(actionSlug, entry.id, { user: null });
|
|
58
|
+
} catch (err) {
|
|
59
|
+
fastify.log.warn(`[forms] Action "${actionSlug}" failed for form "${slug}": ${err.message}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Note: `entry` is the result of `createEntry(...)` - currently it's not stored in a variable. You need to capture it.
|
|
65
|
+
Change this existing line:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
// BEFORE:
|
|
69
|
+
await createEntry(targetSlug, data, { source: `form:${slug}` });
|
|
70
|
+
|
|
71
|
+
// AFTER:
|
|
72
|
+
entry = await createEntry(targetSlug, data, { source: `form:${slug}` });
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
And declare `let entry = null;` before the collection try/catch block.
|
|
76
|
+
|
|
77
|
+
- [ ] **Step 3: Update the return value to include redirect**
|
|
78
|
+
|
|
79
|
+
Locate the final return at the bottom of the submit handler:
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
return { ok: true, message: settings.successMessage || 'Thank you for your submission.' };
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Replace with:
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
return {
|
|
89
|
+
ok: true,
|
|
90
|
+
message: settings.successMessage || 'Thank you for your submission.',
|
|
91
|
+
redirect: settings.successRedirect || null
|
|
92
|
+
};
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Also update the honeypot early-return to match:
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
// BEFORE:
|
|
99
|
+
return { ok: true, message: settings.successMessage };
|
|
100
|
+
|
|
101
|
+
// AFTER:
|
|
102
|
+
return { ok: true, message: settings.successMessage, redirect: settings.successRedirect || null };
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- [ ] **Step 4: Verify syntax**
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
node --check server/routes/api/forms.js
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Expected: no output (no errors).
|
|
112
|
+
|
|
113
|
+
- [ ] **Step 5: Commit**
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
git add server/routes/api/forms.js
|
|
117
|
+
git commit -m "feat: execute CMS action and return redirect on form submission"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Chunk 2: Admin form editor - new settings fields
|
|
123
|
+
|
|
124
|
+
### Task 2: Add HTML fields to form-editor template
|
|
125
|
+
|
|
126
|
+
**Files:**
|
|
127
|
+
|
|
128
|
+
- Modify: `admin/js/templates/form-editor.html`
|
|
129
|
+
|
|
130
|
+
The Settings tab panel starts around line 102. The `setting-success-message` textarea is at line 113-115. Add two new
|
|
131
|
+
fields directly after it.
|
|
132
|
+
|
|
133
|
+
- [ ] **Step 1: Add Success Redirect URL field after success message**
|
|
134
|
+
|
|
135
|
+
Locate:
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<textarea id="setting-success-message" class="form-input" rows="3"
|
|
139
|
+
placeholder="Thank you for your submission."></textarea>
|
|
140
|
+
</div>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Insert immediately after the closing `</div>`:
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<div class="mb-3">
|
|
147
|
+
<label class="form-label">Success Redirect URL</label>
|
|
148
|
+
<input id="setting-success-redirect" type="text" class="form-input"
|
|
149
|
+
placeholder="/thank-you">
|
|
150
|
+
<p class="form-hint text-muted" style="margin-top:.3rem;font-size:.8rem;">
|
|
151
|
+
If set, redirects the visitor to this URL on success. Takes priority over the success message.
|
|
152
|
+
</p>
|
|
153
|
+
</div>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- [ ] **Step 2: Add CMS Action card to the Actions tab**
|
|
157
|
+
|
|
158
|
+
The Actions tab (Tab 4) begins around line 141. It has an Email card, Webhook card, and Spam Protection card. Add a
|
|
159
|
+
new "CMS Action" card as the third column card. Locate the closing `</div>` of the `<div class="row">` wrapper (around
|
|
160
|
+
line 190) and add a new card inside the row before it closes:
|
|
161
|
+
|
|
162
|
+
```html
|
|
163
|
+
<div class="col-6">
|
|
164
|
+
<div class="card mb-4">
|
|
165
|
+
<div class="card-header"><h2>CMS Action</h2></div>
|
|
166
|
+
<div class="card-body">
|
|
167
|
+
<div class="mb-3">
|
|
168
|
+
<label class="form-label">Action on Submit</label>
|
|
169
|
+
<select id="action-cms-slug" class="form-input">
|
|
170
|
+
<option value="">- None -</option>
|
|
171
|
+
</select>
|
|
172
|
+
<p class="form-hint text-muted" style="margin-top:.3rem;font-size:.8rem;">
|
|
173
|
+
Run a CMS Action after the entry is stored. Requires Pro (MongoDB).
|
|
174
|
+
Failures are non-fatal - the submission is always saved first.
|
|
175
|
+
</p>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- [ ] **Step 3: Verify the template renders (visual check only - no syntax errors)**
|
|
183
|
+
|
|
184
|
+
Check that the HTML is valid (no unclosed tags) by reading the modified section.
|
|
185
|
+
|
|
186
|
+
- [ ] **Step 4: Commit**
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
git add admin/js/templates/form-editor.html
|
|
190
|
+
git commit -m "feat: add success redirect and CMS action fields to form editor template"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### Task 3: Wire new fields in form-editor JS
|
|
196
|
+
|
|
197
|
+
**Files:**
|
|
198
|
+
|
|
199
|
+
- Modify: `admin/js/views/form-editor.js`
|
|
200
|
+
|
|
201
|
+
Three changes: collect, populate, and load actions into the select.
|
|
202
|
+
|
|
203
|
+
- [ ] **Step 1: Add fields to collectFormData()**
|
|
204
|
+
|
|
205
|
+
Locate `collectFormData()` (around line 1172). Inside the `settings` object (line 1180), add the two new fields after
|
|
206
|
+
`rateLimitPerMinute`:
|
|
207
|
+
|
|
208
|
+
```js
|
|
209
|
+
// Add after:
|
|
210
|
+
rateLimitPerMinute: parseInt($container.find('#setting-rate-limit').val(), 10) || 3
|
|
211
|
+
|
|
212
|
+
// Insert:
|
|
213
|
+
,
|
|
214
|
+
successRedirect: $container.find('#setting-success-redirect').val().trim() || null,
|
|
215
|
+
actionSlug: $container.find('#action-cms-slug').val() || null
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
- [ ] **Step 2: Populate fields when loading an existing form**
|
|
219
|
+
|
|
220
|
+
Locate the populate section (around line 1320) where `const s = form.settings || {};` is. Add population after the
|
|
221
|
+
existing `rateLimitPerMinute` line:
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
// Add after:
|
|
225
|
+
$container.find('#setting-rate-limit').val(s.rateLimitPerMinute || 3);
|
|
226
|
+
|
|
227
|
+
// Insert:
|
|
228
|
+
$container.find('#setting-success-redirect').val(s.successRedirect || '');
|
|
229
|
+
// actionSlug select populated after actions are loaded (see loadActions below)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
- [ ] **Step 3: Add loadActions() call in onMount**
|
|
233
|
+
|
|
234
|
+
Find the `onMount` function (it calls `E.tabs(...)` and populates form data). After the tabs init and form population,
|
|
235
|
+
add a call to load available actions. Find where `$container.find('#action-email-enabled')` is populated (around line
|
|
236
|
+
1330) and add after the webhook section:
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
// Load CMS Actions into select
|
|
240
|
+
const savedActionSlug = form?.settings?.actionSlug || '';
|
|
241
|
+
try {
|
|
242
|
+
const actions = await apiRequest('/actions').catch(() => []);
|
|
243
|
+
const sel = $container.find('#action-cms-slug').get(0);
|
|
244
|
+
(Array.isArray(actions) ? actions : []).forEach(a => {
|
|
245
|
+
const opt = document.createElement('option');
|
|
246
|
+
opt.value = a.slug;
|
|
247
|
+
opt.textContent = a.title || a.slug;
|
|
248
|
+
if (a.slug === savedActionSlug) opt.selected = true;
|
|
249
|
+
sel.appendChild(opt);
|
|
250
|
+
});
|
|
251
|
+
if (!actions.length) {
|
|
252
|
+
const opt = document.createElement('option');
|
|
253
|
+
opt.value = '';
|
|
254
|
+
opt.textContent = 'No actions available';
|
|
255
|
+
opt.disabled = true;
|
|
256
|
+
sel.appendChild(opt);
|
|
257
|
+
}
|
|
258
|
+
} catch {
|
|
259
|
+
// Actions endpoint unavailable (Pro feature not configured) - leave select empty
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
- [ ] **Step 4: Verify syntax**
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
node --check admin/js/views/form-editor.js
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Expected: no output.
|
|
270
|
+
|
|
271
|
+
- [ ] **Step 5: Commit**
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
git add admin/js/views/form-editor.js
|
|
275
|
+
git commit -m "feat: collect, populate, and load CMS action + success redirect in form editor"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Chunk 3: Public site - handle redirect and inline success
|
|
281
|
+
|
|
282
|
+
### Task 4: Update hydrateFormEmbeds to handle redirect
|
|
283
|
+
|
|
284
|
+
**Files:**
|
|
285
|
+
|
|
286
|
+
- Modify: `public/js/site.js`
|
|
287
|
+
|
|
288
|
+
The `onSubmit` handler is at line 497-506. Currently it awaits `H.post` without capturing the return value, then
|
|
289
|
+
immediately clears the form and calls `showResult`. Update it to check for `redirect` in the response.
|
|
290
|
+
|
|
291
|
+
- [ ] **Step 1: Capture response and handle redirect**
|
|
292
|
+
|
|
293
|
+
Locate this block (around line 497):
|
|
294
|
+
|
|
295
|
+
```js
|
|
296
|
+
const onSubmit = async (formData) => {
|
|
297
|
+
try {
|
|
298
|
+
await H.post(`/api/forms/submit/${form.slug}`, formData);
|
|
299
|
+
while (el.firstChild) el.removeChild(el.firstChild);
|
|
300
|
+
showResult(el, s.successMessage || 'Thank you for your submission.', false);
|
|
301
|
+
} catch (err) {
|
|
302
|
+
showResult(el, err.message || 'Submission failed. Please try again.', true);
|
|
303
|
+
throw err; // re-throw so Domma knows the submit failed
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Replace with:
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
const onSubmit = async (formData) => {
|
|
312
|
+
try {
|
|
313
|
+
const result = await H.post(`/api/forms/submit/${form.slug}`, formData);
|
|
314
|
+
if (result?.redirect) {
|
|
315
|
+
window.location.href = result.redirect;
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
while (el.firstChild) el.removeChild(el.firstChild);
|
|
319
|
+
showResult(el, result?.message || s.successMessage || 'Thank you for your submission.', false);
|
|
320
|
+
} catch (err) {
|
|
321
|
+
showResult(el, err.message || 'Submission failed. Please try again.', true);
|
|
322
|
+
throw err; // re-throw so Domma knows the submit failed
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
- [ ] **Step 2: Verify syntax**
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
node --check public/js/site.js
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Expected: no output.
|
|
334
|
+
|
|
335
|
+
- [ ] **Step 3: Commit**
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
git add public/js/site.js
|
|
339
|
+
git commit -m "feat: handle redirect and success message response in form embed hydration"
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Chunk 4: Example content + tutorial + documentation
|
|
345
|
+
|
|
346
|
+
### Task 5: Create thank-you page and update enquiries form
|
|
347
|
+
|
|
348
|
+
**Files:**
|
|
349
|
+
|
|
350
|
+
- Create: `content/pages/thank-you.md`
|
|
351
|
+
- Modify: `content/forms/enquiries.json`
|
|
352
|
+
|
|
353
|
+
- [ ] **Step 1: Create thank-you page**
|
|
354
|
+
|
|
355
|
+
Create `content/pages/thank-you.md`:
|
|
356
|
+
|
|
357
|
+
```markdown
|
|
358
|
+
---
|
|
359
|
+
title: Thank You
|
|
360
|
+
slug: thank-you
|
|
361
|
+
description: Your message has been received
|
|
362
|
+
layout: default
|
|
363
|
+
status: published
|
|
364
|
+
sortOrder: 99
|
|
365
|
+
showInNav: false
|
|
366
|
+
sidebar: false
|
|
367
|
+
visibility: public
|
|
368
|
+
createdAt: '2026-03-12T00:00:00.000Z'
|
|
369
|
+
updatedAt: '2026-03-12T00:00:00.000Z'
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
[hero variant="dark" size="md" fullwidth="true"]
|
|
373
|
+
|
|
374
|
+
# Thank You
|
|
375
|
+
|
|
376
|
+
[scribe]Your message has been received. We'll be in touch shortly.[/scribe]
|
|
377
|
+
|
|
378
|
+
[/hero]
|
|
379
|
+
|
|
380
|
+
[spacer /]
|
|
381
|
+
|
|
382
|
+
[card]
|
|
383
|
+
|
|
384
|
+
Thanks for getting in touch. We aim to respond within one business day.
|
|
385
|
+
|
|
386
|
+
[Back to Home](/)
|
|
387
|
+
|
|
388
|
+
[/card]
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
- [ ] **Step 2: Update enquiries form to use successRedirect**
|
|
392
|
+
|
|
393
|
+
Read `content/forms/enquiries.json` first, then update the `settings` block to add:
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
"successRedirect": "/thank-you",
|
|
397
|
+
"actionSlug": null
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
The `actionSlug` is `null` since this is a free-tier example (no MongoDB required). The redirect is the primary success
|
|
401
|
+
UX for this form.
|
|
402
|
+
|
|
403
|
+
- [ ] **Step 3: Update contact.md to note the form behaviour**
|
|
404
|
+
|
|
405
|
+
The contact page (`content/pages/contact.md`) already uses `<div data-form="enquiries"></div>`. No markup changes
|
|
406
|
+
needed - the redirect is configured in the form JSON. Optionally add a brief note in the page body:
|
|
407
|
+
|
|
408
|
+
```markdown
|
|
409
|
+
[spacer /]
|
|
410
|
+
|
|
411
|
+
> **Note for developers:** This form is configured with a success redirect to `/thank-you`. To add a CMS Action trigger (Pro), set `actionSlug` in `content/forms/enquiries.json`.
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
This is optional - remove if it feels too developer-facing for a public contact page.
|
|
415
|
+
|
|
416
|
+
- [ ] **Step 4: Commit**
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
git add content/pages/thank-you.md content/forms/enquiries.json content/pages/contact.md
|
|
420
|
+
git commit -m "feat: add thank-you page and configure enquiries form with success redirect"
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
### Task 6: Add tutorial card to tutorials.html
|
|
426
|
+
|
|
427
|
+
**Files:**
|
|
428
|
+
|
|
429
|
+
- Modify: `admin/js/templates/tutorials.html`
|
|
430
|
+
|
|
431
|
+
The file currently has one card: "Writing a Plugin". It ends around line 231-233. Add a new collapsible card after it.
|
|
432
|
+
|
|
433
|
+
- [ ] **Step 1: Add the tutorial card**
|
|
434
|
+
|
|
435
|
+
Locate the closing tags near the end of `tutorials.html`:
|
|
436
|
+
|
|
437
|
+
```html
|
|
438
|
+
</div>
|
|
439
|
+
</div>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Insert the new card before these closing tags:
|
|
443
|
+
|
|
444
|
+
```html
|
|
445
|
+
<!-- Tutorial: Form Follow-Up -->
|
|
446
|
+
<div class="card card-collapsible mb-4">
|
|
447
|
+
<div class="card-header">
|
|
448
|
+
<h2>Form Follow-Up: Notifications & Actions</h2>
|
|
449
|
+
</div>
|
|
450
|
+
<div class="card-body">
|
|
451
|
+
|
|
452
|
+
<p>Every form in Domma CMS can trigger up to four things after a submission is stored:</p>
|
|
453
|
+
<ol>
|
|
454
|
+
<li>Send an <strong>email notification</strong> to one or more recipients</li>
|
|
455
|
+
<li>POST to a <strong>webhook URL</strong></li>
|
|
456
|
+
<li>Execute a <strong>CMS Action</strong> (Pro)</li>
|
|
457
|
+
<li>Redirect the visitor to a <strong>success page</strong> (or show an inline message)</li>
|
|
458
|
+
</ol>
|
|
459
|
+
<p>These are configured per-form in the admin. Open any form in <a href="#/forms">Forms</a> and go to the
|
|
460
|
+
<strong>Settings</strong> and <strong>Actions</strong> tabs.</p>
|
|
461
|
+
|
|
462
|
+
<hr>
|
|
463
|
+
|
|
464
|
+
<h3>1. Email notification</h3>
|
|
465
|
+
<p>Go to the <strong>Actions</strong> tab of your form and enable <em>Send email on submit</em>. Enter one or
|
|
466
|
+
more comma-separated recipient addresses. This uses the SMTP settings configured in
|
|
467
|
+
<a href="#/settings">Site Settings → Email / SMTP</a>.</p>
|
|
468
|
+
|
|
469
|
+
<pre class="code-block"><code>Recipients: admin@example.com, team@example.com
|
|
470
|
+
Subject Prefix: [Contact Form]</code></pre>
|
|
471
|
+
|
|
472
|
+
<h3>2. Webhook</h3>
|
|
473
|
+
<p>Enable <em>POST to webhook on submit</em> and enter a URL. Domma will POST the following JSON body:</p>
|
|
474
|
+
<pre class="code-block"><code>{
|
|
475
|
+
"form": "enquiries",
|
|
476
|
+
"data": {
|
|
477
|
+
"full_name": "Jane Smith",
|
|
478
|
+
"email": "jane@example.com",
|
|
479
|
+
"message": "Hello!"
|
|
480
|
+
}
|
|
481
|
+
}</code></pre>
|
|
482
|
+
<p>Use this to integrate with Zapier, Make, Slack, or any HTTP endpoint.</p>
|
|
483
|
+
|
|
484
|
+
<h3>3. CMS Action (Pro)</h3>
|
|
485
|
+
<p>Actions are reusable workflow steps defined in <a href="#/actions">Actions</a>. A single action can chain
|
|
486
|
+
multiple steps: update a field, move an entry to another collection, send an email, call a webhook, or
|
|
487
|
+
delete an entry.</p>
|
|
488
|
+
<p>To wire an Action to a form:</p>
|
|
489
|
+
<ol>
|
|
490
|
+
<li>Create an Action in <a href="#/actions">Actions</a> targeting the same collection as your form.</li>
|
|
491
|
+
<li>Open the form in <a href="#/forms">Forms</a> → <strong>Actions</strong> tab → <strong>CMS Action</strong>
|
|
492
|
+
card.</li>
|
|
493
|
+
<li>Select the Action from the dropdown and save.</li>
|
|
494
|
+
</ol>
|
|
495
|
+
<p>The Action runs server-side, after the entry is saved. If it fails (e.g. MongoDB is not configured),
|
|
496
|
+
the submission is still stored - the action failure is non-fatal and logged as a warning.</p>
|
|
497
|
+
|
|
498
|
+
<h3>4. Success message vs. redirect</h3>
|
|
499
|
+
<p>After a successful submission the visitor sees one of two things:</p>
|
|
500
|
+
<ul>
|
|
501
|
+
<li><strong>Inline success message</strong> - the form is replaced by the text set in
|
|
502
|
+
<em>Settings → Success Message</em>. Good for simple acknowledgements.</li>
|
|
503
|
+
<li><strong>Page redirect</strong> - the visitor is sent to the URL set in
|
|
504
|
+
<em>Settings → Success Redirect URL</em>. Good for registration flows, checkouts, or when you want
|
|
505
|
+
a full thank-you page with additional content. <strong>Takes priority</strong> if both are set.</li>
|
|
506
|
+
</ul>
|
|
507
|
+
<p>Example: set <em>Success Redirect URL</em> to <code>/thank-you</code> and create a <code>thank-you.md</code>
|
|
508
|
+
page in the CMS with any content you like.</p>
|
|
509
|
+
|
|
510
|
+
<h3>Execution order</h3>
|
|
511
|
+
<p>On every submission, the pipeline runs in this fixed order:</p>
|
|
512
|
+
<ol>
|
|
513
|
+
<li>Validate fields + honeypot + rate limit</li>
|
|
514
|
+
<li>Store entry to collection</li>
|
|
515
|
+
<li>Send email (if enabled)</li>
|
|
516
|
+
<li>Call webhook (if enabled)</li>
|
|
517
|
+
<li>Execute CMS Action (if set)</li>
|
|
518
|
+
<li>Return success response → client redirects or shows message</li>
|
|
519
|
+
</ol>
|
|
520
|
+
<p>Steps 3-5 are non-fatal: a failure in any of them is logged as a warning but does not prevent the
|
|
521
|
+
submission from being stored or the success response from being returned.</p>
|
|
522
|
+
|
|
523
|
+
</div>
|
|
524
|
+
</div>
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
- [ ] **Step 2: Commit**
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
git add admin/js/templates/tutorials.html
|
|
531
|
+
git commit -m "docs: add form follow-up tutorial to admin tutorials page"
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
### Task 7: Add documentation entry to documentation.html
|
|
537
|
+
|
|
538
|
+
**Files:**
|
|
539
|
+
|
|
540
|
+
- Modify: `admin/js/templates/documentation.html`
|
|
541
|
+
|
|
542
|
+
Find the section that covers Forms (search for `forms` or `submission` in the file). Add a concise reference block for
|
|
543
|
+
the two new fields.
|
|
544
|
+
|
|
545
|
+
- [ ] **Step 1: Locate the Forms section**
|
|
546
|
+
|
|
547
|
+
Search for the Forms card heading in `documentation.html`:
|
|
548
|
+
|
|
549
|
+
```bash
|
|
550
|
+
grep -n "Forms\|submission\|Submit" admin/js/templates/documentation.html | head -20
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
- [ ] **Step 2: Add new fields reference**
|
|
554
|
+
|
|
555
|
+
Within the Forms documentation card body, add after the existing content:
|
|
556
|
+
|
|
557
|
+
```html
|
|
558
|
+
<h3>Form follow-up</h3>
|
|
559
|
+
<p>Two optional settings control what happens after a submission is stored:</p>
|
|
560
|
+
<table class="table" style="font-size:.9rem;">
|
|
561
|
+
<thead>
|
|
562
|
+
<tr><th>Field</th><th>Where</th><th>Description</th></tr>
|
|
563
|
+
</thead>
|
|
564
|
+
<tbody>
|
|
565
|
+
<tr>
|
|
566
|
+
<td><code>successMessage</code></td>
|
|
567
|
+
<td>Settings tab</td>
|
|
568
|
+
<td>Text shown inline after submission (replaces the form). Default: "Thank you for your submission."</td>
|
|
569
|
+
</tr>
|
|
570
|
+
<tr>
|
|
571
|
+
<td><code>successRedirect</code></td>
|
|
572
|
+
<td>Settings tab</td>
|
|
573
|
+
<td>URL to redirect the visitor on success. Takes priority over <code>successMessage</code> if set.</td>
|
|
574
|
+
</tr>
|
|
575
|
+
<tr>
|
|
576
|
+
<td><code>actionSlug</code></td>
|
|
577
|
+
<td>Actions tab → CMS Action</td>
|
|
578
|
+
<td>Slug of a CMS Action to execute after the entry is stored. Requires Pro (MongoDB). Non-fatal on failure.</td>
|
|
579
|
+
</tr>
|
|
580
|
+
</tbody>
|
|
581
|
+
</table>
|
|
582
|
+
<p>For the full walkthrough, see the
|
|
583
|
+
<a href="#/tutorials">Tutorials → Form Follow-Up: Notifications & Actions</a> tutorial.</p>
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
- [ ] **Step 3: Commit**
|
|
587
|
+
|
|
588
|
+
```bash
|
|
589
|
+
git add admin/js/templates/documentation.html
|
|
590
|
+
git commit -m "docs: add form follow-up fields reference to documentation"
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
## Verification
|
|
596
|
+
|
|
597
|
+
After a server restart, test the full flow:
|
|
598
|
+
|
|
599
|
+
```bash
|
|
600
|
+
# 1. Submit the enquiries form via curl (no auth needed)
|
|
601
|
+
curl -s -X POST http://localhost:4096/api/forms/submit/enquiries \
|
|
602
|
+
-H 'Content-Type: application/json' \
|
|
603
|
+
-d '{"full_name":"Test User","email":"test@example.com","message":"Hello"}'
|
|
604
|
+
|
|
605
|
+
# Expected: {"ok":true,"message":"...","redirect":"/thank-you"}
|
|
606
|
+
|
|
607
|
+
# 2. Confirm the entry was stored
|
|
608
|
+
TOKEN=$(curl -s -X POST http://localhost:4096/api/auth/login \
|
|
609
|
+
-H 'Content-Type: application/json' \
|
|
610
|
+
-d '{"email":"darryl@dwit.uk","password":"YOUR_PASSWORD"}' | python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")
|
|
611
|
+
curl -s http://localhost:4096/api/forms/enquiries/submissions \
|
|
612
|
+
-H "Authorization: Bearer $TOKEN" | python3 -m json.tool | head -20
|
|
613
|
+
|
|
614
|
+
# 3. Verify the thank-you page renders
|
|
615
|
+
curl -s http://localhost:4096/thank-you | grep -o '<title>[^<]*</title>'
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
**Manual browser test:**
|
|
619
|
+
|
|
620
|
+
1. Visit `/contact` - submit the enquiries form
|
|
621
|
+
2. Should redirect to `/thank-you`
|
|
622
|
+
3. Open the form editor for `enquiries` in the admin - verify the Success Redirect field shows `/thank-you`
|
|
623
|
+
4. Admin tutorials page (`#/tutorials`) - verify the new card appears and is collapsible
|
|
624
|
+
5. Admin documentation page (`#/documentation`) - verify the Forms section shows the new table
|