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/10/10 09:20:44 UTC
[apisix-dashboard] 01/01: feat(Upstream): added components
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch feat-upstream
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
commit 1cb617272d7238dff44ef4cbcce60322b92f1174
Author: juzhiyuan <ju...@apache.org>
AuthorDate: Sat Oct 10 17:20:17 2020 +0800
feat(Upstream): added components
---
src/components/Upstream/UpstreamForm.tsx | 601 +++++++++++++++++++++++++++++
src/components/Upstream/index.ts | 1 +
src/pages/Upstream/components/Step1.tsx | 624 +------------------------------
3 files changed, 607 insertions(+), 619 deletions(-)
diff --git a/src/components/Upstream/UpstreamForm.tsx b/src/components/Upstream/UpstreamForm.tsx
new file mode 100644
index 0000000..fe6df1e
--- /dev/null
+++ b/src/components/Upstream/UpstreamForm.tsx
@@ -0,0 +1,601 @@
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
+import { Button, Col, Divider, Form, Input, InputNumber, Row, Select, Switch } from 'antd';
+import React, { useEffect, useState } from 'react';
+import { useIntl } from 'umi';
+
+import { PanelSection } from '@api7-dashboard/ui';
+
+enum Type {
+ roundrobin = 'roundrobin',
+ chash = 'chash',
+}
+
+enum HashOn {
+ vars = 'vars',
+ header = 'header',
+ cookie = 'cookie',
+ consumer = 'consumer',
+}
+
+enum HashKey {
+ remote_addr = 'remote_addr',
+ host = 'host',
+ uri = 'uri',
+ server_name = 'server_name',
+ server_addr = 'server_addr',
+ request_uri = 'request_uri',
+ query_string = 'query_string',
+ remote_port = 'remote_port',
+ hostname = 'hostname',
+ arg_id = 'arg_id',
+}
+
+type Upstream = {};
+
+type Props = {
+ upstream?: Upstream;
+ id?: string;
+};
+
+const timeoutFields = [
+ {
+ label: '连接超时',
+ name: ['timeout', 'connect'],
+ },
+ {
+ label: '发送超时',
+ name: ['timeout', 'send'],
+ },
+ {
+ label: '接收超时',
+ name: ['timeout', 'read'],
+ },
+];
+
+const UpstreamForm: React.FC<Props> = ({ id }) => {
+ const [readonly] = useState(false);
+ const [form] = Form.useForm();
+ const { formatMessage } = useIntl();
+
+ useEffect(() => {
+ // TODO: 获取 upstream 列表
+ }, []);
+
+ useEffect(() => {
+ if (id) {
+ // TODO: 获取 upstream、设置 readonly、填充数据
+ }
+ }, [id]);
+
+ const CHash = () => (
+ <>
+ <Form.Item label="Hash On" name="hash_on" rules={[{ required: true }]}>
+ <Select disabled={readonly}>
+ {Object.entries(HashOn).map(([label, value]) => (
+ <Select.Option value={value} key={value}>
+ {label}
+ </Select.Option>
+ ))}
+ </Select>
+ </Form.Item>
+ <Form.Item label="Key" name="key" rules={[{ required: true }]}>
+ <Select disabled={readonly}>
+ {Object.entries(HashKey).map(([label, value]) => (
+ <Select.Option value={value} key={value}>
+ {label}
+ </Select.Option>
+ ))}
+ </Select>
+ </Form.Item>
+ </>
+ );
+
+ const TimeUnit = () => <span style={{ margin: '0 8px' }}>ms</span>;
+ const NodeList = () => (
+ <Form.List name="nodes">
+ {(fields, { add, remove }) => (
+ <>
+ {fields.map((field, index) => (
+ <Form.Item
+ required
+ key={field.key}
+ label={index === 0 && '节点域名/IP'}
+ extra={
+ index === 0 && '使用域名时,默认解析本地 /etc/resolv.conf;权重为0则熔断该节点'
+ }
+ labelCol={{ span: index === 0 ? 3 : 0 }}
+ wrapperCol={{ offset: index === 0 ? 0 : 3 }}
+ >
+ <Row style={{ marginBottom: '10px' }} gutter={16}>
+ <Col span={5}>
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={[field.name, 'host']}
+ rules={[
+ {
+ required: true,
+ },
+ {
+ pattern: new RegExp(
+ /(^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])(\.(25[0-5]|1\d{2}|2[0-4]\d|[1-9]?\d)){3}$|^(?![0-9.]+$)([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+){0,}$)/,
+ 'g',
+ ),
+ },
+ ]}
+ >
+ <Input placeholder="域名/IP" disabled={readonly} />
+ </Form.Item>
+ </Col>
+ <Col span={2}>
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={[field.name, 'port']}
+ rules={[
+ {
+ required: true,
+ },
+ ]}
+ >
+ <InputNumber placeholder="端口号" disabled={readonly} min={1} max={65535} />
+ </Form.Item>
+ </Col>
+ <Col span={2}>
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={[field.name, 'weight']}
+ rules={[
+ {
+ required: true,
+ },
+ ]}
+ >
+ <InputNumber placeholder="权重" disabled={readonly} min={0} max={1000} />
+ </Form.Item>
+ </Col>
+ <Col
+ style={{
+ marginLeft: -10,
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ >
+ {!readonly && fields.length > 1 && (
+ <MinusCircleOutlined onClick={() => remove(field.name)} />
+ )}
+ </Col>
+ </Row>
+ </Form.Item>
+ ))}
+ {!readonly && (
+ <Form.Item wrapperCol={{ offset: 3 }}>
+ <Button type="dashed" onClick={add}>
+ <PlusOutlined />
+ 创建节点
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ );
+
+ const ActiveHealthCheck = () => (
+ <>
+ <Form.Item label="超时时间">
+ <Form.Item name={['checks', 'active', 'timeout']} noStyle>
+ <InputNumber disabled={readonly} />
+ </Form.Item>
+ <span style={{ margin: '0 8px' }}>s</span>
+ </Form.Item>
+ <Form.Item
+ label={formatMessage({ id: 'upstream.step.healthy.checks.active.http_path' })}
+ required
+ >
+ <Form.Item
+ name={['checks', 'active', 'http_path']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.http_path' }),
+ },
+ ]}
+ >
+ <Input
+ disabled={readonly}
+ placeholder={formatMessage({
+ id: 'upstream.step.input.healthy.checks.active.http_path',
+ })}
+ />
+ </Form.Item>
+ </Form.Item>
+ <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.active.host' })} required>
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={['checks', 'active', 'host']}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' }),
+ },
+ {
+ pattern: new RegExp(
+ /(^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])(\.(25[0-5]|1\d{2}|2[0-4]\d|[1-9]?\d)){3}$|^(?![0-9.]+$)([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+){0,}$)/,
+ 'g',
+ ),
+ message: formatMessage({ id: 'upstream.step.domain.name.or.ip.rule' }),
+ },
+ ]}
+ >
+ <Input
+ placeholder={formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' })}
+ disabled={readonly}
+ />
+ </Form.Item>
+ </Form.Item>
+
+ <Divider orientation="left" plain>
+ 健康状态
+ </Divider>
+ <Form.Item
+ label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })}
+ required
+ >
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={['checks', 'active', 'healthy', 'interval']}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'upstream.step.input.healthy.checks.active.interval',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} />
+ </Form.Item>
+ </Form.Item>
+ <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required>
+ <Form.Item
+ name={['checks', 'active', 'healthy', 'successes']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'upstream.step.input.healthy.checks.successes' }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+
+ <Divider orientation="left" plain>
+ 不健康状态
+ </Divider>
+ <Form.Item
+ label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })}
+ required
+ >
+ <Form.Item
+ name={['checks', 'active', 'unhealthy', 'interval']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'upstream.step.input.healthy.checks.active.interval',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} />
+ </Form.Item>
+ </Form.Item>
+ <Form.Item
+ label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })}
+ required
+ >
+ <Form.Item
+ name={['checks', 'active', 'unhealthy', 'http_failures']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ <Form.List name={['checks', 'active', 'req_headers']}>
+ {(fields, { add, remove }) => (
+ <>
+ {fields.map((field, index) => (
+ <Form.Item
+ key={field.key}
+ label={
+ index === 0 &&
+ formatMessage({ id: 'upstream.step.healthy.checks.active.req_headers' })
+ }
+ wrapperCol={{ offset: index === 0 ? 0 : 3 }}
+ >
+ <Row style={{ marginBottom: '10px' }} gutter={16}>
+ <Col span={10}>
+ <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
+ <Input
+ placeholder={formatMessage({
+ id: 'upstream.step.input.healthy.checks.active.req_headers',
+ })}
+ disabled={readonly}
+ />
+ </Form.Item>
+ </Col>
+ <Col
+ style={{
+ marginLeft: -10,
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ >
+ {!readonly && fields.length > 1 && (
+ <MinusCircleOutlined
+ style={{ margin: '0 8px' }}
+ onClick={() => {
+ remove(field.name);
+ }}
+ />
+ )}
+ </Col>
+ </Row>
+ </Form.Item>
+ ))}
+ {!readonly && (
+ <Form.Item wrapperCol={{ offset: 3 }}>
+ <Button type="dashed" onClick={() => add()}>
+ <PlusOutlined />
+ 创建请求头
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ </>
+ );
+ const InActiveHealthCheck = () => (
+ <>
+ <Divider orientation="left" plain>
+ 健康状态
+ </Divider>
+ <Form.List name={['checks', 'passive', 'healthy', 'http_statuses']}>
+ {(fields, { add, remove }) => (
+ <>
+ {fields.map((field, index) => (
+ <Form.Item
+ required
+ key={field.key}
+ label={
+ index === 0 &&
+ formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' })
+ }
+ labelCol={{ span: index === 0 ? 3 : 0 }}
+ wrapperCol={{ offset: index === 0 ? 0 : 3 }}
+ >
+ <Row style={{ marginBottom: '10px' }}>
+ <Col span={2}>
+ <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
+ <InputNumber disabled={readonly} />
+ </Form.Item>
+ </Col>
+ <Col
+ style={{
+ marginLeft: -10,
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ >
+ {!readonly && fields.length > 1 && (
+ <MinusCircleOutlined
+ onClick={() => {
+ remove(field.name);
+ }}
+ />
+ )}
+ </Col>
+ </Row>
+ </Form.Item>
+ ))}
+ {!readonly && (
+ <Form.Item wrapperCol={{ offset: 3 }}>
+ <Button type="dashed" onClick={() => add()}>
+ <PlusOutlined />
+ 创建状态码
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required>
+ <Form.Item
+ name={['checks', 'passive', 'healthy', 'successes']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'upstream.step.input.receive.timeout' }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+
+ <Divider orientation="left" plain>
+ 不健康状态
+ </Divider>
+ <Form.List name={['checks', 'passive', 'unhealthy', 'http_statuses']}>
+ {(fields, { add, remove }) => (
+ <>
+ {fields.map((field, index) => (
+ <Form.Item
+ required
+ key={field.key}
+ label={
+ index === 0 &&
+ formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' })
+ }
+ labelCol={{ span: index === 0 ? 3 : 0 }}
+ wrapperCol={{ offset: index === 0 ? 0 : 3 }}
+ >
+ <Row style={{ marginBottom: '10px' }}>
+ <Col span={2}>
+ <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
+ <InputNumber disabled={readonly} max={599} />
+ </Form.Item>
+ </Col>
+ <Col
+ style={{
+ marginLeft: -10,
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ >
+ {!readonly && fields.length > 1 && (
+ <MinusCircleOutlined
+ onClick={() => {
+ remove(field.name);
+ }}
+ />
+ )}
+ </Col>
+ </Row>
+ </Form.Item>
+ ))}
+ {!readonly && (
+ <Form.Item wrapperCol={{ offset: 3 }}>
+ <Button type="dashed" onClick={() => add()}>
+ <PlusOutlined />
+ 创建状态码
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ <Form.Item
+ label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })}
+ required
+ >
+ <Form.Item
+ name={['checks', 'passive', 'unhealthy', 'http_failures']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ <Form.Item
+ label={formatMessage({ id: 'upstream.step.healthy.checks.passive.tcp_failures' })}
+ required
+ >
+ <Form.Item
+ name={['checks', 'passive', 'unhealthy', 'tcp_failures']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'upstream.step.input.healthy.checks.passive.tcp_failures',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ </>
+ );
+
+ return (
+ <Form form={form} labelCol={{ span: 3 }}>
+ <Form.Item label="类型" name="type" rules={[{ required: true }]}>
+ <Select disabled={readonly}>
+ {Object.entries(Type).map(([label, value]) => {
+ return (
+ <Select.Option value={value} key={value}>
+ {label}
+ </Select.Option>
+ );
+ })}
+ </Select>
+ </Form.Item>
+ <Form.Item shouldUpdate noStyle>
+ {() => {
+ if (form.getFieldValue('type') === 'chash') {
+ return <CHash />;
+ }
+ return null;
+ }}
+ </Form.Item>
+
+ <NodeList />
+
+ {timeoutFields.map(({ label, name }) => (
+ <Form.Item label={label} required key={label}>
+ <Form.Item
+ name={name}
+ noStyle
+ rules={[
+ {
+ required: true,
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} />
+ </Form.Item>
+ <TimeUnit />
+ </Form.Item>
+ ))}
+
+ <PanelSection title="健康检查">
+ {[
+ {
+ label: '探活健康检查',
+ name: ['checks', 'active'],
+ component: <ActiveHealthCheck />,
+ },
+ {
+ label: '被动健康检查',
+ name: ['checks', 'passive'],
+ component: <InActiveHealthCheck />,
+ },
+ ].map(({ label, name, component }) => (
+ <>
+ <Form.Item label={label} name={name} valuePropName="checked" key={label}>
+ <Switch disabled={readonly} />
+ </Form.Item>
+ <Form.Item shouldUpdate noStyle>
+ {() => {
+ if (form.getFieldValue(name)) {
+ return component;
+ }
+ return null;
+ }}
+ </Form.Item>
+ </>
+ ))}
+ </PanelSection>
+ </Form>
+ );
+};
+
+export default UpstreamForm;
diff --git a/src/components/Upstream/index.ts b/src/components/Upstream/index.ts
new file mode 100644
index 0000000..677668e
--- /dev/null
+++ b/src/components/Upstream/index.ts
@@ -0,0 +1 @@
+export { default } from './UpstreamForm';
diff --git a/src/pages/Upstream/components/Step1.tsx b/src/pages/Upstream/components/Step1.tsx
index da70c23..e1a457c 100644
--- a/src/pages/Upstream/components/Step1.tsx
+++ b/src/pages/Upstream/components/Step1.tsx
@@ -15,19 +15,11 @@
* limitations under the License.
*/
import React from 'react';
-import { Form, Input, Row, Col, InputNumber, Select, Switch, notification } from 'antd';
+import { Form, Input } from 'antd';
import { FormInstance } from 'antd/lib/form';
import { useIntl } from 'umi';
-import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
-import Button from 'antd/es/button';
-import {
- FORM_ITEM_WITHOUT_LABEL,
- FORM_ITEM_LAYOUT,
- HASH_KEY_LIST,
- HASH_ON_LIST,
-} from '@/pages/Upstream/constants';
-import { PanelSection } from '@api7-dashboard/ui';
+import UpstreamForm from '@/components/Upstream';
type Props = {
form: FormInstance;
@@ -78,518 +70,11 @@ const initialValues = {
},
};
-const Step1: React.FC<Props> = ({ form, disabled, isActive, onChange, isPassive }) => {
+const Step1: React.FC<Props> = ({ form, disabled }) => {
const { formatMessage } = useIntl();
- const renderUpstreamMeta = () => (
- <Form.List name="nodes">
- {(fields, { add, remove }) => (
- <>
- {fields.map((field, index) => (
- <Form.Item
- required
- key={field.key}
- {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
- label={
- index === 0
- ? formatMessage({ id: 'upstream.step.backend.server.domain.or.ip' })
- : ''
- }
- extra={
- index === 0
- ? formatMessage({ id: 'upstream.step.domain.name.default.analysis' })
- : ''
- }
- >
- <Row style={{ marginBottom: '10px' }} gutter={16}>
- <Col span={5}>
- <Form.Item
- style={{ marginBottom: 0 }}
- name={[field.name, 'host']}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.domain.name.or.ip' }),
- },
- {
- pattern: new RegExp(
- /(^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])(\.(25[0-5]|1\d{2}|2[0-4]\d|[1-9]?\d)){3}$|^(?![0-9.]+$)([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+){0,}$)/,
- 'g',
- ),
- message: formatMessage({ id: 'upstream.step.domain.name.or.ip.rule' }),
- },
- ]}
- >
- <Input
- placeholder={formatMessage({ id: 'upstream.step.domain.name.or.ip' })}
- disabled={disabled}
- />
- </Form.Item>
- </Col>
- <Col span={3}>
- <Form.Item
- style={{ marginBottom: 0 }}
- name={[field.name, 'port']}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.port' }),
- },
- ]}
- >
- <InputNumber
- placeholder={formatMessage({ id: 'upstream.step.port' })}
- disabled={disabled}
- min={1}
- max={65535}
- />
- </Form.Item>
- </Col>
- <Col span={3}>
- <Form.Item
- style={{ marginBottom: 0 }}
- name={[field.name, 'weight']}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.weight' }),
- },
- ]}
- >
- <InputNumber
- placeholder={formatMessage({ id: 'upstream.step.weight' })}
- disabled={disabled}
- min={0}
- max={1000}
- />
- </Form.Item>
- </Col>
- <Col
- style={{
- marginLeft: -10,
- display: 'flex',
- alignItems: 'center',
- }}
- >
- {!disabled &&
- (fields.length > 1 ? (
- <MinusCircleOutlined
- style={{ margin: '0 8px' }}
- onClick={() => {
- remove(field.name);
- }}
- />
- ) : null)}
- </Col>
- </Row>
- </Form.Item>
- ))}
- {!disabled && (
- <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
- <Button
- type="dashed"
- onClick={() => {
- add();
- }}
- >
- <PlusOutlined />
- {formatMessage({ id: 'upstream.step.create' })}
- </Button>
- </Form.Item>
- )}
- </>
- )}
- </Form.List>
- );
-
- const renderTimeUnit = () => <span style={{ margin: '0 8px' }}>ms</span>;
-
- const handleActiveChange = () => {
- if (isActive) {
- onChange(!isActive, false);
- form.setFieldsValue({ ...form.getFieldsValue(), passive: false });
- return;
- }
- onChange(!isActive, isPassive);
- form.setFieldsValue({ ...form.getFieldsValue(), active: !isActive });
- };
- const handlePassiveChange = () => {
- if (!isActive) {
- notification.warning({
- message: formatMessage({ id: 'upstream.notificationMessage.enableHealthCheckFirst' }),
- });
- form.setFieldsValue({ ...form.getFieldsValue(), passive: isPassive });
- return;
- }
- onChange(isActive, !isPassive);
- form.setFieldsValue({ ...form.getFieldsValue(), passive: !isPassive });
- };
-
- const renderPassiveHealthyCheck = () => (
- <>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.healthy' })} />
- <Form.List name={['checks', 'passive', 'healthy', 'http_statuses']}>
- {(fields, { add, remove }) => (
- <>
- {fields.map((field, index) => (
- <Form.Item
- required
- key={field.key}
- {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
- label={
- index === 0
- ? formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' })
- : ''
- }
- >
- <Row style={{ marginBottom: '10px' }} gutter={16}>
- <Col span={4}>
- <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
- <InputNumber
- placeholder={formatMessage({
- id: 'upstream.step.input.healthy.checks.passive.http_statuses',
- })}
- disabled={disabled}
- />
- </Form.Item>
- </Col>
- <Col
- style={{
- marginLeft: -10,
- display: 'flex',
- alignItems: 'center',
- }}
- >
- {!disabled &&
- (fields.length > 1 ? (
- <MinusCircleOutlined
- style={{ margin: '0 8px' }}
- onClick={() => {
- remove(field.name);
- }}
- />
- ) : null)}
- </Col>
- </Row>
- </Form.Item>
- ))}
- {!disabled && (
- <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
- <Button
- type="dashed"
- onClick={() => {
- add();
- }}
- >
- <PlusOutlined />
- {formatMessage({ id: 'upstream.step.create' })}
- </Button>
- </Form.Item>
- )}
- </>
- )}
- </Form.List>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required>
- <Form.Item
- name={['checks', 'passive', 'healthy', 'successes']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.receive.timeout' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} min={1} max={254} />
- </Form.Item>
- </Form.Item>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.unhealthy' })} />
- <Form.List name={['checks', 'passive', 'unhealthy', 'http_statuses']}>
- {(fields, { add, remove }) => (
- <>
- {fields.map((field, index) => (
- <Form.Item
- required
- key={field.key}
- {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
- label={
- index === 0
- ? formatMessage({ id: 'upstream.step.healthy.checks.passive.http_statuses' })
- : ''
- }
- >
- <Row style={{ marginBottom: '10px' }} gutter={16}>
- <Col span={4}>
- <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
- <InputNumber
- placeholder={formatMessage({
- id: 'upstream.step.input.healthy.checks.passive.http_statuses',
- })}
- disabled={disabled}
- max={599}
- />
- </Form.Item>
- </Col>
- <Col
- style={{
- marginLeft: -10,
- display: 'flex',
- alignItems: 'center',
- }}
- >
- {!disabled &&
- (fields.length > 1 ? (
- <MinusCircleOutlined
- style={{ margin: '0 8px' }}
- onClick={() => {
- remove(field.name);
- }}
- />
- ) : null)}
- </Col>
- </Row>
- </Form.Item>
- ))}
- {!disabled && (
- <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
- <Button
- type="dashed"
- onClick={() => {
- add();
- }}
- >
- <PlusOutlined />
- {formatMessage({ id: 'upstream.step.create' })}
- </Button>
- </Form.Item>
- )}
- </>
- )}
- </Form.List>
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })}
- required
- >
- <Form.Item
- name={['checks', 'passive', 'unhealthy', 'http_failures']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} min={1} max={254} />
- </Form.Item>
- </Form.Item>
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.passive.tcp_failures' })}
- required
- >
- <Form.Item
- name={['checks', 'passive', 'unhealthy', 'tcp_failures']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({
- id: 'upstream.step.input.healthy.checks.passive.tcp_failures',
- }),
- },
- ]}
- >
- <InputNumber disabled={disabled} min={1} max={254} />
- </Form.Item>
- </Form.Item>
- </>
- );
-
- const renderActiveHealthyCheck = () => (
- <>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.active.timeout' })}>
- <Form.Item name={['checks', 'active', 'timeout']} noStyle>
- <InputNumber disabled={disabled} />
- </Form.Item>
- <span style={{ margin: '0 8px' }}>s</span>
- </Form.Item>
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.active.http_path' })}
- required
- >
- <Form.Item
- name={['checks', 'active', 'http_path']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.http_path' }),
- },
- ]}
- >
- <Input
- disabled={disabled}
- placeholder={formatMessage({
- id: 'upstream.step.input.healthy.checks.active.http_path',
- })}
- />
- </Form.Item>
- </Form.Item>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.active.host' })} required>
- <Form.Item
- style={{ marginBottom: 0 }}
- name={['checks', 'active', 'host']}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' }),
- },
- {
- pattern: new RegExp(
- /(^([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])(\.(25[0-5]|1\d{2}|2[0-4]\d|[1-9]?\d)){3}$|^(?![0-9.]+$)([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+){0,}$)/,
- 'g',
- ),
- message: formatMessage({ id: 'upstream.step.domain.name.or.ip.rule' }),
- },
- ]}
- >
- <Input
- placeholder={formatMessage({ id: 'upstream.step.input.healthy.checks.active.host' })}
- disabled={disabled}
- />
- </Form.Item>
- </Form.Item>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.healthy' })} />
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })}
- required
- >
- <Form.Item
- style={{ marginBottom: 0 }}
- name={['checks', 'active', 'healthy', 'interval']}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.interval' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} min={1} />
- </Form.Item>
- </Form.Item>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.successes' })} required>
- <Form.Item
- name={['checks', 'active', 'healthy', 'successes']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.healthy.checks.successes' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} min={1} max={254} />
- </Form.Item>
- </Form.Item>
- <Form.Item label={formatMessage({ id: 'upstream.step.healthy.checks.unhealthy' })} />
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.active.interval' })}
- required
- >
- <Form.Item
- name={['checks', 'active', 'unhealthy', 'interval']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.healthy.checks.active.interval' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} min={1} />
- </Form.Item>
- </Form.Item>
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.http_failures' })}
- required
- >
- <Form.Item
- name={['checks', 'active', 'unhealthy', 'http_failures']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.healthy.checks.http_failures' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} min={1} max={254} />
- </Form.Item>
- </Form.Item>
- <Form.List name={['checks', 'active', 'req_headers']}>
- {(fields, { add, remove }) => (
- <>
- {fields.map((field, index) => (
- <Form.Item
- key={field.key}
- {...(index === 0 ? FORM_ITEM_LAYOUT : FORM_ITEM_WITHOUT_LABEL)}
- label={
- index === 0
- ? formatMessage({ id: 'upstream.step.healthy.checks.active.req_headers' })
- : ''
- }
- >
- <Row style={{ marginBottom: '10px' }} gutter={16}>
- <Col span={10}>
- <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
- <Input
- placeholder={formatMessage({
- id: 'upstream.step.input.healthy.checks.active.req_headers',
- })}
- disabled={disabled}
- />
- </Form.Item>
- </Col>
- <Col
- style={{
- marginLeft: -10,
- display: 'flex',
- alignItems: 'center',
- }}
- >
- {!disabled &&
- (fields.length > 1 ? (
- <MinusCircleOutlined
- style={{ margin: '0 8px' }}
- onClick={() => {
- remove(field.name);
- }}
- />
- ) : null)}
- </Col>
- </Row>
- </Form.Item>
- ))}
- {!disabled && (
- <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
- <Button
- type="dashed"
- onClick={() => {
- add();
- }}
- >
- <PlusOutlined />
- {formatMessage({ id: 'upstream.step.create' })}
- </Button>
- </Form.Item>
- )}
- </>
- )}
- </Form.List>
- </>
- );
return (
- <Form {...FORM_ITEM_LAYOUT} form={form} initialValues={initialValues}>
+ <Form labelCol={{ span: 3 }} form={form} initialValues={initialValues}>
<Form.Item
label={formatMessage({ id: 'upstream.step.name' })}
name="name"
@@ -607,106 +92,7 @@ const Step1: React.FC<Props> = ({ form, disabled, isActive, onChange, isPassive
disabled={disabled}
/>
</Form.Item>
- <Form.Item
- label={formatMessage({ id: 'upstream.step.type' })}
- name="type"
- rules={[{ required: true }]}
- >
- <Select disabled={disabled}>
- <Select.Option value="roundrobin">roundrobin</Select.Option>
- <Select.Option value="chash">chash</Select.Option>
- </Select>
- </Form.Item>
- <Form.Item shouldUpdate noStyle>
- {() => {
- if (form.getFieldValue('type') === 'chash') {
- return (
- <>
- <Form.Item label="Hash On" name="hash_on" labelCol={{ span: 6 }} rules={[{ required: true }]}>
- <Select disabled={disabled}>
- {HASH_ON_LIST.map((item) => (
- <Select.Option value={item} key={item}>
- {item}
- </Select.Option>
- ))}
- </Select>
- </Form.Item>
- <Form.Item label="Key" name="key" labelCol={{ span: 6 }} rules={[{ required: true }]}>
- <Select disabled={disabled}>
- {HASH_KEY_LIST.map((item) => (
- <Select.Option value={item} key={item}>
- {item}
- </Select.Option>
- ))}
- </Select>
- </Form.Item>
- </>
- );
- }
- return null;
- }}
- </Form.Item>
- {renderUpstreamMeta()}
- <Form.Item label={formatMessage({ id: 'upstream.step.connect.timeout' })} required>
- <Form.Item
- name={['timeout', 'connect']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.connect.timeout' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} />
- </Form.Item>
- {renderTimeUnit()}
- </Form.Item>
- <Form.Item label={formatMessage({ id: 'upstream.step.send.timeout' })} required>
- <Form.Item
- name={['timeout', 'send']}
- noStyle
- rules={[
- { required: true, message: formatMessage({ id: 'upstream.step.input.send.timeout' }) },
- ]}
- >
- <InputNumber disabled={disabled} />
- </Form.Item>
- {renderTimeUnit()}
- </Form.Item>
- <Form.Item label={formatMessage({ id: 'upstream.step.receive.timeout' })} required>
- <Form.Item
- name={['timeout', 'read']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'upstream.step.input.receive.timeout' }),
- },
- ]}
- >
- <InputNumber disabled={disabled} />
- </Form.Item>
- {renderTimeUnit()}
- </Form.Item>
- <PanelSection title={formatMessage({ id: 'upstream.step.healthy.check' })}>
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.active' })}
- name="active"
- valuePropName="checked"
- >
- <Switch disabled={disabled} onChange={handleActiveChange} />
- </Form.Item>
- {isActive && renderActiveHealthyCheck()}
- <Form.Item
- label={formatMessage({ id: 'upstream.step.healthy.checks.passive' })}
- name="passive"
- valuePropName="checked"
- >
- <Switch disabled={disabled} onChange={handlePassiveChange} />
- </Form.Item>
- {isPassive && renderPassiveHealthyCheck()}
- </PanelSection>
+ <UpstreamForm />
</Form>
);
};