feat(client): block schema template manager

This commit is contained in:
chenos 2022-04-06 15:33:09 +08:00
parent c183b98bfb
commit dd79cb05bf
7 changed files with 206 additions and 136 deletions

View File

@ -1,7 +1,9 @@
import { Field } from '@formily/core';
import { useField } from '@formily/react';
import { useRequest } from 'ahooks';
import template from 'lodash/template';
import React, { createContext, useContext } from 'react';
import { Link } from 'react-router-dom';
import { TableFieldResource, useAPIClient, useRecord } from '../';
import { CollectionProvider, useCollection, useCollectionManager } from '../collection-manager';
import { useRecordIndex } from '../record-provider';
@ -175,3 +177,11 @@ export const useParamsFromRecord = () => {
filterByTk: filterByTk,
};
};
export const RecordLink = (props) => {
const field = useField();
const record = useRecord();
const { title, to, ...others } = props;
const compiled = template(to || '');
return <Link {...others} to={compiled({ record: record || {} })}>{field.title}</Link>;
};

View File

@ -1,6 +1,6 @@
import React from 'react';
import { SchemaComponentOptions } from '../schema-component/core/SchemaComponentOptions';
import { useParamsFromRecord, useSourceIdFromParentRecord, useSourceIdFromRecord } from './BlockProvider';
import { RecordLink, useParamsFromRecord, useSourceIdFromParentRecord, useSourceIdFromRecord } from './BlockProvider';
import { CalendarBlockProvider, useCalendarBlockProps } from './CalendarBlockProvider';
import { FormBlockProvider, useFormBlockProps } from './FormBlockProvider';
import * as bp from './hooks';
@ -18,6 +18,7 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
TableSelectorProvider,
FormBlockProvider,
KanbanBlockProvider,
RecordLink,
}}
scope={{
...bp,

View File

@ -6,7 +6,7 @@ export const RecordIndexContext = createContext(null);
export const RecordProvider: React.FC<{ record: any }> = (props) => {
const { record, children } = props;
const __parent = useContext(RecordContext);
return <RecordContext.Provider value={{...record, __parent}}>{children}</RecordContext.Provider>;
return <RecordContext.Provider value={{ ...record, __parent }}>{children}</RecordContext.Provider>;
};
export const RecordIndexProvider: React.FC<{ index: any }> = (props) => {

View File

@ -365,7 +365,7 @@ export const ViewActionInitializer = (props) => {
properties: {
tab1: {
type: 'void',
title: '详情',
title: '{{t("Details")}}',
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
@ -407,11 +407,28 @@ export const UpdateActionInitializer = (props) => {
className: 'nb-action-popup',
},
properties: {
grid: {
tabs: {
type: 'void',
'x-component': 'Grid',
'x-initializer': 'RecordFormBlockInitializers',
properties: {},
'x-component': 'Tabs',
'x-component-props': {},
'x-initializer': 'TabPaneInitializers',
properties: {
tab1: {
type: 'void',
title: '{{t("Edit")}}',
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
properties: {
grid: {
type: 'void',
'x-component': 'Grid',
'x-initializer': 'RecordBlockInitializers',
properties: {},
},
},
},
},
},
},
},

View File

@ -1,55 +1,20 @@
import { Card, PageHeader as AntdPageHeader, Table } from 'antd';
import { PageHeader as AntdPageHeader } from 'antd';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { useCompile, useRequest } from '..';
import { CollectionManagerProvider } from '../collection-manager';
import { SchemaComponent } from '../schema-component';
import { uiSchemaTemplatesCollection } from './collections/uiSchemaTemplates';
import { uiSchemaTemplatesSchema } from './schemas/uiSchemaTemplates';
export const BlockTemplatePage = () => {
const { data, loading } = useRequest({
resource: 'uiSchemaTemplates',
action: 'list',
params: {
appends: ['collection'],
sort: ['-createdAt'],
},
});
const compile = useCompile();
const { t } = useTranslation();
return (
<div>
<AntdPageHeader ghost={false} title={t('Block templates')} />
<div style={{ margin: 24 }}>
<Card bordered={false}>
<Table
rowSelection={{
type: 'checkbox',
}}
columns={[
{
dataIndex: 'name',
title: t('Template name'),
render: (value) => <>{value || '未命名'}</>,
},
{
dataIndex: ['collection', 'title'],
title: t('Collection display name'),
render: (value) => compile(value),
},
{
dataIndex: 'componentName',
title: t('Block type'),
render: (value) => value,
},
{
dataIndex: 'actions',
title: t('Actions'),
render: (_, record) => <Link to={`/admin/block-templates/${record.key}`}></Link>,
},
]}
loading={loading}
dataSource={data?.data}
/>
</Card>
<CollectionManagerProvider collections={[uiSchemaTemplatesCollection]}>
<SchemaComponent schema={uiSchemaTemplatesSchema} />
</CollectionManagerProvider>
</div>
</div>
);

View File

@ -0,0 +1,20 @@
import { CollectionOptions } from '../../collection-manager';
export const uiSchemaTemplatesCollection: CollectionOptions = {
name: 'uiSchemaTemplates',
filterTargetKey: 'key',
targetKey: 'key',
fields: [
{
type: 'integer',
name: 'name',
interface: 'input',
uiSchema: {
title: '{{ t("Template name") }}',
type: 'number',
'x-component': 'Input',
required: true,
},
},
],
};

View File

@ -1,49 +1,26 @@
import { ISchema } from '@formily/react';
import { CollectionOptions } from '../../collection-manager';
const collection: CollectionOptions = {
name: 'uiSchemaTemplates',
filterTargetKey: 'name',
targetKey: 'name',
fields: [
{
type: 'integer',
name: 'name',
interface: 'input',
uiSchema: {
title: '{{ t("Template name") }}',
type: 'number',
'x-component': 'Input',
required: true,
},
},
],
};
import { uid } from '@formily/shared';
export const uiSchemaTemplatesSchema: ISchema = {
type: 'object',
properties: {
block1: {
[uid()]: {
type: 'void',
'x-collection': 'collections',
'x-decorator': 'ResourceActionProvider',
'x-decorator': 'TableBlockProvider',
'x-decorator-props': {
collection,
request: {
resource: 'uiSchemaTemplates',
action: 'list',
params: {
pageSize: 50,
filter: {},
// sort: ['sort'],
appends: [],
},
collection: 'uiSchemaTemplates',
resource: 'uiSchemaTemplates',
action: 'list',
params: {
pageSize: 20,
appends: ['collection'],
sort: ['-createdAt'],
},
rowKey: 'key',
showIndex: true,
dragSort: false,
},
// 'x-component': 'CollectionProvider',
// 'x-component-props': {
// collection,
// },
'x-component': 'CardItem',
properties: {
actions: {
type: 'void',
@ -54,97 +31,177 @@ export const uiSchemaTemplatesSchema: ISchema = {
},
},
properties: {
delete: {
type: 'void',
destroy: {
title: '{{ t("Delete") }}',
'x-action': 'destroy',
'x-component': 'Action',
'x-designer': 'Action.Designer',
'x-component-props': {
useAction: '{{ cm.useBulkDestroyActionAndRefreshCM }}',
icon: 'DeleteOutlined',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
},
},
},
create: {
type: 'void',
title: '{{ t("Add block template") }}',
'x-component': 'Action',
'x-component-props': {
type: 'primary',
useProps: '{{ useBulkDestroyActionProps }}',
},
},
},
},
table: {
type: 'void',
'x-uid': 'input',
'x-component': 'Table.Void',
[uid()]: {
type: 'array',
'x-component': 'TableV2',
'x-component-props': {
rowKey: 'name',
rowSelection: {
type: 'checkbox',
},
useDataSource: '{{ cm.useDataSourceFromRAC }}',
useProps: '{{ useTableBlockProps }}',
},
properties: {
column1: {
type: 'void',
'x-decorator': 'Table.Column.Decorator',
'x-component': 'Table.Column',
properties: {
title: {
'x-component': 'CollectionField',
'x-read-pretty': true,
},
},
},
column2: {
type: 'void',
'x-decorator': 'Table.Column.Decorator',
'x-component': 'Table.Column',
properties: {
name: {
type: 'string',
'x-component': 'CollectionField',
'x-read-pretty': true,
},
},
},
column3: {
actions: {
type: 'void',
title: '{{ t("Actions") }}',
'x-component': 'Table.Column',
'x-component': 'TableV2.Column',
properties: {
actions: {
type: 'void',
'x-decorator': 'DndContext',
'x-component': 'Space',
'x-component-props': {
split: '|',
},
properties: {
view: {
type: 'void',
title: '{{ t("Configure fields") }}',
'x-component': 'Action.Link',
'x-component-props': {},
title: '{{ t("View") }}',
'x-action': 'view',
'x-component': 'RecordLink',
'x-component-props': {
to: '/admin/block-templates/${record.key}',
},
},
delete: {
edit: {
type: 'void',
title: '{{ t("Delete") }}',
title: '{{ t("Edit") }}',
'x-action': 'update',
'x-component': 'Action.Link',
'x-component-props': {
openMode: 'drawer',
icon: 'EditOutlined',
},
properties: {
drawer: {
type: 'void',
title: '{{ t("Edit record") }}',
'x-component': 'Action.Container',
'x-component-props': {
className: 'nb-action-popup',
},
properties: {
form: {
type: 'void',
'x-decorator': 'FormBlockProvider',
'x-decorator-props': {
resource: 'uiSchemaTemplates',
collection: 'uiSchemaTemplates',
action: 'get',
useParams: '{{ useParamsFromRecord }}',
},
'x-component': 'CardItem',
properties: {
[uid()]: {
type: 'void',
'x-component': 'FormV2',
'x-component-props': {
useProps: '{{ useFormBlockProps }}',
},
properties: {
name: {
type: 'string',
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
'x-collection-field': 'uiSchemaTemplates.name',
required: true,
},
actions: {
type: 'void',
'x-component': 'ActionBar',
'x-component-props': {
layout: 'one-column',
style: {
marginTop: 24,
},
},
properties: {
submit: {
title: 'Submit',
'x-action': 'submit',
'x-component': 'Action',
'x-component-props': {
type: 'primary',
htmlType: 'submit',
useProps: '{{ useUpdateActionProps }}',
},
type: 'void',
},
},
},
},
},
},
},
},
},
},
},
destroy: {
title: '{{ t("Delete") }}',
'x-action': 'destroy',
'x-component': 'Action.Link',
'x-component-props': {
icon: 'DeleteOutlined',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
},
useAction: '{{ cm.useDestroyActionAndRefreshCM }}',
useProps: '{{ useDestroyActionProps }}',
},
},
},
},
},
},
column1: {
type: 'void',
'x-decorator': 'TableV2.Column.Decorator',
'x-component': 'TableV2.Column',
properties: {
name: {
type: 'string',
'x-collection-field': 'uiSchemaTemplates.name',
'x-component': 'CollectionField',
'x-read-pretty': true,
'x-component-props': {
ellipsis: true,
},
},
},
},
column2: {
type: 'void',
title: '{{t("Collection display name")}}',
'x-decorator': 'TableV2.Column.Decorator',
'x-component': 'TableV2.Column',
properties: {
'collection.title': {
type: 'string',
'x-collection-field': 'uiSchemaTemplates.collection',
'x-component': 'Input',
'x-read-pretty': true,
'x-component-props': {
ellipsis: true,
},
},
},
},
},
},
},