Skip to content

Commit

Permalink
wip:add layout switching
Browse files Browse the repository at this point in the history
  • Loading branch information
pomelo-nwu committed Feb 8, 2021
1 parent 1ec619b commit 4096a66
Show file tree
Hide file tree
Showing 9 changed files with 675 additions and 230 deletions.
22 changes: 0 additions & 22 deletions packages/graphin/docs/layout/save-render/demos/index.tsx

This file was deleted.

131 changes: 131 additions & 0 deletions packages/graphin/docs/layout/switching/demos/LayoutOptionsPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import * as React from 'react';
import { Option } from './network-layouts';
import { Slider, Switch, Row, Col, InputNumber, Select } from 'antd';

interface LayoutOptionsPanelProps {
options: Option[];
/** 布局类型 */
type: string;
/** 回调函数 */
handleChange: (type: string, options: unknown) => void;
}

const getAntdComponent = (option: Option, props) => {
const { onChange, value } = props;

const { min = 0, max = 500, component, key, enums, step = 1 } = option;

if (component === 'slider') {
return {
component: Slider,
props: {
min,
max,
onChange: val => {
onChange(key, val);
},
value,
step,
},
};
}
if (component === 'input') {
return {
component: InputNumber,
props: {
onChange: val => {
onChange(key, val);
},
value,
},
};
}
if (component === 'switch') {
return {
component: Switch,
props: {
onChange: checked => {
onChange(key, checked);
},
checked: value,
step: 0.01,
},
};
}
if (component === 'select') {
return {
component: Select,
props: {
options: enums,
onChange: checked => {
onChange(key, checked);
},
},
};
}
if (component === 'text') {
return {
component: () => <span>暂时无配置信息</span>,
props: {},
};
}
};

const dumpOptions: Option[] = [
{
key: 'work-in-progress',
component: 'text',
title: 'WIP',
defaultValue: '',
},
];
const LayoutOptionsPanel: React.FunctionComponent<LayoutOptionsPanelProps> = props => {
const { options: OPTIONS = dumpOptions, type, handleChange } = props;

const [options, setOptions] = React.useState({});
const defaultOptions = OPTIONS.map(c => {
const { key, defaultValue } = c;
return { [key]: defaultValue };
}).reduce((acc, curr) => {
return {
...acc,
...curr,
};
}, {});

const onChange = (key, val) => {
const newOptions = {
...defaultOptions,
...options,
[key]: val,
};
setOptions(newOptions);
if (handleChange) {
handleChange(type, newOptions);
}
};
console.log(options);

return (
<Row>
{OPTIONS.map(item => {
const { title, defaultValue, key } = item;
const value = options[key];
const { component: Component, props: ComponentProps } = getAntdComponent(item, {
onChange,
value: value === undefined ? defaultValue : value,
});
return (
<>
<Col span={8}>{title}</Col>
<Col span={16}>
<Component {...ComponentProps} />
</Col>
</>
);
})}
</Row>
);
};

export default LayoutOptionsPanel;
110 changes: 110 additions & 0 deletions packages/graphin/docs/layout/switching/demos/LayoutSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import * as React from 'react';
import { Row, Col, Divider, Dropdown, Menu, Card, Space } from 'antd';
import {
DownOutlined,
TrademarkCircleFilled,
ChromeFilled,
BranchesOutlined,
ApartmentOutlined,
AppstoreFilled,
CopyrightCircleFilled,
ShareAltOutlined,
} from '@ant-design/icons';
import LayoutOptionsPanel from './LayoutOptionsPanel';
import { Layouts } from './network-layouts';

const iconMapByType = {
'graphin-force': <ShareAltOutlined />,
random: <TrademarkCircleFilled />,
concentric: <ChromeFilled />,
circular: <BranchesOutlined />,
force: <AppstoreFilled />,
dagre: <ApartmentOutlined />,
grid: <CopyrightCircleFilled />,
radial: <ShareAltOutlined />,
gForce: <AppstoreFilled />,
mds: <AppstoreFilled />,
};

interface LayoutSelectorProps {
style?: React.CSSProperties;
/** 布局类型 */
type: string;

/** 布局切换的回调函数 */
onChange: ({ type, options }: { type?: string; options?: unknown }) => void;

/** 所有布局信息 */
layouts: Layouts;
}
const defaultStyle: React.CSSProperties = {
position: 'absolute',
top: 50,
right: 30,
boxShadow: `0 5px 5px -3px rgb(0 0 0 / 20%), 0 8px 10px 1px rgb(0 0 0 / 14%), 0 3px 14px 2px rgb(0 0 0 / 12%)`,
width: '300px',
height: '460px',
};

const LayoutMenu = ({ handleChange, description, layouts }) => {
const [visible, setVisible] = React.useState(false);
const handleVisibleChange = flag => {
setVisible(flag);
};
const handleChangeLayoutType = e => {
handleChange(e.key);
setVisible(false);
};
const menu = (
<Menu onClick={handleChangeLayoutType}>
{layouts.map(item => {
const { type, title } = item;
return (
<Menu.Item key={type}>
<Space>
{iconMapByType[type]} {title}
</Space>
</Menu.Item>
);
})}
</Menu>
);
return (
<Dropdown overlay={menu} onVisibleChange={handleVisibleChange} visible={visible}>
<Row style={{ paddingTop: '15px' }}>
<Col span={8}>布局类型</Col>
<Col span={16}> {description}</Col>
</Row>
</Dropdown>
);
};

const LayoutSelector: React.FunctionComponent<LayoutSelectorProps> = props => {
const { style, type, onChange, layouts } = props;
const matchLayout = layouts.find(item => item.type === type);
const matchOptions = matchLayout.options;

const { title } = matchLayout;
const handleChange = (selectedType, options = {}) => {
console.log(selectedType);
if (onChange) {
onChange({ type: selectedType, options });
}
};
const description = (
<Space>
{iconMapByType[type]} {title} <DownOutlined />
</Space>
);
return (
<Card title="布局配置" bordered={false} style={{ ...defaultStyle, ...style }} bodyStyle={{ padding: '0px 12px' }}>
<LayoutMenu handleChange={handleChange} description={description} layouts={layouts} />
<Divider style={{ margin: '15px 0px' }} />
<div style={{ height: '260px', overflow: 'scroll' }}>
<LayoutOptionsPanel options={matchOptions} type={type} key={type} handleChange={handleChange} />
</div>
</Card>
);
};

export default LayoutSelector;
Loading

0 comments on commit 4096a66

Please sign in to comment.