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 <[email protected]> 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> ); };
