@nocobase/portal-template-default 1.0.15 → 1.0.17

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.
Files changed (153) hide show
  1. package/AGENTS.md +8 -0
  2. package/README.MD +4 -0
  3. package/dist/assets/{LineDraw-iG-ADes-.js → LineDraw-BBB5hwuJ.js} +1 -1
  4. package/dist/assets/{SymbolDraw-DXoSw1tM.js → SymbolDraw-CKS3uUb_.js} +1 -1
  5. package/dist/assets/{VisualMapping-C_ee4Eht.js → VisualMapping-BCwaW3TD.js} +1 -1
  6. package/dist/assets/auth-method-demo-BdCCvEEz.js +1 -0
  7. package/dist/assets/{auto-login-provider-5Uxza9Ms.js → auto-login-provider-DO5Il6Dp.js} +2 -2
  8. package/dist/assets/auto-login-provider-TQ08B6-i.js +1 -0
  9. package/dist/assets/auto-redirect-provider-ButXp0A3.js +1 -0
  10. package/dist/assets/auto-redirect-provider-DnGGP2Vn.js +1 -0
  11. package/dist/assets/auto-redirect-provider-ja-vFPaF.js +1 -0
  12. package/dist/assets/calendar-C7xnRgOT.js +1 -0
  13. package/dist/assets/{cas-sign-in-button-CyqG1QME.js → cas-sign-in-button-BZCa4lR6.js} +1 -1
  14. package/dist/assets/{components-D-ptYjX_.js → components-_g-GjQeV.js} +3 -3
  15. package/dist/assets/{configuration-gate-C08mkkiX.js → configuration-gate-B4XVz7tS.js} +1 -1
  16. package/dist/assets/{createClipPathFromCoordSys-wj34-b1B.js → createClipPathFromCoordSys-z9Kmh-tu.js} +1 -1
  17. package/dist/assets/createSeriesDataSimply-CPqysF0K.js +1 -0
  18. package/dist/assets/{customGraphicKeyframeAnimation-DWrhrHL_.js → customGraphicKeyframeAnimation-DMU5crAu.js} +1 -1
  19. package/dist/assets/demo-BPlae2bp.js +1 -0
  20. package/dist/assets/demo-Bj_Y0RrW.js +1 -0
  21. package/dist/assets/demo-CKPAQOib.js +1 -0
  22. package/dist/assets/demo-CXRTPvIx.js +1 -0
  23. package/dist/assets/demo-DJuVDu1n.js +1 -0
  24. package/dist/assets/demo-DUmWU7ik.js +1 -0
  25. package/dist/assets/demo-NhIzFRE1.js +1 -0
  26. package/dist/assets/{dingtalk-sign-in-button-DSWsSruv.js → dingtalk-sign-in-button-DMPgE5kT.js} +1 -1
  27. package/dist/assets/{echarts-preview-DxHNfq1C.js → echarts-preview-R96Pbqmz.js} +1 -1
  28. package/dist/assets/{echarts-runtime-D8kXn6ME.js → echarts-runtime-Ce_z2eX_.js} +3 -3
  29. package/dist/assets/{echarts-runtime-advanced-QY8v95qK.js → echarts-runtime-advanced-Dr80KHJR.js} +1 -1
  30. package/dist/assets/{echarts-runtime-common-D-yqAK-r.js → echarts-runtime-common-DB95Yfc1.js} +1 -1
  31. package/dist/assets/{echarts-runtime-components-P4-i8jPU.js → echarts-runtime-components-DCJEaTJk.js} +1 -1
  32. package/dist/assets/{echarts-runtime-hierarchy-ByQZ-DbP.js → echarts-runtime-hierarchy-CezgZs9O.js} +1 -1
  33. package/dist/assets/{floating-BFVEyPEp.js → floating-O9WmiDXk.js} +2 -2
  34. package/dist/assets/index-BBKV6O5d.css +1 -0
  35. package/dist/assets/{index-Btk35Nx-.js → index-CPzehPGe.js} +3 -3
  36. package/dist/assets/index-Cc6awvdg.js +1064 -0
  37. package/dist/assets/index-ChA0z9ke.js +38 -0
  38. package/dist/assets/{index-um5hdKdZ.js → index-DgB7uTMs.js} +2 -2
  39. package/dist/assets/{index-CwNxd66J.js → index-DroUAK80.js} +1 -1
  40. package/dist/assets/index-WKvygTBp.js +59 -0
  41. package/dist/assets/{labelHelper-DQqRy3a_.js → labelHelper-Dk5jkiD-.js} +1 -1
  42. package/dist/assets/ldap-sign-in-form-CKN4l7qM.js +1 -0
  43. package/dist/assets/{oidc-sign-in-button-CQdRcR_p.js → oidc-sign-in-button-BIRonrpC.js} +1 -1
  44. package/dist/assets/{page-context-CnQ4GYM7.js → page-context-DAiW_dId.js} +3 -3
  45. package/dist/assets/prompt-card-rGZqpqkF.js +1 -0
  46. package/dist/assets/prompt-output-B4h3uLWf.js +1 -0
  47. package/dist/assets/saml-sign-in-button-B4ugaLIb.js +1 -0
  48. package/dist/assets/{sectorHelper-DN_Vv6OL.js → sectorHelper-BuxrrJrA.js} +1 -1
  49. package/dist/assets/shortcut-BhKXxJLs.js +47 -0
  50. package/dist/assets/{sms-sign-in-form-DTX9GV2I.js → sms-sign-in-form-DKpxRDdZ.js} +1 -1
  51. package/dist/assets/{static.browser-jI1psK0d.js → static.browser-kzzpH0Xt.js} +8 -8
  52. package/dist/assets/switch-BdVxPIVU.js +1 -0
  53. package/dist/assets/{tool-cards-DFttLAfo.js → tool-cards-CpczIke-.js} +3 -3
  54. package/dist/assets/{use-authenticator-sign-in-CRGjzXju.js → use-authenticator-sign-in-CIj210ry.js} +1 -1
  55. package/dist/assets/use-dingtalk-sign-in-BW4kkXD3.js +1 -0
  56. package/dist/assets/{use-wecom-sign-in-C9j8wfCD.js → use-wecom-sign-in-dIqMtcN9.js} +1 -1
  57. package/dist/assets/wecom-sign-in-button-Dn_2zDab.js +1 -0
  58. package/dist/index.html +2 -2
  59. package/dist/index.raw.html +2 -2
  60. package/package.json +9 -1
  61. package/src/App.tsx +5 -2
  62. package/src/app/extension.ts +2 -0
  63. package/src/app/extensions.tsx +18 -6
  64. package/src/app/route-access-guard.tsx +22 -0
  65. package/src/app/route-runtime.ts +173 -0
  66. package/src/app/routes.tsx +2 -2
  67. package/src/components/app-shell/header.tsx +56 -1
  68. package/src/components/app-shell/sidebar.tsx +14 -2
  69. package/src/components/auth/sign-up-form.tsx +287 -59
  70. package/src/components/auth/types.ts +23 -1
  71. package/src/extensions/nocobase-acl/README.md +28 -14
  72. package/src/extensions/nocobase-acl/demo/index.tsx +87 -15
  73. package/src/extensions/nocobase-acl/demo/prompt-generator.tsx +1 -0
  74. package/src/extensions/nocobase-mail/README.md +74 -0
  75. package/src/extensions/nocobase-mail/components/index.ts +79 -0
  76. package/src/extensions/nocobase-mail/components/mail-api.ts +423 -0
  77. package/src/extensions/nocobase-mail/components/mail-attachment-list.tsx +67 -0
  78. package/src/extensions/nocobase-mail/components/mail-compose-attachments.tsx +166 -0
  79. package/src/extensions/nocobase-mail/components/mail-compose.tsx +1071 -0
  80. package/src/extensions/nocobase-mail/components/mail-detail.tsx +653 -0
  81. package/src/extensions/nocobase-mail/components/mail-draft-autosave.ts +26 -0
  82. package/src/extensions/nocobase-mail/components/mail-empty.tsx +48 -0
  83. package/src/extensions/nocobase-mail/components/mail-filters.tsx +277 -0
  84. package/src/extensions/nocobase-mail/components/mail-inbox.tsx +544 -0
  85. package/src/extensions/nocobase-mail/components/mail-inline-images.ts +69 -0
  86. package/src/extensions/nocobase-mail/components/mail-label-badge.tsx +25 -0
  87. package/src/extensions/nocobase-mail/components/mail-label-manager.tsx +271 -0
  88. package/src/extensions/nocobase-mail/components/mail-labels-editor.tsx +267 -0
  89. package/src/extensions/nocobase-mail/components/mail-mass-tracking.tsx +271 -0
  90. package/src/extensions/nocobase-mail/components/mail-note-editor.tsx +99 -0
  91. package/src/extensions/nocobase-mail/components/mail-recipient-input.tsx +260 -0
  92. package/src/extensions/nocobase-mail/components/mail-reply-quote.ts +28 -0
  93. package/src/extensions/nocobase-mail/components/mail-rich-editor.tsx +287 -0
  94. package/src/extensions/nocobase-mail/components/mail-send-actions.tsx +238 -0
  95. package/src/extensions/nocobase-mail/components/mail-senders.ts +61 -0
  96. package/src/extensions/nocobase-mail/components/mail-settings-drawer.tsx +708 -0
  97. package/src/extensions/nocobase-mail/components/mail-showcase-layout.tsx +64 -0
  98. package/src/extensions/nocobase-mail/components/mail-signature-manager.tsx +258 -0
  99. package/src/extensions/nocobase-mail/components/mail-signatures.ts +25 -0
  100. package/src/extensions/nocobase-mail/components/mail-table.tsx +476 -0
  101. package/src/extensions/nocobase-mail/components/mail-template-manager.tsx +204 -0
  102. package/src/extensions/nocobase-mail/components/mail-toolbar.tsx +155 -0
  103. package/src/extensions/nocobase-mail/components/mail-unread.tsx +111 -0
  104. package/src/extensions/nocobase-mail/components/types.ts +297 -0
  105. package/src/extensions/nocobase-mail/components/use-mail-compose.tsx +262 -0
  106. package/src/extensions/nocobase-mail/components/use-mail-mass-messages.ts +54 -0
  107. package/src/extensions/nocobase-mail/components/use-mail-messages.ts +113 -0
  108. package/src/extensions/nocobase-mail/components/use-mail-signatures.ts +122 -0
  109. package/src/extensions/nocobase-mail/components/use-mail-templates.ts +54 -0
  110. package/src/extensions/nocobase-mail/extension.tsx +105 -0
  111. package/src/extensions/nocobase-mail/index.ts +1 -0
  112. package/src/extensions/nocobase-mail/mail-demo-pages.tsx +503 -0
  113. package/src/extensions/nocobase-mail/mail-pages.tsx +201 -0
  114. package/src/extensions/nocobase-mail/tests/mail-quote-html-regression.mjs +51 -0
  115. package/src/extensions/nocobase-mail/tests/mail-regression.mjs +649 -0
  116. package/src/extensions/nocobase-users-example/app-routes.tsx +121 -0
  117. package/src/extensions/nocobase-users-example/extension.tsx +2 -100
  118. package/src/extensions/nocobase-users-example/index.ts +1 -0
  119. package/src/lib/nocobase/acl/menu.ts +17 -3
  120. package/src/lib/nocobase/acl/types.ts +4 -0
  121. package/src/locales/en-US.ts +2 -1
  122. package/src/locales/zh-CN.ts +2 -1
  123. package/src/providers/runtime-config.ts +18 -0
  124. package/src/routes.tsx +10 -0
  125. package/src/vite-env.d.ts +3 -0
  126. package/vite.config.ts +8 -0
  127. package/dist/assets/auth-method-demo-DaOCuvsq.js +0 -1
  128. package/dist/assets/auto-login-provider-DyaPGK2D.js +0 -1
  129. package/dist/assets/auto-redirect-provider-CfwRvYOI.js +0 -1
  130. package/dist/assets/auto-redirect-provider-Cr3jmYts.js +0 -1
  131. package/dist/assets/auto-redirect-provider-QkJQRBbG.js +0 -1
  132. package/dist/assets/calendar-DjDRfD5t.js +0 -1
  133. package/dist/assets/card-DuQBOS6A.js +0 -1
  134. package/dist/assets/createSeriesDataSimply-D0A6SAVQ.js +0 -1
  135. package/dist/assets/demo-BYWHeKUe.js +0 -1
  136. package/dist/assets/demo-CPWoNtx8.js +0 -1
  137. package/dist/assets/demo-CyvJk5zV.js +0 -1
  138. package/dist/assets/demo-D4OiKplc.js +0 -1
  139. package/dist/assets/demo-DBueJg0m.js +0 -1
  140. package/dist/assets/demo-DkIhyiRK.js +0 -1
  141. package/dist/assets/demo-tpTjO0sC.js +0 -1
  142. package/dist/assets/index-BgCbGDMc.js +0 -43
  143. package/dist/assets/index-MB-jfQld.js +0 -686
  144. package/dist/assets/index-NH3aqqQz.css +0 -1
  145. package/dist/assets/index-gFtCXH3o.js +0 -58
  146. package/dist/assets/ldap-sign-in-form--6Gt3yGq.js +0 -1
  147. package/dist/assets/prompt-card-B2RS4nt2.js +0 -1
  148. package/dist/assets/prompt-output-DZHRM2ft.js +0 -1
  149. package/dist/assets/saml-sign-in-button-BHL5a0JV.js +0 -1
  150. package/dist/assets/shortcut-C5x5LQWU.js +0 -47
  151. package/dist/assets/switch-CRL8PmRI.js +0 -1
  152. package/dist/assets/use-dingtalk-sign-in-8WYzJ2jf.js +0 -1
  153. package/dist/assets/wecom-sign-in-button-mIS1zGSU.js +0 -1
@@ -0,0 +1,201 @@
1
+ import { useMemo, useState } from "react";
2
+ import { useNavigate, useSearchParams } from "react-router";
3
+ import { Settings } from "lucide-react";
4
+ import {
5
+ MailBoxType,
6
+ MailComposeForm,
7
+ MailFilters,
8
+ MailInbox,
9
+ MailMassTracking,
10
+ MailSettingsDrawer,
11
+ type ComposeInitialValues,
12
+ type MailColumnId,
13
+ type MailFilterValue,
14
+ } from "./components";
15
+ import {
16
+ MailShowcasePage,
17
+ MailShowcaseSection,
18
+ } from "./components/mail-showcase-layout";
19
+ import { Card, CardContent } from "@/components/ui/card";
20
+ import { Button } from "@/components/ui/button";
21
+ import { MailRecipientSelectionDemo } from "./mail-demo-pages";
22
+
23
+ const PERSONAL_COLUMNS: MailColumnId[] = [
24
+ "from",
25
+ "to",
26
+ "subject",
27
+ "boxType",
28
+ "date",
29
+ "isRead",
30
+ "labels",
31
+ ];
32
+ export function MailManagerPage() {
33
+ const [searchParams, setSearchParams] = useSearchParams();
34
+ const [settingsOpen, setSettingsOpen] = useState(false);
35
+ const filterValue = useMemo<MailFilterValue>(() => {
36
+ const folder = searchParams.get("folder");
37
+ const label = Number(searchParams.get("label"));
38
+ const read = searchParams.get("read");
39
+ return {
40
+ boxType: Object.values(MailBoxType).includes(folder as MailBoxType)
41
+ ? (folder as MailBoxType)
42
+ : undefined,
43
+ isRead: read === "read" ? true : read === "unread" ? false : undefined,
44
+ labelId: Number.isFinite(label) && label > 0 ? label : undefined,
45
+ isTodo:
46
+ searchParams.get("todo") === "1" || searchParams.get("starred") === "1"
47
+ ? true
48
+ : undefined,
49
+ };
50
+ }, [searchParams]);
51
+
52
+ const updateParams = (next: MailFilterValue) => {
53
+ const params = new URLSearchParams();
54
+ if (next.boxType) params.set("folder", next.boxType);
55
+ if (next.isRead !== undefined) {
56
+ params.set("read", next.isRead ? "read" : "unread");
57
+ }
58
+ if (next.labelId) params.set("label", String(next.labelId));
59
+ if (next.isTodo) params.set("todo", "1");
60
+ setSearchParams(params, { replace: true });
61
+ };
62
+
63
+ return (
64
+ <MailShowcasePage
65
+ title="My mailbox"
66
+ description="Read, reply to, and manage messages from your connected mailboxes."
67
+ badge="Personal mail"
68
+ >
69
+ <MailShowcaseSection
70
+ eyebrow="Personal mailbox"
71
+ title="Browse and work through your messages"
72
+ description="Use tree filters to find messages, then read, reply, and manage them from the inbox."
73
+ >
74
+ <div className="grid min-h-0 gap-4 lg:grid-cols-[220px_minmax(0,1fr)]">
75
+ <aside className="self-start rounded-xl border bg-card p-4 shadow-[0_1px_2px_rgba(0,0,0,0.04)] lg:sticky lg:top-4">
76
+ <div className="mb-3">
77
+ <h3 className="text-sm font-semibold">Filters</h3>
78
+ </div>
79
+ <MailFilters
80
+ value={filterValue}
81
+ onChange={updateParams}
82
+ orientation="vertical"
83
+ />
84
+ </aside>
85
+ <main className="min-w-0">
86
+ <MailInbox
87
+ scope="personal"
88
+ boxType={filterValue.boxType}
89
+ isRead={filterValue.isRead}
90
+ labelId={filterValue.labelId}
91
+ filter={filterValue.isTodo ? { isTodo: true } : undefined}
92
+ columns={PERSONAL_COLUMNS}
93
+ toolbarActions={
94
+ <Button
95
+ variant="outline"
96
+ size="sm"
97
+ onClick={() => setSettingsOpen(true)}
98
+ >
99
+ <Settings /> Settings
100
+ </Button>
101
+ }
102
+ />
103
+ </main>
104
+ </div>
105
+ </MailShowcaseSection>
106
+ <MailSettingsDrawer open={settingsOpen} onOpenChange={setSettingsOpen} />
107
+ </MailShowcasePage>
108
+ );
109
+ }
110
+
111
+ export function MailBulkPage() {
112
+ const [jobsRevision, setJobsRevision] = useState(0);
113
+
114
+ return (
115
+ <MailShowcasePage
116
+ title="Bulk mail"
117
+ description="Send one separate message per recipient and track every delivery job."
118
+ badge="Bulk delivery"
119
+ >
120
+ <MailShowcaseSection
121
+ eyebrow="Bulk composer"
122
+ title="Prepare one message for multiple recipients"
123
+ description="Add at least two recipients. Each recipient receives an individual message."
124
+ >
125
+ <Card className="gap-0 py-0">
126
+ <CardContent className="max-w-2xl p-6">
127
+ <MailComposeForm
128
+ bulkOnly
129
+ allowScheduleSend={false}
130
+ allowBulkSend
131
+ onSent={() => setJobsRevision((revision) => revision + 1)}
132
+ />
133
+ </CardContent>
134
+ </Card>
135
+ </MailShowcaseSection>
136
+
137
+ <MailShowcaseSection
138
+ eyebrow="Delivery status"
139
+ title="Track bulk jobs"
140
+ description="Track delivery progress, cancel active jobs, and retry failed recipients."
141
+ >
142
+ <MailMassTracking key={jobsRevision} />
143
+ </MailShowcaseSection>
144
+ </MailShowcasePage>
145
+ );
146
+ }
147
+
148
+ export function MailComposePage() {
149
+ const navigate = useNavigate();
150
+ const [searchParams] = useSearchParams();
151
+ const initial = useMemo<ComposeInitialValues>(
152
+ () => ({
153
+ to: searchParams.get("to") ?? undefined,
154
+ cc: searchParams.get("cc") ?? undefined,
155
+ subject: searchParams.get("subject") ?? undefined,
156
+ body: searchParams.get("body") ?? undefined,
157
+ }),
158
+ [searchParams]
159
+ );
160
+
161
+ return (
162
+ <MailShowcasePage
163
+ title="Compose and send"
164
+ description="Compose directly, send to selected user records, or reply from a live mail table."
165
+ badge="Sending patterns"
166
+ >
167
+ <MailShowcaseSection
168
+ eyebrow="Standalone composer"
169
+ title="Compose a message"
170
+ description="Send from a connected mailbox or prefill fields through URL parameters."
171
+ >
172
+ <Card className="gap-0 py-0">
173
+ <CardContent className="max-w-2xl p-6">
174
+ <MailComposeForm
175
+ initial={initial}
176
+ showCancel
177
+ onSent={() => navigate("..")}
178
+ onCancel={() => navigate("..")}
179
+ />
180
+ </CardContent>
181
+ </Card>
182
+ </MailShowcaseSection>
183
+
184
+ <MailShowcaseSection
185
+ eyebrow="Record-driven sending"
186
+ title="Send to selected users"
187
+ description="Select one or more user records and open compose with their addresses in To."
188
+ >
189
+ <MailRecipientSelectionDemo />
190
+ </MailShowcaseSection>
191
+
192
+ <MailShowcaseSection
193
+ eyebrow="Reply workflow"
194
+ title="Reply from a mail table"
195
+ description="Open any message to try Reply, conditional Reply all, and Forward."
196
+ >
197
+ <MailInbox scope="personal" columns={PERSONAL_COLUMNS} />
198
+ </MailShowcaseSection>
199
+ </MailShowcasePage>
200
+ );
201
+ }
@@ -0,0 +1,51 @@
1
+ import assert from "node:assert/strict";
2
+ import { readFile } from "node:fs/promises";
3
+ import { createServer } from "vite";
4
+
5
+ const server = await createServer({
6
+ appType: "custom",
7
+ logLevel: "silent",
8
+ server: { middlewareMode: true },
9
+ });
10
+
11
+ try {
12
+ const { buildComposeInitial } = await server.ssrLoadModule(
13
+ "/registry/nocobase-mail/components/use-mail-compose.tsx"
14
+ );
15
+ const composeSource = await readFile(
16
+ new URL("../components/mail-compose.tsx", import.meta.url),
17
+ "utf8"
18
+ );
19
+ const originalHtml =
20
+ '<div><strong>Formatted sender</strong><p style="color:red">Original content</p></div>';
21
+ const reply = buildComposeInitial(
22
+ {
23
+ id: 1,
24
+ mailId: "message-1",
25
+ email: "team@example.com",
26
+ from: "customer@example.com",
27
+ to: "team@example.com",
28
+ subject: "Formatted message",
29
+ date: "2026-07-30T10:00:00.000Z",
30
+ bodyText: "Formatted sender Original content",
31
+ bodyHtml: originalHtml,
32
+ attachments: [],
33
+ },
34
+ "reply"
35
+ );
36
+
37
+ assert.equal(reply.replyBody, originalHtml);
38
+ assert.equal(
39
+ reply.reference?.html,
40
+ originalHtml,
41
+ "keeps the original HTML available to the quoted-message preview"
42
+ );
43
+ assert.match(
44
+ composeSource,
45
+ /srcDoc=\{contentHtml\}/,
46
+ "renders the quoted-message preview as isolated HTML instead of plain text"
47
+ );
48
+ console.log("mail quote HTML regression checks passed");
49
+ } finally {
50
+ await server.close();
51
+ }