domma-cms 0.3.0 → 0.5.2
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/README.md +3 -3
- package/admin/css/admin.css +1 -1
- package/admin/dist/domma/domma-tools.css +2313 -0
- package/admin/dist/domma/domma-tools.min.js +10 -0
- package/admin/index.html +4 -0
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +8 -4
- package/admin/js/config/sidebar-config.js +1 -1
- package/admin/js/lib/markdown-toolbar.js +18 -10
- package/admin/js/templates/action-editor.html +171 -0
- package/admin/js/templates/actions-list.html +19 -0
- package/admin/js/templates/api-reference.html +1411 -0
- package/admin/js/templates/block-editor.html +158 -0
- package/admin/js/templates/blocks.html +8 -0
- package/admin/js/templates/collection-editor.html +47 -0
- package/admin/js/templates/collection-entries.html +3 -0
- package/admin/js/templates/collections.html +51 -4
- package/admin/js/templates/documentation.html +258 -0
- package/{plugins/form-builder/admin → admin/js}/templates/form-editor.html +238 -199
- package/{plugins/form-builder/admin → admin/js}/templates/form-submissions.html +30 -30
- package/{plugins/form-builder/admin/templates/forms-list.html → admin/js/templates/forms.html} +17 -17
- package/admin/js/templates/login.html +29 -4
- package/admin/js/templates/my-profile.html +17 -0
- package/admin/js/templates/page-editor.html +39 -0
- package/admin/js/templates/pages.html +6 -1
- package/admin/js/templates/pro-docs.html +259 -0
- package/admin/js/templates/role-editor.html +59 -0
- package/admin/js/templates/roles.html +10 -0
- package/admin/js/templates/settings.html +167 -23
- package/admin/js/templates/tutorials.html +81 -0
- package/admin/js/templates/user-editor.html +7 -0
- package/admin/js/templates/users.html +3 -26
- package/admin/js/templates/view-editor.html +201 -0
- package/admin/js/templates/view-preview.html +51 -0
- package/admin/js/templates/views-list.html +19 -0
- package/admin/js/views/action-editor.js +1 -0
- package/admin/js/views/actions-list.js +1 -0
- package/admin/js/views/api-reference.js +1 -0
- package/admin/js/views/block-editor.js +8 -0
- package/admin/js/views/blocks.js +4 -0
- package/admin/js/views/collection-editor.js +3 -3
- package/admin/js/views/collection-entries.js +1 -1
- package/admin/js/views/collections.js +1 -1
- package/admin/js/views/dashboard.js +1 -1
- package/admin/js/views/form-editor.js +8 -0
- package/admin/js/views/form-submissions.js +1 -0
- package/admin/js/views/forms.js +1 -0
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/login.js +2 -2
- package/admin/js/views/media.js +1 -1
- package/admin/js/views/my-profile.js +1 -0
- package/admin/js/views/page-editor.js +34 -15
- package/admin/js/views/pages.js +5 -5
- package/admin/js/views/plugins.js +10 -10
- package/admin/js/views/pro-docs.js +1 -0
- package/admin/js/views/role-editor.js +1 -0
- package/admin/js/views/roles.js +4 -0
- package/admin/js/views/settings.js +3 -1
- package/admin/js/views/user-editor.js +1 -1
- package/admin/js/views/users.js +4 -7
- package/admin/js/views/view-editor.js +1 -0
- package/admin/js/views/view-preview.js +1 -0
- package/admin/js/views/views-list.js +1 -0
- package/bin/cli.js +1 -1
- package/config/auth.json +1 -0
- package/config/connections.json.bak +9 -0
- package/config/connections.json.example +9 -0
- package/config/navigation.json +5 -15
- package/config/plugins.json +19 -29
- package/config/server.json +6 -6
- package/config/site.json +16 -6
- package/package.json +25 -10
- package/plugins/example-analytics/stats.json +17 -12
- package/plugins/form-builder/data/forms/contacts.json +62 -62
- package/plugins/form-builder/data/forms/enquiries.json +103 -0
- package/plugins/form-builder/data/forms/feedback.json +17 -16
- package/plugins/form-builder/data/forms/notes.json +79 -0
- package/plugins/form-builder/data/forms/to-do.json +100 -0
- package/plugins/form-builder/data/submissions/contacts.json +1 -26
- package/plugins/form-builder/data/submissions/notes.json +1 -0
- package/plugins/form-builder/data/submissions/to-do.json +1 -0
- package/plugins/theme-roller/admin/templates/theme-roller.html +71 -0
- package/plugins/theme-roller/admin/views/theme-roller-view.js +403 -0
- package/plugins/theme-roller/config.js +1 -0
- package/plugins/theme-roller/plugin.js +233 -0
- package/plugins/theme-roller/plugin.json +31 -0
- package/plugins/theme-roller/public/active-theme.css +0 -0
- package/plugins/theme-roller/public/inject-head-late.html +1 -0
- package/public/css/forms.css +1 -0
- package/public/css/site.css +1 -1
- package/public/js/forms.js +1 -0
- package/public/js/site.js +1 -1
- package/scripts/build.js +194 -129
- package/scripts/pro.js +254 -0
- package/scripts/reset.js +33 -8
- package/scripts/seed.js +677 -128
- package/scripts/setup.js +1 -0
- package/server/middleware/auth.js +136 -120
- package/server/routes/api/actions.js +200 -0
- package/server/routes/api/auth.js +292 -146
- package/server/routes/api/blocks.js +84 -0
- package/server/routes/api/collections.js +79 -27
- package/{plugins/form-builder/plugin.js → server/routes/api/forms.js} +491 -505
- package/server/routes/api/layouts.js +49 -39
- package/server/routes/api/media.js +118 -92
- package/server/routes/api/navigation.js +40 -36
- package/server/routes/api/pages.js +132 -118
- package/server/routes/api/plugins.js +6 -3
- package/server/routes/api/settings.js +104 -88
- package/server/routes/api/users.js +27 -19
- package/server/routes/api/views.js +148 -0
- package/server/routes/public.js +124 -108
- package/server/server.js +269 -181
- package/server/services/actions.js +387 -0
- package/server/services/adapterRegistry.js +98 -0
- package/server/services/adapters/FileAdapter.js +192 -0
- package/server/services/adapters/MongoAdapter.js +220 -0
- package/server/services/blocks.js +162 -0
- package/server/services/collections.js +74 -86
- package/server/services/connectionManager.js +102 -0
- package/server/services/content.js +312 -307
- package/server/services/email.js +126 -0
- package/server/services/forms.js +173 -0
- package/server/services/markdown.js +1378 -747
- package/server/services/permissionRegistry.js +173 -0
- package/server/services/presetCollections.js +251 -0
- package/server/services/renderer.js +98 -2
- package/server/services/roles.js +227 -0
- package/server/services/rowAccess.js +104 -0
- package/server/services/userProfiles.js +199 -0
- package/server/services/users.js +281 -212
- package/server/services/views.js +280 -0
- package/server/templates/page.html +124 -113
- package/plugins/form-builder/admin/templates/form-settings.html +0 -29
- package/plugins/form-builder/admin/views/form-editor.js +0 -1444
- package/plugins/form-builder/admin/views/form-settings.js +0 -38
- package/plugins/form-builder/admin/views/form-submissions.js +0 -295
- package/plugins/form-builder/admin/views/forms-list.js +0 -164
- package/plugins/form-builder/config.js +0 -9
- package/plugins/form-builder/data/forms/consent.json +0 -104
- package/plugins/form-builder/data/forms/contact-details.json +0 -99
- package/plugins/form-builder/data/submissions/consent.json +0 -13
- package/plugins/form-builder/plugin.json +0 -52
- package/plugins/form-builder/public/inject-body.html +0 -352
- package/plugins/form-builder/public/inject-head.html +0 -58
- package/plugins/form-builder/public/package.json +0 -1
- package/scripts/copy-domma.js +0 -48
- package/server/services/userTypes.js +0 -167
- /package/plugins/form-builder/data/submissions/{contact-details.json → enquiries.json} +0 -0
- /package/{plugins/form-builder/public → public/js}/form-logic-engine.js +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<div class="view-header">
|
|
2
|
+
<h1><span data-icon="box"></span> <span id="block-editor-title">New Block</span></h1>
|
|
3
|
+
<div style="display:flex;gap:.5rem;">
|
|
4
|
+
<a href="#/blocks" class="btn btn-ghost btn-sm">
|
|
5
|
+
<span data-icon="arrow-left"></span> All Blocks
|
|
6
|
+
</a>
|
|
7
|
+
<button id="save-block-btn" class="btn btn-primary">
|
|
8
|
+
<span data-icon="save"></span> Save Block
|
|
9
|
+
</button>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<!-- Block Name -->
|
|
14
|
+
<div class="card card-collapsible mb-3">
|
|
15
|
+
<div class="card-header">
|
|
16
|
+
<h2>Block Name</h2>
|
|
17
|
+
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="card-body" style="max-width:420px;">
|
|
20
|
+
<label class="form-label">Name <span style="color:var(--dm-danger,#f87171);">*</span></label>
|
|
21
|
+
<input id="block-name" type="text" class="form-input" placeholder="e.g. feedback-card">
|
|
22
|
+
<small class="text-muted">Lowercase letters, digits, and hyphens only. Cannot be changed after creation.</small>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<!-- HTML Editor + Preview -->
|
|
27
|
+
<div class="card card-collapsible editor-card mb-3">
|
|
28
|
+
<div class="card-header">
|
|
29
|
+
<h2>Template HTML</h2>
|
|
30
|
+
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="card-body p-0">
|
|
33
|
+
|
|
34
|
+
<!-- Toolbar -->
|
|
35
|
+
<div id="block-editor-toolbar" class="editor-toolbar">
|
|
36
|
+
<button type="button" class="btn btn-ghost btn-sm" data-action="undo" title="Undo (Ctrl+Z)">
|
|
37
|
+
<span data-icon="corner-up-left"></span>
|
|
38
|
+
</button>
|
|
39
|
+
<button type="button" class="btn btn-ghost btn-sm" data-action="redo" title="Redo (Ctrl+Y)">
|
|
40
|
+
<span data-icon="corner-up-right"></span>
|
|
41
|
+
</button>
|
|
42
|
+
<span class="editor-toolbar-sep"></span>
|
|
43
|
+
<button type="button" class="btn btn-ghost btn-sm" data-action="cut" title="Cut (Ctrl+X)">
|
|
44
|
+
<span data-icon="scissors"></span>
|
|
45
|
+
</button>
|
|
46
|
+
<button type="button" class="btn btn-ghost btn-sm" data-action="copy" title="Copy (Ctrl+C)">
|
|
47
|
+
<span data-icon="copy"></span>
|
|
48
|
+
</button>
|
|
49
|
+
<button type="button" class="btn btn-ghost btn-sm" data-action="paste" title="Paste (Ctrl+V)">
|
|
50
|
+
<span data-icon="clipboard"></span>
|
|
51
|
+
</button>
|
|
52
|
+
<span class="editor-toolbar-sep"></span>
|
|
53
|
+
<button type="button" class="btn btn-ghost btn-sm" data-action="select-all" title="Select All (Ctrl+A)">
|
|
54
|
+
<span data-icon="maximize-2"></span>
|
|
55
|
+
</button>
|
|
56
|
+
<button type="button" class="btn btn-ghost btn-sm" data-action="format" title="Format HTML">
|
|
57
|
+
<span data-icon="code"></span> Format
|
|
58
|
+
</button>
|
|
59
|
+
|
|
60
|
+
<!-- View mode toggles (right side) -->
|
|
61
|
+
<div class="editor-toolbar-right">
|
|
62
|
+
<span id="block-cursor-pos"
|
|
63
|
+
style="font-size:.75rem;color:var(--dm-text-muted,#888);margin-right:.5rem;">Ln 1, Col 1</span>
|
|
64
|
+
<span class="editor-toolbar-sep"></span>
|
|
65
|
+
<button type="button" class="editor-view-btn active" data-mode="write" title="Edit only">
|
|
66
|
+
<span data-icon="edit-2"></span>
|
|
67
|
+
</button>
|
|
68
|
+
<button type="button" class="editor-view-btn" data-mode="split" title="Split view">
|
|
69
|
+
<span data-icon="columns"></span>
|
|
70
|
+
</button>
|
|
71
|
+
<button type="button" class="editor-view-btn" data-mode="preview" title="Preview only">
|
|
72
|
+
<span data-icon="eye"></span>
|
|
73
|
+
</button>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<!-- Editor body — split pane -->
|
|
78
|
+
<div id="block-editor-body" class="editor-body editor-mode-write" style="min-height:460px;">
|
|
79
|
+
|
|
80
|
+
<!-- Write pane -->
|
|
81
|
+
<div class="editor-pane editor-pane--write" style="flex-direction:row;overflow:hidden;">
|
|
82
|
+
<div id="block-line-numbers" class="editor-line-numbers">1</div>
|
|
83
|
+
<textarea id="block-content" class="editor-textarea"
|
|
84
|
+
spellcheck="false"
|
|
85
|
+
placeholder="<div class="card mb-3"> <div class="card-body"> <h3>{{title}}</h3> <p>{{message}}</p> </div> </div>"></textarea>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div class="editor-divider"></div>
|
|
89
|
+
|
|
90
|
+
<!-- Preview pane -->
|
|
91
|
+
<div class="editor-pane editor-pane--preview" style="flex-direction:column;overflow:hidden;">
|
|
92
|
+
<!-- Sample data inputs — auto-populated by JS -->
|
|
93
|
+
<div id="block-sample-data" style="
|
|
94
|
+
border-bottom:1px solid var(--dm-border,rgba(255,255,255,.08));
|
|
95
|
+
padding:.6rem .75rem;
|
|
96
|
+
background:var(--dm-surface-subtle,rgba(0,0,0,.1));
|
|
97
|
+
flex-shrink:0;">
|
|
98
|
+
<p class="text-muted" style="font-size:.8rem;margin:0;">
|
|
99
|
+
Write some template HTML to populate sample data fields.
|
|
100
|
+
</p>
|
|
101
|
+
</div>
|
|
102
|
+
<!-- Rendered output -->
|
|
103
|
+
<div id="block-preview-output" style="flex:1;overflow-y:auto;padding:1rem;"></div>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<!-- Placeholder Reference -->
|
|
111
|
+
<div class="card card-collapsible mb-3 card-collapsed">
|
|
112
|
+
<div class="card-header">
|
|
113
|
+
<h2>Placeholder Reference</h2>
|
|
114
|
+
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="card-body" style="font-size:.85rem;line-height:1.8;">
|
|
117
|
+
<p>Use <code class="dm-code-inline">{{fieldName}}</code> to insert entry field values. Values are HTML-escaped
|
|
118
|
+
automatically to prevent XSS.</p>
|
|
119
|
+
<table class="table" style="max-width:520px;margin:.75rem 0;">
|
|
120
|
+
<thead>
|
|
121
|
+
<tr>
|
|
122
|
+
<th style="width:180px;">Placeholder</th>
|
|
123
|
+
<th>Value</th>
|
|
124
|
+
</tr>
|
|
125
|
+
</thead>
|
|
126
|
+
<tbody>
|
|
127
|
+
<tr>
|
|
128
|
+
<td><code class="dm-code-inline">{{fieldName}}</code></td>
|
|
129
|
+
<td>Any entry field — e.g. <code class="dm-code-inline">{{title}}</code>, <code class="dm-code-inline">{{rating}}</code>,
|
|
130
|
+
<code class="dm-code-inline">{{message}}</code></td>
|
|
131
|
+
</tr>
|
|
132
|
+
<tr>
|
|
133
|
+
<td><code class="dm-code-inline">{{_id}}</code></td>
|
|
134
|
+
<td>Entry UUID</td>
|
|
135
|
+
</tr>
|
|
136
|
+
<tr>
|
|
137
|
+
<td><code class="dm-code-inline">{{_createdAt}}</code></td>
|
|
138
|
+
<td>Creation timestamp (ISO 8601)</td>
|
|
139
|
+
</tr>
|
|
140
|
+
<tr>
|
|
141
|
+
<td><code class="dm-code-inline">{{_updatedAt}}</code></td>
|
|
142
|
+
<td>Last-updated timestamp (ISO 8601)</td>
|
|
143
|
+
</tr>
|
|
144
|
+
</tbody>
|
|
145
|
+
</table>
|
|
146
|
+
<p><strong>Use in a shortcode:</strong></p>
|
|
147
|
+
<pre class="dm-code-block">[collection slug="feedback" display="block" block="feedback-card" /]
|
|
148
|
+
[view slug="my-view" display="block" block="feedback-card" /]</pre>
|
|
149
|
+
<p style="margin-top:.75rem;"><strong>Example block template:</strong></p>
|
|
150
|
+
<pre class="dm-code-block"><div class="card mb-3">
|
|
151
|
+
<div class="card-body">
|
|
152
|
+
<h3>{{name}}</h3>
|
|
153
|
+
<p>{{message}}</p>
|
|
154
|
+
<small>Rating: {{rating}} &mdash; {{_createdAt}}</small>
|
|
155
|
+
</div>
|
|
156
|
+
</div></pre>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
<button class="tab-item active">Settings</button>
|
|
16
16
|
<button class="tab-item">Fields</button>
|
|
17
17
|
<button class="tab-item">API Access</button>
|
|
18
|
+
<button class="tab-item" id="storage-tab-btn" style="display:none;">Storage</button>
|
|
18
19
|
</div>
|
|
19
20
|
<div class="tab-content">
|
|
20
21
|
|
|
@@ -39,6 +40,19 @@
|
|
|
39
40
|
<textarea id="field-description" class="form-input" rows="2" placeholder="Optional description…"></textarea>
|
|
40
41
|
</div>
|
|
41
42
|
</div>
|
|
43
|
+
<div class="row mt-3">
|
|
44
|
+
<div class="col-6">
|
|
45
|
+
<label class="form-label">Entry Form Layout</label>
|
|
46
|
+
<select id="collection-layout" class="form-input">
|
|
47
|
+
<option value="stacked">Stacked</option>
|
|
48
|
+
<option value="grid">Grid</option>
|
|
49
|
+
</select>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="col-6" id="collection-columns-group" style="display:none;">
|
|
52
|
+
<label class="form-label">Columns</label>
|
|
53
|
+
<input id="collection-columns" type="number" class="form-input" min="1" max="6" value="2">
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
42
56
|
</div>
|
|
43
57
|
</div>
|
|
44
58
|
</div>
|
|
@@ -76,5 +90,38 @@
|
|
|
76
90
|
</div>
|
|
77
91
|
</div>
|
|
78
92
|
|
|
93
|
+
<!-- Storage tab (Pro) -->
|
|
94
|
+
<div class="tab-panel" id="storage-panel">
|
|
95
|
+
<div class="card">
|
|
96
|
+
<div class="card-header"><h2>Storage Adapter</h2></div>
|
|
97
|
+
<div class="card-body">
|
|
98
|
+
<p class="text-muted mb-4">Choose where this collection's entries are stored. File-based storage is the
|
|
99
|
+
default. MongoDB requires Pro mode to be enabled.</p>
|
|
100
|
+
<div class="form-group mb-3">
|
|
101
|
+
<label class="form-label">Adapter</label>
|
|
102
|
+
<button id="storage-adapter-trigger" class="form-input" type="button"
|
|
103
|
+
style="text-align:left;cursor:pointer;display:flex;align-items:center;justify-content:space-between;">
|
|
104
|
+
<span id="storage-adapter-label">File (default)</span>
|
|
105
|
+
<span data-icon="chevron-down" style="opacity:.5;"></span>
|
|
106
|
+
</button>
|
|
107
|
+
<input type="hidden" id="storage-adapter" value="file">
|
|
108
|
+
</div>
|
|
109
|
+
<div id="storage-connection-group" class="form-group mb-3" style="display:none;">
|
|
110
|
+
<label class="form-label">Connection</label>
|
|
111
|
+
<button id="storage-connection-trigger" class="form-input" type="button"
|
|
112
|
+
style="text-align:left;cursor:pointer;display:flex;align-items:center;justify-content:space-between;">
|
|
113
|
+
<span id="storage-connection-label">default</span>
|
|
114
|
+
<span data-icon="chevron-down" style="opacity:.5;"></span>
|
|
115
|
+
</button>
|
|
116
|
+
<input type="hidden" id="storage-connection" value="default">
|
|
117
|
+
<p class="form-text text-muted mt-1">Named connection from config/connections.json</p>
|
|
118
|
+
</div>
|
|
119
|
+
<div id="storage-migration-warning" class="alert alert-warning mt-3" style="display:none;">
|
|
120
|
+
Changing the storage adapter does not migrate existing entries. Export your data before switching.
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
79
126
|
</div>
|
|
80
127
|
</div>
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
<a id="edit-schema-btn" href="#/collections" class="btn btn-ghost btn-sm">
|
|
8
8
|
<span data-icon="edit-3"></span> Edit Schema
|
|
9
9
|
</a>
|
|
10
|
+
<a id="form-btn" href="#/forms" class="btn btn-ghost btn-sm">
|
|
11
|
+
<span data-icon="layout"></span> Form
|
|
12
|
+
</a>
|
|
10
13
|
<button id="import-btn" class="btn btn-ghost btn-sm">
|
|
11
14
|
<span data-icon="upload"></span> Import
|
|
12
15
|
</button>
|
|
@@ -1,12 +1,59 @@
|
|
|
1
1
|
<div class="view-header">
|
|
2
2
|
<h1><span data-icon="database"></span> Collections</h1>
|
|
3
|
+
<div id="collections-header-actions">
|
|
3
4
|
<button id="create-collection-btn" class="btn btn-primary">
|
|
4
|
-
|
|
5
|
+
<span data-icon="plus"></span> New Collection
|
|
5
6
|
</button>
|
|
7
|
+
</div>
|
|
6
8
|
</div>
|
|
7
9
|
|
|
8
|
-
<div class="
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
<div class="tabs" id="collections-tabs">
|
|
11
|
+
<div class="tab-list">
|
|
12
|
+
<button class="tab-item active">Collections</button>
|
|
13
|
+
<button class="tab-item">Options</button>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="tab-content">
|
|
16
|
+
|
|
17
|
+
<!-- Collections tab -->
|
|
18
|
+
<div class="tab-panel active">
|
|
19
|
+
<div class="card">
|
|
20
|
+
<div class="card-body">
|
|
21
|
+
<div id="collections-table"></div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<!-- Options tab -->
|
|
27
|
+
<div class="tab-panel">
|
|
28
|
+
<div class="card">
|
|
29
|
+
<div class="card-header" style="display:flex;justify-content:space-between;align-items:center;">
|
|
30
|
+
<h2>Database Connections</h2>
|
|
31
|
+
<div style="display:flex;align-items:center;gap:.75rem;">
|
|
32
|
+
<label style="display:flex;align-items:center;gap:.4rem;font-size:.875rem;cursor:pointer;">
|
|
33
|
+
<input type="checkbox" id="connections-raw-toggle"> Raw JSON
|
|
34
|
+
</label>
|
|
35
|
+
<button id="add-connection-btn" class="btn btn-ghost btn-sm" type="button">
|
|
36
|
+
<span data-icon="plus"></span> Add Connection
|
|
37
|
+
</button>
|
|
38
|
+
<button id="save-connections-btn" class="btn btn-primary btn-sm" type="button">
|
|
39
|
+
<span data-icon="save"></span> Save
|
|
40
|
+
</button>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="card-body">
|
|
44
|
+
<div id="connections-form-view">
|
|
45
|
+
<div id="connections-list"></div>
|
|
46
|
+
<p id="connections-empty" class="text-muted" style="text-align:center;padding:2rem 0;">
|
|
47
|
+
No connections configured. Add a connection to enable MongoDB storage.
|
|
48
|
+
</p>
|
|
49
|
+
</div>
|
|
50
|
+
<div id="connections-raw-view" style="display:none;">
|
|
51
|
+
<textarea id="connections-raw-json" class="form-input" rows="12"
|
|
52
|
+
style="font-family:monospace;font-size:.8rem;resize:vertical;width:100%;"></textarea>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
11
56
|
</div>
|
|
57
|
+
|
|
58
|
+
</div>
|
|
12
59
|
</div>
|
|
@@ -249,6 +249,102 @@ Content goes here.
|
|
|
249
249
|
</div>
|
|
250
250
|
</div>
|
|
251
251
|
|
|
252
|
+
<!-- Shortcodes -->
|
|
253
|
+
<div class="card card-collapsible mb-4">
|
|
254
|
+
<div class="card-header" role="button" tabindex="0">
|
|
255
|
+
<div class="card-header-content"><h2><span data-icon="code"></span> Shortcodes</h2></div>
|
|
256
|
+
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
257
|
+
</div>
|
|
258
|
+
<div class="card-body docs-body">
|
|
259
|
+
<p>Shortcodes extend Markdown with layout components. They are processed server-side before Markdown rendering, so you can freely mix shortcodes and Markdown in the same page body.</p>
|
|
260
|
+
<p><strong>Syntax:</strong> <code>[shortcode attribute="value"]</code> (self-closing: <code>[shortcode /]</code>) and <code>[/shortcode]</code> for paired tags.</p>
|
|
261
|
+
|
|
262
|
+
<h3>Layout</h3>
|
|
263
|
+
<table class="table table-sm">
|
|
264
|
+
<thead><tr><th>Shortcode</th><th>Description</th></tr></thead>
|
|
265
|
+
<tbody>
|
|
266
|
+
<tr><td><code>[grid cols="N" gap="N"]...[/grid]</code></td><td>CSS Grid container — N columns (1–12), optional gap (1–6)</td></tr>
|
|
267
|
+
<tr><td><code>[row gap="N"]...[/row]</code></td><td>Flexbox row — columns share width equally</td></tr>
|
|
268
|
+
<tr><td><code>[col span="N"]...[/col]</code></td><td>Column inside a grid or row; <code>span</code> sets column span</td></tr>
|
|
269
|
+
</tbody>
|
|
270
|
+
</table>
|
|
271
|
+
|
|
272
|
+
<h3>Components</h3>
|
|
273
|
+
<table class="table table-sm">
|
|
274
|
+
<thead><tr><th>Shortcode</th><th>Description</th></tr></thead>
|
|
275
|
+
<tbody>
|
|
276
|
+
<tr><td><code>[card title="..."]...[/card]</code></td><td>Styled card; <code>collapsible="true"</code> makes the body toggleable</td></tr>
|
|
277
|
+
<tr><td><code>[tabs]...[/tabs]</code></td><td>Tab group; use <code>[tab title="..."]...[/tab]</code> inside</td></tr>
|
|
278
|
+
<tr><td><code>[accordion]...[/accordion]</code></td><td>Accordion group; use <code>[item title="..."]...[/item]</code> inside</td></tr>
|
|
279
|
+
<tr><td><code>[carousel]...[/carousel]</code></td><td>Carousel; use <code>[slide]...[/slide]</code> inside</td></tr>
|
|
280
|
+
<tr><td><code>[badge variant="success"]...[/badge]</code></td><td>Inline badge; variants: primary, secondary, success, danger, warning, info</td></tr>
|
|
281
|
+
<tr><td><code>[icon name="star" /]</code></td><td>Inline Domma icon; optional <code>size</code> and <code>color</code></td></tr>
|
|
282
|
+
<tr><td><code>[spacer size="16" /]</code></td><td>Vertical whitespace block (px height)</td></tr>
|
|
283
|
+
<tr><td><code>[timeline]...[/timeline]</code></td><td>Progression timeline; use <code>[event title="..." date="..." status="..."]...[/event]</code> inside</td></tr>
|
|
284
|
+
<tr><td><code>[countdown to="2026-12-31" /]</code></td><td>Animated countdown to a date</td></tr>
|
|
285
|
+
</tbody>
|
|
286
|
+
</table>
|
|
287
|
+
|
|
288
|
+
<h3>Content</h3>
|
|
289
|
+
<table class="table table-sm">
|
|
290
|
+
<thead><tr><th>Shortcode</th><th>Description</th></tr></thead>
|
|
291
|
+
<tbody>
|
|
292
|
+
<tr><td><code>[hero variant="dark" size="sm"]...[/hero]</code></td><td>Full-width hero section; supports <code>twinkle</code>, <code>blobs</code>, <code>image</code>, <code>overlay</code></td></tr>
|
|
293
|
+
<tr><td><code>[table striped="true"]...[/table]</code></td><td>Wraps a GFM Markdown table with Domma table CSS classes</td></tr>
|
|
294
|
+
<tr><td><code>[form name="slug" /]</code></td><td>Embeds a Form Builder form by slug</td></tr>
|
|
295
|
+
<tr><td><code>[collection slug="..." display="table" /]</code></td><td>Renders collection entries inline (table, cards, or list)</td></tr>
|
|
296
|
+
</tbody>
|
|
297
|
+
</table>
|
|
298
|
+
|
|
299
|
+
<h3>Form follow-up</h3>
|
|
300
|
+
<p>Two optional settings control what happens after a submission is stored:</p>
|
|
301
|
+
<table class="table" style="font-size:.9rem;">
|
|
302
|
+
<thead>
|
|
303
|
+
<tr><th>Field</th><th>Where</th><th>Description</th></tr>
|
|
304
|
+
</thead>
|
|
305
|
+
<tbody>
|
|
306
|
+
<tr>
|
|
307
|
+
<td><code>successMessage</code></td>
|
|
308
|
+
<td>Settings tab</td>
|
|
309
|
+
<td>Text shown inline after submission (replaces the form). Default: "Thank you for your submission."</td>
|
|
310
|
+
</tr>
|
|
311
|
+
<tr>
|
|
312
|
+
<td><code>successRedirect</code></td>
|
|
313
|
+
<td>Settings tab</td>
|
|
314
|
+
<td>URL to redirect the visitor on success. Takes priority over <code>successMessage</code> if set.</td>
|
|
315
|
+
</tr>
|
|
316
|
+
<tr>
|
|
317
|
+
<td><code>actionSlug</code></td>
|
|
318
|
+
<td>Actions tab → CMS Action</td>
|
|
319
|
+
<td>Slug of a CMS Action to execute after the entry is stored. Requires Pro (MongoDB). Non-fatal on failure.</td>
|
|
320
|
+
</tr>
|
|
321
|
+
</tbody>
|
|
322
|
+
</table>
|
|
323
|
+
<p>For the full walkthrough, see the
|
|
324
|
+
<a href="#/tutorials">Tutorials → Form Follow-Up: Notifications & Actions</a> tutorial.</p>
|
|
325
|
+
|
|
326
|
+
<h3>Interactive</h3>
|
|
327
|
+
<table class="table table-sm">
|
|
328
|
+
<thead><tr><th>Shortcode</th><th>Description</th></tr></thead>
|
|
329
|
+
<tbody>
|
|
330
|
+
<tr><td><code>[slideover title="..." trigger="..."]...[/slideover]</code></td><td>Slide-in panel opened by a trigger button</td></tr>
|
|
331
|
+
<tr><td><code>[dconfig]{...}[/dconfig]</code></td><td>Declarative click handlers and class toggles — no JavaScript needed</td></tr>
|
|
332
|
+
</tbody>
|
|
333
|
+
</table>
|
|
334
|
+
|
|
335
|
+
<h3>Pro shortcodes</h3>
|
|
336
|
+
<table class="table table-sm">
|
|
337
|
+
<thead><tr><th>Shortcode</th><th>Description</th></tr></thead>
|
|
338
|
+
<tbody>
|
|
339
|
+
<tr><td><code>[view slug="..." display="table" /]</code></td><td>Executes a saved View and renders results. Requires MongoDB.</td></tr>
|
|
340
|
+
<tr><td><code>[cta action="..." entry="..."]Label[/cta]</code></td><td>Action-trigger button. Requires the visitor to be logged in.</td></tr>
|
|
341
|
+
</tbody>
|
|
342
|
+
</table>
|
|
343
|
+
|
|
344
|
+
<p>Full attribute reference and live demos: <a href="/resources/shortcodes" target="_blank">Shortcode Reference</a> · <a href="/resources/components" target="_blank">Components</a> · <a href="/resources/effects" target="_blank">Effects</a></p>
|
|
345
|
+
</div>
|
|
346
|
+
</div>
|
|
347
|
+
|
|
252
348
|
<!-- Settings -->
|
|
253
349
|
<div class="card card-collapsible mb-4">
|
|
254
350
|
<div class="card-header" role="button" tabindex="0">
|
|
@@ -366,6 +462,168 @@ Content goes here.
|
|
|
366
462
|
<h3>Authentication</h3>
|
|
367
463
|
<p>The admin panel uses JWT Bearer tokens. Tokens are stored in the browser and automatically refreshed.
|
|
368
464
|
Sessions expire according to <code>config/auth.json</code> — default is 24 hours.</p>
|
|
465
|
+
|
|
466
|
+
<h3>Views & Actions</h3>
|
|
467
|
+
<p>Views and Actions are pro-only features that require a MongoDB connection.
|
|
468
|
+
Both roles — Admin and Manager — can create, edit, and run Views and Actions.</p>
|
|
469
|
+
<table class="table table-sm">
|
|
470
|
+
<thead><tr><th>Role</th><th>Views</th><th>Actions</th></tr></thead>
|
|
471
|
+
<tbody>
|
|
472
|
+
<tr><td><strong>Admin</strong></td><td>Full access</td><td>Full access</td></tr>
|
|
473
|
+
<tr><td><strong>Manager</strong></td><td>Full access</td><td>Full access</td></tr>
|
|
474
|
+
<tr><td><strong>Editor</strong></td><td>No access</td><td>No access</td></tr>
|
|
475
|
+
<tr><td><strong>Subscriber</strong></td><td>No access</td><td>No access</td></tr>
|
|
476
|
+
</tbody>
|
|
477
|
+
</table>
|
|
478
|
+
</div>
|
|
479
|
+
</div>
|
|
480
|
+
|
|
481
|
+
<!-- Views -->
|
|
482
|
+
<div class="card card-collapsible mb-4">
|
|
483
|
+
<div class="card-header" role="button" tabindex="0">
|
|
484
|
+
<div class="card-header-content"><h2><span data-icon="eye"></span> Views <span class="badge badge-warning" style="font-size:.7rem;">Pro</span></h2></div>
|
|
485
|
+
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
486
|
+
</div>
|
|
487
|
+
<div class="card-body docs-body">
|
|
488
|
+
<p>Views are admin-designed display configurations that query one or more Collections via a stored
|
|
489
|
+
MongoDB aggregation pipeline, then render the results in the admin panel.
|
|
490
|
+
Views require a MongoDB connection configured under <strong>Collections → Options</strong>.</p>
|
|
491
|
+
|
|
492
|
+
<h3>Creating a View</h3>
|
|
493
|
+
<ol>
|
|
494
|
+
<li>Navigate to <strong>Data → Views</strong> and click <strong>New View</strong>.</li>
|
|
495
|
+
<li><strong>Source tab</strong> — enter a title, choose the primary source collection, and select the MongoDB connection.</li>
|
|
496
|
+
<li><strong>Pipeline tab</strong> — add aggregation stages in order. Each stage has a type and a JSON config object.</li>
|
|
497
|
+
<li><strong>Display tab</strong> — choose table or list mode, set page size, and optionally define column definitions.</li>
|
|
498
|
+
<li><strong>Access tab</strong> — select which roles can access this view and whether it is publicly accessible.</li>
|
|
499
|
+
<li>Click <strong>Save View</strong>, then use <strong>Preview</strong> to execute and inspect the results.</li>
|
|
500
|
+
</ol>
|
|
501
|
+
|
|
502
|
+
<h3>Allowed Pipeline Stage Types</h3>
|
|
503
|
+
<table class="table table-sm">
|
|
504
|
+
<thead><tr><th>Stage</th><th>Purpose</th></tr></thead>
|
|
505
|
+
<tbody>
|
|
506
|
+
<tr><td><code>$match</code></td><td>Filter documents by condition</td></tr>
|
|
507
|
+
<tr><td><code>$lookup</code></td><td>Left join from another collection</td></tr>
|
|
508
|
+
<tr><td><code>$sort</code></td><td>Sort documents</td></tr>
|
|
509
|
+
<tr><td><code>$project</code></td><td>Include or exclude fields</td></tr>
|
|
510
|
+
<tr><td><code>$unwind</code></td><td>Deconstruct an array field</td></tr>
|
|
511
|
+
<tr><td><code>$addFields</code></td><td>Compute and add new fields</td></tr>
|
|
512
|
+
<tr><td><code>$group</code></td><td>Group and aggregate</td></tr>
|
|
513
|
+
<tr><td><code>$count</code></td><td>Count documents</td></tr>
|
|
514
|
+
<tr><td><code>$skip</code></td><td>Skip documents (added automatically for pagination)</td></tr>
|
|
515
|
+
<tr><td><code>$limit</code></td><td>Limit documents (added automatically for pagination)</td></tr>
|
|
516
|
+
</tbody>
|
|
517
|
+
</table>
|
|
518
|
+
<p>Forbidden stages (<code>$out</code>, <code>$merge</code>, <code>$function</code>, <code>$accumulator</code>,
|
|
519
|
+
<code>$graphLookup</code>) are rejected at save and execution time.</p>
|
|
520
|
+
|
|
521
|
+
<h3>Collection Name Mapping</h3>
|
|
522
|
+
<p>The <strong>source</strong> field in the pipeline config is a collection <em>slug</em>
|
|
523
|
+
(e.g. <code>users</code>). At execution time this is automatically prefixed to
|
|
524
|
+
<code>cms_users</code> to match the MongoDB collection name used by the adapter.</p>
|
|
525
|
+
<p>The same applies inside <code>$lookup</code> stages — use the CMS slug as the <code>from</code> value
|
|
526
|
+
and the service maps it automatically.</p>
|
|
527
|
+
|
|
528
|
+
<h3>Column Definitions</h3>
|
|
529
|
+
<p>On the Display tab, column definitions are a JSON array. Each object has a <code>key</code>
|
|
530
|
+
(dot-path into the result document) and a <code>label</code>.</p>
|
|
531
|
+
<pre class="code-block"><code>[
|
|
532
|
+
{ "key": "data.name", "label": "Name" },
|
|
533
|
+
{ "key": "data.email", "label": "Email" },
|
|
534
|
+
{ "key": "orders", "label": "Orders" }
|
|
535
|
+
]</code></pre>
|
|
536
|
+
<p>If no columns are defined, the preview auto-generates columns from the first result document.</p>
|
|
537
|
+
|
|
538
|
+
<h3>Public Access</h3>
|
|
539
|
+
<p>Tick <strong>Public</strong> on the Access tab to expose the view via
|
|
540
|
+
<code>GET /api/views/:slug/public</code> without requiring a login.
|
|
541
|
+
Leave it unticked to require JWT authentication with one of the allowed roles.</p>
|
|
542
|
+
</div>
|
|
543
|
+
</div>
|
|
544
|
+
|
|
545
|
+
<!-- Actions -->
|
|
546
|
+
<div class="card card-collapsible mb-4">
|
|
547
|
+
<div class="card-header" role="button" tabindex="0">
|
|
548
|
+
<div class="card-header-content"><h2><span data-icon="zap"></span> Actions <span class="badge badge-warning" style="font-size:.7rem;">Pro</span></h2></div>
|
|
549
|
+
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
550
|
+
</div>
|
|
551
|
+
<div class="card-body docs-body">
|
|
552
|
+
<p>Actions are admin-designed sequential workflow operations triggered against individual collection
|
|
553
|
+
entries. When an action is assigned to a collection, a trigger button appears per row in the
|
|
554
|
+
entry list. Actions require a MongoDB connection (pro mode).</p>
|
|
555
|
+
|
|
556
|
+
<h3>Creating an Action</h3>
|
|
557
|
+
<ol>
|
|
558
|
+
<li>Navigate to <strong>Data → Actions</strong> and click <strong>New Action</strong>.</li>
|
|
559
|
+
<li><strong>General tab</strong> — enter a title and select the target collection.</li>
|
|
560
|
+
<li><strong>Trigger tab</strong> — configure the button label, icon, and optional confirmation message.</li>
|
|
561
|
+
<li><strong>Steps tab</strong> — add steps in order. Each step runs sequentially; if one fails the action stops.</li>
|
|
562
|
+
<li><strong>Access tab</strong> — select which roles can trigger this action.</li>
|
|
563
|
+
<li>Click <strong>Save Action</strong>. The button will appear on the collection's entry list.</li>
|
|
564
|
+
</ol>
|
|
565
|
+
|
|
566
|
+
<h3>Phase 1 Step Types</h3>
|
|
567
|
+
<table class="table table-sm">
|
|
568
|
+
<thead><tr><th>Step</th><th>What it does</th><th>Config fields</th></tr></thead>
|
|
569
|
+
<tbody>
|
|
570
|
+
<tr>
|
|
571
|
+
<td><code>updateField</code></td>
|
|
572
|
+
<td>Set a field on the entry to a new value</td>
|
|
573
|
+
<td><code>field</code>, <code>value</code></td>
|
|
574
|
+
</tr>
|
|
575
|
+
<tr>
|
|
576
|
+
<td><code>deleteEntry</code></td>
|
|
577
|
+
<td>Permanently delete the entry</td>
|
|
578
|
+
<td>None</td>
|
|
579
|
+
</tr>
|
|
580
|
+
<tr>
|
|
581
|
+
<td><code>moveToCollection</code></td>
|
|
582
|
+
<td>Create the entry in a target collection then delete it from the source</td>
|
|
583
|
+
<td><code>targetCollection</code></td>
|
|
584
|
+
</tr>
|
|
585
|
+
<tr>
|
|
586
|
+
<td><code>webhook</code></td>
|
|
587
|
+
<td>HTTP request to an external URL</td>
|
|
588
|
+
<td><code>url</code>, <code>method</code>, <code>body</code> (JSON)</td>
|
|
589
|
+
</tr>
|
|
590
|
+
<tr>
|
|
591
|
+
<td><code>email</code></td>
|
|
592
|
+
<td>Send an email via the configured SMTP transport</td>
|
|
593
|
+
<td><code>to</code>, <code>subject</code>, <code>template</code></td>
|
|
594
|
+
</tr>
|
|
595
|
+
</tbody>
|
|
596
|
+
</table>
|
|
597
|
+
|
|
598
|
+
<h3>Template Variables</h3>
|
|
599
|
+
<p>Step config fields support <code>{{variable}}</code> interpolation:</p>
|
|
600
|
+
<table class="table table-sm">
|
|
601
|
+
<thead><tr><th>Variable</th><th>Resolves to</th></tr></thead>
|
|
602
|
+
<tbody>
|
|
603
|
+
<tr><td><code>{{entry.data.fieldName}}</code></td><td>A field value from the current entry</td></tr>
|
|
604
|
+
<tr><td><code>{{entry.id}}</code></td><td>The entry's ID</td></tr>
|
|
605
|
+
<tr><td><code>{{now}}</code></td><td>Current timestamp (ISO 8601)</td></tr>
|
|
606
|
+
<tr><td><code>{{user.name}}</code></td><td>Name of the user who triggered the action</td></tr>
|
|
607
|
+
<tr><td><code>{{user.email}}</code></td><td>Email of the triggering user</td></tr>
|
|
608
|
+
<tr><td><code>{{env.CMS_PUBLIC_*}}</code></td><td>Environment variables prefixed <code>CMS_PUBLIC_</code> only</td></tr>
|
|
609
|
+
</tbody>
|
|
610
|
+
</table>
|
|
611
|
+
<p><strong>Example</strong> — approve an application and notify by email:</p>
|
|
612
|
+
<pre class="code-block"><code>Step 1: updateField field=status value=approved
|
|
613
|
+
Step 2: updateField field=approvedAt value={{now}}
|
|
614
|
+
Step 3: email to={{entry.data.email}}
|
|
615
|
+
subject=Your application has been approved
|
|
616
|
+
template=Congratulations {{entry.data.name}}, your application is approved.</code></pre>
|
|
617
|
+
|
|
618
|
+
<h3>Partial Execution</h3>
|
|
619
|
+
<p>Actions are <strong>not transactional</strong>. If a step fails, the action stops and returns the
|
|
620
|
+
number of steps completed so far (<code>stepsCompleted</code>). Steps that already ran are
|
|
621
|
+
<strong>not rolled back</strong>. Design step order with this in mind — put irreversible steps
|
|
622
|
+
(delete, email) last.</p>
|
|
623
|
+
|
|
624
|
+
<h3>After a deleteEntry step</h3>
|
|
625
|
+
<p>If an action contains a <code>deleteEntry</code> step, subsequent steps will fail because the entry
|
|
626
|
+
no longer exists. Place <code>deleteEntry</code> as the last step.</p>
|
|
369
627
|
</div>
|
|
370
628
|
</div>
|
|
371
629
|
|