domma-cms 0.66.0 → 0.69.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +64 -1
- package/README.md +14 -10
- package/admin/css/admin.css +1 -1
- package/admin/index.html +1 -0
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +4 -4
- package/admin/js/lib/analytics-shape.js +1 -0
- package/admin/js/lib/contacts-arrange.js +1 -0
- package/admin/js/lib/help-popover.js +1 -0
- package/admin/js/lib/notes-arrange.js +1 -0
- package/admin/js/lib/plugin-accent.js +1 -1
- package/admin/js/lib/plugin-chrome.js +1 -1
- package/admin/js/lib/sidebar-grouping.js +1 -1
- package/admin/js/lib/sidebar-grouping.test.js +1 -1
- package/admin/js/lib/sidebar-renderer.js +3 -3
- package/admin/js/lib/todo-arrange.js +1 -0
- package/admin/js/lib/tool-kit.js +1 -0
- package/admin/js/templates/analytics.html +138 -0
- package/admin/js/templates/contacts.html +156 -0
- package/admin/js/templates/notes.html +137 -0
- package/admin/js/templates/plugin-marketplace.html +17 -4
- package/admin/js/templates/plugins.html +13 -7
- package/admin/js/templates/theme.html +38 -0
- package/admin/js/templates/todo.html +113 -0
- package/admin/js/views/analytics.js +62 -0
- package/admin/js/views/contacts.js +174 -0
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/notes.js +104 -0
- package/admin/js/views/plugin-marketplace.js +1 -1
- package/admin/js/views/plugins.js +24 -22
- package/admin/js/views/theme.js +1 -1
- package/admin/js/views/todo.js +96 -0
- package/bin/cli.js +4 -10
- package/bin/lib/plugin-version.js +28 -0
- package/bin/update.js +14 -0
- package/config/menus/admin-sidebar.json +1 -1
- package/config/server.json +3 -1
- package/package.json +3 -7
- package/plugins/_lib/admin/mail/reader-view.js +20 -0
- package/plugins/_lib/mail/store.js +21 -1
- package/plugins/blog/CLAUDE.md +237 -0
- package/plugins/blog/admin/css/index.css +178 -1
- package/plugins/blog/admin/templates/blog.html +35 -53
- package/plugins/blog/admin/templates/categories.html +19 -6
- package/plugins/blog/admin/templates/comments.html +26 -9
- package/plugins/blog/admin/templates/post-editor.html +36 -13
- package/plugins/blog/admin/templates/settings.html +2 -11
- package/plugins/blog/admin/views/blog.js +288 -162
- package/plugins/blog/admin/views/categories.js +212 -201
- package/plugins/blog/admin/views/comments.js +207 -158
- package/plugins/blog/admin/views/kit.js +372 -0
- package/plugins/blog/admin/views/post-editor.js +269 -21
- package/plugins/blog/admin/views/settings-cog.js +56 -0
- package/plugins/blog/admin/views/settings.js +16 -86
- package/plugins/blog/blocks/blog-card-compact.css +17 -0
- package/plugins/blog/blocks/blog-card-compact.html +8 -0
- package/plugins/blog/blocks/blog-card-row.css +22 -0
- package/plugins/blog/blocks/blog-card-row.html +11 -0
- package/plugins/blog/blocks/blog-card.css +35 -0
- package/plugins/blog/blocks/blog-card.html +16 -0
- package/plugins/blog/blocks/blog-post-classic.css +15 -0
- package/plugins/blog/blocks/blog-post-classic.html +28 -0
- package/plugins/blog/blocks/blog-post-feature.css +20 -0
- package/plugins/blog/blocks/blog-post-feature.html +30 -0
- package/plugins/blog/blocks/blog-post-minimal.css +10 -0
- package/plugins/blog/blocks/blog-post-minimal.html +23 -0
- package/plugins/blog/blocks/blog-post-sidebar.css +22 -0
- package/plugins/blog/blocks/blog-post-sidebar.html +36 -0
- package/plugins/blog/collections/posts/schema.json +3 -1
- package/plugins/blog/config.js +6 -0
- package/plugins/blog/lib/layouts.js +304 -0
- package/plugins/blog/lib/page.js +158 -0
- package/plugins/blog/lib/render.js +119 -0
- package/plugins/blog/lib/samples.js +234 -0
- package/plugins/blog/plugin.js +225 -15
- package/plugins/blog/plugin.json +21 -81
- package/plugins/blog/plugin.public.js +115 -210
- package/plugins/blog/public/blog.css +177 -0
- package/plugins/blog/public/blog.js +586 -0
- package/plugins/blog/public/samples/aurora.svg +7 -0
- package/plugins/blog/public/samples/dusk.svg +7 -0
- package/plugins/blog/public/samples/ember.svg +7 -0
- package/plugins/blog/public/samples/harbour.svg +7 -0
- package/plugins/blog/public/samples/meadow.svg +7 -0
- package/plugins/blog/public/samples/rosewood.svg +7 -0
- package/plugins/blog/templates/index.html +9 -8
- package/plugins/blog/templates/post.html +4 -17
- package/plugins/blog/tests/layouts.test.js +97 -0
- package/plugins/blog/tests/public.test.js +71 -0
- package/plugins/free-tier.lock.json +74 -0
- package/plugins/mail-reader/CLAUDE.md +78 -0
- package/plugins/mail-reader/plugin.json +2 -1
- package/public/css/theme-switcher.css +1 -0
- package/public/js/analytics.js +1 -0
- package/public/js/theme-switcher.js +1 -0
- package/scripts/build.js +41 -2
- package/scripts/run-tests.mjs +94 -0
- package/{plugins/analytics/plugin.js → server/routes/api/analytics.js} +89 -41
- package/{plugins/contacts/plugin.js → server/routes/api/contacts.js} +71 -43
- package/server/routes/api/dashboard.js +8 -2
- package/{plugins/notes/plugin.js → server/routes/api/notes.js} +61 -17
- package/server/routes/api/plugin-marketplace.js +78 -23
- package/server/routes/api/plugins.js +148 -3
- package/server/routes/api/todo.js +178 -0
- package/server/server.js +61 -1
- package/server/services/collections.js +13 -3
- package/server/services/managerClient.js +72 -136
- package/server/services/markdown.js +54 -1
- package/server/services/permissionRegistry.js +50 -0
- package/server/services/pluginEntitlement.js +171 -0
- package/server/services/pluginEnvelope.js +242 -0
- package/server/services/pluginInstaller.js +246 -26
- package/server/services/pluginScaffold.js +5 -0
- package/server/services/plugins.js +117 -7
- package/server/services/presetCollections.js +344 -0
- package/server/services/promoted-plugins-migration.js +254 -0
- package/server/services/publicCors.js +46 -0
- package/server/services/renderer.js +83 -3
- package/server/services/sidebarBadges.js +37 -0
- package/server/services/siteGitignore.js +310 -0
- package/server/services/themeSettings.js +39 -0
- package/config/theme.json +0 -18
- package/plugins/analytics/admin/css/index.css +0 -1
- package/plugins/analytics/admin/templates/analytics.html +0 -70
- package/plugins/analytics/admin/views/analytics.js +0 -176
- package/plugins/analytics/config.js +0 -14
- package/plugins/analytics/plugin.json +0 -60
- package/plugins/analytics/public/inject-body.html +0 -60
- package/plugins/analytics/public/inject-head.html +0 -1
- package/plugins/blog/templates/author.html +0 -9
- package/plugins/blog/templates/category.html +0 -9
- package/plugins/blog/templates/tag.html +0 -9
- package/plugins/contacts/admin/templates/contacts.html +0 -254
- package/plugins/contacts/admin/views/contacts.js +0 -943
- package/plugins/contacts/collections/user-contact-groups/schema.json +0 -35
- package/plugins/contacts/collections/user-contacts/schema.json +0 -179
- package/plugins/contacts/config.js +0 -6
- package/plugins/contacts/plugin.json +0 -36
- package/plugins/demo-viewer/config.js +0 -4
- package/plugins/demo-viewer/plugin.js +0 -36
- package/plugins/demo-viewer/plugin.json +0 -9
- package/plugins/invoice/admin/css/index.css +0 -1
- package/plugins/invoice/admin/templates/editor.html +0 -220
- package/plugins/invoice/admin/templates/index.html +0 -173
- package/plugins/invoice/admin/templates/issuers.html +0 -2
- package/plugins/invoice/admin/templates/receivers.html +0 -2
- package/plugins/invoice/admin/views/contacts-source.js +0 -266
- package/plugins/invoice/admin/views/editor.js +0 -434
- package/plugins/invoice/admin/views/export.js +0 -199
- package/plugins/invoice/admin/views/help-content.js +0 -61
- package/plugins/invoice/admin/views/index.js +0 -643
- package/plugins/invoice/admin/views/issuers.js +0 -30
- package/plugins/invoice/admin/views/media.js +0 -172
- package/plugins/invoice/admin/views/party-view.js +0 -386
- package/plugins/invoice/admin/views/payments.js +0 -127
- package/plugins/invoice/admin/views/print.js +0 -130
- package/plugins/invoice/admin/views/receivers.js +0 -55
- package/plugins/invoice/admin/views/send.js +0 -212
- package/plugins/invoice/admin/views/settings.js +0 -594
- package/plugins/invoice/admin/views/view-lifecycle.js +0 -33
- package/plugins/invoice/collections/invoice-issuers/schema.json +0 -82
- package/plugins/invoice/collections/invoice-receivers/schema.json +0 -16
- package/plugins/invoice/collections/invoices/schema.json +0 -33
- package/plugins/invoice/config.js +0 -37
- package/plugins/invoice/pdf.js +0 -164
- package/plugins/invoice/plugin.js +0 -1456
- package/plugins/invoice/plugin.json +0 -86
- package/plugins/invoice/templates/_base.css +0 -1
- package/plugins/invoice/templates/classic-nologo.html +0 -100
- package/plugins/invoice/templates/classic.html +0 -91
- package/plugins/invoice/templates/invoice-print.html +0 -237
- package/plugins/invoice/templates/minimal.html +0 -99
- package/plugins/invoice/templates/modern-nologo.html +0 -114
- package/plugins/invoice/templates/modern.html +0 -113
- package/plugins/invoice/templates/templates.json +0 -11
- package/plugins/notes/admin/templates/notes.html +0 -83
- package/plugins/notes/admin/views/notes.js +0 -281
- package/plugins/notes/collections/user-notes/schema.json +0 -54
- package/plugins/notes/config.js +0 -6
- package/plugins/notes/plugin.json +0 -33
- package/plugins/surveys/admin/templates/audience.html +0 -47
- package/plugins/surveys/admin/templates/results.html +0 -58
- package/plugins/surveys/admin/templates/survey-editor.html +0 -141
- package/plugins/surveys/admin/templates/surveys.html +0 -25
- package/plugins/surveys/admin/views/audience.js +0 -301
- package/plugins/surveys/admin/views/results.js +0 -172
- package/plugins/surveys/admin/views/survey-editor.js +0 -211
- package/plugins/surveys/admin/views/surveys.js +0 -161
- package/plugins/surveys/collections/survey-contacts/schema.json +0 -13
- package/plugins/surveys/collections/survey-groups/schema.json +0 -11
- package/plugins/surveys/collections/survey-invites/schema.json +0 -16
- package/plugins/surveys/collections/surveys/schema.json +0 -23
- package/plugins/surveys/config.js +0 -8
- package/plugins/surveys/lib/audience.js +0 -37
- package/plugins/surveys/lib/campaigns.js +0 -43
- package/plugins/surveys/lib/ledger.js +0 -110
- package/plugins/surveys/lib/sending.js +0 -106
- package/plugins/surveys/lib/stats.js +0 -62
- package/plugins/surveys/lib/submit.js +0 -95
- package/plugins/surveys/lib/tokens.js +0 -28
- package/plugins/surveys/plugin.js +0 -174
- package/plugins/surveys/plugin.json +0 -65
- package/plugins/surveys/plugin.public.js +0 -149
- package/plugins/surveys/public/dist-shared.mjs +0 -1
- package/plugins/surveys/public/survey.css +0 -1
- package/plugins/surveys/public/survey.mjs +0 -1
- package/plugins/surveys/templates/survey-page.html +0 -63
- package/plugins/theme-switcher/admin/templates/theme-switcher.html +0 -86
- package/plugins/theme-switcher/admin/views/theme-switcher.js +0 -65
- package/plugins/theme-switcher/config.js +0 -10
- package/plugins/theme-switcher/plugin.js +0 -26
- package/plugins/theme-switcher/plugin.json +0 -74
- package/plugins/theme-switcher/public/inject-body.html +0 -153
- package/plugins/theme-switcher/public/inject-head.html +0 -260
- package/plugins/todo/admin/templates/todo.html +0 -158
- package/plugins/todo/admin/views/todo.js +0 -343
- package/plugins/todo/collections/todos/schema.json +0 -60
- package/plugins/todo/config.js +0 -7
- package/plugins/todo/plugin.js +0 -102
- package/plugins/todo/plugin.json +0 -33
- /package/{plugins/contacts/admin/css/index.css → admin/css/contacts.css} +0 -0
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"slug": "contacts-groups",
|
|
3
|
-
"title": "Contact Groups",
|
|
4
|
-
"description": "Groups for the Contacts plugin.",
|
|
5
|
-
"plugin": "contacts",
|
|
6
|
-
"fields": [
|
|
7
|
-
{
|
|
8
|
-
"name": "name",
|
|
9
|
-
"label": "Group Name",
|
|
10
|
-
"type": "text",
|
|
11
|
-
"required": true
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"api": {
|
|
15
|
-
"create": {
|
|
16
|
-
"enabled": true,
|
|
17
|
-
"access": "admin"
|
|
18
|
-
},
|
|
19
|
-
"read": {
|
|
20
|
-
"enabled": true,
|
|
21
|
-
"access": "admin"
|
|
22
|
-
},
|
|
23
|
-
"update": {
|
|
24
|
-
"enabled": false,
|
|
25
|
-
"access": "admin"
|
|
26
|
-
},
|
|
27
|
-
"delete": {
|
|
28
|
-
"enabled": false,
|
|
29
|
-
"access": "admin"
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"storage": {
|
|
33
|
-
"adapter": "file"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"slug": "contacts-contacts",
|
|
3
|
-
"title": "Contacts",
|
|
4
|
-
"description": "Contacts managed by the Contacts plugin.",
|
|
5
|
-
"plugin": "contacts",
|
|
6
|
-
"fields": [
|
|
7
|
-
{
|
|
8
|
-
"name": "name",
|
|
9
|
-
"label": "Name",
|
|
10
|
-
"type": "text",
|
|
11
|
-
"required": true
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"name": "email",
|
|
15
|
-
"label": "Email",
|
|
16
|
-
"type": "text",
|
|
17
|
-
"required": false
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"name": "phone",
|
|
21
|
-
"label": "Phone",
|
|
22
|
-
"type": "text",
|
|
23
|
-
"required": false
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"name": "groups",
|
|
27
|
-
"label": "Groups",
|
|
28
|
-
"type": "text",
|
|
29
|
-
"required": false
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"name": "notes",
|
|
33
|
-
"label": "Notes",
|
|
34
|
-
"type": "textarea",
|
|
35
|
-
"required": false
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"name": "favourite",
|
|
39
|
-
"label": "Favourite",
|
|
40
|
-
"type": "text",
|
|
41
|
-
"required": false
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"name": "company",
|
|
45
|
-
"label": "Company",
|
|
46
|
-
"type": "text",
|
|
47
|
-
"required": false
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"name": "jobTitle",
|
|
51
|
-
"label": "Job Title",
|
|
52
|
-
"type": "text",
|
|
53
|
-
"required": false
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"name": "website",
|
|
57
|
-
"label": "Website",
|
|
58
|
-
"type": "text",
|
|
59
|
-
"required": false
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"name": "vatNumber",
|
|
63
|
-
"label": "VAT Number",
|
|
64
|
-
"type": "text",
|
|
65
|
-
"required": false
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
"name": "companyNumber",
|
|
69
|
-
"label": "Company Number",
|
|
70
|
-
"type": "text",
|
|
71
|
-
"required": false
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"name": "reference",
|
|
75
|
-
"label": "Their Reference",
|
|
76
|
-
"type": "text",
|
|
77
|
-
"required": false
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
"name": "billingEmail",
|
|
81
|
-
"label": "Billing Email",
|
|
82
|
-
"type": "text",
|
|
83
|
-
"required": false
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
"name": "paymentTerms",
|
|
87
|
-
"label": "Payment Terms (days)",
|
|
88
|
-
"type": "number",
|
|
89
|
-
"required": false
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"name": "currency",
|
|
93
|
-
"label": "Preferred Currency",
|
|
94
|
-
"type": "text",
|
|
95
|
-
"required": false
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
"name": "addresses",
|
|
99
|
-
"label": "Addresses",
|
|
100
|
-
"type": "json",
|
|
101
|
-
"required": false
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
"name": "emails",
|
|
105
|
-
"label": "Additional Emails",
|
|
106
|
-
"type": "json",
|
|
107
|
-
"required": false
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
"name": "phones",
|
|
111
|
-
"label": "Additional Phones",
|
|
112
|
-
"type": "json",
|
|
113
|
-
"required": false
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
"name": "accountName",
|
|
117
|
-
"label": "Account Name",
|
|
118
|
-
"type": "text",
|
|
119
|
-
"required": false
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
"name": "bankName",
|
|
123
|
-
"label": "Bank",
|
|
124
|
-
"type": "text",
|
|
125
|
-
"required": false
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
"name": "sortCode",
|
|
129
|
-
"label": "Sort Code",
|
|
130
|
-
"type": "text",
|
|
131
|
-
"required": false
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
"name": "accountNumber",
|
|
135
|
-
"label": "Account Number",
|
|
136
|
-
"type": "text",
|
|
137
|
-
"required": false
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
"name": "iban",
|
|
141
|
-
"label": "IBAN",
|
|
142
|
-
"type": "text",
|
|
143
|
-
"required": false
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
"name": "bic",
|
|
147
|
-
"label": "BIC / SWIFT",
|
|
148
|
-
"type": "text",
|
|
149
|
-
"required": false
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
"name": "userId",
|
|
153
|
-
"label": "User ID",
|
|
154
|
-
"type": "text",
|
|
155
|
-
"required": false
|
|
156
|
-
}
|
|
157
|
-
],
|
|
158
|
-
"api": {
|
|
159
|
-
"create": {
|
|
160
|
-
"enabled": true,
|
|
161
|
-
"access": "admin"
|
|
162
|
-
},
|
|
163
|
-
"read": {
|
|
164
|
-
"enabled": true,
|
|
165
|
-
"access": "admin"
|
|
166
|
-
},
|
|
167
|
-
"update": {
|
|
168
|
-
"enabled": false,
|
|
169
|
-
"access": "admin"
|
|
170
|
-
},
|
|
171
|
-
"delete": {
|
|
172
|
-
"enabled": false,
|
|
173
|
-
"access": "admin"
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
"storage": {
|
|
177
|
-
"adapter": "file"
|
|
178
|
-
}
|
|
179
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "contacts",
|
|
3
|
-
"displayName": "Contacts",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"description": "Contact manager with groups, favourites, search, and import/export.",
|
|
6
|
-
"author": "Darryl Waterhouse",
|
|
7
|
-
"date": "2026-03-24",
|
|
8
|
-
"icon": "users",
|
|
9
|
-
"admin": {
|
|
10
|
-
"css": [
|
|
11
|
-
"admin/css/index.css"
|
|
12
|
-
],
|
|
13
|
-
"sidebar": [
|
|
14
|
-
{
|
|
15
|
-
"id": "contacts",
|
|
16
|
-
"text": "Contacts",
|
|
17
|
-
"icon": "users",
|
|
18
|
-
"url": "#/plugins/contacts",
|
|
19
|
-
"section": "#/plugins/contacts"
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
"routes": [
|
|
23
|
-
{
|
|
24
|
-
"path": "/plugins/contacts",
|
|
25
|
-
"view": "plugin-contacts",
|
|
26
|
-
"title": "Contacts - Domma CMS"
|
|
27
|
-
}
|
|
28
|
-
],
|
|
29
|
-
"views": {
|
|
30
|
-
"plugin-contacts": {
|
|
31
|
-
"entry": "contacts/admin/views/contacts.js?v=25e5dae4",
|
|
32
|
-
"exportName": "contactsView"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Demo Viewer Plugin
|
|
3
|
-
*
|
|
4
|
-
* Registers a [demo] shortcode that embeds interactive Domma JS demos via iframe.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* [demo src="elements/accordion" /]
|
|
8
|
-
* [demo src="effects/ambient" height="600px" title="Ambient Effect" /]
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
export default async function demoViewerPlugin(fastify, opts) {
|
|
12
|
-
const {hooks, settings} = opts;
|
|
13
|
-
const basePath = settings.basePath || '/public/demos';
|
|
14
|
-
const defaultHeight = settings.defaultHeight || '500px';
|
|
15
|
-
|
|
16
|
-
hooks.registerShortcode('demo', (attrStr, body, context) => {
|
|
17
|
-
const attrs = context.parseShortcodeAttrs(attrStr);
|
|
18
|
-
const src = attrs.src || '';
|
|
19
|
-
const height = attrs.height || defaultHeight;
|
|
20
|
-
const title = attrs.title || '';
|
|
21
|
-
const iframeSrc = `${basePath}/${src}.html`;
|
|
22
|
-
|
|
23
|
-
const titleBar = title
|
|
24
|
-
? `<div class="demo-viewer-title">${context.escapeAttr(title)}</div>`
|
|
25
|
-
: '';
|
|
26
|
-
|
|
27
|
-
return `<div class="demo-viewer">${titleBar}<iframe src="${context.escapeAttr(iframeSrc)}" style="width:100%;height:${context.escapeAttr(height)};border:none;border-radius:var(--dm-radius, 8px);background:var(--dm-surface, #1a1a2e);" loading="lazy" allowfullscreen></iframe></div>`;
|
|
28
|
-
}, {priority: 5});
|
|
29
|
-
|
|
30
|
-
hooks.registerSanitizeRules({
|
|
31
|
-
tags: ['iframe'],
|
|
32
|
-
attributes: {
|
|
33
|
-
iframe: ['src', 'height', 'width', 'style', 'loading', 'allowfullscreen']
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.invoice-hidden{display:none!important}.invoice-editor{align-items:flex-start}.invoice-editor-main{flex:1;min-width:0}.invoice-editor-side{width:300px;flex-shrink:0}@media(max-width:900px){.invoice-editor{flex-wrap:wrap}.invoice-editor-side{width:100%}}.invoice-num,.invoice-line-total{font-variant-numeric:tabular-nums}#line-items-table th{font-weight:600;font-size:.85em}#line-items-table td{vertical-align:middle}#line-items-table .form-input{padding:.35rem .5rem}#line-items-table th.invoice-col-desc{width:44%}#line-items-table th.invoice-col-qty{width:13%;text-align:right}#line-items-table th.invoice-col-price{width:17%;text-align:right}#line-items-table th.invoice-col-total{width:18%;text-align:right}#line-items-table th.invoice-col-remove{width:8%}#line-items-table td.invoice-line-total{text-align:right}#line-items-table input[type=number]{text-align:right;font-variant-numeric:tabular-nums}.li-remove{font-size:1.1em;line-height:1;padding:.15rem .5rem;min-width:1.9rem}.invoice-number-link{font-weight:600}.invoice-row-actions{display:flex;gap:.4rem}#invoices-table td .invoice-num{display:block;text-align:right}#invoices-table th:nth-child(5){text-align:right}#invoices-table th:last-child,#invoices-table td:last-child{text-align:right;width:3rem}.invoice-party-form{display:flex;flex-direction:column;gap:.75rem;padding:.5rem}.invoice-party-actions{display:flex;justify-content:flex-end;gap:.75rem;margin-top:.75rem}.stat-icon--danger{background:color-mix(in srgb,var(--dm-danger) 15%,transparent);color:var(--dm-danger)}.invoice-col-date,.invoice-col-method{width:22%}#payments-table th{font-weight:600;font-size:.85em}#payments-table td{vertical-align:middle}#payments-table td.invoice-line-total,#payments-table th.invoice-col-total{text-align:right}.invoice-balance strong{color:var(--dm-warning)}.invoice-balance.is-settled strong{color:var(--dm-success)}.invoice-toolbar .card-body{padding:.75rem 1rem}.invoice-toolbar-row{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.invoice-toolbar-row--sub{margin-top:.6rem;padding-top:.6rem;border-top:1px solid var(--dm-border);font-size:.85rem}.invoice-toolbar-spacer{flex:1 1 auto}.invoice-search{position:relative;display:flex;align-items:center;flex:1 1 260px;min-width:200px}.invoice-search>[data-icon],.invoice-search>svg{position:absolute;left:.6rem;color:var(--dm-text-muted);pointer-events:none}.invoice-search .form-input{padding-left:2rem}.invoice-filter-narrow{width:auto;min-width:9rem}.invoice-field{display:flex;align-items:center;gap:.35rem;color:var(--dm-text-muted);white-space:nowrap}.invoice-field .form-input{width:auto}.invoice-check{display:flex;align-items:center;gap:.35rem;white-space:nowrap;cursor:pointer}.invoice-matches{white-space:nowrap}.invoice-hint{margin:-.25rem 0 .75rem}.invoice-row-menu{font-size:1.1rem;line-height:1;padding:.15rem .55rem}.invoice-settings{padding:.25rem}.invoice-settings .tab-panel{padding-top:.75rem}.invoice-settings-form{margin-bottom:.5rem}.invoice-settings-inline{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.invoice-settings-inline .form-label{margin:0;white-space:nowrap}.invoice-settings-inline .form-select{width:auto;min-width:12rem}.invoice-panel-head{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;margin-bottom:.5rem;flex-wrap:wrap}.invoice-number-preview{font-family:var(--dm-font-mono, monospace);color:var(--dm-text-muted);margin-bottom:.25rem}.invoice-slideover-resizer{padding:0;position:absolute;left:0;top:0;bottom:0;width:6px;cursor:col-resize;z-index:2;background:transparent}.invoice-slideover-resizer:hover,.is-resizing>.invoice-slideover-resizer{background:var(--dm-primary);opacity:.7}.is-resizing{user-select:none;transition:none!important}.invoice-media-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:.6rem}.invoice-media-tile{display:flex;flex-direction:column;align-items:center;gap:.3rem;padding:.5rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md, 8px);background:var(--dm-surface);cursor:pointer}.invoice-media-tile:hover{border-color:var(--dm-primary)}.invoice-media-tile img{max-width:100%;max-height:72px;object-fit:contain}.invoice-media-tile span{font-size:.7rem;color:var(--dm-text-muted);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.invoice-logo-frame{display:flex;align-items:center;justify-content:center;min-height:110px;padding:.75rem;border:1px dashed var(--dm-border);border-radius:var(--dm-radius-md, 8px);background:var(--dm-background-alt)}.invoice-logo-preview{max-height:90px;max-width:100%;object-fit:contain}.invoice-media-row{display:flex;gap:.5rem;align-items:center}.invoice-media-row .form-input{flex:1 1 auto;min-width:0}.invoice-media-pick{flex:0 0 auto}.invoice-picker-filters{display:flex;gap:.5rem;margin-bottom:.6rem}.invoice-picker-filters .form-input{flex:1 1 auto}.invoice-picker-filters .form-select{width:auto}.invoice-picker-list{display:flex;flex-direction:column;gap:.2rem;max-height:60vh;overflow-y:auto}.invoice-picker-row{display:flex;align-items:baseline;gap:.6rem;width:100%;padding:.4rem .6rem;border:1px solid transparent;border-radius:var(--dm-radius-sm, 6px);background:transparent;text-align:left;cursor:pointer}.invoice-picker-row:hover{background:var(--dm-hover-bg, var(--dm-background-alt))}.invoice-picker-row.is-chosen{border-color:var(--dm-primary);background:color-mix(in srgb,var(--dm-primary) 10%,transparent)}.invoice-picker-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.invoice-picker-mail{color:var(--dm-text-muted);font-size:.8rem;white-space:nowrap}.invoice-picker-count{flex:1 1 auto}.invoice-recipient-actions{display:flex;gap:.5rem;margin-top:.35rem}.invoice-receiver-row{display:flex;gap:.5rem;align-items:center}.invoice-receiver-row .form-select{flex:1 1 auto;min-width:0}#kpi-outstanding{font-size:1.4rem;line-height:1.2;font-variant-numeric:tabular-nums}@media(max-width:1500px){#kpi-outstanding{font-size:1.15rem}}.invoice-empty{margin:.75rem 0 0;padding:.85rem 1rem;border:1px dashed var(--dm-border);border-radius:var(--dm-radius-md, 8px);text-align:center}.dm-plugin-body .card-header--quiet{background:transparent;border-bottom:0;padding:.65rem 1rem 0;min-height:0}.dm-plugin-body .card-header--quiet+.card-body{padding-top:.5rem}.invoice-cap{display:inline-flex;align-items:center;font-size:.7rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--dm-text-muted)}.invoice-kpi{cursor:pointer;transition:border-color .15s,transform .15s}.invoice-kpi:hover{border-color:var(--dm-primary);transform:translateY(-1px)}.invoice-kpi:active{transform:none}.invoice-setup{border-color:var(--dm-primary);margin-bottom:.75rem}.invoice-setup .card-body{display:flex;flex-direction:column;gap:.4rem}.invoice-setup p{margin:0}#btn-new-invoice:disabled{opacity:.5;cursor:not-allowed}.invoice-template-picker{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:.5rem;margin-bottom:.75rem}.invoice-template-card{display:flex;flex-direction:column;align-items:flex-start;gap:.2rem;padding:.6rem .75rem;text-align:left;background:var(--dm-surface);border:1px solid var(--dm-border);border-radius:var(--dm-radius-md, 8px);cursor:pointer}.invoice-template-card:hover{border-color:var(--dm-primary)}.invoice-template-card.is-chosen{border-color:var(--dm-primary);background:color-mix(in srgb,var(--dm-primary) 10%,transparent)}.invoice-template-name{font-size:.85rem}.invoice-template-desc{font-size:.72rem;color:var(--dm-text-muted);line-height:1.35}.invoice-template-tag{font-size:.6rem;margin-top:.15rem}.invoice-template-preview{width:100%;height:60vh;min-height:320px;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md, 8px);background:#fff}.invoice-template-preview.is-loading{opacity:.5}
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
Every value on this screen is bound. The view builds an observable per field
|
|
3
|
-
and one computed per derived number, then calls M.applyBindings once - there
|
|
4
|
-
is no render function, and no path by which the DOM and the totals can drift.
|
|
5
|
-
The heading is removed by the admin's plugin shell (dedupeHeading), so nothing
|
|
6
|
-
per-record is bound to it.
|
|
7
|
-
-->
|
|
8
|
-
<div class="view-header">
|
|
9
|
-
<h1>Invoice</h1>
|
|
10
|
-
<div class="view-header-actions">
|
|
11
|
-
<button id="btn-print" type="button" class="btn btn-secondary" data-if="isEdit.value" data-on-click="openPrint">
|
|
12
|
-
<span data-icon="printer"></span> Print
|
|
13
|
-
</button>
|
|
14
|
-
<button id="btn-pdf" type="button" class="btn btn-secondary" data-if="canPdf.value" data-on-click="downloadPdf">
|
|
15
|
-
<span data-icon="download"></span> Download PDF
|
|
16
|
-
</button>
|
|
17
|
-
<button id="btn-send" type="button" class="btn btn-secondary" data-if="isEdit.value" data-on-click="sendInvoice">
|
|
18
|
-
<span data-icon="mail"></span> Send
|
|
19
|
-
</button>
|
|
20
|
-
<button id="btn-save" type="button" class="btn btn-primary" data-on-click="save">
|
|
21
|
-
<span data-icon="save"></span> Save
|
|
22
|
-
</button>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
|
|
26
|
-
<div class="flex gap-4 invoice-editor">
|
|
27
|
-
|
|
28
|
-
<div class="invoice-editor-main">
|
|
29
|
-
|
|
30
|
-
<div class="card mb-3">
|
|
31
|
-
<div class="card-body">
|
|
32
|
-
<div class="grid grid-cols-2 gap-3">
|
|
33
|
-
<div>
|
|
34
|
-
<label class="form-label" for="f-number" data-help="Leave it blank and one is allocated when you save - per prefix, per year, never reused.">Invoice Number</label>
|
|
35
|
-
<input id="f-number" type="text" class="form-input font-mono" data-model="number.value" placeholder="auto-generated">
|
|
36
|
-
<div class="text-muted text-sm">Leave blank to auto-number</div>
|
|
37
|
-
</div>
|
|
38
|
-
<div>
|
|
39
|
-
<label class="form-label" for="f-status">Status</label>
|
|
40
|
-
<select id="f-status" class="form-select" data-model="status.value">
|
|
41
|
-
<option value="draft">Draft</option>
|
|
42
|
-
<option value="sent">Sent</option>
|
|
43
|
-
<option value="paid">Paid</option>
|
|
44
|
-
<option value="overdue">Overdue</option>
|
|
45
|
-
<option value="cancelled">Cancelled</option>
|
|
46
|
-
</select>
|
|
47
|
-
</div>
|
|
48
|
-
<div>
|
|
49
|
-
<label class="form-label" for="f-issue-date">Issue Date</label>
|
|
50
|
-
<!-- E.datePicker attaches to these; it writes ISO into the input and
|
|
51
|
-
fires input/change, so data-model keeps working. -->
|
|
52
|
-
<input id="f-issue-date" type="text" class="form-input" data-model="issueDate.value">
|
|
53
|
-
</div>
|
|
54
|
-
<div>
|
|
55
|
-
<label class="form-label" for="f-due-date" data-help="Filled in from your payment terms. Past this date a sent invoice reports itself overdue.">Due Date</label>
|
|
56
|
-
<input id="f-due-date" type="text" class="form-input" data-model="dueDate.value">
|
|
57
|
-
</div>
|
|
58
|
-
<div>
|
|
59
|
-
<label class="form-label" for="f-issuer" data-help="Which of your businesses is raising this. Manage them under the cog, in Issuers.">Issuer</label>
|
|
60
|
-
<select id="f-issuer" class="form-select"
|
|
61
|
-
data-options="issuers.value"
|
|
62
|
-
data-options-text="label"
|
|
63
|
-
data-options-value="id"
|
|
64
|
-
data-options-caption="'- select -'"
|
|
65
|
-
data-model="issuerId.value"></select>
|
|
66
|
-
</div>
|
|
67
|
-
<div>
|
|
68
|
-
<label class="form-label" for="f-receiver" data-help="Who you are billing. From Contacts imports one, with its company name, billing address and VAT number.">Receiver</label>
|
|
69
|
-
<div class="invoice-receiver-row">
|
|
70
|
-
<select id="f-receiver" class="form-select"
|
|
71
|
-
data-options="receivers.value"
|
|
72
|
-
data-options-text="label"
|
|
73
|
-
data-options-value="id"
|
|
74
|
-
data-options-caption="'- select -'"
|
|
75
|
-
data-model="receiverId.value"></select>
|
|
76
|
-
<button type="button" class="btn btn-sm btn-outline" data-if="canImport.value"
|
|
77
|
-
data-on-click="importReceiver" title="Create a receiver from a contact">
|
|
78
|
-
From Contacts
|
|
79
|
-
</button>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<div class="card mb-3">
|
|
87
|
-
<div class="card-header card-header--quiet flex justify-between items-center">
|
|
88
|
-
<span class="invoice-cap" data-help="Prices are NET - VAT is applied once, to the total. Right-click a row to duplicate, move or remove it.">Line items</span>
|
|
89
|
-
<button id="btn-add-line" type="button" class="btn btn-sm btn-outline" data-on-click="addLine">
|
|
90
|
-
<span data-icon="plus"></span> Add Line
|
|
91
|
-
</button>
|
|
92
|
-
</div>
|
|
93
|
-
<div class="card-body">
|
|
94
|
-
<table class="table mb-0" id="line-items-table">
|
|
95
|
-
<thead>
|
|
96
|
-
<tr>
|
|
97
|
-
<th class="invoice-col-desc">Description</th>
|
|
98
|
-
<th class="invoice-col-qty">Qty</th>
|
|
99
|
-
<th class="invoice-col-price">Unit (net)</th>
|
|
100
|
-
<th class="invoice-col-total">Total</th>
|
|
101
|
-
<th class="invoice-col-remove"></th>
|
|
102
|
-
</tr>
|
|
103
|
-
</thead>
|
|
104
|
-
<!-- key=id is required: it is what keeps a row's own input focused
|
|
105
|
-
and uncommitted while the row above it is deleted. -->
|
|
106
|
-
<tbody id="line-items-body" data-each="lineItems.value key=id">
|
|
107
|
-
<tr>
|
|
108
|
-
<td><input type="text" class="form-input" data-model="description.value" placeholder="Description"></td>
|
|
109
|
-
<td><input type="number" class="form-input" min="0" step="0.01" data-model="quantity.value"></td>
|
|
110
|
-
<td><input type="number" class="form-input" min="0" step="0.01" data-model="unitPrice.value"></td>
|
|
111
|
-
<td class="invoice-line-total" data-bind-text="lineTotalText.value"></td>
|
|
112
|
-
<td>
|
|
113
|
-
<button type="button" class="btn btn-sm btn-ghost li-remove" title="Remove"
|
|
114
|
-
data-on-click="$parent.removeLine($data)">×</button>
|
|
115
|
-
</td>
|
|
116
|
-
</tr>
|
|
117
|
-
</tbody>
|
|
118
|
-
</table>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<div class="card mb-3" data-if="isEdit.value">
|
|
123
|
-
<div class="card-header card-header--quiet flex justify-between items-center">
|
|
124
|
-
<span class="invoice-cap" data-help="Money received against this invoice. Settle the balance and the status moves to paid on its own.">Payments</span>
|
|
125
|
-
<button id="btn-record-payment" type="button" class="btn btn-sm btn-outline" data-on-click="recordPayment">
|
|
126
|
-
<span data-icon="plus"></span> Record Payment
|
|
127
|
-
</button>
|
|
128
|
-
</div>
|
|
129
|
-
<div class="card-body">
|
|
130
|
-
<table class="table mb-0" id="payments-table" data-if="hasPayments.value">
|
|
131
|
-
<thead>
|
|
132
|
-
<tr>
|
|
133
|
-
<th class="invoice-col-date">Date</th>
|
|
134
|
-
<th class="invoice-col-method">Method</th>
|
|
135
|
-
<th>Reference</th>
|
|
136
|
-
<th class="invoice-col-total">Amount</th>
|
|
137
|
-
<th class="invoice-col-remove"></th>
|
|
138
|
-
</tr>
|
|
139
|
-
</thead>
|
|
140
|
-
<tbody id="payments-body" data-each="payments.value key=id">
|
|
141
|
-
<tr>
|
|
142
|
-
<td data-bind-text="dateText"></td>
|
|
143
|
-
<td data-bind-text="methodText"></td>
|
|
144
|
-
<td data-bind-text="reference"></td>
|
|
145
|
-
<td class="invoice-line-total" data-bind-text="amountText.value"></td>
|
|
146
|
-
<td>
|
|
147
|
-
<button type="button" class="btn btn-sm btn-ghost li-remove" title="Remove"
|
|
148
|
-
data-on-click="$parent.removePayment($data)">×</button>
|
|
149
|
-
</td>
|
|
150
|
-
</tr>
|
|
151
|
-
</tbody>
|
|
152
|
-
</table>
|
|
153
|
-
<p class="text-muted text-sm mb-0" data-if="noPayments.value">Nothing recorded against this invoice yet.</p>
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
|
|
157
|
-
<div class="card mb-3">
|
|
158
|
-
<div class="card-header card-header--quiet"><span class="invoice-cap" data-help="Printed on the invoice under the totals. Payment instructions, a purchase order number, a thank you.">Notes</span></div>
|
|
159
|
-
<div class="card-body">
|
|
160
|
-
<textarea id="f-notes" class="form-textarea" rows="3" data-model="notes.value"
|
|
161
|
-
placeholder="Optional notes printed on the invoice"></textarea>
|
|
162
|
-
</div>
|
|
163
|
-
</div>
|
|
164
|
-
</div>
|
|
165
|
-
|
|
166
|
-
<div class="invoice-editor-side">
|
|
167
|
-
|
|
168
|
-
<div class="card mb-3">
|
|
169
|
-
<div class="card-header card-header--quiet"><span class="invoice-cap">Totals</span></div>
|
|
170
|
-
<div class="card-body">
|
|
171
|
-
<div class="flex justify-between mb-2">
|
|
172
|
-
<span class="text-muted">Subtotal</span>
|
|
173
|
-
<span class="invoice-num" data-bind-text="subtotalText.value"></span>
|
|
174
|
-
</div>
|
|
175
|
-
<div class="flex justify-between mb-2" id="vat-row" data-if="vatEnabled.value">
|
|
176
|
-
<span class="text-muted">VAT (<span data-bind-text="vatRate.value"></span>%)</span>
|
|
177
|
-
<span class="invoice-num" data-bind-text="vatText.value"></span>
|
|
178
|
-
</div>
|
|
179
|
-
<hr>
|
|
180
|
-
<div class="flex justify-between">
|
|
181
|
-
<strong>Total</strong>
|
|
182
|
-
<strong class="invoice-num" data-bind-text="totalText.value"></strong>
|
|
183
|
-
</div>
|
|
184
|
-
<div class="flex justify-between mt-2" data-if="hasPayments.value">
|
|
185
|
-
<span class="text-muted">Paid</span>
|
|
186
|
-
<span class="invoice-num" data-bind-text="paidText.value"></span>
|
|
187
|
-
</div>
|
|
188
|
-
<div class="flex justify-between mt-1 invoice-balance" data-if="hasPayments.value" data-bind-class="settled.value && 'is-settled'">
|
|
189
|
-
<strong data-bind-text="balanceLabel.value"></strong>
|
|
190
|
-
<strong class="invoice-num" data-bind-text="balanceText.value"></strong>
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
|
|
195
|
-
<div class="card mb-3">
|
|
196
|
-
<div class="card-header card-header--quiet"><span class="invoice-cap" data-help="One rate for the whole invoice, applied to the net total. Switch it off for a non-VAT invoice.">VAT</span></div>
|
|
197
|
-
<div class="card-body">
|
|
198
|
-
<!-- .form-checkbox is a WRAPPER in Domma; the class that styles the box
|
|
199
|
-
itself is .form-check-input (appearance:none, primary fill, tick). -->
|
|
200
|
-
<label class="form-check mb-2" for="f-vat-enabled">
|
|
201
|
-
<input id="f-vat-enabled" type="checkbox" class="form-check-input" data-model="vatEnabled.value">
|
|
202
|
-
<span class="form-check-label">Apply VAT</span>
|
|
203
|
-
</label>
|
|
204
|
-
<label class="form-label" for="f-vat-rate">Rate %</label>
|
|
205
|
-
<input id="f-vat-rate" type="number" min="0" max="100" step="0.01" class="form-input" data-model="vatRate.value">
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
|
|
209
|
-
<div class="card mb-3">
|
|
210
|
-
<div class="card-header card-header--quiet"><span class="invoice-cap" data-help="Set per invoice. The default for new ones lives under the cog, in Defaults.">Currency</span></div>
|
|
211
|
-
<div class="card-body">
|
|
212
|
-
<select id="f-currency" class="form-select" data-model="currency.value">
|
|
213
|
-
<option value="GBP">GBP - British Pound</option>
|
|
214
|
-
<option value="EUR">EUR - Euro</option>
|
|
215
|
-
<option value="USD">USD - US Dollar</option>
|
|
216
|
-
</select>
|
|
217
|
-
</div>
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
</div>
|