feat: details block (#302)
This commit is contained in:
parent
111b9e67b0
commit
1f12c20838
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,7 +8,7 @@ yarn-error.log
|
|||||||
lerna-debug.log
|
lerna-debug.log
|
||||||
/.vscode
|
/.vscode
|
||||||
/.idea
|
/.idea
|
||||||
db.sqlite
|
*.sqlite
|
||||||
coverage
|
coverage
|
||||||
.umi
|
.umi
|
||||||
/uploads
|
/uploads
|
||||||
|
@ -2,12 +2,14 @@ import React from 'react';
|
|||||||
import { SchemaComponentOptions } from '../schema-component/core/SchemaComponentOptions';
|
import { SchemaComponentOptions } from '../schema-component/core/SchemaComponentOptions';
|
||||||
import { RecordLink, useParamsFromRecord, useSourceIdFromParentRecord, useSourceIdFromRecord } from './BlockProvider';
|
import { RecordLink, useParamsFromRecord, useSourceIdFromParentRecord, useSourceIdFromRecord } from './BlockProvider';
|
||||||
import { CalendarBlockProvider, useCalendarBlockProps } from './CalendarBlockProvider';
|
import { CalendarBlockProvider, useCalendarBlockProps } from './CalendarBlockProvider';
|
||||||
|
import { DetailsBlockProvider, useDetailsBlockProps } from './DetailsBlockProvider';
|
||||||
import { FormBlockProvider, useFormBlockProps } from './FormBlockProvider';
|
import { FormBlockProvider, useFormBlockProps } from './FormBlockProvider';
|
||||||
import * as bp from './hooks';
|
import * as bp from './hooks';
|
||||||
import { KanbanBlockProvider, useKanbanBlockProps } from './KanbanBlockProvider';
|
import { KanbanBlockProvider, useKanbanBlockProps } from './KanbanBlockProvider';
|
||||||
import { TableBlockProvider, useTableBlockProps } from './TableBlockProvider';
|
import { TableBlockProvider, useTableBlockProps } from './TableBlockProvider';
|
||||||
import { TableFieldProvider, useTableFieldProps } from './TableFieldProvider';
|
import { TableFieldProvider, useTableFieldProps } from './TableFieldProvider';
|
||||||
import { TableSelectorProvider, useTableSelectorProps } from './TableSelectorProvider';
|
import { TableSelectorProvider, useTableSelectorProps } from './TableSelectorProvider';
|
||||||
|
|
||||||
export const BlockSchemaComponentProvider: React.FC = (props) => {
|
export const BlockSchemaComponentProvider: React.FC = (props) => {
|
||||||
return (
|
return (
|
||||||
<SchemaComponentOptions
|
<SchemaComponentOptions
|
||||||
@ -17,6 +19,7 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
|
|||||||
TableBlockProvider,
|
TableBlockProvider,
|
||||||
TableSelectorProvider,
|
TableSelectorProvider,
|
||||||
FormBlockProvider,
|
FormBlockProvider,
|
||||||
|
DetailsBlockProvider,
|
||||||
KanbanBlockProvider,
|
KanbanBlockProvider,
|
||||||
RecordLink,
|
RecordLink,
|
||||||
}}
|
}}
|
||||||
@ -27,6 +30,7 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
|
|||||||
useParamsFromRecord,
|
useParamsFromRecord,
|
||||||
useCalendarBlockProps,
|
useCalendarBlockProps,
|
||||||
useFormBlockProps,
|
useFormBlockProps,
|
||||||
|
useDetailsBlockProps,
|
||||||
useTableFieldProps,
|
useTableFieldProps,
|
||||||
useTableBlockProps,
|
useTableBlockProps,
|
||||||
useTableSelectorProps,
|
useTableSelectorProps,
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { useField } from '@formily/react';
|
||||||
|
import { Spin } from 'antd';
|
||||||
|
import React, { createContext, useContext, useEffect, useMemo } from 'react';
|
||||||
|
import { RecordProvider } from '../record-provider';
|
||||||
|
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
|
||||||
|
|
||||||
|
export const DetailsBlockContext = createContext<any>({});
|
||||||
|
|
||||||
|
const InternalDetailsBlockProvider = (props) => {
|
||||||
|
const { action, readPretty } = props;
|
||||||
|
const field = useField<any>();
|
||||||
|
const form = useMemo(
|
||||||
|
() =>
|
||||||
|
createForm({
|
||||||
|
readPretty,
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const { resource, service } = useBlockRequestContext();
|
||||||
|
if (service.loading && !field.loaded) {
|
||||||
|
return <Spin />;
|
||||||
|
}
|
||||||
|
field.loaded = true;
|
||||||
|
return (
|
||||||
|
<DetailsBlockContext.Provider
|
||||||
|
value={{
|
||||||
|
action,
|
||||||
|
form,
|
||||||
|
field,
|
||||||
|
service,
|
||||||
|
resource,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RecordProvider record={service?.data?.data?.[0] || {}}>{props.children}</RecordProvider>
|
||||||
|
</DetailsBlockContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DetailsBlockProvider = (props) => {
|
||||||
|
return (
|
||||||
|
<BlockProvider {...props}>
|
||||||
|
<InternalDetailsBlockProvider {...props} />
|
||||||
|
</BlockProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDetailsBlockContext = () => {
|
||||||
|
return useContext(DetailsBlockContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDetailsBlockProps = () => {
|
||||||
|
const ctx = useDetailsBlockContext();
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ctx.service.loading) {
|
||||||
|
ctx.form.setValues(ctx.service?.data?.data?.[0] || {});
|
||||||
|
}
|
||||||
|
}, [ctx.service.loading]);
|
||||||
|
return {
|
||||||
|
form: ctx.form,
|
||||||
|
};
|
||||||
|
};
|
@ -20,15 +20,16 @@ const useGroupField = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const InternalKanbanBlockProvider = (props) => {
|
const InternalKanbanBlockProvider = (props) => {
|
||||||
const field = useField();
|
const field = useField<any>();
|
||||||
const { resource, service } = useBlockRequestContext();
|
const { resource, service } = useBlockRequestContext();
|
||||||
const groupField = useGroupField(props);
|
const groupField = useGroupField(props);
|
||||||
if (!groupField) {
|
if (!groupField) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (service.loading) {
|
if (service.loading && !field.loaded) {
|
||||||
return <Spin />;
|
return <Spin />;
|
||||||
}
|
}
|
||||||
|
field.loaded = true;
|
||||||
return (
|
return (
|
||||||
<KanbanBlockContext.Provider
|
<KanbanBlockContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
@ -5,6 +5,7 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import { useCollection } from '../../collection-manager';
|
import { useCollection } from '../../collection-manager';
|
||||||
import { useActionContext } from '../../schema-component';
|
import { useActionContext } from '../../schema-component';
|
||||||
import { useBlockRequestContext, useFilterByTk } from '../BlockProvider';
|
import { useBlockRequestContext, useFilterByTk } from '../BlockProvider';
|
||||||
|
import { useDetailsBlockContext } from '../DetailsBlockProvider';
|
||||||
import { TableFieldResource } from '../TableFieldProvider';
|
import { TableFieldResource } from '../TableFieldProvider';
|
||||||
|
|
||||||
export const usePickActionProps = () => {
|
export const usePickActionProps = () => {
|
||||||
@ -207,3 +208,23 @@ export const useBulkDestroyActionProps = () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useDetailsPaginationProps = () => {
|
||||||
|
const ctx = useDetailsBlockContext();
|
||||||
|
const count = ctx.service?.data?.meta?.count || 0;
|
||||||
|
return {
|
||||||
|
simple: true,
|
||||||
|
hidden: count <= 1,
|
||||||
|
current: ctx.service?.data?.meta?.page || 1,
|
||||||
|
total: count,
|
||||||
|
pageSize: 1,
|
||||||
|
async onChange(page) {
|
||||||
|
const params = ctx.service?.params?.[0];
|
||||||
|
ctx.service.run({ ...params, page });
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
marginTop: 24,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -81,7 +81,8 @@ export const useSortFields = (collectionName: string) => {
|
|||||||
export const useCollectionFilterOptions = (collectionName: string) => {
|
export const useCollectionFilterOptions = (collectionName: string) => {
|
||||||
const { getCollectionFields, getInterface } = useCollectionManager();
|
const { getCollectionFields, getInterface } = useCollectionManager();
|
||||||
const fields = getCollectionFields(collectionName);
|
const fields = getCollectionFields(collectionName);
|
||||||
const field2option = (field, nochildren) => {
|
let depth = 0;
|
||||||
|
const field2option = (field) => {
|
||||||
if (!field.interface) {
|
if (!field.interface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -94,9 +95,15 @@ export const useCollectionFilterOptions = (collectionName: string) => {
|
|||||||
name: field.name,
|
name: field.name,
|
||||||
title: field?.uiSchema?.title || field.name,
|
title: field?.uiSchema?.title || field.name,
|
||||||
schema: field?.uiSchema,
|
schema: field?.uiSchema,
|
||||||
operators: operators || [],
|
operators:
|
||||||
|
operators?.filter?.((operator) => {
|
||||||
|
return !operator?.visible || operator.visible(field);
|
||||||
|
}) || [],
|
||||||
};
|
};
|
||||||
if (nochildren) {
|
if (field.target && depth > 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (depth > 2) {
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
if (children?.length) {
|
if (children?.length) {
|
||||||
@ -104,16 +111,17 @@ export const useCollectionFilterOptions = (collectionName: string) => {
|
|||||||
}
|
}
|
||||||
if (nested) {
|
if (nested) {
|
||||||
const targetFields = getCollectionFields(field.target);
|
const targetFields = getCollectionFields(field.target);
|
||||||
const options = getOptions(targetFields, true);
|
const options = getOptions(targetFields).filter(Boolean);
|
||||||
option['children'] = option['children'] || [];
|
option['children'] = option['children'] || [];
|
||||||
option['children'].push(...options);
|
option['children'].push(...options);
|
||||||
}
|
}
|
||||||
return option;
|
return option;
|
||||||
};
|
};
|
||||||
const getOptions = (fields, nochildren = false) => {
|
const getOptions = (fields) => {
|
||||||
|
++depth;
|
||||||
const options = [];
|
const options = [];
|
||||||
fields.forEach((field) => {
|
fields.forEach((field) => {
|
||||||
const option = field2option(field, nochildren);
|
const option = field2option(field);
|
||||||
if (option) {
|
if (option) {
|
||||||
options.push(option);
|
options.push(option);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { useField, useFieldSchema } from '@formily/react';
|
import { ArrayItems } from '@formily/antd';
|
||||||
|
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useFormBlockContext } from '../../../block-provider';
|
import { useFormBlockContext } from '../../../block-provider';
|
||||||
|
import { useDetailsBlockContext } from '../../../block-provider/DetailsBlockProvider';
|
||||||
import { useCollection } from '../../../collection-manager';
|
import { useCollection } from '../../../collection-manager';
|
||||||
|
import { useCollectionFilterOptions, useSortFields } from '../../../collection-manager/action-hooks';
|
||||||
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
||||||
import { useSchemaTemplate } from '../../../schema-templates';
|
import { useSchemaTemplate } from '../../../schema-templates';
|
||||||
import { useDesignable } from '../../hooks';
|
import { useDesignable } from '../../hooks';
|
||||||
@ -53,3 +56,162 @@ export const ReadPrettyFormDesigner = () => {
|
|||||||
</GeneralSchemaDesigner>
|
</GeneralSchemaDesigner>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DetailsDesigner = () => {
|
||||||
|
const { name, title } = useCollection();
|
||||||
|
const template = useSchemaTemplate();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const field = useField();
|
||||||
|
const dataSource = useCollectionFilterOptions(name);
|
||||||
|
const { service } = useDetailsBlockContext();
|
||||||
|
const { dn } = useDesignable();
|
||||||
|
const sortFields = useSortFields(name);
|
||||||
|
const defaultFilter = fieldSchema?.['x-decorator-props']?.params?.filter || {};
|
||||||
|
const defaultSort = fieldSchema?.['x-decorator-props']?.params?.sort || [];
|
||||||
|
const sort = defaultSort?.map((item: string) => {
|
||||||
|
return item.startsWith('-')
|
||||||
|
? {
|
||||||
|
field: item.substring(1),
|
||||||
|
direction: 'desc',
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
field: item,
|
||||||
|
direction: 'asc',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<GeneralSchemaDesigner template={template} title={title || name}>
|
||||||
|
<SchemaSettings.ModalItem
|
||||||
|
title={t('Set the data scope')}
|
||||||
|
schema={
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
title: t('Set the data scope'),
|
||||||
|
properties: {
|
||||||
|
filter: {
|
||||||
|
default: defaultFilter,
|
||||||
|
// title: '数据范围',
|
||||||
|
enum: dataSource,
|
||||||
|
'x-component': 'Filter',
|
||||||
|
'x-component-props': {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as ISchema
|
||||||
|
}
|
||||||
|
onSubmit={({ filter }) => {
|
||||||
|
const params = field.decoratorProps.params || {};
|
||||||
|
params.filter = filter;
|
||||||
|
field.decoratorProps.params = params;
|
||||||
|
fieldSchema['x-decorator-props']['params'] = params;
|
||||||
|
service.run({ ...service.params?.[0], filter });
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema: {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
'x-decorator-props': fieldSchema['x-decorator-props'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaSettings.ModalItem
|
||||||
|
title={t('Set default sorting rules')}
|
||||||
|
components={{ ArrayItems }}
|
||||||
|
schema={
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
title: t('Set default sorting rules'),
|
||||||
|
properties: {
|
||||||
|
sort: {
|
||||||
|
type: 'array',
|
||||||
|
default: sort,
|
||||||
|
'x-component': 'ArrayItems',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
space: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Space',
|
||||||
|
properties: {
|
||||||
|
sort: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'ArrayItems.SortHandle',
|
||||||
|
},
|
||||||
|
field: {
|
||||||
|
type: 'string',
|
||||||
|
enum: sortFields,
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-component-props': {
|
||||||
|
style: {
|
||||||
|
width: 260,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
direction: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Radio.Group',
|
||||||
|
'x-component-props': {
|
||||||
|
optionType: 'button',
|
||||||
|
},
|
||||||
|
enum: [
|
||||||
|
{
|
||||||
|
label: t('ASC'),
|
||||||
|
value: 'asc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('DESC'),
|
||||||
|
value: 'desc',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'ArrayItems.Remove',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
add: {
|
||||||
|
type: 'void',
|
||||||
|
title: t('Add sort field'),
|
||||||
|
'x-component': 'ArrayItems.Addition',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as ISchema
|
||||||
|
}
|
||||||
|
onSubmit={({ sort }) => {
|
||||||
|
const sortArr = sort.map((item) => {
|
||||||
|
return item.direction === 'desc' ? `-${item.field}` : item.field;
|
||||||
|
});
|
||||||
|
const params = field.decoratorProps.params || {};
|
||||||
|
params.sort = sortArr;
|
||||||
|
field.decoratorProps.params = params;
|
||||||
|
fieldSchema['x-decorator-props']['params'] = params;
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema: {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
'x-decorator-props': fieldSchema['x-decorator-props'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
service.run({ ...service.params?.[0], sort: sortArr });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaSettings.Template componentName={'Details'} collectionName={name} />
|
||||||
|
<SchemaSettings.Divider />
|
||||||
|
<SchemaSettings.Remove
|
||||||
|
removeParentsIfNoChildren
|
||||||
|
breakRemoveOn={{
|
||||||
|
'x-component': 'Grid',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</GeneralSchemaDesigner>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Form as FormV2 } from './Form';
|
import { Form as FormV2 } from './Form';
|
||||||
import { FormDesigner, ReadPrettyFormDesigner } from './Form.Designer';
|
import { DetailsDesigner, FormDesigner, ReadPrettyFormDesigner } from './Form.Designer';
|
||||||
|
|
||||||
FormV2.Designer = FormDesigner;
|
FormV2.Designer = FormDesigner;
|
||||||
FormV2.ReadPrettyDesigner = ReadPrettyFormDesigner;
|
FormV2.ReadPrettyDesigner = ReadPrettyFormDesigner;
|
||||||
|
|
||||||
export { FormV2 };
|
export { FormV2, DetailsDesigner };
|
||||||
|
@ -22,6 +22,7 @@ export * from './kanban-v2';
|
|||||||
export * from './markdown';
|
export * from './markdown';
|
||||||
export * from './menu';
|
export * from './menu';
|
||||||
export * from './page';
|
export * from './page';
|
||||||
|
export * from './pagination';
|
||||||
export * from './password';
|
export * from './password';
|
||||||
export * from './radio';
|
export * from './radio';
|
||||||
export * from './record-picker';
|
export * from './record-picker';
|
||||||
@ -36,3 +37,4 @@ export * from './tree-select';
|
|||||||
export * from './upload';
|
export * from './upload';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
import { observer } from '@formily/react';
|
||||||
|
import { Pagination as AntdPagination } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import { useProps } from '../../hooks/useProps';
|
||||||
|
|
||||||
|
export const Pagination = observer((props: any) => {
|
||||||
|
const { hidden, ...others } = useProps(props);
|
||||||
|
if (hidden) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <AntdPagination {...others} />;
|
||||||
|
});
|
@ -23,6 +23,12 @@ export const BlockInitializers = {
|
|||||||
title: 'Form',
|
title: 'Form',
|
||||||
component: 'FormBlockInitializer',
|
component: 'FormBlockInitializer',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'details',
|
||||||
|
type: 'item',
|
||||||
|
title: 'Details',
|
||||||
|
component: 'DetailsBlockInitializer',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'calendar',
|
key: 'calendar',
|
||||||
type: 'item',
|
type: 'item',
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
// 表单的操作配置
|
||||||
|
export const DetailsActionInitializers = {
|
||||||
|
title: '{{t("Configure actions")}}',
|
||||||
|
icon: 'SettingOutlined',
|
||||||
|
style: {
|
||||||
|
marginLeft: 8,
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'itemGroup',
|
||||||
|
title: '{{t("Enable actions")}}',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: '{{t("Edit")}}',
|
||||||
|
component: 'UpdateActionInitializer',
|
||||||
|
schema: {
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-decorator': 'ACLActionProvider',
|
||||||
|
'x-component-props': {
|
||||||
|
type: 'primary',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'item',
|
||||||
|
title: '{{t("Delete")}}',
|
||||||
|
component: 'DestroyActionInitializer',
|
||||||
|
schema: {
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-decorator': 'ACLActionProvider',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
@ -6,7 +6,7 @@ import { gridRowColWrap } from '../utils';
|
|||||||
const useRelationFields = () => {
|
const useRelationFields = () => {
|
||||||
const { fields } = useCollection();
|
const { fields } = useCollection();
|
||||||
return fields
|
return fields
|
||||||
.filter((field) => field.interface === 'linkTo')
|
.filter((field) => ['linkTo', 'subTable'].includes(field.interface))
|
||||||
.map((field) => {
|
.map((field) => {
|
||||||
return {
|
return {
|
||||||
key: field.name,
|
key: field.name,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export * from './BlockInitializers';
|
export * from './BlockInitializers';
|
||||||
export * from './CalendarActionInitializers';
|
export * from './CalendarActionInitializers';
|
||||||
export * from './CreateFormBlockInitializers';
|
export * from './CreateFormBlockInitializers';
|
||||||
|
export * from './DetailsActionInitializers';
|
||||||
export * from './FormActionInitializers';
|
export * from './FormActionInitializers';
|
||||||
export * from './FormItemInitializers';
|
export * from './FormItemInitializers';
|
||||||
export * from './ReadPrettyFormActionInitializers';
|
export * from './ReadPrettyFormActionInitializers';
|
||||||
|
@ -12,6 +12,7 @@ import { useSchemaTemplateManager } from '../../schema-templates';
|
|||||||
import { SchemaInitializer } from '../SchemaInitializer';
|
import { SchemaInitializer } from '../SchemaInitializer';
|
||||||
import {
|
import {
|
||||||
createCalendarBlockSchema,
|
createCalendarBlockSchema,
|
||||||
|
createDetailsBlockSchema,
|
||||||
createFormBlockSchema,
|
createFormBlockSchema,
|
||||||
createKanbanBlockSchema,
|
createKanbanBlockSchema,
|
||||||
createReadPrettyFormBlockSchema,
|
createReadPrettyFormBlockSchema,
|
||||||
@ -125,6 +126,23 @@ export const FormBlockInitializer = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DetailsBlockInitializer = (props) => {
|
||||||
|
const { insert } = props;
|
||||||
|
const { getCollection } = useCollectionManager();
|
||||||
|
return (
|
||||||
|
<DataBlockInitializer
|
||||||
|
{...props}
|
||||||
|
icon={<TableOutlined />}
|
||||||
|
componentType={'Details'}
|
||||||
|
onCreateBlockSchema={async ({ item }) => {
|
||||||
|
const collection = getCollection(item.name);
|
||||||
|
const schema = createDetailsBlockSchema({ collection: item.name, rowKey: collection.filterTargetKey || 'id' });
|
||||||
|
insert(schema);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const CalendarBlockInitializer = (props) => {
|
export const CalendarBlockInitializer = (props) => {
|
||||||
const { insert } = props;
|
const { insert } = props;
|
||||||
const { getCollection } = useCollectionManager();
|
const { getCollection } = useCollectionManager();
|
||||||
|
@ -283,6 +283,76 @@ export const useCollectionDataSourceItems = (componentName) => {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createDetailsBlockSchema = (options) => {
|
||||||
|
const {
|
||||||
|
formItemInitializers = 'ReadPrettyFormItemInitializers',
|
||||||
|
actionInitializers = 'DetailsActionInitializers',
|
||||||
|
collection,
|
||||||
|
association,
|
||||||
|
resource,
|
||||||
|
template,
|
||||||
|
...others
|
||||||
|
} = options;
|
||||||
|
const resourceName = resource || association || collection;
|
||||||
|
const schema: ISchema = {
|
||||||
|
type: 'void',
|
||||||
|
'x-acl-action': `${resourceName}:get`,
|
||||||
|
'x-decorator': 'DetailsBlockProvider',
|
||||||
|
'x-decorator-props': {
|
||||||
|
resource: resourceName,
|
||||||
|
collection,
|
||||||
|
association,
|
||||||
|
readPretty: true,
|
||||||
|
action: 'list',
|
||||||
|
params: {
|
||||||
|
pageSize: 1,
|
||||||
|
},
|
||||||
|
// useParams: '{{ useParamsFromRecord }}',
|
||||||
|
...others,
|
||||||
|
},
|
||||||
|
'x-designer': 'DetailsDesigner',
|
||||||
|
'x-component': 'CardItem',
|
||||||
|
properties: {
|
||||||
|
[uid()]: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'FormV2',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
'x-component-props': {
|
||||||
|
useProps: '{{ useDetailsBlockProps }}',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
actions: {
|
||||||
|
type: 'void',
|
||||||
|
'x-initializer': actionInitializers,
|
||||||
|
'x-component': 'ActionBar',
|
||||||
|
'x-component-props': {
|
||||||
|
style: {
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: {},
|
||||||
|
},
|
||||||
|
grid: template || {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid',
|
||||||
|
'x-initializer': formItemInitializers,
|
||||||
|
properties: {},
|
||||||
|
},
|
||||||
|
pagination: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Pagination',
|
||||||
|
'x-component-props': {
|
||||||
|
useProps: '{{ useDetailsPaginationProps }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
console.log(JSON.stringify(schema, null, 2));
|
||||||
|
return schema;
|
||||||
|
};
|
||||||
|
|
||||||
export const createFormBlockSchema = (options) => {
|
export const createFormBlockSchema = (options) => {
|
||||||
const {
|
const {
|
||||||
formItemInitializers = 'FormItemInitializers',
|
formItemInitializers = 'FormItemInitializers',
|
||||||
|
Loading…
Reference in New Issue
Block a user