mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-02 20:27:49 +08:00
fix(filter-form): fix auto-trigger filter action without default value (#4627)
* test: add e2e test * test: add unit tests * fix(reset-button): prevent data clear when default values exist * fix: resolve known issues and add tests
This commit is contained in:
parent
5d48b3b5aa
commit
e6848858d4
@ -32,7 +32,7 @@ import {
|
|||||||
import { useAPIClient, useRequest } from '../../api-client';
|
import { useAPIClient, useRequest } from '../../api-client';
|
||||||
import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
|
import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
|
||||||
import { useCollectionManager_deprecated, useCollection_deprecated } from '../../collection-manager';
|
import { useCollectionManager_deprecated, useCollection_deprecated } from '../../collection-manager';
|
||||||
import { useFilterBlock } from '../../filter-provider/FilterProvider';
|
import { DataBlock, useFilterBlock } from '../../filter-provider/FilterProvider';
|
||||||
import { mergeFilter, transformToFilter } from '../../filter-provider/utils';
|
import { mergeFilter, transformToFilter } from '../../filter-provider/utils';
|
||||||
import { useTreeParentRecord } from '../../modules/blocks/data-blocks/table/TreeRecordProvider';
|
import { useTreeParentRecord } from '../../modules/blocks/data-blocks/table/TreeRecordProvider';
|
||||||
import { useRecord } from '../../record-provider';
|
import { useRecord } from '../../record-provider';
|
||||||
@ -430,6 +430,10 @@ const useDoFilter = () => {
|
|||||||
const { name } = useCollection();
|
const { name } = useCollection();
|
||||||
const { targets = [], uid } = useMemo(() => findFilterTargets(fieldSchema), [fieldSchema]);
|
const { targets = [], uid } = useMemo(() => findFilterTargets(fieldSchema), [fieldSchema]);
|
||||||
|
|
||||||
|
const getFilterFromCurrentForm = useCallback(() => {
|
||||||
|
return removeNullCondition(transformToFilter(form.values, getOperators(), getCollectionJoinField, name));
|
||||||
|
}, [form.values, getCollectionJoinField, getOperators, name]);
|
||||||
|
|
||||||
const doFilter = useCallback(
|
const doFilter = useCallback(
|
||||||
async ({ doNothingWhenFilterIsEmpty = false } = {}) => {
|
async ({ doNothingWhenFilterIsEmpty = false } = {}) => {
|
||||||
try {
|
try {
|
||||||
@ -443,20 +447,19 @@ const useDoFilter = () => {
|
|||||||
// 保留原有的 filter
|
// 保留原有的 filter
|
||||||
const storedFilter = block.service.params?.[1]?.filters || {};
|
const storedFilter = block.service.params?.[1]?.filters || {};
|
||||||
|
|
||||||
storedFilter[uid] = removeNullCondition(
|
// 由当前表单转换而来的 filter
|
||||||
transformToFilter(form.values, getOperators(), getCollectionJoinField, name),
|
storedFilter[uid] = getFilterFromCurrentForm();
|
||||||
);
|
|
||||||
|
|
||||||
const mergedFilter = mergeFilter([
|
const mergedFilter = mergeFilter([
|
||||||
...Object.values(storedFilter).map((filter) => removeNullCondition(filter)),
|
...Object.values(storedFilter).map((filter) => removeNullCondition(filter)),
|
||||||
block.defaultFilter,
|
block.defaultFilter,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (doNothingWhenFilterIsEmpty && _.isEmpty(mergedFilter)) {
|
if (doNothingWhenFilterIsEmpty && _.isEmpty(storedFilter[uid])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.dataLoadingMode === 'manual' && _.isEmpty(mergedFilter)) {
|
if (block.dataLoadingMode === 'manual' && _.isEmpty(storedFilter[uid])) {
|
||||||
return block.clearData();
|
return block.clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +477,7 @@ const useDoFilter = () => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[form.values, getCollectionJoinField, getDataBlocks, getOperators, name, targets, uid],
|
[getDataBlocks, getFilterFromCurrentForm, targets, uid],
|
||||||
);
|
);
|
||||||
|
|
||||||
// 这里的代码是为了实现:筛选表单的筛选操作在首次渲染时自动执行一次
|
// 这里的代码是为了实现:筛选表单的筛选操作在首次渲染时自动执行一次
|
||||||
@ -487,6 +490,10 @@ const useDoFilter = () => {
|
|||||||
* 用于执行筛选表单的筛选操作
|
* 用于执行筛选表单的筛选操作
|
||||||
*/
|
*/
|
||||||
doFilter,
|
doFilter,
|
||||||
|
/**
|
||||||
|
* 根据当前表单的值获取 filter
|
||||||
|
*/
|
||||||
|
getFilterFromCurrentForm,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -504,52 +511,35 @@ export const useFilterBlockActionProps = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useResetBlockActionProps = () => {
|
const useDoReset = () => {
|
||||||
const form = useForm();
|
const form = useForm();
|
||||||
const actionField = useField();
|
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const { getDataBlocks } = useFilterBlock();
|
const { getDataBlocks } = useFilterBlock();
|
||||||
|
const { targets, uid } = findFilterTargets(fieldSchema);
|
||||||
|
const { doFilter, getFilterFromCurrentForm } = useDoFilter();
|
||||||
|
|
||||||
|
return {
|
||||||
|
doReset: async () => {
|
||||||
|
await form.reset();
|
||||||
|
if (_.isEmpty(getFilterFromCurrentForm())) {
|
||||||
|
return doReset({ getDataBlocks, targets, uid });
|
||||||
|
}
|
||||||
|
await doFilter();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useResetBlockActionProps = () => {
|
||||||
|
const actionField = useField();
|
||||||
|
const { doReset } = useDoReset();
|
||||||
|
|
||||||
actionField.data = actionField.data || {};
|
actionField.data = actionField.data || {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async onClick() {
|
async onClick() {
|
||||||
const { targets, uid } = findFilterTargets(fieldSchema);
|
|
||||||
|
|
||||||
form.reset();
|
|
||||||
actionField.data.loading = true;
|
actionField.data.loading = true;
|
||||||
try {
|
await doReset();
|
||||||
// 收集 filter 的值
|
actionField.data.loading = false;
|
||||||
await Promise.all(
|
|
||||||
getDataBlocks().map(async (block) => {
|
|
||||||
const target = targets.find((target) => target.uid === block.uid);
|
|
||||||
if (!target) return;
|
|
||||||
|
|
||||||
if (block.dataLoadingMode === 'manual') {
|
|
||||||
return block.clearData();
|
|
||||||
}
|
|
||||||
|
|
||||||
const param = block.service.params?.[0] || {};
|
|
||||||
// 保留原有的 filter
|
|
||||||
const storedFilter = block.service.params?.[1]?.filters || {};
|
|
||||||
|
|
||||||
delete storedFilter[uid];
|
|
||||||
const mergedFilter = mergeFilter([...Object.values(storedFilter), block.defaultFilter]);
|
|
||||||
|
|
||||||
return block.doFilter(
|
|
||||||
{
|
|
||||||
...param,
|
|
||||||
page: 1,
|
|
||||||
filter: mergedFilter,
|
|
||||||
},
|
|
||||||
{ filters: storedFilter },
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
actionField.data.loading = false;
|
|
||||||
} catch (error) {
|
|
||||||
actionField.data.loading = false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -1347,6 +1337,52 @@ export const useAssociationFilterBlockProps = () => {
|
|||||||
labelKey,
|
labelKey,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
async function doReset({
|
||||||
|
getDataBlocks,
|
||||||
|
targets,
|
||||||
|
uid,
|
||||||
|
}: {
|
||||||
|
getDataBlocks: () => DataBlock[];
|
||||||
|
targets: {
|
||||||
|
/** field uid */
|
||||||
|
uid: string;
|
||||||
|
/** associated field */
|
||||||
|
field?: string;
|
||||||
|
}[];
|
||||||
|
uid: string;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
await Promise.all(
|
||||||
|
getDataBlocks().map(async (block) => {
|
||||||
|
const target = targets.find((target) => target.uid === block.uid);
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
|
if (block.dataLoadingMode === 'manual') {
|
||||||
|
return block.clearData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const param = block.service.params?.[0] || {};
|
||||||
|
// 保留原有的 filter
|
||||||
|
const storedFilter = block.service.params?.[1]?.filters || {};
|
||||||
|
|
||||||
|
delete storedFilter[uid];
|
||||||
|
const mergedFilter = mergeFilter([...Object.values(storedFilter), block.defaultFilter]);
|
||||||
|
|
||||||
|
return block.doFilter(
|
||||||
|
{
|
||||||
|
...param,
|
||||||
|
page: 1,
|
||||||
|
filter: mergedFilter,
|
||||||
|
},
|
||||||
|
{ filters: storedFilter },
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getAssociationPath(str) {
|
export function getAssociationPath(str) {
|
||||||
const lastIndex = str.lastIndexOf('.');
|
const lastIndex = str.lastIndexOf('.');
|
||||||
if (lastIndex !== -1) {
|
if (lastIndex !== -1) {
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CollectionFieldInterface,
|
|
||||||
isTitleField,
|
|
||||||
Application,
|
Application,
|
||||||
useDataSourceHeaders,
|
CollectionFieldInterface,
|
||||||
DEFAULT_DATA_SOURCE_KEY,
|
DEFAULT_DATA_SOURCE_KEY,
|
||||||
|
isTitleField,
|
||||||
|
useDataSourceHeaders,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import { renderHook } from '@nocobase/test/client';
|
import { renderHook } from '@nocobase/test/client';
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getSupportFieldsByAssociation, getSupportFieldsByForeignKey } from '../utils';
|
import { getSupportFieldsByAssociation, getSupportFieldsByForeignKey, transformToFilter } from '../utils';
|
||||||
|
|
||||||
describe('getSupportFieldsByAssociation', () => {
|
describe('getSupportFieldsByAssociation', () => {
|
||||||
it('should return all associated fields matching the inherited collections chain', () => {
|
it('should return all associated fields matching the inherited collections chain', () => {
|
||||||
@ -140,3 +140,80 @@ describe('getSupportFieldsByForeignKey', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('transformToFilter', () => {
|
||||||
|
const values = {
|
||||||
|
field1: 'value1',
|
||||||
|
field2: 'value2',
|
||||||
|
field3: [
|
||||||
|
{
|
||||||
|
id: 'value3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'value4',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const operators = {
|
||||||
|
field1: '$eq',
|
||||||
|
field2: '$ne',
|
||||||
|
field3: '$in',
|
||||||
|
};
|
||||||
|
|
||||||
|
const collectionName = 'collection';
|
||||||
|
|
||||||
|
const getCollectionJoinField = vi.fn((name: string) => {
|
||||||
|
if (name === `${collectionName}.field1`) return {};
|
||||||
|
if (name === `${collectionName}.field2`) return {};
|
||||||
|
if (name === `${collectionName}.field3`) return { target: 'targetCollection', targetKey: 'id' };
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should transform values to filter', () => {
|
||||||
|
const expectedFilter = {
|
||||||
|
$and: [
|
||||||
|
{
|
||||||
|
field1: {
|
||||||
|
$eq: 'value1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field2: {
|
||||||
|
$ne: 'value2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'field3.id': {
|
||||||
|
$eq: ['value3', 'value4'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const filter = transformToFilter(values, operators, getCollectionJoinField, collectionName);
|
||||||
|
|
||||||
|
expect(filter).toEqual(expectedFilter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle null values', () => {
|
||||||
|
const valuesWithNull = {
|
||||||
|
field1: null,
|
||||||
|
field2: 'value2',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedFilter = {
|
||||||
|
$and: [
|
||||||
|
{
|
||||||
|
field2: {
|
||||||
|
$ne: 'value2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const filter = transformToFilter(valuesWithNull, operators, getCollectionJoinField, collectionName);
|
||||||
|
|
||||||
|
expect(filter).toEqual(expectedFilter);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { expect, test } from '@nocobase/test/e2e';
|
import { expect, test } from '@nocobase/test/e2e';
|
||||||
import { tableListDetailsGridCardWithUsers } from './templatesOfBug';
|
import { TableBlockWithDataScope, tableListDetailsGridCardWithUsers } from './templatesOfBug';
|
||||||
|
|
||||||
test.describe('setDataLoadingModeSettingsItem', () => {
|
test.describe('setDataLoadingModeSettingsItem', () => {
|
||||||
test('basic', async ({ page, mockPage }) => {
|
test('basic', async ({ page, mockPage }) => {
|
||||||
@ -72,4 +72,30 @@ test.describe('setDataLoadingModeSettingsItem', () => {
|
|||||||
await expect(page.getByLabel('block-item-CardItem-users-list').getByText('No data')).toBeVisible();
|
await expect(page.getByLabel('block-item-CardItem-users-list').getByText('No data')).toBeVisible();
|
||||||
await expect(page.getByLabel('block-item-BlockItem-users-').getByText('No data')).toBeVisible();
|
await expect(page.getByLabel('block-item-BlockItem-users-').getByText('No data')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('When the data block has data scope settings and dataLoadingMode is manual, data should not be displayed after the first page load', async ({
|
||||||
|
page,
|
||||||
|
mockPage,
|
||||||
|
}) => {
|
||||||
|
await mockPage(TableBlockWithDataScope).goto();
|
||||||
|
await expect(page.getByLabel('block-item-CardItem-users-table').getByText('No data')).toBeVisible();
|
||||||
|
|
||||||
|
// 此时点击 filter 按钮,应该还是没数据,因为表单没有值
|
||||||
|
await page.getByLabel('action-Action-Filter-submit-').click({
|
||||||
|
position: {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await expect(page.getByLabel('block-item-CardItem-users-table').getByText('No data')).toBeVisible();
|
||||||
|
|
||||||
|
// 点击 Reset 按钮,也是一样
|
||||||
|
await page.getByLabel('action-Action-Reset-users-').click({
|
||||||
|
position: {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await expect(page.getByLabel('block-item-CardItem-users-table').getByText('No data')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1558,3 +1558,366 @@ export const detailsBlockWithLinkageRule = {
|
|||||||
'x-index': 1,
|
'x-index': 1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
export const TableBlockWithDataScope = {
|
||||||
|
pageSchema: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Page',
|
||||||
|
properties: {
|
||||||
|
an34615vknp: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': 'page:addBlock',
|
||||||
|
properties: {
|
||||||
|
'62fssedpl0w': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
'93tyrk65qym': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
'0b7maevxkfs': {
|
||||||
|
'x-uid': 'uqnziogzhkq',
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'FilterFormBlockProvider',
|
||||||
|
'x-use-decorator-props': 'useFilterFormBlockDecoratorProps',
|
||||||
|
'x-decorator-props': {
|
||||||
|
dataSource: 'main',
|
||||||
|
collection: 'users',
|
||||||
|
},
|
||||||
|
'x-toolbar': 'BlockSchemaToolbar',
|
||||||
|
'x-settings': 'blockSettings:filterForm',
|
||||||
|
'x-component': 'CardItem',
|
||||||
|
'x-filter-targets': [
|
||||||
|
{
|
||||||
|
uid: 'yg26txxpq4l',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
swmsovm7d4t: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'FormV2',
|
||||||
|
'x-use-component-props': 'useFilterFormBlockProps',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
grid: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': 'filterForm:configureFields',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
mzd4ludncd8: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
w67kg0y8wn6: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
nickname: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
'x-toolbar': 'FormItemSchemaToolbar',
|
||||||
|
'x-settings': 'fieldSettings:FilterFormItem',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-use-decorator-props': 'useFormItemProps',
|
||||||
|
'x-collection-field': 'users.nickname',
|
||||||
|
'x-component-props': {},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-uid': '3azj6wv3v2r',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '1jmg205s2sa',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'wjoskqiuk5b',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 't3gxqyl52ca',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
ceahs5hahgg: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-initializer': 'filterForm:configureActions',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
layout: 'one-column',
|
||||||
|
style: {
|
||||||
|
float: 'right',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
xgjhwz2ln8l: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
title: '{{ t("Filter") }}',
|
||||||
|
'x-action': 'submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-use-component-props': 'useFilterBlockActionProps',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
htmlType: 'submit',
|
||||||
|
},
|
||||||
|
'x-action-settings': {},
|
||||||
|
type: 'void',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-uid': 'ev40o2gk87b',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
qxhdilp319s: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
title: '{{ t("Reset") }}',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-use-component-props': 'useResetBlockActionProps',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-action-settings': {},
|
||||||
|
type: 'void',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-uid': '559bivcwabh',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '8q25gzurfeh',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'v3mwerc709f',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '952up9gdrhf',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'da58ptz1cie',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
dxd8oaoh4a7: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
'27ijajdwyd2': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
'7yz5da41nt3': {
|
||||||
|
'x-uid': 'yg26txxpq4l',
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableBlockProvider',
|
||||||
|
'x-acl-action': 'users:list',
|
||||||
|
'x-use-decorator-props': 'useTableBlockDecoratorProps',
|
||||||
|
'x-decorator-props': {
|
||||||
|
collection: 'users',
|
||||||
|
dataSource: 'main',
|
||||||
|
action: 'list',
|
||||||
|
params: {
|
||||||
|
pageSize: 20,
|
||||||
|
filter: {
|
||||||
|
$and: [
|
||||||
|
{
|
||||||
|
nickname: {
|
||||||
|
$includes: '{{$user.nickname}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowKey: 'id',
|
||||||
|
showIndex: true,
|
||||||
|
dragSort: false,
|
||||||
|
dataLoadingMode: 'manual',
|
||||||
|
},
|
||||||
|
'x-toolbar': 'BlockSchemaToolbar',
|
||||||
|
'x-settings': 'blockSettings:table',
|
||||||
|
'x-component': 'CardItem',
|
||||||
|
'x-filter-targets': [],
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-initializer': 'table:configureActions',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
style: {
|
||||||
|
marginBottom: 'var(--nb-spacing)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-uid': '73fy8oxxxk9',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
wo6mmz3gm4e: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'array',
|
||||||
|
'x-initializer': 'table:configureColumns',
|
||||||
|
'x-component': 'TableV2',
|
||||||
|
'x-use-component-props': 'useTableBlockProps',
|
||||||
|
'x-component-props': {
|
||||||
|
rowKey: 'id',
|
||||||
|
rowSelection: {
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
title: '{{ t("Actions") }}',
|
||||||
|
'x-action-column': 'actions',
|
||||||
|
'x-decorator': 'TableV2.Column.ActionBar',
|
||||||
|
'x-component': 'TableV2.Column',
|
||||||
|
'x-toolbar': 'TableColumnSchemaToolbar',
|
||||||
|
'x-initializer': 'table:configureItemActions',
|
||||||
|
'x-settings': 'fieldSettings:TableColumn',
|
||||||
|
'x-toolbar-props': {
|
||||||
|
initializer: 'table:configureItemActions',
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
k96lkyh071r: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'DndContext',
|
||||||
|
'x-component': 'Space',
|
||||||
|
'x-component-props': {
|
||||||
|
split: '|',
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-uid': 'e0u8ctx63xa',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'kscb8lws4pt',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
tpeettygzf9: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableV2.Column.Decorator',
|
||||||
|
'x-toolbar': 'TableColumnSchemaToolbar',
|
||||||
|
'x-settings': 'fieldSettings:TableColumn',
|
||||||
|
'x-component': 'TableV2.Column',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
properties: {
|
||||||
|
nickname: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
'x-collection-field': 'users.nickname',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-component-props': {
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
'x-read-pretty': true,
|
||||||
|
'x-decorator': null,
|
||||||
|
'x-decorator-props': {
|
||||||
|
labelStyle: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-uid': 'fyeg48brfk6',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '1zzxomha3yb',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'f8zia156lux',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'j9c5x3pl112',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'qkazgqmj5zk',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'iabe2fdu20i',
|
||||||
|
'x-async': false,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'dxf2yvxqvra',
|
||||||
|
'x-async': true,
|
||||||
|
'x-index': 1,
|
||||||
|
},
|
||||||
|
keepUid: true,
|
||||||
|
};
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { expect, test } from '@nocobase/test/e2e';
|
import { expect, test } from '@nocobase/test/e2e';
|
||||||
import { oneFilterFormAndTable } from './templates';
|
import { oneFilterFormAndTable, oneFilterFormAndTableWithManualLoadingData } from './templates';
|
||||||
|
|
||||||
test.describe('filter form', () => {
|
test.describe('filter form', () => {
|
||||||
test('When the filter form field is set with a default value, it should trigger a filtering action on the first page load', async ({
|
test('When the filter form field is set with a default value, it should trigger a filtering action on the first page load', async ({
|
||||||
@ -29,7 +29,65 @@ test.describe('filter form', () => {
|
|||||||
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
||||||
).not.toBeVisible();
|
).not.toBeVisible();
|
||||||
|
|
||||||
// 2. 点击重置按钮后,会显示出全部数据
|
// 2. 点击重置按钮后,数据不变
|
||||||
|
await page.getByLabel('action-Action-Reset-users-').click({
|
||||||
|
position: {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
|
// 3. 清空 nickname 的值后,点击筛选按钮,应该只显示出所有数据
|
||||||
|
await page.getByLabel('block-item-CollectionField-').getByRole('textbox').clear();
|
||||||
|
await page.getByLabel('action-Action-Filter-submit-').click({
|
||||||
|
position: {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
// 4. 此时点击 Reset 按钮,应该只显示一条数据,因为会把 nickname 的值重置为 {{$user.nickname}}
|
||||||
|
await page.getByLabel('action-Action-Reset-users-').click({
|
||||||
|
position: {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
||||||
|
).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('with dataLoadingMode is manual', async ({ page, mockPage, mockRecord }) => {
|
||||||
|
// nickname 字段的默认值是 {{$user.nickname}}
|
||||||
|
const nocoPage = await mockPage(oneFilterFormAndTableWithManualLoadingData).waitForInit();
|
||||||
|
await mockRecord('users', { nickname: 'test name' });
|
||||||
|
await nocoPage.goto();
|
||||||
|
|
||||||
|
// 1. 首次加载,应该已经触发过一次筛选的动作
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
|
// 2. 点击重置按钮后,数据不变
|
||||||
await page.getByLabel('action-Action-Reset-users-').click({
|
await page.getByLabel('action-Action-Reset-users-').click({
|
||||||
position: {
|
position: {
|
||||||
x: 10,
|
x: 10,
|
||||||
@ -41,20 +99,30 @@ test.describe('filter form', () => {
|
|||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
||||||
).toBeVisible();
|
).not.toBeVisible();
|
||||||
|
|
||||||
// 3. 再次点击筛选按钮,应该只显示出符合条件的数据
|
// 3. 清空 nickname 输入框,然后点击 Filter 按钮,应该显示空数据
|
||||||
|
await page.getByLabel('block-item-CollectionField-').getByRole('textbox').clear();
|
||||||
await page.getByLabel('action-Action-Filter-submit-').click({
|
await page.getByLabel('action-Action-Filter-submit-').click({
|
||||||
position: {
|
position: {
|
||||||
x: 10,
|
x: 10,
|
||||||
y: 10,
|
y: 10,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
await expect(page.getByLabel('block-item-CardItem-users-table').getByText('No data')).toBeVisible();
|
||||||
|
|
||||||
|
// 4. 此时点击 Reset 按钮,应该只显示一条数据,因为会把 nickname 的值重置为 {{$user.nickname}}
|
||||||
|
await page.getByLabel('action-Action-Reset-users-').click({
|
||||||
|
position: {
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
await expect(
|
await expect(
|
||||||
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'Super Admin' }),
|
||||||
).not.toBeVisible();
|
).toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
page.getByLabel('block-item-CardItem-users-table').getByRole('button', { name: 'test name' }),
|
||||||
).toBeVisible();
|
).not.toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -501,3 +501,367 @@ export const oneFilterFormAndTable = {
|
|||||||
},
|
},
|
||||||
keepUid: true,
|
keepUid: true,
|
||||||
};
|
};
|
||||||
|
export const oneFilterFormAndTableWithManualLoadingData = {
|
||||||
|
pageSchema: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Page',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
an34615vknp: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': 'page:addBlock',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
'62fssedpl0w': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
'93tyrk65qym': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
'0b7maevxkfs': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'FilterFormBlockProvider',
|
||||||
|
'x-use-decorator-props': 'useFilterFormBlockDecoratorProps',
|
||||||
|
'x-decorator-props': {
|
||||||
|
dataSource: 'main',
|
||||||
|
collection: 'users',
|
||||||
|
},
|
||||||
|
'x-toolbar': 'BlockSchemaToolbar',
|
||||||
|
'x-settings': 'blockSettings:filterForm',
|
||||||
|
'x-component': 'CardItem',
|
||||||
|
'x-filter-targets': [
|
||||||
|
{
|
||||||
|
uid: 'yg26txxpq4l',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
swmsovm7d4t: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'FormV2',
|
||||||
|
'x-use-component-props': 'useFilterFormBlockProps',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
grid: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': 'filterForm:configureFields',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
mzd4ludncd8: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
w67kg0y8wn6: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
nickname: {
|
||||||
|
'x-uid': '3azj6wv3v2r',
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
'x-toolbar': 'FormItemSchemaToolbar',
|
||||||
|
'x-settings': 'fieldSettings:FilterFormItem',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-use-decorator-props': 'useFormItemProps',
|
||||||
|
'x-collection-field': 'users.nickname',
|
||||||
|
'x-component-props': {},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
default: '{{$user.nickname}}',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '1jmg205s2sa',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'wjoskqiuk5b',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 't3gxqyl52ca',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
ceahs5hahgg: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-initializer': 'filterForm:configureActions',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
layout: 'one-column',
|
||||||
|
style: {
|
||||||
|
float: 'right',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 2,
|
||||||
|
properties: {
|
||||||
|
xgjhwz2ln8l: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
title: '{{ t("Filter") }}',
|
||||||
|
'x-action': 'submit',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-use-component-props': 'useFilterBlockActionProps',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
htmlType: 'submit',
|
||||||
|
},
|
||||||
|
'x-action-settings': {},
|
||||||
|
type: 'void',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
'x-uid': 'ev40o2gk87b',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
qxhdilp319s: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
title: '{{ t("Reset") }}',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-use-component-props': 'useResetBlockActionProps',
|
||||||
|
'x-designer': 'Action.Designer',
|
||||||
|
'x-action-settings': {},
|
||||||
|
type: 'void',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 2,
|
||||||
|
'x-uid': '559bivcwabh',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '8q25gzurfeh',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'v3mwerc709f',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'uqnziogzhkq',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '952up9gdrhf',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'da58ptz1cie',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
dxd8oaoh4a7: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 2,
|
||||||
|
properties: {
|
||||||
|
'27ijajdwyd2': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
'7yz5da41nt3': {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableBlockProvider',
|
||||||
|
'x-acl-action': 'users:list',
|
||||||
|
'x-use-decorator-props': 'useTableBlockDecoratorProps',
|
||||||
|
'x-decorator-props': {
|
||||||
|
collection: 'users',
|
||||||
|
dataSource: 'main',
|
||||||
|
action: 'list',
|
||||||
|
params: {
|
||||||
|
pageSize: 20,
|
||||||
|
filter: {
|
||||||
|
$and: [
|
||||||
|
{
|
||||||
|
nickname: {
|
||||||
|
$includes: '{{$user.nickname}}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowKey: 'id',
|
||||||
|
showIndex: true,
|
||||||
|
dragSort: false,
|
||||||
|
dataLoadingMode: 'manual',
|
||||||
|
},
|
||||||
|
'x-toolbar': 'BlockSchemaToolbar',
|
||||||
|
'x-settings': 'blockSettings:table',
|
||||||
|
'x-component': 'CardItem',
|
||||||
|
'x-filter-targets': [],
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-initializer': 'table:configureActions',
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
style: {
|
||||||
|
marginBottom: 'var(--nb-spacing)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
'x-uid': '73fy8oxxxk9',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
wo6mmz3gm4e: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'array',
|
||||||
|
'x-initializer': 'table:configureColumns',
|
||||||
|
'x-component': 'TableV2',
|
||||||
|
'x-use-component-props': 'useTableBlockProps',
|
||||||
|
'x-component-props': {
|
||||||
|
rowKey: 'id',
|
||||||
|
rowSelection: {
|
||||||
|
type: 'checkbox',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 2,
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
title: '{{ t("Actions") }}',
|
||||||
|
'x-action-column': 'actions',
|
||||||
|
'x-decorator': 'TableV2.Column.ActionBar',
|
||||||
|
'x-component': 'TableV2.Column',
|
||||||
|
'x-toolbar': 'TableColumnSchemaToolbar',
|
||||||
|
'x-initializer': 'table:configureItemActions',
|
||||||
|
'x-settings': 'fieldSettings:TableColumn',
|
||||||
|
'x-toolbar-props': {
|
||||||
|
initializer: 'table:configureItemActions',
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
properties: {
|
||||||
|
k96lkyh071r: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'DndContext',
|
||||||
|
'x-component': 'Space',
|
||||||
|
'x-component-props': {
|
||||||
|
split: '|',
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
'x-uid': 'e0u8ctx63xa',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'kscb8lws4pt',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
tpeettygzf9: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'TableV2.Column.Decorator',
|
||||||
|
'x-toolbar': 'TableColumnSchemaToolbar',
|
||||||
|
'x-settings': 'fieldSettings:TableColumn',
|
||||||
|
'x-component': 'TableV2.Column',
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 2,
|
||||||
|
properties: {
|
||||||
|
nickname: {
|
||||||
|
_isJSONSchemaObject: true,
|
||||||
|
version: '2.0',
|
||||||
|
'x-collection-field': 'users.nickname',
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-component-props': {
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
'x-read-pretty': true,
|
||||||
|
'x-decorator': null,
|
||||||
|
'x-decorator-props': {
|
||||||
|
labelStyle: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-app-version': '1.0.1-alpha.2',
|
||||||
|
'x-index': 1,
|
||||||
|
'x-uid': 'fyeg48brfk6',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': '1zzxomha3yb',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'f8zia156lux',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'yg26txxpq4l',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'j9c5x3pl112',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'qkazgqmj5zk',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'iabe2fdu20i',
|
||||||
|
'x-async': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-uid': 'dxf2yvxqvra',
|
||||||
|
'x-async': true,
|
||||||
|
},
|
||||||
|
keepUid: true,
|
||||||
|
};
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of the NocoBase (R) project.
|
||||||
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||||
|
* Authors: NocoBase Team.
|
||||||
|
*
|
||||||
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||||
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { removeNullCondition } from '../useFilterActionProps';
|
||||||
|
|
||||||
|
describe('removeNullCondition', () => {
|
||||||
|
it('should remove null conditions', () => {
|
||||||
|
const filter = {
|
||||||
|
field1: null,
|
||||||
|
field2: 'value2',
|
||||||
|
field3: null,
|
||||||
|
field4: 'value4',
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
field2: 'value2',
|
||||||
|
field4: 'value4',
|
||||||
|
};
|
||||||
|
const result = removeNullCondition(filter);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove undefined conditions', () => {
|
||||||
|
const filter = {
|
||||||
|
field1: undefined,
|
||||||
|
field2: 'value2',
|
||||||
|
field3: undefined,
|
||||||
|
field4: 'value4',
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
field2: 'value2',
|
||||||
|
field4: 'value4',
|
||||||
|
};
|
||||||
|
const result = removeNullCondition(filter);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty filter', () => {
|
||||||
|
const filter = {};
|
||||||
|
const expected = {};
|
||||||
|
const result = removeNullCondition(filter);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle nested filter', () => {
|
||||||
|
const filter = {
|
||||||
|
field1: null,
|
||||||
|
field2: 'value2',
|
||||||
|
field3: {
|
||||||
|
subfield1: null,
|
||||||
|
subfield2: 'value2',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
field2: 'value2',
|
||||||
|
field3: {
|
||||||
|
subfield2: 'value2',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const result = removeNullCondition(filter);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
@ -10,12 +10,12 @@
|
|||||||
import { Field } from '@formily/core';
|
import { Field } from '@formily/core';
|
||||||
import { useField, useFieldSchema } from '@formily/react';
|
import { useField, useFieldSchema } from '@formily/react';
|
||||||
import flat from 'flat';
|
import flat from 'flat';
|
||||||
|
import _ from 'lodash';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useBlockRequestContext } from '../../../block-provider';
|
import { useBlockRequestContext } from '../../../block-provider';
|
||||||
import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
|
import { useCollectionManager_deprecated, useCollection_deprecated } from '../../../collection-manager';
|
||||||
import { mergeFilter } from '../../../filter-provider/utils';
|
import { mergeFilter } from '../../../filter-provider/utils';
|
||||||
import { useDataLoadingMode } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
|
import { useDataLoadingMode } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
export const useGetFilterOptions = () => {
|
export const useGetFilterOptions = () => {
|
||||||
const { getCollectionFields } = useCollectionManager_deprecated();
|
const { getCollectionFields } = useCollectionManager_deprecated();
|
||||||
@ -157,8 +157,8 @@ const isEmpty = (obj) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeNullCondition = (filter) => {
|
export const removeNullCondition = (filter, customFlat = flat) => {
|
||||||
const items = flat(filter || {});
|
const items = customFlat(filter || {});
|
||||||
const values = {};
|
const values = {};
|
||||||
for (const key in items) {
|
for (const key in items) {
|
||||||
const value = items[key];
|
const value = items[key];
|
||||||
@ -166,7 +166,7 @@ export const removeNullCondition = (filter) => {
|
|||||||
values[key] = value;
|
values[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flat.unflatten(values);
|
return customFlat.unflatten(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFilterActionProps = () => {
|
export const useFilterActionProps = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user