domma-cms 0.55.1 → 0.66.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/CLAUDE.md +130 -2
- package/README.md +4 -4
- package/admin/css/admin.css +1 -1
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +3 -3
- package/admin/js/lib/page-picker.js +1 -0
- package/admin/js/lib/plugin-accent.js +1 -0
- package/admin/js/lib/plugin-chrome.js +1 -0
- package/admin/js/lib/shortcode-context-menu.js +2 -2
- 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 +4 -4
- package/admin/js/lib/slideover-resizable.js +1 -0
- package/admin/js/templates/context-menu-editor.html +212 -0
- package/admin/js/templates/context-menus.html +16 -0
- package/admin/js/templates/plugin-code.html +1 -1
- package/{plugins/site-search/admin/templates/site-search.html → admin/js/templates/search.html} +50 -4
- package/admin/js/templates/settings.html +16 -97
- package/admin/js/templates/theme.html +173 -0
- package/admin/js/views/context-menu-editor.js +55 -0
- package/admin/js/views/context-menus.js +5 -0
- package/admin/js/views/form-editor.js +7 -7
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/plugin-marketplace.js +1 -1
- package/admin/js/views/plugins.js +25 -23
- package/admin/js/views/search.js +1 -0
- package/admin/js/views/settings.js +3 -3
- package/admin/js/views/theme.js +1 -0
- package/bin/cli.js +2 -0
- package/bin/update.js +13 -2
- package/config/menus/admin-sidebar.json +129 -23
- package/config/plugins.json +5 -5
- package/config/search.json +13 -0
- package/config/theme.json +18 -0
- package/package.json +12 -4
- package/plugins/_lib/admin/mail/compose-window.js +914 -0
- package/plugins/_lib/admin/mail/contacts.js +301 -0
- package/plugins/_lib/admin/mail/diagnostics-section.js +133 -0
- package/plugins/_lib/admin/mail/folder-tree.js +254 -0
- package/plugins/_lib/admin/mail/identity.js +480 -0
- package/plugins/_lib/admin/mail/image-senders-section.js +131 -0
- package/plugins/_lib/admin/mail/keyboard.js +136 -0
- package/plugins/_lib/admin/mail/mail.css +1 -0
- package/plugins/_lib/admin/mail/mail.html +71 -0
- package/plugins/_lib/admin/mail/panes.js +253 -0
- package/plugins/_lib/admin/mail/reader-view.js +4453 -0
- package/plugins/_lib/admin/mail/resizable.js +26 -0
- package/plugins/_lib/admin/mail/rules.js +343 -0
- package/plugins/_lib/admin/mail/scheduling.js +203 -0
- package/plugins/_lib/admin/mail/section-kit.js +277 -0
- package/plugins/_lib/admin/mail/templates.js +238 -0
- package/plugins/_lib/admin/mail/threads.js +200 -0
- package/plugins/_lib/admin/mail/vacation.js +269 -0
- package/plugins/_lib/admin/ui/help.css +1 -0
- package/plugins/_lib/admin/ui/help.js +174 -0
- package/plugins/_lib/admin/ui/resizable.js +151 -0
- package/plugins/_lib/dataStore.js +117 -0
- package/plugins/_lib/mail/accounts.js +919 -0
- package/plugins/_lib/mail/bodyTokens.js +101 -0
- package/plugins/_lib/mail/compose.js +256 -0
- package/plugins/_lib/mail/defaults.js +57 -0
- package/plugins/_lib/mail/diagnostics.js +154 -0
- package/plugins/_lib/mail/envelope.js +161 -0
- package/plugins/_lib/mail/folders.js +192 -0
- package/plugins/_lib/mail/handoff.js +274 -0
- package/plugins/_lib/mail/imapPool.js +293 -0
- package/plugins/_lib/mail/mbox.js +74 -0
- package/plugins/_lib/mail/pollSchedule.js +79 -0
- package/plugins/_lib/mail/poller.js +135 -0
- package/plugins/_lib/mail/priority.js +138 -0
- package/plugins/_lib/mail/readRoutes.js +680 -0
- package/plugins/_lib/mail/render.js +291 -0
- package/plugins/_lib/mail/ruleRunner.js +152 -0
- package/plugins/_lib/mail/scheduler.js +254 -0
- package/plugins/_lib/mail/secretbox.js +229 -0
- package/plugins/_lib/mail/send.js +396 -0
- package/plugins/_lib/mail/store.js +1002 -0
- package/plugins/_lib/mail/sync.js +292 -0
- package/plugins/_lib/mail/syncPlan.js +126 -0
- package/plugins/_lib/mail/syncSelection.js +82 -0
- package/plugins/_lib/mail/unsubscribe.js +183 -0
- package/plugins/_lib/mail/vacationRunner.js +114 -0
- package/plugins/_lib/mail/write.js +473 -0
- package/plugins/_lib/schemaSync.js +83 -0
- package/plugins/_template/admin/css/index.css +0 -0
- package/plugins/_template/admin/templates/index.html +4 -4
- package/plugins/_template/admin/views/index.js +7 -0
- package/plugins/analytics/admin/css/index.css +1 -0
- package/plugins/analytics/admin/templates/analytics.html +22 -13
- package/plugins/analytics/plugin.json +3 -0
- package/plugins/blog/admin/css/index.css +1 -0
- package/plugins/blog/admin/templates/blog.html +30 -18
- package/plugins/blog/admin/templates/categories.html +2 -2
- package/plugins/blog/admin/templates/comments.html +2 -2
- package/plugins/blog/admin/templates/post-editor.html +34 -34
- package/plugins/blog/admin/templates/settings.html +6 -3
- package/plugins/blog/admin/views/blog.js +8 -5
- package/plugins/blog/admin/views/categories.js +5 -10
- package/plugins/blog/admin/views/comments.js +5 -5
- package/plugins/blog/admin/views/post-editor.js +39 -20
- package/plugins/blog/admin/views/settings.js +52 -50
- package/plugins/blog/collections/categories/schema.json +7 -6
- package/plugins/blog/collections/comments/schema.json +11 -10
- package/plugins/blog/collections/posts/schema.json +14 -13
- package/plugins/blog/plugin.js +36 -13
- package/plugins/blog/plugin.json +13 -5
- package/plugins/blog/plugin.public.js +312 -0
- package/plugins/contacts/admin/css/index.css +1 -0
- package/plugins/contacts/admin/templates/contacts.html +128 -0
- package/plugins/contacts/admin/views/contacts.js +237 -4
- package/plugins/contacts/collections/user-contacts/schema.json +108 -0
- package/plugins/contacts/plugin.js +214 -27
- package/plugins/contacts/plugin.json +4 -1
- package/plugins/invoice/admin/css/index.css +1 -0
- package/plugins/invoice/admin/templates/editor.html +140 -49
- package/plugins/invoice/admin/templates/index.html +153 -23
- package/plugins/invoice/admin/templates/issuers.html +2 -5
- package/plugins/invoice/admin/templates/receivers.html +2 -5
- package/plugins/invoice/admin/views/contacts-source.js +266 -0
- package/plugins/invoice/admin/views/editor.js +366 -199
- package/plugins/invoice/admin/views/export.js +199 -0
- package/plugins/invoice/admin/views/help-content.js +61 -0
- package/plugins/invoice/admin/views/index.js +582 -94
- package/plugins/invoice/admin/views/issuers.js +24 -17
- package/plugins/invoice/admin/views/media.js +172 -0
- package/plugins/invoice/admin/views/party-view.js +305 -67
- package/plugins/invoice/admin/views/payments.js +127 -0
- package/plugins/invoice/admin/views/print.js +130 -0
- package/plugins/invoice/admin/views/receivers.js +49 -16
- package/plugins/invoice/admin/views/send.js +212 -0
- package/plugins/invoice/admin/views/settings.js +594 -0
- package/plugins/invoice/admin/views/view-lifecycle.js +33 -0
- package/plugins/invoice/collections/invoice-issuers/schema.json +77 -11
- package/plugins/invoice/collections/invoice-receivers/schema.json +10 -9
- package/plugins/invoice/collections/invoices/schema.json +19 -13
- package/plugins/invoice/config.js +27 -6
- package/plugins/invoice/pdf.js +164 -0
- package/plugins/invoice/plugin.js +1217 -44
- package/plugins/invoice/plugin.json +10 -9
- package/plugins/invoice/templates/_base.css +1 -0
- package/plugins/invoice/templates/classic-nologo.html +100 -0
- package/plugins/invoice/templates/classic.html +91 -0
- package/plugins/invoice/templates/invoice-print.html +24 -0
- package/plugins/invoice/templates/minimal.html +99 -0
- package/plugins/invoice/templates/modern-nologo.html +114 -0
- package/plugins/invoice/templates/modern.html +113 -0
- package/plugins/invoice/templates/templates.json +11 -0
- package/plugins/mail-reader/admin/views/mail.js +19 -0
- package/plugins/mail-reader/config.js +7 -0
- package/plugins/mail-reader/plugin.js +48 -0
- package/plugins/mail-reader/plugin.json +33 -0
- package/plugins/notes/admin/views/notes.js +1 -1
- package/plugins/notes/plugin.json +2 -2
- package/plugins/surveys/lib/audience.js +37 -0
- package/plugins/surveys/lib/campaigns.js +43 -0
- package/plugins/surveys/lib/ledger.js +110 -0
- package/plugins/surveys/lib/sending.js +106 -0
- package/plugins/surveys/lib/stats.js +62 -0
- package/plugins/surveys/lib/submit.js +95 -0
- package/plugins/surveys/lib/tokens.js +28 -0
- package/plugins/surveys/plugin.public.js +149 -0
- package/plugins/theme-switcher/admin/templates/theme-switcher.html +1 -1
- package/public/css/forms.css +1 -1
- package/public/css/search.css +1 -0
- package/public/css/site.css +1 -1
- package/public/js/collection-context.js +2 -2
- package/public/js/context-menus.js +1 -0
- package/public/js/form-logic-engine.js +1 -1
- package/public/js/forms.js +2 -2
- package/public/js/search.js +1 -0
- package/public/js/site.js +1 -1
- package/scripts/build.js +37 -3
- package/scripts/copy-domma.js +48 -0
- package/scripts/seed.js +1996 -0
- package/server/routes/api/collections.js +34 -0
- package/server/routes/api/context-menus.js +104 -0
- package/server/routes/api/forms.js +42 -3
- package/server/routes/api/notifications.js +69 -19
- package/server/routes/api/plugins.js +50 -6
- package/server/routes/api/search.js +43 -0
- package/server/routes/api/theme.js +69 -0
- package/server/routes/public.js +42 -7
- package/server/server.js +74 -0
- package/server/services/adapters/FileAdapter.js +6 -1
- package/server/services/content.js +26 -0
- package/server/services/contextMenus.js +477 -0
- package/server/services/markdown.js +70 -9
- package/server/services/permissionRegistry.js +24 -0
- package/server/services/pluginFiles.js +52 -11
- package/server/services/plugins.js +229 -6
- package/server/services/renderer.js +144 -22
- package/server/services/roles.js +1 -1
- package/server/services/search-migration.js +82 -0
- package/server/services/search.js +413 -0
- package/server/services/sidebar-migration.js +1 -0
- package/server/services/themeSettings.js +541 -0
- package/server/services/users.js +8 -0
- package/server/templates/page.html +4 -2
- package/plugins/contacts/data/contacts.json +0 -20
- package/plugins/notes/data/notes.json +0 -1
- package/plugins/site-search/admin/views/site-search.js +0 -116
- package/plugins/site-search/config.js +0 -15
- package/plugins/site-search/plugin.js +0 -188
- package/plugins/site-search/plugin.json +0 -40
- package/plugins/site-search/public/inject-body.html +0 -17
- package/plugins/site-search/public/inject-head.html +0 -1
- package/plugins/site-search/public/search.css +0 -1
- package/plugins/site-search/public/search.js +0 -1
- package/plugins/todo/data/todos.json +0 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "invoice",
|
|
3
3
|
"displayName": "Invoices",
|
|
4
|
-
"version": "1.
|
|
5
|
-
"description": "
|
|
4
|
+
"version": "1.4.0",
|
|
5
|
+
"description": "Invoice generator. Issuer profiles, receivers importable from Contacts, line items, optional VAT, payments, archiving, CSV/Excel export, and a print-ready invoice you can email or download as a PDF.",
|
|
6
6
|
"author": "Darryl Waterhouse",
|
|
7
|
-
"date": "2026-
|
|
8
|
-
"icon": "
|
|
7
|
+
"date": "2026-09-21",
|
|
8
|
+
"icon": "receipt",
|
|
9
9
|
"admin": {
|
|
10
10
|
"css": [
|
|
11
|
-
"admin/css/index.css"
|
|
11
|
+
"admin/css/index.css",
|
|
12
|
+
"../_lib/admin/ui/help.css"
|
|
12
13
|
],
|
|
13
14
|
"sidebar": [
|
|
14
15
|
{
|
|
@@ -65,19 +66,19 @@
|
|
|
65
66
|
],
|
|
66
67
|
"views": {
|
|
67
68
|
"plugin-invoice-list": {
|
|
68
|
-
"entry": "invoice/admin/views/index.js?v=
|
|
69
|
+
"entry": "invoice/admin/views/index.js?v=350310c2",
|
|
69
70
|
"exportName": "indexView"
|
|
70
71
|
},
|
|
71
72
|
"plugin-invoice-editor": {
|
|
72
|
-
"entry": "invoice/admin/views/editor.js?v=
|
|
73
|
+
"entry": "invoice/admin/views/editor.js?v=78cd5797",
|
|
73
74
|
"exportName": "editorView"
|
|
74
75
|
},
|
|
75
76
|
"plugin-invoice-issuers": {
|
|
76
|
-
"entry": "invoice/admin/views/issuers.js?v=
|
|
77
|
+
"entry": "invoice/admin/views/issuers.js?v=e2dd5ab2",
|
|
77
78
|
"exportName": "issuersView"
|
|
78
79
|
},
|
|
79
80
|
"plugin-invoice-receivers": {
|
|
80
|
-
"entry": "invoice/admin/views/receivers.js?v=
|
|
81
|
+
"entry": "invoice/admin/views/receivers.js?v=ce0e3964",
|
|
81
82
|
"exportName": "receiversView"
|
|
82
83
|
}
|
|
83
84
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{color-scheme:light}*{box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;color:#222;background:#f3f3f3;margin:0;padding:24px;font-size:14px;line-height:1.5}.invoice{max-width:800px;margin:0 auto;background:#fff;padding:48px 56px;box-shadow:0 4px 20px #00000014}.top{display:flex;justify-content:space-between;align-items:flex-start;gap:24px;border-bottom:2px solid #e5e5e5;padding-bottom:24px;margin-bottom:32px}.logo{max-height:80px;max-width:240px;display:block;margin-bottom:12px}.meta{text-align:right}.meta h1{margin:0;font-size:28px;letter-spacing:1px;color:#000}.meta .number{font-size:18px;color:#555;margin-top:4px}.status{display:inline-block;padding:4px 10px;border-radius:4px;font-size:11px;font-weight:600;letter-spacing:.5px;background:#eee;color:#444;margin-top:8px}.parties{display:grid;grid-template-columns:1fr 1fr;gap:32px;margin-bottom:32px}.party h3{margin:0 0 8px;font-size:11px;text-transform:uppercase;letter-spacing:1px;color:#888}.party .name{font-weight:700;font-size:15px;margin-bottom:4px}.party .lines{color:#555;font-size:13px}table.items{width:100%;border-collapse:collapse;margin-bottom:24px}table.items th{text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:1px;color:#888;padding:8px 10px;border-bottom:2px solid #e5e5e5}table.items td{padding:10px;border-bottom:1px solid #f0f0f0}table.items td.num,table.items th.num{text-align:right}.totals{width:320px;margin-left:auto;margin-bottom:32px}.totals table{width:100%;border-collapse:collapse}.totals th{text-align:left;padding:8px 10px;font-weight:500;color:#555}.totals td.num{text-align:right;padding:8px 10px;font-variant-numeric:tabular-nums}.bank .pay{border-collapse:collapse;margin-top:6px}.bank .pay th{text-align:left;font-weight:400;color:#666;padding:2px 14px 2px 0;white-space:nowrap;vertical-align:top}.bank .pay td{padding:2px 0;font-variant-numeric:tabular-nums;font-weight:600}.bank .pay-notes{margin-top:6px}.totals .balance th,.totals .balance td{font-weight:700;border-top:1px solid #ddd}.totals .settled th,.totals .settled td{color:#197a3d}.totals .grand th,.totals .grand td{font-size:17px;font-weight:700;color:#000;border-top:2px solid #222;padding-top:12px}.footer{margin-top:32px;padding-top:16px;border-top:1px solid #e5e5e5;font-size:12px;color:#888}.notes,.bank{margin-top:24px;padding:12px 16px;background:#fafafa;border-radius:4px;font-size:13px}.muted{color:#999;font-style:italic;text-align:center}.actions{max-width:800px;margin:0 auto 16px;display:flex;justify-content:flex-end;gap:8px}.actions button{background:#222;color:#fff;border:0;padding:8px 16px;font-size:13px;border-radius:4px;cursor:pointer}@media print{body{background:#fff;padding:0}.invoice{box-shadow:none;padding:24px}.actions{display:none}}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Classic, for an issuer with no logo.
|
|
3
|
+
|
|
4
|
+
Not the logo template with an empty slot: an invoice whose masthead is a
|
|
5
|
+
blank 80px gap looks like a page that failed to load. The trading name takes
|
|
6
|
+
the space instead, set as a wordmark, which is what a letterhead does when
|
|
7
|
+
there is no mark to print.
|
|
8
|
+
|
|
9
|
+
Chosen automatically - buildPrintHtml() asks for `<style>-nologo` first when
|
|
10
|
+
neither the issuer nor Settings > Branding has a logo.
|
|
11
|
+
-->
|
|
12
|
+
<!DOCTYPE html>
|
|
13
|
+
<html lang="en">
|
|
14
|
+
<head>
|
|
15
|
+
<meta charset="utf-8">
|
|
16
|
+
<title>Invoice {{number}}</title>
|
|
17
|
+
<style>
|
|
18
|
+
{{baseCss}}
|
|
19
|
+
|
|
20
|
+
/* The name IS the masthead here, so it is set like one. */
|
|
21
|
+
.wordmark {
|
|
22
|
+
font-size: 26px;
|
|
23
|
+
font-weight: 700;
|
|
24
|
+
letter-spacing: -0.4px;
|
|
25
|
+
color: #000;
|
|
26
|
+
margin-bottom: 10px;
|
|
27
|
+
line-height: 1.1;
|
|
28
|
+
}
|
|
29
|
+
.top .party .name { display: none; }
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
|
|
34
|
+
<div class="actions">
|
|
35
|
+
<button onclick="window.print()">Print / Save as PDF</button>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="invoice">
|
|
39
|
+
<div class="top">
|
|
40
|
+
<div>
|
|
41
|
+
<div class="wordmark">{{issuerName}}</div>
|
|
42
|
+
<div class="party">
|
|
43
|
+
<div class="lines">{{issuerAddress}}</div>
|
|
44
|
+
<div class="lines">{{issuerEmail}}</div>
|
|
45
|
+
<div class="lines">{{issuerPhone}}</div>
|
|
46
|
+
{{issuerVat}}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="meta">
|
|
50
|
+
<h1>INVOICE</h1>
|
|
51
|
+
<div class="number">{{number}}</div>
|
|
52
|
+
<div>{{issueDate}}</div>
|
|
53
|
+
{{dueDate}}
|
|
54
|
+
<div class="status">{{status}}</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="parties">
|
|
59
|
+
<div class="party">
|
|
60
|
+
<h3>Billed To</h3>
|
|
61
|
+
<div class="name">{{receiverName}}</div>
|
|
62
|
+
<div class="lines">{{receiverAddress}}</div>
|
|
63
|
+
<div class="lines">{{receiverEmail}}</div>
|
|
64
|
+
{{receiverVat}}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<table class="items">
|
|
69
|
+
<thead>
|
|
70
|
+
<tr>
|
|
71
|
+
<th>Description</th>
|
|
72
|
+
<th class="num">Qty</th>
|
|
73
|
+
<th class="num">Unit</th>
|
|
74
|
+
<th class="num">Total</th>
|
|
75
|
+
</tr>
|
|
76
|
+
</thead>
|
|
77
|
+
<tbody>
|
|
78
|
+
{{items}}
|
|
79
|
+
</tbody>
|
|
80
|
+
</table>
|
|
81
|
+
|
|
82
|
+
<div class="totals">
|
|
83
|
+
<table>
|
|
84
|
+
<tr><th>Subtotal</th><td class="num">{{subtotal}}</td></tr>
|
|
85
|
+
{{vatRow}}
|
|
86
|
+
<tr class="grand"><th>Total</th><td class="num">{{total}}</td></tr>
|
|
87
|
+
{{paidRows}}
|
|
88
|
+
</table>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
{{notes}}
|
|
92
|
+
{{bankDetails}}
|
|
93
|
+
|
|
94
|
+
<div class="footer">{{footerNote}}</div>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
{{autoPrint}}
|
|
98
|
+
|
|
99
|
+
</body>
|
|
100
|
+
</html>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Classic - the default. Logo top left, invoice meta top right.
|
|
3
|
+
|
|
4
|
+
Every template is a whole HTML document: a printout has no stylesheet of its
|
|
5
|
+
own to fetch, so `{{baseCss}}` inlines the shared rules and anything below it
|
|
6
|
+
is what makes this style itself.
|
|
7
|
+
|
|
8
|
+
Slots: number issueDate dueDate status issuerLogo issuerName issuerAddress
|
|
9
|
+
issuerEmail issuerPhone issuerVat receiverName receiverAddress receiverEmail
|
|
10
|
+
receiverVat items subtotal vatRow paidRows total notes bankDetails footerNote
|
|
11
|
+
autoPrint baseCss
|
|
12
|
+
-->
|
|
13
|
+
<!DOCTYPE html>
|
|
14
|
+
<html lang="en">
|
|
15
|
+
<head>
|
|
16
|
+
<meta charset="utf-8">
|
|
17
|
+
<title>Invoice {{number}}</title>
|
|
18
|
+
<style>
|
|
19
|
+
{{baseCss}}
|
|
20
|
+
</style>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
|
|
24
|
+
<div class="actions">
|
|
25
|
+
<button onclick="window.print()">Print / Save as PDF</button>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="invoice">
|
|
29
|
+
<div class="top">
|
|
30
|
+
<div>
|
|
31
|
+
{{issuerLogo}}
|
|
32
|
+
<div class="party">
|
|
33
|
+
<div class="name">{{issuerName}}</div>
|
|
34
|
+
<div class="lines">{{issuerAddress}}</div>
|
|
35
|
+
<div class="lines">{{issuerEmail}}</div>
|
|
36
|
+
<div class="lines">{{issuerPhone}}</div>
|
|
37
|
+
{{issuerVat}}
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="meta">
|
|
41
|
+
<h1>INVOICE</h1>
|
|
42
|
+
<div class="number">{{number}}</div>
|
|
43
|
+
<div>{{issueDate}}</div>
|
|
44
|
+
{{dueDate}}
|
|
45
|
+
<div class="status">{{status}}</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="parties">
|
|
50
|
+
<div class="party">
|
|
51
|
+
<h3>Billed To</h3>
|
|
52
|
+
<div class="name">{{receiverName}}</div>
|
|
53
|
+
<div class="lines">{{receiverAddress}}</div>
|
|
54
|
+
<div class="lines">{{receiverEmail}}</div>
|
|
55
|
+
{{receiverVat}}
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<table class="items">
|
|
60
|
+
<thead>
|
|
61
|
+
<tr>
|
|
62
|
+
<th>Description</th>
|
|
63
|
+
<th class="num">Qty</th>
|
|
64
|
+
<th class="num">Unit</th>
|
|
65
|
+
<th class="num">Total</th>
|
|
66
|
+
</tr>
|
|
67
|
+
</thead>
|
|
68
|
+
<tbody>
|
|
69
|
+
{{items}}
|
|
70
|
+
</tbody>
|
|
71
|
+
</table>
|
|
72
|
+
|
|
73
|
+
<div class="totals">
|
|
74
|
+
<table>
|
|
75
|
+
<tr><th>Subtotal</th><td class="num">{{subtotal}}</td></tr>
|
|
76
|
+
{{vatRow}}
|
|
77
|
+
<tr class="grand"><th>Total</th><td class="num">{{total}}</td></tr>
|
|
78
|
+
{{paidRows}}
|
|
79
|
+
</table>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
{{notes}}
|
|
83
|
+
{{bankDetails}}
|
|
84
|
+
|
|
85
|
+
<div class="footer">{{footerNote}}</div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
{{autoPrint}}
|
|
89
|
+
|
|
90
|
+
</body>
|
|
91
|
+
</html>
|
|
@@ -97,6 +97,29 @@
|
|
|
97
97
|
padding: 8px 10px;
|
|
98
98
|
font-variant-numeric: tabular-nums;
|
|
99
99
|
}
|
|
100
|
+
.bank .pay {
|
|
101
|
+
border-collapse: collapse;
|
|
102
|
+
margin-top: 6px;
|
|
103
|
+
}
|
|
104
|
+
.bank .pay th {
|
|
105
|
+
text-align: left;
|
|
106
|
+
font-weight: 400;
|
|
107
|
+
color: #666;
|
|
108
|
+
padding: 2px 14px 2px 0;
|
|
109
|
+
white-space: nowrap;
|
|
110
|
+
vertical-align: top;
|
|
111
|
+
}
|
|
112
|
+
.bank .pay td {
|
|
113
|
+
padding: 2px 0;
|
|
114
|
+
font-variant-numeric: tabular-nums;
|
|
115
|
+
font-weight: 600;
|
|
116
|
+
}
|
|
117
|
+
.bank .pay-notes { margin-top: 6px; }
|
|
118
|
+
.totals .balance th, .totals .balance td {
|
|
119
|
+
font-weight: 700;
|
|
120
|
+
border-top: 1px solid #ddd;
|
|
121
|
+
}
|
|
122
|
+
.totals .settled th, .totals .settled td { color: #197a3d; }
|
|
100
123
|
.totals .grand th, .totals .grand td {
|
|
101
124
|
font-size: 17px;
|
|
102
125
|
font-weight: 700;
|
|
@@ -198,6 +221,7 @@
|
|
|
198
221
|
<tr><th>Subtotal</th><td class="num">{{subtotal}}</td></tr>
|
|
199
222
|
{{vatRow}}
|
|
200
223
|
<tr class="grand"><th>Total</th><td class="num">{{total}}</td></tr>
|
|
224
|
+
{{paidRows}}
|
|
201
225
|
</table>
|
|
202
226
|
</div>
|
|
203
227
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Minimal - typographic, no rules, no fills, no logo by design.
|
|
3
|
+
|
|
4
|
+
It has no `-nologo` sibling on purpose: there is nowhere in this layout a
|
|
5
|
+
logo would go, so it is the same document either way and the resolver falls
|
|
6
|
+
back to this file.
|
|
7
|
+
-->
|
|
8
|
+
<!DOCTYPE html>
|
|
9
|
+
<html lang="en">
|
|
10
|
+
<head>
|
|
11
|
+
<meta charset="utf-8">
|
|
12
|
+
<title>Invoice {{number}}</title>
|
|
13
|
+
<style>
|
|
14
|
+
{{baseCss}}
|
|
15
|
+
|
|
16
|
+
/* Minimal: no card, no shadow, no bands - just the page. */
|
|
17
|
+
body { background: #fff; padding: 40px 24px; }
|
|
18
|
+
.invoice { box-shadow: none; padding: 0; max-width: 680px; }
|
|
19
|
+
.top { border-bottom: 1px solid #222; padding-bottom: 12px; margin-bottom: 28px; }
|
|
20
|
+
.top .party .name { font-size: 15px; }
|
|
21
|
+
.meta h1 { font-size: 15px; letter-spacing: 4px; font-weight: 600; }
|
|
22
|
+
.meta .number { font-size: 14px; }
|
|
23
|
+
.status { background: transparent; padding: 0; color: #666; letter-spacing: 1.5px; }
|
|
24
|
+
table.items th { border-bottom-color: #222; }
|
|
25
|
+
table.items td { border-bottom-color: #eee; }
|
|
26
|
+
.totals .grand th, .totals .grand td { border-top-color: #222; font-size: 15px; }
|
|
27
|
+
.notes, .bank { background: transparent; padding: 0; border-top: 1px solid #eee; padding-top: 12px; border-radius: 0; }
|
|
28
|
+
.footer { border-top: 1px solid #eee; }
|
|
29
|
+
</style>
|
|
30
|
+
</head>
|
|
31
|
+
<body>
|
|
32
|
+
|
|
33
|
+
<div class="actions">
|
|
34
|
+
<button onclick="window.print()">Print / Save as PDF</button>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="invoice">
|
|
38
|
+
<div class="top">
|
|
39
|
+
<div>
|
|
40
|
+
<div class="party">
|
|
41
|
+
<div class="name">{{issuerName}}</div>
|
|
42
|
+
<div class="lines">{{issuerAddress}}</div>
|
|
43
|
+
<div class="lines">{{issuerEmail}}</div>
|
|
44
|
+
<div class="lines">{{issuerPhone}}</div>
|
|
45
|
+
{{issuerVat}}
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="meta">
|
|
49
|
+
<h1>INVOICE</h1>
|
|
50
|
+
<div class="number">{{number}}</div>
|
|
51
|
+
<div>{{issueDate}}</div>
|
|
52
|
+
{{dueDate}}
|
|
53
|
+
<div class="status">{{status}}</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div class="parties">
|
|
58
|
+
<div class="party">
|
|
59
|
+
<h3>Billed To</h3>
|
|
60
|
+
<div class="name">{{receiverName}}</div>
|
|
61
|
+
<div class="lines">{{receiverAddress}}</div>
|
|
62
|
+
<div class="lines">{{receiverEmail}}</div>
|
|
63
|
+
{{receiverVat}}
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<table class="items">
|
|
68
|
+
<thead>
|
|
69
|
+
<tr>
|
|
70
|
+
<th>Description</th>
|
|
71
|
+
<th class="num">Qty</th>
|
|
72
|
+
<th class="num">Unit</th>
|
|
73
|
+
<th class="num">Total</th>
|
|
74
|
+
</tr>
|
|
75
|
+
</thead>
|
|
76
|
+
<tbody>
|
|
77
|
+
{{items}}
|
|
78
|
+
</tbody>
|
|
79
|
+
</table>
|
|
80
|
+
|
|
81
|
+
<div class="totals">
|
|
82
|
+
<table>
|
|
83
|
+
<tr><th>Subtotal</th><td class="num">{{subtotal}}</td></tr>
|
|
84
|
+
{{vatRow}}
|
|
85
|
+
<tr class="grand"><th>Total</th><td class="num">{{total}}</td></tr>
|
|
86
|
+
{{paidRows}}
|
|
87
|
+
</table>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
{{notes}}
|
|
91
|
+
{{bankDetails}}
|
|
92
|
+
|
|
93
|
+
<div class="footer">{{footerNote}}</div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
{{autoPrint}}
|
|
97
|
+
|
|
98
|
+
</body>
|
|
99
|
+
</html>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Modern, for an issuer with no logo: the trading name is the wordmark in
|
|
3
|
+
the band, so the band is never a dark strip with a hole in it.
|
|
4
|
+
-->
|
|
5
|
+
<!DOCTYPE html>
|
|
6
|
+
<html lang="en">
|
|
7
|
+
<head>
|
|
8
|
+
<meta charset="utf-8">
|
|
9
|
+
<title>Invoice {{number}}</title>
|
|
10
|
+
<style>
|
|
11
|
+
{{baseCss}}
|
|
12
|
+
|
|
13
|
+
/* Modern - a dark masthead band, the numbers doing the talking underneath. */
|
|
14
|
+
.invoice { padding: 0 0 48px; }
|
|
15
|
+
.band {
|
|
16
|
+
background: #1b1f23;
|
|
17
|
+
color: #fff;
|
|
18
|
+
padding: 28px 56px;
|
|
19
|
+
display: flex;
|
|
20
|
+
justify-content: space-between;
|
|
21
|
+
align-items: flex-start;
|
|
22
|
+
gap: 24px;
|
|
23
|
+
}
|
|
24
|
+
.band .wordmark { font-size: 22px; font-weight: 700; letter-spacing: -0.3px; }
|
|
25
|
+
.band .logo { max-height: 56px; margin: 0; }
|
|
26
|
+
.band h1 { margin: 0; font-size: 24px; letter-spacing: 3px; font-weight: 600; }
|
|
27
|
+
.band .number { font-size: 15px; opacity: .75; margin-top: 2px; }
|
|
28
|
+
.band .meta { text-align: right; }
|
|
29
|
+
.band .meta div { opacity: .85; font-size: 13px; }
|
|
30
|
+
.band .status {
|
|
31
|
+
background: rgba(255,255,255,.15);
|
|
32
|
+
color: #fff;
|
|
33
|
+
margin-top: 8px;
|
|
34
|
+
}
|
|
35
|
+
.top { display: none; }
|
|
36
|
+
.body { padding: 32px 56px 0; }
|
|
37
|
+
.parties { grid-template-columns: 1fr 1fr; }
|
|
38
|
+
table.items th { border-bottom-color: #1b1f23; }
|
|
39
|
+
.totals .grand th, .totals .grand td { border-top-color: #1b1f23; }
|
|
40
|
+
</style>
|
|
41
|
+
</head>
|
|
42
|
+
<body>
|
|
43
|
+
|
|
44
|
+
<div class="actions">
|
|
45
|
+
<button onclick="window.print()">Print / Save as PDF</button>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="invoice">
|
|
49
|
+
<div class="band">
|
|
50
|
+
<div>
|
|
51
|
+
<div class="wordmark">{{issuerName}}</div>
|
|
52
|
+
<div class="lines" style="opacity:.8;font-size:12px;margin-top:6px;">{{issuerEmail}}</div>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="meta">
|
|
55
|
+
<h1>INVOICE</h1>
|
|
56
|
+
<div class="number">{{number}}</div>
|
|
57
|
+
<div>{{issueDate}}</div>
|
|
58
|
+
{{dueDate}}
|
|
59
|
+
<div class="status">{{status}}</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="body">
|
|
64
|
+
<div class="parties">
|
|
65
|
+
<div class="party">
|
|
66
|
+
<h3>From</h3>
|
|
67
|
+
<div class="name">{{issuerName}}</div>
|
|
68
|
+
<div class="lines">{{issuerAddress}}</div>
|
|
69
|
+
<div class="lines">{{issuerPhone}}</div>
|
|
70
|
+
{{issuerVat}}
|
|
71
|
+
</div>
|
|
72
|
+
<div class="party">
|
|
73
|
+
<h3>Billed To</h3>
|
|
74
|
+
<div class="name">{{receiverName}}</div>
|
|
75
|
+
<div class="lines">{{receiverAddress}}</div>
|
|
76
|
+
<div class="lines">{{receiverEmail}}</div>
|
|
77
|
+
{{receiverVat}}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<table class="items">
|
|
82
|
+
<thead>
|
|
83
|
+
<tr>
|
|
84
|
+
<th>Description</th>
|
|
85
|
+
<th class="num">Qty</th>
|
|
86
|
+
<th class="num">Unit</th>
|
|
87
|
+
<th class="num">Total</th>
|
|
88
|
+
</tr>
|
|
89
|
+
</thead>
|
|
90
|
+
<tbody>
|
|
91
|
+
{{items}}
|
|
92
|
+
</tbody>
|
|
93
|
+
</table>
|
|
94
|
+
|
|
95
|
+
<div class="totals">
|
|
96
|
+
<table>
|
|
97
|
+
<tr><th>Subtotal</th><td class="num">{{subtotal}}</td></tr>
|
|
98
|
+
{{vatRow}}
|
|
99
|
+
<tr class="grand"><th>Total</th><td class="num">{{total}}</td></tr>
|
|
100
|
+
{{paidRows}}
|
|
101
|
+
</table>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
{{notes}}
|
|
105
|
+
{{bankDetails}}
|
|
106
|
+
|
|
107
|
+
<div class="footer">{{footerNote}}</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
{{autoPrint}}
|
|
112
|
+
|
|
113
|
+
</body>
|
|
114
|
+
</html>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Modern - a dark masthead band carrying the logo and the invoice meta.
|
|
3
|
+
-->
|
|
4
|
+
<!DOCTYPE html>
|
|
5
|
+
<html lang="en">
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="utf-8">
|
|
8
|
+
<title>Invoice {{number}}</title>
|
|
9
|
+
<style>
|
|
10
|
+
{{baseCss}}
|
|
11
|
+
|
|
12
|
+
/* Modern - a dark masthead band, the numbers doing the talking underneath. */
|
|
13
|
+
.invoice { padding: 0 0 48px; }
|
|
14
|
+
.band {
|
|
15
|
+
background: #1b1f23;
|
|
16
|
+
color: #fff;
|
|
17
|
+
padding: 28px 56px;
|
|
18
|
+
display: flex;
|
|
19
|
+
justify-content: space-between;
|
|
20
|
+
align-items: flex-start;
|
|
21
|
+
gap: 24px;
|
|
22
|
+
}
|
|
23
|
+
.band .wordmark { font-size: 22px; font-weight: 700; letter-spacing: -0.3px; }
|
|
24
|
+
.band .logo { max-height: 56px; margin: 0; }
|
|
25
|
+
.band h1 { margin: 0; font-size: 24px; letter-spacing: 3px; font-weight: 600; }
|
|
26
|
+
.band .number { font-size: 15px; opacity: .75; margin-top: 2px; }
|
|
27
|
+
.band .meta { text-align: right; }
|
|
28
|
+
.band .meta div { opacity: .85; font-size: 13px; }
|
|
29
|
+
.band .status {
|
|
30
|
+
background: rgba(255,255,255,.15);
|
|
31
|
+
color: #fff;
|
|
32
|
+
margin-top: 8px;
|
|
33
|
+
}
|
|
34
|
+
.top { display: none; }
|
|
35
|
+
.body { padding: 32px 56px 0; }
|
|
36
|
+
.parties { grid-template-columns: 1fr 1fr; }
|
|
37
|
+
table.items th { border-bottom-color: #1b1f23; }
|
|
38
|
+
.totals .grand th, .totals .grand td { border-top-color: #1b1f23; }
|
|
39
|
+
</style>
|
|
40
|
+
</head>
|
|
41
|
+
<body>
|
|
42
|
+
|
|
43
|
+
<div class="actions">
|
|
44
|
+
<button onclick="window.print()">Print / Save as PDF</button>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="invoice">
|
|
48
|
+
<div class="band">
|
|
49
|
+
<div>
|
|
50
|
+
{{issuerLogo}}
|
|
51
|
+
<div class="lines" style="opacity:.8;font-size:12px;margin-top:6px;">{{issuerEmail}}</div>
|
|
52
|
+
</div>
|
|
53
|
+
<div class="meta">
|
|
54
|
+
<h1>INVOICE</h1>
|
|
55
|
+
<div class="number">{{number}}</div>
|
|
56
|
+
<div>{{issueDate}}</div>
|
|
57
|
+
{{dueDate}}
|
|
58
|
+
<div class="status">{{status}}</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div class="body">
|
|
63
|
+
<div class="parties">
|
|
64
|
+
<div class="party">
|
|
65
|
+
<h3>From</h3>
|
|
66
|
+
<div class="name">{{issuerName}}</div>
|
|
67
|
+
<div class="lines">{{issuerAddress}}</div>
|
|
68
|
+
<div class="lines">{{issuerPhone}}</div>
|
|
69
|
+
{{issuerVat}}
|
|
70
|
+
</div>
|
|
71
|
+
<div class="party">
|
|
72
|
+
<h3>Billed To</h3>
|
|
73
|
+
<div class="name">{{receiverName}}</div>
|
|
74
|
+
<div class="lines">{{receiverAddress}}</div>
|
|
75
|
+
<div class="lines">{{receiverEmail}}</div>
|
|
76
|
+
{{receiverVat}}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<table class="items">
|
|
81
|
+
<thead>
|
|
82
|
+
<tr>
|
|
83
|
+
<th>Description</th>
|
|
84
|
+
<th class="num">Qty</th>
|
|
85
|
+
<th class="num">Unit</th>
|
|
86
|
+
<th class="num">Total</th>
|
|
87
|
+
</tr>
|
|
88
|
+
</thead>
|
|
89
|
+
<tbody>
|
|
90
|
+
{{items}}
|
|
91
|
+
</tbody>
|
|
92
|
+
</table>
|
|
93
|
+
|
|
94
|
+
<div class="totals">
|
|
95
|
+
<table>
|
|
96
|
+
<tr><th>Subtotal</th><td class="num">{{subtotal}}</td></tr>
|
|
97
|
+
{{vatRow}}
|
|
98
|
+
<tr class="grand"><th>Total</th><td class="num">{{total}}</td></tr>
|
|
99
|
+
{{paidRows}}
|
|
100
|
+
</table>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
{{notes}}
|
|
104
|
+
{{bankDetails}}
|
|
105
|
+
|
|
106
|
+
<div class="footer">{{footerNote}}</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
{{autoPrint}}
|
|
111
|
+
|
|
112
|
+
</body>
|
|
113
|
+
</html>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "The templates offered in Settings > Templates. A site can add its own: drop <id>.html (and optionally <id>-nologo.html) beside this file and add an entry. `nologo: false` means the style has nowhere to put a logo, so it is used as-is either way.",
|
|
3
|
+
"templates": [
|
|
4
|
+
{ "id": "classic", "name": "Classic", "nologo": true,
|
|
5
|
+
"description": "Logo top left, invoice details top right. The traditional letterhead layout." },
|
|
6
|
+
{ "id": "modern", "name": "Modern", "nologo": true,
|
|
7
|
+
"description": "A dark masthead band across the top carrying the logo and the invoice number." },
|
|
8
|
+
{ "id": "minimal", "name": "Minimal", "nologo": false,
|
|
9
|
+
"description": "Typographic and unfilled - no logo, no colour. Prints cleanly in black and white." }
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mail Reader admin view.
|
|
3
|
+
*
|
|
4
|
+
* The three-pane reader is shared with the other edition and lives in
|
|
5
|
+
* `plugins/_lib/admin/mail/reader-view.js`. It is imported dynamically so the
|
|
6
|
+
* loader's cache-busting token reaches it: a static specifier is fixed, so the
|
|
7
|
+
* shared code would keep being served from cache after an update while this
|
|
8
|
+
* file was refetched.
|
|
9
|
+
*
|
|
10
|
+
* @module mail-reader/admin/views/mail
|
|
11
|
+
*/
|
|
12
|
+
const ASSET_VERSION = new URL(import.meta.url).searchParams.get('v') ?? '1';
|
|
13
|
+
|
|
14
|
+
const {createReaderView} = await import(`/plugins/_lib/admin/mail/reader-view.js?v=${ASSET_VERSION}`);
|
|
15
|
+
|
|
16
|
+
export const mailView = createReaderView({
|
|
17
|
+
pluginName: 'mail-reader',
|
|
18
|
+
assetVersion: ASSET_VERSION
|
|
19
|
+
});
|