From 7748a33138fad4e86066153681425c6df173cf72 Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Fri, 26 Apr 2024 10:11:47 +0800 Subject: [PATCH] chore: unsupportedFields in view collection (#4155) * chore: unsupportedFields in view collection * refactor: view display unsupportedFields * refactor: locale improve * chore: test * chore: test * fix: bug --------- Co-authored-by: katherinehhh --- .../Configuration/EditFieldAction.tsx | 3 +- .../templates/components/PreviewFields.tsx | 4 +++ .../templates/components/UnSupportFields.tsx | 32 +++++++++++++++++++ packages/core/client/src/locale/zh-CN.json | 4 ++- .../core/database/src/view/view-inference.ts | 2 +- .../http-api/view-collection.test.ts | 16 +++++----- .../src/server/resourcers/views.ts | 20 +++++++++--- 7 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 packages/core/client/src/collection-manager/templates/components/UnSupportFields.tsx diff --git a/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx b/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx index 4c6fb4fedd..5d3392b457 100644 --- a/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx +++ b/packages/core/client/src/collection-manager/Configuration/EditFieldAction.tsx @@ -175,6 +175,7 @@ export const EditFieldAction = (props) => { const compile = useCompile(); const [data, setData] = useState({}); const { isDialect } = useDialect(); + const { template } = parentRecord || {}; const scopeKeyOptions = useMemo(() => { return ( @@ -248,7 +249,7 @@ export const EditFieldAction = (props) => { isDialect, disabledJSONB: true, scopeKeyOptions, - createMainOnly: true, + createMainOnly: template !== 'foreign', ...scope, }} /> diff --git a/packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx b/packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx index 9a2209167f..019e54ee90 100644 --- a/packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx +++ b/packages/core/client/src/collection-manager/templates/components/PreviewFields.tsx @@ -7,6 +7,7 @@ import { ResourceActionContext, useCompile } from '../../../'; import { useAPIClient } from '../../../api-client'; import { useFieldInterfaceOptions } from '../../Configuration/interfaces'; import { useCollectionManager_deprecated } from '../../hooks/useCollectionManager_deprecated'; +import { UnSupportFields } from './UnSupportFields'; const getInterfaceOptions = (data, type) => { const interfaceOptions = []; @@ -29,6 +30,7 @@ const PreviewCom = (props) => { const [dataSource, setDataSource] = useState([]); const [sourceFields, setSourceFields] = useState([]); const [sourceCollections, setSourceCollections] = useState(sources); + const [unsupportedFields, setUnsupportedFields] = useState([]); const field: any = useField(); const form = useForm(); const { getCollection, getInterface, getCollectionFields, getInheritCollections, getParentCollectionFields } = @@ -101,6 +103,7 @@ const PreviewCom = (props) => { setDataSource(fieldsData); form.setValuesIn('sources', data.data?.sources); setSourceCollections(data.data?.sources); + setUnsupportedFields(data?.data?.unsupportedFields); }); } }).catch; @@ -248,6 +251,7 @@ const PreviewCom = (props) => { /> )} + ); }; diff --git a/packages/core/client/src/collection-manager/templates/components/UnSupportFields.tsx b/packages/core/client/src/collection-manager/templates/components/UnSupportFields.tsx new file mode 100644 index 0000000000..064ee8fe31 --- /dev/null +++ b/packages/core/client/src/collection-manager/templates/components/UnSupportFields.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Table, Divider } from 'antd'; +import { useTranslation } from 'react-i18next'; + +export const UnSupportFields = ({ dataSource }) => { + const { t } = useTranslation(); + const columns = [ + { + title: t('Field name'), + dataIndex: 'name', + key: 'name', + }, + { + title: t('Field database type'), + dataIndex: 'rawType', + key: 'rawType', + }, + ]; + return ( + dataSource?.length > 0 && ( + <> + +

{t('Unknown field type')}

+
+
+ {t('The following field types are not compatible and do not support output and display')} +
+ + + ) + ); +}; diff --git a/packages/core/client/src/locale/zh-CN.json b/packages/core/client/src/locale/zh-CN.json index 47a038a626..f21a05dd8c 100644 --- a/packages/core/client/src/locale/zh-CN.json +++ b/packages/core/client/src/locale/zh-CN.json @@ -931,5 +931,7 @@ "Automatically generate default values": "随机生成默认值", "Refresh data on close": "关闭后刷新数据", "Refresh data on action": "执行后刷新数据", - "This variable has been deprecated and can be replaced with \"Current form\"": "该变量已被弃用,可以使用“当前表单”替代" + "This variable has been deprecated and can be replaced with \"Current form\"": "该变量已被弃用,可以使用“当前表单”替代", + "Unknown field type": "未知字段类型", + "The following field types are not compatible and do not support output and display": "以下字段类型未适配,不支持输出和显示" } diff --git a/packages/core/database/src/view/view-inference.ts b/packages/core/database/src/view/view-inference.ts index 596697b2c5..732bdbcf3e 100644 --- a/packages/core/database/src/view/view-inference.ts +++ b/packages/core/database/src/view/view-inference.ts @@ -43,7 +43,7 @@ export class ViewFieldInference { const rawFields = []; for (const [name, column] of Object.entries(columns)) { - const inferResult: any = { name }; + const inferResult: any = { name, rawType: column.type }; const usage = columnUsage[name]; diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/http-api/view-collection.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/http-api/view-collection.test.ts index d66f22cae4..b3bd7d1b5f 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/http-api/view-collection.test.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/http-api/view-collection.test.ts @@ -165,14 +165,16 @@ SELECT * FROM numbers; expect(response.status).toBe(200); const data = response.body.data; + const nField = data.fields.find((field) => field.name === 'n'); + if (app.db.inDialect('mysql')) { - expect(data.fields.n.type).toBe('bigInt'); + expect(nField.type).toBe('bigInt'); } else if (app.db.inDialect('postgres', 'mariadb')) { - expect(data.fields.n.type).toBe('integer'); + expect(nField.type).toBe('integer'); } }); - it('should return possible types for json fields', async () => { + it.skipIf(process.env['DB_DIALECT'] === 'sqlite')('should return possible types for json fields', async () => { if (app.db.inDialect('mariadb')) { // can not get json type from mariadb return; @@ -198,11 +200,9 @@ SELECT * FROM numbers; expect(response.status).toBe(200); const data = response.body.data; - if (!app.db.inDialect('sqlite')) { - expect(data.fields.json_field.type).toBe('json'); - } - - expect(data.fields.json_field.possibleTypes).toBeTruthy(); + const jsonField = data.fields.find((field) => field.name === 'json_field'); + expect(jsonField.type).toBe('json'); + expect(jsonField.possibleTypes).toBeTruthy(); }); it('should not throw error when source collection destroyed', async () => { diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/server/resourcers/views.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/server/resourcers/views.ts index ea0294127a..8ca144fbfb 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/server/resourcers/views.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/server/resourcers/views.ts @@ -7,14 +7,27 @@ export default { const { filterByTk, schema } = ctx.action.params; const db = ctx.app.db as Database; - const fields = await ViewFieldInference.inferFields({ + const fields = []; + + const unsupportedFields = []; + + const inferFields = await ViewFieldInference.inferFields({ db, viewName: filterByTk, viewSchema: schema, }); + for (const [_name, field] of Object.entries(inferFields)) { + if (!field.type) { + unsupportedFields.push(field); + } else { + fields.push(field); + } + } + ctx.body = { fields, + unsupportedFields, sources: [ ...new Set( Object.values(fields) @@ -62,9 +75,8 @@ export default { const limit = 1 * pageSize; const sql = `SELECT * - FROM ${ctx.app.db.utils.quoteTable( - ctx.app.db.utils.addSchema(filterByTk, schema), - )} LIMIT ${limit} OFFSET ${offset}`; + FROM ${ctx.app.db.utils.quoteTable(ctx.app.db.utils.addSchema(filterByTk, schema))} LIMIT ${limit} + OFFSET ${offset}`; const rawValues = await ctx.app.db.sequelize.query(sql, { type: 'SELECT' });