You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/06/01 09:46:30 UTC
[incubator-apisix-dashboard] branch next updated: feat: add step2
page (#228)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch next
in repository https://gitbox.apache.org/repos/asf/incubator-apisix-dashboard.git
The following commit(s) were added to refs/heads/next by this push:
new 0b00d08 feat: add step2 page (#228)
0b00d08 is described below
commit 0b00d08cec6d09557ead7e045201b9c0c56aeb9e
Author: litesun <31...@users.noreply.github.com>
AuthorDate: Mon Jun 1 17:46:20 2020 +0800
feat: add step2 page (#228)
* feat: limit upload file
* feat: intercept default upload api request
* feat: limit upload file type
* fix: show file when parse SSL file fail
* feat: add search feature
* feat: format code
* fix: remove list item not work
* feat: remove relatedRouting
* feat: add routes step1 page
* feat: update route
* feat: format code
* feat: update
* feat: update
* feat: add checkbox rule
* feat: handle Modal close event
* feat: add routes step2 page
* feat: add routes step2 page
* feat: format code
* feat: add page skip
* feat: format code
* feat: format code
* Update Create.tsx
Co-authored-by: 琚致远 <ju...@apache.org>
---
src/pages/Routes/Create.tsx | 20 +++
src/pages/Routes/components/Step2/index.tsx | 258 ++++++++++++++++++++++++++++
src/pages/Routes/typing.d.ts | 25 +++
3 files changed, 303 insertions(+)
diff --git a/src/pages/Routes/Create.tsx b/src/pages/Routes/Create.tsx
index 872e4e6..bed1970 100644
--- a/src/pages/Routes/Create.tsx
+++ b/src/pages/Routes/Create.tsx
@@ -3,6 +3,7 @@ import { Card, Steps } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import Step1 from './components/Step1';
+import Step2 from './components/Step2';
import styles from './Create.less';
import CreateStep3 from './components/CreateStep3';
import ActionBar from './components/ActionBar';
@@ -19,6 +20,17 @@ const Create: React.FC = () => {
advancedMatchingRules: [],
});
+ const [step2Data, setStep2Data] = useState<RouteModule.Step2Data>({
+ backendProtocol: 'originalRequest',
+ backendAddressList: [{ host: '', port: 0, weight: 0 }],
+ upstream_header: [],
+ timeout: {
+ connect: 30000,
+ send: 30000,
+ read: 30000,
+ },
+ });
+
const [step3Data, setStep3Data] = useState<RouteModule.Step3Data>({
plugins: {
'limit-count': {
@@ -34,6 +46,7 @@ const Create: React.FC = () => {
const [stepHeader] = useState(['定义 API 请求', '定义 API 后端服务', '插件配置', '预览']);
const data = {
step1Data,
+ step2Data,
step3Data,
};
@@ -46,6 +59,13 @@ const Create: React.FC = () => {
onChange={(params: RouteModule.Step1Data) => setStep1Data({ ...step1Data, ...params })}
/>
);
+ case 1:
+ return (
+ <Step2
+ data={data}
+ onChange={(params: RouteModule.Step2Data) => setStep2Data({ ...step2Data, ...params })}
+ />
+ );
case 2:
return <CreateStep3 data={data} onChange={setStep3Data} />;
default:
diff --git a/src/pages/Routes/components/Step2/index.tsx b/src/pages/Routes/components/Step2/index.tsx
new file mode 100644
index 0000000..89e56bf
--- /dev/null
+++ b/src/pages/Routes/components/Step2/index.tsx
@@ -0,0 +1,258 @@
+import React, { useState } from 'react';
+import { Form, Row, Col, Input, Space, Button, Radio, InputNumber, Table, Modal } from 'antd';
+import { RadioChangeEvent } from 'antd/lib/radio';
+import PanelSection from '../PanelSection';
+import styles from '../../Create.less';
+
+const { TextArea } = Input;
+
+const DEFAULT_MODAL_DATA: RouteModule.UpstreamHeader = {
+ header_name: '',
+ header_value: '',
+ header_desc: '',
+ key: '',
+};
+
+const formItemLayout = {
+ labelCol: {
+ span: 6,
+ },
+ wrapperCol: {
+ span: 18,
+ },
+};
+
+const Step2: React.FC<RouteModule.Data> = ({ data, onChange }) => {
+ const { step2Data } = data;
+ const { upstream_header, backendAddressList, backendProtocol } = step2Data;
+ const [modalVisible, setModalVisible] = useState(false);
+ const [modalForm] = Form.useForm();
+ const [editModalData, setEditModalData] = useState<RouteModule.UpstreamHeader>(
+ DEFAULT_MODAL_DATA,
+ );
+ const [form] = Form.useForm();
+
+ const handleRemove = (key: string) => {
+ onChange({ upstream_header: upstream_header.filter((item) => item.key !== key) });
+ };
+
+ const columns = [
+ {
+ title: '请求头',
+ dataIndex: 'header_name',
+ key: 'header_name',
+ },
+ {
+ title: '值',
+ dataIndex: 'header_value',
+ key: 'header_value',
+ },
+ {
+ title: '描述',
+ dataIndex: 'header_desc',
+ key: 'header_desc',
+ },
+ {
+ title: '操作',
+ key: 'action',
+ render: (_: any, record: RouteModule.UpstreamHeader) => (
+ <Space size="middle">
+ <a
+ onClick={() => {
+ handleRemove(record.key);
+ }}
+ >
+ 移除
+ </a>
+ </Space>
+ ),
+ },
+ ];
+
+ const renderRequestRewrite = () => {
+ const onProtocolChange = (e: RadioChangeEvent) => {
+ onChange({ backendProtocol: e.target.value });
+ };
+
+ const addBackendAddress = () => {
+ onChange({
+ backendAddressList: backendAddressList.concat({ host: '', port: 0, weight: 0 }),
+ });
+ };
+
+ const renderBackendAddress = () =>
+ backendAddressList.map((item, index) => (
+ <Row key={`${item.host + index}`} style={{ marginBottom: '10px' }} gutter={[16, 16]}>
+ <Col span={12}>
+ <Input placeholder="HOST" />
+ </Col>
+ <Col span={4}>
+ <InputNumber placeholder="Port" />
+ </Col>
+ <Col span={4}>
+ <InputNumber placeholder="Weight" />
+ </Col>
+ <Col span={4}>
+ <Space>
+ {backendAddressList.length > 1 && (
+ <Button
+ type="primary"
+ danger
+ onClick={() => {
+ onChange({
+ backendAddressList: backendAddressList.filter(
+ (_, _index) => _index !== index,
+ ),
+ });
+ }}
+ >
+ 删除
+ </Button>
+ )}
+ </Space>
+ </Col>
+ </Row>
+ ));
+
+ return (
+ <PanelSection title="请求改写">
+ <Form
+ {...formItemLayout}
+ form={form}
+ layout="horizontal"
+ className={styles.stepForm}
+ initialValues={step2Data}
+ >
+ <Form.Item
+ label="协议"
+ name="protocol"
+ rules={[{ required: true, message: '请勾选协议' }]}
+ >
+ <Row>
+ <Radio.Group
+ onChange={onProtocolChange}
+ name="backendProtocol"
+ value={backendProtocol}
+ >
+ <Radio value="HTTP">HTTP</Radio>
+ <Radio value="HTTPS">HTTPS</Radio>
+ <Radio value="originalRequest">原始请求</Radio>
+ </Radio.Group>
+ </Row>
+ </Form.Item>
+ <Form.Item label="后端地址" rules={[{ required: true, message: '请输入后端地址' }]}>
+ {renderBackendAddress()}
+ <Button type="primary" onClick={addBackendAddress}>
+ 增加
+ </Button>
+ </Form.Item>
+ <Form.Item label="后端请求 Path">
+ <Row>
+ <Input />
+ </Row>
+ </Form.Item>
+ <Form.Item label="连接超时">
+ <InputNumber /> ms
+ </Form.Item>
+ <Form.Item label="发送超时">
+ <InputNumber /> ms
+ </Form.Item>
+ <Form.Item label="接收超时">
+ <InputNumber /> ms
+ </Form.Item>
+ </Form>
+ </PanelSection>
+ );
+ };
+
+ const renderHttpHeaderRewrite = () => {
+ const handleAdd = () => {
+ setModalVisible(true);
+ };
+ return (
+ <PanelSection title="HTTP 头改写">
+ <div>
+ <Button
+ onClick={handleAdd}
+ type="primary"
+ style={{
+ marginBottom: 16,
+ }}
+ >
+ 新增
+ </Button>
+ <Table key="table" bordered dataSource={upstream_header} columns={columns} />
+ </div>
+ </PanelSection>
+ );
+ };
+
+ const renderModal = () => {
+ const handleOk = () => {
+ modalForm.validateFields().then((value) => {
+ onChange({
+ upstream_header: upstream_header.concat({
+ ...(value as RouteModule.UpstreamHeader),
+ key: Math.random().toString(36).slice(2),
+ }),
+ });
+ setModalVisible(false);
+ });
+ };
+ const handleCancel = () => {
+ setModalVisible(false);
+ };
+
+ const handleClose = () => {
+ setEditModalData(DEFAULT_MODAL_DATA);
+ modalForm.resetFields();
+ };
+
+ return (
+ <Modal
+ title="新增"
+ centered
+ visible={modalVisible}
+ onOk={handleOk}
+ onCancel={handleCancel}
+ afterClose={handleClose}
+ destroyOnClose
+ >
+ <Form
+ form={modalForm}
+ labelCol={{ span: 4 }}
+ wrapperCol={{ span: 20 }}
+ initialValues={editModalData}
+ >
+ <Form.Item
+ label="请求头"
+ name="header_name"
+ rules={[{ required: true, message: '请输入请求头' }]}
+ >
+ <Input />
+ </Form.Item>
+ <Form.Item
+ label="值"
+ name="header_value"
+ rules={[{ required: true, message: '请输入值' }]}
+ >
+ <Input />
+ </Form.Item>
+ <Form.Item label="描述" name="upstream_header_desc">
+ <TextArea />
+ </Form.Item>
+ </Form>
+ </Modal>
+ );
+ };
+
+ return (
+ <>
+ {renderModal()}
+ {renderRequestRewrite()}
+ {renderHttpHeaderRewrite()}
+ </>
+ );
+};
+
+export default Step2;
diff --git a/src/pages/Routes/typing.d.ts b/src/pages/Routes/typing.d.ts
index f51d0a6..51fe10d 100644
--- a/src/pages/Routes/typing.d.ts
+++ b/src/pages/Routes/typing.d.ts
@@ -25,8 +25,33 @@ declare namespace RouteModule {
interface Data {
data: {
step1Data: Step1Data;
+ step2Data: Step2Data;
step3Data: Step3Data;
};
onChange(data: T): void;
}
+
+ type backendAddressItemProps = {
+ host: '';
+ port: number;
+ weight: number;
+ };
+
+ interface UpstreamHeader {
+ header_name: string;
+ header_value: string;
+ header_desc: string;
+ key: string;
+ }
+
+ type Step2Data = {
+ backendProtocol: 'HTTP' | 'HTTPS' | 'originalRequest';
+ backendAddressList: backendAddressItemProps[];
+ upstream_header: UpstreamHeader[];
+ timeout: {
+ connect: number;
+ send: number;
+ read: number;
+ };
+ };
}