domma-cms 0.93.0 → 0.94.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/admin/css/admin.css +1 -1
- package/admin/js/app.js +2 -2
- package/admin/js/templates/docs/api-actions.html +86 -64
- package/admin/js/templates/docs/api-authentication.html +159 -123
- package/admin/js/templates/docs/api-builder.html +197 -0
- package/admin/js/templates/docs/api-collections.html +199 -259
- package/admin/js/templates/docs/api-external.html +225 -0
- package/admin/js/templates/docs/api-forms.html +268 -0
- package/admin/js/templates/docs/api-layouts.html +70 -45
- package/admin/js/templates/docs/api-media.html +57 -80
- package/admin/js/templates/docs/api-navigation.html +66 -22
- package/admin/js/templates/docs/api-pages.html +109 -129
- package/admin/js/templates/docs/api-plugins.html +123 -61
- package/admin/js/templates/docs/api-scaffold.html +185 -0
- package/admin/js/templates/docs/api-settings.html +72 -64
- package/admin/js/templates/docs/api-users.html +74 -107
- package/admin/js/templates/docs/api-views.html +68 -54
- package/admin/js/templates/docs/components-howto.html +20 -17
- package/admin/js/templates/docs/components-reference.html +13 -16
- package/admin/js/templates/docs/components-rules.html +7 -6
- package/admin/js/templates/docs/components-walkthrough.html +19 -19
- package/admin/js/templates/docs/tutorial-crud.html +68 -38
- package/admin/js/templates/docs/tutorial-forms.html +51 -35
- package/admin/js/templates/docs/tutorial-plugin.html +132 -56
- package/admin/js/templates/docs/usage-actions.html +55 -14
- package/admin/js/templates/docs/usage-collections.html +108 -0
- package/admin/js/templates/docs/usage-cta-shortcode.html +14 -3
- package/admin/js/templates/docs/usage-dconfig.html +0 -3
- package/admin/js/templates/docs/usage-editions.html +213 -0
- package/admin/js/templates/docs/usage-media.html +22 -6
- package/admin/js/templates/docs/usage-navigation.html +74 -18
- package/admin/js/templates/docs/usage-pages.html +60 -20
- package/admin/js/templates/docs/usage-plugins.html +89 -17
- package/admin/js/templates/docs/usage-shortcodes.html +123 -70
- package/admin/js/templates/docs/usage-site-settings.html +50 -18
- package/admin/js/templates/docs/usage-tools.html +73 -0
- package/admin/js/templates/docs/usage-users-roles.html +99 -20
- package/admin/js/templates/docs/usage-views.html +36 -19
- package/admin/js/templates/documentation.html +153 -32
- package/admin/js/templates/plugin-guide.html +15 -0
- package/admin/js/templates/plugin-guides.html +21 -0
- package/admin/js/templates/pro-docs.html +53 -234
- package/admin/js/templates/tutorials.html +5 -4
- package/admin/js/views/doc-pages.js +1 -1
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/plugin-guides.js +5 -0
- package/bin/cli.js +6 -6
- package/package.json +1 -1
- package/plugins/blog/docs/guide.md +205 -0
- package/plugins/blog/plugin.json +1 -1
- package/plugins/feedback/docs/guide.md +95 -0
- package/plugins/feedback/plugin.json +1 -1
- package/plugins/free-tier.lock.json +16 -11
- package/plugins/mail-reader/docs/guide.md +147 -0
- package/plugins/mail-reader/plugin.json +1 -1
- package/plugins/security/docs/guide.md +170 -0
- package/plugins/security/plugin.json +1 -1
- package/plugins/shopping-cart/docs/guide.md +191 -0
- package/plugins/shopping-cart/plugin.json +1 -1
- package/server/routes/api/documentation.js +42 -0
- package/server/server.js +12 -0
- package/server/services/docs.js +13 -2
- package/server/services/pluginGuides.js +255 -0
- package/server/services/plugins.js +8 -0
|
@@ -1,259 +1,78 @@
|
|
|
1
1
|
<div class="view-header">
|
|
2
2
|
<h1><span data-icon="zap"></span> Pro Documentation</h1>
|
|
3
|
+
<a href="#/documentation" class="btn btn-ghost btn-sm"><span data-icon="arrow-left"></span> All usage topics</a>
|
|
3
4
|
</div>
|
|
4
5
|
|
|
5
6
|
<div class="tabs" id="pro-docs-tabs">
|
|
6
7
|
<div class="tab-list">
|
|
7
|
-
<button class="tab-item active">
|
|
8
|
+
<button class="tab-item active">What needs Pro</button>
|
|
9
|
+
<button class="tab-item">Views</button>
|
|
8
10
|
<button class="tab-item">Actions</button>
|
|
9
|
-
<button class="tab-item">CTA Shortcode</button>
|
|
10
11
|
</div>
|
|
12
|
+
|
|
11
13
|
<div class="tab-content">
|
|
12
14
|
|
|
13
|
-
<!--
|
|
15
|
+
<!-- What needs Pro -->
|
|
14
16
|
<div class="tab-panel active">
|
|
15
|
-
|
|
16
|
-
<div class="card card-collapsible mb-4">
|
|
17
|
-
<div class="card-header" role="button" tabindex="0">
|
|
18
|
-
<div class="card-header-content"><h2><span data-icon="eye"></span> What is a View?</h2></div>
|
|
19
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="card-body docs-body">
|
|
22
|
-
<p>A <strong>View</strong> is a saved MongoDB aggregation pipeline that runs against a collection and returns shaped results. Views are created under <strong>Data → Views</strong> and exposed via a REST endpoint that respects role-level and row-level access.</p>
|
|
23
|
-
<p>Views require a MongoDB connection configured in <code>config/connections.json</code>.</p>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<div class="card card-collapsible mb-4">
|
|
28
|
-
<div class="card-header" role="button" tabindex="0">
|
|
29
|
-
<div class="card-header-content"><h2><span data-icon="layers"></span> Allowed Pipeline Stages</h2></div>
|
|
30
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
31
|
-
</div>
|
|
17
|
+
<div class="card mb-4">
|
|
32
18
|
<div class="card-body docs-body">
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<p>Collections are prefixed <code>cms_</code> in MongoDB - use this prefix in <code>$lookup</code> <code>from</code> values.</p>
|
|
19
|
+
<p>Pro, for the data features, means one thing: a working <strong>MongoDB connection</strong>
|
|
20
|
+
(the <strong>Database connections</strong> tab on Data > Collections, stored in <code>config/connections.json</code>). With one, a site gets:</p>
|
|
21
|
+
<ul>
|
|
22
|
+
<li><strong>Actions</strong> - workflow buttons, transitions and <code>[cta]</code>. Without MongoDB,
|
|
23
|
+
Data > Actions says so and nothing can be run.</li>
|
|
24
|
+
<li><strong>MongoDB storage</strong> for any collection, chosen on its Storage tab. Moving a collection
|
|
25
|
+
either way keeps every entry's id.</li>
|
|
26
|
+
<li><strong>Notes and Todo on MongoDB</strong>, as their collections declare. A site whose files
|
|
27
|
+
still hold notes or to-dos stays on files until the Storage move settles it.</li>
|
|
28
|
+
</ul>
|
|
29
|
+
<p>Everything else works without it: collections on files, <strong>Views</strong> (a built-in
|
|
30
|
+
evaluator runs the same pipeline stages), forms, <code>[collection]</code> and <code>[view]</code>
|
|
31
|
+
displays, the Collection Browser, the API and API Builder.</p>
|
|
32
|
+
<p>Pro plugins (SEO Pro, Analytics Pro, Security Pro, Blog Pro and others) are a separate matter: they come
|
|
33
|
+
from the Marketplace with a licence. See <a href="#/docs/usage/editions">Editions & Licences</a> and
|
|
34
|
+
<a href="#/docs/plugins">Plugin guides</a>.</p>
|
|
50
35
|
</div>
|
|
51
36
|
</div>
|
|
37
|
+
</div>
|
|
52
38
|
|
|
53
|
-
|
|
54
|
-
<div class="card-header" role="button" tabindex="0">
|
|
55
|
-
<div class="card-header-content"><h2><span data-icon="code"></span> Example Pipeline</h2></div>
|
|
56
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
57
|
-
</div>
|
|
58
|
-
<div class="card-body docs-body">
|
|
59
|
-
<p>Match active entries and count related submissions:</p>
|
|
60
|
-
<pre class="code-block"><code>[
|
|
61
|
-
{ "$match": { "data.isActive": true } },
|
|
62
|
-
{
|
|
63
|
-
"$lookup": {
|
|
64
|
-
"from": "cms_feedback",
|
|
65
|
-
"localField": "_id",
|
|
66
|
-
"foreignField": "data.userId",
|
|
67
|
-
"as": "submissions"
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
{ "$addFields": { "submissionCount": { "$size": "$submissions" } } },
|
|
71
|
-
{ "$project": { "data.name": 1, "data.email": 1, "submissionCount": 1 } },
|
|
72
|
-
{ "$sort": { "submissionCount": -1 } }
|
|
73
|
-
]</code></pre>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<div class="card card-collapsible mb-4">
|
|
78
|
-
<div class="card-header" role="button" tabindex="0">
|
|
79
|
-
<div class="card-header-content"><h2><span data-icon="lock"></span> Access Control</h2></div>
|
|
80
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
81
|
-
</div>
|
|
82
|
-
<div class="card-body docs-body">
|
|
83
|
-
<table class="table table-sm">
|
|
84
|
-
<thead><tr><th>Setting</th><th>Description</th></tr></thead>
|
|
85
|
-
<tbody>
|
|
86
|
-
<tr><td>Allowed Roles</td><td>Which roles can call <code>GET /api/views/:slug/public</code></td></tr>
|
|
87
|
-
<tr><td>Public</td><td>No authentication required when checked</td></tr>
|
|
88
|
-
<tr><td>Row-Level - Owner</td><td>User sees only entries they created</td></tr>
|
|
89
|
-
<tr><td>Row-Level - Field Match</td><td>A specified entry field must match a user property</td></tr>
|
|
90
|
-
</tbody>
|
|
91
|
-
</table>
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
94
|
-
|
|
95
|
-
</div><!-- /Views tab -->
|
|
96
|
-
|
|
97
|
-
<!-- ── Actions tab ───────────────────────────────────── -->
|
|
39
|
+
<!-- Views -->
|
|
98
40
|
<div class="tab-panel">
|
|
99
|
-
|
|
100
|
-
<div class="card card-collapsible mb-4">
|
|
101
|
-
<div class="card-header" role="button" tabindex="0">
|
|
102
|
-
<div class="card-header-content"><h2><span data-icon="zap"></span> What is an Action?</h2></div>
|
|
103
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
104
|
-
</div>
|
|
105
|
-
<div class="card-body docs-body">
|
|
106
|
-
<p>An <strong>Action</strong> is a named sequence of steps that runs against a single collection entry. Actions are defined under <strong>Data → Actions</strong> and can be triggered from the entry list or via the <code>[cta]</code> shortcode on any public page.</p>
|
|
107
|
-
<p>Actions require a MongoDB connection configured in <code>config/connections.json</code>.</p>
|
|
108
|
-
<p>Steps run in order. If a step fails, execution stops and a partial result is returned with a <code>stepsCompleted</code> count.</p>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
|
|
112
|
-
<div class="card card-collapsible mb-4">
|
|
113
|
-
<div class="card-header" role="button" tabindex="0">
|
|
114
|
-
<div class="card-header-content"><h2><span data-icon="list"></span> Step Types</h2></div>
|
|
115
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
116
|
-
</div>
|
|
41
|
+
<div class="card mb-4">
|
|
117
42
|
<div class="card-body docs-body">
|
|
118
|
-
<
|
|
119
|
-
<
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
</table>
|
|
43
|
+
<p>A <strong>View</strong> is a saved pipeline over a collection (<code>$match</code>,
|
|
44
|
+
<code>$lookup</code>, <code>$sort</code>, <code>$project</code>, <code>$unwind</code>,
|
|
45
|
+
<code>$addFields</code>, <code>$group</code>, <code>$count</code>, <code>$skip</code>,
|
|
46
|
+
<code>$limit</code>). Views do <strong>not</strong> need MongoDB: a MongoDB collection runs a native
|
|
47
|
+
aggregation, any other runs the built-in evaluator.</p>
|
|
48
|
+
<p>Who may read a view is set on its Access tab: public, any listed role and everyone more senior, or -
|
|
49
|
+
with no roles - the admin tier. A row-level rule (Owner or Field match) shows each user only their
|
|
50
|
+
results.</p>
|
|
51
|
+
<p>Full guide: <a href="#/docs/usage/views">Views</a> and the <a href="#/docs/api/views">Views API</a>.</p>
|
|
128
52
|
</div>
|
|
129
53
|
</div>
|
|
54
|
+
</div>
|
|
130
55
|
|
|
131
|
-
|
|
132
|
-
<div class="card-header" role="button" tabindex="0">
|
|
133
|
-
<div class="card-header-content"><h2><span data-icon="tag"></span> Template Variables</h2></div>
|
|
134
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
135
|
-
</div>
|
|
136
|
-
<div class="card-body docs-body">
|
|
137
|
-
<p>All step field values support <code>{{...}}</code> interpolation:</p>
|
|
138
|
-
<table class="table table-sm">
|
|
139
|
-
<thead><tr><th>Variable</th><th>Value</th></tr></thead>
|
|
140
|
-
<tbody>
|
|
141
|
-
<tr><td><code>{{entry.data.fieldName}}</code></td><td>Any field from the target entry</td></tr>
|
|
142
|
-
<tr><td><code>{{entry.id}}</code></td><td>The entry's UUID</td></tr>
|
|
143
|
-
<tr><td><code>{{now}}</code></td><td>Current ISO 8601 timestamp</td></tr>
|
|
144
|
-
<tr><td><code>{{user.name}}</code></td><td>Name of the triggering user</td></tr>
|
|
145
|
-
<tr><td><code>{{user.email}}</code></td><td>Email of the triggering user</td></tr>
|
|
146
|
-
<tr><td><code>{{user.id}}</code></td><td>UUID of the triggering user</td></tr>
|
|
147
|
-
<tr><td><code>{{env.CMS_PUBLIC_*}}</code></td><td>Public environment variables</td></tr>
|
|
148
|
-
</tbody>
|
|
149
|
-
</table>
|
|
150
|
-
</div>
|
|
151
|
-
</div>
|
|
152
|
-
|
|
153
|
-
<div class="card card-collapsible mb-4">
|
|
154
|
-
<div class="card-header" role="button" tabindex="0">
|
|
155
|
-
<div class="card-header-content"><h2><span data-icon="code"></span> Step Examples</h2></div>
|
|
156
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
157
|
-
</div>
|
|
158
|
-
<div class="card-body docs-body">
|
|
159
|
-
<p><strong>updateField</strong> - mark an entry as approved:</p>
|
|
160
|
-
<pre class="code-block"><code>{ "field": "status", "value": "approved" }</code></pre>
|
|
161
|
-
<p><strong>webhook</strong> - notify an external service:</p>
|
|
162
|
-
<pre class="code-block"><code>{
|
|
163
|
-
"url": "https://hooks.example.com/notify",
|
|
164
|
-
"headers": { "X-Secret": "{{env.CMS_PUBLIC_HOOK_SECRET}}" }
|
|
165
|
-
}</code></pre>
|
|
166
|
-
<p><strong>email</strong> - send confirmation to applicant:</p>
|
|
167
|
-
<pre class="code-block"><code>{
|
|
168
|
-
"to": "{{entry.data.email}}",
|
|
169
|
-
"subject": "Your application was approved",
|
|
170
|
-
"body": "Hi {{entry.data.name}}, your application has been approved."
|
|
171
|
-
}</code></pre>
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
|
|
175
|
-
</div><!-- /Actions tab -->
|
|
176
|
-
|
|
177
|
-
<!-- ── CTA Shortcode tab ──────────────────────────────── -->
|
|
56
|
+
<!-- Actions -->
|
|
178
57
|
<div class="tab-panel">
|
|
179
|
-
|
|
180
|
-
<div class="card card-collapsible mb-4">
|
|
181
|
-
<div class="card-header" role="button" tabindex="0">
|
|
182
|
-
<div class="card-header-content"><h2><span data-icon="mouse-pointer"></span> What is the CTA shortcode?</h2></div>
|
|
183
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
184
|
-
</div>
|
|
185
|
-
<div class="card-body docs-body">
|
|
186
|
-
<p>The <code>[cta]</code> shortcode places an action-trigger button in any public page. Clicking it calls <code>POST /api/actions/:slug/public</code> with the entry ID, using the logged-in user's JWT.</p>
|
|
187
|
-
<p>If the user is not logged in, a warning toast is shown instead.</p>
|
|
188
|
-
</div>
|
|
189
|
-
</div>
|
|
190
|
-
|
|
191
|
-
<div class="card card-collapsible mb-4">
|
|
192
|
-
<div class="card-header" role="button" tabindex="0">
|
|
193
|
-
<div class="card-header-content"><h2><span data-icon="code"></span> Syntax & Attributes</h2></div>
|
|
194
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
195
|
-
</div>
|
|
196
|
-
<div class="card-body docs-body">
|
|
197
|
-
<p><strong>Wrapping form:</strong></p>
|
|
198
|
-
<pre class="code-block"><code>[cta action="slug" entry="entry-id" icon="check" confirm="Are you sure?"]Button label[/cta]</code></pre>
|
|
199
|
-
<p><strong>Self-closing form:</strong></p>
|
|
200
|
-
<pre class="code-block"><code>[cta action="slug" entry="entry-id" label="Button label" /]</code></pre>
|
|
201
|
-
<table class="table table-sm" style="margin-top:1rem;">
|
|
202
|
-
<thead><tr><th>Attribute</th><th>Required</th><th>Default</th><th>Description</th></tr></thead>
|
|
203
|
-
<tbody>
|
|
204
|
-
<tr><td><code>action</code></td><td>Yes</td><td>-</td><td>Action slug</td></tr>
|
|
205
|
-
<tr><td><code>entry</code></td><td>Yes</td><td>-</td><td>Entry UUID to act on</td></tr>
|
|
206
|
-
<tr><td><code>label</code></td><td>No</td><td><code>"Run"</code></td><td>Button text (self-closing only)</td></tr>
|
|
207
|
-
<tr><td><code>style</code></td><td>No</td><td><code>"primary"</code></td><td>primary · secondary · ghost · danger</td></tr>
|
|
208
|
-
<tr><td><code>icon</code></td><td>No</td><td>-</td><td>Domma icon name</td></tr>
|
|
209
|
-
<tr><td><code>size</code></td><td>No</td><td>-</td><td>sm · md · lg</td></tr>
|
|
210
|
-
<tr><td><code>confirm</code></td><td>No</td><td>-</td><td>Confirmation prompt before executing</td></tr>
|
|
211
|
-
</tbody>
|
|
212
|
-
</table>
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
|
|
216
|
-
<div class="card card-collapsible mb-4">
|
|
217
|
-
<div class="card-header" role="button" tabindex="0">
|
|
218
|
-
<div class="card-header-content"><h2><span data-icon="grid"></span> Collection Integration</h2></div>
|
|
219
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
220
|
-
</div>
|
|
221
|
-
<div class="card-body docs-body">
|
|
222
|
-
<p>Add per-entry buttons to any <code>[collection]</code> shortcode:</p>
|
|
223
|
-
<pre class="code-block"><code>[collection slug="applications" display="cards" title-field="name"
|
|
224
|
-
cta="approve-application"
|
|
225
|
-
cta-label="Approve"
|
|
226
|
-
cta-icon="check"
|
|
227
|
-
cta-style="primary"
|
|
228
|
-
cta-confirm="Approve this application?" /]</code></pre>
|
|
229
|
-
<table class="table table-sm" style="margin-top:1rem;">
|
|
230
|
-
<thead><tr><th>Attribute</th><th>Default</th><th>Description</th></tr></thead>
|
|
231
|
-
<tbody>
|
|
232
|
-
<tr><td><code>cta</code></td><td>-</td><td>Action slug - enables per-entry buttons</td></tr>
|
|
233
|
-
<tr><td><code>cta-label</code></td><td><code>"Run"</code></td><td>Button label</td></tr>
|
|
234
|
-
<tr><td><code>cta-icon</code></td><td>-</td><td>Domma icon name</td></tr>
|
|
235
|
-
<tr><td><code>cta-style</code></td><td><code>"primary"</code></td><td>Button variant</td></tr>
|
|
236
|
-
<tr><td><code>cta-confirm</code></td><td>-</td><td>Confirmation prompt</td></tr>
|
|
237
|
-
</tbody>
|
|
238
|
-
</table>
|
|
239
|
-
<p>All three display modes support CTA buttons: <strong>cards</strong> (card footer), <strong>list</strong> (inline), <strong>table</strong> (dedicated column).</p>
|
|
240
|
-
</div>
|
|
241
|
-
</div>
|
|
242
|
-
|
|
243
|
-
<div class="card card-collapsible mb-4">
|
|
244
|
-
<div class="card-header" role="button" tabindex="0">
|
|
245
|
-
<div class="card-header-content"><h2><span data-icon="book-open"></span> Full Reference</h2></div>
|
|
246
|
-
<span class="card-collapse-icon" data-icon="chevron-down"></span>
|
|
247
|
-
</div>
|
|
58
|
+
<div class="card mb-4">
|
|
248
59
|
<div class="card-body docs-body">
|
|
249
|
-
<p>
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
60
|
+
<p>An <strong>Action</strong> is a named sequence of steps (update a field, delete, move to or create in
|
|
61
|
+
another collection, webhook, email, notify) run against one entry. Actions need MongoDB.</p>
|
|
62
|
+
<ul>
|
|
63
|
+
<li>Any role the action lists is enough to run it, and everyone more senior. No roles means admins
|
|
64
|
+
only; a role the site does not have admits only the level-0 role.</li>
|
|
65
|
+
<li>A transition makes the action a workflow step, offered only in the states it starts from. An
|
|
66
|
+
interactive <code>[collection ... transitions]</code> shows the buttons that apply to each row,
|
|
67
|
+
including on a <code>scope="mine"</code> block. A move that no longer applies is refused with 409.</li>
|
|
68
|
+
<li>Steps are not rolled back if a later one fails - put deletes and emails last.</li>
|
|
69
|
+
</ul>
|
|
70
|
+
<p>Full guides: <a href="#/docs/usage/actions">Actions</a>,
|
|
71
|
+
<a href="#/docs/usage/cta-shortcode">CTA Shortcode</a> and the
|
|
72
|
+
<a href="#/docs/api/actions">Actions API</a>.</p>
|
|
253
73
|
</div>
|
|
254
74
|
</div>
|
|
75
|
+
</div>
|
|
255
76
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
</div><!-- .tab-content -->
|
|
259
|
-
</div><!-- .tabs -->
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
<div class="card-body">
|
|
29
29
|
<h3 style="margin-top:0;"><span data-icon="package"></span> Writing a Plugin</h3>
|
|
30
30
|
<p class="text-muted" style="margin-bottom:0;">
|
|
31
|
-
Extend the CMS with your own server routes, admin pages and page-injection snippets
|
|
32
|
-
|
|
31
|
+
Extend the CMS with your own server routes, admin pages and page-injection snippets:
|
|
32
|
+
the manifest, the Fastify entry point, switching it on and testing it.
|
|
33
33
|
</p>
|
|
34
34
|
</div>
|
|
35
35
|
</a>
|
|
@@ -50,8 +50,9 @@
|
|
|
50
50
|
|
|
51
51
|
<p class="text-muted" style="font-size:.9rem;">
|
|
52
52
|
Looking for reusable custom elements? See <a href="#/docs/components">Documentation → Components</a>.
|
|
53
|
-
For task-by-task usage, see <a href="#/documentation">
|
|
54
|
-
<a href="#/api-reference">API Reference</a
|
|
53
|
+
For task-by-task usage, see <a href="#/documentation">Documentation</a>; for the REST surface, see
|
|
54
|
+
<a href="#/api-reference">API Reference</a>; for installed Marketplace plugins, see
|
|
55
|
+
<a href="#/docs/plugins">Plugin guides</a>.
|
|
55
56
|
</p>
|
|
56
57
|
|
|
57
58
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mountScaffolder as i}from"../lib/crud-tutorial.js";function t(o,
|
|
1
|
+
import{mountScaffolder as i}from"../lib/crud-tutorial.js";function t(o,s){return{templateUrl:`/admin/js/templates/docs/${o}.html`,async onMount(e){typeof s=="function"&&s(e),Domma.icons.scan(),Domma.syntax.scan()}}}export const docViews={tutorialCrud:t("tutorial-crud",o=>{const s=o.find("#tutorial-scaffolder-mount").get(0);s&&i(s,null,null)}),tutorialPlugin:t("tutorial-plugin"),tutorialForms:t("tutorial-forms"),componentsReference:t("components-reference"),componentsHowto:t("components-howto"),componentsWalkthrough:t("components-walkthrough"),componentsRules:t("components-rules")};const a=["pages","media","navigation","dconfig","shortcodes","site-settings","plugins","users-roles","views","actions","cta-shortcode","editions","collections","tools"],c=["authentication","pages","settings","layouts","navigation","media","users","plugins","collections","views","actions","forms","scaffold","external","builder"],n=o=>o.split("-").map(s=>s.charAt(0).toUpperCase()+s.slice(1)).join("");for(const o of a)docViews["usage"+n(o)]=t(`usage-${o}`);for(const o of c)docViews["apiRef"+n(o)]=t(`api-${o}`);
|
package/admin/js/views/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{dashboardView as o}from"./dashboard.js";import{pagesView as i}from"./pages.js";import{pageEditorView as r}from"./page-editor.js";import{settingsView as t}from"./settings.js";import{themeView as e}from"./theme.js";import{notificationsView as m}from"./notifications.js";import{layoutsView as p}from"./layouts.js";import{mediaView as
|
|
1
|
+
import{dashboardView as o}from"./dashboard.js";import{pagesView as i}from"./pages.js";import{pageEditorView as r}from"./page-editor.js";import{settingsView as t}from"./settings.js";import{themeView as e}from"./theme.js";import{notificationsView as m}from"./notifications.js";import{layoutsView as p}from"./layouts.js";import{mediaView as n}from"./media.js";import{loginView as s}from"./login.js";import{usersView as f}from"./users.js";import{userEditorView as w}from"./user-editor.js";import{pluginsView as c}from"./plugins.js";import{pluginCodeView as V}from"./plugin-code.js";import{documentationView as d}from"./documentation.js";import{tutorialsView as a}from"./tutorials.js";import{docViews as l}from"./doc-pages.js";import{pluginGuidesView as u,pluginGuideView as E}from"./plugin-guides.js";import{apiReferenceView as g}from"./api-reference.js";import{collectionsView as v}from"./collections.js";import{collectionEditorView as b}from"./collection-editor.js";import{collectionEntriesView as h}from"./collection-entries.js";import{formsView as y}from"./forms.js";import{formEditorView as j}from"./form-editor.js";import{formSubmissionsView as k}from"./form-submissions.js";import{viewsListView as L}from"./views-list.js";import{viewEditorView as x}from"./view-editor.js";import{viewPreviewView as M}from"./view-preview.js";import{actionsListView as D}from"./actions-list.js";import{actionEditorView as G}from"./action-editor.js";import{proDocsView as P}from"./pro-docs.js";import{blocksView as R}from"./blocks.js";import{blockEditorView as S}from"./block-editor.js";import{componentsView as C}from"./components.js";import{componentEditorView as T}from"./component-editor.js";import{myProfileView as U}from"./my-profile.js";import{rolesView as q}from"./roles.js";import{roleEditorView as z}from"./role-editor.js";import{effectsView as A}from"./effects.js";import{searchView as B}from"./search.js";import{notesView as F}from"./notes.js";import{todoView as H}from"./todo.js";import{analyticsView as I}from"./analytics.js";import{seoView as J}from"./seo.js";import{contactsView as K}from"./contacts.js";import{menusView as N}from"./menus.js";import{contextMenusView as O}from"./context-menus.js";import{contextMenuEditorView as Q}from"./context-menu-editor.js";import{menuEditorView as W}from"./menu-editor.js";import{menuLocationsView as X}from"./menu-locations.js";import{projectsView as Y}from"./projects.js";import{projectDetailView as Z}from"./project-detail.js";import{projectSettingsView as _}from"./project-settings.js";import{apiTokensView as $}from"./api-tokens.js";import{apiEndpointsView as oo}from"./api-endpoints.js";import{apiEndpointEditorView as io}from"./api-endpoint-editor.js";const ro={templateUrl:"",async onMount(){location.hash="#/menus"}};export const views={projects:Y,projectDetail:Z,projectSettings:_,apiTokens:$,apiEndpoints:oo,apiEndpointEditor:io,dashboard:o,pages:i,pageEditor:r,settings:t,theme:e,layouts:p,media:n,login:s,users:f,userEditor:w,plugins:c,pluginCode:V,documentation:d,tutorials:a,apiReference:g,collections:v,collectionEditor:b,collectionEntries:h,forms:y,formEditor:j,formSubmissions:k,viewsList:L,viewEditor:x,viewPreview:M,actionsList:D,actionEditor:G,proDocs:P,blocks:R,blockEditor:S,components:C,componentEditor:T,myProfile:U,roles:q,roleEditor:z,effects:A,search:B,notes:F,todo:H,analytics:I,seo:J,contacts:K,notifications:m,menus:N,contextMenus:O,contextMenuEditor:Q,menuEditor:W,menuLocations:X,menusRedirect:ro,pluginGuides:u,pluginGuide:E,...l};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const a=t=>String(t??"").replace(/[&<>"']/g,n=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[n]),l=t=>/^[a-z0-9-]+$/i.test(String(t||""))?t:"package";export function parseGuideHash(t){const n=String(t||"").match(/^#\/docs\/plugins\/([^/?#]+)(?:\/([^/?#]+))?/);return n?{name:decodeURIComponent(n[1]),page:n[2]?decodeURIComponent(n[2]):null}:null}function d(){Domma.icons.scan(),Domma.syntax?.scan?.()}export const pluginGuidesView={templateUrl:"/admin/js/templates/plugin-guides.html",async onMount(t){const n=t.find("#pg-grid").get(0);let o=[];try{o=(await H.get("/api/documentation/plugins"))?.guides??[]}catch{o=[]}if(n?.isConnected){if(!o.length){t.find("#pg-empty").get(0)?.removeAttribute("hidden"),d();return}n.innerHTML=o.map(e=>{const s=e.pages.length>1?`<p class="pg-card-pages">${e.pages.map(p=>a(p.title)).join(" \xB7 ")}</p>`:"";return`<a href="#/docs/plugins/${encodeURIComponent(e.name)}" class="card pg-card">
|
|
2
|
+
<div class="card-body">
|
|
3
|
+
<h3><span data-icon="${a(l(e.icon))}"></span> ${a(e.displayName)}</h3>
|
|
4
|
+
<p class="text-muted">${a(e.description)}</p>${s}
|
|
5
|
+
</div></a>`}).join(""),d()}}},pluginGuideView={templateUrl:"/admin/js/templates/plugin-guide.html",async onMount(t){const n=parseGuideHash(location.hash),o=t.find("#pg-body").get(0);if(!n||!o)return;let e=null,s="";try{const i=`/api/documentation/plugins/${encodeURIComponent(n.name)}`+(n.page?`/${encodeURIComponent(n.page)}`:"");e=await H.get(i)}catch(i){s=i?.status===403||/403|forbidden/i.test(String(i?.message))?"Your role cannot use this plugin, so its guide is not shown.":"There is no guide here. The plugin may be disabled, or the page may have moved."}if(!o.isConnected)return;if(!e?.page){o.innerHTML=`<p class="text-muted">${a(s||"There is no guide here.")}</p><p><a href="#/docs/plugins">See all plugin guides</a></p>`,d();return}t.find("#pg-title").get(0).textContent=`${e.displayName} - ${e.page.title}`;const p=t.find("#pg-icon").get(0);p&&(p.innerHTML=`<span data-icon="${a(l(e.icon))}"></span>`),document.title=`${e.displayName} guide - Domma CMS`;const c=[e.version&&`Version ${e.version}`,e.tier==="free"?"Free plugin":e.tier==="paid"?"Paid plugin":""].filter(Boolean).join(" \xB7 ");if(t.find("#pg-meta").get(0).textContent=[c,e.description].filter(Boolean).join(" - "),e.toolUrl){const i=t.find("#pg-tool").get(0);i.setAttribute("href",e.toolUrl),t.find("#pg-tool-text").get(0).textContent=`Open ${e.displayName}`,i.removeAttribute("hidden")}if(e.pages.length>1){const i=t.find("#pg-pages").get(0);i.innerHTML=e.pages.map(g=>{const r=g.slug===e.page.slug;return`<a href="#/docs/plugins/${encodeURIComponent(e.name)}/${encodeURIComponent(g.slug)}" class="btn btn-sm ${r?"btn-secondary":"btn-ghost"}"${r?' aria-current="page"':""}>${a(g.title)}</a>`}).join(""),i.removeAttribute("hidden")}o.innerHTML=e.page.html,d()}};
|
package/bin/cli.js
CHANGED
|
@@ -24,14 +24,14 @@ const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
|
24
24
|
// Node version check
|
|
25
25
|
// ---------------------------------------------------------------------------
|
|
26
26
|
|
|
27
|
-
// The minimum comes from package.json `engines
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
// fleet is on the engines version.
|
|
27
|
+
// The minimum comes from package.json `engines`, and below it the CLI stops:
|
|
28
|
+
// scaffolding or updating on an older Node leaves a site that will not run.
|
|
29
|
+
// The fleet (the manager and every site it forks) runs on Node 24, so fleet
|
|
30
|
+
// rolls pass this check.
|
|
32
31
|
const NODE_RANGE = JSON.parse(readFileSync(path.join(PACKAGE_ROOT, 'package.json'), 'utf8')).engines?.node;
|
|
33
32
|
if (!nodeVersionOk(process.versions.node, NODE_RANGE)) {
|
|
34
|
-
console.
|
|
33
|
+
console.error(`\n ✗ Domma CMS requires Node.js ${minNodeMajor(NODE_RANGE)} or higher (this is ${process.versions.node}). Upgrade Node and run this again.\n`);
|
|
34
|
+
process.exit(1);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// ---------------------------------------------------------------------------
|