Browse Source

feat: schemaForm简易版

master
suanmei 5 years ago
committed by 拾邑
parent
commit
faf2d7dfa5
  1. 2
      packages/core/package.json
  2. 69
      packages/core/src/components/schema-form.tsx
  3. 161
      packages/core/src/components/setting.tsx
  4. 20
      packages/core/src/components/sidebar.tsx
  5. 45
      packages/core/src/data/cells.ts

2
packages/core/package.json

@ -30,7 +30,7 @@
"prepublishOnly": "node scripts/prepublishOnly.js",
"declare-type": "tsc --emitDeclarationOnly",
"build": "rollup -c & npm run declare-type",
"watch": "watch 'rollup -c' ./src"
"watch": "watch 'npm run build' ./src"
},
"bugs": {
"url": "https://github.com/suanmei/iMove/issues"

69
packages/core/src/components/schema-form.tsx

@ -0,0 +1,69 @@
import * as React from 'react';
import { Form, Input, InputNumber } from 'antd';
const { Item } = Form;
const labelCol = { span: 7 };
export interface SchemaFormProps {
schema: any;
data: any;
}
export interface SchemaFormState {
data: any;
}
class SchemaForm extends React.Component<SchemaFormProps, SchemaFormState> {
constructor(props: SchemaFormProps) {
super(props);
this.state = {
data: props.data,
};
}
changeValue = (e: React.ChangeEvent<HTMLInputElement>, key: string): void => {
const { data } = this.state;
const value = e.target.value.trim();
data[key] = value;
this.setState({ data });
};
changeNumValue = (value: number | undefined, key: string): void => {
const { data } = this.state;
data[key] = value;
this.setState({ data });
};
render(): JSX.Element {
const { data } = this.state;
const {
schema: { properties },
} = this.props;
return (
<Form labelCol={labelCol} initialValues={data}>
{Object.keys(properties).map((key) => (
<Item label={properties[key].title} name={properties[key].title}>
{properties[key].type === 'string' ? (
<Input
onChange={(e): void => {
this.changeValue(e, key);
}}
/>
) : (
<InputNumber
onChange={(value): void => {
this.changeNumValue(value, key);
}}
/>
)}
</Item>
))}
</Form>
);
}
}
export default SchemaForm;

161
packages/core/src/components/setting.tsx

@ -1,15 +1,18 @@
/** @jsx jsx */
import { useState } from 'react';
import { Component } from 'react';
import { jsx, css } from '@emotion/core';
import styled from '@emotion/styled';
import { Graph, Cell } from '@antv/x6';
import { Collapse, Form, Input } from 'antd';
import SchemaForm from './schema-form';
import 'antd/lib/form/style';
import 'antd/lib/input/style';
const { Panel } = Collapse;
const { Item } = Form;
const labelCol = { span: 7 };
const Header = styled.h3`
margin-bottom: 0;
padding-left: 20px;
@ -36,55 +39,123 @@ interface SettingProps {
graph: Graph;
}
const Setting = ({ graph }: SettingProps): JSX.Element => {
const [cell, setCell] = useState<Cell<any> | null>(null);
interface SettingState {
cell: Cell<any> | null;
}
class Setting extends Component<SettingProps, SettingState> {
constructor(props: SettingProps) {
super(props);
graph.on('selection:changed', () => {
const cells = graph.getSelectedCells();
setCell(cells.length > 0 ? cells[0] : null);
});
this.state = {
cell: null,
};
let cellType = '';
const { graph } = this.props;
graph.on('selection:changed', () => {
const cells = graph.getSelectedCells();
if (cells.length === 0) {
this.setState({ cell: null });
return;
}
if (cell) {
if (cell.isNode()) {
cellType = cell.data.type.toUpperCase();
const cell = cells[0];
if (cell.isEdge()) {
cell.data = {};
}
this.setState({ cell });
});
}
render(): JSX.Element {
const { graph } = this.props;
const { cell } = this.state;
let cellType = '';
if (cell) {
if (cell.isNode()) {
cellType = cell.data.type.toUpperCase();
} else {
cellType = 'EDGE';
}
} else {
cellType = 'EDGE';
cellType = 'FLOW';
}
} else {
cellType = 'FLOW';
}
return (
<div
css={css`
height: 100%;
overflow: auto;
border-left: 1px solid #ddd;
`}
>
<Header>{cellType}</Header>
{cell && cell.isNode() && ['decision', 'action'].includes(cell.data.type) && (
<SettingCollapse defaultActiveKey={['general']}>
<Panel header="General" key="general">
<Form initialValues={{ label: cell.data.label }}>
<Item label="名称" name="label">
<Input
onChange={(e): void => {
console.log(`first: ${cell.data.label}`);
cell.data.label = e.target.value.trim();
console.log(`then: ${cell.data.label}`);
graph.setCellData(cell, cell.data);
}}
/>
</Item>
</Form>
</Panel>
</SettingCollapse>
)}
</div>
);
};
return (
<div
css={css`
height: 100%;
overflow: auto;
border-left: 1px solid #ddd;
`}
>
<Header>{cellType}</Header>
{cell && !['start', 'end'].includes(cell.data.type) && (
<SettingCollapse
defaultActiveKey={['general', 'event', 'input', 'output']}
key={cell && cell.id ? cell.id : ''}
>
<Panel header="General" key="general">
<Form labelCol={labelCol} initialValues={{ label: cell.data.label }}>
<Item label="名称" name="label">
<Input
onChange={(e): void => {
cell.data.label = e.target.value.trim();
graph.setCellData(cell, cell.data);
}}
/>
</Item>
</Form>
</Panel>
{/* <Panel header="Event" key="event">
<Form
labelCol={labelCol}
initialValues={{ event: cell.data && cell.data.data && cell.data.data.event }}
>
<Item label="触发事件" name="event">
<Input
onChange={(e): void => {
if (!cell.data.data) {
cell.data.data = {};
}
cell.data.data.event = e.target.value.trim();
graph.setCellData(cell, cell.data);
}}
/>
</Item>
</Form>
</Panel> */}
{cell.data && cell.data.schema && (
<Panel header="Input" key="input">
<SchemaForm schema={cell.data.schema} data={cell.data.data} />
</Panel>
)}
<Panel header="Output" key="output">
<Form
labelCol={labelCol}
initialValues={{ event: cell.data && cell.data.data && cell.data.data.contextKey }}
>
<Item label="存储字段" name="contextKey">
<Input
onChange={(e): void => {
if (!cell.data.data) {
cell.data.data = {};
}
cell.data.data.contextKey = e.target.value.trim();
graph.setCellData(cell, cell.data);
}}
/>
</Item>
</Form>
</Panel>
</SettingCollapse>
)}
</div>
);
}
}
export default Setting;

20
packages/core/src/components/sidebar.tsx

@ -4,7 +4,7 @@ import { jsx, css } from '@emotion/core';
import styled from '@emotion/styled';
import { Graph } from '@antv/x6';
import { Collapse } from 'antd';
import { generals, DataItem } from '../data/cells';
import { generals, gists, DataItem } from '../data/cells';
import patchDnd from '../utils/patch-dnd';
import Cells from './cells';
import 'antd/lib/collapse/style';
@ -79,10 +79,14 @@ const CellWrapper = ({ data, children }: { data: DataItem; children: ReactNode }
const Sidebar = ({ graph }: SidebarProps): JSX.Element => {
const generalRef = useRef<HTMLDivElement>(null);
const gistRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const generalContainer = generalRef.current;
patchDnd(generalContainer, graph, generals);
const gistContainer = gistRef.current;
patchDnd(gistContainer, graph, gists);
});
return (
@ -93,7 +97,7 @@ const Sidebar = ({ graph }: SidebarProps): JSX.Element => {
border-right: 1px solid #ddd;
`}
>
<ToolCollapse defaultActiveKey={['general']}>
<ToolCollapse defaultActiveKey={['general', 'gist']}>
<ToolPanel header="General" key="general">
<div ref={generalRef}>
{generals.map((cell) => {
@ -106,6 +110,18 @@ const Sidebar = ({ graph }: SidebarProps): JSX.Element => {
})}
</div>
</ToolPanel>
<ToolPanel header="业务元件" key="gist">
<div ref={gistRef}>
{gists.map((cell) => {
const Cell = Cells[cell.type];
return (
<CellWrapper key={`${cell.type}${cell.label}`} data={cell}>
<Cell />
</CellWrapper>
);
})}
</div>
</ToolPanel>
</ToolCollapse>
</div>
);

45
packages/core/src/data/cells.ts

@ -12,6 +12,7 @@ export interface DataItem {
style: Style;
data?: any;
isEdge?: boolean;
schema?: any;
}
export const generals: DataItem[] = [
@ -25,30 +26,56 @@ export const generals: DataItem[] = [
},
},
{
label: 'Action',
type: 'action',
label: 'End Event',
type: 'end',
style: {
width: 48,
height: 30,
width: 20,
height: 20,
scale: 2,
},
},
];
export const gists: DataItem[] = [
{
label: 'End Event',
type: 'end',
label: '查询库存',
type: 'action',
style: {
width: 20,
height: 20,
width: 48,
height: 30,
scale: 2,
},
data: {
code: '',
dependencies: [],
},
schema: {
type: 'object',
properties: {
activity: {
type: 'string',
title: 'activity',
},
initAmount: {
type: 'string',
title: 'initAmount',
},
},
required: ['initAmount', 'activity'],
title: '参数',
},
},
{
label: 'Decision',
label: '判断是否登录',
type: 'decision',
style: {
width: 48,
height: 30,
scale: 2,
},
data: {
code: '',
dependencies: [],
},
},
];

Loading…
Cancel
Save