@nocobase/client-v2 2.1.0-beta.36 → 2.1.0-beta.38

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 (154) hide show
  1. package/es/Application.d.ts +1 -0
  2. package/es/BaseApplication.d.ts +4 -0
  3. package/es/RouterManager.d.ts +1 -0
  4. package/es/components/KeepAlive.d.ts +22 -0
  5. package/es/components/RouterBridge.d.ts +9 -0
  6. package/es/components/form/DialogFormLayout.d.ts +5 -29
  7. package/es/components/form/filter/CollectionFilter.d.ts +41 -0
  8. package/es/components/form/filter/CollectionFilterItem.d.ts +41 -0
  9. package/es/components/form/filter/DateFilterDynamicComponent.d.ts +57 -0
  10. package/es/components/form/filter/FilterValueInput.d.ts +29 -0
  11. package/es/components/form/filter/index.d.ts +11 -0
  12. package/es/components/form/filter/useFilterActionProps.d.ts +96 -0
  13. package/es/components/form/index.d.ts +1 -0
  14. package/es/data-source/ExtendCollectionsProvider.d.ts +50 -0
  15. package/es/data-source/index.d.ts +9 -0
  16. package/es/flow/FlowPage.d.ts +2 -1
  17. package/es/flow/admin-shell/AdminLayoutRouteCoordinator.d.ts +8 -40
  18. package/es/flow/admin-shell/BaseLayoutModel.d.ts +89 -0
  19. package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +74 -0
  20. package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +12 -0
  21. package/es/flow/admin-shell/admin-layout/AdminLayoutModel.d.ts +7 -92
  22. package/es/flow/admin-shell/admin-layout/index.d.ts +2 -0
  23. package/es/flow/admin-shell/useAdminLayoutRoutePage.d.ts +2 -2
  24. package/es/flow/admin-shell/useLayoutRoutePage.d.ts +23 -0
  25. package/es/flow/components/FlowRoute.d.ts +10 -1
  26. package/es/flow/components/filter/index.d.ts +2 -0
  27. package/es/flow/components/filter/useFilterOptions.d.ts +54 -0
  28. package/es/flow/index.d.ts +4 -0
  29. package/es/flow/models/base/PageModel/PageModel.d.ts +3 -1
  30. package/es/flow/models/blocks/form/FormActionGroupModel.d.ts +1 -0
  31. package/es/flow/models/blocks/table/TableBlockModel.d.ts +10 -0
  32. package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.d.ts +1 -1
  33. package/es/flow-compat/passwordUtils.d.ts +1 -1
  34. package/es/index.d.ts +2 -0
  35. package/es/index.mjs +491 -439
  36. package/es/layout-manager/LayoutContentRoute.d.ts +14 -0
  37. package/es/layout-manager/LayoutManager.d.ts +22 -0
  38. package/es/layout-manager/LayoutRoute.d.ts +14 -0
  39. package/es/layout-manager/index.d.ts +13 -0
  40. package/es/layout-manager/types.d.ts +20 -0
  41. package/es/layout-manager/utils.d.ts +14 -0
  42. package/es/nocobase-buildin-plugin/index.d.ts +3 -10
  43. package/es/settings-center/index.d.ts +1 -1
  44. package/es/settings-center/plugin-manager/BulkEnableButton.d.ts +15 -0
  45. package/es/settings-center/plugin-manager/PluginCard.d.ts +15 -0
  46. package/es/settings-center/plugin-manager/PluginDetail.d.ts +16 -0
  47. package/es/settings-center/{PluginManagerPage.d.ts → plugin-manager/index.d.ts} +1 -7
  48. package/es/settings-center/plugin-manager/types.d.ts +34 -0
  49. package/lib/index.js +491 -439
  50. package/package.json +8 -7
  51. package/src/Application.tsx +27 -12
  52. package/src/BaseApplication.tsx +19 -0
  53. package/src/PluginSettingsManager.ts +1 -1
  54. package/src/RouterManager.tsx +17 -1
  55. package/src/__tests__/PluginSettingsManager.test.ts +41 -2
  56. package/src/__tests__/app.test.tsx +17 -1
  57. package/src/__tests__/globalDeps.test.ts +1 -0
  58. package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +45 -2
  59. package/src/__tests__/plugin-manager.test.tsx +177 -0
  60. package/src/__tests__/settings-center.test.tsx +24 -2
  61. package/src/components/KeepAlive.tsx +131 -0
  62. package/src/components/README.md +89 -6
  63. package/src/components/README.zh-CN.md +89 -7
  64. package/src/components/RouterBridge.tsx +28 -4
  65. package/src/components/__tests__/KeepAlive.test.tsx +63 -0
  66. package/src/components/__tests__/RouterBridge.test.tsx +27 -0
  67. package/src/components/form/DialogFormLayout.tsx +5 -29
  68. package/src/components/form/filter/CollectionFilter.tsx +101 -0
  69. package/src/components/form/filter/CollectionFilterItem.tsx +176 -0
  70. package/src/components/form/filter/DateFilterDynamicComponent.tsx +283 -0
  71. package/src/components/form/filter/FilterValueInput.tsx +198 -0
  72. package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +205 -0
  73. package/src/components/form/filter/__tests__/DateFilterDynamicComponent.test.tsx +148 -0
  74. package/src/components/form/filter/__tests__/FilterValueInput.test.tsx +243 -0
  75. package/src/components/form/filter/__tests__/compileFilterGroup.test.ts +146 -0
  76. package/src/components/form/filter/index.ts +13 -0
  77. package/src/components/form/filter/useFilterActionProps.ts +200 -0
  78. package/src/components/form/index.tsx +1 -0
  79. package/src/data-source/ExtendCollectionsProvider.tsx +144 -0
  80. package/src/data-source/__tests__/ExtendCollectionsProvider.test.tsx +264 -0
  81. package/src/data-source/index.ts +10 -0
  82. package/src/flow/FlowPage.tsx +35 -7
  83. package/src/flow/__tests__/FlowPage.test.tsx +79 -0
  84. package/src/flow/__tests__/FlowRoute.test.tsx +529 -2
  85. package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +191 -0
  86. package/src/flow/actions/__tests__/openView.subModelKey.test.tsx +33 -0
  87. package/src/flow/actions/aclCheck.tsx +4 -0
  88. package/src/flow/actions/aclCheckRefresh.tsx +4 -0
  89. package/src/flow/actions/dateTimeFormat.tsx +12 -8
  90. package/src/flow/actions/linkageRules.tsx +122 -0
  91. package/src/flow/actions/openView.tsx +28 -4
  92. package/src/flow/admin-shell/AdminLayoutRouteCoordinator.ts +11 -329
  93. package/src/flow/admin-shell/BaseLayoutModel.tsx +455 -0
  94. package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +502 -0
  95. package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +547 -3
  96. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +4 -4
  97. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +160 -0
  98. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +0 -12
  99. package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +28 -201
  100. package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +11 -2
  101. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +1 -26
  102. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +149 -27
  103. package/src/flow/admin-shell/admin-layout/index.ts +2 -0
  104. package/src/flow/admin-shell/useAdminLayoutRoutePage.ts +10 -26
  105. package/src/flow/admin-shell/useLayoutRoutePage.ts +61 -0
  106. package/src/flow/components/AdminLayout.tsx +4 -154
  107. package/src/flow/components/FlowRoute.tsx +105 -15
  108. package/src/flow/components/filter/index.ts +3 -0
  109. package/src/flow/components/filter/useFilterOptions.ts +80 -0
  110. package/src/flow/index.ts +4 -0
  111. package/src/flow/models/base/ActionModel.tsx +8 -1
  112. package/src/flow/models/base/PageModel/PageModel.tsx +51 -18
  113. package/src/flow/models/base/PageModel/RootPageModel.tsx +6 -13
  114. package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +102 -1
  115. package/src/flow/models/base/RouteModel.tsx +1 -1
  116. package/src/flow/models/blocks/form/FormActionGroupModel.tsx +14 -0
  117. package/src/flow/models/blocks/form/FormItemModel.tsx +8 -1
  118. package/src/flow/models/blocks/form/__tests__/FormActionGroupModel.test.ts +46 -0
  119. package/src/flow/models/blocks/form/submitValues.ts +4 -1
  120. package/src/flow/models/blocks/table/TableBlockModel.tsx +118 -16
  121. package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +114 -0
  122. package/src/flow/models/fields/AssociationFieldModel/SubFormFieldModel.tsx +7 -1
  123. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +1 -1
  124. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -5
  125. package/src/flow/models/fields/ClickableFieldModel.tsx +9 -1
  126. package/src/flow/models/fields/DisplayTimeFieldModel.tsx +1 -1
  127. package/src/flow/models/fields/TimeFieldModel.tsx +1 -1
  128. package/src/flow/models/fields/__tests__/TimeFieldModel.test.tsx +61 -0
  129. package/src/flow/models/fields/mobile-components/MobileDatePicker.tsx +19 -3
  130. package/src/flow/models/fields/mobile-components/__tests__/MobileDatePicker.test.tsx +94 -0
  131. package/src/flow/models/topbar/TopbarActionModel.tsx +1 -1
  132. package/src/flow/utils/__tests__/dateTimeFormat.test.ts +91 -0
  133. package/src/index.ts +2 -0
  134. package/src/layout-manager/LayoutContentRoute.tsx +90 -0
  135. package/src/layout-manager/LayoutManager.tsx +185 -0
  136. package/src/layout-manager/LayoutRoute.tsx +138 -0
  137. package/src/layout-manager/__tests__/LayoutManager.test.tsx +335 -0
  138. package/src/layout-manager/__tests__/LayoutRoute.test.tsx +473 -0
  139. package/src/layout-manager/index.ts +14 -0
  140. package/src/layout-manager/types.ts +22 -0
  141. package/src/layout-manager/utils.ts +37 -0
  142. package/src/nocobase-buildin-plugin/index.tsx +69 -67
  143. package/src/nocobase-buildin-plugin/plugins/LocalePlugin.ts +1 -0
  144. package/src/settings-center/index.ts +1 -1
  145. package/src/settings-center/plugin-manager/BulkEnableButton.tsx +111 -0
  146. package/src/settings-center/plugin-manager/PluginCard.tsx +270 -0
  147. package/src/settings-center/plugin-manager/PluginDetail.tsx +195 -0
  148. package/src/settings-center/plugin-manager/index.tsx +254 -0
  149. package/src/settings-center/plugin-manager/types.ts +35 -0
  150. package/src/settings-center/utils.tsx +8 -1
  151. package/src/theme/__tests__/globalStyles.test.ts +24 -0
  152. package/src/theme/globalStyles.ts +10 -0
  153. package/src/utils/globalDeps.ts +2 -0
  154. package/src/settings-center/PluginManagerPage.tsx +0 -162
@@ -0,0 +1,335 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import React from 'react';
11
+ import { matchRoutes } from 'react-router';
12
+ import { describe, expect, it, vi } from 'vitest';
13
+ import { RouterManager } from '../../RouterManager';
14
+ import { LayoutManager } from '../LayoutManager';
15
+
16
+ function createManager() {
17
+ const routes: Record<string, any> = {};
18
+ const app = {
19
+ router: {
20
+ add: vi.fn((name: string, route: any) => {
21
+ routes[name] = route;
22
+ }),
23
+ },
24
+ };
25
+
26
+ return {
27
+ app,
28
+ routes,
29
+ manager: new LayoutManager(app as any),
30
+ };
31
+ }
32
+
33
+ describe('LayoutManager', () => {
34
+ it('registers layout with defaults and standard page routes', () => {
35
+ const { manager, routes } = createManager();
36
+
37
+ const layout = manager.registerLayout({
38
+ routeName: 'mobile',
39
+ routePath: 'mobile/',
40
+ uid: 'mobile-layout-model',
41
+ layoutModelClass: 'MobileLayoutModel',
42
+ });
43
+
44
+ expect(layout).toMatchObject({
45
+ routeName: 'mobile',
46
+ routePath: '/mobile',
47
+ rootRouteName: 'mobile',
48
+ uid: 'mobile-layout-model',
49
+ layoutModelClass: 'MobileLayoutModel',
50
+ rootPageModelClass: 'RootPageModel',
51
+ childPageModelClass: 'ChildPageModel',
52
+ authCheck: true,
53
+ });
54
+ expect(routes.mobile).toMatchObject({
55
+ path: '/mobile',
56
+ authCheck: true,
57
+ });
58
+ expect(React.isValidElement(routes.mobile.element)).toBe(true);
59
+ expect(routes['mobile.__page']).toMatchObject({
60
+ path: ':name',
61
+ authCheck: true,
62
+ });
63
+ expect(routes['mobile.__pageTab']).toMatchObject({
64
+ path: ':name/tab/:tabUid',
65
+ authCheck: true,
66
+ });
67
+ expect(routes['mobile.__pageView']).toMatchObject({
68
+ path: ':name/view/*',
69
+ authCheck: true,
70
+ });
71
+ expect(routes['mobile.__pageTabView']).toMatchObject({
72
+ path: ':name/tab/:tabUid/view/*',
73
+ authCheck: true,
74
+ });
75
+ });
76
+
77
+ it('registers nested layout route by dotted routeName and relative routePath', () => {
78
+ const { manager, routes } = createManager();
79
+
80
+ const layout = manager.registerLayout({
81
+ routeName: 'admin.settings.publicForms',
82
+ routePath: 'public-forms/',
83
+ uid: 'public-form-layout-model',
84
+ layoutModelClass: 'PublicFormLayoutModel',
85
+ });
86
+
87
+ expect(layout).toMatchObject({
88
+ routeName: 'admin.settings.publicForms',
89
+ routePath: 'public-forms',
90
+ rootRouteName: 'admin',
91
+ });
92
+ expect(routes['admin.settings.publicForms']).toMatchObject({
93
+ path: 'public-forms',
94
+ authCheck: true,
95
+ });
96
+ expect(routes['admin.settings.publicForms.__pageView']).toMatchObject({
97
+ path: ':name/view/*',
98
+ authCheck: true,
99
+ });
100
+ });
101
+
102
+ it('registers nested layout route with empty routePath', () => {
103
+ const { manager, routes } = createManager();
104
+
105
+ const layout = manager.registerLayout({
106
+ routeName: 'admin.settings.publicForms.layout',
107
+ routePath: '',
108
+ uid: 'public-form-layout-model',
109
+ layoutModelClass: 'PublicFormLayoutModel',
110
+ });
111
+
112
+ expect(layout).toMatchObject({
113
+ routeName: 'admin.settings.publicForms.layout',
114
+ routePath: '',
115
+ rootRouteName: 'admin',
116
+ });
117
+ expect(routes['admin.settings.publicForms.layout']).toMatchObject({
118
+ path: '',
119
+ authCheck: true,
120
+ });
121
+ expect(routes['admin.settings.publicForms.layout.__page']).toMatchObject({
122
+ path: ':name',
123
+ authCheck: true,
124
+ });
125
+ expect(routes['admin.settings.publicForms.layout.__pageTab']).toMatchObject({
126
+ path: ':name/tab/:tabUid',
127
+ authCheck: true,
128
+ });
129
+ expect(routes['admin.settings.publicForms.layout.__pageView']).toMatchObject({
130
+ path: ':name/view/*',
131
+ authCheck: true,
132
+ });
133
+ });
134
+
135
+ it('matches nested layout under existing parent route tree', () => {
136
+ const app: any = {
137
+ renderComponent: vi.fn(),
138
+ };
139
+ app.router = new RouterManager({}, app);
140
+ const manager = new LayoutManager(app);
141
+
142
+ app.router.add('admin', {
143
+ path: '/admin',
144
+ element: <div />,
145
+ });
146
+ app.router.add('admin.settings', {
147
+ path: '/admin/settings',
148
+ element: <div />,
149
+ });
150
+ app.router.add('admin.settings.route-empty', {
151
+ path: '*',
152
+ element: <div />,
153
+ });
154
+ manager.registerLayout({
155
+ routeName: 'admin.settings.publicForms',
156
+ routePath: 'public-forms',
157
+ uid: 'public-form-layout-model',
158
+ layoutModelClass: 'PublicFormLayoutModel',
159
+ });
160
+
161
+ const matches = matchRoutes(app.router.getRoutesTree(), '/admin/settings/public-forms/form-1/view/popup');
162
+
163
+ expect(matches?.map((match) => match.route.id)).toEqual([
164
+ 'admin',
165
+ 'admin.settings',
166
+ 'admin.settings.publicForms',
167
+ 'admin.settings.publicForms.__pageView',
168
+ ]);
169
+ });
170
+
171
+ it('matches empty routePath layout under existing parent route tree', () => {
172
+ const app: any = {
173
+ renderComponent: vi.fn(),
174
+ };
175
+ app.router = new RouterManager({}, app);
176
+ const manager = new LayoutManager(app);
177
+
178
+ app.router.add('admin', {
179
+ path: '/admin',
180
+ element: <div />,
181
+ });
182
+ app.router.add('admin.settings', {
183
+ path: '/admin/settings',
184
+ element: <div />,
185
+ });
186
+ app.router.add('admin.settings.publicForms', {
187
+ path: '/admin/settings/public-forms',
188
+ element: <div />,
189
+ });
190
+ manager.registerLayout({
191
+ routeName: 'admin.settings.publicForms.layout',
192
+ routePath: '',
193
+ uid: 'public-form-layout-model',
194
+ layoutModelClass: 'PublicFormLayoutModel',
195
+ });
196
+
197
+ const matches = matchRoutes(app.router.getRoutesTree(), '/admin/settings/public-forms/form-1/view/popup');
198
+
199
+ expect(matches?.map((match) => match.route.id)).toEqual([
200
+ 'admin',
201
+ 'admin.settings',
202
+ 'admin.settings.publicForms',
203
+ 'admin.settings.publicForms.layout',
204
+ 'admin.settings.publicForms.layout.__pageView',
205
+ ]);
206
+ });
207
+
208
+ it('allows explicit page model classes and authCheck', () => {
209
+ const { manager, routes } = createManager();
210
+
211
+ expect(
212
+ manager.registerLayout({
213
+ routeName: 'embed',
214
+ routePath: '/embed',
215
+ uid: 'embed-layout-model',
216
+ layoutModelClass: 'EmbedLayoutModelV2',
217
+ rootPageModelClass: 'EmbedRootPageModel',
218
+ childPageModelClass: 'EmbedChildPageModel',
219
+ authCheck: false,
220
+ }),
221
+ ).toMatchObject({
222
+ rootPageModelClass: 'EmbedRootPageModel',
223
+ childPageModelClass: 'EmbedChildPageModel',
224
+ authCheck: false,
225
+ });
226
+ expect(routes.embed).toMatchObject({
227
+ authCheck: false,
228
+ skipAuthCheck: true,
229
+ });
230
+ expect(routes['embed.__page']).toMatchObject({
231
+ authCheck: false,
232
+ skipAuthCheck: true,
233
+ });
234
+ });
235
+
236
+ it('validates public fields', () => {
237
+ const { manager } = createManager();
238
+
239
+ expect(() =>
240
+ manager.registerLayout({
241
+ routeName: '.bad',
242
+ routePath: '/bad',
243
+ uid: 'bad-layout-model',
244
+ layoutModelClass: 'BadLayoutModel',
245
+ }),
246
+ ).toThrowError(/invalid routeName/);
247
+ expect(() =>
248
+ manager.registerLayout({
249
+ routeName: 'root',
250
+ routePath: '/',
251
+ uid: 'root-layout-model',
252
+ layoutModelClass: 'RootLayoutModel',
253
+ }),
254
+ ).toThrowError(/root routePath/);
255
+ expect(() =>
256
+ manager.registerLayout({
257
+ routeName: 'emptyRoot',
258
+ routePath: '',
259
+ uid: 'empty-root-layout-model',
260
+ layoutModelClass: 'EmptyRootLayoutModel',
261
+ }),
262
+ ).toThrowError(/root routePath/);
263
+ expect(() =>
264
+ manager.registerLayout({
265
+ routeName: 'admin.settings.bad',
266
+ routePath: '/bad',
267
+ uid: 'bad-nested-layout-model',
268
+ layoutModelClass: 'BadNestedLayoutModel',
269
+ }),
270
+ ).toThrowError(/must be relative/);
271
+ expect(() =>
272
+ manager.registerLayout({
273
+ routeName: '',
274
+ routePath: '/empty',
275
+ uid: 'empty-layout-model',
276
+ layoutModelClass: 'EmptyLayoutModel',
277
+ }),
278
+ ).toThrowError(/routeName/);
279
+ expect(() =>
280
+ manager.registerLayout({
281
+ routeName: 'badRootModel',
282
+ routePath: '/bad-root-model',
283
+ uid: 'bad-root-model-layout-model',
284
+ layoutModelClass: 'BadRootModelLayoutModel',
285
+ rootPageModelClass: '' as any,
286
+ }),
287
+ ).toThrowError(/rootPageModelClass/);
288
+ expect(() =>
289
+ manager.registerLayout({
290
+ routeName: 'badChildModel',
291
+ routePath: '/bad-child-model',
292
+ uid: 'bad-child-model-layout-model',
293
+ layoutModelClass: 'BadChildModelLayoutModel',
294
+ childPageModelClass: {} as any,
295
+ }),
296
+ ).toThrowError(/childPageModelClass/);
297
+ expect(() =>
298
+ manager.registerLayout({
299
+ routeName: 'badAuthCheck',
300
+ routePath: '/bad-auth-check',
301
+ uid: 'bad-auth-check-layout-model',
302
+ layoutModelClass: 'BadAuthCheckLayoutModel',
303
+ authCheck: 'false' as any,
304
+ }),
305
+ ).toThrowError(/authCheck/);
306
+ });
307
+
308
+ it('rejects duplicate routeName or uid', () => {
309
+ const { manager } = createManager();
310
+
311
+ manager.registerLayout({
312
+ routeName: 'admin',
313
+ routePath: '/admin',
314
+ uid: 'admin-layout-model',
315
+ layoutModelClass: 'AdminLayoutModel',
316
+ });
317
+
318
+ expect(() =>
319
+ manager.registerLayout({
320
+ routeName: 'admin',
321
+ routePath: '/admin2',
322
+ uid: 'admin-layout-model-2',
323
+ layoutModelClass: 'AdminLayoutModel2',
324
+ }),
325
+ ).toThrowError(/already been registered/);
326
+ expect(() =>
327
+ manager.registerLayout({
328
+ routeName: 'admin3',
329
+ routePath: '/admin3',
330
+ uid: 'admin-layout-model',
331
+ layoutModelClass: 'AdminLayoutModel3',
332
+ }),
333
+ ).toThrowError(/uid 'admin-layout-model'/);
334
+ });
335
+ });