mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 21:49:25 +08:00
fix(kanban): fix incorrect appends parameter issue (#5592)
* refactor(kanban): optimize get appends function * fix(kanban): fix incorrect appends parameter issue * chore: remove useless code
This commit is contained in:
parent
ee1dd2375f
commit
a6f16acf1c
@ -0,0 +1,248 @@
|
||||
/**
|
||||
* 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 { Schema } from '@formily/json-schema';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { getAppends } from '../../hooks/index';
|
||||
|
||||
describe('getAppends', () => {
|
||||
const mockGetCollectionJoinField = (name: string) => {
|
||||
const fields = {
|
||||
'users.profile': {
|
||||
type: 'hasOne',
|
||||
target: 'profiles',
|
||||
},
|
||||
'users.posts': {
|
||||
type: 'hasMany',
|
||||
target: 'posts',
|
||||
},
|
||||
'posts.author': {
|
||||
type: 'belongsTo',
|
||||
target: 'users',
|
||||
},
|
||||
'users.roles': {
|
||||
type: 'belongsToMany',
|
||||
target: 'roles',
|
||||
},
|
||||
'users.categories': {
|
||||
type: 'belongsToArray',
|
||||
target: 'categories',
|
||||
},
|
||||
};
|
||||
return fields[name];
|
||||
};
|
||||
|
||||
const mockGetCollection = (name: string) => {
|
||||
const collections = {
|
||||
categories: {
|
||||
template: 'tree',
|
||||
},
|
||||
users: {
|
||||
template: 'general',
|
||||
},
|
||||
};
|
||||
return collections[name];
|
||||
};
|
||||
|
||||
const createSchema = (properties) => {
|
||||
return new Schema({
|
||||
properties,
|
||||
});
|
||||
};
|
||||
|
||||
it('should handle basic association fields', () => {
|
||||
const schema = createSchema({
|
||||
profile: {
|
||||
'x-component': 'Input',
|
||||
'x-collection-field': 'users.profile',
|
||||
name: 'profile',
|
||||
},
|
||||
});
|
||||
|
||||
const updateAssociationValues = new Set<string>();
|
||||
const appends = new Set<string>();
|
||||
|
||||
getAppends({
|
||||
schema,
|
||||
prefix: '',
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField: mockGetCollectionJoinField,
|
||||
getCollection: mockGetCollection,
|
||||
dataSource: 'main',
|
||||
});
|
||||
|
||||
expect(Array.from(appends)).toEqual(['profile']);
|
||||
expect(Array.from(updateAssociationValues)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle tree collection fields', () => {
|
||||
const schema = createSchema({
|
||||
categories: {
|
||||
'x-component': 'Input',
|
||||
'x-collection-field': 'users.categories',
|
||||
name: 'categories',
|
||||
},
|
||||
});
|
||||
|
||||
const updateAssociationValues = new Set<string>();
|
||||
const appends = new Set<string>();
|
||||
|
||||
getAppends({
|
||||
schema,
|
||||
prefix: '',
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField: mockGetCollectionJoinField,
|
||||
getCollection: mockGetCollection,
|
||||
dataSource: 'main',
|
||||
});
|
||||
|
||||
expect(Array.from(appends)).toEqual(['categories', 'categories.parent(recursively=true)']);
|
||||
});
|
||||
|
||||
it('should handle nested fields with sorting', () => {
|
||||
const schema = createSchema({
|
||||
posts: {
|
||||
'x-component': 'Input',
|
||||
'x-collection-field': 'users.posts',
|
||||
'x-component-props': {
|
||||
sortArr: 'createdAt',
|
||||
},
|
||||
name: 'posts',
|
||||
},
|
||||
});
|
||||
|
||||
const updateAssociationValues = new Set<string>();
|
||||
const appends = new Set<string>();
|
||||
|
||||
getAppends({
|
||||
schema,
|
||||
prefix: '',
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField: mockGetCollectionJoinField,
|
||||
getCollection: mockGetCollection,
|
||||
dataSource: 'main',
|
||||
});
|
||||
|
||||
expect(Array.from(appends)).toEqual(['posts(sort=createdAt)']);
|
||||
});
|
||||
|
||||
it('should handle nested SubTable mode', () => {
|
||||
const schema = createSchema({
|
||||
posts: {
|
||||
'x-component': 'Input',
|
||||
'x-collection-field': 'users.posts',
|
||||
'x-component-props': {
|
||||
mode: 'SubTable',
|
||||
},
|
||||
name: 'posts',
|
||||
properties: {
|
||||
author: {
|
||||
'x-component': 'Input',
|
||||
'x-collection-field': 'posts.author',
|
||||
name: 'author',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const updateAssociationValues = new Set<string>();
|
||||
const appends = new Set<string>();
|
||||
|
||||
getAppends({
|
||||
schema,
|
||||
prefix: '',
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField: mockGetCollectionJoinField,
|
||||
getCollection: mockGetCollection,
|
||||
dataSource: 'main',
|
||||
});
|
||||
|
||||
expect(Array.from(appends)).toEqual(['posts', 'posts.author']);
|
||||
expect(Array.from(updateAssociationValues)).toEqual(['posts']);
|
||||
});
|
||||
|
||||
it('should ignore TableField components', () => {
|
||||
const schema = createSchema({
|
||||
posts: {
|
||||
'x-component': 'TableField',
|
||||
'x-collection-field': 'users.posts',
|
||||
name: 'posts',
|
||||
},
|
||||
});
|
||||
|
||||
const updateAssociationValues = new Set<string>();
|
||||
const appends = new Set<string>();
|
||||
|
||||
getAppends({
|
||||
schema,
|
||||
prefix: '',
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField: mockGetCollectionJoinField,
|
||||
getCollection: mockGetCollection,
|
||||
dataSource: 'main',
|
||||
});
|
||||
|
||||
expect(Array.from(appends)).toEqual([]);
|
||||
expect(Array.from(updateAssociationValues)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should ignore Kanban.CardViewer components', () => {
|
||||
const schema = createSchema({
|
||||
cardViewer: {
|
||||
'x-component': 'Kanban.CardViewer',
|
||||
name: 'cardViewer',
|
||||
properties: {
|
||||
drawer: {
|
||||
name: 'drawer',
|
||||
type: 'void',
|
||||
properties: {
|
||||
grid: {
|
||||
name: 'grid',
|
||||
type: 'void',
|
||||
properties: {
|
||||
field1: {
|
||||
'x-component': 'Input',
|
||||
'x-collection-field': 'users.posts',
|
||||
name: 'field1',
|
||||
},
|
||||
field2: {
|
||||
'x-component': 'Input',
|
||||
'x-collection-field': 'posts.author',
|
||||
name: 'field2',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const updateAssociationValues = new Set<string>();
|
||||
const appends = new Set<string>();
|
||||
|
||||
getAppends({
|
||||
schema,
|
||||
prefix: '',
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField: mockGetCollectionJoinField,
|
||||
getCollection: mockGetCollection,
|
||||
dataSource: 'main',
|
||||
});
|
||||
|
||||
expect(Array.from(appends)).toEqual([]);
|
||||
expect(Array.from(updateAssociationValues)).toEqual([]);
|
||||
});
|
||||
});
|
@ -35,7 +35,7 @@ import {
|
||||
import { useAPIClient, useRequest } from '../../api-client';
|
||||
import { useNavigateNoUpdate } from '../../application/CustomRouterContextProvider';
|
||||
import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
|
||||
import { useCollectionManager_deprecated, useCollection_deprecated } from '../../collection-manager';
|
||||
import { CollectionOptions, useCollectionManager_deprecated, useCollection_deprecated } from '../../collection-manager';
|
||||
import { DataBlock, useFilterBlock } from '../../filter-provider/FilterProvider';
|
||||
import { mergeFilter, transformToFilter } from '../../filter-provider/utils';
|
||||
import { useTreeParentRecord } from '../../modules/blocks/data-blocks/table/TreeRecordProvider';
|
||||
@ -1494,14 +1494,25 @@ export function getAssociationPath(str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
export const useAssociationNames = (dataSource?: string) => {
|
||||
let updateAssociationValues = new Set([]);
|
||||
let appends = new Set([]);
|
||||
const { getCollectionJoinField, getCollection } = useCollectionManager_deprecated(dataSource);
|
||||
const fieldSchema = useFieldSchema();
|
||||
const _getAssociationAppends = (schema, str) => {
|
||||
export const getAppends = ({
|
||||
schema,
|
||||
prefix: defaultPrefix,
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField,
|
||||
getCollection,
|
||||
dataSource,
|
||||
}: {
|
||||
schema: any;
|
||||
prefix: string;
|
||||
updateAssociationValues: Set<string>;
|
||||
appends: Set<string>;
|
||||
getCollectionJoinField: (name: string, dataSource: string) => any;
|
||||
getCollection: (name: any, customDataSource?: string) => CollectionOptions;
|
||||
dataSource: string;
|
||||
}) => {
|
||||
schema.reduceProperties((pre, s) => {
|
||||
const prefix = pre || str;
|
||||
const prefix = pre || defaultPrefix;
|
||||
const collectionField = s['x-collection-field'] && getCollectionJoinField(s['x-collection-field'], dataSource);
|
||||
const isAssociationSubfield = s.name.includes('.');
|
||||
const isAssociationField =
|
||||
@ -1534,8 +1545,10 @@ export const useAssociationNames = (dataSource?: string) => {
|
||||
collectAppends(condition);
|
||||
});
|
||||
}
|
||||
|
||||
const isTreeCollection =
|
||||
isAssociationField && getCollection(collectionField.target, dataSource)?.template === 'tree';
|
||||
|
||||
if (collectionField && (isAssociationField || isAssociationSubfield) && s['x-component'] !== 'TableField') {
|
||||
const fieldPath = !isAssociationField && isAssociationSubfield ? getAssociationPath(s.name) : s.name;
|
||||
const path = prefix === '' || !prefix ? fieldPath : prefix + '.' + fieldPath;
|
||||
@ -1550,10 +1563,18 @@ export const useAssociationNames = (dataSource?: string) => {
|
||||
appends.add(path);
|
||||
}
|
||||
}
|
||||
if (['Nester', 'SubTable', 'PopoverNester'].includes(s['x-component-props']?.mode)) {
|
||||
if (isSubMode(s)) {
|
||||
updateAssociationValues.add(path);
|
||||
const bufPrefix = prefix && prefix !== '' ? prefix + '.' + s.name : s.name;
|
||||
_getAssociationAppends(s, bufPrefix);
|
||||
getAppends({
|
||||
schema: s,
|
||||
prefix: bufPrefix,
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField,
|
||||
getCollection,
|
||||
dataSource,
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
![
|
||||
@ -1567,17 +1588,43 @@ export const useAssociationNames = (dataSource?: string) => {
|
||||
'AssociationField.Selector',
|
||||
'AssociationField.AddNewer',
|
||||
'TableField',
|
||||
'Kanban.CardViewer',
|
||||
].includes(s['x-component'])
|
||||
) {
|
||||
_getAssociationAppends(s, str);
|
||||
getAppends({
|
||||
schema: s,
|
||||
prefix: defaultPrefix,
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField,
|
||||
getCollection,
|
||||
dataSource,
|
||||
});
|
||||
}
|
||||
}, str);
|
||||
};
|
||||
}, defaultPrefix);
|
||||
};
|
||||
|
||||
export const useAssociationNames = (dataSource?: string) => {
|
||||
const { getCollectionJoinField, getCollection } = useCollectionManager_deprecated(dataSource);
|
||||
const fieldSchema = useFieldSchema();
|
||||
|
||||
const getAssociationAppends = () => {
|
||||
updateAssociationValues = new Set([]);
|
||||
appends = new Set([]);
|
||||
_getAssociationAppends(fieldSchema, '');
|
||||
const updateAssociationValues = new Set([]);
|
||||
let appends = new Set([]);
|
||||
|
||||
getAppends({
|
||||
schema: fieldSchema,
|
||||
prefix: '',
|
||||
updateAssociationValues,
|
||||
appends,
|
||||
getCollectionJoinField,
|
||||
getCollection,
|
||||
dataSource,
|
||||
});
|
||||
appends = fillParentFields(appends);
|
||||
|
||||
console.log('appends', appends);
|
||||
|
||||
return { appends: [...appends], updateAssociationValues: [...updateAssociationValues] };
|
||||
};
|
||||
|
||||
|
@ -10,17 +10,17 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { FormLayout } from '@formily/antd-v5';
|
||||
import { createForm } from '@formily/core';
|
||||
import { observer, RecursionField, useFieldSchema } from '@formily/react';
|
||||
import { RecursionField, useFieldSchema } from '@formily/react';
|
||||
import {
|
||||
DndContext,
|
||||
FormProvider,
|
||||
getCardItemSchema,
|
||||
PopupContextProvider,
|
||||
useCollection,
|
||||
useCollectionRecordData,
|
||||
usePopupSettings,
|
||||
usePopupUtils,
|
||||
VariablePopupRecordProvider,
|
||||
getCardItemSchema,
|
||||
} from '@nocobase/client';
|
||||
import { Schema } from '@nocobase/utils';
|
||||
import { Card } from 'antd';
|
||||
@ -68,8 +68,7 @@ const cardCss = css`
|
||||
const MemorizedRecursionField = React.memo(RecursionField);
|
||||
MemorizedRecursionField.displayName = 'MemorizedRecursionField';
|
||||
|
||||
export const KanbanCard: any = observer(
|
||||
() => {
|
||||
export const KanbanCard: any = () => {
|
||||
const collection = useCollection();
|
||||
const { setDisableCardDrag } = useContext(KanbanCardContext) || {};
|
||||
const fieldSchema = useFieldSchema();
|
||||
@ -157,9 +156,7 @@ export const KanbanCard: any = observer(
|
||||
</PopupContextProvider>
|
||||
</>
|
||||
);
|
||||
},
|
||||
{ displayName: 'KanbanCard' },
|
||||
);
|
||||
};
|
||||
|
||||
function getPopupSchemaFromParent(fieldSchema: Schema) {
|
||||
if (fieldSchema.parent?.properties?.cardViewer?.properties?.drawer) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user