@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
@@ -14,6 +14,7 @@ import { message } from 'antd';
14
14
  import { AdminSettingsLayoutModel as ClientV2AdminSettingsLayoutModel } from '../settings-center';
15
15
  import { AdminSettingsLayoutModel as ClientV1AdminSettingsLayoutModel } from '../../../client/src/pm/AdminSettingsLayoutModel';
16
16
  import { NocoBaseBuildInPlugin } from '../nocobase-buildin-plugin';
17
+ import { matchSettingsRoute } from '../settings-center/utils';
17
18
 
18
19
  class TestAclPlugin extends Plugin {
19
20
  async load() {
@@ -145,6 +146,28 @@ const mockAdminRuntime = (
145
146
  };
146
147
 
147
148
  describe('settings center', () => {
149
+ it('should match nested layout paths under a registered settings page', () => {
150
+ const settings = {
151
+ '/admin/settings/public-forms': {
152
+ name: 'public-forms.index',
153
+ topLevelName: 'public-forms',
154
+ path: '/admin/settings/public-forms',
155
+ },
156
+ '/admin/settings/public-forms/advanced': {
157
+ name: 'public-forms.advanced',
158
+ topLevelName: 'public-forms',
159
+ path: '/admin/settings/public-forms/advanced',
160
+ },
161
+ } as any;
162
+
163
+ expect(matchSettingsRoute(settings, '/admin/settings/public-forms/form-1')).toMatchObject({
164
+ name: 'public-forms.index',
165
+ });
166
+ expect(matchSettingsRoute(settings, '/admin/settings/public-forms/advanced/form-1')).toMatchObject({
167
+ name: 'public-forms.advanced',
168
+ });
169
+ });
170
+
148
171
  it('should redirect /admin/settings to system-settings by default', async () => {
149
172
  const app = createMockClient({
150
173
  plugins: [NocoBaseBuildInPlugin, TestAclPlugin],
@@ -211,8 +234,7 @@ describe('settings center', () => {
211
234
  await renderApp(app);
212
235
  await waitForGetRequests(app, ['/auth:check', 'roles:check', 'pm:list']);
213
236
 
214
- expect(await screen.findByText('demo-plugin')).toBeInTheDocument();
215
- expect(screen.getByText('@nocobase/demo-plugin')).toBeInTheDocument();
237
+ expect(await screen.findByText('Demo plugin')).toBeInTheDocument();
216
238
  });
217
239
 
218
240
  it('should hide plugin-manager menu item when pm snippet is missing', async () => {
@@ -10,7 +10,15 @@
10
10
  import type { ISchema } from '@formily/react';
11
11
  import { tval } from '@nocobase/utils/client';
12
12
  import { capitalize, cloneDeep, set } from 'lodash';
13
+ import type { ComponentType, ReactNode } from 'react';
13
14
 
15
+ import {
16
+ normalizeFilterableOperators,
17
+ resolveFilterOperators,
18
+ type FieldFilterable,
19
+ type FieldFilterOperator,
20
+ } from '../collection-manager/filter-operators';
21
+ import type { FieldConfigureItem } from '../collection-manager/field-configure';
14
22
  import { defaultProps } from '../collection-manager/interfaces/properties';
15
23
  import { CollectionFieldInterfaceManager } from './CollectionFieldInterfaceManager';
16
24
  export type CollectionFieldInterfaceFactory = new (
@@ -24,6 +32,55 @@ export interface CollectionFieldInterfaceComponentOption {
24
32
  useProps?: () => any;
25
33
  }
26
34
 
35
+ export type FieldConfigureFormMode = 'create' | 'edit';
36
+
37
+ export interface FieldConfigureContext {
38
+ mode: FieldConfigureFormMode;
39
+ fieldInterface: CollectionFieldInterface | FieldInterfaceConfigure;
40
+ collection?: Record<string, any>;
41
+ field?: Record<string, any>;
42
+ disabledJSONB?: boolean;
43
+ createOnly?: boolean;
44
+ editMainOnly?: boolean;
45
+ }
46
+
47
+ export type FieldConfigureFormProps = FieldConfigureContext;
48
+
49
+ export interface FieldConfigurePropertyComponentProps extends FieldConfigureContext {
50
+ name: string;
51
+ namePath: Array<string | number>;
52
+ schema: Record<string, any>;
53
+ form?: any;
54
+ disabled?: boolean;
55
+ collections?: Array<Record<string, any>>;
56
+ context: Record<string, boolean>;
57
+ title?: ReactNode;
58
+ tooltip?: ReactNode;
59
+ componentProps?: Record<string, any>;
60
+ }
61
+
62
+ export interface FieldInterfaceConfigure {
63
+ name?: string;
64
+ title?: ReactNode;
65
+ group?: string;
66
+ order?: number;
67
+ default?: Record<string, any>;
68
+ titleUsable?: boolean;
69
+ isAssociation?: boolean;
70
+ supportDataSourceType?: string[];
71
+ notSupportDataSourceType?: string[];
72
+ properties?: Record<string, any>;
73
+ items?: FieldConfigureItem[];
74
+ getConfigureFormProperties?: (collectionInfo?: Record<string, any>) => Record<string, any>;
75
+ components?: Record<string, ComponentType<FieldConfigurePropertyComponentProps>>;
76
+ initialize?: (values: Record<string, any>, context?: FieldConfigureContext) => void;
77
+ ConfigureForm?: ComponentType<FieldConfigureFormProps>;
78
+ Component?: ComponentType<FieldConfigureFormProps>;
79
+ normalizeValues?: (values: Record<string, any>, context: FieldConfigureContext) => Record<string, any>;
80
+ normalize?: (values: Record<string, any>, context: FieldConfigureContext) => Record<string, any>;
81
+ validate?: (values: Record<string, any>, context: FieldConfigureContext) => Promise<void> | void;
82
+ }
83
+
27
84
  export abstract class CollectionFieldInterface {
28
85
  constructor(public collectionFieldInterfaceManager: CollectionFieldInterfaceManager) {}
29
86
  name: string;
@@ -45,30 +102,19 @@ export abstract class CollectionFieldInterface {
45
102
  hasDefaultValue?: boolean;
46
103
  componentOptions?: CollectionFieldInterfaceComponentOption[];
47
104
  isAssociation?: boolean;
48
- operators?: any[];
105
+ operators?: FieldFilterOperator[];
49
106
  properties?: any;
50
107
  validationType?: string;
51
108
  availableValidationOptions: string[] = [];
109
+ configure?: FieldInterfaceConfigure;
52
110
  excludeValidationOptions?: string[];
53
111
  /**
54
112
  * - 如果该值为空,则在 Filter 组件中该字段会被过滤掉
55
113
  * - 如果该值为空,则不会在变量列表中看到该字段
56
114
  */
57
- filterable?: {
58
- /**
59
- * 字段所支持的操作符,会在 Filter 组件中显示,比如设置 `数据范围` 的时候可以看见
60
- */
61
- operators?: any[];
62
- /**
63
- * 为当前字段添加子选项,这个子选项会在 Filter 组件中显示,比如设置 `数据范围` 的时候可以看见
64
- */
65
- children?: any[];
66
- [key: string]: any;
67
- };
115
+ filterable?: FieldFilterable;
68
116
  titleUsable?: boolean;
69
- validateSchema?(fieldSchema: ISchema): Record<string, ISchema>;
70
117
  usePathOptions?(field: any): any;
71
- schemaInitialize?(schema: ISchema, data: any): void;
72
118
  hidden?: boolean;
73
119
 
74
120
  addComponentOption(componentOption: CollectionFieldInterfaceComponentOption) {
@@ -93,10 +139,12 @@ export abstract class CollectionFieldInterface {
93
139
  this.componentOptions.push(componentOption);
94
140
  }
95
141
  getConfigureFormProperties(collectionInfo?: any): Record<string, ISchema> {
142
+ const configuredProperties =
143
+ this.configure?.getConfigureFormProperties?.(collectionInfo) || this.configure?.properties || {};
96
144
  const defaultValueProps = this.hasDefaultValue ? this.getDefaultValueProperty() : {};
97
- this.availableValidationOptions.push('required');
98
145
  const isViewCollection = collectionInfo?.view;
99
146
  const isSqlCollection = collectionInfo?.template === 'sql' || collectionInfo?.sql;
147
+ const availableValidationOptions = [...new Set([...this.availableValidationOptions, 'required'])];
100
148
  const validationProps =
101
149
  !isViewCollection && !isSqlCollection && this.validationType
102
150
  ? {
@@ -107,7 +155,7 @@ export abstract class CollectionFieldInterface {
107
155
  'x-component': 'FieldValidation',
108
156
  'x-component-props': {
109
157
  type: this.validationType,
110
- availableValidationOptions: [...new Set(this.availableValidationOptions)],
158
+ availableValidationOptions,
111
159
  excludeValidationOptions: [...new Set(this.excludeValidationOptions)],
112
160
  isAssociation: this.isAssociation,
113
161
  },
@@ -115,7 +163,7 @@ export abstract class CollectionFieldInterface {
115
163
  }
116
164
  : {};
117
165
  return {
118
- ...cloneDeep({ ...defaultProps, ...this?.properties }),
166
+ ...cloneDeep({ ...defaultProps, ...this?.properties, ...configuredProperties }),
119
167
  ...defaultValueProps,
120
168
  ...validationProps,
121
169
  };
@@ -128,73 +176,19 @@ export abstract class CollectionFieldInterface {
128
176
  required: false,
129
177
  title: '{{ t("Default value") }}',
130
178
  'x-decorator': 'FormItem',
131
- 'x-reactions': [
132
- {
133
- dependencies: [
134
- 'uiSchema.x-component-props.gmt',
135
- 'uiSchema.x-component-props.showTime',
136
- 'uiSchema.x-component-props.dateFormat',
137
- 'uiSchema.x-component-props.timeFormat',
138
- 'uiSchema.x-component-props.picker',
139
- 'uiSchema.x-component-props.format',
140
- ],
141
- fulfill: {
142
- state: {
143
- componentProps: {
144
- gmt: '{{$deps[0]}}',
145
- showTime: '{{$deps[1]}}',
146
- dateFormat: '{{$deps[2]}}',
147
- timeFormat: '{{$deps[3]}}',
148
- picker: '{{$deps[4]}}',
149
- format: '{{$deps[5]}}',
150
- },
151
- },
152
- },
153
- },
154
- {
155
- // 当 picker 改变时,清空 defaultValue
156
- dependencies: ['uiSchema.x-component-props.picker'],
157
- fulfill: {
158
- state: {
159
- value: null,
160
- },
161
- },
162
- },
163
- {
164
- dependencies: ['primaryKey', 'unique', 'autoIncrement', 'defaultToCurrentTime'],
165
- when: '{{$deps[0]||$deps[1]||$deps[2]||$deps[3]}}',
166
- fulfill: {
167
- state: {
168
- hidden: true,
169
- value: null,
170
- },
171
- },
172
- otherwise: {
173
- state: {
174
- hidden: false,
175
- },
176
- },
177
- },
178
- {
179
- dependencies: ['uiSchema.enum'],
180
- fulfill: {
181
- state: {
182
- dataSource: '{{$deps[0]}}',
183
- },
184
- },
185
- },
186
- ],
187
179
  },
188
180
  };
189
181
  }
190
182
 
191
- addOperator(operatorOption: any) {
192
- set(this, 'filterable.operators', [...(this.filterable.operators || [])]);
183
+ addOperator(operatorOption: FieldFilterOperator) {
184
+ normalizeFilterableOperators(this.filterable);
185
+ const operators = [...resolveFilterOperators(this.filterable?.operators)];
186
+ set(this, 'filterable.operators', operators);
193
187
 
194
- if (this.filterable.operators.find((item) => item.value === operatorOption.value)) {
188
+ if (operators.find((item) => item.value === operatorOption.value)) {
195
189
  return;
196
190
  }
197
191
 
198
- this.filterable.operators.push(operatorOption);
192
+ operators.push(operatorOption);
199
193
  }
200
194
  }
@@ -7,16 +7,43 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
+ import {
11
+ filterOperatorRegistry,
12
+ normalizeFilterableOperators,
13
+ type FieldFilterable,
14
+ type FieldFilterOperator,
15
+ type FieldFilterOperatorReference,
16
+ } from '../collection-manager/filter-operators';
17
+ import { configurePropertiesToItems } from '../collection-manager/field-configure';
18
+ import {
19
+ addFieldValidationConfiguresToGroup,
20
+ fieldValidationConfigureRegistry,
21
+ registerFieldValidationConfigure,
22
+ registerFieldValidationConfigureGroup,
23
+ type FieldValidationConfigureInput,
24
+ type FieldValidationConfigureItem,
25
+ } from '../collection-manager/field-validation';
26
+ import type { FieldInterfaceConfigure } from './CollectionFieldInterface';
27
+ import type { ReactNode } from 'react';
28
+
10
29
  interface FieldInterfaceLike {
11
30
  name?: string;
31
+ title?: ReactNode;
32
+ group?: string;
33
+ order?: number;
34
+ isAssociation?: boolean;
12
35
  supportDataSourceType?: string[];
13
36
  notSupportDataSourceType?: string[];
37
+ properties?: Record<string, any>;
38
+ configure?: FieldInterfaceConfigure;
39
+ filterable?: FieldFilterable;
14
40
  addComponentOption?: (option: any) => void;
15
- addOperator?: (option: any) => void;
41
+ addOperator?: (option: FieldFilterOperator) => void;
42
+ getConfigureFormProperties?: (collectionInfo?: any) => Record<string, any>;
16
43
  }
17
44
 
18
45
  interface PendingAction {
19
- type: 'addComponentOption' | 'addOperator';
46
+ type: 'addComponentOption' | 'addOperator' | 'registerConfigure';
20
47
  data: any;
21
48
  }
22
49
 
@@ -50,10 +77,14 @@ export class CollectionFieldInterfaceManager {
50
77
  ) {
51
78
  const newCollectionFieldInterfaces = fieldInterfaceClasses.reduce<Record<string, FieldInterfaceLike>>(
52
79
  (acc, Interface) => {
80
+ if (typeof Interface !== 'function') {
81
+ return acc;
82
+ }
53
83
  const instance = new Interface(this);
54
84
  if (!instance?.name) {
55
85
  return acc;
56
86
  }
87
+ normalizeFilterableOperators(instance.filterable);
57
88
  acc[instance.name] = instance;
58
89
  if (Array.isArray(this.actionList[instance.name])) {
59
90
  this.actionList[instance.name].forEach((item) => {
@@ -61,9 +92,13 @@ export class CollectionFieldInterfaceManager {
61
92
  instance.addComponentOption?.(item.data);
62
93
  return;
63
94
  }
95
+ if (item.type === 'registerConfigure') {
96
+ instance.configure = this.mergeFieldInterfaceConfigure(instance.configure, item.data);
97
+ return;
98
+ }
64
99
  instance.addOperator?.(item.data);
65
100
  });
66
- this.actionList[instance.name] = undefined;
101
+ delete this.actionList[instance.name];
67
102
  }
68
103
  return acc;
69
104
  },
@@ -96,7 +131,7 @@ export class CollectionFieldInterfaceManager {
96
131
  * @param operatorOption 操作符配置
97
132
  * @returns void
98
133
  */
99
- addFieldInterfaceOperator(name: string, operatorOption: any) {
134
+ addFieldInterfaceOperator(name: string, operatorOption: FieldFilterOperator) {
100
135
  const fieldInterface = this.getFieldInterface(name);
101
136
  if (!fieldInterface) {
102
137
  this.enqueueAction(name, { type: 'addOperator', data: operatorOption });
@@ -105,6 +140,78 @@ export class CollectionFieldInterfaceManager {
105
140
  fieldInterface.addOperator?.(operatorOption);
106
141
  }
107
142
 
143
+ /**
144
+ * 注册 v2 字段过滤操作符。
145
+ *
146
+ * 插件可通过该方法补充自己的过滤操作符,再把它们加入自定义 operator group。
147
+ *
148
+ * @param operator 过滤操作符配置
149
+ * @returns void
150
+ */
151
+ registerFieldFilterOperator(operator: FieldFilterOperator) {
152
+ filterOperatorRegistry.register(operator);
153
+ }
154
+
155
+ /**
156
+ * 注册 v2 字段过滤操作符分组。
157
+ *
158
+ * 字段 interface 可以通过 `createFilterable(groupName)` 引用这里注册的分组。
159
+ *
160
+ * @param name 分组名
161
+ * @param operators 操作符配置或已注册操作符名
162
+ * @returns void
163
+ */
164
+ registerFieldFilterOperatorGroup(name: string, operators: FieldFilterOperatorReference[] = []) {
165
+ filterOperatorRegistry.registerGroup(name, operators);
166
+ this.normalizeFieldInterfaceFilterables();
167
+ }
168
+
169
+ /**
170
+ * 向已有 v2 字段过滤操作符分组追加操作符。
171
+ *
172
+ * @param name 分组名
173
+ * @param operators 操作符配置或已注册操作符名
174
+ * @returns void
175
+ */
176
+ addFieldFilterOperatorsToGroup(name: string, operators: FieldFilterOperatorReference[] = []) {
177
+ filterOperatorRegistry.addToGroup(name, operators);
178
+ this.normalizeFieldInterfaceFilterables();
179
+ }
180
+
181
+ registerFieldValidationConfigure(item: FieldValidationConfigureItem) {
182
+ registerFieldValidationConfigure(item);
183
+ }
184
+
185
+ registerFieldValidationConfigureGroup(name: string, items: FieldValidationConfigureInput[] = []) {
186
+ registerFieldValidationConfigureGroup(name, items);
187
+ }
188
+
189
+ addFieldValidationConfiguresToGroup(name: string, items: FieldValidationConfigureInput[] = []) {
190
+ addFieldValidationConfiguresToGroup(name, items);
191
+ }
192
+
193
+ getFieldValidationConfigureGroup(name: string) {
194
+ return fieldValidationConfigureRegistry.getGroup(name);
195
+ }
196
+
197
+ /**
198
+ * 注册字段接口创建/编辑字段时的配置项。
199
+ *
200
+ * 字段插件可以把复杂配置组件、配置属性、normalize / initialize 等逻辑挂到字段接口自身。
201
+ * 如果字段接口尚未注册,配置会暂存并在接口注册后回放。
202
+ *
203
+ * @param options 字段接口配置
204
+ * @returns void
205
+ */
206
+ registerFieldInterfaceConfigure(options: FieldInterfaceConfigure & { name: string }) {
207
+ const fieldInterface = this.getFieldInterface(options.name);
208
+ if (!fieldInterface) {
209
+ this.enqueueAction(options.name, { type: 'registerConfigure', data: options });
210
+ return;
211
+ }
212
+ fieldInterface.configure = this.mergeFieldInterfaceConfigure(fieldInterface.configure, options);
213
+ }
214
+
108
215
  /**
109
216
  * 获取单个字段接口实例。
110
217
  *
@@ -139,6 +246,54 @@ export class CollectionFieldInterfaceManager {
139
246
  }) as T[];
140
247
  }
141
248
 
249
+ /**
250
+ * 获取字段接口创建/编辑字段时的配置属性。
251
+ *
252
+ * 字段接口可以通过自身的 properties / getConfigureFormProperties() 定义专属配置项。
253
+ * 数据源管理等 v2 页面只需要通过该方法读取,不需要硬编码具体字段类型。
254
+ *
255
+ * @param name 字段接口名
256
+ * @param collectionInfo 当前数据表信息
257
+ * @returns 配置属性映射
258
+ */
259
+ getFieldInterfaceConfigureProperties(name: string, collectionInfo?: any) {
260
+ const configure = this.getFieldInterfaceConfigure(name, collectionInfo);
261
+ return configure?.getConfigureFormProperties?.(collectionInfo) || configure?.properties || {};
262
+ }
263
+
264
+ /**
265
+ * 获取字段接口配置。
266
+ *
267
+ * 返回值会合并字段接口自身声明和后注册配置;后注册配置优先。
268
+ *
269
+ * @param name 字段接口名
270
+ * @param collectionInfo 当前数据表信息
271
+ * @returns 字段接口配置
272
+ */
273
+ getFieldInterfaceConfigure(name: string, collectionInfo?: any) {
274
+ const fieldInterface = this.getFieldInterface(name);
275
+ if (!fieldInterface) {
276
+ return undefined;
277
+ }
278
+ const properties = fieldInterface.getConfigureFormProperties?.(collectionInfo) || fieldInterface.properties || {};
279
+ const baseConfigure: FieldInterfaceConfigure = {
280
+ name: fieldInterface.name,
281
+ title: fieldInterface.title,
282
+ group: fieldInterface.group,
283
+ order: fieldInterface.order,
284
+ default: (fieldInterface as any).default,
285
+ titleUsable: (fieldInterface as any).titleUsable,
286
+ isAssociation: fieldInterface.isAssociation,
287
+ supportDataSourceType: fieldInterface.supportDataSourceType,
288
+ notSupportDataSourceType: fieldInterface.notSupportDataSourceType,
289
+ properties,
290
+ items: configurePropertiesToItems(properties, { components: fieldInterface.configure?.components }),
291
+ getConfigureFormProperties: fieldInterface.getConfigureFormProperties?.bind(fieldInterface),
292
+ };
293
+
294
+ return this.mergeFieldInterfaceConfigure(baseConfigure, fieldInterface.configure);
295
+ }
296
+
142
297
  /**
143
298
  * 注册字段接口分组。
144
299
  *
@@ -174,4 +329,46 @@ export class CollectionFieldInterfaceManager {
174
329
  }
175
330
  this.actionList[interfaceName].push(action);
176
331
  }
332
+
333
+ protected normalizeFieldInterfaceFilterables() {
334
+ Object.values(this.collectionFieldInterfaceInstances).forEach((fieldInterface) => {
335
+ normalizeFilterableOperators(fieldInterface.filterable);
336
+ });
337
+ }
338
+
339
+ protected mergeFieldInterfaceConfigure(
340
+ base?: FieldInterfaceConfigure,
341
+ override?: FieldInterfaceConfigure,
342
+ ): FieldInterfaceConfigure | undefined {
343
+ if (!base) {
344
+ return override;
345
+ }
346
+ if (!override) {
347
+ return base;
348
+ }
349
+ return {
350
+ ...base,
351
+ ...override,
352
+ default: override.default || base.default,
353
+ properties: {
354
+ ...(base.properties || {}),
355
+ ...(override.properties || {}),
356
+ },
357
+ items: this.mergeFieldConfigureItems(base.items, override.items),
358
+ components: {
359
+ ...(base.components || {}),
360
+ ...(override.components || {}),
361
+ },
362
+ };
363
+ }
364
+
365
+ protected mergeFieldConfigureItems(
366
+ baseItems: FieldInterfaceConfigure['items'] = [],
367
+ overrideItems: FieldInterfaceConfigure['items'] = [],
368
+ ) {
369
+ const itemMap = new Map<string, NonNullable<FieldInterfaceConfigure['items']>[number]>();
370
+ baseItems.forEach((item) => itemMap.set(item.name, item));
371
+ overrideItems.forEach((item) => itemMap.set(item.name, item));
372
+ return Array.from(itemMap.values());
373
+ }
177
374
  }