From 5e9bbc5f150581c9541a00ff7272b9bad689c4a3 Mon Sep 17 00:00:00 2001
From: yangon <2689991790@qq.com>
Date: Mon, 17 Jun 2024 14:18:20 +0800
Subject: [PATCH] obproxy management (#451)
---
ui/src/api/generated/api.ts | 199 ++++++++++---
ui/src/components/CustomFormItem/index.tsx | 33 +++
ui/src/components/InputLabelComp/index.tsx | 14 +-
ui/src/components/TooltipPretty/index.less | 5 +
ui/src/components/TooltipPretty/index.tsx | 22 ++
ui/src/constants/doc.ts | 3 +-
ui/src/constants/index.ts | 20 ++
ui/src/i18n/strings/zh-CN.json | 38 ++-
ui/src/pages/Cluster/New/BasicInfo.tsx | 12 +-
ui/src/pages/Cluster/New/Observer.tsx | 64 ++---
ui/src/pages/OBProxy/ClusterList.tsx | 4 +-
.../OBProxy/Detail/Overview/ConfigDrawer.tsx | 266 ++++++++++++++++++
.../OBProxy/Detail/Overview/DetailConfig.tsx | 45 +--
ui/src/pages/OBProxy/New/BasicConfig.tsx | 83 ++++--
ui/src/pages/OBProxy/New/DetailConfig.tsx | 147 ++++++++++
ui/src/pages/OBProxy/New/index.less | 4 +
ui/src/pages/OBProxy/New/index.tsx | 44 ++-
ui/src/pages/OBProxy/helper.ts | 26 ++
ui/src/type/obproxy.d.ts | 13 +
ui/src/type/typings.d.ts | 1 +
20 files changed, 893 insertions(+), 150 deletions(-)
create mode 100644 ui/src/components/CustomFormItem/index.tsx
create mode 100644 ui/src/components/TooltipPretty/index.less
create mode 100644 ui/src/components/TooltipPretty/index.tsx
create mode 100644 ui/src/pages/OBProxy/Detail/Overview/ConfigDrawer.tsx
create mode 100644 ui/src/pages/OBProxy/New/DetailConfig.tsx
create mode 100644 ui/src/pages/OBProxy/New/index.less
create mode 100644 ui/src/pages/OBProxy/helper.ts
create mode 100644 ui/src/type/obproxy.d.ts
diff --git a/ui/src/api/generated/api.ts b/ui/src/api/generated/api.ts
index b2830f146..e6329dba5 100644
--- a/ui/src/api/generated/api.ts
+++ b/ui/src/api/generated/api.ts
@@ -990,6 +990,31 @@ export interface ListOBProxies200Response {
*/
'successful': boolean;
}
+/**
+ *
+ * @export
+ * @interface ListOBProxyParameters200Response
+ */
+export interface ListOBProxyParameters200Response {
+ /**
+ *
+ * @type {Array}
+ * @memberof ListOBProxyParameters200Response
+ */
+ 'data': Array;
+ /**
+ *
+ * @type {string}
+ * @memberof ListOBProxyParameters200Response
+ */
+ 'message': string;
+ /**
+ *
+ * @type {boolean}
+ * @memberof ListOBProxyParameters200Response
+ */
+ 'successful': boolean;
+}
/**
*
* @export
@@ -1796,6 +1821,43 @@ export interface ModelsStorageSpec {
*/
'storageSize'?: number;
}
+/**
+ *
+ * @export
+ * @interface ObproxyConfigItem
+ */
+export interface ObproxyConfigItem {
+ /**
+ *
+ * @type {string}
+ * @memberof ObproxyConfigItem
+ */
+ 'info'?: string;
+ /**
+ *
+ * @type {string}
+ * @memberof ObproxyConfigItem
+ */
+ 'name'?: string;
+ /**
+ *
+ * @type {boolean}
+ * @memberof ObproxyConfigItem
+ */
+ 'needReboot'?: boolean;
+ /**
+ *
+ * @type {string}
+ * @memberof ObproxyConfigItem
+ */
+ 'value'?: string;
+ /**
+ *
+ * @type {string}
+ * @memberof ObproxyConfigItem
+ */
+ 'visibleLevel'?: string;
+}
/**
*
* @export
@@ -2052,22 +2114,16 @@ export interface ObproxyOBProxyOverview {
export interface ObproxyPatchOBProxyParam {
/**
*
- * @type {Array}
- * @memberof ObproxyPatchOBProxyParam
- */
- 'addedParameters'?: Array;
- /**
- *
- * @type {Array}
+ * @type {string}
* @memberof ObproxyPatchOBProxyParam
*/
- 'deletedParameters'?: Array;
+ 'image'?: string;
/**
*
- * @type {string}
+ * @type {Array}
* @memberof ObproxyPatchOBProxyParam
*/
- 'image'?: string;
+ 'parameters'?: Array;
/**
*
* @type {number}
@@ -5043,51 +5099,51 @@ export interface ResponseStorageSpec {
/**
*
* @export
- * @interface RouteRoute
+ * @interface RouteRouteParam
*/
-export interface RouteRoute {
+export interface RouteRouteParam {
/**
*
* @type {Array}
- * @memberof RouteRoute
+ * @memberof RouteRouteParam
*/
'aggregateLabels': Array;
/**
*
* @type {number}
- * @memberof RouteRoute
+ * @memberof RouteRouteParam
*/
'groupInterval': number;
/**
*
* @type {number}
- * @memberof RouteRoute
+ * @memberof RouteRouteParam
*/
'groupWait': number;
+ /**
+ *
+ * @type {string}
+ * @memberof RouteRouteParam
+ */
+ 'id'?: string;
/**
*
* @type {Array}
- * @memberof RouteRoute
+ * @memberof RouteRouteParam
*/
'matchers': Array;
/**
*
* @type {string}
- * @memberof RouteRoute
+ * @memberof RouteRouteParam
*/
'receiver': string;
/**
*
* @type {number}
- * @memberof RouteRoute
+ * @memberof RouteRouteParam
*/
'repeatInterval': number;
- /**
- *
- * @type {string}
- * @memberof RouteRoute
- */
- 'id'?: string;
}
/**
*
@@ -5592,11 +5648,11 @@ export const AlarmApiAxiosParamCreator = function (configuration?: Configuration
/**
* Create or update alarm route.
* @summary Create or update alarm route
- * @param {RouteRoute} body route
+ * @param {RouteRouteParam} body route
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
- createOrUpdateRoute: async (body: RouteRoute, options: RawAxiosRequestConfig = {}): Promise => {
+ createOrUpdateRoute: async (body: RouteRouteParam, options: RawAxiosRequestConfig = {}): Promise => {
// verify required parameter 'body' is not null or undefined
assertParamExists('createOrUpdateRoute', 'body', body)
const localVarPath = `/api/v1/alarm/route/routes`;
@@ -6275,11 +6331,11 @@ export const AlarmApiFp = function(configuration?: Configuration) {
/**
* Create or update alarm route.
* @summary Create or update alarm route
- * @param {RouteRoute} body route
+ * @param {RouteRouteParam} body route
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
- async createOrUpdateRoute(body: RouteRoute, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ async createOrUpdateRoute(body: RouteRouteParam, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
const localVarAxiosArgs = await localVarAxiosParamCreator.createOrUpdateRoute(body, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['AlarmApi.createOrUpdateRoute']?.[localVarOperationServerIndex]?.url;
@@ -6526,11 +6582,11 @@ export const AlarmApiFactory = function (configuration?: Configuration, basePath
/**
* Create or update alarm route.
* @summary Create or update alarm route
- * @param {RouteRoute} body route
+ * @param {RouteRouteParam} body route
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
- createOrUpdateRoute(body: RouteRoute, options?: any): AxiosPromise {
+ createOrUpdateRoute(body: RouteRouteParam, options?: any): AxiosPromise {
return localVarFp.createOrUpdateRoute(body, options).then((request) => request(axios, basePath));
},
/**
@@ -6725,12 +6781,12 @@ export class AlarmApi extends BaseAPI {
/**
* Create or update alarm route.
* @summary Create or update alarm route
- * @param {RouteRoute} body route
+ * @param {RouteRouteParam} body route
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof AlarmApi
*/
- public createOrUpdateRoute(body: RouteRoute, options?: RawAxiosRequestConfig) {
+ public createOrUpdateRoute(body: RouteRouteParam, options?: RawAxiosRequestConfig) {
return AlarmApiFp(this.configuration).createOrUpdateRoute(body, options).then((request) => request(this.axios, this.basePath));
}
@@ -7347,7 +7403,8 @@ export class ClusterApi extends BaseAPI {
export const ListK8sEventsObjectTypeEnum = {
OBCLUSTER: 'OBCLUSTER',
OBTENANT: 'OBTENANT',
- OBBACKUPPOLICY: 'OBBACKUPPOLICY'
+ OBBACKUPPOLICY: 'OBBACKUPPOLICY',
+ OBPROXY: 'OBPROXY'
} as const;
export type ListK8sEventsObjectTypeEnum = typeof ListK8sEventsObjectTypeEnum[keyof typeof ListK8sEventsObjectTypeEnum];
/**
@@ -8791,6 +8848,44 @@ export const OBProxyApiAxiosParamCreator = function (configuration?: Configurati
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ /**
+ * List OBProxy Parameters by namespace and name
+ * @summary List OBProxy Parameters
+ * @param {string} namespace namespace of obproxy deployment
+ * @param {string} name name of obproxy deployment
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ listOBProxyParameters: async (namespace: string, name: string, options: RawAxiosRequestConfig = {}): Promise => {
+ // verify required parameter 'namespace' is not null or undefined
+ assertParamExists('listOBProxyParameters', 'namespace', namespace)
+ // verify required parameter 'name' is not null or undefined
+ assertParamExists('listOBProxyParameters', 'name', name)
+ const localVarPath = `/api/v1/obproxies/{namespace}/{name}/parameters`
+ .replace(`{${"namespace"}}`, encodeURIComponent(String(namespace)))
+ .replace(`{${"name"}}`, encodeURIComponent(String(name)));
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
@@ -8911,6 +9006,20 @@ export const OBProxyApiFp = function(configuration?: Configuration) {
const localVarOperationServerBasePath = operationServerMap['OBProxyApi.listOBProxies']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
+ /**
+ * List OBProxy Parameters by namespace and name
+ * @summary List OBProxy Parameters
+ * @param {string} namespace namespace of obproxy deployment
+ * @param {string} name name of obproxy deployment
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async listOBProxyParameters(namespace: string, name: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.listOBProxyParameters(namespace, name, options);
+ const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
+ const localVarOperationServerBasePath = operationServerMap['OBProxyApi.listOBProxyParameters']?.[localVarOperationServerIndex]?.url;
+ return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
+ },
/**
* Patch OBProxy with the specified parameters
* @summary Patch OBProxy
@@ -8978,6 +9087,17 @@ export const OBProxyApiFactory = function (configuration?: Configuration, basePa
listOBProxies(ns?: string, options?: any): AxiosPromise {
return localVarFp.listOBProxies(ns, options).then((request) => request(axios, basePath));
},
+ /**
+ * List OBProxy Parameters by namespace and name
+ * @summary List OBProxy Parameters
+ * @param {string} namespace namespace of obproxy deployment
+ * @param {string} name name of obproxy deployment
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ listOBProxyParameters(namespace: string, name: string, options?: any): AxiosPromise {
+ return localVarFp.listOBProxyParameters(namespace, name, options).then((request) => request(axios, basePath));
+ },
/**
* Patch OBProxy with the specified parameters
* @summary Patch OBProxy
@@ -9050,6 +9170,19 @@ export class OBProxyApi extends BaseAPI {
return OBProxyApiFp(this.configuration).listOBProxies(ns, options).then((request) => request(this.axios, this.basePath));
}
+ /**
+ * List OBProxy Parameters by namespace and name
+ * @summary List OBProxy Parameters
+ * @param {string} namespace namespace of obproxy deployment
+ * @param {string} name name of obproxy deployment
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof OBProxyApi
+ */
+ public listOBProxyParameters(namespace: string, name: string, options?: RawAxiosRequestConfig) {
+ return OBProxyApiFp(this.configuration).listOBProxyParameters(namespace, name, options).then((request) => request(this.axios, this.basePath));
+ }
+
/**
* Patch OBProxy with the specified parameters
* @summary Patch OBProxy
diff --git a/ui/src/components/CustomFormItem/index.tsx b/ui/src/components/CustomFormItem/index.tsx
new file mode 100644
index 000000000..f70223428
--- /dev/null
+++ b/ui/src/components/CustomFormItem/index.tsx
@@ -0,0 +1,33 @@
+import { intl } from '@/utils/intl';
+import type { FormItemProps } from 'antd';
+import { Form } from 'antd';
+
+export const CustomFormItem = (prop: FormItemProps & { message?: string }) => {
+ const { label, message } = prop;
+ return (
+
+ {prop.children}
+
+ );
+};
diff --git a/ui/src/components/InputLabelComp/index.tsx b/ui/src/components/InputLabelComp/index.tsx
index ba6949ea3..9177e6516 100644
--- a/ui/src/components/InputLabelComp/index.tsx
+++ b/ui/src/components/InputLabelComp/index.tsx
@@ -13,6 +13,8 @@ interface InputLabelCompPorps {
maxLength?: number;
defaulLabelName?: string;
regex?: boolean;
+ disable?: boolean;
+ allowDelete?: boolean;
}
export default function InputLabelComp(props: InputLabelCompPorps) {
@@ -23,6 +25,8 @@ export default function InputLabelComp(props: InputLabelCompPorps) {
onBlur,
defaulLabelName = 'key',
regex,
+ disable = false,
+ allowDelete = true,
} = props;
const labelNameInput = (value: string, index: number) => {
@@ -54,8 +58,9 @@ export default function InputLabelComp(props: InputLabelCompPorps) {
{labels?.map((label, index) => (
-
+
labelNameInput(e.target.value, index)}
@@ -65,8 +70,9 @@ export default function InputLabelComp(props: InputLabelCompPorps) {
})}
/>
-
+
labelValueInput(e.target.value, index)}
@@ -92,7 +98,7 @@ export default function InputLabelComp(props: InputLabelCompPorps) {
)}
- {labels.length > 1 && (
+ {labels.length > 1 && allowDelete && (
- {!maxLength || labels.length < maxLength ? (
+ {(!maxLength || labels.length < maxLength) && !disable ? (
-
-
-
+
-
+
@@ -217,7 +191,7 @@ export default function Observer({ storageClasses, form }: ObserverProps) {
})}
-
-
-
+
@@ -245,7 +219,7 @@ export default function Observer({ storageClasses, form }: ObserverProps) {
)}
{/* */}
-
+
@@ -256,7 +230,7 @@ export default function Observer({ storageClasses, form }: ObserverProps) {
})}
-
-
-
+
@@ -282,13 +256,13 @@ export default function Observer({ storageClasses, form }: ObserverProps) {
TooltipItemContent={TooltipItemContent}
/>
)}
-
+
redoLog
-
-
-
+
)}
-
+
diff --git a/ui/src/pages/OBProxy/ClusterList.tsx b/ui/src/pages/OBProxy/ClusterList.tsx
index aaf4f2cf8..5174dda7b 100644
--- a/ui/src/pages/OBProxy/ClusterList.tsx
+++ b/ui/src/pages/OBProxy/ClusterList.tsx
@@ -56,8 +56,8 @@ const columns: ColumnsType = [
id: 'src.pages.OBProxy.A62C101E',
defaultMessage: '副本数',
}),
- dataIndex: 'Replicas',
- key: 'Replicas',
+ dataIndex: 'replicas',
+ key: 'replicas',
},
{
title: intl.formatMessage({
diff --git a/ui/src/pages/OBProxy/Detail/Overview/ConfigDrawer.tsx b/ui/src/pages/OBProxy/Detail/Overview/ConfigDrawer.tsx
new file mode 100644
index 000000000..7af01190b
--- /dev/null
+++ b/ui/src/pages/OBProxy/Detail/Overview/ConfigDrawer.tsx
@@ -0,0 +1,266 @@
+import { obproxy } from '@/api';
+import type { CommonKVPair } from '@/api/generated';
+import { ObproxyPatchOBProxyParam } from '@/api/generated';
+import AlertDrawer from '@/components/AlertDrawer';
+import { CustomFormItem } from '@/components/CustomFormItem';
+import { SERVICE_TYPE, SUFFIX_UNIT } from '@/constants';
+import { MIRROR_OBPROXY } from '@/constants/doc';
+import { OBProxy } from '@/type/obproxy';
+import { intl } from '@/utils/intl';
+import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
+import { useRequest } from 'ahooks';
+import type { DrawerProps } from 'antd';
+import {
+ Button,
+ Col,
+ Form,
+ Input,
+ InputNumber,
+ Row,
+ Select,
+ Typography,
+} from 'antd';
+import { useEffect, useRef } from 'react';
+import { isDifferentParams } from '../../helper';
+
+type ConfigDrawerProps = {
+ onClose: () => void;
+} & OBProxy.CommonProxyDetail &
+ DrawerProps;
+
+type FormValue = {
+ parameters?: { key: string; value: string }[];
+} & ObproxyPatchOBProxyParam;
+
+const { Text } = Typography;
+
+export default function ConfigDrawer({
+ onClose,
+ name,
+ namespace,
+ ...props
+}: ConfigDrawerProps) {
+ const [form] = Form.useForm();
+ const preParameters = useRef();
+ const { data: listParametersRes } = useRequest(
+ obproxy.listOBProxyParameters,
+ {
+ defaultParams: [namespace, name],
+ },
+ );
+ const listParametersOptions = listParametersRes?.data.map((item) => ({
+ label: item.name,
+ value: item.name,
+ info: item.info,
+ }));
+
+ const submit = (values: FormValue) => {
+ if (
+ !isDifferentParams(values.parameters || [], preParameters.current || [])
+ ) {
+ delete values.parameters;
+ }
+ };
+ const titleStyle = { fontSize: 14, fontWeight: 600 };
+
+ const labelChange = (label: string, name: number) => {
+ const value = listParametersRes?.data?.find(
+ (parameter) => parameter.name === label,
+ )?.value;
+ value && form.setFieldValue(['parameters', name, 'value'], value);
+ };
+ useEffect(() => {
+ preParameters.current = props.parameters;
+ }, [props.parameters]);
+ return (
+ form.submit()}
+ destroyOnClose={true}
+ onClose={() => onClose()}
+ {...props}
+ >
+
+ {(fields, { add, remove }) => (
+ <>
+ {fields.map(({ name }) => (
+
+
+
+
+
+
+
+
+
+
+
+ remove(name)} />
+
+
+ ))}
+
+
+
+ >
+ )}
+
+
+
+ );
+}
diff --git a/ui/src/pages/OBProxy/Detail/Overview/DetailConfig.tsx b/ui/src/pages/OBProxy/Detail/Overview/DetailConfig.tsx
index a58af682e..7c83c0d38 100644
--- a/ui/src/pages/OBProxy/Detail/Overview/DetailConfig.tsx
+++ b/ui/src/pages/OBProxy/Detail/Overview/DetailConfig.tsx
@@ -1,26 +1,17 @@
-import type { CommonKVPair, CommonResourceSpec } from '@/api/generated';
+import InputLabelComp from '@/components/InputLabelComp';
+import { OBProxy } from '@/type/obproxy';
import { intl } from '@/utils/intl';
import { Button, Card, Col, Row } from 'antd';
-
-interface DetailConfigProps {
- name?: string;
- namespace?: string;
- image?: string;
- parameters?: CommonKVPair[];
- resource?: CommonResourceSpec;
- serviceType?: string;
- replicas?: number;
+import { useState } from 'react';
+import ConfigDrawer from './ConfigDrawer';
+interface DetailConfigProps extends OBProxy.CommonProxyDetail {
style?: React.CSSProperties;
}
-export default function DetailConfig({
- image,
- parameters,
- resource,
- serviceType,
- replicas,
- style,
-}: DetailConfigProps) {
+export default function DetailConfig({ style, ...props }: DetailConfigProps) {
+ const { image, serviceType, replicas, resource, parameters } = props;
+
+ const [drawerOpen, setDrawerOpen] = useState(false);
return (
}
extra={
-
);
}
diff --git a/ui/src/pages/OBProxy/New/BasicConfig.tsx b/ui/src/pages/OBProxy/New/BasicConfig.tsx
index 56ddbea67..d1d8f51d5 100644
--- a/ui/src/pages/OBProxy/New/BasicConfig.tsx
+++ b/ui/src/pages/OBProxy/New/BasicConfig.tsx
@@ -1,10 +1,13 @@
import IconTip from '@/components/IconTip';
import SelectNSFromItem from '@/components/SelectNSFromItem';
+import TooltipPretty from '@/components/TooltipPretty';
+import { resourceNameRule } from '@/constants/rules';
import { getSimpleClusterList } from '@/services';
import { intl } from '@/utils/intl';
import { useRequest } from 'ahooks';
import { Card, Col, Form, Input, Row, Select } from 'antd';
import type { FormInstance } from 'antd/lib/form';
+import { useEffect } from 'react';
interface BasicConfigProps {
form: FormInstance;
@@ -12,10 +15,17 @@ interface BasicConfigProps {
export default function BasicConfig({ form }: BasicConfigProps) {
const { data: clusterListRes } = useRequest(getSimpleClusterList);
+ const selectCluster = Form.useWatch('obCluster');
const clisterList = clusterListRes?.data.map((cluster) => ({
label: cluster.name,
- value: `${cluster.name}+${cluster.namespace}`,
+ value: JSON.stringify({ name: cluster.name, namespace: cluster.namespace }),
}));
+
+ useEffect(() => {
+ if (selectCluster && !form.getFieldValue('namespace')) {
+ form.setFieldValue('namespace', selectCluster.split('+')?.[1]);
+ }
+ }, [selectCluster]);
return (
-
-
-
+ validateFirst
+ name={'name'}
+ rules={[
+ {
+ required: true,
+ message: intl.formatMessage({
+ id: 'src.pages.OBProxy.New.F602E292',
+ defaultMessage: '请输入k8s资源名称',
+ }),
+ },
+ {
+ pattern: /\D/,
+ message: intl.formatMessage({
+ id: 'src.pages.OBProxy.New.37FA27BA',
+ defaultMessage: '资源名不能使用纯数字',
+ }),
+ },
+ resourceNameRule,
+ ]}
+ >
+
+
+
+
+
+ {intl.formatMessage({
+ id: 'src.pages.OBProxy.New.0C4EFBB0',
+ defaultMessage: '资源设置',
+ })}
+
+
+
+ {intl.formatMessage({
+ id: 'Dashboard.Cluster.New.Observer.Image',
+ defaultMessage: '镜像',
+ })}{' '}
+
+ {intl.formatMessage({
+ id: 'Dashboard.Cluster.New.Observer.ImageList',
+ defaultMessage: '(镜像列表)',
+ })}
+
+ >
+ }
+ name="image"
+ message={intl.formatMessage({
+ id: 'Dashboard.Cluster.New.Observer.EnterAnImage',
+ defaultMessage: '请输入镜像',
+ })}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {intl.formatMessage({
+ id: 'src.pages.OBProxy.New.134CD1CE',
+ defaultMessage: '参数设置',
+ })}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/ui/src/pages/OBProxy/New/index.less b/ui/src/pages/OBProxy/New/index.less
new file mode 100644
index 000000000..95a2e940f
--- /dev/null
+++ b/ui/src/pages/OBProxy/New/index.less
@@ -0,0 +1,4 @@
+.titleText {
+ font-size: 14px;
+ font-weight: 600;
+ }
\ No newline at end of file
diff --git a/ui/src/pages/OBProxy/New/index.tsx b/ui/src/pages/OBProxy/New/index.tsx
index 6aa3a500c..7fc1f6c99 100644
--- a/ui/src/pages/OBProxy/New/index.tsx
+++ b/ui/src/pages/OBProxy/New/index.tsx
@@ -1,12 +1,40 @@
+import { obproxy } from '@/api';
+import { ObproxyCreateOBProxyParam } from '@/api/generated';
import { intl } from '@/utils/intl';
import { PageContainer } from '@ant-design/pro-components';
import { useNavigate } from '@umijs/max';
-import { Button, Col, Form, Row } from 'antd';
+import { Button, Form, Space, message } from 'antd';
import BasicConfig from './BasicConfig';
+import DetailConfig from './DetailConfig';
+
+type FormValues = {
+ obCluster: string;
+} & ObproxyCreateOBProxyParam;
export default function New() {
const navigate = useNavigate();
const [form] = Form.useForm();
+ const submit = async (values: FormValues) => {
+ try {
+ const res = await obproxy.createOBPROXY({
+ ...values,
+ obCluster: JSON.parse(values.obCluster),
+ });
+ if (res.successful) {
+ message.success(
+ intl.formatMessage({
+ id: 'src.pages.OBProxy.New.49694AC5',
+ defaultMessage: '创建成功!',
+ }),
+ 3,
+ );
+ form.resetFields();
+ history.back();
+ }
+ } catch (err) {
+ console.error('err:', err);
+ }
+ };
return (
,
-
+ form.submit()} type="primary">
{intl.formatMessage({
id: 'src.pages.OBProxy.New.E2247569',
defaultMessage: '提交',
})}
,
]}
+ style={{ paddingBottom: 50 }}
>
-
);
diff --git a/ui/src/pages/OBProxy/helper.ts b/ui/src/pages/OBProxy/helper.ts
new file mode 100644
index 000000000..29f4e6ec7
--- /dev/null
+++ b/ui/src/pages/OBProxy/helper.ts
@@ -0,0 +1,26 @@
+import type { CommonKVPair } from '@/api/generated';
+
+const buildLabelsMap = (labels: CommonKVPair[]) => {
+ const labelsMap = new Map();
+ for (const label of labels) {
+ labelsMap.set(label.key, label.value);
+ }
+ return labelsMap;
+};
+
+/**
+ *
+ * @description Determines whether two parameter lists are different
+ */
+export const isDifferentParams = (
+ newParams: CommonKVPair[],
+ oldParams: CommonKVPair[],
+) => {
+ const newParamsMap = buildLabelsMap(newParams),
+ oldParamsMap = buildLabelsMap(oldParams);
+ if (newParamsMap.size !== oldParamsMap.size) return true;
+ for (const key of newParamsMap.keys()) {
+ if (newParamsMap.get(key) !== oldParamsMap.get(key)) return true;
+ }
+ return false;
+};
diff --git a/ui/src/type/obproxy.d.ts b/ui/src/type/obproxy.d.ts
new file mode 100644
index 000000000..ec8355e1c
--- /dev/null
+++ b/ui/src/type/obproxy.d.ts
@@ -0,0 +1,13 @@
+declare namespace OBProxy {
+ interface CommonProxyDetail {
+ name: string;
+ namespace: string;
+ image?: string;
+ parameters?: CommonKVPair[];
+ resource?: CommonResourceSpec;
+ serviceType?: string;
+ replicas?: number;
+ }
+}
+
+export { OBProxy };
diff --git a/ui/src/type/typings.d.ts b/ui/src/type/typings.d.ts
index c1079c0c8..9f39b0d3c 100644
--- a/ui/src/type/typings.d.ts
+++ b/ui/src/type/typings.d.ts
@@ -849,4 +849,5 @@ declare namespace API {
setVisible: (prop: boolean) => void;
successCallback?: (val?: any) => void;
};
+
}