You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by le...@apache.org on 2022/08/24 01:49:41 UTC
[inlong] branch master updated: [INLONG-5648][Dashboard] Optimize the create logic, support specifying specific types (#5649)
This is an automated email from the ASF dual-hosted git repository.
leezng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git
The following commit(s) were added to refs/heads/master by this push:
new 21de72e7a [INLONG-5648][Dashboard] Optimize the create logic, support specifying specific types (#5649)
21de72e7a is described below
commit 21de72e7a9ff8780ce1e3672e26853ed3957c711
Author: Daniel <le...@apache.org>
AuthorDate: Wed Aug 24 09:49:36 2022 +0800
[INLONG-5648][Dashboard] Optimize the create logic, support specifying specific types (#5649)
---
inlong-dashboard/src/locales/cn.json | 14 +-
inlong-dashboard/src/locales/en.json | 14 +-
inlong-dashboard/src/metas/clusters/index.tsx | 124 +++++++++-------
inlong-dashboard/src/metas/sources/file.ts | 1 -
.../src/pages/Clusters/CreateModal.tsx | 16 +-
inlong-dashboard/src/pages/Clusters/index.tsx | 3 +-
.../pages/GroupDetail/DataSources/DetailModal.tsx | 80 ++++++++--
.../src/pages/GroupDetail/DataSources/index.tsx | 61 +-------
.../pages/GroupDetail/DataStorage/DetailModal.tsx | 161 +++++++++------------
.../src/pages/GroupDetail/DataStorage/index.tsx | 70 +--------
10 files changed, 230 insertions(+), 314 deletions(-)
diff --git a/inlong-dashboard/src/locales/cn.json b/inlong-dashboard/src/locales/cn.json
index 484877aa4..328831c33 100644
--- a/inlong-dashboard/src/locales/cn.json
+++ b/inlong-dashboard/src/locales/cn.json
@@ -14,9 +14,8 @@
"basic.CreateTime": "创建时间",
"basic.Yes": "是",
"basic.No": "否",
- "components.AccessHelper.DataSourcesEditor.NewDataSource": "新建数据源",
- "components.AccessHelper.DataSourcesEditor.CreateModal.DataSourceName": "数据源名称",
- "components.AccessHelper.DataSourcesEditor.CreateModal.File": "文件",
+ "meta.Sources.Name": "数据源名称",
+ "meta.Sources.Type": "类型",
"meta.Sources.File.SerializationType": "文件类型",
"meta.Sources.File.DataSourceIP": "数据源IP",
"meta.Sources.File.FilePath": "⽂件路径",
@@ -36,9 +35,10 @@
"meta.Sources.Db.TableWhiteList": "表名白名单",
"meta.Sources.Db.WhiteListHelp": "多个白名单之间用英文逗号分隔,单个为正则表达式,比如:b1,b*",
"components.AccessHelper.DataStorageEditor.Editor.AddTo": "添加",
- "meta.Sinks.SinkName": "流向名称",
+ "meta.Sinks.SinkName": "名称",
"meta.Sinks.SinkNameRule": "以英文字母开头,只能包含英文字母、数字、中划线、下划线",
- "meta.Sinks.Description": "流向描述",
+ "meta.Sinks.SinkType": "类型",
+ "meta.Sinks.Description": "描述",
"meta.Sinks.SourceFieldName": "源字段名",
"meta.Sinks.SourceFieldType": "源字段类型",
"meta.Sinks.SourceFieldNameRule": "以英文字母开头,只能包含英文字母、数字、下划线",
@@ -304,13 +304,10 @@
"pages.GroupDetail.Info.CheckMsg": "请检查表单",
"pages.GroupDetail.Info.Previous": "上一步",
"pages.GroupDetail.Info.Create": "新建分组",
- "pages.GroupDetail.Sources.Type": "类型",
- "pages.GroupDetail.Sources.File": "文件",
"pages.GroupDetail.Sources.SaveSuccessfully": "保存成功",
"pages.GroupDetail.Sources.DeleteConfirm": "确认删除吗",
"pages.GroupDetail.Sources.DeleteSuccessfully": "删除成功",
"pages.GroupDetail.Sources.DataStreams": "数据流",
- "pages.GroupDetail.Sources.NoDataStreams": "暂无可用数据流,请先创建新数据流",
"pages.GroupDetail.Sources.Create": "新建数据源",
"pages.GroupDetail.Sources.status.Disable": "失效",
"pages.GroupDetail.Sources.status.Normal": "正常",
@@ -330,7 +327,6 @@
"pages.GroupDetail.Sink.New": "新建流向配置",
"pages.GroupDetail.Sink.Type": "类型",
"pages.GroupDetail.Sink.DataStreams": "数据流",
- "pages.GroupDetail.Sink.NoDataStreams": "暂无可用数据流,请先创建新数据流",
"pages.GroupDetail.Sink.Status.New": "新建",
"pages.GroupDetail.Sink.Status.Pending": "配置中",
"pages.GroupDetail.Sink.Status.Error": "配置失败",
diff --git a/inlong-dashboard/src/locales/en.json b/inlong-dashboard/src/locales/en.json
index 59f535eb5..8838587c3 100644
--- a/inlong-dashboard/src/locales/en.json
+++ b/inlong-dashboard/src/locales/en.json
@@ -14,9 +14,8 @@
"basic.CreateTime": "CreateTime",
"basic.Yes": "Yes",
"basic.No": "No",
- "components.AccessHelper.DataSourcesEditor.NewDataSource": "New DataSource",
- "components.AccessHelper.DataSourcesEditor.CreateModal.DataSourceName": "DataSource Name",
- "components.AccessHelper.DataSourcesEditor.CreateModal.File": "File",
+ "meta.Sources.Name": "Source Name",
+ "meta.Sources.Type": "Type",
"meta.Sources.File.SerializationType": "File type",
"meta.Sources.File.DataSourceIP": "Data source IP",
"meta.Sources.File.FilePath": "File path",
@@ -36,8 +35,9 @@
"meta.Sources.Db.TableWhiteList": "Table WhiteList",
"meta.Sources.Db.WhiteListHelp": "Multiple whitelists are separated by commas, each of which is a regular expression, for example b1,b*",
"components.AccessHelper.DataStorageEditor.Editor.AddTo": "Add",
- "meta.Sinks.SinkName": "SinkName",
+ "meta.Sinks.SinkName": "Name",
"meta.Sinks.SinkNameRule": "At the beginning of English letters, only English letters, numbers, minus, and underscores",
+ "meta.Sinks.SinkType": "Type",
"meta.Sinks.Description": "SinkDescription",
"meta.Sinks.SourceFieldName": "SourceFieldName",
"meta.Sinks.SourceFieldType": "SourceFieldType",
@@ -303,14 +303,11 @@
"pages.GroupDetail.Info.SubmittedSuccessfully": "Submitted successfully",
"pages.GroupDetail.Info.CheckMsg": "Please check the form",
"pages.GroupDetail.Info.Previous": "Previous",
- "pages.GroupDetail.Info.Create": "Access Create",
- "pages.GroupDetail.Sources.Type": "Type",
- "pages.GroupDetail.Sources.File": "File",
+ "pages.GroupDetail.Info.Create": "Create",
"pages.GroupDetail.Sources.SaveSuccessfully": "Save successfully",
"pages.GroupDetail.Sources.DeleteConfirm": "Delete confirm",
"pages.GroupDetail.Sources.DeleteSuccessfully": "Delete successfully",
"pages.GroupDetail.Sources.DataStreams": "DataStreams",
- "pages.GroupDetail.Sources.NoDataStreams": "NoDataStreams",
"pages.GroupDetail.Sources.Create": "Create",
"pages.GroupDetail.Sources.status.Disable": "Disable",
"pages.GroupDetail.Sources.status.Normal": "Normal",
@@ -330,7 +327,6 @@
"pages.GroupDetail.Sink.New": "Create",
"pages.GroupDetail.Sink.Type": "Type",
"pages.GroupDetail.Sink.DataStreams": "DataStreams",
- "pages.GroupDetail.Sink.NoDataStreams": "NoDataStreams",
"pages.GroupDetail.Sink.Status.New": "New",
"pages.GroupDetail.Sink.Status.Pending": "Pending",
"pages.GroupDetail.Sink.Status.Error": "Error",
diff --git a/inlong-dashboard/src/metas/clusters/index.tsx b/inlong-dashboard/src/metas/clusters/index.tsx
index 39e77f8da..35a96b2ba 100644
--- a/inlong-dashboard/src/metas/clusters/index.tsx
+++ b/inlong-dashboard/src/metas/clusters/index.tsx
@@ -32,7 +32,7 @@ export interface ClusterItemType {
tableColumns: ClsTableItemType[];
}
-export const Clusters: ClusterItemType[] = [
+const _Clusters: Omit<ClusterItemType, 'tableColumns'>[] = [
{
label: 'DataProxy',
value: 'DATAPROXY',
@@ -48,65 +48,81 @@ export const Clusters: ClusterItemType[] = [
value: 'TUBEMQ',
config: TubeMQ,
},
-].map(item => {
- const defaultConfig: ClsConfigItemType[] = [
- {
- type: 'input',
- label: i18n.t('pages.Clusters.Name'),
- name: 'name',
- rules: [{ required: true }],
- props: {
- maxLength: 128,
- },
- _inTable: true,
+];
+
+const defaultConfig: ClsConfigItemType[] = [
+ {
+ type: 'input',
+ label: i18n.t('pages.Clusters.Name'),
+ name: 'name',
+ rules: [{ required: true }],
+ props: {
+ maxLength: 128,
+ },
+ _inTable: true,
+ },
+ {
+ type: 'radio',
+ name: 'type',
+ label: i18n.t('pages.Clusters.Type'),
+ initialValue: _Clusters[0].value,
+ rules: [{ required: true }],
+ props: {
+ options: _Clusters.map(item => ({
+ label: item.label,
+ value: item.value,
+ })),
},
- {
- type: 'select',
- label: i18n.t('pages.Clusters.Tag'),
- name: 'clusterTags',
- rules: [{ required: true }],
- props: {
- mode: 'multiple',
- filterOption: false,
- options: {
- requestTrigger: ['onOpen', 'onSearch'],
- requestService: keyword => ({
- url: '/cluster/tag/list',
- method: 'POST',
- data: {
- keyword,
- pageNum: 1,
- pageSize: 20,
- },
- }),
- requestParams: {
- formatResult: result =>
- result?.list?.map(item => ({
- ...item,
- label: item.clusterTag,
- value: item.clusterTag,
- })),
+ },
+ {
+ type: 'select',
+ label: i18n.t('pages.Clusters.Tag'),
+ name: 'clusterTags',
+ rules: [{ required: true }],
+ props: {
+ mode: 'multiple',
+ filterOption: false,
+ options: {
+ requestTrigger: ['onOpen', 'onSearch'],
+ requestService: keyword => ({
+ url: '/cluster/tag/list',
+ method: 'POST',
+ data: {
+ keyword,
+ pageNum: 1,
+ pageSize: 20,
},
+ }),
+ requestParams: {
+ formatResult: result =>
+ result?.list?.map(item => ({
+ ...item,
+ label: item.clusterTag,
+ value: item.clusterTag,
+ })),
},
},
- _inTable: true,
},
- {
- type: <UserSelect mode="multiple" />,
- label: i18n.t('pages.Clusters.InCharges'),
- name: 'inCharges',
- rules: [{ required: true }],
- _inTable: true,
- },
- {
- type: 'textarea',
- label: i18n.t('pages.Clusters.Description'),
- name: 'description',
- props: {
- maxLength: 256,
- },
+ _inTable: true,
+ },
+ {
+ type: <UserSelect mode="multiple" />,
+ label: i18n.t('pages.Clusters.InCharges'),
+ name: 'inCharges',
+ rules: [{ required: true }],
+ _inTable: true,
+ },
+ {
+ type: 'textarea',
+ label: i18n.t('pages.Clusters.Description'),
+ name: 'description',
+ props: {
+ maxLength: 256,
},
- ];
+ },
+];
+
+export const Clusters: ClusterItemType[] = _Clusters.map(item => {
const config = defaultConfig.concat(item.config);
return {
diff --git a/inlong-dashboard/src/metas/sources/file.ts b/inlong-dashboard/src/metas/sources/file.ts
index 89746be8e..3e3286f26 100644
--- a/inlong-dashboard/src/metas/sources/file.ts
+++ b/inlong-dashboard/src/metas/sources/file.ts
@@ -50,7 +50,6 @@ const getForm = (type: 'form' | 'col' = 'form', { currentValues } = {} as any) =
label: i18n.t('meta.Sources.File.TimeOffset'),
name: 'timeOffset',
tooltip: i18n.t('meta.Sources.File.TimeOffsetHelp'),
- _inTable: true,
},
];
diff --git a/inlong-dashboard/src/pages/Clusters/CreateModal.tsx b/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
index 403f8e884..d266db4fc 100644
--- a/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
+++ b/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { useMemo } from 'react';
+import React, { useState, useMemo } from 'react';
import { Modal, message } from 'antd';
import { ModalProps } from 'antd/es/modal';
import FormGenerator, { useForm } from '@/components/FormGenerator';
@@ -27,14 +27,15 @@ import { Clusters } from '@/metas/clusters';
import i18n from '@/i18n';
export interface Props extends ModalProps {
- type: string;
// Require when edit
id?: string;
}
-const Comp: React.FC<Props> = ({ type, id, ...modalProps }) => {
+const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
const [form] = useForm();
+ const [type, setType] = useState(Clusters[0].value);
+
const { data: savedData, run: getData } = useRequest(
id => ({
url: `/cluster/get/${id}`,
@@ -48,6 +49,7 @@ const Comp: React.FC<Props> = ({ type, id, ...modalProps }) => {
}),
onSuccess: result => {
form.setFieldsValue(result);
+ setType(result.type);
},
},
);
@@ -57,7 +59,6 @@ const Comp: React.FC<Props> = ({ type, id, ...modalProps }) => {
const isUpdate = id;
const submitData = {
...values,
- type,
inCharges: values.inCharges?.join(','),
clusterTags: values.clusterTags?.join(','),
};
@@ -95,7 +96,12 @@ const Comp: React.FC<Props> = ({ type, id, ...modalProps }) => {
title={id ? i18n.t('pages.Clusters.Edit') : i18n.t('pages.Clusters.Create')}
onOk={onOk}
>
- <FormGenerator content={content} form={form} useMaxWidth />
+ <FormGenerator
+ content={content}
+ form={form}
+ onValuesChange={(c, values) => setType(values.type)}
+ useMaxWidth
+ />
</Modal>
);
};
diff --git a/inlong-dashboard/src/pages/Clusters/index.tsx b/inlong-dashboard/src/pages/Clusters/index.tsx
index 9fd9e9c94..5e16f1c45 100644
--- a/inlong-dashboard/src/pages/Clusters/index.tsx
+++ b/inlong-dashboard/src/pages/Clusters/index.tsx
@@ -186,9 +186,8 @@ const Comp: React.FC = () => {
<CreateModal
{...createModal}
- type={options.type as any}
visible={createModal.visible as boolean}
- onOk={async values => {
+ onOk={async () => {
await getList();
setCreateModal({ visible: false });
}}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx b/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx
index 04871e68d..d44dc3386 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx
@@ -18,22 +18,19 @@
*/
import React, { useCallback, useMemo, useState } from 'react';
-import { Modal } from 'antd';
+import { Modal, message } from 'antd';
import { ModalProps } from 'antd/es/modal';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { useRequest, useUpdateEffect } from '@/hooks';
import { useTranslation } from 'react-i18next';
import { FormItemProps } from '@/components/FormGenerator';
import { sources, SourceType } from '@/metas/sources';
+import request from '@/utils/request';
export interface Props extends ModalProps {
- type: 'MYSQL_BINLOG' | 'FILE';
// When editing, use the ID to call the interface for obtaining details
id?: string;
- // Pass when editing, directly echo the record data
- record?: Record<string, any>;
- // Additional form configuration
- content?: FormItemProps[];
+ inlongGroupId?: string;
}
const sourcesMap: Record<string, SourceType> = sources.reduce(
@@ -44,12 +41,14 @@ const sourcesMap: Record<string, SourceType> = sources.reduce(
{},
);
-const Comp: React.FC<Props> = ({ type, id, content = [], record, ...modalProps }) => {
+const Comp: React.FC<Props> = ({ id, inlongGroupId, ...modalProps }) => {
const [form] = useForm();
const { t } = useTranslation();
const [currentValues, setCurrentValues] = useState({});
+ const [type, setType] = useState(sources[0].value);
+
const toFormVals = useCallback(
v => {
const mapFunc = sourcesMap[type]?.toFormValues;
@@ -79,14 +78,29 @@ const Comp: React.FC<Props> = ({ type, id, content = [], record, ...modalProps }
onSuccess: result => {
form.setFieldsValue(result);
setCurrentValues(result);
+ setType(result.sourceType);
},
},
);
const onOk = async () => {
const values = await form.validateFields();
- if (data) values.version = data.version;
- modalProps?.onOk(toSubmitVals(values));
+ const submitData = toSubmitVals(values);
+ const isUpdate = Boolean(id);
+ if (isUpdate) {
+ submitData.id = id;
+ submitData.version = data?.version;
+ }
+ await request({
+ url: `/source/${isUpdate ? 'update' : 'save'}`,
+ method: 'POST',
+ data: {
+ ...submitData,
+ inlongGroupId,
+ },
+ });
+ modalProps?.onOk(submitData);
+ message.success(t('pages.GroupDetail.Sources.SaveSuccessfully'));
};
useUpdateEffect(() => {
@@ -95,9 +109,6 @@ const Comp: React.FC<Props> = ({ type, id, content = [], record, ...modalProps }
form.resetFields(); // Note that it will cause the form to remount to initiate a select request
if (id) {
getData(id);
- } else if (!id && Object.keys(record || {})?.length) {
- form.setFieldsValue(toFormVals(record));
- setCurrentValues(toFormVals(record));
}
} else {
setCurrentValues({});
@@ -111,23 +122,62 @@ const Comp: React.FC<Props> = ({ type, id, content = [], record, ...modalProps }
form,
}) as FormItemProps[];
return [
+ {
+ type: 'select',
+ label: t('pages.GroupDetail.Sources.DataStreams'),
+ name: 'inlongStreamId',
+ props: {
+ disabled: !!id,
+ options: {
+ requestService: {
+ url: '/stream/list',
+ method: 'POST',
+ data: {
+ pageNum: 1,
+ pageSize: 1000,
+ inlongGroupId,
+ },
+ },
+ requestParams: {
+ formatResult: result =>
+ result?.list.map(item => ({
+ label: item.inlongStreamId,
+ value: item.inlongStreamId,
+ })) || [],
+ },
+ },
+ },
+ rules: [{ required: true }],
+ },
{
name: 'sourceName',
type: 'input',
- label: t('components.AccessHelper.DataSourcesEditor.CreateModal.DataSourceName'),
+ label: t('meta.Sources.Name'),
+ rules: [{ required: true }],
+ props: {
+ disabled: !!id,
+ },
+ },
+ {
+ name: 'sourceType',
+ type: 'radio',
+ label: t('meta.Sources.Type'),
rules: [{ required: true }],
+ initialValue: type,
props: {
disabled: !!id,
+ options: sources,
+ onChange: e => setType(e.target.value),
},
} as FormItemProps,
].concat(config);
- }, [type, id, currentValues, form, t]);
+ }, [type, id, currentValues, form, t, inlongGroupId]);
return (
<>
<Modal {...modalProps} title={sourcesMap[type]?.label} width={666} onOk={onOk}>
<FormGenerator
- content={content.concat(formContent)}
+ content={formContent}
onValuesChange={vals => setCurrentValues(prev => ({ ...prev, ...vals }))}
allValues={currentValues}
form={form}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx b/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx
index 8c2d85d03..955c626e1 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx
@@ -86,26 +86,6 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
},
);
- const onSave = async values => {
- const isUpdate = createModal.id;
- const submitData = {
- ...values,
- inlongGroupId: inlongGroupId,
- sourceType: options.sourceType,
- };
- if (isUpdate) {
- submitData.id = createModal.id;
- }
-
- await request({
- url: `/source/${isUpdate ? 'update' : 'save'}`,
- method: 'POST',
- data: submitData,
- });
- await getList();
- message.success(i18n.t('pages.GroupDetail.Sources.SaveSuccessfully'));
- };
-
const onEdit = ({ id }) => {
setCreateModal({ visible: true, id });
};
@@ -167,7 +147,7 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
dataIndex: 'inlongStreamId',
},
{
- title: i18n.t('components.AccessHelper.DataSourcesEditor.CreateModal.DataSourceName'),
+ title: i18n.t('meta.Sources.Name'),
dataIndex: 'sourceName',
},
]
@@ -197,38 +177,6 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
} as any,
]);
- const createContent = [
- {
- type: 'select',
- label: i18n.t('pages.GroupDetail.Sources.DataStreams'),
- name: 'inlongStreamId',
- props: {
- notFoundContent: i18n.t('pages.GroupDetail.Sources.NoDataStreams'),
- disabled: !!createModal.id,
- options: {
- requestService: {
- url: '/stream/list',
- method: 'POST',
- data: {
- pageNum: 1,
- pageSize: 1000,
- inlongGroupId,
- },
- },
- requestParams: {
- ready: !!(createModal.visible && !createModal.id),
- formatResult: result =>
- result?.list.map(item => ({
- label: item.inlongStreamId,
- value: item.inlongStreamId,
- })) || [],
- },
- },
- },
- rules: [{ required: true }],
- },
- ];
-
return (
<>
<HighTable
@@ -255,11 +203,10 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
<DetailModal
{...createModal}
- type={options.sourceType as any}
- content={createContent}
+ inlongGroupId={inlongGroupId}
visible={createModal.visible as boolean}
- onOk={async values => {
- await onSave(values);
+ onOk={async () => {
+ await getList();
setCreateModal({ visible: false });
}}
onCancel={() => setCreateModal({ visible: false })}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStorage/DetailModal.tsx b/inlong-dashboard/src/pages/GroupDetail/DataStorage/DetailModal.tsx
index 950f5b7f4..73ca25892 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStorage/DetailModal.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataStorage/DetailModal.tsx
@@ -18,32 +18,20 @@
*/
import React, { useMemo, useState, useCallback } from 'react';
-import { Modal } from 'antd';
+import { Modal, message } from 'antd';
import { ModalProps } from 'antd/es/modal';
import { useRequest, useUpdateEffect } from '@/hooks';
import { useTranslation } from 'react-i18next';
-import FormGenerator, {
- useForm,
- FormItemProps,
- FormGeneratorProps,
-} from '@/components/FormGenerator';
+import FormGenerator, { useForm, FormItemProps } from '@/components/FormGenerator';
import { Sinks, SinkType } from '@/metas/sinks';
+import request from '@/utils/request';
export interface DetailModalProps extends ModalProps {
inlongGroupId: string;
- name?: string;
- content?: FormItemProps[];
// (True operation, save and adjust interface) Need to upload when editing
id?: string;
- // (False operation) Need to pass when editing, row data
- record?: Record<string, any>;
- sinkType: string;
- dataType?: string;
- // defaultRowTypeFields, which can be used to auto-fill form default values
- defaultRowTypeFields?: Record<string, unknown>[];
// others
onOk?: (values) => void;
- onValuesChange?: FormGeneratorProps['onValuesChange'];
}
const SinksMap: Record<string, SinkType> = Sinks.reduce(
@@ -54,43 +42,14 @@ const SinksMap: Record<string, SinkType> = Sinks.reduce(
{},
);
-const Comp: React.FC<DetailModalProps> = ({
- inlongGroupId,
- id,
- record,
- sinkType,
- name,
- content = [],
- dataType,
- defaultRowTypeFields,
- onValuesChange,
- ...modalProps
-}) => {
+const Comp: React.FC<DetailModalProps> = ({ inlongGroupId, id, ...modalProps }) => {
const [form] = useForm();
const { t } = useTranslation();
const [currentValues, setCurrentValues] = useState({});
- const fieldListKey = useMemo(() => {
- return {
- HIVE: {
- // Field name of the field array form
- columnsKey: 'sinkFieldList',
- // In addition to the defaultRowTypeFields field that is populated by default, additional fields that need to be populated
- // The left is the defaultRowTypeFields field, and the right is the newly filled field
- restMapping: {
- fieldName: 'fieldName',
- },
- },
- CLICKHOUSE: {
- columnsKey: 'sinkFieldList',
- restMapping: {
- fieldName: 'fieldName',
- },
- },
- }[sinkType];
- }, [sinkType]);
+ const [sinkType, setSinkType] = useState(Sinks[0].value);
const toFormVals = useCallback(
v => {
@@ -117,9 +76,11 @@ const Comp: React.FC<DetailModalProps> = ({
}),
{
manual: true,
+ formatResult: result => toFormVals(result),
onSuccess: result => {
- form.setFieldsValue(toFormVals(result));
- setCurrentValues(toFormVals(result));
+ form.setFieldsValue(result);
+ setCurrentValues(result);
+ setSinkType(result.sinkType);
},
},
);
@@ -130,43 +91,6 @@ const Comp: React.FC<DetailModalProps> = ({
form.resetFields(); // Note that it will cause the form to remount to initiate a select request
if (id) {
getData(id);
- return;
- }
- if (Object.keys(record || {})?.length) {
- form.setFieldsValue(toFormVals(record));
- setCurrentValues(toFormVals(record));
- } else {
- const usefulDefaultRowTypeFields = defaultRowTypeFields?.filter(
- item => item.fieldName && item.fieldType,
- );
- if (fieldListKey && usefulDefaultRowTypeFields?.length) {
- const getFieldListColumns = Sinks.find(item => item.value === sinkType)
- ?.getFieldListColumns;
- form.setFieldsValue({
- [fieldListKey.columnsKey]: usefulDefaultRowTypeFields?.map(item => ({
- // The default value defined by cloumns
- ...getFieldListColumns(dataType).reduce(
- (acc, cur) => ({
- ...acc,
- [cur.dataIndex]: cur.initialValue,
- }),
- {},
- ),
- // Extra fill
- ...Object.keys(fieldListKey.restMapping).reduce(
- (acc, key) => ({
- ...acc,
- [fieldListKey.restMapping[key]]: item[key],
- }),
- {},
- ),
- // Default fill
- sourceFieldName: item.fieldName,
- sourceFieldType: item.fieldType,
- fieldComment: item.fieldComment,
- })),
- });
- }
}
} else {
setCurrentValues({});
@@ -179,10 +103,36 @@ const Comp: React.FC<DetailModalProps> = ({
currentValues,
inlongGroupId,
isEdit: !!id,
- dataType,
form,
}) as FormItemProps[];
return [
+ {
+ type: 'select',
+ label: t('pages.GroupDetail.Sink.DataStreams'),
+ name: 'inlongStreamId',
+ props: {
+ disabled: !!id,
+ options: {
+ requestService: {
+ url: '/stream/list',
+ method: 'POST',
+ data: {
+ pageNum: 1,
+ pageSize: 1000,
+ inlongGroupId,
+ },
+ },
+ requestParams: {
+ formatResult: result =>
+ result?.list.map(item => ({
+ label: item.inlongStreamId,
+ value: item.inlongStreamId,
+ })) || [],
+ },
+ },
+ },
+ rules: [{ required: true }],
+ },
{
name: 'sinkName',
type: 'input',
@@ -198,6 +148,18 @@ const Comp: React.FC<DetailModalProps> = ({
disabled: !!id,
},
},
+ {
+ name: 'sinkType',
+ type: 'select',
+ label: t('meta.Sinks.SinkType'),
+ rules: [{ required: true }],
+ initialValue: sinkType,
+ props: {
+ disabled: !!id,
+ options: Sinks,
+ onChange: value => setSinkType(value),
+ },
+ },
{
name: 'description',
type: 'textarea',
@@ -208,30 +170,39 @@ const Comp: React.FC<DetailModalProps> = ({
},
} as FormItemProps,
].concat(config);
- }, [sinkType, dataType, inlongGroupId, id, currentValues, form, t]);
+ }, [sinkType, inlongGroupId, id, currentValues, form, t]);
const onOk = async () => {
const values = await form.validateFields();
delete values._showHigher; // delete front-end key
- if (data) values.version = data.version;
- modalProps.onOk && modalProps.onOk(toSubmitVals(values));
+ const submitData = toSubmitVals(values);
+ const isUpdate = Boolean(id);
+ if (isUpdate) {
+ submitData.id = id;
+ submitData.version = data?.version;
+ }
+ await request({
+ url: isUpdate ? '/sink/update' : '/sink/save',
+ method: 'POST',
+ data: {
+ ...submitData,
+ inlongGroupId,
+ },
+ });
+ modalProps?.onOk(submitData);
+ message.success(t('basic.OperatingSuccess'));
};
const onValuesChangeHandler = (...rest) => {
setCurrentValues(prev => ({ ...prev, ...rest[1] }));
-
- if (onValuesChange) {
- (onValuesChange as any)(...rest);
- }
};
return (
<Modal title={SinksMap[sinkType]?.label} width={1200} {...modalProps} onOk={onOk}>
<FormGenerator
- name={name}
labelCol={{ span: 4 }}
wrapperCol={{ span: 20 }}
- content={content.concat(formContent)}
+ content={formContent}
form={form}
allValues={data}
onValuesChange={onValuesChangeHandler}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStorage/index.tsx b/inlong-dashboard/src/pages/GroupDetail/DataStorage/index.tsx
index c7e1472ab..07196f437 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStorage/index.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataStorage/index.tsx
@@ -68,8 +68,6 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
sinkType: Sinks[0].value,
});
- const [curDataStreamIdentifier, setCurDataStreamIdentifier] = useState<string>();
-
const [createModal, setCreateModal] = useState<Record<string, unknown>>({
visible: false,
});
@@ -87,44 +85,8 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
},
);
- const { data: streamList = [] } = useRequest(
- {
- url: '/stream/list',
- method: 'POST',
- data: {
- pageNum: 1,
- pageSize: 1000,
- inlongGroupId,
- },
- },
- {
- ready: !!createModal.visible,
- formatResult: result => result?.list || [],
- },
- );
-
- const onSave = async values => {
- const isUpdate = createModal.id;
- const submitData = {
- ...values,
- sinkType: options.sinkType,
- inlongGroupId: inlongGroupId,
- };
- if (isUpdate) {
- submitData.id = createModal.id;
- }
- await request({
- url: isUpdate ? '/sink/update' : '/sink/save',
- method: 'POST',
- data: submitData,
- });
- await getList();
- message.success(i18n.t('basic.OperatingSuccess'));
- };
-
- const onEdit = ({ id, inlongStreamId }) => {
+ const onEdit = ({ id }) => {
setCreateModal({ visible: true, id });
- setCurDataStreamIdentifier(inlongStreamId);
};
const onDelete = ({ id }) => {
@@ -178,28 +140,6 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
[],
);
- const createContent = useMemo(
- () => [
- {
- type: 'select',
- label: i18n.t('pages.GroupDetail.Sink.DataStreams'),
- name: 'inlongStreamId',
- props: {
- notFoundContent: i18n.t('pages.GroupDetail.Sink.NoDataStreams'),
- disabled: !!createModal.id,
- options: streamList.map(item => ({
- label: item.inlongStreamId,
- value: item.inlongStreamId,
- })),
- },
- rules: [{ required: true }],
- },
- ],
- [createModal.id, streamList],
- );
-
- const streamItem = streamList.find(item => item.inlongStreamId === curDataStreamIdentifier);
-
const columns = [
{
title: i18n.t('pages.GroupDetail.Sink.DataStreams'),
@@ -259,13 +199,9 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
<DetailModal
{...createModal}
inlongGroupId={inlongGroupId}
- content={createContent}
- sinkType={options.sinkType as any}
visible={createModal.visible as boolean}
- dataType={streamItem?.dataType}
- onValuesChange={(c, v) => setCurDataStreamIdentifier(v?.inlongStreamId)}
- onOk={async values => {
- await onSave(values);
+ onOk={async () => {
+ await getList();
setCreateModal({ visible: false });
}}
onCancel={() => setCreateModal({ visible: false })}