@nocobase/client-v2 2.2.0-beta.8 → 2.2.0
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.
- package/es/APIClient.d.ts +13 -3
- package/es/BaseApplication.d.ts +3 -0
- package/es/RouteRepository.d.ts +8 -0
- package/es/RouterManager.d.ts +15 -0
- package/es/authRedirect.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterface.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +1 -0
- package/es/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
- package/es/components/category-tabs/index.d.ts +9 -0
- package/es/components/form/ScanInput/useCodeScanner.d.ts +3 -2
- package/es/components/form/TypedVariableInput.d.ts +31 -5
- package/es/components/form/filter/CollectionFilter.d.ts +2 -0
- package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
- package/es/components/form/filter/CollectionFilterPanel.d.ts +2 -0
- package/es/components/form/filter/index.d.ts +2 -0
- package/es/components/form/filter/useFilterActionProps.d.ts +2 -0
- package/es/components/index.d.ts +1 -0
- package/es/entry-actions/EntryActionManager.d.ts +24 -0
- package/es/entry-actions/index.d.ts +9 -0
- package/es/flow/actions/index.d.ts +1 -1
- package/es/flow/actions/linkageRules.d.ts +27 -0
- package/es/flow/admin-shell/BaseLayoutModel.d.ts +6 -0
- package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +7 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +1 -0
- package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +2 -1
- package/es/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.d.ts +24 -0
- package/es/flow/admin-shell/admin-layout/index.d.ts +1 -0
- package/es/flow/admin-shell/admin-layout/useApplications.d.ts +7 -2
- package/es/flow/components/FieldAssignExactDatePicker.d.ts +1 -0
- package/es/flow/components/FieldAssignValueInput.d.ts +7 -24
- package/es/flow/components/FlowRoute.d.ts +2 -2
- package/es/flow/components/RunJSValueEditor.d.ts +1 -0
- package/es/flow/components/field-value-variable/DateVariableEditor.d.ts +24 -0
- package/es/flow/components/field-value-variable/FieldValueVariableInput.d.ts +31 -0
- package/es/flow/components/field-value-variable/dateValue.d.ts +36 -0
- package/es/flow/components/field-value-variable/index.d.ts +11 -0
- package/es/flow/components/filter/FilterGroup.d.ts +1 -0
- package/es/flow/components/filter/VariableFilterItem.d.ts +6 -1
- package/es/flow/components/placeholders/BlockPlaceholder.d.ts +1 -0
- package/es/flow/index.d.ts +1 -0
- package/es/flow/internal/registerDeviceTypeContext.d.ts +10 -0
- package/es/flow/internal/utils/operatorSchemaHelper.d.ts +2 -2
- package/es/flow/models/actions/UpdateRecordActionUtils.d.ts +8 -2
- package/es/flow/models/base/ActionModelCore.d.ts +6 -2
- package/es/flow/models/base/BlockGridModel.d.ts +3 -0
- package/es/flow/models/base/CollectionBlockModel.d.ts +3 -0
- package/es/flow/models/base/PageModel/PageModel.d.ts +12 -0
- package/es/flow/models/base/PageModel/PageModelTabBar.d.ts +22 -0
- package/es/flow/models/base/PageModel/PageTabModel.d.ts +12 -0
- package/es/flow/models/blocks/details/DetailsBlockModel.d.ts +3 -0
- package/es/flow/models/blocks/filter-form/FilterFormGridModel.d.ts +1 -0
- package/es/flow/models/blocks/filter-form/FilterFormSubmitActionModel.d.ts +3 -1
- package/es/flow/models/blocks/form/FormBlockModel.d.ts +7 -0
- package/es/flow/models/blocks/form/FormGridModel.d.ts +6 -0
- package/es/flow/models/blocks/form/QuickEditFormModel.d.ts +17 -2
- package/es/flow/models/blocks/form/value-runtime/rules.d.ts +1 -0
- package/es/flow/models/blocks/table/JSColumnModel.d.ts +2 -0
- package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableColumnModel.d.ts +12 -0
- package/es/flow/models/blocks/table/utils.d.ts +1 -0
- package/es/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.d.ts +2 -1
- package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +0 -17
- package/es/flow/models/fields/AssociationFieldModel/recordSelectShared.d.ts +41 -0
- package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +15 -7
- package/es/flow/routeTransientInputArgs.d.ts +14 -0
- package/es/flow-compat/fieldValidationConstants.d.ts +1 -1
- package/es/flow-compat/passwordUtils.d.ts +1 -1
- package/es/flow-compat/routeTypes.d.ts +1 -0
- package/es/index.d.ts +7 -0
- package/es/index.mjs +301 -177
- package/es/ui-operation/index.d.ts +15 -0
- package/es/ui-operation/ui-operation-codec.d.ts +10 -0
- package/es/utils/getRouteRuntimeVersion.d.ts +23 -0
- package/es/utils/index.d.ts +1 -0
- package/es/utils/markdownSanitize.d.ts +11 -0
- package/lib/index.js +313 -189
- package/lib/locale/languageCodes.js +3 -1
- package/package.json +9 -7
- package/src/APIClient.ts +90 -7
- package/src/Application.tsx +7 -1
- package/src/BaseApplication.tsx +13 -6
- package/src/RouteRepository.ts +25 -0
- package/src/RouterManager.tsx +142 -1
- package/src/__tests__/APIClient.test.tsx +58 -0
- package/src/__tests__/RouteRepository.test.ts +23 -0
- package/src/__tests__/RouterManager.test.ts +125 -0
- package/src/__tests__/app.test.tsx +73 -0
- package/src/__tests__/authRedirect.test.ts +17 -0
- package/src/__tests__/browserChecker.test.ts +61 -0
- package/src/__tests__/getRouteRuntimeVersion.test.ts +68 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +35 -2
- package/src/__tests__/settings-center.test.tsx +270 -6
- package/src/acl/ACLProvider.tsx +2 -0
- package/src/acl/__tests__/ACLProvider.test.tsx +92 -0
- package/src/authRedirect.ts +38 -0
- package/src/collection-field-interface/CollectionFieldInterface.ts +1 -0
- package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +1 -0
- package/src/collection-manager/field-validation.ts +1 -1
- package/src/components/README.md +7 -1
- package/src/components/README.zh-CN.md +6 -1
- package/src/components/category-tabs/SortableCategoryTabs.tsx +210 -0
- package/src/components/category-tabs/index.ts +10 -0
- package/src/components/form/JsonTextArea.tsx +4 -0
- package/src/components/form/ScanInput/CodeScanner.tsx +79 -35
- package/src/components/form/ScanInput/__tests__/CodeScanner.test.tsx +101 -0
- package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +284 -11
- package/src/components/form/ScanInput/useCodeScanner.ts +332 -24
- package/src/components/form/TypedVariableInput.tsx +452 -101
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +364 -12
- package/src/components/form/filter/CollectionFilter.tsx +4 -0
- package/src/components/form/filter/CollectionFilterItem.tsx +36 -9
- package/src/components/form/filter/CollectionFilterPanel.tsx +4 -0
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +55 -0
- package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +95 -0
- package/src/components/form/filter/index.ts +2 -0
- package/src/components/form/filter/useFilterActionProps.ts +37 -6
- package/src/components/form/table/Table.tsx +81 -6
- package/src/components/form/table/__tests__/Table.columnWidth.test.tsx +433 -0
- package/src/components/index.ts +1 -0
- package/src/entry-actions/EntryActionManager.ts +76 -0
- package/src/entry-actions/index.ts +10 -0
- package/src/flow/FlowPage.tsx +38 -3
- package/src/flow/__tests__/FlowPage.test.tsx +201 -27
- package/src/flow/__tests__/FlowRoute.test.tsx +675 -12
- package/src/flow/__tests__/PluginFlowEngine.test.ts +58 -0
- package/src/flow/actions/__tests__/actionLinkageRules.forkProps.test.ts +314 -0
- package/src/flow/actions/__tests__/dataScopeFilter.test.ts +62 -0
- package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +102 -0
- package/src/flow/actions/__tests__/linkageRules.actionStates.test.ts +33 -0
- package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +72 -0
- package/src/flow/actions/__tests__/linkageRules.tab.test.ts +171 -0
- package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +7 -3
- package/src/flow/actions/__tests__/openView.defineProps.route.test.tsx +80 -20
- package/src/flow/actions/dataScopeFilter.ts +10 -1
- package/src/flow/actions/dateTimeFormat.tsx +2 -2
- package/src/flow/actions/index.ts +2 -0
- package/src/flow/actions/linkageRules.tsx +144 -26
- package/src/flow/actions/linkageRulesRefresh.tsx +2 -6
- package/src/flow/actions/openView.tsx +21 -1
- package/src/flow/admin-shell/BaseLayoutModel.tsx +124 -0
- package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +184 -42
- package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +1016 -119
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +41 -5
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +177 -1
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +20 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +78 -59
- package/src/flow/admin-shell/admin-layout/AppListRender.tsx +13 -2
- package/src/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.tsx +289 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +253 -6
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +228 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +436 -2
- package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +48 -0
- package/src/flow/admin-shell/admin-layout/index.ts +1 -0
- package/src/flow/admin-shell/admin-layout/useApplications.tsx +81 -12
- package/src/flow/common/Markdown/Display.tsx +14 -3
- package/src/flow/common/Markdown/Edit.tsx +19 -7
- package/src/flow/common/Markdown/style.ts +4 -0
- package/src/flow/components/BlockItemCard.tsx +2 -2
- package/src/flow/components/FieldAssignExactDatePicker.tsx +25 -11
- package/src/flow/components/FieldAssignValueInput.tsx +72 -584
- package/src/flow/components/FlowRoute.tsx +204 -46
- package/src/flow/components/RunJSValueEditor.tsx +9 -1
- package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +216 -0
- package/src/flow/components/field-value-variable/DateVariableEditor.tsx +181 -0
- package/src/flow/components/field-value-variable/FieldValueVariableInput.tsx +326 -0
- package/src/flow/components/field-value-variable/__tests__/FieldValueVariableInput.test.tsx +380 -0
- package/src/flow/components/field-value-variable/dateValue.ts +223 -0
- package/src/flow/components/field-value-variable/index.ts +12 -0
- package/src/flow/components/filter/FilterGroup.tsx +33 -5
- package/src/flow/components/filter/VariableFilterItem.tsx +170 -13
- package/src/flow/components/filter/__tests__/FilterGroup.test.tsx +45 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.leftMetaTree.test.tsx +9 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +195 -1
- package/src/flow/components/placeholders/BlockPlaceholder.tsx +70 -23
- package/src/flow/components/placeholders/__tests__/BlockPlaceholder.test.tsx +57 -7
- package/src/flow/index.ts +3 -0
- package/src/flow/internal/components/Markdown/util.ts +2 -1
- package/src/flow/internal/registerDeviceTypeContext.ts +39 -0
- package/src/flow/internal/utils/operatorSchemaHelper.ts +3 -2
- package/src/flow/models/actions/UpdateRecordActionModel.tsx +18 -1
- package/src/flow/models/actions/UpdateRecordActionUtils.ts +18 -6
- package/src/flow/models/actions/__tests__/UpdateRecordActionModel.test.ts +76 -4
- package/src/flow/models/base/ActionModel.tsx +10 -8
- package/src/flow/models/base/ActionModelCore.tsx +16 -2
- package/src/flow/models/base/BlockGridModel.tsx +26 -0
- package/src/flow/models/base/CollectionBlockModel.tsx +38 -3
- package/src/flow/models/base/PageModel/PageModel.tsx +387 -53
- package/src/flow/models/base/PageModel/PageModelTabBar.tsx +114 -0
- package/src/flow/models/base/PageModel/PageTabModel.tsx +249 -18
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +790 -10
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.module-isolation.test.tsx +130 -0
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.test.tsx +118 -0
- package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +1075 -7
- package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +49 -0
- package/src/flow/models/base/__tests__/BlockGridModel.selectSceneActivation.test.ts +124 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.addAppends.test.ts +41 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.initialBeforeRenderRefresh.test.ts +125 -9
- package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +28 -53
- package/src/flow/models/blocks/details/DetailsBlockModel.tsx +8 -3
- package/src/flow/models/blocks/details/__tests__/DetailsBlockModel.initialPaginationChangeRefresh.test.ts +32 -1
- package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +28 -3
- package/src/flow/models/blocks/filter-form/FilterFormGridModel.tsx +36 -5
- package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +155 -25
- package/src/flow/models/blocks/filter-form/FilterFormSubmitActionModel.tsx +57 -4
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormGridModel.onModelCreated.test.ts +174 -1
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +395 -1
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.getFilterValue.test.ts +72 -0
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormSubmitActionModel.lifecycle.test.ts +90 -0
- package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +66 -4
- package/src/flow/models/blocks/filter-manager/FilterManager.ts +5 -0
- package/src/flow/models/blocks/filter-manager/__tests__/FilterManager.test.ts +40 -0
- package/src/flow/models/blocks/form/FormBlockModel.tsx +47 -0
- package/src/flow/models/blocks/form/FormGridModel.tsx +4 -0
- package/src/flow/models/blocks/form/QuickEditFormModel.tsx +189 -36
- package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +8 -2
- package/src/flow/models/blocks/form/__tests__/QuickEditFormModel.quickEdit.test.ts +350 -2
- package/src/flow/models/blocks/form/__tests__/runJsFormSubmit.test.ts +131 -0
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +435 -0
- package/src/flow/models/blocks/form/value-runtime/rules.ts +67 -14
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +43 -19
- package/src/flow/models/blocks/js-block/JSBlock.tsx +1 -1
- package/src/flow/models/blocks/table/JSColumnModel.tsx +10 -1
- package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +2 -1
- package/src/flow/models/blocks/table/TableBlockModel.tsx +29 -3
- package/src/flow/models/blocks/table/TableColumnModel.tsx +54 -11
- package/src/flow/models/blocks/table/__tests__/JSColumnModel.test.tsx +52 -5
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.filterReset.test.ts +78 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.quickEditRefresh.test.ts +12 -0
- package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +84 -0
- package/src/flow/models/blocks/table/utils.ts +7 -0
- package/src/flow/models/fields/AssociationFieldModel/CascadeSelectFieldModel.tsx +33 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +10 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/__tests__/popupContext.test.ts +120 -0
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/actions/PopupSubTableEditActionModel.tsx +10 -2
- package/src/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.tsx +24 -1
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +54 -149
- package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +167 -3
- package/src/flow/models/fields/AssociationFieldModel/recordSelectShared.tsx +156 -0
- package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +149 -0
- package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +149 -113
- package/src/flow/models/fields/DisplayNumberFieldModel.tsx +1 -1
- package/src/flow/models/fields/JsonFieldModel.tsx +31 -8
- package/src/flow/models/fields/NumberFieldModel.tsx +1 -1
- package/src/flow/models/fields/TextareaFieldModel.tsx +42 -19
- package/src/flow/models/fields/VariableFieldFormModel.tsx +3 -3
- package/src/flow/models/fields/__tests__/DisplayNumberFieldModel.test.ts +33 -0
- package/src/flow/models/fields/__tests__/JsonFieldModel.test.ts +82 -0
- package/src/flow/models/fields/__tests__/NumberFieldModel.test.tsx +47 -0
- package/src/flow/models/fields/__tests__/TextareaFieldModel.test.tsx +32 -1
- package/src/flow/models/fields/__tests__/VariableFieldFormModel.test.tsx +51 -0
- package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +26 -10
- package/src/flow/models/fields/mobile-components/MobileSelect.tsx +51 -14
- package/src/flow/models/fields/mobile-components/__tests__/MobileSelect.test.tsx +139 -13
- package/src/flow/models/topbar/TopbarActionModel.tsx +78 -3
- package/src/flow/routeTransientInputArgs.ts +27 -0
- package/src/flow/utils/__tests__/dateTimeFormat.test.ts +42 -0
- package/src/flow/utils/dataScopeFormValueClear.ts +4 -3
- package/src/flow-compat/fieldValidationConstants.ts +1 -1
- package/src/flow-compat/routeTypes.ts +1 -0
- package/src/index.ts +7 -0
- package/src/layout-manager/LayoutContentRoute.tsx +2 -1
- package/src/layout-manager/LayoutRoute.tsx +2 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +87 -1
- package/src/locale/languageCodes.ts +3 -1
- package/src/nocobase-buildin-plugin/index.tsx +19 -1
- package/src/settings-center/AdminSettingsLayout.tsx +23 -2
- package/src/ui-operation/index.ts +33 -0
- package/src/ui-operation/ui-operation-codec.ts +54 -0
- package/src/utils/getRouteRuntimeVersion.ts +185 -0
- package/src/utils/index.tsx +1 -0
- package/src/utils/markdownSanitize.ts +88 -0
|
@@ -45,6 +45,7 @@ interface FilterGroupProps {
|
|
|
45
45
|
value: Record<string, any>;
|
|
46
46
|
/** 自定义筛选项组件 */
|
|
47
47
|
FilterItem?: React.FC<FilterItemProps>;
|
|
48
|
+
disabled?: boolean;
|
|
48
49
|
closeIcon?: ReactNode;
|
|
49
50
|
/** 是否显示边框 */
|
|
50
51
|
showBorder?: boolean;
|
|
@@ -89,6 +90,7 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
89
90
|
const {
|
|
90
91
|
value = { logic: '$and', items: [] },
|
|
91
92
|
FilterItem,
|
|
93
|
+
disabled = false,
|
|
92
94
|
showBorder = false,
|
|
93
95
|
onRemove,
|
|
94
96
|
onChange,
|
|
@@ -120,11 +122,17 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
120
122
|
};
|
|
121
123
|
|
|
122
124
|
const handleLogicChange = (newLogic: '$and' | '$or') => {
|
|
125
|
+
if (disabled) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
123
128
|
value.logic = newLogic;
|
|
124
129
|
onChange?.(value);
|
|
125
130
|
};
|
|
126
131
|
|
|
127
132
|
const handleAddCondition = () => {
|
|
133
|
+
if (disabled) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
128
136
|
items.push({
|
|
129
137
|
path: '',
|
|
130
138
|
operator: '',
|
|
@@ -134,6 +142,9 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
134
142
|
};
|
|
135
143
|
|
|
136
144
|
const handleAddConditionGroup = () => {
|
|
145
|
+
if (disabled) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
137
148
|
items.push({
|
|
138
149
|
logic: '$and',
|
|
139
150
|
items: [],
|
|
@@ -142,6 +153,9 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
142
153
|
};
|
|
143
154
|
|
|
144
155
|
const handleRemoveItem = (index: number) => {
|
|
156
|
+
if (disabled) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
145
159
|
items.splice(index, 1);
|
|
146
160
|
onChange?.(value);
|
|
147
161
|
};
|
|
@@ -160,11 +174,12 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
160
174
|
<button
|
|
161
175
|
type="button"
|
|
162
176
|
aria-label="icon-close"
|
|
177
|
+
disabled={disabled}
|
|
163
178
|
style={{
|
|
164
179
|
position: 'absolute',
|
|
165
180
|
right: 10,
|
|
166
181
|
top: 10,
|
|
167
|
-
cursor: 'pointer',
|
|
182
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
168
183
|
background: 'transparent',
|
|
169
184
|
border: 0,
|
|
170
185
|
padding: 0,
|
|
@@ -182,6 +197,7 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
182
197
|
data-testid="filter-select-all-or-any"
|
|
183
198
|
style={{ width: 'auto' }}
|
|
184
199
|
value={logic}
|
|
200
|
+
disabled={disabled}
|
|
185
201
|
onChange={handleLogicChange}
|
|
186
202
|
>
|
|
187
203
|
<Select.Option value="$and">{t('All')}</Select.Option>
|
|
@@ -200,6 +216,7 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
200
216
|
key={getFilterItemKey(item)}
|
|
201
217
|
value={item}
|
|
202
218
|
FilterItem={FilterItem}
|
|
219
|
+
disabled={disabled}
|
|
203
220
|
showBorder={true}
|
|
204
221
|
onRemove={() => handleRemoveItem(index)}
|
|
205
222
|
onChange={(v) => {
|
|
@@ -221,11 +238,12 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
221
238
|
<button
|
|
222
239
|
type="button"
|
|
223
240
|
aria-label="icon-close"
|
|
241
|
+
disabled={disabled}
|
|
224
242
|
style={{
|
|
225
243
|
marginLeft: 8,
|
|
226
244
|
marginRight: 8,
|
|
227
245
|
flex: '0 0 auto',
|
|
228
|
-
cursor: 'pointer',
|
|
246
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
229
247
|
background: 'transparent',
|
|
230
248
|
border: 0,
|
|
231
249
|
padding: 0,
|
|
@@ -251,11 +269,12 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
251
269
|
<button
|
|
252
270
|
type="button"
|
|
253
271
|
aria-label="icon-close"
|
|
272
|
+
disabled={disabled}
|
|
254
273
|
style={{
|
|
255
274
|
marginLeft: 8,
|
|
256
275
|
marginRight: 8,
|
|
257
276
|
flex: '0 0 auto',
|
|
258
|
-
cursor: 'pointer',
|
|
277
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
259
278
|
background: 'transparent',
|
|
260
279
|
border: 0,
|
|
261
280
|
padding: 0,
|
|
@@ -277,11 +296,12 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
277
296
|
<button
|
|
278
297
|
type="button"
|
|
279
298
|
aria-label="icon-close"
|
|
299
|
+
disabled={disabled}
|
|
280
300
|
style={{
|
|
281
301
|
marginLeft: 8,
|
|
282
302
|
marginRight: 8,
|
|
283
303
|
flex: '0 0 auto',
|
|
284
|
-
cursor: 'pointer',
|
|
304
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
285
305
|
background: 'transparent',
|
|
286
306
|
border: 0,
|
|
287
307
|
padding: 0,
|
|
@@ -298,7 +318,14 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
298
318
|
</div>
|
|
299
319
|
|
|
300
320
|
<Space size={16} style={{ marginTop: 8, marginBottom: 8 }}>
|
|
301
|
-
<Button
|
|
321
|
+
<Button
|
|
322
|
+
style={{ padding: 0 }}
|
|
323
|
+
type="link"
|
|
324
|
+
size="small"
|
|
325
|
+
icon={<PlusOutlined />}
|
|
326
|
+
onClick={handleAddCondition}
|
|
327
|
+
disabled={disabled}
|
|
328
|
+
>
|
|
302
329
|
{t('Add condition')}
|
|
303
330
|
</Button>
|
|
304
331
|
<Button
|
|
@@ -307,6 +334,7 @@ export const FilterGroup: FC<FilterGroupProps> = observer(
|
|
|
307
334
|
size="small"
|
|
308
335
|
icon={<PlusOutlined />}
|
|
309
336
|
onClick={handleAddConditionGroup}
|
|
337
|
+
disabled={disabled}
|
|
310
338
|
>
|
|
311
339
|
{t('Add condition group')}
|
|
312
340
|
</Button>
|
|
@@ -34,6 +34,8 @@ const { DateFilterDynamicComponent: DateFilterDynamicComponentLazy } = lazy(
|
|
|
34
34
|
'DateFilterDynamicComponent',
|
|
35
35
|
);
|
|
36
36
|
|
|
37
|
+
const fallbackInputComponents = new Set(['Input', 'Input.URL', 'NanoIDInput', 'DatePicker']);
|
|
38
|
+
|
|
37
39
|
// 简化的本地辅助:按需获取 ctx.collection 的字段树(MetaTreeNode[])
|
|
38
40
|
async function buildCollectionLeftMetaTreeLocal(ctx: any): Promise<MetaTreeNode[]> {
|
|
39
41
|
const resolve = async (sub: any): Promise<MetaTreeNode[]> => {
|
|
@@ -62,6 +64,51 @@ async function buildCollectionLeftMetaTreeLocal(ctx: any): Promise<MetaTreeNode[
|
|
|
62
64
|
return await resolve(subTree);
|
|
63
65
|
}
|
|
64
66
|
|
|
67
|
+
function buildCollectionFieldMetaNode(collection: any, path: string[]): MetaTreeNode | null {
|
|
68
|
+
if (!collection || !path.length) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const normalizedPath = path[0] === 'collection' ? path.slice(1) : path;
|
|
73
|
+
if (!normalizedPath.length) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const parentTitles: string[] = [];
|
|
78
|
+
let currentCollection = collection;
|
|
79
|
+
let currentNode: MetaTreeNode | null = null;
|
|
80
|
+
|
|
81
|
+
for (const segment of normalizedPath) {
|
|
82
|
+
const field =
|
|
83
|
+
currentCollection?.getField?.(segment) ??
|
|
84
|
+
currentCollection?.getFields?.()?.find?.((candidate: any) => candidate?.name === segment);
|
|
85
|
+
if (!field) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const title = field.title || field.uiSchema?.title || field.name || segment;
|
|
90
|
+
currentNode = {
|
|
91
|
+
name: field.name || segment,
|
|
92
|
+
title,
|
|
93
|
+
type: field.type,
|
|
94
|
+
interface: field.interface,
|
|
95
|
+
uiSchema: field.uiSchema,
|
|
96
|
+
options: field.options,
|
|
97
|
+
paths: ['collection', ...normalizedPath.slice(0, parentTitles.length + 1)],
|
|
98
|
+
parentTitles: [...parentTitles],
|
|
99
|
+
} as MetaTreeNode;
|
|
100
|
+
|
|
101
|
+
if (field.targetCollection) {
|
|
102
|
+
parentTitles.push(title);
|
|
103
|
+
currentCollection = field.targetCollection;
|
|
104
|
+
} else {
|
|
105
|
+
currentCollection = null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return currentNode;
|
|
110
|
+
}
|
|
111
|
+
|
|
65
112
|
export interface VariableFilterItemValue {
|
|
66
113
|
path: string;
|
|
67
114
|
operator: string;
|
|
@@ -75,6 +122,7 @@ export interface VariableFilterItemProps {
|
|
|
75
122
|
/** 筛选条件值对象 */
|
|
76
123
|
value: VariableFilterItemValue;
|
|
77
124
|
model: FlowModel;
|
|
125
|
+
disabled?: boolean;
|
|
78
126
|
/**
|
|
79
127
|
* 是否启用右侧 VariableInput(变量或静态值二合一)。
|
|
80
128
|
* 默认 false:保持原有行为,右侧仅静态输入组件。
|
|
@@ -85,6 +133,10 @@ export interface VariableFilterItemProps {
|
|
|
85
133
|
* 默认使用整棵 ctx 的 metaTree:model.context.getPropertyMetaTree()
|
|
86
134
|
*/
|
|
87
135
|
rightMetaTree?: MetaTreeNode[] | (() => MetaTreeNode[] | Promise<MetaTreeNode[]>);
|
|
136
|
+
/**
|
|
137
|
+
* 右侧变量的领域转换器。常量和空值仍由 VariableFilterItem 处理,未匹配的值回退到 FlowEngine 默认转换器。
|
|
138
|
+
*/
|
|
139
|
+
rightVariableConverters?: Pick<Converters, 'resolvePathFromValue' | 'resolveValueFromPath'>;
|
|
88
140
|
ignoreFieldNames?: string[];
|
|
89
141
|
maxAssociationFieldDepth?: number;
|
|
90
142
|
}
|
|
@@ -226,9 +278,9 @@ function createStaticInputRenderer(
|
|
|
226
278
|
onChange={(v: unknown) => onChange?.(v as VariableFilterItemValue['value'])}
|
|
227
279
|
/>
|
|
228
280
|
);
|
|
229
|
-
//
|
|
281
|
+
// 未直接处理的 x-component:尝试从 app 解析组件,可由筛选器接管的过渡组件查找失败时静默回退到 Input
|
|
230
282
|
if (xComp && app?.getComponent) {
|
|
231
|
-
const Comp = app.getComponent(xComp
|
|
283
|
+
const Comp = app.getComponent(xComp, !fallbackInputComponents.has(xComp));
|
|
232
284
|
if (Comp) {
|
|
233
285
|
return (
|
|
234
286
|
<Comp
|
|
@@ -265,11 +317,57 @@ function normalizeRightValueInput(input: unknown) {
|
|
|
265
317
|
return input;
|
|
266
318
|
}
|
|
267
319
|
|
|
320
|
+
function findMetaTreeNodeByPath(metaTree: MetaTreeNode[], targetPath: string[]): MetaTreeNode | null {
|
|
321
|
+
if (!Array.isArray(metaTree) || !targetPath.length) {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const traverseByName = (nodes: MetaTreeNode[], path: string[]): MetaTreeNode | null => {
|
|
326
|
+
if (!path.length) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const [head, ...rest] = path;
|
|
331
|
+
const matched = nodes.find((node) => String(node.name) === String(head));
|
|
332
|
+
if (!matched) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
if (!rest.length) {
|
|
336
|
+
return matched;
|
|
337
|
+
}
|
|
338
|
+
if (!Array.isArray(matched.children)) {
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
return traverseByName(matched.children as MetaTreeNode[], rest);
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
const byNames = traverseByName(metaTree, targetPath);
|
|
345
|
+
if (byNames) {
|
|
346
|
+
return byNames;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const topNames = new Set(metaTree.map((node) => String(node.name)));
|
|
350
|
+
if (!topNames.has(String(targetPath[0]))) {
|
|
351
|
+
return traverseByName(metaTree, targetPath.slice(1));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
268
357
|
/**
|
|
269
358
|
* 上下文筛选项组件
|
|
270
359
|
*/
|
|
271
360
|
export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
272
|
-
({
|
|
361
|
+
({
|
|
362
|
+
value,
|
|
363
|
+
model,
|
|
364
|
+
disabled = false,
|
|
365
|
+
rightAsVariable,
|
|
366
|
+
rightMetaTree,
|
|
367
|
+
rightVariableConverters,
|
|
368
|
+
ignoreFieldNames,
|
|
369
|
+
maxAssociationFieldDepth,
|
|
370
|
+
}) => {
|
|
273
371
|
// 使用 View 上下文,确保可访问 ctx.view 的异步子树
|
|
274
372
|
const ctx = useFlowViewContext();
|
|
275
373
|
const t = model.translate;
|
|
@@ -334,6 +432,9 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
334
432
|
// 处理左侧值变化(值由 converters 决定如何解析)
|
|
335
433
|
const handleLeftChange = useCallback(
|
|
336
434
|
(variableValue: string, meta?: MetaTreeNode) => {
|
|
435
|
+
if (disabled) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
337
438
|
const prevPath = value.path || '';
|
|
338
439
|
const nextPath = variableValue || '';
|
|
339
440
|
const changed = nextPath !== prevPath;
|
|
@@ -348,7 +449,7 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
348
449
|
setLeftMeta(meta);
|
|
349
450
|
}
|
|
350
451
|
},
|
|
351
|
-
[value],
|
|
452
|
+
[disabled, value],
|
|
352
453
|
);
|
|
353
454
|
|
|
354
455
|
// 自定义转换器来捕获 MetaTreeNode,并在选择左值时设置默认操作符
|
|
@@ -376,6 +477,9 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
376
477
|
// 处理操作符变化
|
|
377
478
|
const handleOperatorChange = useCallback(
|
|
378
479
|
(operatorValue: string) => {
|
|
480
|
+
if (disabled) {
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
379
483
|
value.operator = operatorValue;
|
|
380
484
|
const cur = operatorMetaList.find((op) => op.value === operatorValue);
|
|
381
485
|
if (cur?.noValue) {
|
|
@@ -386,7 +490,7 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
386
490
|
value.noValue = false;
|
|
387
491
|
}
|
|
388
492
|
},
|
|
389
|
-
[operatorMetaList, value],
|
|
493
|
+
[disabled, operatorMetaList, value],
|
|
390
494
|
);
|
|
391
495
|
|
|
392
496
|
// 使用公共静态输入渲染器(抽取到 utils)
|
|
@@ -464,9 +568,12 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
464
568
|
|
|
465
569
|
const setRightValue = useCallback(
|
|
466
570
|
(next: unknown) => {
|
|
571
|
+
if (disabled) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
467
574
|
value.value = normalizeRightValueInput(next) as VariableFilterItemValue['value'];
|
|
468
575
|
},
|
|
469
|
-
[value],
|
|
576
|
+
[disabled, value],
|
|
470
577
|
);
|
|
471
578
|
|
|
472
579
|
// 右侧静态输入(无变量模式)与右侧 VariableInput 的静态渲染组件,统一复用
|
|
@@ -490,8 +597,14 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
490
597
|
|
|
491
598
|
const renderRightValueComponent = useCallback(() => {
|
|
492
599
|
// 文本类多关键词:优先使用操作符 schema 声明的组件
|
|
493
|
-
const resolved = resolveOperatorComponent(model.context.app, operator, operatorMetaList);
|
|
494
600
|
const supportKeyword = operator === '$in' || operator === '$notIn';
|
|
601
|
+
const operatorComponent = currentOpMeta?.schema?.['x-component'] as string | undefined;
|
|
602
|
+
const isLocallyRenderedComponent =
|
|
603
|
+
operatorComponent === 'Select' ||
|
|
604
|
+
(typeof operatorComponent === 'string' && fallbackInputComponents.has(operatorComponent));
|
|
605
|
+
const resolved = supportKeyword
|
|
606
|
+
? resolveOperatorComponent(model.context.app, operator, operatorMetaList, !isLocallyRenderedComponent)
|
|
607
|
+
: null;
|
|
495
608
|
if (resolved && supportKeyword) {
|
|
496
609
|
const { Comp, props: xProps } = resolved;
|
|
497
610
|
const nextProps = { ...xProps };
|
|
@@ -520,6 +633,7 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
520
633
|
{...nextProps}
|
|
521
634
|
style={{ width: '100%', ...pickStyle(nextProps.style) }}
|
|
522
635
|
value={normalized}
|
|
636
|
+
disabled={disabled}
|
|
523
637
|
onChange={(vals: any) => setRightValue(vals)}
|
|
524
638
|
/>
|
|
525
639
|
</div>
|
|
@@ -529,10 +643,20 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
529
643
|
const Comp = staticInputRenderer;
|
|
530
644
|
return (
|
|
531
645
|
<div style={{ flex: '1 1 40%', minWidth: 160, maxWidth: '100%' }}>
|
|
532
|
-
<Comp value={rightValue} onChange={(val) => setRightValue(val)} />
|
|
646
|
+
<Comp value={rightValue} onChange={(val) => setRightValue(val)} disabled={disabled} />
|
|
533
647
|
</div>
|
|
534
648
|
);
|
|
535
|
-
}, [
|
|
649
|
+
}, [
|
|
650
|
+
disabled,
|
|
651
|
+
operator,
|
|
652
|
+
operatorMetaList,
|
|
653
|
+
currentOpMeta,
|
|
654
|
+
rightValue,
|
|
655
|
+
staticInputRenderer,
|
|
656
|
+
model.context.app,
|
|
657
|
+
setRightValue,
|
|
658
|
+
enumOptions,
|
|
659
|
+
]);
|
|
536
660
|
|
|
537
661
|
// Null 占位组件(仿照 DefaultValue.tsx 的实现)
|
|
538
662
|
const NullComponent = useMemo(() => {
|
|
@@ -582,17 +706,19 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
582
706
|
const first = meta?.paths?.[0];
|
|
583
707
|
if (first === 'constant') return '';
|
|
584
708
|
if (first === 'null') return null;
|
|
585
|
-
return
|
|
709
|
+
return rightVariableConverters?.resolveValueFromPath?.(meta);
|
|
586
710
|
},
|
|
587
711
|
resolvePathFromValue: (val) => {
|
|
588
712
|
if (val === null) return ['null'];
|
|
589
|
-
//
|
|
590
|
-
const parsed =
|
|
713
|
+
// 变量表达式:优先使用领域转换器,再回退内置解析;其他静态值走 constant
|
|
714
|
+
const parsed =
|
|
715
|
+
rightVariableConverters?.resolvePathFromValue?.(val) ??
|
|
716
|
+
(typeof val === 'string' ? parseValueToPath(val) : undefined);
|
|
591
717
|
if (parsed) return parsed;
|
|
592
718
|
return ['constant'];
|
|
593
719
|
},
|
|
594
720
|
};
|
|
595
|
-
}, [NullComponent, staticInputRenderer]);
|
|
721
|
+
}, [NullComponent, rightVariableConverters, staticInputRenderer]);
|
|
596
722
|
|
|
597
723
|
// 为 2.0 左侧字段选择器追加“接口 filterable.children”定义(如 chinaRegion 的“省市区名称”子项),
|
|
598
724
|
// 以恢复 1.0 左侧子菜单的能力。
|
|
@@ -652,6 +778,34 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
652
778
|
};
|
|
653
779
|
}, [getFieldInterface, model, maxAssociationFieldDepth]);
|
|
654
780
|
|
|
781
|
+
useEffect(() => {
|
|
782
|
+
if (leftMeta || !value.path) {
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
let cancelled = false;
|
|
787
|
+
const restore = async () => {
|
|
788
|
+
const nodes = await enhancedMetaTree();
|
|
789
|
+
if (cancelled) {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
const path = customConverters.resolvePathFromValue(value.path);
|
|
793
|
+
if (!path?.length) {
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
const matched =
|
|
797
|
+
findMetaTreeNodeByPath(nodes, path) || buildCollectionFieldMetaNode(model.context.collection, path);
|
|
798
|
+
if (matched) {
|
|
799
|
+
setLeftMeta(matched);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
restore();
|
|
804
|
+
return () => {
|
|
805
|
+
cancelled = true;
|
|
806
|
+
};
|
|
807
|
+
}, [customConverters, enhancedMetaTree, leftMeta, model.context.collection, value.path]);
|
|
808
|
+
|
|
655
809
|
return (
|
|
656
810
|
<Space wrap style={{ width: '100%' }}>
|
|
657
811
|
<VariableInput
|
|
@@ -659,6 +813,7 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
659
813
|
metaTree={enhancedMetaTree}
|
|
660
814
|
onChange={handleLeftChange}
|
|
661
815
|
converters={customConverters}
|
|
816
|
+
disabled={disabled}
|
|
662
817
|
showValueComponent={false}
|
|
663
818
|
style={{ flex: '1 1 40%', minWidth: 160, maxWidth: '100%' }}
|
|
664
819
|
onlyLeafSelectable={true}
|
|
@@ -670,6 +825,7 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
670
825
|
style={{ flex: '0 0 140px', minWidth: 120, maxWidth: '100%' }}
|
|
671
826
|
placeholder={t('Comparison')}
|
|
672
827
|
value={operator || undefined}
|
|
828
|
+
disabled={disabled}
|
|
673
829
|
onChange={handleOperatorChange}
|
|
674
830
|
>
|
|
675
831
|
{operatorOptions.map((op) => (
|
|
@@ -686,6 +842,7 @@ export const VariableFilterItem: React.FC<VariableFilterItemProps> = observer(
|
|
|
686
842
|
onChange={(v) => setRightValue(v)}
|
|
687
843
|
metaTree={mergedRightMetaTree}
|
|
688
844
|
converters={rightConverters}
|
|
845
|
+
disabled={disabled}
|
|
689
846
|
showValueComponent
|
|
690
847
|
style={{ flex: '1 1 40%', minWidth: 160, maxWidth: '100%' }}
|
|
691
848
|
placeholder={t('Enter value')}
|
|
@@ -140,4 +140,49 @@ describe('FilterGroup closeIcon', () => {
|
|
|
140
140
|
expect(onChange).toHaveBeenCalledTimes(1);
|
|
141
141
|
expect(value.items[0].items).toHaveLength(1);
|
|
142
142
|
});
|
|
143
|
+
|
|
144
|
+
it('disables close and add actions when the filter group is disabled', () => {
|
|
145
|
+
const value = {
|
|
146
|
+
logic: '$and',
|
|
147
|
+
items: [
|
|
148
|
+
{
|
|
149
|
+
path: 'name',
|
|
150
|
+
operator: 'eq',
|
|
151
|
+
value: 'test',
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
const onRemove = vi.fn();
|
|
156
|
+
const onChange = vi.fn();
|
|
157
|
+
|
|
158
|
+
renderWithProviders(
|
|
159
|
+
<FilterGroup
|
|
160
|
+
value={value}
|
|
161
|
+
FilterItem={DummyFilterItem}
|
|
162
|
+
showBorder
|
|
163
|
+
onRemove={onRemove}
|
|
164
|
+
onChange={onChange}
|
|
165
|
+
disabled
|
|
166
|
+
/>,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const closeButtons = screen
|
|
170
|
+
.getAllByLabelText('icon-close')
|
|
171
|
+
.map((element) => element.closest('button'))
|
|
172
|
+
.filter(Boolean) as HTMLButtonElement[];
|
|
173
|
+
expect(closeButtons).toHaveLength(2);
|
|
174
|
+
expect(closeButtons[0]).toBeDisabled();
|
|
175
|
+
expect(closeButtons[1]).toBeDisabled();
|
|
176
|
+
expect(screen.getByText('Add condition').closest('button')).toBeDisabled();
|
|
177
|
+
expect(screen.getByText('Add condition group').closest('button')).toBeDisabled();
|
|
178
|
+
|
|
179
|
+
fireEvent.click(closeButtons[0]);
|
|
180
|
+
fireEvent.click(closeButtons[1]);
|
|
181
|
+
fireEvent.click(screen.getByText('Add condition').closest('button') as HTMLButtonElement);
|
|
182
|
+
fireEvent.click(screen.getByText('Add condition group').closest('button') as HTMLButtonElement);
|
|
183
|
+
|
|
184
|
+
expect(onRemove).not.toHaveBeenCalled();
|
|
185
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
186
|
+
expect(value.items).toHaveLength(1);
|
|
187
|
+
});
|
|
143
188
|
});
|
|
@@ -193,4 +193,13 @@ describe('VariableFilterItem with leftMetaTree', () => {
|
|
|
193
193
|
fireEvent.click(screen.getByTestId('variable-input'));
|
|
194
194
|
expect(value.path).toBe('title');
|
|
195
195
|
});
|
|
196
|
+
|
|
197
|
+
it('restores the saved left meta so the operator select shows its label on reopen', async () => {
|
|
198
|
+
const value = { path: 'title', operator: '$eq', value: 'x' } as any;
|
|
199
|
+
const model = createModelWithCollection();
|
|
200
|
+
|
|
201
|
+
render(<VariableFilterItem value={value} model={model} rightAsVariable={false} />);
|
|
202
|
+
|
|
203
|
+
expect(await screen.findByText('Equals')).toBeInTheDocument();
|
|
204
|
+
});
|
|
196
205
|
});
|