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:43 UTC
[apisix-dashboard] branch feat-upstream created (now 1cb6172)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a change to branch feat-upstream
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git.
at 1cb6172 feat(Upstream): added components
This branch includes the following new commits:
new 1cb6172 feat(Upstream): added components
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[apisix-dashboard] 01/01: feat(Upstream): added components
Posted by ju...@apache.org.
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>
);
};