feat: improve code

This commit is contained in:
chenos 2022-02-25 23:09:42 +08:00
parent 585d9dd580
commit bcc42a9455
12 changed files with 276 additions and 18 deletions

View File

@ -38,7 +38,7 @@ const InternalField: React.FC = (props) => {
if (!uiSchema) {
return null;
}
return React.createElement(component, props);
return React.createElement(component, props, props.children);
};
export const CollectionField = connect((props) => {

View File

@ -8,13 +8,14 @@ import {
useDataSourceFromRAC
} from './';
import * as hooks from './action-hooks';
import { DataSourceProvider, ds } from './sub-table';
import { DataSourceProvider, ds, SubFieldDataSourceProvider } from './sub-table';
export const CollectionManagerSchemaComponentProvider: React.FC = (props) => {
return (
<SchemaComponentOptions
scope={{ cm: { ...hooks, useDataSourceFromRAC }, ds }}
components={{
SubFieldDataSourceProvider,
DataSourceProvider,
CollectionField,
CollectionFieldProvider,

View File

@ -3,7 +3,7 @@ import { CollectionContext } from './context';
import { useCollectionManager } from './hooks';
import { CollectionOptions } from './types';
export const CollectionProvider: React.FC<{ name?: string; collection: CollectionOptions }> = (props) => {
export const CollectionProvider: React.FC<{ name?: string; collection?: CollectionOptions }> = (props) => {
const { name, collection, children } = props;
const { get } = useCollectionManager();
return (

View File

@ -33,7 +33,7 @@ export const subTable: IField = {
...defaultProps,
subtable: {
type: 'void',
'x-component': 'DataSourceProvider',
'x-component': 'SubFieldDataSourceProvider',
properties: {
actions: {
type: 'void',

View File

@ -1,4 +1,5 @@
import { observer, useForm } from '@formily/react';
import { cloneDeep } from 'lodash';
import React, { createContext, useContext, useState } from 'react';
import { CollectionOptions, CollectionProvider, useActionContext, useRecord, useRequest } from '../';
import { useAPIClient } from '../api-client';
@ -88,11 +89,12 @@ const useCreateAction = () => {
const { setVisible } = useActionContext();
return {
async run() {
// console.log(ctx.dataSource);
console.log('form.values', form.values);
const dataSource = ctx.dataSource || [];
dataSource.push(form.values);
dataSource.push(cloneDeep(form.values));
ctx.setDataSource([...dataSource]);
setVisible(false);
await form.reset();
},
};
};
@ -159,7 +161,7 @@ export const ds = {
useDestroyAction,
};
export const DataSourceProvider = observer((props) => {
export const SubFieldDataSourceProvider = observer((props) => {
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [dataSource, setDataSource] = useState([]);
const record = useRecord();
@ -212,3 +214,50 @@ export const DataSourceProvider = observer((props) => {
</CollectionProvider>
);
});
export const DataSourceProvider = observer((props: any) => {
const { rowKey = 'id', collection, association } = props;
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [dataSource, setDataSource] = useState([]);
const record = useRecord();
const api = useAPIClient();
const resourceOf = record?.[association.targetKey || 'id'];
console.log('record', record);
const service = useRequest(
() => {
if (resourceOf) {
return api
.request({
resource: `${collection}.${association.name}`,
resourceOf,
action: 'list',
})
.then((res) => res.data);
}
return Promise.resolve({
data: record?.[association.name] || [],
});
},
{
onSuccess(data) {
setDataSource(data?.data);
},
},
);
return (
<CollectionProvider name={collection}>
<DataSourceContext.Provider
value={{
rowKey,
service,
dataSource,
setDataSource,
selectedRowKeys,
setSelectedRowKeys,
}}
>
{props.children}
</DataSourceContext.Provider>
</CollectionProvider>
);
});

View File

@ -1,11 +1,10 @@
import { observer } from '@formily/react';
import React from 'react';
import { Link } from 'react-router-dom';
import Action from './Action';
import { ComposedAction } from './types';
export const ActionLink: ComposedAction = observer((props: any) => {
return <Action {...props} component={Link} className={'nb-action-link'}/>;
return <Action {...props} component={'a'} className={'nb-action-link'}/>;
});
export default ActionLink;

View File

@ -72,7 +72,9 @@ export const Action: ComposedAction = observer((props: any) => {
<ActionContext.Provider value={{ visible, setVisible, openMode, containerRefKey }}>
<SortableItem
{...others}
onClick={(e) => {
onClick={(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
const onOk = () => {
onClick?.(e);
setVisible(true);

View File

@ -0,0 +1,171 @@
import { ISchema } from '@formily/react';
import { Switch } from 'antd';
import React from 'react';
import { SchemaInitializer } from '../../SchemaInitializer';
import { useCurrentSchema } from '../utils';
export const SubTableFieldInitializer = (props) => {
const { item, insert } = props;
const { exists, remove } = useCurrentSchema(
item.schema['x-collection-field'],
'x-collection-field',
item.find,
item.remove,
);
return (
<SchemaInitializer.Item
onClick={() => {
console.log(item, exists);
if (exists) {
return remove();
}
insert({
...item.schema,
properties: {
block: {
type: 'void',
'x-component': 'DataSourceProvider',
'x-component-props': {
rowKey: 'id',
collection: item?.field?.target,
association: {
name: item.field.name,
sourceKey: item.field.sourceKey,
targetKey: item.field.targetKey,
},
},
properties: {
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: '{{ ds.useBulkDestroyAction }}',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
},
},
},
create: {
type: 'void',
title: '{{ t("Add new") }}',
'x-action': 'create',
'x-component': 'Action',
'x-component-props': {
type: 'primary',
openMode: 'drawer',
},
properties: {
drawer: {
type: 'void',
title: '{{ t("Add new record") }}',
'x-component': 'Action.Container',
'x-component-props': {},
'x-decorator': 'Form',
properties: {
grid: {
type: 'void',
'x-component': 'Grid',
'x-initializer': 'GridFormItemInitializers',
properties: {},
},
footer: {
type: 'void',
'x-component': 'Action.Container.Footer',
properties: {
actions: {
type: 'void',
'x-component': 'ActionBar',
'x-component-props': {
layout: 'one-column',
},
properties: {
cancel: {
title: '{{ t("Cancel") }}',
'x-action': 'cancel',
'x-component': 'Action',
'x-component-props': {
useAction: '{{ cm.useCancelAction }}',
},
},
submit: {
title: '{{ t("Submit") }}',
'x-action': 'submit',
'x-component': 'Action',
'x-component-props': {
type: 'primary',
useAction: '{{ ds.useCreateAction }}',
},
},
},
},
},
},
},
},
},
},
},
},
[item.field.name]: {
type: 'array',
title: '{{t("Fields")}}',
'x-component': 'Table.Array',
'x-initializer': 'TableColumnInitializers',
'x-component-props': {
pagination: false,
expandable: {
childrenColumnName: '__nochildren__',
},
rowKey: 'id',
rowSelection: {
type: 'checkbox',
},
useSelectedRowKeys: '{{ ds.useSelectedRowKeys }}',
useDataSource: '{{ ds.useDataSource }}',
// scroll: { x: '100%' },
},
properties: {
actions: {
type: 'void',
title: '{{ t("Actions") }}',
'x-decorator': 'Table.Column.ActionBar',
'x-component': 'Table.Column',
'x-designer': 'Table.RowActionDesigner',
'x-initializer': 'TableRecordActionInitializers',
properties: {
actions: {
type: 'void',
'x-decorator': 'DndContext',
'x-component': 'Space',
'x-component-props': {
split: '|',
},
properties: {},
},
},
},
},
},
},
},
},
} as ISchema);
}}
>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
{item.title} <Switch style={{ marginLeft: 20 }} size={'small'} checked={exists} />
</div>
</SchemaInitializer.Item>
);
};

View File

@ -5,5 +5,6 @@ export * from './CollectionFieldInitializer';
export * from './FormBlockInitializer';
export * from './GeneralInitializer';
export * from './MarkdownBlockInitializer';
export * from './SubTableFieldInitializer';
export * from './TableBlockInitializer';

View File

@ -12,7 +12,6 @@ export const TableRecordActionInitializers = (props: any) => {
const api = useAPIClient();
const { refresh } = useDesignable();
const { t } = useTranslation();
console.log('TableRecordActionInitializers');
return (
<SchemaInitializer.Button
className={css`
@ -118,7 +117,7 @@ export const TableRecordActionInitializers = (props: any) => {
grid: {
type: 'void',
'x-component': 'Grid',
'x-item-initializer': 'FormItemInitializer',
'x-initializer': 'GridFormItemInitializers',
properties: {},
},
footer: {
@ -127,7 +126,7 @@ export const TableRecordActionInitializers = (props: any) => {
properties: {
actions: {
type: 'void',
'x-action-initializer': 'PopupFormActionInitializer',
'x-initializer': 'PopupFormActionInitializers',
'x-decorator': 'DndContext',
'x-component': 'ActionBar',
'x-component-props': {

View File

@ -23,9 +23,9 @@ export const gridRowColWrap = (schema: ISchema) => {
export const removeTableColumn = (schema, cb) => {
cb(schema, {
removeParentsIfNoChildren: true,
breakRemoveOn: {
'x-component': 'ArrayTable',
},
// breakRemoveOn: (s) => {
// return s['x-component'].startsWith('Table.');
// },
});
};
@ -38,6 +38,24 @@ export const removeGridFormItem = (schema, cb) => {
});
};
const findTableColumn = (schema: Schema, key: string, action: string, deepth: number = 0) => {
return schema.reduceProperties((buf, s) => {
if (s[key] === action) {
return s;
}
const c = s.reduceProperties((buf, s) => {
if (s[key] === action) {
return s;
}
return buf;
});
if (c) {
return c;
}
return buf;
});
};
export const useTableColumnInitializerFields = () => {
const { name, fields } = useCollection();
return (
@ -53,6 +71,7 @@ export const useTableColumnInitializerFields = () => {
'x-component': 'CollectionField',
},
component: 'CollectionFieldInitializer',
find: findTableColumn,
remove: removeTableColumn,
} as SchemaInitializerItemOptions;
})
@ -62,6 +81,23 @@ export const useTableColumnInitializerFields = () => {
export const useFormItemInitializerFields = () => {
const { name, fields } = useCollection();
return fields?.map((field) => {
if (field.interface === 'subTable') {
return {
type: 'item',
title: field?.uiSchema?.title || field.name,
component: 'SubTableFieldInitializer',
remove: removeGridFormItem,
field,
schema: {
type: 'void',
name: field.name,
'x-designer': 'FormItem.Designer',
'x-component': 'div',
'x-decorator': 'FormItem',
'x-collection-field': `${name}.${field.name}`,
},
} as SchemaInitializerItemOptions;
}
return {
type: 'item',
title: field?.uiSchema?.title || field.name,

View File

@ -39,7 +39,7 @@ interface ItemOptions extends ItemCommonOptions {
component?: any;
schema?: ISchema;
remove?: (schema: Schema, cb: RemoveCallback) => void;
find?: (schema: Schema, current: string) => Schema | null | undefined;
find?: (schema: Schema, key?: string, current?: string) => Schema | null | undefined;
[key: string]: any;
}