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 2021/04/12 07:55:59 UTC
[apisix-dashboard] branch master updated: chore: refactor upstream
form module (#1726)
This is an automated email from the ASF dual-hosted git repository.
juzhiyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new eede893 chore: refactor upstream form module (#1726)
eede893 is described below
commit eede8939499a758fa8aa489eb34f49363b889bea
Author: 琚致远 <ju...@apache.org>
AuthorDate: Mon Apr 12 15:55:10 2021 +0800
chore: refactor upstream form module (#1726)
---
web/cypress/fixtures/export-route-dataset.json | 6 +-
web/src/components/Plugin/UI/plugin.tsx | 2 +-
web/src/components/Upstream/UpstreamForm.tsx | 761 +++------------------
web/src/components/Upstream/components/Nodes.tsx | 125 ++++
.../components/Upstream/components/PassHost.tsx | 88 +++
.../plugin.tsx => Upstream/components/Retries.tsx} | 41 +-
web/src/components/Upstream/components/Scheme.tsx | 62 ++
.../components/TimeUnit.tsx} | 29 +-
.../plugin.tsx => Upstream/components/Timeout.tsx} | 53 +-
web/src/components/Upstream/components/Type.tsx | 112 +++
.../Upstream/components/UpstreamSelector.tsx | 69 ++
.../components/active-check/Healthy/Interval.tsx | 54 ++
.../components/active-check/Healthy/Successes.tsx | 50 ++
.../components/active-check/Healthy/index.ts} | 31 +-
.../Upstream/components/active-check/Host.tsx | 61 ++
.../Upstream/components/active-check/HttpPath.tsx | 55 ++
.../components/active-check/Port.tsx} | 45 +-
.../components/active-check/ReqHeaders.tsx | 81 +++
.../components/active-check/Timeout.tsx} | 39 +-
.../components/active-check/Type.tsx} | 57 +-
.../active-check/Unhealthy/HttpFailures.tsx | 52 ++
.../active-check/Unhealthy/HttpStatuses.tsx | 74 ++
.../components/active-check/Unhealthy/Interval.tsx | 54 ++
.../active-check/Unhealthy/Timeouts.tsx} | 40 +-
.../components/active-check/Unhealthy/index.ts} | 35 +-
.../components/active-check/index.ts} | 42 +-
.../passive-check/Healthy/HttpStatuses.tsx | 76 ++
.../components/passive-check/Healthy/Successes.tsx | 49 ++
.../components/passive-check/Healthy/index.ts} | 31 +-
.../components/passive-check/Type.tsx} | 57 +-
.../passive-check/Unhealthy/HttpFailures.tsx | 52 ++
.../passive-check/Unhealthy/HttpStatuses.tsx | 75 ++
.../passive-check/Unhealthy/TcpFailures.tsx | 51 ++
.../passive-check/Unhealthy/Timeouts.tsx} | 40 +-
.../components/passive-check/Unhealthy/index.ts} | 35 +-
.../components/passive-check/index.ts} | 33 +-
web/src/components/Upstream/constant.ts | 56 +-
web/src/pages/Route/locales/zh-CN.ts | 2 +-
web/src/pages/Upstream/locales/en-US.ts | 6 +-
web/src/pages/Upstream/locales/zh-CN.ts | 8 +-
40 files changed, 1642 insertions(+), 1047 deletions(-)
diff --git a/web/cypress/fixtures/export-route-dataset.json b/web/cypress/fixtures/export-route-dataset.json
index 133971f..15f70fc 100644
--- a/web/cypress/fixtures/export-route-dataset.json
+++ b/web/cypress/fixtures/export-route-dataset.json
@@ -38,13 +38,13 @@
"weight": 1
}
],
- "retries": 1,
"timeout": {
"connect": 6,
"read": 6,
"send": 6
},
"type": "roundrobin",
+ "scheme": "http",
"pass_host": "pass"
}
}
@@ -90,13 +90,13 @@
"weight": 1
}
],
- "retries": 1,
"timeout": {
"connect": 6,
"read": 6,
"send": 6
},
"type": "roundrobin",
+ "scheme": "http",
"pass_host": "pass"
}
}
@@ -141,13 +141,13 @@
"weight": 1
}
],
- "retries": 1,
"timeout": {
"connect": 6,
"read": 6,
"send": 6
},
"type": "roundrobin",
+ "scheme": "http",
"pass_host": "pass"
}
}
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Plugin/UI/plugin.tsx
index f13b31a..620f98b 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Plugin/UI/plugin.tsx
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import React from 'react';
-import { FormInstance } from 'antd/es/form';
+import type { FormInstance } from 'antd/es/form';
import { Empty } from 'antd';
import { useIntl } from 'umi';
diff --git a/web/src/components/Upstream/UpstreamForm.tsx b/web/src/components/Upstream/UpstreamForm.tsx
index 2d54f75..7fade14 100644
--- a/web/src/components/Upstream/UpstreamForm.tsx
+++ b/web/src/components/Upstream/UpstreamForm.tsx
@@ -14,8 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
-import { Button, Col, Divider, Form, Input, InputNumber, Row, Select, Switch } from 'antd';
+import { Divider, Form, Switch } from 'antd';
import React, { useState, forwardRef, useImperativeHandle, useEffect } from 'react';
import { useIntl } from 'umi';
import type { FormInstance } from 'antd/es/form';
@@ -23,32 +22,15 @@ import type { FormInstance } from 'antd/es/form';
import { PanelSection } from '@api7-dashboard/ui';
import { transformRequest } from '@/pages/Upstream/transform';
import { DEFAULT_UPSTREAM } from './constant';
-
-enum Type {
- roundrobin = 'roundrobin',
- chash = 'chash',
- ewma = 'ewma',
-}
-
-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',
-}
+import PassiveCheck from './components/passive-check';
+import ActiveCheck from './components/active-check'
+import Nodes from './components/Nodes'
+import Scheme from './components/Scheme';
+import Timeout from './components/Timeout';
+import Type from './components/Type';
+import UpstreamSelector from './components/UpstreamSelector';
+import Retries from './components/Retries';
+import PassHost from './components/PassHost';
type Upstream = {
name?: string;
@@ -65,12 +47,6 @@ type Props = {
required?: boolean;
};
-const removeBtnStyle = {
- marginLeft: 20,
- display: 'flex',
- alignItems: 'center',
-};
-
const UpstreamForm: React.FC<Props> = forwardRef(
({ form, disabled, list = [], showSelector, required = true }, ref) => {
const { formatMessage } = useIntl();
@@ -130,487 +106,102 @@ const UpstreamForm: React.FC<Props> = forwardRef(
setReadonly(Boolean(upstream_id) || disabled);
}, [list]);
- 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' }}>s</span>;
- const NodeList = () => (
- <Form.List name="nodes">
- {(fields, { add, remove }) => (
- <>
- <Form.Item label={formatMessage({ id: 'page.upstream.form.item-label.node.domain.or.ip' })}>
- {fields.map((field, index) => (
- <Row style={{ marginBottom: 10 }} gutter={16} key={index}>
- <Col span={5}>
- <Form.Item
- style={{ marginBottom: 0 }}
- name={[field.name, 'host']}
- rules={[
- {
- required: true,
- message: formatMessage({
- id: 'page.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',
- ),
- },
- ]}
- >
- <Input
- placeholder={formatMessage({ id: 'page.upstream.step.domain.name.or.ip' })}
- disabled={readonly}
- />
- </Form.Item>
- </Col>
- <Col span={4}>
- <Form.Item
- style={{ marginBottom: 0 }}
- name={[field.name, 'port']}
- label={formatMessage({ id: 'page.upstream.step.port' })}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'page.upstream.step.input.port' }),
- },
- ]}
- >
- <InputNumber
- placeholder={formatMessage({ id: 'page.upstream.step.port' })}
- disabled={readonly}
- min={0}
- max={65535}
- />
- </Form.Item>
- </Col>
- <Col span={5}>
- <Form.Item
- style={{ marginBottom: 0 }}
- name={[field.name, 'weight']}
- label={formatMessage({ id: 'page.upstream.step.weight' })}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'page.upstream.step.input.weight' }),
- },
- ]}
- >
- <InputNumber
- placeholder={formatMessage({ id: 'page.upstream.step.weight' })}
- disabled={readonly}
- min={0}
- max={1000}
- />
- </Form.Item>
- </Col>
- <Col style={{ ...removeBtnStyle, marginLeft: -25 }}>
- {!readonly && (
- <MinusCircleOutlined onClick={() => remove(field.name)} />
- )}
- </Col>
- </Row>
- ))}
- </Form.Item>
- {!readonly && (
- <Form.Item wrapperCol={{ offset: 3 }}>
- <Button type="dashed" onClick={add}>
- <PlusOutlined />
- {formatMessage({ id: 'page.upstream.step.create.node' })}
- </Button>
- </Form.Item>
- )}
- </>
- )}
- </Form.List>
- );
const ActiveHealthCheck = () => (
- <>
- <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.timeout' })} tooltip={formatMessage({ id: 'page.upstream.checks.active.timeout.description' })}>
- <Form.Item name={['checks', 'active', 'timeout']} noStyle>
- <InputNumber disabled={readonly} min={0} />
- </Form.Item>
- <TimeUnit />
- </Form.Item>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeHost' })}
- required
- tooltip={formatMessage({ id: 'page.upstream.checks.active.host.description' })}
- >
- <Form.Item
- style={{ marginBottom: 0 }}
- name={['checks', 'active', 'host']}
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.activeHost' }),
- },
- {
- 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: 'page.upstream.step.domain.name.or.ip.rule' }),
- },
- ]}
- >
- <Input
- placeholder={formatMessage({
- id: 'page.upstream.step.input.healthyCheck.activeHost',
- })}
- disabled={readonly}
- />
- </Form.Item>
- </Form.Item>
-
- <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.activePort' })}>
- <Form.Item name={['checks', 'active', 'port']} noStyle>
- <InputNumber
- placeholder={formatMessage({
- id: 'page.upstream.step.input.healthyCheck.activePort',
- })}
- disabled={readonly}
- min={0}
- max={65535}
- />
- </Form.Item>
- </Form.Item>
-
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.http_path' })}
- required
- tooltip={formatMessage({
- id: 'page.upstream.step.input.healthyCheck.active.http_path',
- })}
- >
- <Form.Item
- name={['checks', 'active', 'http_path']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'page.upstream.checks.active.http_path.placeholder' }),
- },
- ]}
- >
- <Input
- disabled={readonly}
- placeholder={formatMessage({ id: 'page.upstream.checks.active.http_path.placeholder' })}
- />
- </Form.Item>
- </Form.Item>
+ <React.Fragment>
+ <ActiveCheck.Type readonly={readonly} />
+ <ActiveCheck.Timeout readonly={readonly} />
+ <ActiveCheck.Host readonly={readonly} />
+ <ActiveCheck.Port readonly={readonly} />
+ <ActiveCheck.HttpPath readonly={readonly} />
<Divider orientation="left" plain>
{formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.status' })}
</Divider>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })}
- required
- tooltip={formatMessage({ id: 'page.upstream.checks.active.healthy.interval.description' })}
- >
- <Form.Item
- noStyle
- style={{ marginBottom: 0 }}
- name={['checks', 'active', 'healthy', 'interval']}
- rules={[
- {
- required: true,
- message: formatMessage({
- id: 'page.upstream.step.input.healthyCheck.activeInterval',
- }),
- },
- ]}
- >
- <InputNumber disabled={readonly} min={1} />
- </Form.Item>
- <TimeUnit />
- </Form.Item>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })}
- required
- tooltip={formatMessage({ id: 'page.upstream.checks.active.healthy.successes.description' })}
- >
- <Form.Item
- name={['checks', 'active', 'healthy', 'successes']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }),
- },
- ]}
- >
- <InputNumber disabled={readonly} min={1} max={254} />
- </Form.Item>
- </Form.Item>
+
+ <ActiveCheck.Healthy.Interval readonly={readonly} />
+ <ActiveCheck.Healthy.Successes readonly={readonly} />
<Divider orientation="left" plain>
{formatMessage({ id: 'page.upstream.step.healthyCheck.unhealthyStatus' })}
</Divider>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })}
- required
- tooltip={formatMessage({ id: 'page.upstream.checks.active.unhealthy.interval.description' })}
- >
- <Form.Item
- name={['checks', 'active', 'unhealthy', 'interval']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({
- id: 'page.upstream.step.input.healthyCheck.activeInterval',
- }),
- },
- ]}
- >
- <InputNumber disabled={readonly} min={1} />
- </Form.Item>
- <TimeUnit />
- </Form.Item>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })}
- required
- tooltip={formatMessage({ id: 'page.upstream.checks.active.unhealthy.http_failures.description' })}
- >
- <Form.Item
- name={['checks', 'active', 'unhealthy', 'http_failures']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({
- id: 'page.upstream.step.input.healthyCheck.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: 'page.upstream.step.healthyCheck.active.req_headers' })
- }
- wrapperCol={{ offset: index === 0 ? 0 : 3 }}
- >
- <Row style={{ marginBottom: 10 }} gutter={16}>
- <Col span={10}>
- <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
- <Input
- placeholder={formatMessage({
- id: 'page.upstream.step.input.healthyCheck.active.req_headers',
- })}
- disabled={readonly}
- />
- </Form.Item>
- </Col>
- <Col style={removeBtnStyle}>
- {!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 />
- {formatMessage({
- id: 'page.upstream.step.healthyCheck.active.create.req_headers',
- })}
- </Button>
- </Form.Item>
- )}
- </>
- )}
- </Form.List>
- </>
+
+ <ActiveCheck.Unhealthy.Timeouts readonly={readonly} />
+ <ActiveCheck.Unhealthy.Interval readonly={readonly} />
+ <ActiveCheck.Unhealthy.HttpStatuses readonly={readonly} />
+ <ActiveCheck.Unhealthy.HttpFailures readonly={readonly} />
+
+ <Divider orientation="left" plain>Others</Divider>
+
+ <ActiveCheck.ReqHeaders readonly={readonly} />
+ </React.Fragment>
);
+
const InActiveHealthCheck = () => (
- <>
+ <React.Fragment>
+ <PassiveCheck.Type readonly={readonly} />
+
<Divider orientation="left" plain>
{formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.status' })}
</Divider>
- <Form.List name={['checks', 'passive', 'healthy', 'http_statuses']}>
- {(fields, { add, remove }) => (
- <>
- <Form.Item
- required
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' })}
- tooltip={formatMessage({ id: 'page.upstream.checks.passive.healthy.http_statuses.description' })}
- >
- {fields.map((field, index) => (
- <Row style={{ marginBottom: 10 }} key={index}>
- <Col span={2}>
- <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
- <InputNumber disabled={readonly} min={200} max={599} />
- </Form.Item>
- </Col>
- <Col style={removeBtnStyle}>
- {!readonly && (
- <MinusCircleOutlined
- onClick={() => {
- remove(field.name);
- }}
- />
- )}
- </Col>
- </Row>
- ))}
- </Form.Item>
- {!readonly && (
- <Form.Item wrapperCol={{ offset: 3 }}>
- <Button type="dashed" onClick={() => add()}>
- <PlusOutlined />
- {formatMessage({
- id: 'page.upstream.step.healthyCheck.passive.create.http_statuses',
- })}
- </Button>
- </Form.Item>
- )}
- </>
- )}
- </Form.List>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })}
- tooltip={formatMessage({ id: 'page.upstream.checks.passive.healthy.successes.description' })}
- required
- >
- <Form.Item
- name={['checks', 'passive', 'healthy', 'successes']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }),
- },
- ]}
- >
- <InputNumber disabled={readonly} min={1} max={254} />
- </Form.Item>
- </Form.Item>
+
+ <PassiveCheck.Healthy.HttpStatuses readonly={readonly} />
+ <PassiveCheck.Healthy.Successes readonly={readonly} />
<Divider orientation="left" plain>
{formatMessage({ id: 'page.upstream.step.healthyCheck.unhealthyStatus' })}
</Divider>
- <Form.List name={['checks', 'passive', 'unhealthy', 'http_statuses']}>
- {(fields, { add, remove }) => (
+
+ <PassiveCheck.Unhealthy.Timeouts readonly={readonly} />
+ <PassiveCheck.Unhealthy.TcpFailures readonly={readonly} />
+ <PassiveCheck.Unhealthy.HttpFailures readonly={readonly} />
+ <PassiveCheck.Unhealthy.HttpStatuses readonly={readonly} />
+ </React.Fragment>
+ );
+
+ const HealthCheckComponent = () => {
+ const options = [
+ {
+ label: formatMessage({ id: 'page.upstream.step.healthyCheck.active' }),
+ name: ['checks', 'active'],
+ component: (
<>
- <Form.Item
- required
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' })}
- tooltip={formatMessage({ id: 'page.upstream.checks.passive.unhealthy.http_statuses.description' })}
- >
- {fields.map((field, index) => (
- <Row style={{ marginBottom: 10 }} key={index}>
- <Col span={2}>
- <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
- <InputNumber disabled={readonly} min={200} max={599} />
- </Form.Item>
- </Col>
- <Col style={removeBtnStyle}>
- {!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 />
- {formatMessage({
- id: 'page.upstream.step.healthyCheck.passive.create.http_statuses',
- })}
- </Button>
- </Form.Item>
- )}
+ <ActiveHealthCheck />
+ <Divider orientation="left" plain />
</>
- )}
- </Form.List>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })}
- required
- tooltip={formatMessage({ id: 'page.upstream.checks.passive.unhealthy.http_failures.description' })}
- >
- <Form.Item
- name={['checks', 'passive', 'unhealthy', 'http_failures']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({
- id: 'page.upstream.step.input.healthyCheck.http_failures',
- }),
- },
- ]}
- >
- <InputNumber disabled={readonly} min={1} max={254} />
- </Form.Item>
- </Form.Item>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.tcp_failures' })}
- required
- tooltip={formatMessage({ id: 'page.upstream.checks.passive.unhealthy.tcp_failures.description' })}
+ ),
+ },
+ {
+ label: formatMessage({ id: 'page.upstream.step.healthyCheck.passive' }),
+ name: ['checks', 'passive'],
+ component: <InActiveHealthCheck />,
+ },
+ ]
+
+ return (
+ <PanelSection
+ title={formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.check' })}
>
- <Form.Item
- name={['checks', 'passive', 'unhealthy', 'tcp_failures']}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({
- id: 'page.upstream.step.input.healthyCheck.passive.tcp_failures',
- }),
- },
- ]}
- >
- <InputNumber disabled={readonly} min={1} max={254} />
- </Form.Item>
- </Form.Item>
- </>
- );
+ {options.map(({ label, name, component }) => (
+ <div key={label}>
+ <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>
+ </div>
+ ))}
+ </PanelSection>
+ )
+ }
+
return (
<Form
@@ -621,9 +212,10 @@ const UpstreamForm: React.FC<Props> = forwardRef(
}}
>
{showSelector && (
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.select.upstream' })}
- name="upstream_id"
+ <UpstreamSelector
+ list={list}
+ disabled={disabled}
+ required={required}
shouldUpdate={(prev, next) => {
setReadonly(Boolean(next.upstream_id));
if (prev.upstream_id !== next.upstream_id) {
@@ -637,173 +229,32 @@ const UpstreamForm: React.FC<Props> = forwardRef(
}
return prev.upstream_id !== next.upstream_id;
}}
- >
- <Select
- showSearch
- data-cy="upstream_selector"
- disabled={disabled}
- onChange={(upstream_id) => {
- setReadonly(Boolean(upstream_id));
- setHiddenForm(Boolean(upstream_id === 'None'));
- form.setFieldsValue(list.find((item) => item.id === upstream_id));
- if (upstream_id === '') {
- form.resetFields();
- form.setFieldsValue(DEFAULT_UPSTREAM);
- }
- }}
- filterOption={(input, item) =>
- item?.children.toLowerCase().includes(input.toLowerCase())
+ onChange={(upstream_id) => {
+ setReadonly(Boolean(upstream_id));
+ setHiddenForm(Boolean(upstream_id === 'None'));
+ form.setFieldsValue(list.find((item) => item.id === upstream_id));
+ if (upstream_id === '') {
+ form.resetFields();
+ form.setFieldsValue(DEFAULT_UPSTREAM);
}
- >
- {Boolean(!required) && <Select.Option value={'None'}>None</Select.Option>}
- {[
- {
- name: formatMessage({ id: 'page.upstream.step.select.upstream.select.option' }),
- id: '',
- },
- ...list,
- ].map((item) => (
- <Select.Option value={item.id!} key={item.id}>
- {item.name}
- </Select.Option>
- ))}
- </Select>
- </Form.Item>
+ }}
+ />
)}
{!hiddenForm && (
- <>
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.type' })}
- name="type"
- rules={[{ required: true }]}
- >
- <Select disabled={readonly}>
- {Object.entries(Type).map(([label, value]) => {
- return (
- <Select.Option value={value} key={value}>
- {formatMessage({ id: `page.upstream.type.${label}` })}
- </Select.Option>
- );
- })}
- </Select>
- </Form.Item>
- <Form.Item shouldUpdate noStyle>
- {() => {
- if (form.getFieldValue('type') === 'chash') {
- return <CHash />;
- }
- return null;
- }}
- </Form.Item>
- {NodeList()}
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.pass-host' })}
- name="pass_host"
- >
- <Select disabled={readonly}>
- <Select.Option value="pass">
- {formatMessage({ id: 'page.upstream.step.pass-host.pass' })}
- </Select.Option>
- <Select.Option value="node">
- {formatMessage({ id: 'page.upstream.step.pass-host.node' })}
- </Select.Option>
- <Select.Option value="rewrite" disabled>
- {formatMessage({ id: 'page.upstream.step.pass-host.rewrite' })}
- </Select.Option>
- </Select>
- </Form.Item>
-
- <Form.Item
- label={formatMessage({ id: 'page.upstream.retries' })}
- name="retries"
- >
- <InputNumber
- disabled={disabled}
- />
- </Form.Item>
+ <React.Fragment>
+ <Type form={form} readonly={readonly} />
+ <Nodes readonly={readonly} />
- <Form.Item
- noStyle
- shouldUpdate={(prev, next) => {
- return prev.pass_host !== next.pass_host;
- }}
- >
- {() => {
- if (form.getFieldValue('pass_host') === 'rewrite') {
- return (
- <Form.Item
- label={formatMessage({ id: 'page.upstream.step.pass-host.upstream_host' })}
- name="upstream_host"
- rules={[
- {
- required: true,
- message: "",
- },
- ]}
- >
- <Input disabled={readonly} placeholder={formatMessage({ id: `page.upstream.upstream_host.required` })} />
- </Form.Item>
- );
- }
- return null;
- }}
- </Form.Item>
-
- {timeoutFields.map(({ label, name, desc = '' }) => (
- <Form.Item label={label} required key={label} tooltip={desc}>
- <Form.Item
- name={name}
- noStyle
- rules={[
- {
- required: true,
- message: formatMessage({ id: `page.upstream.step.input.${name[1]}.timeout` }),
- },
- ]}
- >
- <InputNumber disabled={readonly} />
- </Form.Item>
- <TimeUnit />
- </Form.Item>
+ <PassHost form={form} readonly={readonly} />
+ <Retries readonly={readonly} />
+ <Scheme readonly={readonly} />
+ {timeoutFields.map((item, index) => (
+ <Timeout key={index} {...item} readonly={readonly} />
))}
- <PanelSection
- title={formatMessage({ id: 'page.upstream.step.healthyCheck.healthy.check' })}
- >
- {[
- {
- label: formatMessage({ id: 'page.upstream.step.healthyCheck.active' }),
- name: ['checks', 'active'],
- component: (
- <>
- <ActiveHealthCheck />
- <Divider orientation="left" plain />
- </>
- ),
- },
- {
- label: formatMessage({ id: 'page.upstream.step.healthyCheck.passive' }),
- name: ['checks', 'passive'],
- component: <InActiveHealthCheck />,
- },
- ].map(({ label, name, component }) => (
- <div key={label}>
- <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>
- </div>
- ))}
- </PanelSection>
- </>
+ <HealthCheckComponent />
+ </React.Fragment>
)}
</Form>
);
diff --git a/web/src/components/Upstream/components/Nodes.tsx b/web/src/components/Upstream/components/Nodes.tsx
new file mode 100644
index 0000000..2a92d48
--- /dev/null
+++ b/web/src/components/Upstream/components/Nodes.tsx
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Input, Row, Col, InputNumber, Button } from 'antd'
+import { useIntl } from 'umi'
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'
+
+import { removeBtnStyle } from '..'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.List name="nodes">
+ {(fields, { add, remove }) => (
+ <>
+ <Form.Item label={formatMessage({ id: 'page.upstream.form.item-label.node.domain.or.ip' })} style={{ marginBottom: 0 }}>
+ {fields.map((field, index) => (
+ <Row style={{ marginBottom: 10 }} gutter={16} key={index}>
+ <Col span={5}>
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={[field.name, 'host']}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'page.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',
+ ),
+ },
+ ]}
+ >
+ <Input
+ placeholder={formatMessage({ id: 'page.upstream.step.domain.name.or.ip' })}
+ disabled={readonly}
+ />
+ </Form.Item>
+ </Col>
+ <Col span={4}>
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={[field.name, 'port']}
+ label={formatMessage({ id: 'page.upstream.step.port' })}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'page.upstream.step.input.port' }),
+ },
+ ]}
+ >
+ <InputNumber
+ placeholder={formatMessage({ id: 'page.upstream.step.port' })}
+ disabled={readonly}
+ min={1}
+ max={65535}
+ />
+ </Form.Item>
+ </Col>
+ <Col span={5}>
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={[field.name, 'weight']}
+ label={formatMessage({ id: 'page.upstream.step.weight' })}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'page.upstream.step.input.weight' }),
+ },
+ ]}
+ >
+ <InputNumber
+ placeholder={formatMessage({ id: 'page.upstream.step.weight' })}
+ disabled={readonly}
+ min={0}
+ max={1000}
+ />
+ </Form.Item>
+ </Col>
+ <Col style={{ ...removeBtnStyle, marginLeft: -50 }}>
+ {!readonly && (
+ <MinusCircleOutlined onClick={() => remove(field.name)} />
+ )}
+ </Col>
+ </Row>
+ ))}
+ </Form.Item>
+ {!readonly && (
+ <Form.Item wrapperCol={{ offset: 3 }}>
+ <Button type="dashed" onClick={add}>
+ <PlusOutlined />
+ {formatMessage({ id: 'component.global.add' })}
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/PassHost.tsx b/web/src/components/Upstream/components/PassHost.tsx
new file mode 100644
index 0000000..6102076
--- /dev/null
+++ b/web/src/components/Upstream/components/PassHost.tsx
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Input, Select } from 'antd'
+import { useIntl } from 'umi'
+import type { FormInstance } from 'antd/lib/form'
+
+type Props = {
+ form: FormInstance
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ form, readonly }) => {
+ const { formatMessage } = useIntl()
+
+ const options = [
+ {
+ value: "pass",
+ label: formatMessage({ id: 'page.upstream.step.pass-host.pass' })
+ }, {
+ value: "node",
+ label: formatMessage({ id: 'page.upstream.step.pass-host.node' })
+ }, {
+ value: "rewrite",
+ label: formatMessage({ id: 'page.upstream.step.pass-host.rewrite' }),
+ disabled: true
+ }
+ ]
+
+ return (
+ <React.Fragment>
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.pass-host' })}
+ name="pass_host"
+ >
+ <Select disabled={readonly}>
+ {options.map(item => (
+ <Select.Option value={item.value} key={item.value} disabled={item.disabled}>
+ {item.label}
+ </Select.Option>
+ ))}
+ </Select>
+ </Form.Item>
+ <Form.Item
+ noStyle
+ shouldUpdate={(prev, next) => {
+ return prev.pass_host !== next.pass_host;
+ }}
+ >
+ {() => {
+ if (form.getFieldValue('pass_host') === 'rewrite') {
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.pass-host.upstream_host' })}
+ name="upstream_host"
+ rules={[
+ {
+ required: true,
+ message: "",
+ },
+ ]}
+ >
+ <Input disabled={readonly} placeholder={formatMessage({ id: `page.upstream.upstream_host.required` })} />
+ </Form.Item>
+ );
+ }
+ return null;
+ }}
+ </Form.Item>
+ </React.Fragment>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/Retries.tsx
similarity index 56%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/Retries.tsx
index f13b31a..a77ecef 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/Retries.tsx
@@ -14,31 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
-
-import BasicAuth from './basic-auth'
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+ readonly?: boolean
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.retries' })}
+ name="retries"
+ >
+ <InputNumber
+ disabled={readonly}
+ />
+ </Form.Item>
+ )
}
+
+export default Component
diff --git a/web/src/components/Upstream/components/Scheme.tsx b/web/src/components/Upstream/components/Scheme.tsx
new file mode 100644
index 0000000..840d5e6
--- /dev/null
+++ b/web/src/components/Upstream/components/Scheme.tsx
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Select } from 'antd'
+import { useIntl } from 'umi'
+
+const options = [
+ {
+ label: "HTTP",
+ value: "http"
+ }, {
+ label: "HTTPs",
+ value: "https"
+ }, {
+ label: "gRPC",
+ value: "grpc"
+ }, {
+ label: "gRPCs",
+ value: "grpcs"
+ }
+]
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.scheme' })}
+ name="scheme"
+ rules={[{ required: true }]}
+ >
+ <Select disabled={readonly}>
+ {options.map(item => {
+ return (
+ <Select.Option value={item.value} key={item.value}>
+ {item.label}
+ </Select.Option>
+ );
+ })}
+ </Select>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/TimeUnit.tsx
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/TimeUnit.tsx
index f13b31a..292c0cf 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/TimeUnit.tsx
@@ -14,31 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import React from 'react'
-import BasicAuth from './basic-auth'
+const TimeUnit = () => <span style={{ margin: '0 8px' }}>s</span>;
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
-}
-
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
-}
+export default TimeUnit
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/Timeout.tsx
similarity index 52%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/Timeout.tsx
index f13b31a..059b63a 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/Timeout.tsx
@@ -14,31 +14,36 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
-import BasicAuth from './basic-auth'
+import TimeUnit from './TimeUnit'
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+const Component: React.FC<{
+ label: string;
+ desc: string;
+ name: string[];
+ readonly?: boolean;
+}> = ({ label, desc, name, readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item label={label} required tooltip={desc}>
+ <Form.Item
+ name={name}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: `page.upstream.step.input.${name[1]}.timeout` }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} />
+ </Form.Item>
+ <TimeUnit />
+ </Form.Item>
+ )
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
-}
+export default Component
diff --git a/web/src/components/Upstream/components/Type.tsx b/web/src/components/Upstream/components/Type.tsx
new file mode 100644
index 0000000..0a7ce25
--- /dev/null
+++ b/web/src/components/Upstream/components/Type.tsx
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Select } from 'antd'
+import { useIntl } from 'umi'
+import type { FormInstance } from 'antd/es/form'
+
+enum Type {
+ roundrobin = 'roundrobin',
+ chash = 'chash',
+ ewma = 'ewma',
+ // TODO: new type
+ // least_conn = 'least_conn'
+}
+
+enum HashOn {
+ vars = 'vars',
+ header = 'header',
+ cookie = 'cookie',
+ consumer = 'consumer',
+ // TODO: new hash_on key
+ // vars_combinations = 'vars_combinations'
+}
+
+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 Props = {
+ readonly?: boolean
+ form: FormInstance
+}
+
+const CHash: React.FC<Pick<Props, 'readonly'>> = ({ readonly }) => (
+ <>
+ <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 Component: React.FC<Props> = ({ readonly, form }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <React.Fragment>
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.type' })}
+ name="type"
+ rules={[{ required: true }]}
+ >
+ <Select disabled={readonly}>
+ {Object.entries(Type).map(([label, value]) => {
+ return (
+ <Select.Option value={value} key={value}>
+ {formatMessage({ id: `page.upstream.type.${label}` })}
+ </Select.Option>
+ );
+ })}
+ </Select>
+ </Form.Item>
+ <Form.Item shouldUpdate noStyle>
+ {() => {
+ if (form.getFieldValue('type') === 'chash') {
+ return <CHash readonly={readonly} />;
+ }
+ return null;
+ }}
+ </Form.Item>
+ </React.Fragment>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/UpstreamSelector.tsx b/web/src/components/Upstream/components/UpstreamSelector.tsx
new file mode 100644
index 0000000..1f8b225
--- /dev/null
+++ b/web/src/components/Upstream/components/UpstreamSelector.tsx
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Select } from 'antd'
+import { useIntl } from 'umi'
+
+type Upstream = {
+ name?: string;
+ id?: string;
+};
+
+type Props = {
+ list?: Upstream[];
+ disabled?: boolean;
+ required?: boolean;
+ shouldUpdate: (prev: any, next: any) => void;
+ onChange: (id: string) => void
+}
+
+const Component: React.FC<Props> = ({ shouldUpdate, onChange, list = [], disabled, required }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.select.upstream' })}
+ name="upstream_id"
+ shouldUpdate={shouldUpdate as any}
+ >
+ <Select
+ showSearch
+ data-cy="upstream_selector"
+ disabled={disabled}
+ onChange={onChange}
+ filterOption={(input, item) =>
+ item?.children.toLowerCase().includes(input.toLowerCase())
+ }
+ >
+ {Boolean(!required) && <Select.Option value={'None'}>None</Select.Option>}
+ {[
+ {
+ name: formatMessage({ id: 'page.upstream.step.select.upstream.select.option' }),
+ id: '',
+ },
+ ...list,
+ ].map((item) => (
+ <Select.Option value={item.id!} key={item.id}>
+ {item.name}
+ </Select.Option>
+ ))}
+ </Select>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/active-check/Healthy/Interval.tsx b/web/src/components/Upstream/components/active-check/Healthy/Interval.tsx
new file mode 100644
index 0000000..47ca56e
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/Healthy/Interval.tsx
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
+import TimeUnit from '../../TimeUnit'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })}
+ required
+ tooltip={formatMessage({ id: 'page.upstream.checks.active.healthy.interval.description' })}
+ >
+ <Form.Item
+ noStyle
+ style={{ marginBottom: 0 }}
+ name={['checks', 'active', 'healthy', 'interval']}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.activeInterval',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} />
+ </Form.Item>
+ <TimeUnit />
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/active-check/Healthy/Successes.tsx b/web/src/components/Upstream/components/active-check/Healthy/Successes.tsx
new file mode 100644
index 0000000..84fbccf
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/Healthy/Successes.tsx
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Form, InputNumber } from 'antd'
+import React from 'react'
+import { useIntl } from 'umi'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })}
+ required
+ tooltip={formatMessage({ id: 'page.upstream.checks.active.healthy.successes.description' })}
+ >
+ <Form.Item
+ name={['checks', 'active', 'healthy', 'successes']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/active-check/Healthy/index.ts
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/active-check/Healthy/index.ts
index f13b31a..cef27c1 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/active-check/Healthy/index.ts
@@ -14,31 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import Interval from './Interval'
+import Successes from './Successes'
-import BasicAuth from './basic-auth'
-
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
-}
-
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+export default {
+ Interval,
+ Successes
}
diff --git a/web/src/components/Upstream/components/active-check/Host.tsx b/web/src/components/Upstream/components/active-check/Host.tsx
new file mode 100644
index 0000000..871000b
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/Host.tsx
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Input } from 'antd'
+import { useIntl } from 'umi'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeHost' })}
+ required
+ tooltip={formatMessage({ id: 'page.upstream.checks.active.host.description' })}
+ >
+ <Form.Item
+ style={{ marginBottom: 0 }}
+ name={['checks', 'active', 'host']}
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.activeHost' }),
+ },
+ {
+ 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: 'page.upstream.step.domain.name.or.ip.rule' }),
+ },
+ ]}
+ >
+ <Input
+ placeholder={formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.activeHost',
+ })}
+ disabled={readonly}
+ />
+ </Form.Item>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/active-check/HttpPath.tsx b/web/src/components/Upstream/components/active-check/HttpPath.tsx
new file mode 100644
index 0000000..4914a49
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/HttpPath.tsx
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Input } from 'antd'
+import { useIntl } from 'umi'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.http_path' })}
+ required
+ tooltip={formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.active.http_path',
+ })}
+ >
+ <Form.Item
+ name={['checks', 'active', 'http_path']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'page.upstream.checks.active.http_path.placeholder' }),
+ },
+ ]}
+ >
+ <Input
+ disabled={readonly}
+ placeholder={formatMessage({ id: 'page.upstream.checks.active.http_path.placeholder' })}
+ />
+ </Form.Item>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/active-check/Port.tsx
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/active-check/Port.tsx
index f13b31a..3d04e07 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/active-check/Port.tsx
@@ -14,31 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
-
-import BasicAuth from './basic-auth'
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+ readonly?: boolean
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.activePort' })}>
+ <Form.Item name={['checks', 'active', 'port']} noStyle>
+ <InputNumber
+ placeholder={formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.activePort',
+ })}
+ disabled={readonly}
+ min={1}
+ max={65535}
+ />
+ </Form.Item>
+ </Form.Item>
+ )
}
+
+export default Component
diff --git a/web/src/components/Upstream/components/active-check/ReqHeaders.tsx b/web/src/components/Upstream/components/active-check/ReqHeaders.tsx
new file mode 100644
index 0000000..25fb8d6
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/ReqHeaders.tsx
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Row, Col, Input, Button } from 'antd'
+import { useIntl } from 'umi'
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'
+
+import { removeBtnStyle } from '../../constant'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.List name={['checks', 'active', 'req_headers']}>
+ {(fields, { add, remove }) => (
+ <>
+ <Form.Item
+ label={
+ formatMessage({ id: 'page.upstream.step.healthyCheck.active.req_headers' })
+ }
+ style={{ marginBottom: 0 }}
+ >
+ {fields.map((field, index) => (
+ <Row style={{ marginBottom: 10 }} gutter={12} key={index}>
+ <Col span={5}>
+ <Form.Item noStyle name={[field.name]}>
+ <Input
+ placeholder={formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.active.req_headers',
+ })}
+ disabled={readonly}
+ />
+ </Form.Item>
+ </Col>
+ <Col style={{ ...removeBtnStyle, marginLeft: 0 }}>
+ {!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 />
+ {formatMessage({
+ id: 'component.global.add',
+ })}
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/active-check/Timeout.tsx
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/active-check/Timeout.tsx
index f13b31a..4d294b7 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/active-check/Timeout.tsx
@@ -14,31 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
-
-import BasicAuth from './basic-auth'
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
+import TimeUnit from '../TimeUnit'
type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+ readonly?: boolean
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
+const ActiveCheckTimeoutComponent: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+ return (
+ <Form.Item label={formatMessage({ id: 'page.upstream.step.healthyCheck.active.timeout' })} tooltip={formatMessage({ id: 'page.upstream.checks.active.timeout.description' })}>
+ <Form.Item name={['checks', 'active', 'timeout']} noStyle>
+ <InputNumber disabled={readonly} min={0} />
+ </Form.Item>
+ <TimeUnit />
+ </Form.Item>
+ )
}
+
+export default ActiveCheckTimeoutComponent
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/active-check/Type.tsx
similarity index 52%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/active-check/Type.tsx
index f13b31a..e8b95c6 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/active-check/Type.tsx
@@ -14,31 +14,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
-
-import BasicAuth from './basic-auth'
+import React from 'react'
+import { Form, Select } from 'antd'
type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+ readonly?: boolean
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
+const options = [
+ {
+ label: "HTTP",
+ value: "http"
+ }, {
+ label: "HTTPs",
+ value: "https"
+ }, {
+ label: "TCP",
+ value: "tcp"
}
+]
+
+const ActiveCheckTypeComponent: React.FC<Props> = ({ readonly }) => {
+ return (
+ <Form.Item
+ label="Type"
+ name={['checks', 'active', 'type']}
+ rules={[{ required: true }]}
+ >
+ <Select disabled={readonly}>
+ {options.map(item => {
+ return (
+ <Select.Option value={item.value} key={item.value}>
+ {item.label}
+ </Select.Option>
+ );
+ })}
+ </Select>
+ </Form.Item>
+ )
}
+
+export default ActiveCheckTypeComponent
diff --git a/web/src/components/Upstream/components/active-check/Unhealthy/HttpFailures.tsx b/web/src/components/Upstream/components/active-check/Unhealthy/HttpFailures.tsx
new file mode 100644
index 0000000..dbd4118
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/Unhealthy/HttpFailures.tsx
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Form, InputNumber } from 'antd'
+import React from 'react'
+import { useIntl } from 'umi'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })}
+ required
+ tooltip={formatMessage({ id: 'page.upstream.checks.active.unhealthy.http_failures.description' })}
+ >
+ <Form.Item
+ name={['checks', 'active', 'unhealthy', 'http_failures']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.http_failures',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/active-check/Unhealthy/HttpStatuses.tsx b/web/src/components/Upstream/components/active-check/Unhealthy/HttpStatuses.tsx
new file mode 100644
index 0000000..0cdad52
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/Unhealthy/HttpStatuses.tsx
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Row, Col, Button, InputNumber } from 'antd'
+import { useIntl } from 'umi'
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'
+
+import { removeBtnStyle } from '@/components/Upstream'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.List name={['checks', 'active', 'unhealthy', 'http_statuses']}>
+ {(fields, { add, remove }) => (
+ <>
+ <Form.Item
+ required
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' })}
+ style={{ marginBottom: 0 }}
+ >
+ {fields.map((field, index) => (
+ <Row style={{ marginBottom: 10 }} key={index}>
+ <Col span={2}>
+ <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
+ <InputNumber disabled={readonly} min={200} max={599} />
+ </Form.Item>
+ </Col>
+ <Col style={removeBtnStyle}>
+ {!readonly && (
+ <MinusCircleOutlined
+ onClick={() => {
+ remove(field.name);
+ }}
+ />
+ )}
+ </Col>
+ </Row>
+ ))}
+ </Form.Item>
+ {!readonly && (
+ <Form.Item wrapperCol={{ offset: 3 }}>
+ <Button type="dashed" onClick={() => add()}>
+ <PlusOutlined />
+ {formatMessage({
+ id: 'component.global.add',
+ })}
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ )
+}
+export default Component
diff --git a/web/src/components/Upstream/components/active-check/Unhealthy/Interval.tsx b/web/src/components/Upstream/components/active-check/Unhealthy/Interval.tsx
new file mode 100644
index 0000000..8052808
--- /dev/null
+++ b/web/src/components/Upstream/components/active-check/Unhealthy/Interval.tsx
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
+
+import TimeUnit from '../../TimeUnit'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.activeInterval' })}
+ required
+ tooltip={formatMessage({ id: 'page.upstream.checks.active.unhealthy.interval.description' })}
+ >
+ <Form.Item
+ name={['checks', 'active', 'unhealthy', 'interval']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.activeInterval',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} />
+ </Form.Item>
+ <TimeUnit />
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/active-check/Unhealthy/Timeouts.tsx
similarity index 56%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/active-check/Unhealthy/Timeouts.tsx
index f13b31a..2f5af5f 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/active-check/Unhealthy/Timeouts.tsx
@@ -14,31 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
-
-import BasicAuth from './basic-auth'
+import React from 'react'
+import { Form, InputNumber } from 'antd'
type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+ readonly?: boolean
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
+const Component: React.FC<Props> = ({ readonly }) => (
+ <Form.Item
+ label="Timeouts"
+ required
+ >
+ <Form.Item
+ name={['checks', 'active', 'unhealthy', 'timeouts']}
+ noStyle
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+)
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
-}
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/active-check/Unhealthy/index.ts
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/active-check/Unhealthy/index.ts
index f13b31a..bb9b869 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/active-check/Unhealthy/index.ts
@@ -14,31 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import Timeouts from './Timeouts'
+import Interval from './Interval'
+import HttpStatuses from './HttpStatuses'
+import HttpFailures from './HttpFailures'
-import BasicAuth from './basic-auth'
-
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
-}
-
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+export default {
+ Timeouts,
+ Interval,
+ HttpStatuses,
+ HttpFailures
}
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/active-check/index.ts
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/active-check/index.ts
index f13b31a..efc3046 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/active-check/index.ts
@@ -14,31 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import Unhealthy from './Unhealthy'
+import Healthy from './Healthy'
-import BasicAuth from './basic-auth'
+import Timeout from './Timeout'
+import Type from './Type'
+import ReqHeaders from './ReqHeaders'
+import Host from './Host'
+import Port from './Port'
+import HttpPath from './HttpPath'
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
-}
-
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+export default {
+ Unhealthy,
+ Healthy,
+ Timeout,
+ Type,
+ ReqHeaders,
+ Host,
+ Port,
+ HttpPath
}
diff --git a/web/src/components/Upstream/components/passive-check/Healthy/HttpStatuses.tsx b/web/src/components/Upstream/components/passive-check/Healthy/HttpStatuses.tsx
new file mode 100644
index 0000000..f1b06d2
--- /dev/null
+++ b/web/src/components/Upstream/components/passive-check/Healthy/HttpStatuses.tsx
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Row, Col, InputNumber, Button } from 'antd'
+import { useIntl } from 'umi'
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'
+
+import { removeBtnStyle } from '@/components/Upstream/constant'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.List name={['checks', 'passive', 'healthy', 'http_statuses']}>
+ {(fields, { add, remove }) => (
+ <>
+ <Form.Item
+ required
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' })}
+ tooltip={formatMessage({ id: 'page.upstream.checks.passive.healthy.http_statuses.description' })}
+ style={{ marginBottom: 0 }}
+ >
+ {fields.map((field, index) => (
+ <Row style={{ marginBottom: 10 }} key={index}>
+ <Col span={2}>
+ <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
+ <InputNumber disabled={readonly} min={200} max={599} />
+ </Form.Item>
+ </Col>
+ <Col style={removeBtnStyle}>
+ {!readonly && (
+ <MinusCircleOutlined
+ onClick={() => {
+ remove(field.name);
+ }}
+ />
+ )}
+ </Col>
+ </Row>
+ ))}
+ </Form.Item>
+ {!readonly && (
+ <Form.Item wrapperCol={{ offset: 3 }}>
+ <Button type="dashed" onClick={() => add()}>
+ <PlusOutlined />
+ {formatMessage({
+ id: 'component.global.add',
+ })}
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/passive-check/Healthy/Successes.tsx b/web/src/components/Upstream/components/passive-check/Healthy/Successes.tsx
new file mode 100644
index 0000000..2ee3590
--- /dev/null
+++ b/web/src/components/Upstream/components/passive-check/Healthy/Successes.tsx
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.successes' })}
+ tooltip={formatMessage({ id: 'page.upstream.checks.passive.healthy.successes.description' })}
+ required
+ >
+ <Form.Item
+ name={['checks', 'passive', 'healthy', 'successes']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({ id: 'page.upstream.step.input.healthyCheck.successes' }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/passive-check/Healthy/index.ts
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/passive-check/Healthy/index.ts
index f13b31a..737fbf4 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/passive-check/Healthy/index.ts
@@ -14,31 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import HttpStatuses from './HttpStatuses'
+import Successes from './Successes'
-import BasicAuth from './basic-auth'
-
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
-}
-
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+export default {
+ HttpStatuses,
+ Successes
}
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/passive-check/Type.tsx
similarity index 51%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/passive-check/Type.tsx
index f13b31a..d3401ee 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/passive-check/Type.tsx
@@ -14,31 +14,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
-
-import BasicAuth from './basic-auth'
+import React from 'react'
+import { Form, Select } from 'antd'
type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+ readonly?: boolean
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
+const PassiveCheckTypeComponent: React.FC<Props> = ({ readonly }) => {
+ const options = [
+ {
+ label: "HTTP",
+ value: "http"
+ }, {
+ label: "HTTPs",
+ value: "https"
+ }, {
+ label: "TCP",
+ value: "tcp"
+ }
+ ]
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+ return (
+ <Form.Item
+ label="Type"
+ name={['checks', 'passive', 'type']}
+ rules={[{ required: true }]}
+ >
+ <Select disabled={readonly}>
+ {options.map(item => {
+ return (
+ <Select.Option value={item.value} key={item.value}>
+ {item.label}
+ </Select.Option>
+ );
+ })}
+ </Select>
+ </Form.Item>
+ )
}
+
+export default PassiveCheckTypeComponent
diff --git a/web/src/components/Upstream/components/passive-check/Unhealthy/HttpFailures.tsx b/web/src/components/Upstream/components/passive-check/Unhealthy/HttpFailures.tsx
new file mode 100644
index 0000000..3ba6154
--- /dev/null
+++ b/web/src/components/Upstream/components/passive-check/Unhealthy/HttpFailures.tsx
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.http_failures' })}
+ required
+ tooltip={formatMessage({ id: 'page.upstream.checks.passive.unhealthy.http_failures.description' })}
+ >
+ <Form.Item
+ name={['checks', 'passive', 'unhealthy', 'http_failures']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.http_failures',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/passive-check/Unhealthy/HttpStatuses.tsx b/web/src/components/Upstream/components/passive-check/Unhealthy/HttpStatuses.tsx
new file mode 100644
index 0000000..ba9ba75
--- /dev/null
+++ b/web/src/components/Upstream/components/passive-check/Unhealthy/HttpStatuses.tsx
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, Row, Col, InputNumber, Button } from 'antd'
+import { useIntl } from 'umi'
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'
+
+import { removeBtnStyle } from '@/components/Upstream/constant'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.List name={['checks', 'passive', 'unhealthy', 'http_statuses']}>
+ {(fields, { add, remove }) => (
+ <>
+ <Form.Item
+ required
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.http_statuses' })}
+ tooltip={formatMessage({ id: 'page.upstream.checks.passive.unhealthy.http_statuses.description' })}
+ style={{ marginBottom: 0 }}
+ >
+ {fields.map((field, index) => (
+ <Row style={{ marginBottom: 10 }} key={index}>
+ <Col span={2}>
+ <Form.Item style={{ marginBottom: 0 }} name={[field.name]}>
+ <InputNumber disabled={readonly} min={200} max={599} />
+ </Form.Item>
+ </Col>
+ <Col style={removeBtnStyle}>
+ {!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 />
+ {formatMessage({
+ id: 'component.global.add',
+ })}
+ </Button>
+ </Form.Item>
+ )}
+ </>
+ )}
+ </Form.List>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Upstream/components/passive-check/Unhealthy/TcpFailures.tsx b/web/src/components/Upstream/components/passive-check/Unhealthy/TcpFailures.tsx
new file mode 100644
index 0000000..175d22f
--- /dev/null
+++ b/web/src/components/Upstream/components/passive-check/Unhealthy/TcpFailures.tsx
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react'
+import { Form, InputNumber } from 'antd'
+import { useIntl } from 'umi'
+
+type Props = {
+ readonly?: boolean
+}
+
+const Component: React.FC<Props> = ({ readonly }) => {
+ const { formatMessage } = useIntl()
+ return (
+ <Form.Item
+ label={formatMessage({ id: 'page.upstream.step.healthyCheck.passive.tcp_failures' })}
+ required
+ tooltip={formatMessage({ id: 'page.upstream.checks.passive.unhealthy.tcp_failures.description' })}
+ >
+ <Form.Item
+ name={['checks', 'passive', 'unhealthy', 'tcp_failures']}
+ noStyle
+ rules={[
+ {
+ required: true,
+ message: formatMessage({
+ id: 'page.upstream.step.input.healthyCheck.passive.tcp_failures',
+ }),
+ },
+ ]}
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+ )
+}
+
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/passive-check/Unhealthy/Timeouts.tsx
similarity index 56%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/passive-check/Unhealthy/Timeouts.tsx
index f13b31a..91b7b4f 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/passive-check/Unhealthy/Timeouts.tsx
@@ -14,31 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
-
-import BasicAuth from './basic-auth'
+import React from 'react'
+import { Form, InputNumber } from 'antd'
type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
+ readonly?: boolean
}
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
+const Component: React.FC<Props> = ({ readonly }) => (
+ <Form.Item
+ label="Timeouts"
+ required
+ >
+ <Form.Item
+ name={['checks', 'passive', 'unhealthy', 'timeouts']}
+ noStyle
+ >
+ <InputNumber disabled={readonly} min={1} max={254} />
+ </Form.Item>
+ </Form.Item>
+)
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
-}
+export default Component
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/passive-check/Unhealthy/index.ts
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/passive-check/Unhealthy/index.ts
index f13b31a..88ab9c2 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/passive-check/Unhealthy/index.ts
@@ -14,31 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import Timeouts from './Timeouts'
+import HttpFailures from './HttpFailures'
+import TcpFailures from './TcpFailures'
+import HttpStatuses from './HttpStatuses'
-import BasicAuth from './basic-auth'
-
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
-}
-
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+export default {
+ Timeouts,
+ HttpFailures,
+ TcpFailures,
+ HttpStatuses
}
diff --git a/web/src/components/Plugin/UI/plugin.tsx b/web/src/components/Upstream/components/passive-check/index.ts
similarity index 55%
copy from web/src/components/Plugin/UI/plugin.tsx
copy to web/src/components/Upstream/components/passive-check/index.ts
index f13b31a..f0637fd 100644
--- a/web/src/components/Plugin/UI/plugin.tsx
+++ b/web/src/components/Upstream/components/passive-check/index.ts
@@ -14,31 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
-import { FormInstance } from 'antd/es/form';
-import { Empty } from 'antd';
-import { useIntl } from 'umi';
+import Healthy from './Healthy'
+import Unhealthy from './Unhealthy'
+import Type from './Type'
-import BasicAuth from './basic-auth'
-
-type Props = {
- name: string,
- form: FormInstance,
- renderForm: boolean
-}
-
-export const PLUGIN_UI_LIST = ['basic-auth',];
-
-export const PluginForm: React.FC<Props> = ({ name, renderForm, form }) => {
-
- const { formatMessage } = useIntl();
-
- if (!renderForm) { return <Empty description={formatMessage({ id: 'component.global.noConfigurationRequired' })} /> };
-
- switch (name) {
- case 'basic-auth':
- return <BasicAuth form={form} />
- default:
- return null;
- }
+export default {
+ Healthy,
+ Unhealthy,
+ Type
}
diff --git a/web/src/components/Upstream/constant.ts b/web/src/components/Upstream/constant.ts
index 58d8ed5..d4f243b 100644
--- a/web/src/components/Upstream/constant.ts
+++ b/web/src/components/Upstream/constant.ts
@@ -16,6 +16,8 @@
*/
export const DEFAULT_UPSTREAM = {
upstream_id: '',
+ // NOTE: the following fields are the default configurations
+ // https://github.com/apache/apisix/blob/master/apisix/schema_def.lua#L325
nodes: [
{
host: '',
@@ -23,42 +25,66 @@ export const DEFAULT_UPSTREAM = {
weight: 1
}
],
- type: 'roundrobin',
+ retries: 0,
timeout: {
connect: 6,
send: 6,
read: 6,
},
- retries: 1
+ type: 'roundrobin',
+ checks: {},
+ scheme: "http",
+ pass_host: "pass",
+ name: "",
+ desc: ""
};
// NOTE: checks.active
+// https://github.com/apache/apisix/blob/master/apisix/schema_def.lua#L40
export const DEFAULT_HEALTH_CHECK_ACTIVE = {
- timeout: 0,
- http_path: '/',
- host: '',
+ type: "http",
+ timeout: 1,
+ concurrency: 10,
+ host: "",
port: 80,
+ http_path: "",
+ https_verify_certificate: true,
healthy: {
interval: 1,
- successes: 1
+ http_statuses: [200, 302],
+ successes: 2
},
unhealthy: {
interval: 1,
- http_failures: 1,
- req_headers: []
- }
+ http_statuses: [429, 404, 500, 501, 502, 503, 504, 505],
+ http_failures: 5,
+ tcp_failures: 2,
+ timeouts: 3
+ },
+ req_headers: []
}
// NOTE: checks.passive
export const DEFAULT_HEALTH_CHECK_PASSIVE = {
+ type: "http",
healthy: {
- http_statuses: [],
- successes: 1
+ http_statuses: [
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 226, 300, 301, 302, 303, 304, 305,
+ 306, 307, 308
+ ],
+ successes: 5
},
unhealthy: {
- http_statuses: [],
- tcp_failures: 1,
- timeouts: 1,
- http_failures: 1
+ http_statuses: [429, 500, 503],
+ tcp_failures: 2,
+ timeouts: 7,
+ http_failures: 5
}
}
+
+export const removeBtnStyle = {
+ marginLeft: 20,
+ display: 'flex',
+ alignItems: 'center',
+};
diff --git a/web/src/pages/Route/locales/zh-CN.ts b/web/src/pages/Route/locales/zh-CN.ts
index ca97132..5d8adda 100644
--- a/web/src/pages/Route/locales/zh-CN.ts
+++ b/web/src/pages/Route/locales/zh-CN.ts
@@ -36,7 +36,7 @@ export default {
'page.route.status': '状态',
'page.route.groupName': '分组名称',
'page.route.offline': '下线',
- 'page.route.publish': '是否发布',
+ 'page.route.publish': '发布',
'page.route.published': '已发布',
'page.route.unpublished': '未发布',
'page.route.onlineDebug': '在线调试',
diff --git a/web/src/pages/Upstream/locales/en-US.ts b/web/src/pages/Upstream/locales/en-US.ts
index a78a162..bc078e2 100644
--- a/web/src/pages/Upstream/locales/en-US.ts
+++ b/web/src/pages/Upstream/locales/en-US.ts
@@ -32,7 +32,6 @@ export default {
'page.upstream.step.description': 'Description',
'page.upstream.step.input.description': 'Please enter upstream\'s description',
'page.upstream.step.type': 'Algorithm',
- 'page.upstream.step.create.node': 'Add Target',
'page.upstream.step.pass-host': 'Hostname',
'page.upstream.step.pass-host.pass': 'Keep the same Host from client request',
'page.upstream.step.pass-host.node': 'Use the domain or IP from Node List',
@@ -65,12 +64,10 @@ export default {
'page.upstream.step.healthyCheck.successes': 'Successes',
'page.upstream.step.input.healthyCheck.successes': 'Please enter successes',
'page.upstream.step.healthyCheck.http_failures': 'HTTP Failures',
- 'page.upstream.step.healthyCheck.active.create.req_headers': 'Add Request Headers',
'page.upstream.step.input.healthyCheck.http_failures': 'Please enter http failures',
'page.upstream.step.healthyCheck.active.req_headers': 'Request Headers',
'page.upstream.step.input.healthyCheck.active.req_headers': 'Please enter request headers',
'page.upstream.step.healthyCheck.passive': 'Passive',
- 'page.upstream.step.healthyCheck.passive.create.http_statuses': 'Add HTTP Status',
'page.upstream.step.healthyCheck.passive.http_statuses': 'HTTP Status',
'page.upstream.step.input.healthyCheck.passive.http_statuses': 'Please enter http status',
'page.upstream.step.healthyCheck.passive.tcp_failures': 'TCP Failures',
@@ -120,5 +117,6 @@ export default {
'page.upstream.checks.passive.healthy.successes.description': 'Number of successes to consider a target healthy',
'page.upstream.checks.passive.unhealthy.http_statuses.description': 'Which HTTP statuses to consider a success',
'page.upstream.checks.passive.unhealthy.http_failures.description': 'Number of HTTP failures to consider a target unhealthy',
- 'page.upstream.checks.passive.unhealthy.tcp_failures.description': 'Number of TCP failures to consider a target unhealthy'
+ 'page.upstream.checks.passive.unhealthy.tcp_failures.description': 'Number of TCP failures to consider a target unhealthy',
+ 'page.upstream.scheme': 'Scheme'
};
diff --git a/web/src/pages/Upstream/locales/zh-CN.ts b/web/src/pages/Upstream/locales/zh-CN.ts
index 3049b97..58620ba 100644
--- a/web/src/pages/Upstream/locales/zh-CN.ts
+++ b/web/src/pages/Upstream/locales/zh-CN.ts
@@ -32,8 +32,7 @@ export default {
'page.upstream.step.description': '描述',
'page.upstream.step.input.description': '请输入上游服务的描述',
'page.upstream.step.type': '负载均衡算法',
- 'page.upstream.step.create.node': '增加目标节点',
- 'page.upstream.step.pass-host': 'Host 转换',
+ 'page.upstream.step.pass-host': 'Host 请求头',
'page.upstream.step.pass-host.pass': '保持与客户端请求一致的 Host 请求头',
'page.upstream.step.pass-host.node': '使用上游节点列表中的域名或 IP',
'page.upstream.step.pass-host.rewrite': '自定义 Host 请求头(即将废弃)',
@@ -65,12 +64,10 @@ export default {
'page.upstream.step.healthyCheck.successes': '成功次数',
'page.upstream.step.input.healthyCheck.successes': '请输入成功次数',
'page.upstream.step.healthyCheck.http_failures': '失败次数',
- 'page.upstream.step.healthyCheck.active.create.req_headers': '增加请求头',
'page.upstream.step.input.healthyCheck.http_failures': '请输入失败次数',
'page.upstream.step.healthyCheck.active.req_headers': '请求头',
'page.upstream.step.input.healthyCheck.active.req_headers': '请输入请求头',
'page.upstream.step.healthyCheck.passive': '被动检查',
- 'page.upstream.step.healthyCheck.passive.create.http_statuses': '增加状态码',
'page.upstream.step.healthyCheck.passive.http_statuses': '状态码',
'page.upstream.step.input.healthyCheck.passive.http_statuses': '请输入状态码',
'page.upstream.step.healthyCheck.passive.tcp_failures': 'TCP 失败次数',
@@ -120,5 +117,6 @@ export default {
'page.upstream.checks.passive.healthy.successes.description': '通过被动健康检查观察到的正常代理流量的成功次数。如果达到该值,上游服务目标节点将被视为健康。',
'page.upstream.checks.passive.unhealthy.http_statuses.description': '当被动健康检查的探针返回值是 HTTP 状态码列表的某一个值时,代表不健康状态是由代理流量产生的。',
'page.upstream.checks.passive.unhealthy.http_failures.description': '由被动健康检查所观察,代理流量中 HTTP 失败的次数。如果达到此值,则认为上游服务目标节点是不健康的。',
- 'page.upstream.checks.passive.unhealthy.tcp_failures.description': '被动健康检查所观察到的代理流量中 TCP 失败的次数。如果达到此值,则认为上游服务目标节点是不健康的。'
+ 'page.upstream.checks.passive.unhealthy.tcp_failures.description': '被动健康检查所观察到的代理流量中 TCP 失败的次数。如果达到此值,则认为上游服务目标节点是不健康的。',
+ 'page.upstream.scheme': '协议'
};