@nocobase/portal-template-default 1.0.9 → 1.0.11

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 (338) hide show
  1. package/.env.example +5 -0
  2. package/.github/workflows/publish.yml +106 -0
  3. package/.gitignore +33 -0
  4. package/AGENTS.md +19 -0
  5. package/README.MD +61 -180
  6. package/dist/assets/{LineDraw-C0m1GONT.js → LineDraw-iG-ADes-.js} +1 -1
  7. package/dist/assets/{SymbolDraw-CCospe5G.js → SymbolDraw-DXoSw1tM.js} +1 -1
  8. package/dist/assets/VisualMapping-C_ee4Eht.js +1 -0
  9. package/dist/assets/auth-method-demo-DaOCuvsq.js +1 -0
  10. package/dist/assets/auto-login-provider-5Uxza9Ms.js +2 -0
  11. package/dist/assets/auto-login-provider-DyaPGK2D.js +1 -0
  12. package/dist/assets/auto-redirect-provider-CfwRvYOI.js +1 -0
  13. package/dist/assets/auto-redirect-provider-Cr3jmYts.js +1 -0
  14. package/dist/assets/auto-redirect-provider-QkJQRBbG.js +1 -0
  15. package/dist/assets/calendar-DjDRfD5t.js +1 -0
  16. package/dist/assets/card-DuQBOS6A.js +1 -0
  17. package/dist/assets/cas-sign-in-button-CyqG1QME.js +1 -0
  18. package/dist/assets/components-D-ptYjX_.js +20 -0
  19. package/dist/assets/configuration-gate-C08mkkiX.js +1 -0
  20. package/dist/assets/{createClipPathFromCoordSys-uEftn1Mq.js → createClipPathFromCoordSys-wj34-b1B.js} +1 -1
  21. package/dist/assets/createSeriesDataSimply-D0A6SAVQ.js +1 -0
  22. package/dist/assets/customGraphicKeyframeAnimation-DWrhrHL_.js +3 -0
  23. package/dist/assets/demo-BYWHeKUe.js +1 -0
  24. package/dist/assets/demo-CPWoNtx8.js +1 -0
  25. package/dist/assets/demo-CyvJk5zV.js +1 -0
  26. package/dist/assets/demo-D4OiKplc.js +1 -0
  27. package/dist/assets/demo-DBueJg0m.js +1 -0
  28. package/dist/assets/demo-DkIhyiRK.js +1 -0
  29. package/dist/assets/demo-tpTjO0sC.js +1 -0
  30. package/dist/assets/dingtalk-sign-in-button-DSWsSruv.js +1 -0
  31. package/dist/assets/echarts-preview-DxHNfq1C.js +1 -0
  32. package/dist/assets/{echarts-runtime-CEgJbv68.js → echarts-runtime-D8kXn6ME.js} +3 -3
  33. package/dist/assets/{echarts-runtime-advanced-Buhm2BHz.js → echarts-runtime-advanced-QY8v95qK.js} +1 -1
  34. package/dist/assets/{echarts-runtime-common-DLAdBAIa.js → echarts-runtime-common-D-yqAK-r.js} +1 -1
  35. package/dist/assets/{echarts-runtime-components-ypnyLkYx.js → echarts-runtime-components-P4-i8jPU.js} +1 -1
  36. package/dist/assets/{echarts-runtime-hierarchy-ClStquCF.js → echarts-runtime-hierarchy-ByQZ-DbP.js} +1 -1
  37. package/dist/assets/floating-BFVEyPEp.js +15 -0
  38. package/dist/assets/index-BgCbGDMc.js +43 -0
  39. package/dist/assets/index-Btk35Nx-.js +23 -0
  40. package/dist/assets/index-CwNxd66J.js +1 -0
  41. package/dist/assets/index-MB-jfQld.js +686 -0
  42. package/dist/assets/index-NH3aqqQz.css +1 -0
  43. package/dist/assets/index-gFtCXH3o.js +58 -0
  44. package/dist/assets/index-um5hdKdZ.js +23 -0
  45. package/dist/assets/{labelHelper-C137W5gU.js → labelHelper-DQqRy3a_.js} +1 -1
  46. package/dist/assets/ldap-sign-in-form--6Gt3yGq.js +1 -0
  47. package/dist/assets/oidc-sign-in-button-CQdRcR_p.js +1 -0
  48. package/dist/assets/{page-context-Cxx11gzg.js → page-context-CnQ4GYM7.js} +10 -10
  49. package/dist/assets/prompt-card-B2RS4nt2.js +1 -0
  50. package/dist/assets/prompt-output-DZHRM2ft.js +1 -0
  51. package/dist/assets/saml-sign-in-button-BHL5a0JV.js +1 -0
  52. package/dist/assets/{sectorHelper-Fqgz3uEk.js → sectorHelper-DN_Vv6OL.js} +1 -1
  53. package/dist/assets/shortcut-C5x5LQWU.js +47 -0
  54. package/dist/assets/sms-sign-in-form-DTX9GV2I.js +1 -0
  55. package/dist/assets/{static.browser-CfQQzERe.js → static.browser-jI1psK0d.js} +8 -8
  56. package/dist/assets/{switch-DrxImI8F.js → switch-CRL8PmRI.js} +1 -1
  57. package/dist/assets/{tool-cards-BGfsY8JF.js → tool-cards-DFttLAfo.js} +6 -7
  58. package/dist/assets/use-authenticator-sign-in-CRGjzXju.js +1 -0
  59. package/dist/assets/use-dingtalk-sign-in-8WYzJ2jf.js +1 -0
  60. package/dist/assets/use-wecom-sign-in-C9j8wfCD.js +1 -0
  61. package/dist/assets/wecom-sign-in-button-mIS1zGSU.js +1 -0
  62. package/dist/index.html +2 -2
  63. package/dist/index.raw.html +5 -2
  64. package/package.json +3 -5
  65. package/scripts/build-html.mjs +12 -0
  66. package/src/App.css +2 -0
  67. package/src/App.tsx +35 -186
  68. package/src/app/development.tsx +154 -0
  69. package/src/app/extension.ts +5 -0
  70. package/src/app/extensions.tsx +18 -4
  71. package/src/app/routes.tsx +65 -0
  72. package/src/components/access-control/acl-bootstrap.tsx +11 -3
  73. package/src/components/access-control/acl-gate.tsx +7 -6
  74. package/src/components/access-control/can-access.tsx +17 -0
  75. package/src/components/access-control/navigate-to-accessible-resource.tsx +8 -3
  76. package/src/components/app-shell/sidebar.tsx +21 -5
  77. package/src/components/auth/auto-redirect-provider.tsx +2 -1
  78. package/src/extensions/nocobase-acl/README.md +74 -0
  79. package/{registry → src/extensions}/nocobase-acl/components/acl-boundary.tsx +22 -25
  80. package/{registry → src/extensions}/nocobase-acl/components/role-switcher.tsx +26 -23
  81. package/src/extensions/nocobase-acl/demo/acl-preview-provider.tsx +81 -0
  82. package/{registry → src/extensions}/nocobase-acl/demo/boundary-api.tsx +58 -0
  83. package/{registry → src/extensions}/nocobase-acl/demo/index.tsx +243 -105
  84. package/{registry → src/extensions}/nocobase-acl/demo/prompt-generator.tsx +3 -1
  85. package/src/extensions/nocobase-acl/extension.tsx +73 -0
  86. package/{registry → src/extensions}/nocobase-ai/README.md +21 -5
  87. package/{registry → src/extensions}/nocobase-ai/components/chat/chat-composer.tsx +3 -1
  88. package/{registry → src/extensions}/nocobase-ai/components/chat/chat-messages.tsx +38 -3
  89. package/{registry → src/extensions}/nocobase-ai/components/chat/tool-call-card.tsx +1 -9
  90. package/{registry → src/extensions}/nocobase-ai/components/index.ts +5 -0
  91. package/src/extensions/nocobase-ai/components/surfaces/chat-dialog.tsx +17 -0
  92. package/src/extensions/nocobase-ai/components/surfaces/chat-side-panel.tsx +35 -0
  93. package/src/extensions/nocobase-ai/components/surfaces/chat-surface.tsx +108 -0
  94. package/{registry → src/extensions}/nocobase-ai/components/triggers/ai-chat-floating-trigger.tsx +2 -2
  95. package/{registry → src/extensions}/nocobase-ai/demo/configuration-gate.tsx +4 -1
  96. package/{registry → src/extensions}/nocobase-ai/demo/container-showcase.tsx +2 -2
  97. package/{registry → src/extensions}/nocobase-ai/demo/floating.tsx +45 -15
  98. package/{registry → src/extensions}/nocobase-ai/demo/index.tsx +116 -74
  99. package/{registry → src/extensions}/nocobase-ai/demo/prompt-generator.tsx +3 -3
  100. package/{registry → src/extensions}/nocobase-ai/demo/tool-cards.tsx +2 -3
  101. package/src/extensions/nocobase-ai/extension.tsx +160 -0
  102. package/{registry → src/extensions}/nocobase-ai/global-ai-chat.tsx +12 -28
  103. package/{registry → src/extensions}/nocobase-ai/providers/ai-provider.tsx +14 -1
  104. package/{registry → src/extensions}/nocobase-ai/providers/chat-context.tsx +1 -0
  105. package/{registry → src/extensions}/nocobase-ai/providers/chat-provider.tsx +29 -8
  106. package/{registry → src/extensions}/nocobase-ai/providers/use-chat-attachments.ts +6 -1
  107. package/{registry → src/extensions}/nocobase-ai/providers/use-chat-work-context.ts +4 -1
  108. package/{registry → src/extensions}/nocobase-route-surfaces/README.md +2 -1
  109. package/{registry → src/extensions}/nocobase-route-surfaces/demo/index.tsx +33 -7
  110. package/{registry → src/extensions}/nocobase-route-surfaces/demo/scenarios.ts +20 -14
  111. package/{registry → src/extensions}/nocobase-route-surfaces/extension.tsx +55 -52
  112. package/src/{pages/users → extensions/nocobase-users-example}/create.tsx +4 -4
  113. package/src/{pages/users → extensions/nocobase-users-example}/edit.tsx +5 -9
  114. package/src/extensions/nocobase-users-example/extension.tsx +109 -0
  115. package/src/{pages/users → extensions/nocobase-users-example}/form-context.ts +11 -9
  116. package/src/extensions/nocobase-users-example/layout.tsx +16 -0
  117. package/src/{pages/users → extensions/nocobase-users-example}/list.tsx +1 -1
  118. package/src/extensions/nocobase-users-example/locales/en-US.ts +77 -0
  119. package/src/extensions/nocobase-users-example/locales/index.ts +8 -0
  120. package/src/extensions/nocobase-users-example/locales/zh-CN.ts +73 -0
  121. package/src/extensions/nocobase-users-example/optional-ai.ts +67 -0
  122. package/src/{pages/users → extensions/nocobase-users-example}/role-detail.tsx +4 -15
  123. package/src/{pages/users → extensions/nocobase-users-example}/routes.ts +1 -4
  124. package/src/extensions/nocobase-users-example/show.tsx +266 -0
  125. package/src/lib/nocobase/acl/context.ts +32 -0
  126. package/src/lib/nocobase/acl/evaluator.ts +186 -0
  127. package/src/lib/nocobase/acl/hooks.ts +40 -0
  128. package/src/lib/nocobase/acl/index.ts +4 -1
  129. package/src/lib/nocobase/acl/menu.ts +6 -6
  130. package/src/lib/nocobase/acl/record-permissions.ts +37 -7
  131. package/src/lib/nocobase/acl/store-provider.tsx +14 -0
  132. package/src/lib/nocobase/acl/store.ts +92 -86
  133. package/src/lib/nocobase/acl/types.ts +52 -32
  134. package/src/lib/nocobase/auth-session.ts +128 -0
  135. package/src/lib/nocobase/client.ts +48 -50
  136. package/src/locales/en-US.ts +0 -78
  137. package/src/locales/index.ts +2 -7
  138. package/src/locales/zh-CN.ts +0 -74
  139. package/src/providers/access-control.ts +43 -8
  140. package/src/providers/auth-callback.ts +1 -0
  141. package/src/providers/auth.ts +24 -26
  142. package/src/providers/constants.ts +0 -4
  143. package/src/providers/data.ts +14 -26
  144. package/src/providers/runtime-config.ts +40 -0
  145. package/src/vite-env.d.ts +9 -0
  146. package/tests/auth-session-regression.mjs +101 -0
  147. package/tsconfig.json +2 -1
  148. package/vite.config.ts +9 -1
  149. package/dist/assets/VisualMapping-Cbv1v7Cd.js +0 -1
  150. package/dist/assets/ai-employee-shortcut-B253WWow.js +0 -1
  151. package/dist/assets/calendar-B3dXXyIv.js +0 -1
  152. package/dist/assets/chat-inline-xpQ9iq4p.js +0 -1
  153. package/dist/assets/chat-side-panel-layout-BVWsp5rr.js +0 -1
  154. package/dist/assets/components-ChhJaNRc.js +0 -20
  155. package/dist/assets/configuration-gate-Dwdq_lxf.js +0 -1
  156. package/dist/assets/createSeriesDataSimply-CI7l7Ufv.js +0 -1
  157. package/dist/assets/customGraphicKeyframeAnimation-DE3jSfMd.js +0 -3
  158. package/dist/assets/echarts-preview-C-cNUtJF.js +0 -1
  159. package/dist/assets/floating-BarTmn-b.js +0 -13
  160. package/dist/assets/index-BJIcYTdc.js +0 -53
  161. package/dist/assets/index-C6xNKxpg.js +0 -656
  162. package/dist/assets/index-D4JQi1TM.js +0 -54
  163. package/dist/assets/index-YA7-AUO8.css +0 -1
  164. package/dist/assets/index-g8zWVpP9.js +0 -23
  165. package/dist/assets/prompt-card-BsYMW_rq.js +0 -1
  166. package/dist/assets/shortcut-xtghDP63.js +0 -47
  167. package/registry/nocobase-acl/README.md +0 -19
  168. package/registry/nocobase-acl/extension.tsx +0 -71
  169. package/registry/nocobase-acl/tests/acl-regression.mjs +0 -314
  170. package/registry/nocobase-ai/components/surfaces/chat-dialog.tsx +0 -31
  171. package/registry/nocobase-ai/components/surfaces/chat-side-panel.tsx +0 -74
  172. package/registry/nocobase-ai/extension.tsx +0 -158
  173. package/registry/nocobase-ai/tests/business-report-regression.mjs +0 -70
  174. package/registry/nocobase-ai/tests/form-filler-regression.mjs +0 -129
  175. package/registry/nocobase-ai/tests/frontend-tool-regression.mjs +0 -128
  176. package/registry/nocobase-ai/tests/page-context-regression.mjs +0 -48
  177. package/registry/nocobase-ai/tests/stream-regression.mjs +0 -207
  178. package/registry/nocobase-auth-cas/README.md +0 -6
  179. package/registry/nocobase-auth-cas/cas-sign-in-button.tsx +0 -41
  180. package/registry/nocobase-auth-cas/demo.tsx +0 -20
  181. package/registry/nocobase-auth-cas/extension.tsx +0 -46
  182. package/registry/nocobase-auth-cas/index.ts +0 -1
  183. package/registry/nocobase-auth-cas/use-cas-sign-in.ts +0 -29
  184. package/registry/nocobase-auth-dingtalk/README.md +0 -7
  185. package/registry/nocobase-auth-dingtalk/auto-login-provider.tsx +0 -154
  186. package/registry/nocobase-auth-dingtalk/demo.tsx +0 -23
  187. package/registry/nocobase-auth-dingtalk/dingtalk-sign-in-button.tsx +0 -45
  188. package/registry/nocobase-auth-dingtalk/extension.tsx +0 -55
  189. package/registry/nocobase-auth-dingtalk/index.ts +0 -4
  190. package/registry/nocobase-auth-dingtalk/use-dingtalk-sign-in.ts +0 -64
  191. package/registry/nocobase-auth-ldap/README.md +0 -6
  192. package/registry/nocobase-auth-ldap/demo.tsx +0 -21
  193. package/registry/nocobase-auth-ldap/extension.tsx +0 -46
  194. package/registry/nocobase-auth-ldap/index.ts +0 -1
  195. package/registry/nocobase-auth-ldap/ldap-sign-in-form.tsx +0 -69
  196. package/registry/nocobase-auth-ldap/use-ldap-sign-in.ts +0 -5
  197. package/registry/nocobase-auth-oidc/README.md +0 -11
  198. package/registry/nocobase-auth-oidc/auto-redirect-provider.tsx +0 -13
  199. package/registry/nocobase-auth-oidc/demo.tsx +0 -20
  200. package/registry/nocobase-auth-oidc/extension.tsx +0 -51
  201. package/registry/nocobase-auth-oidc/index.ts +0 -1
  202. package/registry/nocobase-auth-oidc/oidc-sign-in-button.tsx +0 -44
  203. package/registry/nocobase-auth-oidc/use-oidc-sign-in.ts +0 -58
  204. package/registry/nocobase-auth-saml/README.md +0 -6
  205. package/registry/nocobase-auth-saml/auto-redirect-provider.tsx +0 -13
  206. package/registry/nocobase-auth-saml/demo.tsx +0 -20
  207. package/registry/nocobase-auth-saml/extension.tsx +0 -51
  208. package/registry/nocobase-auth-saml/index.ts +0 -1
  209. package/registry/nocobase-auth-saml/saml-sign-in-button.tsx +0 -43
  210. package/registry/nocobase-auth-saml/use-saml-sign-in.ts +0 -51
  211. package/registry/nocobase-auth-sms/README.md +0 -7
  212. package/registry/nocobase-auth-sms/demo.tsx +0 -25
  213. package/registry/nocobase-auth-sms/extension.tsx +0 -46
  214. package/registry/nocobase-auth-sms/index.ts +0 -1
  215. package/registry/nocobase-auth-sms/sms-sign-in-form.tsx +0 -107
  216. package/registry/nocobase-auth-sms/use-sms-sign-in.ts +0 -88
  217. package/registry/nocobase-auth-wecom/README.md +0 -6
  218. package/registry/nocobase-auth-wecom/auto-login-provider.tsx +0 -21
  219. package/registry/nocobase-auth-wecom/demo.tsx +0 -23
  220. package/registry/nocobase-auth-wecom/extension.tsx +0 -49
  221. package/registry/nocobase-auth-wecom/index.ts +0 -1
  222. package/registry/nocobase-auth-wecom/use-wecom-sign-in.ts +0 -62
  223. package/registry/nocobase-auth-wecom/wecom-sign-in-button.tsx +0 -70
  224. package/registry/nocobase-i18n/README.md +0 -44
  225. package/registry/nocobase-i18n/components/index.ts +0 -1
  226. package/registry/nocobase-i18n/components/language-switcher.tsx +0 -138
  227. package/registry/nocobase-i18n/demo/index.tsx +0 -209
  228. package/registry/nocobase-i18n/demo/prompt-generator.tsx +0 -132
  229. package/registry/nocobase-i18n/extension.tsx +0 -45
  230. package/registry/nocobase-i18n/index.ts +0 -7
  231. package/registry/nocobase-i18n/locales/en-US.ts +0 -39
  232. package/registry/nocobase-i18n/locales/index.ts +0 -8
  233. package/registry/nocobase-i18n/locales/zh-CN.ts +0 -35
  234. package/registry/nocobase-i18n/provider.tsx +0 -44
  235. package/registry/nocobase-i18n/server-resources.ts +0 -166
  236. package/registry/nocobase-i18n/tests/i18n-regression.mjs +0 -51
  237. package/registry.config.json +0 -302
  238. package/scripts/registry.mjs +0 -164
  239. package/src/components/access-control/resource-access-guard.tsx +0 -21
  240. package/src/components/access-control/use-acl-runtime.ts +0 -28
  241. package/src/lib/nocobase/acl/action.ts +0 -147
  242. package/src/pages/users/layout.tsx +0 -15
  243. package/src/pages/users/show.tsx +0 -278
  244. /package/{registry → src/extensions}/nocobase-acl/components/index.ts +0 -0
  245. /package/{registry → src/extensions}/nocobase-acl/components/role-options.ts +0 -0
  246. /package/{registry → src/extensions}/nocobase-acl/demo/components.tsx +0 -0
  247. /package/{registry → src/extensions}/nocobase-acl/demo/lazy-route.tsx +0 -0
  248. /package/{registry → src/extensions}/nocobase-acl/demo/role-switcher-prompt-generator.tsx +0 -0
  249. /package/{registry → src/extensions}/nocobase-acl/demo/scenario-section.tsx +0 -0
  250. /package/{registry → src/extensions}/nocobase-acl/index.ts +0 -0
  251. /package/{registry → src/extensions}/nocobase-ai/adapters/react-hook-form.ts +0 -0
  252. /package/{registry → src/extensions}/nocobase-ai/assets/nocobase-ai-chat.svg +0 -0
  253. /package/{registry → src/extensions}/nocobase-ai/components/ai-root-provider.tsx +0 -0
  254. /package/{registry → src/extensions}/nocobase-ai/components/chat/ai-employee-avatar.tsx +0 -0
  255. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-attachment.tsx +0 -0
  256. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-compact.tsx +0 -0
  257. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-empty-state.tsx +0 -0
  258. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-header.tsx +0 -0
  259. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-history-dialog.tsx +0 -0
  260. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-message.tsx +0 -0
  261. /package/{registry → src/extensions}/nocobase-ai/components/chat/chat-window.tsx +0 -0
  262. /package/{registry → src/extensions}/nocobase-ai/components/chat/conversation-list.tsx +0 -0
  263. /package/{registry → src/extensions}/nocobase-ai/components/chat/markdown-message.tsx +0 -0
  264. /package/{registry → src/extensions}/nocobase-ai/components/chat/model-select-options.tsx +0 -0
  265. /package/{registry → src/extensions}/nocobase-ai/components/chat/reasoning-panel.tsx +0 -0
  266. /package/{registry → src/extensions}/nocobase-ai/components/chat/sub-agent-conversation.tsx +0 -0
  267. /package/{registry → src/extensions}/nocobase-ai/components/chat/user-prompt-editor.tsx +0 -0
  268. /package/{registry → src/extensions}/nocobase-ai/components/chat/work-context-chip.tsx +0 -0
  269. /package/{registry → src/extensions}/nocobase-ai/components/page-elements/ai-form.tsx +0 -0
  270. /package/{registry → src/extensions}/nocobase-ai/components/page-elements/page-element-provider.tsx +0 -0
  271. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-inline.tsx +0 -0
  272. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-page.tsx +0 -0
  273. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-side-panel-layout.tsx +0 -0
  274. /package/{registry → src/extensions}/nocobase-ai/components/surfaces/chat-surface-actions.tsx +0 -0
  275. /package/{registry → src/extensions}/nocobase-ai/components/tools/builtin-tool-renderers.tsx +0 -0
  276. /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-dialog.tsx +0 -0
  277. /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-renderer.tsx +0 -0
  278. /package/{registry → src/extensions}/nocobase-ai/components/tools/business-report-utils.tsx +0 -0
  279. /package/{registry → src/extensions}/nocobase-ai/components/tools/chart-renderer.tsx +0 -0
  280. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-preview.tsx +0 -0
  281. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-advanced.ts +0 -0
  282. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-common.ts +0 -0
  283. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-components.ts +0 -0
  284. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime-hierarchy.ts +0 -0
  285. /package/{registry → src/extensions}/nocobase-ai/components/tools/echarts-runtime.ts +0 -0
  286. /package/{registry → src/extensions}/nocobase-ai/components/tools/sub-agent-renderer.tsx +0 -0
  287. /package/{registry → src/extensions}/nocobase-ai/components/tools/suggestions-renderer.tsx +0 -0
  288. /package/{registry → src/extensions}/nocobase-ai/components/tools/tool-renderer-provider.tsx +0 -0
  289. /package/{registry → src/extensions}/nocobase-ai/components/tools/tool-renderer-utils.ts +0 -0
  290. /package/{registry → src/extensions}/nocobase-ai/components/tools/workflow-renderer.tsx +0 -0
  291. /package/{registry → src/extensions}/nocobase-ai/components/triggers/ai-employee-shortcut.tsx +0 -0
  292. /package/{registry → src/extensions}/nocobase-ai/demo/interaction-showcase.tsx +0 -0
  293. /package/{registry → src/extensions}/nocobase-ai/demo/page-context-prompt-generator.tsx +0 -0
  294. /package/{registry → src/extensions}/nocobase-ai/demo/page-context.tsx +0 -0
  295. /package/{registry → src/extensions}/nocobase-ai/demo/page-element-showcase.tsx +0 -0
  296. /package/{registry → src/extensions}/nocobase-ai/demo/prompt-card.tsx +0 -0
  297. /package/{registry → src/extensions}/nocobase-ai/demo/shortcut.tsx +0 -0
  298. /package/{registry → src/extensions}/nocobase-ai/index.ts +0 -0
  299. /package/{registry → src/extensions}/nocobase-ai/providers/avatars.ts +0 -0
  300. /package/{registry → src/extensions}/nocobase-ai/providers/chat-controller.ts +0 -0
  301. /package/{registry → src/extensions}/nocobase-ai/providers/chat-message-utils.ts +0 -0
  302. /package/{registry → src/extensions}/nocobase-ai/providers/chat-reducer.ts +0 -0
  303. /package/{registry → src/extensions}/nocobase-ai/providers/chat-task-utils.ts +0 -0
  304. /package/{registry → src/extensions}/nocobase-ai/providers/chat-transport.ts +0 -0
  305. /package/{registry → src/extensions}/nocobase-ai/providers/form-registry.tsx +0 -0
  306. /package/{registry → src/extensions}/nocobase-ai/providers/frontend-tool-registry.tsx +0 -0
  307. /package/{registry → src/extensions}/nocobase-ai/providers/index.ts +0 -0
  308. /package/{registry → src/extensions}/nocobase-ai/providers/model.ts +0 -0
  309. /package/{registry → src/extensions}/nocobase-ai/providers/page-context.tsx +0 -0
  310. /package/{registry → src/extensions}/nocobase-ai/providers/stream-coalescer.ts +0 -0
  311. /package/{registry → src/extensions}/nocobase-ai/providers/stream-event-utils.ts +0 -0
  312. /package/{registry → src/extensions}/nocobase-ai/providers/stream-parser.ts +0 -0
  313. /package/{registry → src/extensions}/nocobase-ai/providers/sub-agent-stream.ts +0 -0
  314. /package/{registry → src/extensions}/nocobase-ai/providers/types.ts +0 -0
  315. /package/{registry → src/extensions}/nocobase-ai/providers/ui-message-stream.ts +0 -0
  316. /package/{registry → src/extensions}/nocobase-ai/providers/use-automatic-tool-approval.ts +0 -0
  317. /package/{registry → src/extensions}/nocobase-ai/providers/use-chat-message-actions.ts +0 -0
  318. /package/{registry → src/extensions}/nocobase-ai/providers/use-chat-runtime.ts +0 -0
  319. /package/{registry → src/extensions}/nocobase-ai/providers/use-conversation-catalog.ts +0 -0
  320. /package/{registry → src/extensions}/nocobase-ai/providers/use-conversation-history.ts +0 -0
  321. /package/{registry → src/extensions}/nocobase-ai/services/index.ts +0 -0
  322. /package/{registry → src/extensions}/nocobase-ai/services/nocobase-ai-service.ts +0 -0
  323. /package/{registry → src/extensions}/nocobase-ai/services/types.ts +0 -0
  324. /package/{registry → src/extensions}/nocobase-route-surfaces/demo/lazy-route.tsx +0 -0
  325. /package/{registry → src/extensions}/nocobase-route-surfaces/demo/prompt-generator.tsx +0 -0
  326. /package/{registry → src/extensions}/nocobase-route-surfaces/index.ts +0 -0
  327. /package/{registry → src/extensions}/nocobase-route-surfaces/route-dialog.tsx +0 -0
  328. /package/{registry → src/extensions}/nocobase-route-surfaces/route-drawer.tsx +0 -0
  329. /package/{registry → src/extensions}/nocobase-route-surfaces/route-page.tsx +0 -0
  330. /package/{registry → src/extensions}/nocobase-route-surfaces/route-surface-context.ts +0 -0
  331. /package/{registry → src/extensions}/nocobase-route-surfaces/use-refine-unsaved-changes.tsx +0 -0
  332. /package/{registry → src/extensions}/nocobase-route-surfaces/use-route-surface-close.ts +0 -0
  333. /package/{registry → src/extensions}/nocobase-route-surfaces/use-route-surface-state.ts +0 -0
  334. /package/src/{pages/users → extensions/nocobase-users-example}/form-fields.tsx +0 -0
  335. /package/src/{pages/users → extensions/nocobase-users-example}/index.ts +0 -0
  336. /package/src/{pages/users → extensions/nocobase-users-example}/role-badges.tsx +0 -0
  337. /package/src/{pages/users → extensions/nocobase-users-example}/role-utils.ts +0 -0
  338. /package/src/{pages/users → extensions/nocobase-users-example}/types.ts +0 -0
@@ -1,209 +0,0 @@
1
- import { useGetLocale, useTranslate } from "@refinedev/core";
2
- import { Database, Languages, PanelsTopLeft } from "lucide-react";
3
-
4
- import { Badge } from "@/components/ui/badge";
5
- import {
6
- Card,
7
- CardContent,
8
- CardDescription,
9
- CardHeader,
10
- CardTitle,
11
- } from "@/components/ui/card";
12
- import { nocobaseClient } from "@/lib/nocobase/client";
13
- import {
14
- LanguageSwitcher,
15
- useEnabledLocales,
16
- } from "@/extensions/nocobase-i18n";
17
- import { I18nPromptGenerator } from "./prompt-generator";
18
-
19
- export function I18nDemoPage() {
20
- const t = useTranslate();
21
- const getLocale = useGetLocale();
22
- const locale = getLocale();
23
- const locales = useEnabledLocales();
24
- const canSwitchLanguage = locales.length > 1;
25
-
26
- return (
27
- <div className="space-y-10 pb-12">
28
- <header className="space-y-2">
29
- <div className="flex items-center gap-2">
30
- <Badge variant="secondary">i18n</Badge>
31
- <Badge variant="outline">{locale}</Badge>
32
- </div>
33
- <h1 className="text-2xl font-semibold tracking-[-0.025em] sm:text-3xl">
34
- {t("demo.title", { ns: "nocobase-i18n" }, "Internationalization")}
35
- </h1>
36
- <p className="max-w-3xl text-sm leading-6 text-muted-foreground">
37
- {t(
38
- "demo.description",
39
- { ns: "nocobase-i18n" },
40
- "Optional NocoBase server translations and language controls built on the Starter's internationalization runtime."
41
- )}
42
- </p>
43
- </header>
44
-
45
- <section className="grid gap-5 xl:grid-cols-3">
46
- <Card>
47
- <CardHeader>
48
- <CardTitle className="flex items-center gap-2">
49
- <Languages className="size-4" />
50
- {t(
51
- "demo.switcher.title",
52
- { ns: "nocobase-i18n" },
53
- "Language switcher"
54
- )}
55
- </CardTitle>
56
- <CardDescription>
57
- {t(
58
- "demo.switcher.description",
59
- { ns: "nocobase-i18n" },
60
- "The same reusable component is also integrated into the signed-in user menu."
61
- )}
62
- </CardDescription>
63
- </CardHeader>
64
- <CardContent>
65
- {canSwitchLanguage ? (
66
- <LanguageSwitcher className="max-w-sm" />
67
- ) : (
68
- <div className="flex items-start gap-3 rounded-lg border bg-muted/30 p-4">
69
- <Languages className="mt-0.5 size-5 shrink-0 text-muted-foreground" />
70
- <div>
71
- <p className="text-sm font-medium">
72
- {t(
73
- "demo.switcher.unavailable.title",
74
- { ns: "nocobase-i18n" },
75
- "Only one language is enabled"
76
- )}
77
- </p>
78
- <p className="mt-1 text-xs leading-5 text-muted-foreground">
79
- {t(
80
- "demo.switcher.unavailable.description",
81
- { ns: "nocobase-i18n" },
82
- "Enable another language in NocoBase system settings to display the switcher."
83
- )}
84
- </p>
85
- </div>
86
- </div>
87
- )}
88
- </CardContent>
89
- </Card>
90
-
91
- <CapabilityCard
92
- icon={<PanelsTopLeft className="size-4" />}
93
- title={t(
94
- "demo.frontend.title",
95
- { ns: "nocobase-i18n" },
96
- "Application UI translations"
97
- )}
98
- description={t(
99
- "demo.frontend.description",
100
- { ns: "nocobase-i18n" },
101
- "The Starter provides the runtime while application and Registry components keep their messages in local resource files."
102
- )}
103
- >
104
- <div className="divide-y rounded-lg border">
105
- <DemoRow
106
- label={t(
107
- "language.current",
108
- { ns: "nocobase-i18n" },
109
- "Current language"
110
- )}
111
- value={locale}
112
- />
113
- <DemoRow
114
- label={t(
115
- "demo.frontend.actions",
116
- { ns: "nocobase-i18n" },
117
- "Common actions"
118
- )}
119
- value={`${t("buttons.apply", "Apply")} · ${t(
120
- "buttons.clear",
121
- "Clear"
122
- )}`}
123
- />
124
- </div>
125
- </CapabilityCard>
126
-
127
- <CapabilityCard
128
- icon={<Database className="size-4" />}
129
- title={t(
130
- "demo.server.title",
131
- { ns: "nocobase-i18n" },
132
- "NocoBase metadata translations"
133
- )}
134
- description={t(
135
- "demo.server.description",
136
- { ns: "nocobase-i18n" },
137
- "Collection and field labels are loaded from dynamic server namespaces such as lm-collections."
138
- )}
139
- >
140
- <div className="divide-y rounded-lg border">
141
- <DemoRow
142
- label="Users"
143
- value={t("Users", { ns: "lm-collections" }, "Users")}
144
- />
145
- <DemoRow
146
- label="Nickname"
147
- value={t("Nickname", { ns: "lm-collections" }, "Nickname")}
148
- />
149
- <DemoRow
150
- label="X-Locale"
151
- value={nocobaseClient.getLocale() ?? locale}
152
- code
153
- />
154
- </div>
155
- </CapabilityCard>
156
- </section>
157
-
158
- <section className="border-t pt-8">
159
- <I18nPromptGenerator />
160
- </section>
161
- </div>
162
- );
163
- }
164
-
165
- function DemoRow({
166
- code,
167
- label,
168
- value,
169
- }: {
170
- code?: boolean;
171
- label: string;
172
- value: string;
173
- }) {
174
- return (
175
- <div className="flex items-center justify-between gap-4 px-3 py-2.5">
176
- <span className="text-xs text-muted-foreground">{label}</span>
177
- {code ? (
178
- <code className="rounded bg-muted px-2 py-1 text-xs">{value}</code>
179
- ) : (
180
- <span className="text-sm font-medium">{value}</span>
181
- )}
182
- </div>
183
- );
184
- }
185
-
186
- function CapabilityCard({
187
- children,
188
- description,
189
- icon,
190
- title,
191
- }: {
192
- children: React.ReactNode;
193
- description: string;
194
- icon: React.ReactNode;
195
- title: string;
196
- }) {
197
- return (
198
- <Card>
199
- <CardHeader>
200
- <CardTitle className="flex items-center gap-2">
201
- {icon}
202
- {title}
203
- </CardTitle>
204
- <CardDescription>{description}</CardDescription>
205
- </CardHeader>
206
- <CardContent className="text-sm">{children}</CardContent>
207
- </Card>
208
- );
209
- }
@@ -1,132 +0,0 @@
1
- import { useTranslate } from "@refinedev/core";
2
- import { ChevronDown, Sparkles } from "lucide-react";
3
- import { useMemo, useState } from "react";
4
-
5
- import { PromptOutput } from "@/components/demo/prompt-output";
6
- import {
7
- Card,
8
- CardContent,
9
- CardDescription,
10
- CardHeader,
11
- CardTitle,
12
- } from "@/components/ui/card";
13
- import { Input } from "@/components/ui/input";
14
- import { Label } from "@/components/ui/label";
15
- import { Textarea } from "@/components/ui/textarea";
16
-
17
- export function I18nPromptGenerator() {
18
- const t = useTranslate();
19
- const [scene, setScene] = useState("A customer support workspace");
20
- const [languages, setLanguages] = useState("English and Simplified Chinese");
21
-
22
- const prompt = useMemo(
23
- () => `Build a complete multilingual scene in the NocoBase Admin Starter.
24
-
25
- Application scene
26
- - Product or page: ${scene}
27
- - Supported languages: ${languages}
28
- - Translate the complete visible user flow, including empty, loading, validation, and error states.
29
-
30
- Implementation contract
31
- - Use the Starter's @/providers/i18n runtime and the application's translation and locale hooks.
32
- - Put application-owned React messages in src/locales and register the app namespace through registerTranslationResources from @/lib/i18n.
33
- - Keep each Registry component's messages in its own namespace and register them with registerLocaleResources().
34
- - Do not place application messages inside src/extensions/nocobase-i18n/locales because installed Registry files may be refreshed independently.
35
- - Use the reusable LanguageSwitcher when the page needs an explicit language control; the signed-in user menu already includes one.
36
- - Reuse the Starter's shared system settings instead of requesting systemSettings:get again.
37
- - Keep Starter and Registry UI resources local. Use app:getLang only for registered dynamic server namespaces such as lm-collections when the NocoBase i18n Registry is installed.
38
- - Let the shared NocoBase client send the selected locale through X-Locale.
39
- - Preserve compatibility when server metadata contains exact {{t("...")}} expressions.
40
- - Provide complete React components, locale resource files, route/resource integration, and realistic visible content.`,
41
- [languages, scene]
42
- );
43
-
44
- return (
45
- <details open className="group rounded-xl border bg-muted/15">
46
- <summary className="flex cursor-pointer list-none items-center gap-2 px-4 py-3 text-sm font-medium marker:hidden">
47
- <Sparkles className="size-4 text-primary" />
48
- {t("demo.prompt.title", { ns: "nocobase-i18n" }, "Prompt generator")}
49
- <ChevronDown className="ml-auto size-4 text-muted-foreground transition-transform group-open:rotate-180" />
50
- </summary>
51
- <div className="grid items-start gap-5 border-t p-4 xl:grid-cols-[360px_minmax(0,1fr)]">
52
- <Card className="gap-0 py-0">
53
- <CardHeader className="border-b py-4">
54
- <CardTitle className="text-base">
55
- {t(
56
- "demo.prompt.settings",
57
- { ns: "nocobase-i18n" },
58
- "Scene settings"
59
- )}
60
- </CardTitle>
61
- <CardDescription>
62
- {t(
63
- "demo.prompt.description",
64
- { ns: "nocobase-i18n" },
65
- "Describe a complete multilingual application scene and generate an implementation prompt."
66
- )}
67
- </CardDescription>
68
- </CardHeader>
69
- <CardContent className="space-y-5 py-5">
70
- <div className="space-y-2">
71
- <Label htmlFor="i18n-prompt-scene">
72
- {t(
73
- "demo.prompt.scene",
74
- { ns: "nocobase-i18n" },
75
- "Application scene"
76
- )}
77
- </Label>
78
- <Input
79
- id="i18n-prompt-scene"
80
- value={scene}
81
- onChange={(event) => setScene(event.target.value)}
82
- />
83
- </div>
84
- <div className="space-y-2">
85
- <Label htmlFor="i18n-prompt-languages">
86
- {t(
87
- "demo.prompt.languages",
88
- { ns: "nocobase-i18n" },
89
- "Languages"
90
- )}
91
- </Label>
92
- <Textarea
93
- id="i18n-prompt-languages"
94
- value={languages}
95
- onChange={(event) => setLanguages(event.target.value)}
96
- className="min-h-24"
97
- />
98
- </div>
99
- </CardContent>
100
- </Card>
101
- <PromptOutput
102
- title={t(
103
- "demo.prompt.output",
104
- { ns: "nocobase-i18n" },
105
- "Generated prompt"
106
- )}
107
- description={t(
108
- "demo.prompt.outputDescription",
109
- { ns: "nocobase-i18n" },
110
- "Updates as you change the scene and language requirements."
111
- )}
112
- prompt={prompt}
113
- copyLabel={t(
114
- "demo.prompt.copy",
115
- { ns: "nocobase-i18n" },
116
- "Copy prompt"
117
- )}
118
- copiedLabel={t(
119
- "demo.prompt.copied",
120
- { ns: "nocobase-i18n" },
121
- "Copied"
122
- )}
123
- copyErrorLabel={t(
124
- "demo.prompt.copyError",
125
- { ns: "nocobase-i18n" },
126
- "Clipboard access failed. Select the prompt and copy it manually."
127
- )}
128
- />
129
- </div>
130
- </details>
131
- );
132
- }
@@ -1,45 +0,0 @@
1
- import type { AppExtension } from "@/app/extension";
2
- import { LoadingState } from "@/components/app-shell/loading-state";
3
- import { Languages } from "lucide-react";
4
- import { lazy, Suspense } from "react";
5
- import { Route } from "react-router";
6
- import { LanguageUserMenuItems } from "./components";
7
- import "./locales";
8
- import { NocoBaseI18nBootstrap } from "./provider";
9
-
10
- const I18nDemoPage = lazy(() =>
11
- import("./demo").then((module) => ({ default: module.I18nDemoPage }))
12
- );
13
-
14
- const nocobaseI18nExtension: AppExtension = {
15
- id: "nocobase-i18n",
16
- Provider: NocoBaseI18nBootstrap,
17
- UserMenuItems: LanguageUserMenuItems,
18
- resources: [
19
- {
20
- name: "i18n-demo",
21
- list: "/i18n",
22
- meta: {
23
- label: "Internationalization",
24
- i18nKey: "navigation.demo",
25
- i18nOptions: { ns: "nocobase-i18n" },
26
- icon: <Languages />,
27
- description: "Optional frontend internationalization for the Starter.",
28
- acl: { type: "authenticated" },
29
- },
30
- },
31
- ],
32
- routes: (
33
- <Route
34
- key="nocobase-i18n-demo"
35
- path="/i18n"
36
- element={
37
- <Suspense fallback={<LoadingState className="min-h-80" />}>
38
- <I18nDemoPage />
39
- </Suspense>
40
- }
41
- />
42
- ),
43
- };
44
-
45
- export default nocobaseI18nExtension;
@@ -1,7 +0,0 @@
1
- export * from "./components";
2
- export * from "./provider";
3
- export * from "./server-resources";
4
- export {
5
- registerLocaleResources,
6
- useEnabledLocales,
7
- } from "@/providers/i18n";
@@ -1,39 +0,0 @@
1
- const enUS = {
2
- "language.label": "Language",
3
- "language.current": "Current language",
4
- "language.switchError": "Unable to switch language.",
5
- "navigation.group": "Localization",
6
- "navigation.demo": "Internationalization",
7
- "demo.title": "Internationalization",
8
- "demo.description":
9
- "Optional NocoBase server translations and language controls built on the Starter's internationalization runtime.",
10
- "demo.switcher.title": "Language switcher",
11
- "demo.switcher.description":
12
- "The same reusable component is also integrated into the signed-in user menu.",
13
- "demo.switcher.unavailable.title": "Only one language is enabled",
14
- "demo.switcher.unavailable.description":
15
- "Enable another language in NocoBase system settings to display the switcher.",
16
- "demo.frontend.title": "Application UI translations",
17
- "demo.frontend.description":
18
- "The Starter provides the runtime while application and Registry components keep their messages in local resource files.",
19
- "demo.frontend.actions": "Common actions",
20
- "demo.server.title": "NocoBase metadata translations",
21
- "demo.server.description":
22
- "Collection and field labels are loaded from dynamic server namespaces such as lm-collections.",
23
- "demo.currentLocale": "Current locale: {{locale}}",
24
- "demo.prompt.title": "Prompt generator",
25
- "demo.prompt.description":
26
- "Describe a complete multilingual application scene and generate an implementation prompt.",
27
- "demo.prompt.settings": "Scene settings",
28
- "demo.prompt.scene": "Application scene",
29
- "demo.prompt.languages": "Languages",
30
- "demo.prompt.copy": "Copy prompt",
31
- "demo.prompt.copied": "Copied",
32
- "demo.prompt.copyError":
33
- "Clipboard access failed. Select the prompt and copy it manually.",
34
- "demo.prompt.output": "Generated prompt",
35
- "demo.prompt.outputDescription":
36
- "Updates as you change the scene and language requirements.",
37
- } as const;
38
-
39
- export default enUS;
@@ -1,8 +0,0 @@
1
- import { registerLocaleResources } from "@/providers/i18n";
2
- import enUS from "./en-US";
3
- import zhCN from "./zh-CN";
4
-
5
- registerLocaleResources("nocobase-i18n", {
6
- "en-US": enUS,
7
- "zh-CN": zhCN,
8
- });
@@ -1,35 +0,0 @@
1
- const zhCN = {
2
- "language.label": "语言",
3
- "language.current": "当前语言",
4
- "language.switchError": "无法切换语言。",
5
- "navigation.group": "本地化",
6
- "navigation.demo": "国际化",
7
- "demo.title": "国际化",
8
- "demo.description":
9
- "基于 Starter 国际化运行时的可选 NocoBase 服务端翻译与语言切换能力。",
10
- "demo.switcher.title": "语言切换器",
11
- "demo.switcher.description": "同一个可复用组件也会集成到登录用户菜单中。",
12
- "demo.switcher.unavailable.title": "当前仅启用一种语言",
13
- "demo.switcher.unavailable.description":
14
- "请在 NocoBase 系统设置中启用其他语言,语言切换器才会显示。",
15
- "demo.frontend.title": "应用 UI 文案翻译",
16
- "demo.frontend.description":
17
- "Starter 提供运行时,应用和 Registry 组件分别维护自己的本地语言资源。",
18
- "demo.frontend.actions": "常用操作",
19
- "demo.server.title": "NocoBase 元数据翻译",
20
- "demo.server.description":
21
- "数据表和字段名称从 lm-collections 等服务端动态 namespace 加载。",
22
- "demo.currentLocale": "当前语言:{{locale}}",
23
- "demo.prompt.title": "提示词生成器",
24
- "demo.prompt.description": "描述完整的多语言应用场景并生成实现提示词。",
25
- "demo.prompt.settings": "场景设置",
26
- "demo.prompt.scene": "应用场景",
27
- "demo.prompt.languages": "语言",
28
- "demo.prompt.copy": "复制提示词",
29
- "demo.prompt.copied": "已复制",
30
- "demo.prompt.copyError": "无法访问剪贴板,请手动选中并复制提示词。",
31
- "demo.prompt.output": "生成的提示词",
32
- "demo.prompt.outputDescription": "修改场景和语言要求时会实时更新。",
33
- } as const;
34
-
35
- export default zhCN;
@@ -1,44 +0,0 @@
1
- import { useEffect, useState, type PropsWithChildren } from "react";
2
-
3
- import { LoadingState } from "@/components/app-shell/loading-state";
4
- import { nocobaseClient } from "@/lib/nocobase/client";
5
- import { setLocalePersistence } from "@/providers/i18n";
6
- import { useSystemSettings } from "@/providers/system-settings";
7
- import { loadServerLocaleResources } from "./server-resources";
8
-
9
- export function NocoBaseI18nBootstrap({ children }: PropsWithChildren) {
10
- const { settings } = useSystemSettings();
11
- const [ready, setReady] = useState(false);
12
-
13
- useEffect(
14
- () =>
15
- setLocalePersistence(async (locale) => {
16
- if (!nocobaseClient.getToken()) return;
17
- await nocobaseClient.action("users", "updateLang", {
18
- method: "POST",
19
- body: { appLang: locale },
20
- });
21
- }),
22
- []
23
- );
24
-
25
- useEffect(() => {
26
- let active = true;
27
- void loadServerLocaleResources(settings)
28
- .catch((error) => {
29
- console.warn("Unable to load NocoBase locale resources", error);
30
- })
31
- .finally(() => {
32
- if (active) setReady(true);
33
- });
34
- return () => {
35
- active = false;
36
- };
37
- }, [settings]);
38
-
39
- if (!ready) {
40
- return <LoadingState className="min-h-80" />;
41
- }
42
-
43
- return children;
44
- }
@@ -1,166 +0,0 @@
1
- import { nocobaseClient } from "@/lib/nocobase/client";
2
- import {
3
- type LocaleSystemSettings,
4
- applyDocumentLocale,
5
- getCurrentLocale,
6
- i18n,
7
- registerLocale,
8
- setEnabledLocales,
9
- } from "@/providers/i18n";
10
-
11
- type ServerLanguagePayload = {
12
- lang?: string;
13
- resources?: Record<string, Record<string, string>>;
14
- };
15
-
16
- const serverResourceNamespaces = new Set(["lm-collections"]);
17
- const loadedServerResourceNamespaces = new Set<string>();
18
- const namespaceLoadPromises = new Map<string, Promise<void>>();
19
- let cachedServerResources: ServerLanguagePayload["resources"] = {};
20
- let serverResourcesPromise: Promise<void> | undefined;
21
- let bootstrapStarted = false;
22
- let bootstrapComplete = false;
23
-
24
- function mergeNamespace(namespace: string, locale?: string) {
25
- const resource = cachedServerResources?.[namespace];
26
- if (!locale || !resource) return false;
27
- i18n.addResourceBundle(locale, namespace, resource, true, false);
28
- loadedServerResourceNamespaces.add(namespace);
29
- return true;
30
- }
31
-
32
- async function requestServerResources(
33
- namespaces: string[],
34
- requestedLocale?: string
35
- ) {
36
- const payload = await nocobaseClient.action<ServerLanguagePayload>(
37
- "app",
38
- "getLang",
39
- {
40
- method: "GET",
41
- query: {
42
- ...(requestedLocale ? { locale: requestedLocale } : {}),
43
- ...(namespaces.length ? { ns: namespaces.join(",") } : {}),
44
- },
45
- includeRole: false,
46
- withAclMeta: false,
47
- }
48
- );
49
-
50
- cachedServerResources = {
51
- ...cachedServerResources,
52
- ...payload.resources,
53
- };
54
- for (const namespace of namespaces) {
55
- mergeNamespace(namespace, payload.lang);
56
- loadedServerResourceNamespaces.add(namespace);
57
- }
58
-
59
- return payload;
60
- }
61
-
62
- async function ensureServerResourceNamespaces(namespaces: string[]) {
63
- const pending: Promise<void>[] = [];
64
- const missing: string[] = [];
65
-
66
- for (const namespace of namespaces) {
67
- if (loadedServerResourceNamespaces.has(namespace)) continue;
68
- if (mergeNamespace(namespace, getCurrentLocale())) continue;
69
- const existing = namespaceLoadPromises.get(namespace);
70
- if (existing) pending.push(existing);
71
- else missing.push(namespace);
72
- }
73
-
74
- if (missing.length) {
75
- const request = requestServerResources(
76
- missing,
77
- nocobaseClient.getStoredLocale() ?? getCurrentLocale()
78
- ).then(() => undefined);
79
- for (const namespace of missing) {
80
- namespaceLoadPromises.set(namespace, request);
81
- }
82
- const cleanup = () => {
83
- for (const namespace of missing) {
84
- if (namespaceLoadPromises.get(namespace) === request) {
85
- namespaceLoadPromises.delete(namespace);
86
- }
87
- }
88
- };
89
- void request.then(cleanup, cleanup);
90
- pending.push(request);
91
- }
92
-
93
- await Promise.all(pending);
94
- }
95
-
96
- export function registerServerResourceNamespace(namespace: string) {
97
- if (!namespace) return;
98
- serverResourceNamespaces.add(namespace);
99
-
100
- if (
101
- mergeNamespace(namespace, getCurrentLocale()) ||
102
- !bootstrapStarted ||
103
- !bootstrapComplete
104
- ) {
105
- return;
106
- }
107
-
108
- void ensureServerResourceNamespaces([namespace]).catch((error) => {
109
- console.warn(
110
- `Unable to load NocoBase locale namespace ${namespace}`,
111
- error
112
- );
113
- });
114
- }
115
-
116
- export function getServerResourceNamespaces() {
117
- return [...serverResourceNamespaces];
118
- }
119
-
120
- export function loadServerLocaleResources(settings?: LocaleSystemSettings) {
121
- if (serverResourcesPromise) return serverResourcesPromise;
122
-
123
- bootstrapStarted = true;
124
- const requestedLocale = nocobaseClient.getStoredLocale();
125
- const initialNamespaces = [...serverResourceNamespaces];
126
- const configuredLocales = Array.isArray(settings?.enabledLanguages)
127
- ? settings.enabledLanguages
128
- : [];
129
- if (configuredLocales.length) setEnabledLocales(configuredLocales);
130
- const languagePromise = requestServerResources(
131
- initialNamespaces,
132
- requestedLocale
133
- );
134
-
135
- serverResourcesPromise = languagePromise
136
- .then(async (payload) => {
137
- const serverLocale = payload.lang;
138
-
139
- if (!configuredLocales.length && serverLocale) {
140
- setEnabledLocales([serverLocale]);
141
- }
142
-
143
- if (serverLocale) {
144
- registerLocale({ locale: serverLocale, label: serverLocale });
145
- nocobaseClient.setLocale(serverLocale);
146
- await i18n.changeLanguage(serverLocale);
147
- applyDocumentLocale(serverLocale);
148
- }
149
-
150
- bootstrapComplete = true;
151
- const lateNamespaces = [...serverResourceNamespaces].filter(
152
- (namespace) => !loadedServerResourceNamespaces.has(namespace)
153
- );
154
- if (lateNamespaces.length) {
155
- await ensureServerResourceNamespaces(lateNamespaces);
156
- }
157
- })
158
- .catch((error) => {
159
- bootstrapComplete = true;
160
- if (!configuredLocales.length) setEnabledLocales([getCurrentLocale()]);
161
- serverResourcesPromise = undefined;
162
- throw error;
163
- });
164
-
165
- return serverResourcesPromise;
166
- }