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,60 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "analytics",
|
|
3
|
-
"displayName": "Analytics",
|
|
4
|
-
"version": "2.1.0",
|
|
5
|
-
"description": "Page view analytics with daily trends, time-range filtering, top-pages table and CSV export. Honours Do-Not-Track and dedups per session.",
|
|
6
|
-
"author": "Darryl Waterhouse",
|
|
7
|
-
"date": "2026-05-04",
|
|
8
|
-
"icon": "chart-bar",
|
|
9
|
-
"admin": {
|
|
10
|
-
"css": [
|
|
11
|
-
"admin/css/index.css"
|
|
12
|
-
],
|
|
13
|
-
"sidebar": [
|
|
14
|
-
{
|
|
15
|
-
"id": "analytics",
|
|
16
|
-
"text": "Analytics",
|
|
17
|
-
"icon": "chart-bar",
|
|
18
|
-
"url": "#/plugins/analytics",
|
|
19
|
-
"section": "#/plugins/analytics"
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
"routes": [
|
|
23
|
-
{
|
|
24
|
-
"path": "/plugins/analytics",
|
|
25
|
-
"view": "plugin-analytics",
|
|
26
|
-
"title": "Analytics - Domma CMS"
|
|
27
|
-
}
|
|
28
|
-
],
|
|
29
|
-
"views": {
|
|
30
|
-
"plugin-analytics": {
|
|
31
|
-
"entry": "analytics/admin/views/analytics.js?v=28fcef99",
|
|
32
|
-
"exportName": "analyticsView"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"inject": {
|
|
37
|
-
"head": "public/inject-head.html",
|
|
38
|
-
"bodyEnd": "public/inject-body.html"
|
|
39
|
-
},
|
|
40
|
-
"scaffold": {
|
|
41
|
-
"reset": [
|
|
42
|
-
{
|
|
43
|
-
"path": "data/lifetime.json",
|
|
44
|
-
"content": "{}"
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"path": "data/daily.json",
|
|
48
|
-
"content": "{}"
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"path": "data/journeys.json",
|
|
52
|
-
"content": "{}"
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"path": "data/stats.json",
|
|
56
|
-
"content": "{}"
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<!-- analytics: page view tracker (DNT-aware, session-deduped) -->
|
|
2
|
-
<script>
|
|
3
|
-
(function () {
|
|
4
|
-
if (typeof fetch !== 'function') return;
|
|
5
|
-
|
|
6
|
-
// Preview renders are not visits. The editor previews a page into an
|
|
7
|
-
// iframe where location.pathname is the srcdoc document rather than any
|
|
8
|
-
// real URL, so tracking one both invents a page and inflates the counts.
|
|
9
|
-
if (window.__CMS_PREVIEW__) return;
|
|
10
|
-
|
|
11
|
-
var dnt = navigator.doNotTrack === '1'
|
|
12
|
-
|| window.doNotTrack === '1'
|
|
13
|
-
|| navigator.msDoNotTrack === '1';
|
|
14
|
-
if (dnt) return;
|
|
15
|
-
|
|
16
|
-
var url = window.location.pathname;
|
|
17
|
-
|
|
18
|
-
// Session-scoped anonymous ID - clears with the tab. Cookie-less.
|
|
19
|
-
var sid = '';
|
|
20
|
-
try {
|
|
21
|
-
sid = sessionStorage.getItem('dm_sid') || '';
|
|
22
|
-
if (!sid) {
|
|
23
|
-
sid = (crypto && crypto.randomUUID)
|
|
24
|
-
? crypto.randomUUID()
|
|
25
|
-
: (Date.now().toString(36) + Math.random().toString(36).slice(2, 10));
|
|
26
|
-
sessionStorage.setItem('dm_sid', sid);
|
|
27
|
-
}
|
|
28
|
-
} catch (e) {
|
|
29
|
-
// sessionStorage unavailable - proceed without sid
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Session dedup (one hit per URL per session)
|
|
33
|
-
try {
|
|
34
|
-
var key = 'dm_analytics_seen';
|
|
35
|
-
var seen = sessionStorage.getItem(key);
|
|
36
|
-
var list = seen ? seen.split('|') : [];
|
|
37
|
-
if (list.indexOf(url) !== -1) return;
|
|
38
|
-
list.push(url);
|
|
39
|
-
sessionStorage.setItem(key, list.join('|'));
|
|
40
|
-
} catch (e) {
|
|
41
|
-
// proceed anyway
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Strip query/fragment from referrer; only keep same-origin or external origin+path
|
|
45
|
-
var ref = '';
|
|
46
|
-
try {
|
|
47
|
-
if (document.referrer) {
|
|
48
|
-
var r = new URL(document.referrer);
|
|
49
|
-
ref = r.origin === window.location.origin ? r.pathname : (r.origin + r.pathname);
|
|
50
|
-
}
|
|
51
|
-
} catch (e) { /* ignore */ }
|
|
52
|
-
|
|
53
|
-
fetch('/api/plugins/analytics/hit', {
|
|
54
|
-
method: 'POST',
|
|
55
|
-
headers: { 'Content-Type': 'application/json' },
|
|
56
|
-
keepalive: true,
|
|
57
|
-
body: JSON.stringify({ url: url, sid: sid, ref: ref })
|
|
58
|
-
}).catch(function () { /* silent */ });
|
|
59
|
-
})();
|
|
60
|
-
</script>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<!-- analytics: head injection (empty - tracking is done via body script) -->
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
<div class="contacts-plugin">
|
|
2
|
-
|
|
3
|
-
<!-- Toolbar -->
|
|
4
|
-
<div class="toolbar mb-3" style="display:flex;align-items:center;gap:0.5rem;flex-wrap:wrap;">
|
|
5
|
-
<input id="contacts-search" type="text" class="form-input" placeholder="Search contacts…" style="width:220px;">
|
|
6
|
-
<select id="group-filter" class="form-input" style="width:160px;">
|
|
7
|
-
<option value="">All groups</option>
|
|
8
|
-
</select>
|
|
9
|
-
<button id="fav-toggle" class="btn btn-outline" title="Show favourites only">
|
|
10
|
-
<span data-icon="star"></span>
|
|
11
|
-
Favourites
|
|
12
|
-
</button>
|
|
13
|
-
<span style="flex:1;"></span>
|
|
14
|
-
<button id="export-btn" class="btn btn-outline">
|
|
15
|
-
<span data-icon="download"></span>
|
|
16
|
-
Export
|
|
17
|
-
</button>
|
|
18
|
-
<button id="import-btn" class="btn btn-outline">
|
|
19
|
-
<span data-icon="upload"></span>
|
|
20
|
-
Import
|
|
21
|
-
</button>
|
|
22
|
-
<input id="import-file" type="file" accept=".json" style="display:none;">
|
|
23
|
-
<button id="add-contact-btn" class="btn btn-primary">
|
|
24
|
-
<span data-icon="plus"></span>
|
|
25
|
-
Add Contact
|
|
26
|
-
</button>
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<!-- Stats bar -->
|
|
30
|
-
<div id="contacts-stats" class="mb-3" style="display:flex;gap:1.5rem;font-size:0.875rem;color:var(--dm-text-muted);">
|
|
31
|
-
<span>Total: <strong id="stat-total">0</strong></span>
|
|
32
|
-
<span>Groups: <strong id="stat-groups">0</strong></span>
|
|
33
|
-
<span>Favourites: <strong id="stat-favs">0</strong></span>
|
|
34
|
-
<span id="bulk-actions" style="display:none;margin-left:auto;">
|
|
35
|
-
<button id="bulk-delete-btn" class="btn btn-sm btn-danger">
|
|
36
|
-
<span data-icon="trash"></span>
|
|
37
|
-
Delete selected (<span id="selected-count">0</span>)
|
|
38
|
-
</button>
|
|
39
|
-
</span>
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
<!-- Groups panel -->
|
|
43
|
-
<div id="groups-panel" class="card mb-3">
|
|
44
|
-
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;cursor:pointer;" id="groups-panel-toggle">
|
|
45
|
-
<span><span data-icon="folder"></span> <strong>Manage Groups</strong></span>
|
|
46
|
-
<span data-icon="chevron-down" id="groups-chevron"></span>
|
|
47
|
-
</div>
|
|
48
|
-
<div id="groups-panel-body" class="card-body" style="display:none;">
|
|
49
|
-
<div style="display:flex;gap:0.5rem;margin-bottom:1rem;">
|
|
50
|
-
<input id="new-group-input" type="text" class="form-input" placeholder="New group name…"
|
|
51
|
-
style="flex:1;">
|
|
52
|
-
<button id="add-group-btn" class="btn btn-primary">
|
|
53
|
-
<span data-icon="plus"></span>
|
|
54
|
-
Add Group
|
|
55
|
-
</button>
|
|
56
|
-
</div>
|
|
57
|
-
<div id="groups-list">
|
|
58
|
-
<p class="text-muted">No groups yet. Add one above.</p>
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
<!-- Contact editor overlay -->
|
|
64
|
-
<div id="contact-editor" class="card mb-3" style="display:none;">
|
|
65
|
-
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
|
|
66
|
-
<strong id="editor-title">Add Contact</strong>
|
|
67
|
-
<button id="editor-cancel-btn" class="btn btn-sm btn-outline">Cancel</button>
|
|
68
|
-
</div>
|
|
69
|
-
<div class="card-body">
|
|
70
|
-
<div class="grid grid-cols-2" style="gap:1rem;">
|
|
71
|
-
<div class="form-group">
|
|
72
|
-
<label for="contact-name" class="form-label">Name <span style="color:var(--dm-danger)">*</span></label>
|
|
73
|
-
<input id="contact-name" type="text" class="form-input" placeholder="Full name">
|
|
74
|
-
</div>
|
|
75
|
-
<div class="form-group">
|
|
76
|
-
<label for="contact-email" class="form-label">Email</label>
|
|
77
|
-
<input id="contact-email" type="email" class="form-input" placeholder="email@example.com">
|
|
78
|
-
</div>
|
|
79
|
-
<div class="form-group">
|
|
80
|
-
<label for="contact-phone" class="form-label">Phone</label>
|
|
81
|
-
<input id="contact-phone" type="text" class="form-input" placeholder="+44 …">
|
|
82
|
-
</div>
|
|
83
|
-
<div class="form-group">
|
|
84
|
-
<label class="form-label">Groups</label>
|
|
85
|
-
<div id="contact-groups-display" style="min-height:38px;padding:0.375rem 0.75rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius);cursor:pointer;display:flex;flex-wrap:wrap;gap:0.25rem;align-items:center;">
|
|
86
|
-
<span class="text-muted" id="groups-placeholder">Select groups…</span>
|
|
87
|
-
</div>
|
|
88
|
-
<div id="groups-dropdown-list" class="card mt-1" style="display:none;max-height:180px;overflow-y:auto;position:absolute;z-index:100;min-width:200px;">
|
|
89
|
-
<div class="card-body" id="groups-dropdown-items" style="padding:0.25rem;"></div>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
<div class="form-group" style="grid-column:1/-1;">
|
|
93
|
-
<label for="contact-notes" class="form-label">Notes</label>
|
|
94
|
-
<textarea id="contact-notes" class="form-input" rows="3" placeholder="Optional notes…"></textarea>
|
|
95
|
-
</div>
|
|
96
|
-
<div class="form-group">
|
|
97
|
-
<label class="form-label" style="display:flex;align-items:center;gap:0.5rem;cursor:pointer;">
|
|
98
|
-
<input id="contact-favourite" type="checkbox" class="form-check-input">
|
|
99
|
-
Mark as favourite
|
|
100
|
-
</label>
|
|
101
|
-
</div>
|
|
102
|
-
</div>
|
|
103
|
-
<!-- Everything an invoice needs. Folded away because most contacts
|
|
104
|
-
are a name and a number, and the day you need a VAT number you
|
|
105
|
-
know where to look. -->
|
|
106
|
-
<div class="contacts-billing">
|
|
107
|
-
<button type="button" id="billing-toggle" class="contacts-billing-toggle">
|
|
108
|
-
<span data-icon="chevron-right" id="billing-chevron"></span>
|
|
109
|
-
<strong>Company, addresses & invoicing</strong>
|
|
110
|
-
<span class="text-muted text-sm" id="billing-summary"></span>
|
|
111
|
-
</button>
|
|
112
|
-
|
|
113
|
-
<div id="billing-body" class="contacts-billing-body">
|
|
114
|
-
<div class="grid grid-cols-2 contacts-field-grid">
|
|
115
|
-
<div class="form-group">
|
|
116
|
-
<label for="contact-company" class="form-label">Company</label>
|
|
117
|
-
<input id="contact-company" type="text" class="form-input" placeholder="Acme Ltd">
|
|
118
|
-
</div>
|
|
119
|
-
<div class="form-group">
|
|
120
|
-
<label for="contact-job-title" class="form-label">Job Title</label>
|
|
121
|
-
<input id="contact-job-title" type="text" class="form-input" placeholder="Finance Manager">
|
|
122
|
-
</div>
|
|
123
|
-
<div class="form-group">
|
|
124
|
-
<label for="contact-website" class="form-label">Website</label>
|
|
125
|
-
<input id="contact-website" type="text" class="form-input" placeholder="acme.co.uk">
|
|
126
|
-
</div>
|
|
127
|
-
<div class="form-group">
|
|
128
|
-
<label for="contact-billing-email" class="form-label">Billing Email</label>
|
|
129
|
-
<input id="contact-billing-email" type="email" class="form-input" placeholder="accounts@acme.co.uk">
|
|
130
|
-
<div class="text-muted text-sm">Where invoices go, if not the email above.</div>
|
|
131
|
-
</div>
|
|
132
|
-
<div class="form-group">
|
|
133
|
-
<label for="contact-vat-number" class="form-label">VAT Number</label>
|
|
134
|
-
<input id="contact-vat-number" type="text" class="form-input font-mono" placeholder="GB123456789">
|
|
135
|
-
</div>
|
|
136
|
-
<div class="form-group">
|
|
137
|
-
<label for="contact-company-number" class="form-label">Company Number</label>
|
|
138
|
-
<input id="contact-company-number" type="text" class="form-input font-mono" placeholder="01234567">
|
|
139
|
-
</div>
|
|
140
|
-
<div class="form-group">
|
|
141
|
-
<label for="contact-reference" class="form-label">Their Reference</label>
|
|
142
|
-
<input id="contact-reference" type="text" class="form-input" placeholder="PO-4471">
|
|
143
|
-
<div class="text-muted text-sm">Printed on their invoices, if they need one.</div>
|
|
144
|
-
</div>
|
|
145
|
-
<div class="form-group">
|
|
146
|
-
<label for="contact-payment-terms" class="form-label">Payment Terms</label>
|
|
147
|
-
<div class="flex items-center gap-2">
|
|
148
|
-
<input id="contact-payment-terms" type="number" min="0" max="365" class="form-input contacts-terms-input" placeholder="30">
|
|
149
|
-
<span class="text-muted text-sm">days</span>
|
|
150
|
-
</div>
|
|
151
|
-
</div>
|
|
152
|
-
<div class="form-group">
|
|
153
|
-
<label for="contact-currency" class="form-label">Preferred Currency</label>
|
|
154
|
-
<select id="contact-currency" class="form-select">
|
|
155
|
-
<option value="">Use the invoice default</option>
|
|
156
|
-
<option value="GBP">GBP - British Pound</option>
|
|
157
|
-
<option value="EUR">EUR - Euro</option>
|
|
158
|
-
<option value="USD">USD - US Dollar</option>
|
|
159
|
-
</select>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
|
|
163
|
-
<div class="contacts-repeater">
|
|
164
|
-
<div class="contacts-repeater-head">
|
|
165
|
-
<strong>Bank Details</strong>
|
|
166
|
-
<span class="text-muted text-sm">Printed on an invoice so it can be paid.</span>
|
|
167
|
-
</div>
|
|
168
|
-
<div class="grid grid-cols-2 contacts-field-grid">
|
|
169
|
-
<div class="form-group">
|
|
170
|
-
<label for="contact-account-name" class="form-label">Account Name</label>
|
|
171
|
-
<input id="contact-account-name" type="text" class="form-input" placeholder="Acme Ltd">
|
|
172
|
-
</div>
|
|
173
|
-
<div class="form-group">
|
|
174
|
-
<label for="contact-bank-name" class="form-label">Bank</label>
|
|
175
|
-
<input id="contact-bank-name" type="text" class="form-input" placeholder="Barclays">
|
|
176
|
-
</div>
|
|
177
|
-
<div class="form-group">
|
|
178
|
-
<label for="contact-sort-code" class="form-label">Sort Code</label>
|
|
179
|
-
<input id="contact-sort-code" type="text" class="form-input font-mono" placeholder="20-00-00" maxlength="8">
|
|
180
|
-
</div>
|
|
181
|
-
<div class="form-group">
|
|
182
|
-
<label for="contact-account-number" class="form-label">Account Number</label>
|
|
183
|
-
<input id="contact-account-number" type="text" class="form-input font-mono" placeholder="12345678" maxlength="8">
|
|
184
|
-
</div>
|
|
185
|
-
<div class="form-group">
|
|
186
|
-
<label for="contact-iban" class="form-label">IBAN</label>
|
|
187
|
-
<input id="contact-iban" type="text" class="form-input font-mono" placeholder="GB29 NWBK 6016 1331 9268 19">
|
|
188
|
-
</div>
|
|
189
|
-
<div class="form-group">
|
|
190
|
-
<label for="contact-bic" class="form-label">BIC / SWIFT</label>
|
|
191
|
-
<input id="contact-bic" type="text" class="form-input font-mono" placeholder="NWBKGB2L">
|
|
192
|
-
</div>
|
|
193
|
-
</div>
|
|
194
|
-
</div>
|
|
195
|
-
|
|
196
|
-
<div class="contacts-repeater" id="addresses-repeater">
|
|
197
|
-
<div class="contacts-repeater-head">
|
|
198
|
-
<strong>Addresses</strong>
|
|
199
|
-
<button type="button" class="btn btn-sm btn-outline" id="add-address-btn">
|
|
200
|
-
<span data-icon="plus"></span> Add Address
|
|
201
|
-
</button>
|
|
202
|
-
</div>
|
|
203
|
-
<div id="addresses-list"></div>
|
|
204
|
-
<p class="text-muted text-sm contacts-empty-row" id="addresses-empty">No address yet.</p>
|
|
205
|
-
</div>
|
|
206
|
-
|
|
207
|
-
<div class="contacts-repeater" id="emails-repeater">
|
|
208
|
-
<div class="contacts-repeater-head">
|
|
209
|
-
<strong>Additional Emails</strong>
|
|
210
|
-
<button type="button" class="btn btn-sm btn-outline" id="add-email-btn">
|
|
211
|
-
<span data-icon="plus"></span> Add Email
|
|
212
|
-
</button>
|
|
213
|
-
</div>
|
|
214
|
-
<div id="emails-list"></div>
|
|
215
|
-
<p class="text-muted text-sm contacts-empty-row" id="emails-empty">None.</p>
|
|
216
|
-
</div>
|
|
217
|
-
|
|
218
|
-
<div class="contacts-repeater" id="phones-repeater">
|
|
219
|
-
<div class="contacts-repeater-head">
|
|
220
|
-
<strong>Additional Phones</strong>
|
|
221
|
-
<button type="button" class="btn btn-sm btn-outline" id="add-phone-btn">
|
|
222
|
-
<span data-icon="plus"></span> Add Phone
|
|
223
|
-
</button>
|
|
224
|
-
</div>
|
|
225
|
-
<div id="phones-list"></div>
|
|
226
|
-
<p class="text-muted text-sm contacts-empty-row" id="phones-empty">None.</p>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
|
|
231
|
-
<div style="display:flex;gap:0.5rem;margin-top:1rem;">
|
|
232
|
-
<button id="editor-save-btn" class="btn btn-primary">
|
|
233
|
-
<span data-icon="save"></span>
|
|
234
|
-
<span id="editor-save-label">Save Contact</span>
|
|
235
|
-
</button>
|
|
236
|
-
<button id="editor-delete-btn" class="btn btn-danger" style="display:none;">
|
|
237
|
-
<span data-icon="trash"></span>
|
|
238
|
-
Delete
|
|
239
|
-
</button>
|
|
240
|
-
<button id="editor-cancel-btn2" class="btn btn-outline">Cancel</button>
|
|
241
|
-
</div>
|
|
242
|
-
</div>
|
|
243
|
-
</div>
|
|
244
|
-
|
|
245
|
-
<!-- Contacts table -->
|
|
246
|
-
<div id="contacts-table"></div>
|
|
247
|
-
|
|
248
|
-
<!-- Empty state -->
|
|
249
|
-
<div id="contacts-empty" style="display:none;text-align:center;padding:3rem 1rem;color:var(--dm-text-muted);">
|
|
250
|
-
<span data-icon="users" style="font-size:3rem;display:block;margin-bottom:1rem;"></span>
|
|
251
|
-
<p>No contacts yet. Click <strong>Add Contact</strong> to get started.</p>
|
|
252
|
-
</div>
|
|
253
|
-
|
|
254
|
-
</div>
|