You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by zi...@apache.org on 2022/08/24 06:33:42 UTC

[inlong] 01/03: [INLONG-5648][Dashboard] Optimize the create logic, support specifying specific types (#5649)

This is an automated email from the ASF dual-hosted git repository.

zirui pushed a commit to branch release-1.3.0
in repository https://gitbox.apache.org/repos/asf/inlong.git

commit 9b8a0c3352ce53701568d4a433f87d39b79996f7
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 })}