@nocobase/client-v2 2.1.0-alpha.40 → 2.1.0-alpha.45

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 (278) hide show
  1. package/es/Application.d.ts +7 -0
  2. package/es/BaseApplication.d.ts +13 -0
  3. package/es/RouterManager.d.ts +1 -0
  4. package/es/collection-field-interface/CollectionFieldInterface.d.ts +51 -15
  5. package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +82 -3
  6. package/es/collection-manager/field-configure.d.ts +80 -0
  7. package/es/collection-manager/field-validation.d.ts +43 -0
  8. package/es/collection-manager/filter-operators/index.d.ts +46 -0
  9. package/es/collection-manager/filter-operators/operators.d.ts +30 -0
  10. package/es/collection-manager/interfaces/checkbox.d.ts +1 -41
  11. package/es/collection-manager/interfaces/checkboxGroup.d.ts +12 -44
  12. package/es/collection-manager/interfaces/collection.d.ts +12 -51
  13. package/es/collection-manager/interfaces/color.d.ts +1 -16
  14. package/es/collection-manager/interfaces/createdAt.d.ts +1 -44
  15. package/es/collection-manager/interfaces/createdBy.d.ts +0 -4
  16. package/es/collection-manager/interfaces/dateOnly.d.ts +7 -44
  17. package/es/collection-manager/interfaces/datetime.d.ts +1 -44
  18. package/es/collection-manager/interfaces/datetimeNoTz.d.ts +1 -44
  19. package/es/collection-manager/interfaces/email.d.ts +1 -29
  20. package/es/collection-manager/interfaces/id.d.ts +1 -16
  21. package/es/collection-manager/interfaces/index.d.ts +2 -3
  22. package/es/collection-manager/interfaces/input.d.ts +1 -102
  23. package/es/collection-manager/interfaces/integer.d.ts +1 -95
  24. package/es/collection-manager/interfaces/json.d.ts +16 -7
  25. package/es/collection-manager/interfaces/m2m.d.ts +11 -19
  26. package/es/collection-manager/interfaces/m2o.d.ts +11 -19
  27. package/es/collection-manager/interfaces/markdown.d.ts +1 -63
  28. package/es/collection-manager/interfaces/multipleSelect.d.ts +12 -44
  29. package/es/collection-manager/interfaces/nanoid.d.ts +1 -34
  30. package/es/collection-manager/interfaces/number.d.ts +1 -87
  31. package/es/collection-manager/interfaces/o2m.d.ts +12 -24
  32. package/es/collection-manager/interfaces/obo.d.ts +207 -0
  33. package/es/collection-manager/interfaces/oho.d.ts +207 -0
  34. package/es/collection-manager/interfaces/password.d.ts +1 -56
  35. package/es/collection-manager/interfaces/percent.d.ts +1 -84
  36. package/es/collection-manager/interfaces/phone.d.ts +1 -25
  37. package/es/collection-manager/interfaces/properties/index.d.ts +0 -28
  38. package/es/collection-manager/interfaces/radioGroup.d.ts +1 -29
  39. package/es/collection-manager/interfaces/richText.d.ts +1 -63
  40. package/es/collection-manager/interfaces/select.d.ts +12 -44
  41. package/es/collection-manager/interfaces/snowflake-id.d.ts +1 -34
  42. package/es/collection-manager/interfaces/tableoid.d.ts +1 -10
  43. package/es/collection-manager/interfaces/textarea.d.ts +1 -51
  44. package/es/collection-manager/interfaces/time.d.ts +1 -16
  45. package/es/collection-manager/interfaces/types.d.ts +3 -12
  46. package/es/collection-manager/interfaces/unixTimestamp.d.ts +1 -44
  47. package/es/collection-manager/interfaces/updatedAt.d.ts +1 -44
  48. package/es/collection-manager/interfaces/updatedBy.d.ts +0 -4
  49. package/es/collection-manager/interfaces/url.d.ts +1 -20
  50. package/es/collection-manager/interfaces/uuid.d.ts +1 -34
  51. package/es/collection-manager/template-fields.d.ts +53 -0
  52. package/es/components/KeepAlive.d.ts +22 -0
  53. package/es/components/RouterBridge.d.ts +9 -0
  54. package/es/components/form/DialogFormLayout.d.ts +5 -29
  55. package/es/components/form/VariableInput.d.ts +53 -2
  56. package/es/components/form/filter/CollectionFilter.d.ts +49 -0
  57. package/es/components/form/filter/CollectionFilterItem.d.ts +49 -0
  58. package/es/components/form/filter/DateFilterDynamicComponent.d.ts +57 -0
  59. package/es/components/form/filter/FilterValueInput.d.ts +29 -0
  60. package/es/components/form/filter/index.d.ts +11 -0
  61. package/es/components/form/filter/useFilterActionProps.d.ts +96 -0
  62. package/es/components/form/index.d.ts +1 -0
  63. package/es/data-source/ExtendCollectionsProvider.d.ts +50 -0
  64. package/es/data-source/index.d.ts +9 -0
  65. package/es/flow/FlowPage.d.ts +2 -1
  66. package/es/flow/admin-shell/AdminLayoutRouteCoordinator.d.ts +8 -40
  67. package/es/flow/admin-shell/BaseLayoutModel.d.ts +89 -0
  68. package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +74 -0
  69. package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +12 -0
  70. package/es/flow/admin-shell/admin-layout/AdminLayoutModel.d.ts +7 -92
  71. package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +11 -0
  72. package/es/flow/admin-shell/admin-layout/index.d.ts +3 -0
  73. package/es/flow/admin-shell/admin-layout/useApplications.d.ts +3 -2
  74. package/es/flow/admin-shell/useAdminLayoutRoutePage.d.ts +2 -2
  75. package/es/flow/admin-shell/useLayoutRoutePage.d.ts +23 -0
  76. package/es/flow/components/FlowRoute.d.ts +10 -1
  77. package/es/flow/components/filter/index.d.ts +2 -0
  78. package/es/flow/components/filter/useFilterOptions.d.ts +66 -0
  79. package/es/flow/index.d.ts +4 -0
  80. package/es/flow/models/base/PageModel/PageModel.d.ts +3 -1
  81. package/es/flow/models/blocks/assign-form/assignFieldValuesFlow.d.ts +84 -0
  82. package/es/flow/models/blocks/assign-form/index.d.ts +1 -0
  83. package/es/flow/models/blocks/form/FormActionGroupModel.d.ts +1 -0
  84. package/es/flow/models/blocks/form/FormActionModel.d.ts +9 -2
  85. package/es/flow/models/blocks/table/TableBlockModel.d.ts +10 -0
  86. package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.d.ts +1 -1
  87. package/es/flow-compat/passwordUtils.d.ts +1 -1
  88. package/es/index.d.ts +6 -0
  89. package/es/index.mjs +552 -459
  90. package/es/layout-manager/LayoutContentRoute.d.ts +14 -0
  91. package/es/layout-manager/LayoutManager.d.ts +22 -0
  92. package/es/layout-manager/LayoutRoute.d.ts +14 -0
  93. package/es/layout-manager/index.d.ts +13 -0
  94. package/es/layout-manager/types.d.ts +20 -0
  95. package/es/layout-manager/utils.d.ts +14 -0
  96. package/es/nocobase-buildin-plugin/index.d.ts +3 -10
  97. package/es/settings-center/index.d.ts +1 -1
  98. package/es/settings-center/plugin-manager/BulkEnableButton.d.ts +15 -0
  99. package/es/settings-center/plugin-manager/PluginCard.d.ts +15 -0
  100. package/es/settings-center/plugin-manager/PluginDetail.d.ts +16 -0
  101. package/es/settings-center/{PluginManagerPage.d.ts → plugin-manager/index.d.ts} +1 -7
  102. package/es/settings-center/plugin-manager/types.d.ts +34 -0
  103. package/lib/index.js +552 -459
  104. package/package.json +8 -7
  105. package/src/Application.tsx +51 -12
  106. package/src/BaseApplication.tsx +32 -0
  107. package/src/PluginSettingsManager.ts +1 -1
  108. package/src/RouterManager.tsx +17 -1
  109. package/src/__tests__/PluginSettingsManager.test.ts +41 -2
  110. package/src/__tests__/app.test.tsx +17 -1
  111. package/src/__tests__/globalDeps.test.ts +1 -0
  112. package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +45 -2
  113. package/src/__tests__/plugin-manager.test.tsx +177 -0
  114. package/src/__tests__/settings-center.test.tsx +24 -2
  115. package/src/collection-field-interface/CollectionFieldInterface.ts +71 -77
  116. package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +201 -4
  117. package/src/collection-manager/field-configure.ts +548 -0
  118. package/src/collection-manager/field-validation.ts +195 -0
  119. package/src/collection-manager/filter-operators/index.ts +176 -0
  120. package/src/collection-manager/{interfaces/properties → filter-operators}/operators.ts +24 -13
  121. package/src/collection-manager/interfaces/checkbox.ts +2 -9
  122. package/src/collection-manager/interfaces/checkboxGroup.ts +2 -10
  123. package/src/collection-manager/interfaces/collection.ts +2 -15
  124. package/src/collection-manager/interfaces/color.ts +2 -2
  125. package/src/collection-manager/interfaces/createdAt.ts +2 -2
  126. package/src/collection-manager/interfaces/createdBy.ts +1 -12
  127. package/src/collection-manager/interfaces/dateOnly.ts +8 -2
  128. package/src/collection-manager/interfaces/datetime.ts +2 -2
  129. package/src/collection-manager/interfaces/datetimeNoTz.ts +2 -2
  130. package/src/collection-manager/interfaces/email.ts +2 -9
  131. package/src/collection-manager/interfaces/id.ts +1 -2
  132. package/src/collection-manager/interfaces/index.ts +2 -3
  133. package/src/collection-manager/interfaces/input.ts +2 -133
  134. package/src/collection-manager/interfaces/integer.ts +2 -71
  135. package/src/collection-manager/interfaces/json.tsx +17 -11
  136. package/src/collection-manager/interfaces/m2m.tsx +0 -21
  137. package/src/collection-manager/interfaces/m2o.tsx +0 -22
  138. package/src/collection-manager/interfaces/markdown.ts +2 -51
  139. package/src/collection-manager/interfaces/multipleSelect.ts +2 -14
  140. package/src/collection-manager/interfaces/nanoid.ts +2 -2
  141. package/src/collection-manager/interfaces/number.ts +2 -85
  142. package/src/collection-manager/interfaces/o2m.tsx +1 -22
  143. package/src/collection-manager/interfaces/obo.tsx +145 -0
  144. package/src/collection-manager/interfaces/oho.tsx +145 -0
  145. package/src/collection-manager/interfaces/password.ts +2 -44
  146. package/src/collection-manager/interfaces/percent.ts +2 -74
  147. package/src/collection-manager/interfaces/phone.ts +2 -2
  148. package/src/collection-manager/interfaces/properties/index.ts +0 -133
  149. package/src/collection-manager/interfaces/radioGroup.ts +2 -2
  150. package/src/collection-manager/interfaces/richText.ts +2 -51
  151. package/src/collection-manager/interfaces/select.ts +2 -14
  152. package/src/collection-manager/interfaces/snowflake-id.ts +2 -2
  153. package/src/collection-manager/interfaces/tableoid.ts +1 -2
  154. package/src/collection-manager/interfaces/textarea.ts +2 -51
  155. package/src/collection-manager/interfaces/time.ts +2 -2
  156. package/src/collection-manager/interfaces/types.ts +4 -12
  157. package/src/collection-manager/interfaces/unixTimestamp.tsx +2 -2
  158. package/src/collection-manager/interfaces/updatedAt.ts +2 -2
  159. package/src/collection-manager/interfaces/updatedBy.ts +1 -12
  160. package/src/collection-manager/interfaces/url.ts +2 -4
  161. package/src/collection-manager/interfaces/uuid.ts +2 -2
  162. package/src/collection-manager/template-fields.ts +109 -0
  163. package/src/components/KeepAlive.tsx +131 -0
  164. package/src/components/README.md +90 -6
  165. package/src/components/README.zh-CN.md +90 -7
  166. package/src/components/RouterBridge.tsx +28 -4
  167. package/src/components/__tests__/KeepAlive.test.tsx +63 -0
  168. package/src/components/__tests__/RouterBridge.test.tsx +27 -0
  169. package/src/components/form/DialogFormLayout.tsx +5 -29
  170. package/src/components/form/VariableInput.tsx +101 -28
  171. package/src/components/form/__tests__/VariableInput.test.ts +85 -0
  172. package/src/components/form/filter/CollectionFilter.tsx +111 -0
  173. package/src/components/form/filter/CollectionFilterItem.tsx +184 -0
  174. package/src/components/form/filter/DateFilterDynamicComponent.tsx +283 -0
  175. package/src/components/form/filter/FilterValueInput.tsx +198 -0
  176. package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +247 -0
  177. package/src/components/form/filter/__tests__/DateFilterDynamicComponent.test.tsx +148 -0
  178. package/src/components/form/filter/__tests__/FilterValueInput.test.tsx +243 -0
  179. package/src/components/form/filter/__tests__/compileFilterGroup.test.ts +146 -0
  180. package/src/components/form/filter/index.ts +13 -0
  181. package/src/components/form/filter/useFilterActionProps.ts +203 -0
  182. package/src/components/form/index.tsx +1 -0
  183. package/src/data-source/ExtendCollectionsProvider.tsx +144 -0
  184. package/src/data-source/__tests__/ExtendCollectionsProvider.test.tsx +264 -0
  185. package/src/data-source/index.ts +10 -0
  186. package/src/flow/FlowPage.tsx +35 -7
  187. package/src/flow/__tests__/FlowPage.test.tsx +79 -0
  188. package/src/flow/__tests__/FlowRoute.test.tsx +529 -2
  189. package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +191 -0
  190. package/src/flow/actions/__tests__/openView.subModelKey.test.tsx +33 -0
  191. package/src/flow/actions/aclCheck.tsx +4 -0
  192. package/src/flow/actions/aclCheckRefresh.tsx +4 -0
  193. package/src/flow/actions/dateTimeFormat.tsx +12 -8
  194. package/src/flow/actions/linkageRules.tsx +122 -0
  195. package/src/flow/actions/openView.tsx +28 -4
  196. package/src/flow/admin-shell/AdminLayoutRouteCoordinator.ts +11 -329
  197. package/src/flow/admin-shell/BaseLayoutModel.tsx +455 -0
  198. package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +502 -0
  199. package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +547 -3
  200. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +35 -7
  201. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +160 -0
  202. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +0 -12
  203. package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +28 -201
  204. package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +11 -2
  205. package/src/flow/admin-shell/admin-layout/AppListRender.tsx +139 -0
  206. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +1 -26
  207. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +149 -27
  208. package/src/flow/admin-shell/admin-layout/index.ts +3 -0
  209. package/src/flow/admin-shell/admin-layout/useApplications.tsx +34 -1
  210. package/src/flow/admin-shell/useAdminLayoutRoutePage.ts +10 -26
  211. package/src/flow/admin-shell/useLayoutRoutePage.ts +61 -0
  212. package/src/flow/components/AdminLayout.tsx +4 -154
  213. package/src/flow/components/FlowRoute.tsx +105 -15
  214. package/src/flow/components/filter/index.ts +3 -0
  215. package/src/flow/components/filter/useFilterOptions.ts +102 -0
  216. package/src/flow/index.ts +4 -0
  217. package/src/flow/models/actions/UpdateRecordActionModel.tsx +14 -95
  218. package/src/flow/models/actions/UpdateRecordActionUtils.ts +4 -7
  219. package/src/flow/models/actions/__tests__/AssignFormRefill.test.ts +26 -1
  220. package/src/flow/models/base/ActionModel.tsx +8 -1
  221. package/src/flow/models/base/PageModel/PageModel.tsx +51 -18
  222. package/src/flow/models/base/PageModel/RootPageModel.tsx +6 -13
  223. package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +102 -1
  224. package/src/flow/models/base/RouteModel.tsx +1 -1
  225. package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +63 -2
  226. package/src/flow/models/blocks/assign-form/assignFieldValuesFlow.tsx +206 -0
  227. package/src/flow/models/blocks/assign-form/index.ts +1 -0
  228. package/src/flow/models/blocks/form/FormActionGroupModel.tsx +14 -0
  229. package/src/flow/models/blocks/form/FormActionModel.tsx +30 -3
  230. package/src/flow/models/blocks/form/FormItemModel.tsx +8 -1
  231. package/src/flow/models/blocks/form/__tests__/FormActionGroupModel.test.ts +46 -0
  232. package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +71 -0
  233. package/src/flow/models/blocks/form/submitHandler.ts +8 -1
  234. package/src/flow/models/blocks/form/submitValues.ts +4 -1
  235. package/src/flow/models/blocks/table/TableBlockModel.tsx +118 -16
  236. package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +114 -0
  237. package/src/flow/models/fields/AssociationFieldModel/SubFormFieldModel.tsx +7 -1
  238. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +1 -1
  239. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -5
  240. package/src/flow/models/fields/ClickableFieldModel.tsx +9 -1
  241. package/src/flow/models/fields/CollectionSelectorFieldModel.tsx +8 -2
  242. package/src/flow/models/fields/DisplayEnumFieldModel.tsx +8 -2
  243. package/src/flow/models/fields/DisplayTimeFieldModel.tsx +1 -1
  244. package/src/flow/models/fields/TimeFieldModel.tsx +1 -1
  245. package/src/flow/models/fields/__tests__/TimeFieldModel.test.tsx +61 -0
  246. package/src/flow/models/fields/mobile-components/MobileDatePicker.tsx +19 -3
  247. package/src/flow/models/fields/mobile-components/__tests__/MobileDatePicker.test.tsx +94 -0
  248. package/src/flow/models/topbar/TopbarActionModel.tsx +1 -1
  249. package/src/flow/utils/__tests__/dateTimeFormat.test.ts +91 -0
  250. package/src/index.ts +6 -0
  251. package/src/layout-manager/LayoutContentRoute.tsx +90 -0
  252. package/src/layout-manager/LayoutManager.tsx +185 -0
  253. package/src/layout-manager/LayoutRoute.tsx +138 -0
  254. package/src/layout-manager/__tests__/LayoutManager.test.tsx +335 -0
  255. package/src/layout-manager/__tests__/LayoutRoute.test.tsx +473 -0
  256. package/src/layout-manager/index.ts +14 -0
  257. package/src/layout-manager/types.ts +22 -0
  258. package/src/layout-manager/utils.ts +37 -0
  259. package/src/nocobase-buildin-plugin/index.tsx +69 -67
  260. package/src/nocobase-buildin-plugin/plugins/LocalePlugin.ts +1 -0
  261. package/src/settings-center/index.ts +1 -1
  262. package/src/settings-center/plugin-manager/BulkEnableButton.tsx +111 -0
  263. package/src/settings-center/plugin-manager/PluginCard.tsx +270 -0
  264. package/src/settings-center/plugin-manager/PluginDetail.tsx +195 -0
  265. package/src/settings-center/plugin-manager/index.tsx +254 -0
  266. package/src/settings-center/plugin-manager/types.ts +35 -0
  267. package/src/settings-center/utils.tsx +8 -1
  268. package/src/theme/__tests__/globalStyles.test.ts +24 -0
  269. package/src/theme/globalStyles.ts +10 -0
  270. package/src/utils/globalDeps.ts +2 -0
  271. package/es/collection-manager/interfaces/linkTo.d.ts +0 -90
  272. package/es/collection-manager/interfaces/o2o.d.ts +0 -621
  273. package/es/collection-manager/interfaces/properties/operators.d.ts +0 -294
  274. package/es/collection-manager/interfaces/subTable.d.ts +0 -172
  275. package/src/collection-manager/interfaces/linkTo.ts +0 -120
  276. package/src/collection-manager/interfaces/o2o.tsx +0 -561
  277. package/src/collection-manager/interfaces/subTable.ts +0 -218
  278. 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
+ });