Skip to content

Commit

Permalink
Feat: added Route Consumer and Upstream (#304)
Browse files Browse the repository at this point in the history
* feat: added routes

* feat: added Consumer

* feat: added upstream

* feat: update SSL

* fix: routes
  • Loading branch information
LiteSun authored Jul 12, 2020
1 parent 853d5f3 commit f25b4c2
Show file tree
Hide file tree
Showing 81 changed files with 2,517 additions and 771 deletions.
77 changes: 72 additions & 5 deletions config/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,19 @@ const routes = [
{
path: '/ssl/list',
name: 'list',
component: './ssl/List',
component: './SSL/List',
hideInMenu: true,
},
{
name: 'create',
path: '/ssl/create',
component: './ssl/Create',
component: './SSL/Create',
hideInMenu: true,
},
{
name: 'edit',
path: '/ssl/:id/edit',
component: './SSL/Create',
hideInMenu: true,
},
],
Expand All @@ -52,18 +58,79 @@ const routes = [
path: '/routes/list',
name: 'list',
icon: 'BarsOutlined',
component: './Routes/List',
component: './Route/List',
hideInMenu: true,
},
{
path: '/routes/create',
name: 'create',
component: './Routes/Create',
component: './Route/Create',
hideInMenu: true,
},
{
path: '/routes/:rid/edit',
name: 'edit',
component: './Routes/Create',
component: './Route/Create',
hideInMenu: true,
},
],
},
{
name: 'consumer',
path: '/consumer',
icon: 'BarsOutlined',
routes: [
{
path: '/consumer',
redirect: '/Consumer/list',
},
{
path: '/consumer/list',
name: 'list',
icon: 'BarsOutlined',
component: './Consumer/List',
hideInMenu: true,
},
{
path: '/consumer/create',
name: 'create',
component: './Consumer/Create',
hideInMenu: true,
},
{
path: '/consumer/:id/edit',
name: 'edit',
component: './Consumer/Create',
hideInMenu: true,
},
],
},
{
name: 'upstream',
path: '/upstream',
icon: 'BarsOutlined',
routes: [
{
path: '/upstream',
redirect: '/Upstream/list',
},
{
path: '/upstream/list',
name: 'list',
icon: 'BarsOutlined',
component: './Upstream/List',
hideInMenu: true,
},
{
path: '/upstream/create',
name: 'create',
component: './Upstream/Create',
hideInMenu: true,
},
{
path: '/upstream/:id/edit',
name: 'edit',
component: './Upstream/Create',
hideInMenu: true,
},
],
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@
},
"husky": {
"hooks": {
"pre-commit": "npm run lint-staged",
"commit-msg": "node scripts/verifyCommit.js"
"pre-commit": "npm run lint-staged"
}
},
"lint-staged": {
Expand All @@ -48,8 +47,12 @@
"@ant-design/icons": "^4.2.1",
"@ant-design/pro-layout": "6.0.0-2",
"@ant-design/pro-table": "^2.3.3",
"@rjsf/antd": "^2.2.0",
"@rjsf/core": "^2.2.0",
"antd": "^4.3.3",
"classnames": "^2.2.6",
"dayjs": "^1.8.28",
"json-schema": "^0.2.5",
"lodash": "^4.17.15",
"moment": "^2.25.3",
"nzh": "^1.0.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { Row, Col, Button } from 'antd';

interface Props {
step: number;
lastStep: number;
onChange(nextStep: number): void;
redirect?: boolean;
withResultView?: boolean;
}

const style: CSSProperties = {
Expand All @@ -19,23 +20,23 @@ const style: CSSProperties = {
width: '100%',
};

const ActionBar: React.FC<Props> = ({ step, onChange, redirect }) => {
if (step > 3) {
const ActionBar: React.FC<Props> = ({ step, lastStep, onChange, withResultView }) => {
if (step > lastStep && !withResultView) {
onChange(lastStep);
return null;
}

return (
<div style={style}>
<Row gutter={10} justify="end">
<Col>
<Button type="primary" onClick={() => onChange(step - 1)} disabled={step === 0}>
<Button type="primary" onClick={() => onChange(step - 1)} disabled={step === 1}>
上一步
</Button>
</Col>
<Col>
<Button type="primary" onClick={() => onChange(step + 1)}>
{!redirect && (step < 3 ? '下一步' : '提交')}
{redirect && (step === 0 ? '下一步' : '提交')}
{step < lastStep ? '下一步' : '提交'}
</Button>
</Col>
</Row>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
import React from 'react';
import React, { Fragment } from 'react';
import { Drawer, Button } from 'antd';
import { useForm } from 'antd/es/form/util';
import { withTheme, FormProps } from '@rjsf/core';
import { Theme as AntDTheme } from '@rjsf/antd';
import { JSONSchema7 } from 'json-schema';

import PluginForm from '@/components/PluginForm';

interface Props extends Omit<PluginForm.Props, 'form'> {
interface Props {
name?: string;
initialData: any;
active?: boolean;
disabled?: boolean;
schema: JSONSchema7;
onActive(name: string): void;
onInactive(name: string): void;
onClose(): void;
onFinish(values: any): void;
}

const PluginDrawer: React.FC<Props> = ({
name,
active,
disabled,
schema,
initialData,
onActive,
onInactive,
onClose,
...rest
onFinish,
}) => {
const [form] = useForm();
const PluginForm = withTheme(AntDTheme);

if (!name) {
return null;
}

// NOTE: 用于作为 PluginForm 的引用
let form: any;

return (
<Drawer
title={`配置 ${name} 插件`}
Expand Down Expand Up @@ -55,7 +64,9 @@ const PluginDrawer: React.FC<Props> = ({
<Button
type="primary"
style={{ marginRight: 8, marginLeft: 8 }}
onClick={() => form.submit()}
onClick={() => {
form.submit();
}}
>
确认
</Button>
Expand All @@ -65,7 +76,22 @@ const PluginDrawer: React.FC<Props> = ({
)
}
>
<PluginForm name={name!} form={form} {...rest} disabled={disabled} />
<PluginForm
schema={schema}
liveValidate
disabled={disabled || !active}
formData={initialData}
showErrorList={false}
ref={(_form: FormProps<any>) => {
form = _form;
}}
onSubmit={({ formData }) => {
onFinish(formData);
}}
>
{/* NOTE: 留空,用于隐藏 Submit 按钮 */}
<Fragment />
</PluginForm>
</Drawer>
);
};
Expand Down
125 changes: 125 additions & 0 deletions src/components/PluginPage/PluginPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import React, { useState, useEffect } from 'react';
import { LinkOutlined, SettingOutlined } from '@ant-design/icons';
import { omit } from 'lodash';
import { JSONSchema7 } from 'json-schema';

import PanelSection from '@/components/PanelSection';

import PluginCard from './PluginCard';
import PluginDrawer from './PluginDrawer';
import { getList, fetchPluginSchema } from './service';
import { PLUGIN_MAPPER_SOURCE } from './data';

type Props = {
disabled?: boolean;
data: PluginPage.PluginData;
onChange?(data: PluginPage.PluginData): void;
};

const PluginPage: React.FC<Props> = ({ data = {}, disabled, onChange }) => {
const [pluginName, setPluginName] = useState<string | undefined>();
const [activeList, setActiveList] = useState<PluginPage.PluginProps[]>([]);
const [inactiveList, setInactiveList] = useState<PluginPage.PluginProps[]>([]);
const [schema, setSchema] = useState<JSONSchema7>();

const pluginList = [
{
title: '已启用',
list: activeList,
},
{
title: '未启用',
list: inactiveList,
},
];

useEffect(() => {
getList(data).then((props) => {
setActiveList(props.activeList);
setInactiveList(props.inactiveList);
});
}, []);

return (
<>
{pluginList.map(({ list, title }) => {
if (disabled && title === '未启用') {
return null;
}
return (
<PanelSection
title={title}
key={title}
style={{
display: 'grid',
gridTemplateColumns: 'repeat(3, 33.333%)',
gridRowGap: 10,
gridColumnGap: 10,
}}
>
{list.map(({ name }) => (
<PluginCard
name={name}
actions={[
<SettingOutlined
onClick={() => {
fetchPluginSchema(name).then((schemaData) => {
setSchema(schemaData);
setTimeout(() => {
setPluginName(name);
}, 300);
});
}}
/>,
<LinkOutlined
onClick={() =>
window.open(
`https://github.com/apache/incubator-apisix/blob/master/doc/plugins/${name}.md`,
)
}
/>,
]}
key={name}
/>
))}
</PanelSection>
);
})}

<PluginDrawer
name={pluginName}
initialData={pluginName ? data[pluginName] : {}}
active={Boolean(activeList.find((item) => item.name === pluginName))}
schema={schema!}
disabled={disabled}
onActive={(name) => {
// TODO: 需测试诸如 普罗米修斯 此类只需通过 {} 即可启用的插件
setActiveList(activeList.concat({ name, ...PLUGIN_MAPPER_SOURCE[name] }));
setInactiveList(inactiveList.filter((item) => item.name !== name));
}}
onInactive={(name) => {
if (!onChange) {
throw new Error('请提供 onChange 方法');
}
onChange(omit(Object.assign({}, data), name));
setInactiveList(inactiveList.concat({ name, ...PLUGIN_MAPPER_SOURCE[name] }));
setActiveList(activeList.filter((item) => item.name !== name));
setPluginName(undefined);
}}
onClose={() => setPluginName(undefined)}
onFinish={(value) => {
if (!pluginName) {
return;
}
if (!onChange) {
throw new Error('请提供 onChange 方法');
}
onChange(Object.assign({}, data, { [pluginName]: value }));
setPluginName(undefined);
}}
/>
</>
);
};

export default PluginPage;
Loading

0 comments on commit f25b4c2

Please sign in to comment.