@nocobase/client-v2 2.1.0-beta.43 → 2.1.0-beta.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 (91) hide show
  1. package/es/BaseApplication.d.ts +9 -0
  2. package/es/authRedirect.d.ts +12 -0
  3. package/es/collection-manager/filter-operators/index.d.ts +1 -0
  4. package/es/components/form/filter/CollectionFilterItem.d.ts +5 -1
  5. package/es/components/form/filter/FilterValueInput.d.ts +5 -0
  6. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +1 -0
  7. package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +11 -0
  8. package/es/flow/admin-shell/admin-layout/index.d.ts +1 -0
  9. package/es/flow/admin-shell/admin-layout/useApplications.d.ts +3 -2
  10. package/es/flow/components/ConditionBuilder.d.ts +1 -0
  11. package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
  12. package/es/flow/components/FieldAssignValueInput.d.ts +1 -0
  13. package/es/flow/components/fieldAssignOptions.d.ts +10 -0
  14. package/es/flow/components/filter/LinkageFilterItem.d.ts +1 -0
  15. package/es/flow/components/filter/VariableFilterItem.d.ts +1 -0
  16. package/es/flow/components/filter/metaTreeAssociationDepth.d.ts +13 -0
  17. package/es/flow/internal/utils/operatorSchemaHelper.d.ts +26 -3
  18. package/es/flow/models/base/AssociationFieldGroupModel.d.ts +2 -33
  19. package/es/flow/models/blocks/filter-manager/utils.d.ts +23 -1
  20. package/es/flow/models/blocks/table/TableColumnModel.d.ts +2 -0
  21. package/es/index.mjs +179 -101
  22. package/lib/index.js +187 -109
  23. package/package.json +7 -7
  24. package/src/BaseApplication.tsx +13 -0
  25. package/src/__tests__/browserChecker.test.ts +103 -0
  26. package/src/__tests__/dataSourceRuntime.test.tsx +22 -1
  27. package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +5 -0
  28. package/src/authRedirect.ts +43 -0
  29. package/src/collection-field-interface/CollectionFieldInterface.ts +14 -7
  30. package/src/collection-manager/filter-operators/index.ts +29 -2
  31. package/src/components/form/filter/CollectionFilterItem.tsx +10 -2
  32. package/src/components/form/filter/FilterValueInput.tsx +27 -2
  33. package/src/components/form/filter/__tests__/FilterValueInput.test.tsx +39 -0
  34. package/src/flow/__tests__/FlowRoute.test.tsx +8 -1
  35. package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +369 -2
  36. package/src/flow/actions/dataScope.tsx +8 -1
  37. package/src/flow/actions/linkageRules.tsx +56 -1
  38. package/src/flow/actions/setTargetDataScope.tsx +1 -1
  39. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +31 -3
  40. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +15 -1
  41. package/src/flow/admin-shell/admin-layout/AppListRender.tsx +139 -0
  42. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +75 -1
  43. package/src/flow/admin-shell/admin-layout/index.ts +1 -0
  44. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +11 -0
  45. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +2 -4
  46. package/src/flow/admin-shell/admin-layout/useApplications.tsx +34 -1
  47. package/src/flow/common/Markdown/Edit.tsx +32 -4
  48. package/src/flow/components/ConditionBuilder.tsx +12 -2
  49. package/src/flow/components/DefaultValue.tsx +14 -8
  50. package/src/flow/components/FieldAssignRulesEditor.tsx +37 -46
  51. package/src/flow/components/FieldAssignValueInput.tsx +14 -14
  52. package/src/flow/components/__tests__/FieldAssignRulesEditor.test.tsx +112 -1
  53. package/src/flow/components/__tests__/fieldAssignOptions.test.ts +71 -1
  54. package/src/flow/components/fieldAssignOptions.ts +23 -6
  55. package/src/flow/components/filter/LinkageFilterItem.tsx +26 -12
  56. package/src/flow/components/filter/VariableFilterItem.tsx +32 -13
  57. package/src/flow/components/filter/__tests__/fieldsToOptions.test.ts +48 -0
  58. package/src/flow/components/filter/__tests__/metaTreeAssociationDepth.test.ts +60 -0
  59. package/src/flow/components/filter/fieldsToOptions.ts +9 -4
  60. package/src/flow/components/filter/metaTreeAssociationDepth.ts +69 -0
  61. package/src/flow/internal/utils/operatorSchemaHelper.ts +112 -5
  62. package/src/flow/models/actions/FilterActionModel.tsx +15 -3
  63. package/src/flow/models/base/AssociationFieldGroupModel.tsx +20 -3
  64. package/src/flow/models/base/GridModel.tsx +1 -1
  65. package/src/flow/models/base/PageModel/ChildPageModel.tsx +5 -1
  66. package/src/flow/models/base/PageModel/__tests__/ChildPageModel.test.ts +12 -0
  67. package/src/flow/models/base/__tests__/AssociationFieldGroupModel.test.ts +86 -0
  68. package/src/flow/models/base/__tests__/GridModel.render.test.tsx +53 -0
  69. package/src/flow/models/blocks/assign-form/AssignFormGridModel.tsx +11 -0
  70. package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +14 -12
  71. package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +6 -1
  72. package/src/flow/models/blocks/filter-manager/__tests__/getDefaultOperator.test.ts +35 -1
  73. package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/customizeFilterRender.test.tsx +148 -0
  74. package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/defaultOperator.test.tsx +85 -0
  75. package/src/flow/models/blocks/filter-manager/flow-actions/connectFields.tsx +48 -6
  76. package/src/flow/models/blocks/filter-manager/flow-actions/customizeFilterRender.tsx +14 -44
  77. package/src/flow/models/blocks/filter-manager/flow-actions/defaultOperator.tsx +3 -5
  78. package/src/flow/models/blocks/filter-manager/flow-actions/operatorComponentProps.tsx +2 -12
  79. package/src/flow/models/blocks/filter-manager/utils.ts +143 -4
  80. package/src/flow/models/blocks/form/FormAssociationItemModel.tsx +9 -0
  81. package/src/flow/models/blocks/form/FormItemModel.tsx +9 -0
  82. package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +17 -0
  83. package/src/flow/models/blocks/form/__tests__/FormItemModel.defineChildren.test.ts +27 -2
  84. package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +29 -0
  85. package/src/flow/models/blocks/form/value-runtime/runtime.ts +5 -1
  86. package/src/flow/models/blocks/table/TableColumnModel.tsx +15 -5
  87. package/src/flow/models/blocks/table/TableCustomColumnModel.tsx +2 -2
  88. package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +18 -0
  89. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +6 -7
  90. package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +5 -3
  91. package/src/flow/models/fields/mobile-components/__tests__/MobileSelect.test.tsx +70 -0
@@ -10,7 +10,7 @@
10
10
  import { useFlowModelContext } from '@nocobase/flow-engine';
11
11
  import { Select } from 'antd';
12
12
  import type { CSSProperties } from 'react';
13
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
13
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
14
14
  import { Button, CheckList, Popup, SearchBar, SpinLoading } from 'antd-mobile';
15
15
  import { css } from '@emotion/css';
16
16
  import {
@@ -51,7 +51,7 @@ function deriveRecordsFromValue(
51
51
  ) {
52
52
  if (isMultiple) {
53
53
  if (Array.isArray(value)) {
54
- return (value.filter(Boolean) as any[]).map((item) => {
54
+ return (value.filter((item) => item !== null && item !== undefined) as any[]).map((item) => {
55
55
  if (valueMode === 'value') {
56
56
  return optionMap.get(item) ?? { [valueKey]: item };
57
57
  }
@@ -113,11 +113,13 @@ export function MobileLazySelect(props: Readonly<LazySelectProps>) {
113
113
  );
114
114
 
115
115
  const [selectedRecords, setSelectedRecords] = useState<AssociationOption[]>(() => derivedRecords);
116
+ const wasVisibleRef = useRef(visible);
116
117
 
117
118
  useEffect(() => {
118
- if (visible) {
119
+ if (visible && !wasVisibleRef.current) {
119
120
  setSelectedRecords(derivedRecords);
120
121
  }
122
+ wasVisibleRef.current = visible;
121
123
  }, [derivedRecords, visible]);
122
124
 
123
125
  useEffect(() => {
@@ -10,6 +10,7 @@
10
10
  import React from 'react';
11
11
  import { beforeEach, describe, it, expect, vi } from 'vitest';
12
12
  import { act, fireEvent, render, screen } from '@nocobase/test/client';
13
+ import { MobileLazySelect } from '../MobileLazySelect';
13
14
  import { MobileSelect } from '../MobileSelect';
14
15
 
15
16
  const DEFAULT_OPTIONS = [
@@ -17,6 +18,11 @@ const DEFAULT_OPTIONS = [
17
18
  { label: 'Option B', value: 'b' },
18
19
  ];
19
20
 
21
+ const RELATION_OPTIONS = [
22
+ { uuid: '05f6a3b4-bfb7-7943-578a-3819e2687a7e' },
23
+ { uuid: 'c7d99828-a1de-9e70-4c2d-b0139abdf02e' },
24
+ ];
25
+
20
26
  const mockState = vi.hoisted(() => ({
21
27
  selectProps: undefined as any,
22
28
  popupProps: undefined as any,
@@ -44,6 +50,13 @@ function openPopup() {
44
50
  expect(screen.getByTestId('popup')).toBeInTheDocument();
45
51
  }
46
52
 
53
+ function openLazyPopup() {
54
+ act(() => {
55
+ mockState.selectProps?.onClick?.();
56
+ });
57
+ expect(screen.getByTestId('popup')).toBeInTheDocument();
58
+ }
59
+
47
60
  function selectValues(values: string[]) {
48
61
  act(() => {
49
62
  mockState.checklistProps?.onChange?.(values);
@@ -73,6 +86,30 @@ function renderMobileSelect(props: Record<string, any> = {}) {
73
86
  return { onChange, onChangeComplete };
74
87
  }
75
88
 
89
+ function renderMobileLazySelect(props: Record<string, any> = {}) {
90
+ const onChange = props.onChange ?? vi.fn();
91
+ const renderComponent = (nextProps: Record<string, any> = {}) => (
92
+ <MobileLazySelect
93
+ fieldNames={{ label: 'uuid', value: 'uuid' }}
94
+ value={[]}
95
+ multiple
96
+ allowMultiple
97
+ options={RELATION_OPTIONS}
98
+ {...props}
99
+ {...nextProps}
100
+ onChange={onChange}
101
+ />
102
+ );
103
+
104
+ const result = render(renderComponent());
105
+
106
+ return {
107
+ ...result,
108
+ onChange,
109
+ rerender: (nextProps: Record<string, any> = {}) => result.rerender(renderComponent(nextProps)),
110
+ };
111
+ }
112
+
76
113
  vi.mock('@nocobase/flow-engine', async () => {
77
114
  const actual = await vi.importActual<any>('@nocobase/flow-engine');
78
115
  return {
@@ -80,6 +117,12 @@ vi.mock('@nocobase/flow-engine', async () => {
80
117
  useFlowModelContext: () => ({
81
118
  t: (value: string) => value,
82
119
  }),
120
+ useFlowModel: () => ({
121
+ context: {
122
+ collectionField: {},
123
+ },
124
+ subModels: {},
125
+ }),
83
126
  };
84
127
  });
85
128
 
@@ -240,3 +283,30 @@ describe('MobileSelect in SubForm/SubTable containers', () => {
240
283
  expect(onCommit).toHaveBeenNthCalledWith(2, ['a', 'b']);
241
284
  });
242
285
  });
286
+
287
+ describe('MobileLazySelect', () => {
288
+ beforeEach(() => {
289
+ resetMockState();
290
+ });
291
+
292
+ it('keeps pending relation records selected until confirm', () => {
293
+ const { onChange, rerender } = renderMobileLazySelect();
294
+
295
+ openLazyPopup();
296
+ expect(mockState.checklistProps?.value).toEqual([]);
297
+
298
+ selectValues(['c7d99828-a1de-9e70-4c2d-b0139abdf02e']);
299
+ expect(mockState.checklistProps?.value).toEqual(['c7d99828-a1de-9e70-4c2d-b0139abdf02e']);
300
+
301
+ rerender({
302
+ options: RELATION_OPTIONS.map((item) => ({ ...item })),
303
+ });
304
+
305
+ expect(mockState.checklistProps?.value).toEqual(['c7d99828-a1de-9e70-4c2d-b0139abdf02e']);
306
+
307
+ confirmSelection();
308
+
309
+ expect(onChange).toHaveBeenCalledTimes(1);
310
+ expect(onChange).toHaveBeenCalledWith([RELATION_OPTIONS[1]]);
311
+ });
312
+ });