mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-07-01 18:52:20 +08:00
fix(collection-manager): no refresh after override the field (#4022)
* refactor: code improve * fix: bug
This commit is contained in:
parent
a18dab363a
commit
1658415402
@ -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) => {
|
export const OverridingCollectionField = (props) => {
|
||||||
const record = useRecord();
|
const record = useRecord();
|
||||||
const parentRecordData = useCollectionParentRecordData();
|
const parentRecordData = useCollectionParentRecordData();
|
||||||
@ -135,7 +102,15 @@ const getIsOverriding = (currentFields, record) => {
|
|||||||
return flag;
|
return flag;
|
||||||
};
|
};
|
||||||
export const OverridingFieldAction = (props) => {
|
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 { target, through } = record;
|
||||||
const { getInterface, getCurrentCollectionFields, getChildrenCollections, collections } =
|
const { getInterface, getCurrentCollectionFields, getChildrenCollections, collections } =
|
||||||
useCollectionManager_deprecated();
|
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 (
|
return (
|
||||||
<RecordProvider record={{ ...record, collectionName: parentRecord.name }} parent={parentRecord}>
|
<RecordProvider record={{ ...record, collectionName: parentRecord.name }} parent={parentRecord}>
|
||||||
<ActionContextProvider value={{ visible, setVisible }}>
|
<ActionContextProvider value={{ visible, setVisible }}>
|
||||||
@ -213,7 +221,6 @@ export const OverridingFieldAction = (props) => {
|
|||||||
isOverride: true,
|
isOverride: true,
|
||||||
targetScope: { target: getFilterCollections(target), through: getFilterCollections(through) },
|
targetScope: { target: getFilterCollections(target), through: getFilterCollections(through) },
|
||||||
collections: currentCollections,
|
collections: currentCollections,
|
||||||
|
|
||||||
...scope,
|
...scope,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
import { createForm, Field } from '@formily/core';
|
import { createForm, Field } from '@formily/core';
|
||||||
import { FieldContext, FormContext, useField } from '@formily/react';
|
import { FieldContext, FormContext, useField } from '@formily/react';
|
||||||
import { Space, Switch, Table, TableColumnProps, Tag, Tooltip } from 'antd';
|
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 { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
Action,
|
Action,
|
||||||
@ -30,7 +30,24 @@ import {
|
|||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
|
|
||||||
import { collection } from './schemas/collectionFields';
|
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`
|
const indentStyle = css`
|
||||||
.ant-table {
|
.ant-table {
|
||||||
margin-left: -16px !important;
|
margin-left: -16px !important;
|
||||||
@ -60,6 +77,7 @@ const tableContainer = css`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const titlePrompt = 'Default title for each record';
|
const titlePrompt = 'Default title for each record';
|
||||||
|
const RefreshContext = createContext(null);
|
||||||
|
|
||||||
const CurrentFields = (props) => {
|
const CurrentFields = (props) => {
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
@ -238,9 +256,11 @@ const InheritFields = (props) => {
|
|||||||
dataIndex: 'actions',
|
dataIndex: 'actions',
|
||||||
title: t('Actions'),
|
title: t('Actions'),
|
||||||
render: function Render(_, record) {
|
render: function Render(_, record) {
|
||||||
|
const { handleRefresh } = useContext(RefreshContext);
|
||||||
const overrideProps = {
|
const overrideProps = {
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
currentCollection: name,
|
currentCollection: name,
|
||||||
|
handleRefresh,
|
||||||
};
|
};
|
||||||
const viewCollectionProps = {
|
const viewCollectionProps = {
|
||||||
type: 'primary',
|
type: 'primary',
|
||||||
@ -383,25 +403,6 @@ export const CollectionFields = () => {
|
|||||||
.filter(Boolean),
|
.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(
|
const deleteProps = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
useAction: useBulkDestroyActionAndRefreshCM,
|
useAction: useBulkDestroyActionAndRefreshCM,
|
||||||
@ -417,58 +418,65 @@ export const CollectionFields = () => {
|
|||||||
);
|
);
|
||||||
const addProps = { type: 'primary', database };
|
const addProps = { type: 'primary', database };
|
||||||
const syncProps = { type: 'primary' };
|
const syncProps = { type: 'primary' };
|
||||||
|
const [refresh, setRefresh] = useState(false);
|
||||||
|
|
||||||
|
const handleRefresh = () => {
|
||||||
|
setRefresh(!refresh);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<ResourceActionProvider {...resourceActionProps}>
|
<RefreshContext.Provider value={{ refresh, handleRefresh }}>
|
||||||
<FormContext.Provider value={form}>
|
<ResourceActionProvider {...resourceActionProps}>
|
||||||
<FieldContext.Provider value={f}>
|
<FormContext.Provider value={form}>
|
||||||
<Space
|
<FieldContext.Provider value={f}>
|
||||||
align={'end'}
|
<Space
|
||||||
className={css`
|
align={'end'}
|
||||||
justify-content: flex-end;
|
className={css`
|
||||||
display: flex;
|
justify-content: flex-end;
|
||||||
margin-bottom: 16px;
|
display: flex;
|
||||||
`}
|
margin-bottom: 16px;
|
||||||
>
|
`}
|
||||||
<Action {...deleteProps} />
|
>
|
||||||
<SyncFieldsAction {...syncProps} />
|
<Action {...deleteProps} />
|
||||||
<SyncSQLFieldsAction refreshCMList={refreshAsync} />
|
<SyncFieldsAction {...syncProps} />
|
||||||
<SchemaComponent
|
<SyncSQLFieldsAction refreshCMList={refreshAsync} />
|
||||||
schema={{
|
<SchemaComponent
|
||||||
type: 'object',
|
schema={{
|
||||||
properties: {
|
type: 'object',
|
||||||
...targetTemplate.configureActions,
|
properties: {
|
||||||
},
|
...targetTemplate.configureActions,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddCollectionField {...addProps} />
|
||||||
|
</Space>
|
||||||
|
<Table
|
||||||
|
rowKey={'key'}
|
||||||
|
columns={columns}
|
||||||
|
dataSource={dataSource.filter((d) => d.fields.length)}
|
||||||
|
pagination={false}
|
||||||
|
className={tableContainer}
|
||||||
|
expandable={{
|
||||||
|
defaultExpandAllRows: true,
|
||||||
|
defaultExpandedRowKeys: dataSource.map((d) => d.key),
|
||||||
|
expandedRowRender: (record) =>
|
||||||
|
record.inherit ? (
|
||||||
|
<InheritFields
|
||||||
|
fields={record.fields}
|
||||||
|
collectionResource={collectionResource}
|
||||||
|
refreshAsync={refreshAsync}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<CurrentFields
|
||||||
|
fields={record.fields}
|
||||||
|
collectionResource={collectionResource}
|
||||||
|
refreshAsync={refreshAsync}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<AddCollectionField {...addProps} />
|
</FieldContext.Provider>
|
||||||
</Space>
|
</FormContext.Provider>
|
||||||
<Table
|
</ResourceActionProvider>
|
||||||
rowKey={'key'}
|
</RefreshContext.Provider>
|
||||||
columns={columns}
|
|
||||||
dataSource={dataSource.filter((d) => d.fields.length)}
|
|
||||||
pagination={false}
|
|
||||||
className={tableContainer}
|
|
||||||
expandable={{
|
|
||||||
defaultExpandAllRows: true,
|
|
||||||
defaultExpandedRowKeys: dataSource.map((d) => d.key),
|
|
||||||
expandedRowRender: (record) =>
|
|
||||||
record.inherit ? (
|
|
||||||
<InheritFields
|
|
||||||
fields={record.fields}
|
|
||||||
collectionResource={collectionResource}
|
|
||||||
refreshAsync={refreshAsync}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<CurrentFields
|
|
||||||
fields={record.fields}
|
|
||||||
collectionResource={collectionResource}
|
|
||||||
refreshAsync={refreshAsync}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FieldContext.Provider>
|
|
||||||
</FormContext.Provider>
|
|
||||||
</ResourceActionProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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<any> & {
|
|
||||||
request?: any;
|
|
||||||
useSelectedRowKeys?: any;
|
|
||||||
useDataSource?: (
|
|
||||||
options?: Options<any, any> & { uid?: string },
|
|
||||||
props?: any,
|
|
||||||
) => Result<any, any> & { 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<TableVoidProps> = observer(
|
|
||||||
(props) => {
|
|
||||||
const { rowKey = 'id', useDataSource = useDef, useSelectedRowKeys = useDefSelectedRowKeys } = props;
|
|
||||||
const field = useField<Field>();
|
|
||||||
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 (
|
|
||||||
<AsyncDataProvider value={result}>
|
|
||||||
<FormContext.Provider value={form}>
|
|
||||||
<FieldContext.Provider value={f}>
|
|
||||||
<CollectionFieldsTableArray
|
|
||||||
{...props}
|
|
||||||
rowKey={rowKey}
|
|
||||||
loading={result?.['loading']}
|
|
||||||
useSelectedRowKeys={useSelectedRowKeys}
|
|
||||||
pagination={false}
|
|
||||||
/>
|
|
||||||
</FieldContext.Provider>
|
|
||||||
</FormContext.Provider>
|
|
||||||
</AsyncDataProvider>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
{ displayName: 'CollectionFieldsTable' },
|
|
||||||
);
|
|
@ -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 <tr {...props} />;
|
|
||||||
},
|
|
||||||
cell: (props) => (
|
|
||||||
<td
|
|
||||||
{...props}
|
|
||||||
className={classNames(
|
|
||||||
props.className,
|
|
||||||
css`
|
|
||||||
max-width: 300px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
`,
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const useDef = () => {
|
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
|
||||||
return [selectedRowKeys, setSelectedRowKeys];
|
|
||||||
};
|
|
||||||
|
|
||||||
const useDefDataSource = (options, props) => {
|
|
||||||
const field = useField<Field>();
|
|
||||||
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<CategorizeKey, string>([
|
|
||||||
['primaryAndForeignKey', 'PK & FK fields'],
|
|
||||||
['relation', 'Association fields'],
|
|
||||||
['systemInfo', 'System fields'],
|
|
||||||
['basic', 'General fields'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
interface CategorizeDataItem {
|
|
||||||
key: CategorizeKey;
|
|
||||||
name: string;
|
|
||||||
data: Array<any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CollectionFieldsTableArray: React.FC<any> = observer(
|
|
||||||
(props) => {
|
|
||||||
const sortKeyArr: Array<CategorizeKey> = ['primaryAndForeignKey', 'relation', 'basic', 'systemInfo'];
|
|
||||||
const field = useField<ArrayField>();
|
|
||||||
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<Array<CategorizeDataItem>>([]);
|
|
||||||
const [expandedKeys, setExpendedKeys] = useState(selectedRowKeys);
|
|
||||||
const inherits = getInheritCollections(name);
|
|
||||||
useDataSource({
|
|
||||||
onSuccess(data) {
|
|
||||||
field.value = data?.data || [];
|
|
||||||
const tmpData: Array<CategorizeDataItem> = [];
|
|
||||||
const categorizeMap = new Map<CategorizeKey, any>();
|
|
||||||
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: <RecursionField name={s.name} schema={s} onlyRenderSelf />,
|
|
||||||
dataIndex: s.name,
|
|
||||||
key: s.name,
|
|
||||||
render: (v, record) => {
|
|
||||||
const index = findIndex(field.value, record);
|
|
||||||
return (
|
|
||||||
<RecordIndexProvider index={index}>
|
|
||||||
<RecordProvider record={record} parent={recordData}>
|
|
||||||
<RecursionField schema={s} name={index} onlyRenderProperties />
|
|
||||||
</RecordProvider>
|
|
||||||
</RecordIndexProvider>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
} as TableColumnProps<any>;
|
|
||||||
});
|
|
||||||
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: <RecursionField name={'column4'} schema={overridingSchema as Schema} onlyRenderSelf />,
|
|
||||||
dataIndex: 'column4',
|
|
||||||
key: 'column4',
|
|
||||||
render: (v, record) => {
|
|
||||||
const index = findIndex(field.value, record);
|
|
||||||
return (
|
|
||||||
<RecordIndexProvider index={index}>
|
|
||||||
<RecordProvider record={record} parent={recordData}>
|
|
||||||
<SchemaComponent
|
|
||||||
scope={{ currentCollection: name }}
|
|
||||||
schema={overridingSchema as Schema}
|
|
||||||
name={index}
|
|
||||||
onlyRenderProperties
|
|
||||||
/>
|
|
||||||
</RecordProvider>
|
|
||||||
</RecordIndexProvider>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const restProps = {
|
|
||||||
rowSelection:
|
|
||||||
props.rowSelection && !inherits.includes(record.key)
|
|
||||||
? {
|
|
||||||
type: 'checkbox',
|
|
||||||
selectedRowKeys,
|
|
||||||
onChange(selectedRowKeys: any[]) {
|
|
||||||
setSelectedRowKeys(selectedRowKeys);
|
|
||||||
},
|
|
||||||
...props.rowSelection,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<Table
|
|
||||||
{...others}
|
|
||||||
{...restProps}
|
|
||||||
components={components}
|
|
||||||
showHeader={true}
|
|
||||||
columns={columns}
|
|
||||||
dataSource={record.data}
|
|
||||||
pagination={false}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={css`
|
|
||||||
.ant-table {
|
|
||||||
overflow-x: auto;
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<Table
|
|
||||||
showHeader={false}
|
|
||||||
loading={props?.loading}
|
|
||||||
columns={groupColumns}
|
|
||||||
dataSource={categorizeData}
|
|
||||||
pagination={false}
|
|
||||||
expandable={{
|
|
||||||
expandedRowRender: ExpandedRowRender,
|
|
||||||
expandedRowKeys: expandedKeys,
|
|
||||||
}}
|
|
||||||
onExpand={(expanded, record) => {
|
|
||||||
let keys = [];
|
|
||||||
if (expanded) {
|
|
||||||
keys = expandedKeys.concat([record.key]);
|
|
||||||
} else {
|
|
||||||
keys = expandedKeys.filter((v) => {
|
|
||||||
return v !== record.key;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setExpendedKeys(keys);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
{ displayName: 'CollectionFieldsTableArray' },
|
|
||||||
);
|
|
@ -3,7 +3,7 @@ import { action } from '@formily/reactive';
|
|||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import React, { useContext, useState } from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { CollectionFieldsTable } from '.';
|
// import { CollectionFieldsTable } from '.';
|
||||||
import {
|
import {
|
||||||
useAPIClient,
|
useAPIClient,
|
||||||
useCurrentAppInfo,
|
useCurrentAppInfo,
|
||||||
@ -191,7 +191,6 @@ export const ConfigurationTable = () => {
|
|||||||
EditSubFieldAction,
|
EditSubFieldAction,
|
||||||
FieldSummary,
|
FieldSummary,
|
||||||
TemplateSummay: TemplateSummary,
|
TemplateSummay: TemplateSummary,
|
||||||
CollectionFieldsTable,
|
|
||||||
CollectionFields,
|
CollectionFields,
|
||||||
}}
|
}}
|
||||||
scope={{
|
scope={{
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { registerValidateFormats } from '@formily/core';
|
import { registerValidateFormats } from '@formily/core';
|
||||||
export * from './ConfigurationTable';
|
export * from './ConfigurationTable';
|
||||||
export * from './CollectionFieldsTable';
|
|
||||||
export * from './schemas/collections';
|
export * from './schemas/collections';
|
||||||
export * from './ConfigurationTabs';
|
export * from './ConfigurationTabs';
|
||||||
export * from './AddCategoryAction';
|
export * from './AddCategoryAction';
|
||||||
|
@ -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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user