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 <lee...@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 })}