This is an automated email from the ASF dual-hosted git repository.
healchow 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 be60ede17 [INLONG-5035][Dashboard] Support version control for backend
APIs (#5048)
be60ede17 is described below
commit be60ede17ecf3e816f077b61f91c9fde0be2d838
Author: Daniel <[email protected]>
AuthorDate: Thu Jul 14 18:56:10 2022 +0800
[INLONG-5035][Dashboard] Support version control for backend APIs (#5048)
---
.../AccessHelper/DataSourcesEditor/CreateModal.tsx | 35 ++---
.../AccessHelper/DataStorageEditor/DetailModal.tsx | 1 +
inlong-dashboard/src/configs/routes/index.tsx | 2 +-
.../AccessDetail/DataStream/StreamItemModal.tsx | 7 +-
.../src/pages/AccessDetail/DataStream/helper.ts | 51 +------
.../src/pages/AccessDetail/DataStream/index.tsx | 4 +-
.../src/pages/AccessDetail/Info/index.tsx | 1 +
.../src/pages/ClusterTags/ClusterBindModal.tsx | 2 +-
.../src/pages/ClusterTags/TagDetailModal.tsx | 3 +-
.../src/pages/Clusters/CreateModal.tsx | 4 +-
.../src/pages/Clusters/NodeEditModal.tsx | 6 +-
.../src/pages/ConsumeCreate/Info/index.tsx | 1 -
.../src/pages/ConsumeDetail/Info/config.tsx | 113 +++++++++-------
.../src/pages/ConsumeDetail/Info/index.tsx | 82 +++++++-----
.../src/pages/ConsumeDetail/common.d.ts | 5 +-
inlong-dashboard/src/pages/ConsumeDetail/index.tsx | 147 +++++++++++++++++----
.../src/pages/UserManagement/DetailModal.tsx | 3 +-
17 files changed, 281 insertions(+), 186 deletions(-)
diff --git
a/inlong-dashboard/src/components/AccessHelper/DataSourcesEditor/CreateModal.tsx
b/inlong-dashboard/src/components/AccessHelper/DataSourcesEditor/CreateModal.tsx
index 9c120a693..519a5a0df 100644
---
a/inlong-dashboard/src/components/AccessHelper/DataSourcesEditor/CreateModal.tsx
+++
b/inlong-dashboard/src/components/AccessHelper/DataSourcesEditor/CreateModal.tsx
@@ -67,8 +67,26 @@ const Comp: React.FC<Props> = ({ type, id, content = [],
record, ...modalProps }
[type],
);
+ const { data, run: getData } = useRequest(
+ id => ({
+ url: `/source/get/${id}`,
+ params: {
+ sourceType: type,
+ },
+ }),
+ {
+ manual: true,
+ formatResult: result => toFormVals(result),
+ onSuccess: result => {
+ form.setFieldsValue(result);
+ setCurrentValues(result);
+ },
+ },
+ );
+
const onOk = async () => {
const values = await form.validateFields();
+ if (data) values.version = data.version;
modalProps?.onOk(toSubmitVals(values));
};
@@ -87,23 +105,6 @@ const Comp: React.FC<Props> = ({ type, id, content = [],
record, ...modalProps }
}
}, [modalProps.visible]);
- const { run: getData } = useRequest(
- id => ({
- url: `/source/get/${id}`,
- params: {
- sourceType: type,
- },
- }),
- {
- manual: true,
- formatResult: result => toFormVals(result),
- onSuccess: result => {
- form.setFieldsValue(result);
- setCurrentValues(result);
- },
- },
- );
-
const getCreateFormContent = useMemo(
() => currentValues => {
const config = {
diff --git
a/inlong-dashboard/src/components/AccessHelper/DataStorageEditor/DetailModal.tsx
b/inlong-dashboard/src/components/AccessHelper/DataStorageEditor/DetailModal.tsx
index c3186e969..9bdff00d5 100644
---
a/inlong-dashboard/src/components/AccessHelper/DataStorageEditor/DetailModal.tsx
+++
b/inlong-dashboard/src/components/AccessHelper/DataStorageEditor/DetailModal.tsx
@@ -213,6 +213,7 @@ const Comp: React.FC<DetailModalProps> = ({
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));
};
diff --git a/inlong-dashboard/src/configs/routes/index.tsx
b/inlong-dashboard/src/configs/routes/index.tsx
index 9ecd804af..1bfda4f25 100644
--- a/inlong-dashboard/src/configs/routes/index.tsx
+++ b/inlong-dashboard/src/configs/routes/index.tsx
@@ -60,7 +60,7 @@ const routes: RouteProps[] = [
childRoutes: [
{
path: '/create',
- component: () => import('@/pages/ConsumeCreate'),
+ component: () => import('@/pages/ConsumeDetail'),
exact: true,
},
{
diff --git
a/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx
b/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx
index 4f5313147..bc8c3b5bf 100644
--- a/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx
+++ b/inlong-dashboard/src/pages/AccessDetail/DataStream/StreamItemModal.tsx
@@ -94,16 +94,15 @@ const Comp: React.FC<Props> = ({ inlongGroupId, record,
mqType, ...modalProps })
const [form] = useForm();
const onOk = async () => {
const values = {
- ...pickObject(['id', 'inlongGroupId', 'inlongStreamId'], record),
+ ...pickObject(['id', 'inlongGroupId', 'inlongStreamId', 'version'],
record),
...(await form.validateFields()),
};
- const data = valuesToData(values ? [values] : [], inlongGroupId);
- const submitData = data.map(item => pickObject(['streamInfo'], item));
+ const submitData = valuesToData(values ? [values] : [], inlongGroupId);
await request({
url: '/stream/update',
method: 'POST',
- data: submitData?.[0]?.streamInfo,
+ data: submitData?.[0],
});
await modalProps?.onOk(values);
message.success(i18n.t('basic.OperatingSuccess'));
diff --git a/inlong-dashboard/src/pages/AccessDetail/DataStream/helper.ts
b/inlong-dashboard/src/pages/AccessDetail/DataStream/helper.ts
index a71cd5781..6f77c642b 100644
--- a/inlong-dashboard/src/pages/AccessDetail/DataStream/helper.ts
+++ b/inlong-dashboard/src/pages/AccessDetail/DataStream/helper.ts
@@ -20,50 +20,7 @@
// Convert form data into interface submission data format
export const valuesToData = (values, inlongGroupId) => {
const array = values.map(item => {
- const {
- inlongStreamId,
- predefinedFields = [],
- rowTypeFields = [],
- dataSourceType,
- dataSourcesConfig = [],
- streamSink = [],
- ...rest
- } = item;
- const output = {} as any;
- if (dataSourceType !== 'AUTO_PUSH') {
- output.sourceInfo = dataSourcesConfig.map(k => {
- return {
- ...k,
- sourceType: dataSourceType,
- inlongGroupId,
- inlongStreamId,
- };
- });
- } else {
- output.sourceInfo = [
- {
- sourceType: dataSourceType,
- sourceName: inlongStreamId,
- inlongGroupId,
- inlongStreamId,
- },
- ];
- }
-
- output.sinkInfo = streamSink.reduce((acc, type) => {
- if (!type) return acc;
-
- const data = rest[`streamSink${type}`] || [];
- delete rest[`streamSink${type}`];
- const formatData = data.map(ds => ({
- ...ds,
- inlongGroupId,
- inlongStreamId,
- sinkType: type,
- }));
-
- return acc.concat(formatData);
- }, []);
+ const { inlongStreamId, predefinedFields = [], rowTypeFields = [],
version, ...rest } = item;
const fieldList = predefinedFields.concat(rowTypeFields).map((item, idx)
=> ({
...item,
@@ -72,14 +29,14 @@ export const valuesToData = (values, inlongGroupId) => {
isPredefinedField: idx < predefinedFields.length ? 1 : 0,
}));
- output.streamInfo = {
+ const output = {
...rest,
inlongGroupId,
inlongStreamId,
- dataSourceType,
+ version,
};
- if (fieldList?.length) output.streamInfo.fieldList = fieldList;
+ if (fieldList?.length) output.fieldList = fieldList;
return output;
});
diff --git a/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx
b/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx
index a8b3962a6..47260411f 100644
--- a/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx
+++ b/inlong-dashboard/src/pages/AccessDetail/DataStream/index.tsx
@@ -119,7 +119,7 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props,
ref) => {
await request({
url: '/stream/update',
method: 'POST',
- data: data?.[0]?.streamInfo,
+ data: data?.[0],
});
} else {
// create
@@ -129,7 +129,7 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props,
ref) => {
await request({
url: '/stream/save',
method: 'POST',
- data: data?.[0]?.streamInfo,
+ data: data?.[0],
});
}
await getList();
diff --git a/inlong-dashboard/src/pages/AccessDetail/Info/index.tsx
b/inlong-dashboard/src/pages/AccessDetail/Info/index.tsx
index d2cf67e45..433ce4d0b 100644
--- a/inlong-dashboard/src/pages/AccessDetail/Info/index.tsx
+++ b/inlong-dashboard/src/pages/AccessDetail/Info/index.tsx
@@ -57,6 +57,7 @@ const Comp = ({ inlongGroupId, readonly, isCreate }: Props,
ref) => {
const submitData = {
...values,
+ version: data.version,
inCharges: values.inCharges?.join(','),
followers: values.followers?.join(','),
};
diff --git a/inlong-dashboard/src/pages/ClusterTags/ClusterBindModal.tsx
b/inlong-dashboard/src/pages/ClusterTags/ClusterBindModal.tsx
index 1705b0f11..9cecf3b1e 100644
--- a/inlong-dashboard/src/pages/ClusterTags/ClusterBindModal.tsx
+++ b/inlong-dashboard/src/pages/ClusterTags/ClusterBindModal.tsx
@@ -79,7 +79,7 @@ const Comp: React.FC<Props> = ({ clusterTag, ...modalProps })
=> {
formatResult: result =>
result?.list?.map(item => ({
...item,
- label: item.name,
+ label: `${item.name} (${item.type})`,
value: item.id,
})),
},
diff --git a/inlong-dashboard/src/pages/ClusterTags/TagDetailModal.tsx
b/inlong-dashboard/src/pages/ClusterTags/TagDetailModal.tsx
index 1790faed7..1e12913d3 100644
--- a/inlong-dashboard/src/pages/ClusterTags/TagDetailModal.tsx
+++ b/inlong-dashboard/src/pages/ClusterTags/TagDetailModal.tsx
@@ -33,7 +33,7 @@ export interface TagDetailModalProps extends ModalProps {
const TagDetailModal: React.FC<TagDetailModalProps> = ({ id, ...modalProps })
=> {
const [form] = useForm();
- const { run: getData } = useRequest(
+ const { data: savedData, run: getData } = useRequest(
id => ({
url: `/cluster/tag/get/${id}`,
}),
@@ -58,6 +58,7 @@ const TagDetailModal: React.FC<TagDetailModalProps> = ({ id,
...modalProps }) =>
};
if (isUpdate) {
submitData.id = id;
+ submitData.version = savedData?.version;
}
await request({
url: `/cluster/tag/${isUpdate ? 'update' : 'save'}`,
diff --git a/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
b/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
index a0e3a150f..3b2793509 100644
--- a/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
+++ b/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
@@ -35,7 +35,7 @@ export interface Props extends ModalProps {
const Comp: React.FC<Props> = ({ type, id, ...modalProps }) => {
const [form] = useForm();
- const { run: getData } = useRequest(
+ const { data: savedData, run: getData } = useRequest(
id => ({
url: `/cluster/get/${id}`,
}),
@@ -63,7 +63,7 @@ const Comp: React.FC<Props> = ({ type, id, ...modalProps })
=> {
};
if (isUpdate) {
submitData.id = id;
- // submitData.version = data?.version;
+ submitData.version = savedData?.version;
}
await request({
url: `/cluster/${isUpdate ? 'update' : 'save'}`,
diff --git a/inlong-dashboard/src/pages/Clusters/NodeEditModal.tsx
b/inlong-dashboard/src/pages/Clusters/NodeEditModal.tsx
index 1916d05f9..bd500d084 100644
--- a/inlong-dashboard/src/pages/Clusters/NodeEditModal.tsx
+++ b/inlong-dashboard/src/pages/Clusters/NodeEditModal.tsx
@@ -40,10 +40,6 @@ const NodeEditModal: React.FC<NodeEditModalProps> = ({ id,
type, clusterId, ...m
}),
{
manual: true,
- formatResult: result => ({
- ...result,
- // inCharges: result.inCharges.split(','),
- }),
onSuccess: result => {
form.setFieldsValue(result);
},
@@ -57,10 +53,10 @@ const NodeEditModal: React.FC<NodeEditModalProps> = ({ id,
type, clusterId, ...m
...values,
type,
parentId: savedData?.parentId || clusterId,
- // inCharges: values.inCharges?.join(','),
};
if (isUpdate) {
submitData.id = id;
+ submitData.version = savedData?.version;
}
await request({
url: `/cluster/node/${isUpdate ? 'update' : 'save'}`,
diff --git a/inlong-dashboard/src/pages/ConsumeCreate/Info/index.tsx
b/inlong-dashboard/src/pages/ConsumeCreate/Info/index.tsx
index 4ceab172d..f4f0e37b7 100644
--- a/inlong-dashboard/src/pages/ConsumeCreate/Info/index.tsx
+++ b/inlong-dashboard/src/pages/ConsumeCreate/Info/index.tsx
@@ -81,7 +81,6 @@ const Comp = ({ id }: Props, ref) => {
await request({
url: `/consumption/startProcess/${result}`,
method: 'POST',
- data,
});
return result;
};
diff --git a/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx
b/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx
index 6132b64ea..e4cfd04d9 100644
--- a/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx
+++ b/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx
@@ -17,59 +17,82 @@
* under the License.
*/
-import React from 'react';
import { genBasicFields } from '@/components/ConsumeHelper';
import i18n from '@/i18n';
-export const getFormContent = ({ editing, initialValues }) =>
- genBasicFields(
- [
- {
- type: 'text',
- label: i18n.t('pages.ConsumeDetail.Info.config.ConsumerGroupID'),
- name: 'consumerGroupId',
- rules: [{ required: true }],
- },
- 'consumerGroupName',
- 'inCharges',
- 'masterUrl',
- 'inlongGroupId',
- 'topic',
- 'filterEnabled',
- 'inlongStreamId',
- 'mqExtInfo.isDlq',
- 'mqExtInfo.deadLetterTopic',
- 'mqExtInfo.isRlq',
- 'mqExtInfo.retryLetterTopic',
- ],
- initialValues,
- ).map(item => {
- const obj = { ...item };
- if (typeof obj.suffix !== 'string') {
- delete obj.suffix;
- }
- delete obj.extra;
- if (!editing) {
- if (typeof obj.type === 'string') {
- obj.type = 'text';
- }
- if (obj.name === 'inCharges') {
- obj.type = <span>{initialValues?.inCharges?.join(', ')}</span>;
- }
- }
+export const getFormContent = ({ editing, initialValues, isCreate }) => {
+ const keys = [
+ !isCreate && {
+ type: 'text',
+ label: i18n.t('pages.ConsumeDetail.Info.config.ConsumerGroupID'),
+ name: 'consumerGroupId',
+ rules: [{ required: true }],
+ },
+ 'consumerGroupName',
+ 'inCharges',
+ !isCreate && 'masterUrl',
+ 'inlongGroupId',
+ 'topic',
+ 'filterEnabled',
+ 'inlongStreamId',
+ 'mqExtInfo.isDlq',
+ 'mqExtInfo.deadLetterTopic',
+ 'mqExtInfo.isRlq',
+ 'mqExtInfo.retryLetterTopic',
+ ].filter(Boolean);
- if (
- [
+ return isCreate
+ ? genBasicFields(keys, initialValues).map(item => {
+ return item;
+ })
+ : genBasicFields(keys, initialValues).map(item => ({
+ ...item,
+ type: transType(editing, item, initialValues),
+ suffix:
+ typeof item.suffix === 'object' && !editing
+ ? {
+ ...item.suffix,
+ type: 'text',
+ }
+ : item.suffix,
+ extra: null,
+ }));
+};
+
+function transType(editing: boolean, conf, initialValues) {
+ const arr = [
+ {
+ name: [
'consumerGroupId',
'consumerGroupName',
'inlongGroupId',
'topic',
'filterEnabled',
'inlongStreamId',
- ].includes(obj.name as string)
- ) {
- obj.type = 'text';
- }
+ ],
+ as: 'text',
+ active: true,
+ },
+ {
+ name: [
+ 'inCharges',
+ 'mqExtInfo.isDlq',
+ 'mqExtInfo.deadLetterTopic',
+ 'mqExtInfo.isRlq',
+ 'mqExtInfo.retryLetterTopic',
+ ],
+ as: 'text',
+ active: !editing,
+ },
+ ].reduce((acc, cur) => {
+ return acc.concat(Array.isArray(cur.name) ? cur.name.map(name => ({
...cur, name })) : cur);
+ }, []);
+
+ const map = new Map(arr.map(item => [item.name, item]));
+ if (map.has(conf.name)) {
+ const item = map.get(conf.name);
+ return item.active ? item.as : conf.type;
+ }
- return obj;
- });
+ return conf.type;
+}
diff --git a/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx
b/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx
index 7e4c28c87..b0d05dd04 100644
--- a/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx
+++ b/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx
@@ -17,8 +17,7 @@
* under the License.
*/
-import React from 'react';
-import ReactDom from 'react-dom';
+import React, { useState, useMemo, useImperativeHandle, forwardRef } from
'react';
import { Button, Space, message } from 'antd';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { useRequest, useBoolean } from '@/hooks';
@@ -29,12 +28,18 @@ import { getFormContent } from './config';
type Props = CommonInterface;
-const Comp: React.FC<Props> = ({ id, isActive, readonly, extraRef }) => {
+const Comp = ({ id, readonly, isCreate }: Props, ref) => {
const { t } = useTranslation();
const [editing, { setTrue, setFalse }] = useBoolean(false);
const [form] = useForm();
+ const isUpdate = useMemo(() => {
+ return !!id;
+ }, [id]);
+
+ const [changedValues, setChangedValues] = useState<Record<string,
unknown>>({});
+
const { data, run: getDetail } = useRequest(
{
url: `/consumption/get/${id}`,
@@ -46,27 +51,41 @@ const Comp: React.FC<Props> = ({ id, isActive, readonly,
extraRef }) => {
...result,
inCharges: result.inCharges?.split(',') || [],
}),
- onSuccess: data => form.setFieldsValue(data),
+ onSuccess: data => {
+ form.setFieldsValue(data);
+ setChangedValues(data);
+ },
},
);
- const onSave = async () => {
+ const onOk = async () => {
const values = await form.validateFields();
const submitData = {
...values,
inCharges: values.inCharges.join(','),
- consumerGroupId: values.consumerGroupName,
- mqType: values?.mqType || data?.mqType,
+ consumerGroupId: values.consumerGroupName || data?.consumerGroupId,
+ topic: Array.isArray(values.topic) ? values.topic.join(',') :
values.topic,
+ version: data?.version,
mqExtInfo: {
...values.mqExtInfo,
mqType: values.mqType,
},
};
- await request({
- url: `/consumption/update/${id}`,
+
+ const result = await request({
+ url: isUpdate ? `/consumption/update/${id}` : '/consumption/save',
method: 'POST',
data: submitData,
});
+ return result;
+ };
+
+ useImperativeHandle(ref, () => ({
+ onOk,
+ }));
+
+ const onSave = async () => {
+ await onOk();
await getDetail();
setFalse();
message.success(t('basic.OperatingSuccess'));
@@ -77,39 +96,38 @@ const Comp: React.FC<Props> = ({ id, isActive, readonly,
extraRef }) => {
setFalse();
};
- const Extra = () => {
- return editing ? (
- <Space>
- <Button type="primary" onClick={onSave}>
- {t('basic.Save')}
- </Button>
- <Button onClick={onCancel}>{t('basic.Cancel')}</Button>
- </Space>
- ) : (
- <Button type="primary" onClick={setTrue}>
- {t('basic.Edit')}
- </Button>
- );
- };
-
return (
- <>
+ <div style={{ position: 'relative' }}>
<FormGenerator
form={form}
content={getFormContent({
editing,
- initialValues: data,
+ initialValues: changedValues,
+ isCreate,
})}
allValues={data}
useMaxWidth={800}
+ onValuesChange={(c, v) => setChangedValues(prev => ({ ...prev, ...v
}))}
/>
- {isActive &&
- !readonly &&
- extraRef?.current &&
- ReactDom.createPortal(<Extra />, extraRef.current)}
- </>
+ {!isCreate && !readonly && (
+ <div style={{ position: 'absolute', top: 0, right: 0 }}>
+ {editing ? (
+ <Space>
+ <Button type="primary" onClick={onSave}>
+ {t('basic.Save')}
+ </Button>
+ <Button onClick={onCancel}>{t('basic.Cancel')}</Button>
+ </Space>
+ ) : (
+ <Button type="primary" onClick={setTrue}>
+ {t('basic.Edit')}
+ </Button>
+ )}
+ </div>
+ )}
+ </div>
);
};
-export default Comp;
+export default forwardRef(Comp);
diff --git a/inlong-dashboard/src/pages/ConsumeDetail/common.d.ts
b/inlong-dashboard/src/pages/ConsumeDetail/common.d.ts
index a1731b668..e92b23429 100644
--- a/inlong-dashboard/src/pages/ConsumeDetail/common.d.ts
+++ b/inlong-dashboard/src/pages/ConsumeDetail/common.d.ts
@@ -22,7 +22,6 @@ import React from 'react';
export interface CommonInterface {
id: number;
readonly?: boolean;
- isActive?: boolean;
- // extraRef of Tab
- extraRef?: React.RefObject<HTMLDivElement>;
+ isCreate?: boolean;
+ ref?: React.RefObject<unknown>;
}
diff --git a/inlong-dashboard/src/pages/ConsumeDetail/index.tsx
b/inlong-dashboard/src/pages/ConsumeDetail/index.tsx
index be4311460..0af00ef80 100644
--- a/inlong-dashboard/src/pages/ConsumeDetail/index.tsx
+++ b/inlong-dashboard/src/pages/ConsumeDetail/index.tsx
@@ -18,23 +18,34 @@
*/
import React, { useState, useMemo, useRef } from 'react';
-import { Tabs } from 'antd';
+import { Tabs, Button, Card, message, Steps, Space } from 'antd';
import { useTranslation } from 'react-i18next';
-import { PageContainer } from '@/components/PageContainer';
-import { useParams, useRequest } from '@/hooks';
+import { parse } from 'qs';
+import { PageContainer, FooterToolbar } from '@/components/PageContainer';
+import { useParams, useRequest, useSet, useHistory, useLocation } from
'@/hooks';
+import request from '@/utils/request';
import Info from './Info';
const Comp: React.FC = () => {
const { t } = useTranslation();
- const id = +useParams<{ id: string }>().id;
+ const history = useHistory();
+ const location = useLocation();
+ const _id = +useParams<{ id: string }>().id;
+
+ const qs = parse(location.search.slice(1));
+
+ const [current, setCurrent] = useState(+qs.step || 0);
+ const [, { add: addOpened, has: hasOpened }] = useSet([current]);
+ const [confirmLoading, setConfirmLoading] = useState(false);
+ const [id, setId] = useState(_id);
+ const childRef = useRef(null);
+ const [isCreate] = useState(location.pathname.indexOf('/consume/create') ===
0);
const { data } = useRequest(`/consumption/get/${id}`, {
ready: !!id,
refreshDeps: [id],
});
- const extraRef = useRef<HTMLDivElement>();
-
const isReadonly = useMemo(() => [11, 20, 22].includes(data?.status),
[data]);
const list = useMemo(
@@ -48,30 +59,118 @@ const Comp: React.FC = () => {
[t],
);
- const [actived, setActived] = useState(list[0].value);
+ const onOk = async current => {
+ const onOk = childRef?.current?.onOk;
+ setConfirmLoading(true);
+ try {
+ const result = onOk && (await onOk());
+ if (current === 0) {
+ setId(result);
+ history.push({
+ search: `?id=${result}&step=1`,
+ });
+ }
+ } finally {
+ setConfirmLoading(false);
+ }
+ };
+
+ const onSubmit = async () => {
+ await request({
+ url: `/consumption/startProcess/${id}`,
+ method: 'POST',
+ data,
+ });
+ message.success(t('basic.OperatingSuccess'));
+ history.push('/consume');
+ };
+
+ const Footer = () => (
+ <Space style={{ display: 'flex', justifyContent: 'center' }}>
+ {current > 0 && (
+ <Button onClick={() => setCurrent(current -
1)}>{t('pages.ConsumeCreate.Prev')}</Button>
+ )}
+ {current !== list.length - 1 && (
+ <Button
+ type="primary"
+ loading={confirmLoading}
+ onClick={async () => {
+ await onOk(current);
+ const newCurrent = current + 1;
+ setCurrent(newCurrent);
+ if (!hasOpened(newCurrent)) addOpened(newCurrent);
+ }}
+ >
+ {t('pages.ConsumeCreate.Next')}
+ </Button>
+ )}
+ {current === list.length - 1 && (
+ <Button
+ type="primary"
+ onClick={async () => {
+ await onOk(current);
+ await onSubmit();
+ }}
+ >
+ {t('pages.ConsumeCreate.Submit')}
+ </Button>
+ )}
+ <Button onClick={() =>
history.push('/consume')}>{t('pages.ConsumeCreate.Back')}</Button>
+ </Space>
+ );
+
+ const Div = isCreate ? Card : Tabs;
return (
<PageContainer
breadcrumb={[
- { name:
`${t('pages.ConsumeDetail.ConsumptionDetails')}${data?.consumerGroupId}` },
+ {
+ name: isCreate
+ ? t('pages.ConsumeCreate.NewConsume')
+ : `${t('pages.ConsumeDetail.ConsumptionDetails')}${data?.id}`,
+ },
]}
+ useDefaultContainer={!isCreate}
>
- <Tabs
- activeKey={actived}
- onChange={val => setActived(val)}
- tabBarExtraContent={<div ref={extraRef} />}
- >
- {list.map(({ content: Content, ...item }) => (
- <Tabs.TabPane tab={item.label} key={item.value}>
- <Content
- id={id}
- isActive={actived === item.value}
- readonly={isReadonly}
- extraRef={extraRef}
- />
- </Tabs.TabPane>
- ))}
- </Tabs>
+ {isCreate && (
+ <Steps
+ current={current}
+ size="small"
+ style={{ marginBottom: 20, width: 600 }}
+ onChange={c => setCurrent(c)}
+ >
+ {list.map(item => (
+ <Steps.Step key={item.label} title={item.label} />
+ ))}
+ </Steps>
+ )}
+
+ <Div>
+ {list.map(({ content: Content, ...item }, index) => {
+ // Lazy load the content of the step, and at the same time make the
loaded useCache content not destroy
+ const child =
+ !isCreate || hasOpened(index) ? (
+ <Content
+ id={id}
+ readonly={isReadonly}
+ isCreate={isCreate}
+ ref={index === current ? childRef : null}
+ />
+ ) : null;
+
+ return isCreate ? (
+ <div key={item.label} style={{ display: `${index === current ?
'block' : 'none'}` }}>
+ {child}
+ </div>
+ ) : (
+ <Tabs.TabPane tab={item.label} key={item.value}>
+ {child}
+ </Tabs.TabPane>
+ );
+ })}
+ </Div>
+
+ {isCreate && <FooterToolbar extra={<Footer />} />}
</PageContainer>
);
};
diff --git a/inlong-dashboard/src/pages/UserManagement/DetailModal.tsx
b/inlong-dashboard/src/pages/UserManagement/DetailModal.tsx
index 22bac8699..a7c37ab5a 100644
--- a/inlong-dashboard/src/pages/UserManagement/DetailModal.tsx
+++ b/inlong-dashboard/src/pages/UserManagement/DetailModal.tsx
@@ -75,7 +75,7 @@ const content = [
const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
const [form] = useForm();
- const { run: getData } = useRequest(
+ const { data: savedData, run: getData } = useRequest(
id => ({
url: `/user/get/${id}`,
}),
@@ -92,6 +92,7 @@ const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
const isUpdate = id;
if (isUpdate) {
values.id = id;
+ values.version = savedData?.version;
}
await request({
url: isUpdate ? '/user/update' : '/user/register',