From 165841540257cd03a14a703b75f83e3274c3e27e Mon Sep 17 00:00:00 2001 From: katherinehhh Date: Fri, 12 Apr 2024 17:57:38 +0800 Subject: [PATCH] fix(collection-manager): no refresh after override the field (#4022) * refactor: code improve * fix: bug --- .../OverridingCollectionField.tsx | 77 ++--- .../Configuration/CollectionFields.tsx | 150 +++++----- .../Configuration/CollectionFieldsTable.tsx | 72 ----- .../CollectionFieldsTableArray.tsx | 283 ------------------ .../Configuration/ConfigurationTable.tsx | 3 +- .../Configuration/index.tsx | 1 - .../Configuration/schemas/collectionFields.ts | 212 ------------- 7 files changed, 122 insertions(+), 676 deletions(-) delete mode 100644 packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTable.tsx delete mode 100644 packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTableArray.tsx diff --git a/packages/core/client/src/collection-manager/Configuration/OverridingCollectionField.tsx b/packages/core/client/src/collection-manager/Configuration/OverridingCollectionField.tsx index 709e05ec60..c62784c9de 100644 --- a/packages/core/client/src/collection-manager/Configuration/OverridingCollectionField.tsx +++ b/packages/core/client/src/collection-manager/Configuration/OverridingCollectionField.tsx @@ -89,39 +89,6 @@ const getSchema = (schema: IField, record: any, compile, getContainer): ISchema }; }; -const useOverridingCollectionField = () => { - const form = useForm(); - const { refreshCM } = useCollectionManager_deprecated(); - const ctx = useActionContext(); - const { refresh } = useResourceActionContext(); - const { resource } = useResourceContext(); - return { - async run() { - await form.submit(); - const values = cloneDeep(form.values); - const data = omit(values, [ - 'key', - 'uiSchemaUid', - 'collectionName', - 'autoCreateReverseField', - 'uiSchema.x-uid', - 'reverseField', - 'reverseKey', - 'parentKey', - // 'reverseField.key', - // 'reverseField.uiSchemaUid', - ]); - await resource.create({ - values: data, - }); - ctx.setVisible(false); - await form.reset(); - refresh(); - await refreshCM(); - }, - }; -}; - export const OverridingCollectionField = (props) => { const record = useRecord(); const parentRecordData = useCollectionParentRecordData(); @@ -135,7 +102,15 @@ const getIsOverriding = (currentFields, record) => { return flag; }; export const OverridingFieldAction = (props) => { - const { scope, getContainer, item: record, parentItem: parentRecord, children, currentCollection } = props; + const { + scope, + getContainer, + item: record, + parentItem: parentRecord, + children, + currentCollection, + handleRefresh, + } = props; const { target, through } = record; const { getInterface, getCurrentCollectionFields, getChildrenCollections, collections } = useCollectionManager_deprecated(); @@ -163,6 +138,39 @@ export const OverridingFieldAction = (props) => { }; }); }, []); + const useOverridingCollectionField = () => { + const form = useForm(); + const { refresh } = useResourceActionContext(); + const { refreshCM } = useCollectionManager_deprecated(); + const ctx = useActionContext(); + const { resource } = useResourceContext(); + return { + async run() { + await form.submit(); + const values = cloneDeep(form.values); + const data = omit(values, [ + 'key', + 'uiSchemaUid', + 'collectionName', + 'autoCreateReverseField', + 'uiSchema.x-uid', + 'reverseField', + 'reverseKey', + 'parentKey', + // 'reverseField.key', + // 'reverseField.uiSchemaUid', + ]); + await resource.create({ + values: data, + }); + await form.reset(); + await refreshCM(); + await refresh(); + handleRefresh?.(); + ctx.setVisible(false); + }, + }; + }; return ( @@ -213,7 +221,6 @@ export const OverridingFieldAction = (props) => { isOverride: true, targetScope: { target: getFilterCollections(target), through: getFilterCollections(through) }, collections: currentCollections, - ...scope, }} /> diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFields.tsx b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFields.tsx index ae0ccc8c0a..3319b91b91 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFields.tsx +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFields.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import { createForm, Field } from '@formily/core'; import { FieldContext, FormContext, useField } from '@formily/react'; import { Space, Switch, Table, TableColumnProps, Tag, Tooltip } from 'antd'; -import React, { useContext, useMemo } from 'react'; +import React, { useContext, useMemo, createContext, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Action, @@ -30,7 +30,24 @@ import { } from '@nocobase/client'; import { collection } from './schemas/collectionFields'; - +const resourceActionProps = { + association: { + sourceKey: 'name', + targetKey: 'name', + }, + collection, + request: { + resource: 'collections.fields', + action: 'list', + params: { + paginate: false, + filter: { + $or: [{ 'interface.$not': null }, { 'options.source.$notEmpty': true }], + }, + sort: ['sort'], + }, + }, +}; const indentStyle = css` .ant-table { margin-left: -16px !important; @@ -60,6 +77,7 @@ const tableContainer = css` `; const titlePrompt = 'Default title for each record'; +const RefreshContext = createContext(null); const CurrentFields = (props) => { const compile = useCompile(); @@ -238,9 +256,11 @@ const InheritFields = (props) => { dataIndex: 'actions', title: t('Actions'), render: function Render(_, record) { + const { handleRefresh } = useContext(RefreshContext); const overrideProps = { type: 'primary', currentCollection: name, + handleRefresh, }; const viewCollectionProps = { type: 'primary', @@ -383,25 +403,6 @@ export const CollectionFields = () => { .filter(Boolean), ); - const resourceActionProps = { - association: { - sourceKey: 'name', - targetKey: 'name', - }, - collection, - request: { - resource: 'collections.fields', - action: 'list', - params: { - paginate: false, - filter: { - $or: [{ 'interface.$not': null }, { 'options.source.$notEmpty': true }], - }, - sort: ['sort'], - }, - }, - }; - const deleteProps = useMemo( () => ({ useAction: useBulkDestroyActionAndRefreshCM, @@ -417,58 +418,65 @@ export const CollectionFields = () => { ); const addProps = { type: 'primary', database }; const syncProps = { type: 'primary' }; + const [refresh, setRefresh] = useState(false); + + const handleRefresh = () => { + setRefresh(!refresh); + }; return ( - - - - - - - - + + + + + + + + + + + d.fields.length)} + pagination={false} + className={tableContainer} + expandable={{ + defaultExpandAllRows: true, + defaultExpandedRowKeys: dataSource.map((d) => d.key), + expandedRowRender: (record) => + record.inherit ? ( + + ) : ( + + ), }} /> - - -
d.fields.length)} - pagination={false} - className={tableContainer} - expandable={{ - defaultExpandAllRows: true, - defaultExpandedRowKeys: dataSource.map((d) => d.key), - expandedRowRender: (record) => - record.inherit ? ( - - ) : ( - - ), - }} - /> - - - + + + + ); }; diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTable.tsx b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTable.tsx deleted file mode 100644 index c78d3a4357..0000000000 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTable.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { createForm, Field } from '@formily/core'; -import { FieldContext, FormContext, observer, useField, useFieldSchema } from '@formily/react'; -import { useAttach } from '@formily/react/esm/hooks/useAttach'; -import { Options, Result } from 'ahooks/es/useRequest/src/types'; -import { TableProps } from 'antd'; -import React, { useMemo } from 'react'; -import { AsyncDataProvider, useAsyncData, useRequest } from '@nocobase/client'; -import { CollectionFieldsTableArray } from './CollectionFieldsTableArray'; - -type TableVoidProps = TableProps & { - request?: any; - useSelectedRowKeys?: any; - useDataSource?: ( - options?: Options & { uid?: string }, - props?: any, - ) => Result & { state?: any; setState?: any }; -}; - -const useDefSelectedRowKeys = () => { - const result = useAsyncData(); - return [result?.state?.selectedRowKeys, (selectedRowKeys) => result?.setState?.({ selectedRowKeys })]; -}; -const useDef = (options, props) => { - const { request, dataSource } = props; - const result = useRequest(request(props), { ...options, manual: true }); - - if (request) { - result.run(); - return result; - } else { - return Promise.resolve({ - data: dataSource, - }); - } -}; - -export const CollectionFieldsTable: React.FC = observer( - (props) => { - const { rowKey = 'id', useDataSource = useDef, useSelectedRowKeys = useDefSelectedRowKeys } = props; - const field = useField(); - const fieldSchema = useFieldSchema(); - const form = useMemo(() => createForm(), []); - const f = useAttach(form.createArrayField({ ...field.props, basePath: '' })); - const result = useDataSource( - { - uid: fieldSchema['x-uid'], - onSuccess(data) { - form.setValues({ - [fieldSchema.name]: data?.data, - }); - }, - }, - props, - ); - return ( - - - - - - - - ); - }, - { displayName: 'CollectionFieldsTable' }, -); diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTableArray.tsx b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTableArray.tsx deleted file mode 100644 index b16eea40bc..0000000000 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/CollectionFieldsTableArray.tsx +++ /dev/null @@ -1,283 +0,0 @@ -import { css } from '@emotion/css'; -import { ArrayField, Field } from '@formily/core'; -import { RecursionField, Schema, observer, useField, useFieldSchema } from '@formily/react'; -import { - RecordIndexProvider, - RecordProvider, - SchemaComponent, - useCollectionManager_deprecated, - useCompile, - useRecord, - useRequest, - useSchemaInitializerRender, -} from '@nocobase/client'; -import { Table, TableColumnProps } from 'antd'; -import { default as classNames } from 'classnames'; -import { findIndex } from 'lodash'; -import React, { useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { overridingSchema } from '../Configuration/schemas/collectionFields'; - -const isColumnComponent = (schema: Schema) => { - return schema['x-component']?.endsWith('.Column') > -1; -}; - -export const components = { - body: { - row: (props) => { - return ; - }, - cell: (props) => ( -
- ), - }, -}; - -const useDef = () => { - const [selectedRowKeys, setSelectedRowKeys] = useState([]); - return [selectedRowKeys, setSelectedRowKeys]; -}; - -const useDefDataSource = (options, props) => { - const field = useField(); - return useRequest(() => { - return Promise.resolve({ - data: field.value, - }); - }, options); -}; - -const groupColumns = [ - { - dataIndex: 'name', - key: 'name', - }, -]; - -type CategorizeKey = 'primaryAndForeignKey' | 'relation' | 'systemInfo' | 'basic'; -const CategorizeKeyNameMap = new Map([ - ['primaryAndForeignKey', 'PK & FK fields'], - ['relation', 'Association fields'], - ['systemInfo', 'System fields'], - ['basic', 'General fields'], -]); - -interface CategorizeDataItem { - key: CategorizeKey; - name: string; - data: Array; -} - -export const CollectionFieldsTableArray: React.FC = observer( - (props) => { - const sortKeyArr: Array = ['primaryAndForeignKey', 'relation', 'basic', 'systemInfo']; - const field = useField(); - const recordData = useRecord(); - const { name } = recordData; - const { t } = useTranslation(); - const compile = useCompile(); - const { getInterface, getInheritCollections, getCollection, getCurrentCollectionFields, getInheritedFields } = - useCollectionManager_deprecated(); - const { - showIndex = true, - useSelectedRowKeys = useDef, - useDataSource = useDefDataSource, - onChange, - ...others - } = props; - const [selectedRowKeys, setSelectedRowKeys] = useSelectedRowKeys(); - const [categorizeData, setCategorizeData] = useState>([]); - const [expandedKeys, setExpendedKeys] = useState(selectedRowKeys); - const inherits = getInheritCollections(name); - useDataSource({ - onSuccess(data) { - field.value = data?.data || []; - const tmpData: Array = []; - const categorizeMap = new Map(); - const addCategorizeVal = (categorizeKey: CategorizeKey, val) => { - let fieldArr = categorizeMap.get(categorizeKey); - if (!fieldArr) { - fieldArr = []; - } - fieldArr.push(val); - categorizeMap.set(categorizeKey, fieldArr); - }; - field.value.forEach((item) => { - const itemInterface = getInterface(item?.interface); - if (item?.primaryKey || item.isForeignKey) { - addCategorizeVal('primaryAndForeignKey', item); - return; - } - const group = itemInterface?.group as CategorizeKey; - switch (group) { - case 'systemInfo': - case 'relation': - addCategorizeVal(group, item); - break; - default: - addCategorizeVal('basic', item); - } - }); - if (inherits) { - inherits.forEach((v: any) => { - sortKeyArr.push(v); - const parentCollection = getCollection(v); - parentCollection.fields.map((k) => { - if (k.interface) { - addCategorizeVal(v, new Proxy(k, {})); - field.value.push(new Proxy(k, {})); - } - }); - }); - } - sortKeyArr.forEach((key) => { - if (categorizeMap.get(key)?.length > 0) { - const parentCollection = getCollection(key); - tmpData.push({ - key, - name: - t(CategorizeKeyNameMap.get(key)) || - t(`Parent collection fields`) + `(${compile(parentCollection.title)})`, - data: categorizeMap.get(key), - }); - } - }); - setExpendedKeys(sortKeyArr); - setCategorizeData(tmpData); - }, - }); - const useTableColumns = () => { - const schema = useFieldSchema(); - const { exists, render } = useSchemaInitializerRender(schema['x-initializer'], schema['x-initializer-props']); - const columns = schema - .reduceProperties((buf, s) => { - if (isColumnComponent(s)) { - return buf.concat([s]); - } - }, []) - .map((s: Schema) => { - return { - title: , - dataIndex: s.name, - key: s.name, - render: (v, record) => { - const index = findIndex(field.value, record); - return ( - - - - - - ); - }, - } as TableColumnProps; - }); - if (!exists) { - return columns; - } - return columns.concat({ - title: render(), - dataIndex: 'TABLE_COLUMN_INITIALIZER', - key: 'TABLE_COLUMN_INITIALIZER', - }); - }; - - const ExpandedRowRender = (record: CategorizeDataItem, index, indent, expanded) => { - const columns = useTableColumns(); - if (!props.loading) { - if (inherits.includes(record.key)) { - columns.pop(); - columns.push({ - title: , - dataIndex: 'column4', - key: 'column4', - render: (v, record) => { - const index = findIndex(field.value, record); - return ( - - - - - - ); - }, - }); - } - const restProps = { - rowSelection: - props.rowSelection && !inherits.includes(record.key) - ? { - type: 'checkbox', - selectedRowKeys, - onChange(selectedRowKeys: any[]) { - setSelectedRowKeys(selectedRowKeys); - }, - ...props.rowSelection, - } - : undefined, - }; - return ( - - ); - } - }; - return ( -
-
{ - let keys = []; - if (expanded) { - keys = expandedKeys.concat([record.key]); - } else { - keys = expandedKeys.filter((v) => { - return v !== record.key; - }); - } - setExpendedKeys(keys); - }} - /> - - ); - }, - { displayName: 'CollectionFieldsTableArray' }, -); diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/ConfigurationTable.tsx b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/ConfigurationTable.tsx index cebbddf9d4..ef370ffd4a 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/ConfigurationTable.tsx +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/ConfigurationTable.tsx @@ -3,7 +3,7 @@ import { action } from '@formily/reactive'; import { uid } from '@formily/shared'; import React, { useContext, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { CollectionFieldsTable } from '.'; +// import { CollectionFieldsTable } from '.'; import { useAPIClient, useCurrentAppInfo, @@ -191,7 +191,6 @@ export const ConfigurationTable = () => { EditSubFieldAction, FieldSummary, TemplateSummay: TemplateSummary, - CollectionFieldsTable, CollectionFields, }} scope={{ diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/index.tsx b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/index.tsx index 1cca50b2cd..bafb996d14 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/index.tsx +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/index.tsx @@ -1,6 +1,5 @@ import { registerValidateFormats } from '@formily/core'; export * from './ConfigurationTable'; -export * from './CollectionFieldsTable'; export * from './schemas/collections'; export * from './ConfigurationTabs'; export * from './AddCategoryAction'; diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/schemas/collectionFields.ts b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/schemas/collectionFields.ts index d383d8d239..8ab05fea3e 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/schemas/collectionFields.ts +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/MainDataSourceManager/Configuration/schemas/collectionFields.ts @@ -65,215 +65,3 @@ export const collection: CollectionOptions = { }, ], }; - -export const collectionFieldSchema: ISchema = { - type: 'void', - 'x-collection-field': 'collections.fields', - 'x-decorator': 'ResourceActionProvider', - 'x-decorator-props': { - association: { - sourceKey: 'name', - targetKey: 'name', - }, - collection, - request: { - resource: 'collections.fields', - action: 'list', - params: { - paginate: false, - filter: { - $or: [{ 'interface.$not': null }, { 'options.source.$notEmpty': true }], - }, - sort: ['sort'], - // appends: ['uiSchema'], - }, - }, - }, - properties: { - summary: { - type: 'void', - 'x-component': 'FieldSummary', - }, - actions: { - type: 'void', - 'x-component': 'ActionBar', - 'x-component-props': { - style: { - marginBottom: 16, - }, - }, - properties: { - delete: { - type: 'void', - title: '{{ t("Delete") }}', - 'x-component': 'Action', - 'x-component-props': { - useAction: '{{ cm.useBulkDestroyActionAndRefreshCM }}', - confirm: { - title: "{{t('Delete record')}}", - content: "{{t('Are you sure you want to delete it?')}}", - }, - }, - }, - syncfromDatabase: { - type: 'void', - title: '{{ t("Sync from database") }}', - 'x-component': 'SyncFieldsAction', - 'x-component-props': { - type: 'primary', - }, - }, - syncSQL: { - type: 'void', - title: '{{ t("Sync from database") }}', - 'x-component': 'SyncSQLFieldsAction', - 'x-component-props': { - type: 'primary', - }, - }, - create: { - type: 'void', - title: '{{ t("Add new") }}', - 'x-component': 'AddCollectionField', - 'x-component-props': { - type: 'primary', - }, - }, - }, - }, - table: { - type: 'void', - 'x-uid': 'input', - 'x-component': 'CollectionFieldsTable', - 'x-component-props': { - rowKey: 'name', - rowSelection: { - type: 'checkbox', - }, - useDataSource: '{{ cm.useDataSourceFromRAC }}', - }, - properties: { - column1: { - type: 'void', - title: '{{ t("Field display name") }}', - 'x-component': 'Table.Column', - properties: { - 'uiSchema.title': { - type: 'number', - 'x-component': 'Input', - 'x-read-pretty': true, - }, - }, - }, - column2: { - type: 'void', - 'x-decorator': 'Table.Column.Decorator', - 'x-component': 'Table.Column', - properties: { - name: { - 'x-component': 'CollectionField', - 'x-read-pretty': true, - }, - }, - }, - column3: { - type: 'void', - 'x-decorator': 'Table.Column.Decorator', - 'x-component': 'Table.Column', - title: '{{t("Field interface")}}', - properties: { - interface: { - 'x-component': CollectionFieldInterfaceTag, - 'x-read-pretty': true, - }, - }, - }, - column4: { - type: 'void', - 'x-decorator': 'Table.Column.Decorator', - 'x-component': 'Table.Column', - title: '{{ t("Description") }}', - properties: { - interface: { - 'x-component': 'CollectionField', - 'x-read-pretty': true, - }, - }, - }, - column5: { - type: 'void', - title: '{{ t("Actions") }}', - 'x-component': 'Table.Column', - properties: { - actions: { - type: 'void', - 'x-component': 'Space', - 'x-component-props': { - split: '|', - }, - properties: { - update: { - type: 'void', - title: '{{ t("Edit") }}', - 'x-component': 'EditCollectionField', - 'x-component-props': { - role: 'button', - 'aria-label': '{{ "edit-button-" + $record.name }}', - type: 'primary', - }, - }, - delete: { - type: 'void', - title: '{{ t("Delete") }}', - 'x-disabled': '{{cm.useDeleteButtonDisabled()}}', - 'x-component': 'Action.Link', - 'x-component-props': { - confirm: { - title: "{{t('Delete record')}}", - content: "{{t('Are you sure you want to delete it?')}}", - }, - useAction: '{{ cm.useDestroyActionAndRefreshCM }}', - }, - }, - }, - }, - }, - }, - }, - }, - }, -}; - -export const overridingSchema: ISchema = { - type: 'void', - title: '{{ t("Actions") }}', - 'x-component': 'Table.Column', - properties: { - actions: { - type: 'void', - 'x-component': 'Space', - 'x-component-props': { - split: '|', - }, - properties: { - overriding: { - type: 'void', - title: '{{ t("Overriding") }}', - 'x-component': 'OverridingCollectionField', - 'x-component-props': { - type: 'primary', - currentCollection: '{{ currentCollection }}', - }, - }, - view: { - type: 'void', - title: '{{ t("View") }}', - 'x-component': 'ViewCollectionField', - 'x-component-props': { - type: 'primary', - }, - }, - }, - }, - }, -};