You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by do...@apache.org on 2022/10/27 03:08:41 UTC
[inlong] branch master updated: [INLONG-6273][Dashboard] Ability to load plugins asynchronously (#6295)
This is an automated email from the ASF dual-hosted git repository.
dockerzhang 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 d9b633eed [INLONG-6273][Dashboard] Ability to load plugins asynchronously (#6295)
d9b633eed is described below
commit d9b633eedd393e84bedcf5e67e994f91349c10f7
Author: Daniel <le...@apache.org>
AuthorDate: Thu Oct 27 11:08:37 2022 +0800
[INLONG-6273][Dashboard] Ability to load plugins asynchronously (#6295)
---
.../{consume/extends/index.tsx => DataStatic.ts} | 18 +-
inlong-dashboard/src/metas/DataWithBackend.ts | 122 ++++++++++
inlong-dashboard/src/metas/clusters/agent.tsx | 20 --
.../{index.tsx => common/ClusterDefaultInfo.ts} | 128 +++++-----
.../index.tsx => clusters/common/ClusterInfo.ts} | 8 +-
.../index.tsx => clusters/defaults/Agent.ts} | 7 +-
.../index.tsx => clusters/defaults/DataProxy.ts} | 7 +-
.../clusters/{pulsar.tsx => defaults/Pulsar.ts} | 44 ++--
.../clusters/{tubeMQ.tsx => defaults/TubeMq.ts} | 35 +--
.../clusters/defaults/index.ts} | 36 ++-
.../index.tsx => clusters/extends/index.ts} | 6 +-
.../extends/index.tsx => clusters/index.ts} | 9 +-
inlong-dashboard/src/metas/consume/index.tsx | 266 ---------------------
.../metas/consumes/common/ConsumeDefaultInfo.ts | 192 +++++++++++++++
.../index.tsx => consumes/common/ConsumeInfo.ts} | 8 +-
.../metas/{consume => consumes/common}/status.tsx | 0
.../src/metas/consumes/defaults/Pulsar.ts | 83 +++++++
.../tubeMQ.tsx => consumes/defaults/TubeMq.ts} | 56 ++---
.../consumes/defaults/index.ts} | 26 +-
.../index.tsx => consumes/extends/index.ts} | 6 +-
.../extends/index.tsx => consumes/index.ts} | 9 +-
.../src/metas/groups/common/GroupDefaultInfo.ts | 124 ++++++++++
.../dataProxy.tsx => groups/common/GroupInfo.ts} | 6 +-
.../src/metas/{group => groups/common}/status.tsx | 0
.../{group/index.tsx => groups/defaults/Pulsar.ts} | 239 ++++--------------
.../src/metas/groups/defaults/TubeMq.ts | 74 ++++++
.../config.tsx => metas/groups/defaults/index.ts} | 26 +-
.../extends/index.tsx => groups/extends/index.ts} | 6 +-
.../{consume/extends/index.tsx => groups/index.ts} | 9 +-
inlong-dashboard/src/metas/index.ts | 82 +++++++
.../src/metas/nodes/common/NodeDefaultInfo.ts | 89 +++++++
.../extends/index.tsx => nodes/common/NodeInfo.ts} | 8 +-
inlong-dashboard/src/metas/nodes/common/dao.ts | 93 +++++++
.../src/metas/nodes/{hive.tsx => defaults/Hive.ts} | 35 +--
.../extends/index.tsx => nodes/defaults/index.ts} | 15 +-
.../extends/index.tsx => nodes/extends/index.ts} | 6 +-
.../{consume/extends/index.tsx => nodes/index.ts} | 11 +-
inlong-dashboard/src/metas/nodes/index.tsx | 87 -------
.../src/metas/sources/common/SourceDefaultInfo.ts | 118 +++++++++
.../index.tsx => sources/common/SourceInfo.ts} | 8 +-
.../index.tsx => sources/defaults/AutoPush.ts} | 7 +-
.../metas/sources/{file.ts => defaults/File.ts} | 39 +--
.../sources/{binLog.ts => defaults/MysqlBinlog.ts} | 94 ++++----
.../config.tsx => metas/sources/defaults/index.ts} | 32 ++-
.../extends/index.tsx => sources/extends/index.ts} | 6 +-
inlong-dashboard/src/metas/sources/index.ts | 83 +------
.../common/StreamDefaultInfo.ts} | 127 +++++-----
.../autoPush.ts => streams/common/StreamInfo.ts} | 6 +-
.../metas/{stream => streams/common}/status.tsx | 0
.../index.tsx => streams/defaults/index.ts} | 10 +-
.../extends/index.tsx => streams/extends/index.ts} | 6 +-
.../extends/index.tsx => streams/index.ts} | 9 +-
.../metas/{consume/extends/index.tsx => types.ts} | 32 ++-
.../src/pages/Clusters/CreateModal.tsx | 15 +-
inlong-dashboard/src/pages/Clusters/index.tsx | 55 +++--
.../src/pages/ConsumeDashboard/config.tsx | 107 +++++----
.../src/pages/ConsumeDashboard/index.tsx | 6 +-
.../src/pages/ConsumeDetail/Info/config.tsx | 8 +-
.../src/pages/ConsumeDetail/Info/index.tsx | 22 +-
.../src/pages/GroupDashboard/config.tsx | 104 ++++----
.../src/pages/GroupDashboard/index.tsx | 6 +-
.../pages/GroupDetail/DataSources/DetailModal.tsx | 79 ++----
.../src/pages/GroupDetail/DataSources/index.tsx | 119 +++++----
.../GroupDetail/DataStream/StreamItemModal.tsx | 93 +++++--
.../src/pages/GroupDetail/DataStream/config.tsx | 20 +-
.../src/pages/GroupDetail/DataStream/index.tsx | 8 +-
.../src/pages/GroupDetail/Info/config.tsx | 9 +-
.../src/pages/GroupDetail/Info/index.tsx | 28 ++-
inlong-dashboard/src/pages/Nodes/DetailModal.tsx | 66 +++--
inlong-dashboard/src/pages/Nodes/index.tsx | 128 +++++-----
.../src/pages/ProcessDetail/Access.tsx | 9 +-
.../src/pages/ProcessDetail/AccessConfig.tsx | 20 +-
.../src/pages/ProcessDetail/Consume.tsx | 7 +-
.../src/pages/ProcessDetail/ConsumeConfig.tsx | 11 +-
inlong-dashboard/tsconfig.json | 3 +-
75 files changed, 2023 insertions(+), 1473 deletions(-)
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/DataStatic.ts
similarity index 65%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/DataStatic.ts
index 8a7c0bd8e..0059abdf8 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/DataStatic.ts
@@ -17,8 +17,18 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import i18n from '@/i18n';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export abstract class DataStatic {
+ static I18nMap: Record<string, unknown> = {};
+
+ static I18n(i18nkey: string): PropertyDecorator {
+ return (target: any, propertyKey: string) => {
+ const { I18nMap } = target.constructor;
+ target.constructor.I18nMap = {
+ ...I18nMap,
+ [propertyKey]: i18nkey.indexOf('.') !== -1 ? i18n.t(i18nkey) : i18nkey,
+ };
+ };
+ }
+}
diff --git a/inlong-dashboard/src/metas/DataWithBackend.ts b/inlong-dashboard/src/metas/DataWithBackend.ts
new file mode 100644
index 000000000..34cf70b39
--- /dev/null
+++ b/inlong-dashboard/src/metas/DataWithBackend.ts
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ColumnType } from 'antd/es/table';
+import type { FieldItemType } from '@/metas/common';
+import { isDevelopEnv } from '@/utils';
+import { DataStatic } from './DataStatic';
+
+interface PositionObjectType extends Record<string, unknown> {
+ position: ['before' | 'after', string];
+}
+
+function sortListPosition(list: PositionObjectType[], primaryPositionKey = 'name') {
+ const output: Record<string, unknown>[] = [];
+ const notFoundPosMap: Record<string, PositionObjectType> = {};
+ const _list = [...list];
+ let loopCount = 0;
+ while (_list.length) {
+ loopCount++;
+ if (loopCount > 500) {
+ console.error(
+ '[Apache InLong Error] The number of loops of the sorting algorithm array has reached the maximum limit, please check or adjust the configuration.',
+ );
+ break;
+ }
+ const listItem = _list.shift();
+ if (!listItem) continue;
+ if (listItem.position) {
+ const [positionType, positionName] = listItem.position;
+ const index = output.findIndex(item => item[primaryPositionKey] === positionName);
+ if (index !== -1) {
+ output.splice(positionType === 'before' ? index : index + 1, 0, listItem);
+ } else {
+ notFoundPosMap[positionName] = listItem;
+ }
+ } else {
+ output.push(listItem);
+ }
+ const currentItemName = listItem[primaryPositionKey] as string;
+ if (notFoundPosMap[currentItemName]) {
+ _list.push(notFoundPosMap[currentItemName]);
+ delete notFoundPosMap[currentItemName];
+ }
+ }
+
+ const notFoundPosList = Object.keys(notFoundPosMap).map(name => notFoundPosMap[name]);
+ return output.concat(notFoundPosList);
+}
+
+export abstract class DataWithBackend extends DataStatic {
+ static FieldList: FieldItemType[] = [];
+ static ColumnList: ColumnType<Record<string, any>>[] = [];
+
+ static FormField(config: FieldItemType): PropertyDecorator {
+ return (target: any, propertyKey: string) => {
+ const { I18nMap, FieldList } = target.constructor;
+ const newFieldList = [...FieldList];
+
+ if (isDevelopEnv()) {
+ // Hot refresh of the development env will have old data
+ const existIndex = newFieldList.findIndex(item => item.name === propertyKey);
+ if (existIndex !== -1) {
+ newFieldList.splice(existIndex, 1);
+ }
+ }
+
+ newFieldList.push({
+ ...config,
+ name: propertyKey,
+ label: I18nMap[propertyKey],
+ });
+
+ // console.log('--', target.constructor, target.constructor.timer);
+ // if (target.constructor.timer) {
+ // clearTimeout(target.constructor.timer);
+ // }
+ // target.constructor.timer = setTimeout(() => {
+ // sortListPosition(newFieldList);
+ // }, 0);
+ // const sortedFieldList = sortListPosition(newFieldList);
+
+ target.constructor.FieldList = newFieldList;
+ };
+ }
+
+ static TableColumn(config?: ColumnType<Record<string, any>>): PropertyDecorator {
+ return (target: any, propertyKey: string) => {
+ const { I18nMap, ColumnList } = target.constructor;
+ const oldIndex = ColumnList.findIndex(item => item.name === propertyKey);
+ const subColumnList = [...ColumnList];
+ if (oldIndex !== -1) {
+ subColumnList.splice(oldIndex, 1);
+ }
+ subColumnList.push({
+ ...(typeof config === 'object' ? config : {}),
+ dataIndex: propertyKey,
+ title: I18nMap[propertyKey],
+ });
+ target.constructor.ColumnList = subColumnList;
+ };
+ }
+
+ abstract parse<T, K>(data: T): K;
+
+ abstract stringify<T, K>(data: T): K;
+}
diff --git a/inlong-dashboard/src/metas/clusters/agent.tsx b/inlong-dashboard/src/metas/clusters/agent.tsx
deleted file mode 100644
index f2cf14150..000000000
--- a/inlong-dashboard/src/metas/clusters/agent.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import type { FieldItemType } from '@/metas/common';
-
-export const agent: FieldItemType[] = [];
diff --git a/inlong-dashboard/src/metas/clusters/index.tsx b/inlong-dashboard/src/metas/clusters/common/ClusterDefaultInfo.ts
similarity index 52%
rename from inlong-dashboard/src/metas/clusters/index.tsx
rename to inlong-dashboard/src/metas/clusters/common/ClusterDefaultInfo.ts
index 95d103903..0cb4c385c 100644
--- a/inlong-dashboard/src/metas/clusters/index.tsx
+++ b/inlong-dashboard/src/metas/clusters/common/ClusterDefaultInfo.ts
@@ -17,67 +17,45 @@
* under the License.
*/
-import React from 'react';
-import i18n from '@/i18n';
+import { DataWithBackend } from '@/metas/DataWithBackend';
import UserSelect from '@/components/UserSelect';
-import type { FieldItemType } from '@/metas/common';
-import { genFields, genForm, genTable } from '@/metas/common';
-import { agent } from './agent';
-import { dataProxy } from './dataProxy';
-import { pulsar } from './pulsar';
-import { tubeMQ } from './tubeMQ';
+import { clusters, defaultValue } from '..';
-const allClusters = [
- {
- label: 'Agent',
- value: 'AGENT',
- fields: agent,
- },
- {
- label: 'DataProxy',
- value: 'DATAPROXY',
- fields: dataProxy,
- },
- {
- label: 'Pulsar',
- value: 'PULSAR',
- fields: pulsar,
- },
- {
- label: 'TubeMQ',
- value: 'TUBEMQ',
- fields: tubeMQ,
- },
-];
+const { I18n, FormField, TableColumn } = DataWithBackend;
-const defaultCommonFields: FieldItemType[] = [
- {
+export class ClusterDefaultInfo extends DataWithBackend {
+ id: number;
+
+ @FormField({
type: 'input',
- label: i18n.t('pages.Clusters.Name'),
- name: 'name',
rules: [{ required: true }],
props: {
maxLength: 128,
},
- _renderTable: true,
- },
- {
- type: 'radio',
- name: 'type',
- label: i18n.t('pages.Clusters.Type'),
- initialValue: allClusters[0].value,
+ })
+ @TableColumn()
+ @I18n('pages.Clusters.Name')
+ name: string;
+
+ @FormField({
+ type: clusters.length > 3 ? 'select' : 'radio',
+ initialValue: defaultValue,
rules: [{ required: true }],
props: {
- options: allClusters.map(item => ({
- label: item.label,
- value: item.value,
- })),
+ options: clusters
+ .filter(item => item.value)
+ .map(item => ({
+ label: item.label,
+ value: item.value,
+ })),
},
- },
- {
+ })
+ @TableColumn()
+ @I18n('pages.Clusters.Type')
+ type: string;
+
+ @FormField({
type: 'select',
- label: i18n.t('pages.Clusters.Tag'),
- name: 'clusterTags',
rules: [{ required: true }],
props: {
mode: 'multiple',
@@ -103,33 +81,39 @@ const defaultCommonFields: FieldItemType[] = [
},
},
},
- _renderTable: true,
- },
- {
- type: <UserSelect mode="multiple" />,
- label: i18n.t('pages.Clusters.InCharges'),
- name: 'inCharges',
+ })
+ @TableColumn()
+ @I18n('pages.Clusters.Tag')
+ clusterTags: string;
+
+ @FormField({
+ type: UserSelect,
rules: [{ required: true }],
- _renderTable: true,
- },
- {
+ props: {
+ mode: 'multiple',
+ currentUserClosable: false,
+ },
+ })
+ @TableColumn()
+ @I18n('pages.Clusters.InCharges')
+ inCharges: string;
+
+ @FormField({
type: 'textarea',
- label: i18n.t('pages.Clusters.Description'),
- name: 'description',
props: {
maxLength: 256,
},
- },
-];
+ })
+ @I18n('pages.Clusters.Description')
+ description: string;
+
+ version?: number;
-export const clusters = allClusters.map(item => {
- const itemFields = defaultCommonFields.concat(item.fields);
- const fields = genFields(itemFields);
+ parse(data) {
+ return data;
+ }
- return {
- ...item,
- fields,
- form: genForm(fields),
- table: genTable(fields),
- };
-});
+ stringify(data) {
+ return data;
+ }
+}
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/clusters/common/ClusterInfo.ts
similarity index 83%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/clusters/common/ClusterInfo.ts
index 8a7c0bd8e..f14292db9 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/clusters/common/ClusterInfo.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { ClusterDefaultInfo } from './ClusterDefaultInfo';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export class ClusterInfo extends ClusterDefaultInfo {
+ // You can extends ClusterInfo at here...
+}
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/clusters/defaults/Agent.ts
similarity index 80%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/clusters/defaults/Agent.ts
index 8a7c0bd8e..d0f817001 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/clusters/defaults/Agent.ts
@@ -17,8 +17,7 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import { ClusterInfo } from '../common/ClusterInfo';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export default class AgentCluster extends ClusterInfo implements DataWithBackend {}
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/clusters/defaults/DataProxy.ts
similarity index 80%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/clusters/defaults/DataProxy.ts
index 8a7c0bd8e..8a0a6fb6f 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/clusters/defaults/DataProxy.ts
@@ -17,8 +17,7 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import { ClusterInfo } from '../common/ClusterInfo';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export default class DataProxyCluster extends ClusterInfo implements DataWithBackend {}
diff --git a/inlong-dashboard/src/metas/clusters/pulsar.tsx b/inlong-dashboard/src/metas/clusters/defaults/Pulsar.ts
similarity index 73%
rename from inlong-dashboard/src/metas/clusters/pulsar.tsx
rename to inlong-dashboard/src/metas/clusters/defaults/Pulsar.ts
index b1cd76276..443b7296d 100644
--- a/inlong-dashboard/src/metas/clusters/pulsar.tsx
+++ b/inlong-dashboard/src/metas/clusters/defaults/Pulsar.ts
@@ -18,42 +18,48 @@
*/
import i18n from '@/i18n';
-import type { FieldItemType } from '@/metas/common';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import { ClusterInfo } from '../common/ClusterInfo';
-export const pulsar: FieldItemType[] = [
- {
+const { I18n, FormField } = DataWithBackend;
+
+export default class PulsarCluster extends ClusterInfo implements DataWithBackend {
+ @FormField({
type: 'input',
- label: 'Service URL',
- name: 'url',
tooltip: i18n.t('pages.Clusters.Pulsar.ServiceUrlHelper'),
rules: [{ required: true }],
props: {
placeholder: 'pulsar://127.0.0.1:6650,127.0.1.2:6650',
},
- },
- {
+ })
+ @I18n('Service URL')
+ url: string;
+
+ @FormField({
type: 'input',
- label: 'Admin URL',
- name: 'adminUrl',
tooltip: i18n.t('pages.Clusters.Pulsar.AdminUrlHelper'),
rules: [{ required: true }],
props: {
placeholder: 'http://127.0.0.1:8080,127.0.1.2:8080',
},
- },
- {
+ })
+ @I18n('Admin URL')
+ adminUrl: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('pages.Clusters.Pulsar.Tenant'),
- name: 'tenant',
rules: [{ required: true }],
initialValue: 'public',
- },
- {
+ })
+ @I18n('pages.Clusters.Pulsar.Tenant')
+ tenant: string;
+
+ @FormField({
type: 'input',
- label: 'Token',
- name: 'token',
props: {
placeholder: 'Required if the cluster is configured with Token',
},
- },
-];
+ })
+ @I18n('Token')
+ token: string;
+}
diff --git a/inlong-dashboard/src/metas/clusters/tubeMQ.tsx b/inlong-dashboard/src/metas/clusters/defaults/TubeMq.ts
similarity index 75%
copy from inlong-dashboard/src/metas/clusters/tubeMQ.tsx
copy to inlong-dashboard/src/metas/clusters/defaults/TubeMq.ts
index 3a669e324..6519c4a45 100644
--- a/inlong-dashboard/src/metas/clusters/tubeMQ.tsx
+++ b/inlong-dashboard/src/metas/clusters/defaults/TubeMq.ts
@@ -18,35 +18,40 @@
*/
import i18n from '@/i18n';
-import type { FieldItemType } from '@/metas/common';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import { ClusterInfo } from '../common/ClusterInfo';
-export const tubeMQ: FieldItemType[] = [
- {
+const { I18n, FormField } = DataWithBackend;
+
+export default class TubeMqCluster extends ClusterInfo implements DataWithBackend {
+ @FormField({
type: 'input',
- label: 'RPC URL',
- name: 'url',
rules: [{ required: true }],
tooltip: i18n.t('pages.Clusters.Tube.MasterRpcUrlHelper'),
props: {
placeholder: '127.0.0.1:8715,127.0.1.2:8715',
},
- },
- {
+ })
+ @I18n('RPC URL')
+ url: string;
+
+ @FormField({
type: 'input',
- label: 'Web URL',
- name: 'masterWebUrl',
rules: [{ required: true }],
tooltip: i18n.t('pages.Clusters.Tube.MasterWebUrlHelper'),
props: {
placeholder: 'http://127.0.0.1:8080',
},
- },
- {
+ })
+ @I18n('Web URL')
+ masterWebUrl: string;
+
+ @FormField({
type: 'input',
- label: 'Token',
- name: 'token',
props: {
placeholder: 'Required if the cluster is configured with Token',
},
- },
-];
+ })
+ @I18n('Token')
+ token: string;
+}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx b/inlong-dashboard/src/metas/clusters/defaults/index.ts
similarity index 56%
copy from inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
copy to inlong-dashboard/src/metas/clusters/defaults/index.ts
index 9641bacd1..5ba19e0c7 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
+++ b/inlong-dashboard/src/metas/clusters/defaults/index.ts
@@ -17,18 +17,32 @@
* under the License.
*/
-import { streamForm } from '@/metas/stream';
-import { pickObjectArray } from '@/utils';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const getFilterFormContent = (defaultValues = {} as any) => [
+export const allDefaultClusters: MetaExportWithBackendList = [
{
- type: 'inputsearch',
- name: 'keyword',
- initialValue: defaultValues.keyword,
+ label: 'ALL',
+ value: '',
+ LoadEntity: () => import('../common/ClusterInfo').then(r => ({ default: r.ClusterInfo })),
+ },
+ {
+ label: 'Agent',
+ value: 'AGENT',
+ LoadEntity: () => import('./Agent'),
+ },
+ {
+ label: 'DataProxy',
+ value: 'DATAPROXY',
+ LoadEntity: () => import('./DataProxy'),
+ },
+ {
+ label: 'Pulsar',
+ value: 'PULSAR',
+ LoadEntity: () => import('./Pulsar'),
+ },
+ {
+ label: 'TubeMQ',
+ value: 'TUBEMQ',
+ LoadEntity: () => import('./TubeMq'),
},
- ...pickObjectArray(['status'], streamForm).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/clusters/extends/index.ts
similarity index 83%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/clusters/extends/index.ts
index 8a7c0bd8e..4d794befd 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/clusters/extends/index.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
+export const allExtendsClusters: MetaExportWithBackendList = [
+ // You can extends at here...
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/clusters/index.ts
similarity index 78%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/clusters/index.ts
index 8a7c0bd8e..2c6643083 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/clusters/index.ts
@@ -17,8 +17,9 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { allDefaultClusters } from './defaults';
+import { allExtendsClusters } from './extends';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export const clusters = allDefaultClusters.concat(allExtendsClusters);
+
+export const defaultValue = clusters[0].value;
diff --git a/inlong-dashboard/src/metas/consume/index.tsx b/inlong-dashboard/src/metas/consume/index.tsx
deleted file mode 100644
index 32ef3be34..000000000
--- a/inlong-dashboard/src/metas/consume/index.tsx
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import React from 'react';
-import UserSelect from '@/components/UserSelect';
-import type { FieldItemType } from '@/metas/common';
-import { genFields, genForm, genTable } from '@/metas/common';
-import i18n from '@/i18n';
-import { timestampFormat } from '@/utils';
-import {
- statusList,
- lastConsumerStatusList,
- genStatusTag,
- genLastConsumerStatusTag,
-} from './status';
-import { consumeExtends } from './extends';
-
-const consumeDefault: FieldItemType[] = [
- {
- type: 'input',
- label: i18n.t('meta.Consume.ConsumerGroupName'),
- name: 'consumerGroup',
- extra: i18n.t('meta.Consume.ConsumerGroupNameRules'),
- rules: [
- { required: true },
- {
- pattern: /^[0-9a-z_-]+$/,
- message: i18n.t('meta.Consume.ConsumerGroupNameRules'),
- },
- ],
- _renderTable: true,
- },
- {
- type: <UserSelect mode="multiple" currentUserClosable={false} />,
- label: i18n.t('meta.Consume.Owner'),
- name: 'inCharges',
- extra: i18n.t('meta.Consume.OwnersExtra'),
- rules: [{ required: true }],
- _renderTable: true,
- },
- {
- type: 'select',
- label: i18n.t('meta.Consume.TargetInlongGroupID'),
- name: 'inlongGroupId',
- extraNames: ['mqType'],
- rules: [{ required: true }],
- props: {
- showSearch: true,
- filterOption: false,
- options: {
- requestTrigger: ['onOpen', 'onSearch'],
- requestService: keyword => ({
- url: '/group/list',
- method: 'POST',
- data: {
- keyword,
- pageNum: 1,
- pageSize: 20,
- status: 130,
- },
- }),
- requestParams: {
- formatResult: result =>
- result?.list?.map(item => ({
- ...item,
- label: `${item.inlongGroupId} (${item.mqType})`,
- value: item.inlongGroupId,
- })),
- },
- },
- onChange: (value, option) => ({
- topic: undefined,
- mqType: option.mqType,
- }),
- },
- _renderTable: true,
- },
- {
- type: 'text',
- label: i18n.t('meta.Consume.MQType'),
- name: 'mqType',
- visible: false,
- _renderTable: true,
- },
- {
- type: 'select',
- label: i18n.t('meta.Consume.TopicName'),
- name: 'topic',
- rules: [{ required: true }],
- props: values => ({
- mode: values.mqType === 'PULSAR' ? 'multiple' : '',
- options: {
- requestService: `/group/getTopic/${values.inlongGroupId}`,
- requestParams: {
- formatResult: result =>
- result.mqType === 'TUBEMQ'
- ? [
- {
- label: result.mqResource,
- value: result.mqResource,
- },
- ]
- : result.streamTopics?.map(item => ({
- ...item,
- label: item.mqResource,
- value: item.mqResource,
- })) || [],
- },
- },
- onChange: (value, option) => {
- if (typeof value !== 'string') {
- return {
- inlongStreamId: option.map(item => item.streamTopics).join(','),
- };
- }
- },
- }),
- visible: values => !!values.inlongGroupId,
- _renderTable: true,
- },
- {
- type: 'select',
- label: i18n.t('basic.Status'),
- name: 'status',
- props: {
- allowClear: true,
- options: statusList,
- dropdownMatchSelectWidth: false,
- },
- visible: false,
- _renderTable: {
- render: text => genStatusTag(text),
- },
- },
- {
- type: 'input',
- label: i18n.t('pages.ConsumeDashboard.config.RecentConsumeTime'),
- name: 'lastConsumeTime',
- visible: false,
- _renderTable: {
- render: text => text && timestampFormat(text),
- },
- },
- {
- type: 'select',
- label: i18n.t('pages.ConsumeDashboard.config.OperatingStatus'),
- name: 'lastConsumeStatus',
- props: {
- allowClear: true,
- dropdownMatchSelectWidth: false,
- options: lastConsumerStatusList,
- },
- visible: false,
- _renderTable: {
- render: text => text && genLastConsumerStatusTag(text),
- },
- },
- {
- type: 'radio',
- label: i18n.t('meta.Consume.FilterEnabled'),
- name: 'filterEnabled',
- initialValue: 0,
- props: {
- options: [
- {
- label: i18n.t('meta.Consume.Yes'),
- value: 1,
- },
- {
- label: i18n.t('meta.Consume.No'),
- value: 0,
- },
- ],
- },
- rules: [{ required: true }],
- visible: values => !!values.mqType && values.mqType !== 'PULSAR',
- },
- {
- type: 'input',
- label: i18n.t('meta.Consume.TargetInlongStreamID'),
- name: 'inlongStreamId',
- rules: [{ required: true }],
- visible: values => values.filterEnabled,
- },
- {
- type: 'text',
- label: i18n.t('meta.Consume.MQAddress'),
- name: 'masterUrl',
- },
- {
- type: 'radio',
- label: 'isDlq',
- name: 'isDlq',
- initialValue: 0,
- rules: [{ required: true }],
- props: {
- options: [
- {
- label: i18n.t('meta.Consume.Yes'),
- value: 1,
- },
- {
- label: i18n.t('meta.Consume.No'),
- value: 0,
- },
- ],
- },
- visible: values => values.mqType === 'PULSAR',
- },
- {
- type: 'input',
- label: 'deadLetterTopic',
- name: 'deadLetterTopic',
- rules: [{ required: true }],
- visible: values => values?.isDlq && values.mqType === 'PULSAR',
- },
- {
- type: 'radio',
- label: 'isRlq',
- name: 'isRlq',
- initialValue: 0,
- rules: [{ required: true }],
- props: {
- options: [
- {
- label: i18n.t('meta.Consume.Yes'),
- value: 1,
- },
- {
- label: i18n.t('meta.Consume.No'),
- value: 0,
- },
- ],
- },
- visible: values => values?.isDlq && values.mqType === 'PULSAR',
- },
- {
- type: 'input',
- label: 'retryLetterTopic',
- name: 'retryLetterTopic',
- rules: [{ required: true }],
- visible: values => values?.isDlq && values?.isRlq && values.mqType === 'PULSAR',
- },
-];
-
-export const consume = genFields(consumeDefault, consumeExtends);
-
-export const consumeForm = genForm(consume);
-
-export const consumeTable = genTable(consume);
diff --git a/inlong-dashboard/src/metas/consumes/common/ConsumeDefaultInfo.ts b/inlong-dashboard/src/metas/consumes/common/ConsumeDefaultInfo.ts
new file mode 100644
index 000000000..bc8e65875
--- /dev/null
+++ b/inlong-dashboard/src/metas/consumes/common/ConsumeDefaultInfo.ts
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import UserSelect from '@/components/UserSelect';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import i18n from '@/i18n';
+import { timestampFormat } from '@/utils';
+import {
+ statusList,
+ lastConsumerStatusList,
+ genStatusTag,
+ genLastConsumerStatusTag,
+} from './status';
+
+const { I18n, FormField, TableColumn } = DataWithBackend;
+
+export class ConsumeDefaultInfo extends DataWithBackend {
+ readonly id: number;
+
+ @FormField({
+ type: 'input',
+ extra: i18n.t('meta.Consume.ConsumerGroupNameRules'),
+ rules: [
+ { required: true },
+ {
+ pattern: /^[0-9a-z_-]+$/,
+ message: i18n.t('meta.Consume.ConsumerGroupNameRules'),
+ },
+ ],
+ })
+ @TableColumn()
+ @I18n('meta.Consume.ConsumerGroupName')
+ consumerGroup: string;
+
+ @FormField({
+ type: UserSelect,
+ extra: i18n.t('meta.Consume.OwnersExtra'),
+ rules: [{ required: true }],
+ props: {
+ mode: 'multiple',
+ currentUserClosable: false,
+ },
+ })
+ @TableColumn()
+ @I18n('meta.Consume.Owner')
+ inCharges: string;
+
+ @FormField({
+ type: 'select',
+ extraNames: ['mqType'],
+ rules: [{ required: true }],
+ props: {
+ showSearch: true,
+ filterOption: false,
+ options: {
+ requestTrigger: ['onOpen', 'onSearch'],
+ requestService: keyword => ({
+ url: '/group/list',
+ method: 'POST',
+ data: {
+ keyword,
+ pageNum: 1,
+ pageSize: 20,
+ status: 130,
+ },
+ }),
+ requestParams: {
+ formatResult: result =>
+ result?.list?.map(item => ({
+ ...item,
+ label: `${item.inlongGroupId} (${item.mqType})`,
+ value: item.inlongGroupId,
+ })),
+ },
+ },
+ onChange: (value, option) => ({
+ topic: undefined,
+ mqType: option.mqType,
+ }),
+ },
+ })
+ @TableColumn()
+ @I18n('meta.Consume.TargetInlongGroupID')
+ inlongGroupId: string;
+
+ @TableColumn()
+ @I18n('meta.Consume.MQType')
+ mqType: string;
+
+ @FormField({
+ type: 'select',
+ rules: [{ required: true }],
+ props: values => ({
+ mode: values.mqType === 'PULSAR' ? 'multiple' : '',
+ options: {
+ requestService: `/group/getTopic/${values.inlongGroupId}`,
+ requestParams: {
+ formatResult: result =>
+ result.mqType === 'TUBEMQ'
+ ? [
+ {
+ label: result.mqResource,
+ value: result.mqResource,
+ },
+ ]
+ : result.streamTopics?.map(item => ({
+ ...item,
+ label: item.mqResource,
+ value: item.mqResource,
+ })) || [],
+ },
+ },
+ onChange: (value, option) => {
+ if (typeof value !== 'string') {
+ return {
+ inlongStreamId: option.map(item => item.streamTopics).join(','),
+ };
+ }
+ },
+ }),
+ visible: values => Boolean(values.inlongGroupId),
+ })
+ @TableColumn()
+ @I18n('meta.Consume.TopicName')
+ topic: string;
+
+ @FormField({
+ type: 'select',
+ props: {
+ allowClear: true,
+ options: statusList,
+ dropdownMatchSelectWidth: false,
+ },
+ visible: false,
+ })
+ @TableColumn({
+ render: text => genStatusTag(text),
+ })
+ @I18n('basic.Status')
+ readonly status: string;
+
+ @TableColumn({
+ render: text => text && timestampFormat(text),
+ })
+ @I18n('pages.ConsumeDashboard.config.RecentConsumeTime')
+ readonly lastConsumeTime: string;
+
+ @FormField({
+ type: 'select',
+ props: {
+ allowClear: true,
+ dropdownMatchSelectWidth: false,
+ options: lastConsumerStatusList,
+ },
+ visible: false,
+ })
+ @TableColumn({
+ render: text => text && genLastConsumerStatusTag(text),
+ })
+ @I18n('pages.ConsumeDashboard.config.OperatingStatus')
+ readonly lastConsumeStatus: string;
+
+ @FormField({
+ type: 'text',
+ })
+ @I18n('meta.Consume.MQAddress')
+ readonly masterUrl: string;
+
+ parse(data) {
+ return data;
+ }
+
+ stringify(data) {
+ return data;
+ }
+}
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/consumes/common/ConsumeInfo.ts
similarity index 83%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/consumes/common/ConsumeInfo.ts
index 8a7c0bd8e..a5ea8178d 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/consumes/common/ConsumeInfo.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { ConsumeDefaultInfo } from './ConsumeDefaultInfo';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export class ConsumeInfo extends ConsumeDefaultInfo {
+ // You can extends ConsumeInfo at here...
+}
diff --git a/inlong-dashboard/src/metas/consume/status.tsx b/inlong-dashboard/src/metas/consumes/common/status.tsx
similarity index 100%
rename from inlong-dashboard/src/metas/consume/status.tsx
rename to inlong-dashboard/src/metas/consumes/common/status.tsx
diff --git a/inlong-dashboard/src/metas/consumes/defaults/Pulsar.ts b/inlong-dashboard/src/metas/consumes/defaults/Pulsar.ts
new file mode 100644
index 000000000..f5a8ae6a3
--- /dev/null
+++ b/inlong-dashboard/src/metas/consumes/defaults/Pulsar.ts
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import i18n from '@/i18n';
+import { ConsumeInfo } from '../common/ConsumeInfo';
+
+const { I18n, FormField } = DataWithBackend;
+
+export default class PulsarConsume extends ConsumeInfo implements DataWithBackend {
+ @FormField({
+ type: 'radio',
+ initialValue: 0,
+ rules: [{ required: true }],
+ props: {
+ options: [
+ {
+ label: i18n.t('meta.Consume.Yes'),
+ value: 1,
+ },
+ {
+ label: i18n.t('meta.Consume.No'),
+ value: 0,
+ },
+ ],
+ },
+ })
+ @I18n('isDlq')
+ isDlq: 0 | 1;
+
+ @FormField({
+ type: 'input',
+ rules: [{ required: true }],
+ visible: values => values?.isDlq,
+ })
+ @I18n('deadLetterTopic')
+ deadLetterTopic: string;
+
+ @FormField({
+ type: 'radio',
+ initialValue: 0,
+ rules: [{ required: true }],
+ props: {
+ options: [
+ {
+ label: i18n.t('meta.Consume.Yes'),
+ value: 1,
+ },
+ {
+ label: i18n.t('meta.Consume.No'),
+ value: 0,
+ },
+ ],
+ },
+ visible: values => values?.isDlq,
+ })
+ @I18n('isRlq')
+ isRlq: 0 | 1;
+
+ @FormField({
+ type: 'input',
+ rules: [{ required: true }],
+ visible: values => values?.isDlq && values?.isRlq,
+ })
+ @I18n('retryLetterTopic')
+ retryLetterTopic: string;
+}
diff --git a/inlong-dashboard/src/metas/clusters/tubeMQ.tsx b/inlong-dashboard/src/metas/consumes/defaults/TubeMq.ts
similarity index 57%
rename from inlong-dashboard/src/metas/clusters/tubeMQ.tsx
rename to inlong-dashboard/src/metas/consumes/defaults/TubeMq.ts
index 3a669e324..9aa4ef7da 100644
--- a/inlong-dashboard/src/metas/clusters/tubeMQ.tsx
+++ b/inlong-dashboard/src/metas/consumes/defaults/TubeMq.ts
@@ -17,36 +17,38 @@
* under the License.
*/
+import { DataWithBackend } from '@/metas/DataWithBackend';
import i18n from '@/i18n';
-import type { FieldItemType } from '@/metas/common';
+import { ConsumeInfo } from '../common/ConsumeInfo';
-export const tubeMQ: FieldItemType[] = [
- {
- type: 'input',
- label: 'RPC URL',
- name: 'url',
- rules: [{ required: true }],
- tooltip: i18n.t('pages.Clusters.Tube.MasterRpcUrlHelper'),
+const { I18n, FormField } = DataWithBackend;
+
+export default class TubeMqConsume extends ConsumeInfo implements DataWithBackend {
+ @FormField({
+ type: 'radio',
+ initialValue: 0,
props: {
- placeholder: '127.0.0.1:8715,127.0.1.2:8715',
+ options: [
+ {
+ label: i18n.t('meta.Consume.Yes'),
+ value: 1,
+ },
+ {
+ label: i18n.t('meta.Consume.No'),
+ value: 0,
+ },
+ ],
},
- },
- {
- type: 'input',
- label: 'Web URL',
- name: 'masterWebUrl',
rules: [{ required: true }],
- tooltip: i18n.t('pages.Clusters.Tube.MasterWebUrlHelper'),
- props: {
- placeholder: 'http://127.0.0.1:8080',
- },
- },
- {
+ })
+ @I18n('meta.Consume.FilterEnabled')
+ filterEnabled: 0 | 1;
+
+ @FormField({
type: 'input',
- label: 'Token',
- name: 'token',
- props: {
- placeholder: 'Required if the cluster is configured with Token',
- },
- },
-];
+ rules: [{ required: true }],
+ visible: values => values.filterEnabled,
+ })
+ @I18n('meta.Consume.TargetInlongStreamID')
+ inlongStreamId: string;
+}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx b/inlong-dashboard/src/metas/consumes/defaults/index.ts
similarity index 65%
copy from inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
copy to inlong-dashboard/src/metas/consumes/defaults/index.ts
index 9641bacd1..792430a45 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
+++ b/inlong-dashboard/src/metas/consumes/defaults/index.ts
@@ -17,18 +17,22 @@
* under the License.
*/
-import { streamForm } from '@/metas/stream';
-import { pickObjectArray } from '@/utils';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const getFilterFormContent = (defaultValues = {} as any) => [
+export const allDefaultConsumes: MetaExportWithBackendList = [
{
- type: 'inputsearch',
- name: 'keyword',
- initialValue: defaultValues.keyword,
+ label: 'ALL',
+ value: '',
+ LoadEntity: () => import('../common/ConsumeInfo').then(r => ({ default: r.ConsumeInfo })),
+ },
+ {
+ label: 'Pulsar',
+ value: 'PULSAR',
+ LoadEntity: () => import('./Pulsar'),
+ },
+ {
+ label: 'TubeMq',
+ value: 'TUBEMQ',
+ LoadEntity: () => import('./TubeMq'),
},
- ...pickObjectArray(['status'], streamForm).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/consumes/extends/index.ts
similarity index 83%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/consumes/extends/index.ts
index 8a7c0bd8e..ce5443978 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/consumes/extends/index.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
+export const allExtendsConsumes: MetaExportWithBackendList = [
+ // You can extends at here...
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/consumes/index.ts
similarity index 78%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/consumes/index.ts
index 8a7c0bd8e..2ed0bd403 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/consumes/index.ts
@@ -17,8 +17,9 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { allDefaultConsumes } from './defaults';
+import { allExtendsConsumes } from './extends';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export const consumes = allDefaultConsumes.concat(allExtendsConsumes);
+
+export const defaultValue = consumes[0].value;
diff --git a/inlong-dashboard/src/metas/groups/common/GroupDefaultInfo.ts b/inlong-dashboard/src/metas/groups/common/GroupDefaultInfo.ts
new file mode 100644
index 000000000..762c66a25
--- /dev/null
+++ b/inlong-dashboard/src/metas/groups/common/GroupDefaultInfo.ts
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import UserSelect from '@/components/UserSelect';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import i18n from '@/i18n';
+import { statusList, genStatusTag } from './status';
+import { groups, defaultValue } from '..';
+
+const { I18n, FormField, TableColumn } = DataWithBackend;
+
+export class GroupDefaultInfo extends DataWithBackend {
+ readonly id: number;
+
+ @FormField({
+ type: 'input',
+ props: {
+ maxLength: 32,
+ },
+ rules: [
+ { required: true },
+ {
+ pattern: /^[a-z_\-\d]+$/,
+ message: i18n.t('meta.Group.InlongGroupIdRules'),
+ },
+ ],
+ })
+ @TableColumn()
+ @I18n('meta.Group.InlongGroupId')
+ inlongGroupId: string;
+
+ @FormField({
+ type: 'input',
+ props: {
+ maxLength: 32,
+ },
+ })
+ @I18n('meta.Group.InlongGroupName')
+ name: string;
+
+ @FormField({
+ type: UserSelect,
+ extra: i18n.t('meta.Group.InlongGroupOwnersExtra'),
+ rules: [{ required: true }],
+ props: {
+ mode: 'multiple',
+ currentUserClosable: false,
+ },
+ })
+ @TableColumn()
+ @I18n('meta.Group.InlongGroupOwners')
+ inCharges: string;
+
+ @FormField({
+ type: 'textarea',
+ props: {
+ showCount: true,
+ maxLength: 100,
+ },
+ })
+ @I18n('meta.Group.InlongGroupIntroduction')
+ description: string;
+
+ @FormField({
+ type: 'radio',
+ initialValue: defaultValue,
+ rules: [{ required: true }],
+ props: {
+ options: groups.filter(item => Boolean(item.value)),
+ },
+ })
+ @TableColumn()
+ @I18n('meta.Group.MQType')
+ mqType: string;
+
+ @FormField({
+ type: 'text',
+ })
+ @I18n('MQ Resource')
+ readonly mqResource: string;
+
+ @FormField({
+ type: 'select',
+ props: {
+ allowClear: true,
+ options: statusList,
+ dropdownMatchSelectWidth: false,
+ },
+ visible: false,
+ })
+ @TableColumn({
+ render: text => genStatusTag(text),
+ })
+ @I18n('basic.Status')
+ readonly status: string;
+
+ @TableColumn()
+ @I18n('basic.CreateTime')
+ readonly createTime: string;
+
+ parse(data) {
+ return data;
+ }
+
+ stringify(data) {
+ return data;
+ }
+}
diff --git a/inlong-dashboard/src/metas/clusters/dataProxy.tsx b/inlong-dashboard/src/metas/groups/common/GroupInfo.ts
similarity index 84%
rename from inlong-dashboard/src/metas/clusters/dataProxy.tsx
rename to inlong-dashboard/src/metas/groups/common/GroupInfo.ts
index 5219858a2..a4977155e 100644
--- a/inlong-dashboard/src/metas/clusters/dataProxy.tsx
+++ b/inlong-dashboard/src/metas/groups/common/GroupInfo.ts
@@ -17,6 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { GroupDefaultInfo } from './GroupDefaultInfo';
-export const dataProxy: FieldItemType[] = [];
+export class GroupInfo extends GroupDefaultInfo {
+ // You can extends GroupInfo at here...
+}
diff --git a/inlong-dashboard/src/metas/group/status.tsx b/inlong-dashboard/src/metas/groups/common/status.tsx
similarity index 100%
rename from inlong-dashboard/src/metas/group/status.tsx
rename to inlong-dashboard/src/metas/groups/common/status.tsx
diff --git a/inlong-dashboard/src/metas/group/index.tsx b/inlong-dashboard/src/metas/groups/defaults/Pulsar.ts
similarity index 53%
rename from inlong-dashboard/src/metas/group/index.tsx
rename to inlong-dashboard/src/metas/groups/defaults/Pulsar.ts
index 1ec6cd1e4..d62249492 100644
--- a/inlong-dashboard/src/metas/group/index.tsx
+++ b/inlong-dashboard/src/metas/groups/defaults/Pulsar.ts
@@ -17,110 +17,15 @@
* under the License.
*/
-import React from 'react';
-import UserSelect from '@/components/UserSelect';
-import type { FieldItemType } from '@/metas/common';
-import { genFields, genForm, genTable } from '@/metas/common';
+import { DataWithBackend } from '@/metas/DataWithBackend';
import i18n from '@/i18n';
-import { statusList, genStatusTag } from './status';
-import { groupExtends } from './extends';
+import { GroupInfo } from '../common/GroupInfo';
-const groupDefault: FieldItemType[] = [
- {
- type: 'input',
- label: i18n.t('meta.Group.InlongGroupId'),
- name: 'inlongGroupId',
- props: {
- maxLength: 32,
- },
- rules: [
- { required: true },
- {
- pattern: /^[a-z_\-\d]+$/,
- message: i18n.t('meta.Group.InlongGroupIdRules'),
- },
- ],
- _renderTable: true,
- },
- {
- type: 'input',
- label: i18n.t('meta.Group.InlongGroupName'),
- name: 'name',
- props: {
- maxLength: 32,
- },
- },
- {
- type: <UserSelect mode="multiple" currentUserClosable={false} />,
- label: i18n.t('meta.Group.InlongGroupOwners'),
- name: 'inCharges',
- rules: [
- {
- required: true,
- },
- ],
- extra: i18n.t('meta.Group.InlongGroupOwnersExtra'),
- _renderTable: true,
- },
- {
- type: 'textarea',
- label: i18n.t('meta.Group.InlongGroupIntroduction'),
- name: 'description',
- props: {
- showCount: true,
- maxLength: 100,
- },
- },
- {
- type: 'radio',
- label: i18n.t('meta.Group.MQType'),
- name: 'mqType',
- initialValue: 'TUBEMQ',
- rules: [{ required: true }],
- props: {
- options: [
- {
- label: 'TubeMQ',
- value: 'TUBEMQ',
- },
- {
- label: 'Pulsar',
- value: 'PULSAR',
- },
- ],
- },
- _renderTable: true,
- },
- {
- type: 'text',
- label: 'MQ Resource',
- name: 'mqResource',
- },
- {
- type: 'input',
- label: i18n.t('basic.CreateTime'),
- name: 'createTime',
- visible: false,
- _renderTable: true,
- },
- {
- type: 'select',
- label: i18n.t('basic.Status'),
- name: 'status',
- props: {
- allowClear: true,
- options: statusList,
- dropdownMatchSelectWidth: false,
- },
- visible: false,
- _renderTable: {
- render: text => genStatusTag(text),
- },
- },
- {
+const { I18n, FormField } = DataWithBackend;
+
+export default class PulsarGroup extends GroupInfo implements DataWithBackend {
+ @FormField({
type: 'radio',
- label: i18n.t('meta.Group.QueueModule'),
- name: 'queueModule',
initialValue: 'SERIAL',
rules: [{ required: true }],
props: {
@@ -135,12 +40,12 @@ const groupDefault: FieldItemType[] = [
},
],
},
- visible: values => values.mqType === 'PULSAR',
- },
- {
+ })
+ @I18n('meta.Group.QueueModule')
+ queueModule: string;
+
+ @FormField({
type: 'inputnumber',
- label: i18n.t('meta.Group.PartitionNum'),
- name: 'partitionNum',
initialValue: 3,
rules: [{ required: true }],
props: {
@@ -148,60 +53,13 @@ const groupDefault: FieldItemType[] = [
max: 20,
precision: 0,
},
- visible: values => values.mqType === 'PULSAR' && values.queueModule === 'PARALLEL',
- },
- {
- type: 'inputnumber',
- label: i18n.t('meta.Group.NumberOfAccess'),
- name: 'dailyRecords',
- rules: [{ required: true }],
- suffix: i18n.t('meta.Group.TenThousand/Day'),
- props: {
- min: 1,
- precision: 0,
- },
- visible: values => values.mqType === 'TUBEMQ',
- },
- {
- type: 'inputnumber',
- label: i18n.t('meta.Group.AccessSize'),
- name: 'dailyStorage',
- rules: [{ required: true }],
- suffix: i18n.t('meta.Group.GB/Day'),
- props: {
- min: 1,
- precision: 0,
- },
- visible: values => values.mqType === 'TUBEMQ',
- },
- {
- type: 'inputnumber',
- label: i18n.t('meta.Group.AccessPeakPerSecond'),
- name: 'peakRecords',
- rules: [{ required: true }],
- suffix: i18n.t('meta.Group.Stripe/Second'),
- props: {
- min: 1,
- precision: 0,
- },
- visible: values => values.mqType === 'TUBEMQ',
- },
- {
- type: 'inputnumber',
- label: i18n.t('meta.Group.SingleStripMaximumLength'),
- name: 'maxLength',
- rules: [{ required: true }],
- suffix: 'Byte',
- props: {
- min: 1,
- precision: 0,
- },
- visible: values => values.mqType === 'TUBEMQ',
- },
- {
+ visible: values => values.queueModule === 'PARALLEL',
+ })
+ @I18n('meta.Group.PartitionNum')
+ partitionNum: number;
+
+ @FormField({
type: 'inputnumber',
- label: 'ensemble',
- name: 'ensemble',
initialValue: 3,
suffix: i18n.t('meta.Group.EnsembleSuffix'),
extra: i18n.t('meta.Group.EnsembleExtra'),
@@ -224,12 +82,12 @@ const groupDefault: FieldItemType[] = [
max: 10,
precision: 0,
},
- visible: values => values.mqType === 'PULSAR',
- },
- {
+ })
+ @I18n('ensemble')
+ ensemble: number;
+
+ @FormField({
type: 'inputnumber',
- label: 'Write Quorum',
- name: 'writeQuorum',
initialValue: 3,
suffix: i18n.t('meta.Group.WriteQuorumSuffix'),
extra: i18n.t('meta.Group.WriteQuorumExtra'),
@@ -238,12 +96,12 @@ const groupDefault: FieldItemType[] = [
max: 10,
precision: 0,
},
- visible: values => values.mqType === 'PULSAR',
- },
- {
+ })
+ @I18n('Write Quorum')
+ writeQuorum: number;
+
+ @FormField({
type: 'inputnumber',
- label: 'ACK Quorum',
- name: 'ackQuorum',
initialValue: 2,
suffix: i18n.t('meta.Group.AckQuorumSuffix'),
extra: i18n.t('meta.Group.AckQuorumExtra'),
@@ -252,12 +110,12 @@ const groupDefault: FieldItemType[] = [
max: 10,
precision: 0,
},
- visible: values => values.mqType === 'PULSAR',
- },
- {
+ })
+ @I18n('ACK Quorum')
+ ackQuorum: number;
+
+ @FormField({
type: 'inputnumber',
- label: 'Time To Live',
- name: 'ttl',
initialValue: 24,
rules: [
({ getFieldValue }) => ({
@@ -293,12 +151,12 @@ const groupDefault: FieldItemType[] = [
min: 1,
precision: 0,
},
- visible: values => values.mqType === 'PULSAR',
- },
- {
+ })
+ @I18n('Time To Live')
+ ttl: number;
+
+ @FormField({
type: 'inputnumber',
- label: 'Retention Time',
- name: 'retentionTime',
initialValue: 72,
rules: [
({ getFieldValue }) => ({
@@ -342,12 +200,12 @@ const groupDefault: FieldItemType[] = [
min: -1,
precision: 0,
},
- visible: values => values.mqType === 'PULSAR',
- },
- {
+ })
+ @I18n('Retention Time')
+ retentionTime: number;
+
+ @FormField({
type: 'inputnumber',
- label: 'Retention Size',
- name: 'retentionSize',
initialValue: -1,
suffix: {
type: 'select',
@@ -375,12 +233,7 @@ const groupDefault: FieldItemType[] = [
min: -1,
precision: 0,
},
- visible: values => values.mqType === 'PULSAR',
- },
-];
-
-export const group = genFields(groupDefault, groupExtends);
-
-export const groupForm = genForm(group);
-
-export const groupTable = genTable(group);
+ })
+ @I18n('Retention Size')
+ retentionSize: number;
+}
diff --git a/inlong-dashboard/src/metas/groups/defaults/TubeMq.ts b/inlong-dashboard/src/metas/groups/defaults/TubeMq.ts
new file mode 100644
index 000000000..e38ef6889
--- /dev/null
+++ b/inlong-dashboard/src/metas/groups/defaults/TubeMq.ts
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import i18n from '@/i18n';
+import { GroupInfo } from '../common/GroupInfo';
+
+const { I18n, FormField } = DataWithBackend;
+
+export default class TubeMqGroup extends GroupInfo implements DataWithBackend {
+ @FormField({
+ type: 'inputnumber',
+ rules: [{ required: true }],
+ suffix: i18n.t('meta.Group.TenThousand/Day'),
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ })
+ @I18n('meta.Group.NumberOfAccess')
+ dailyRecords: number;
+
+ @FormField({
+ type: 'inputnumber',
+ rules: [{ required: true }],
+ suffix: i18n.t('meta.Group.GB/Day'),
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ })
+ @I18n('meta.Group.AccessSize')
+ dailyStorage: number;
+
+ @FormField({
+ type: 'inputnumber',
+ rules: [{ required: true }],
+ suffix: i18n.t('meta.Group.Stripe/Second'),
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ })
+ @I18n('meta.Group.AccessPeakPerSecond')
+ peakRecords: number;
+
+ @FormField({
+ type: 'inputnumber',
+ rules: [{ required: true }],
+ suffix: 'Byte',
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ })
+ @I18n('meta.Group.SingleStripMaximumLength')
+ maxLength: number;
+}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx b/inlong-dashboard/src/metas/groups/defaults/index.ts
similarity index 65%
copy from inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
copy to inlong-dashboard/src/metas/groups/defaults/index.ts
index 9641bacd1..adab3a02b 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
+++ b/inlong-dashboard/src/metas/groups/defaults/index.ts
@@ -17,18 +17,22 @@
* under the License.
*/
-import { streamForm } from '@/metas/stream';
-import { pickObjectArray } from '@/utils';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const getFilterFormContent = (defaultValues = {} as any) => [
+export const allDefaultGroups: MetaExportWithBackendList = [
{
- type: 'inputsearch',
- name: 'keyword',
- initialValue: defaultValues.keyword,
+ label: 'ALL',
+ value: '',
+ LoadEntity: () => import('../common/GroupInfo').then(r => ({ default: r.GroupInfo })),
+ },
+ {
+ label: 'Pulsar',
+ value: 'PULSAR',
+ LoadEntity: () => import('./Pulsar'),
+ },
+ {
+ label: 'TubeMq',
+ value: 'TUBEMQ',
+ LoadEntity: () => import('./TubeMq'),
},
- ...pickObjectArray(['status'], streamForm).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/groups/extends/index.ts
similarity index 83%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/groups/extends/index.ts
index 8a7c0bd8e..abe3010b7 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/groups/extends/index.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
+export const allExtendsGroups: MetaExportWithBackendList = [
+ // You can extends at here...
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/groups/index.ts
similarity index 79%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/groups/index.ts
index 8a7c0bd8e..a794094eb 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/groups/index.ts
@@ -17,8 +17,9 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { allDefaultGroups } from './defaults';
+import { allExtendsGroups } from './extends';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export const groups = allDefaultGroups.concat(allExtendsGroups);
+
+export const defaultValue = groups[0].value;
diff --git a/inlong-dashboard/src/metas/index.ts b/inlong-dashboard/src/metas/index.ts
new file mode 100644
index 000000000..3b4645c6a
--- /dev/null
+++ b/inlong-dashboard/src/metas/index.ts
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { useState, useEffect, useCallback } from 'react';
+import type { MetaExportWithBackend, MetaExportWithBackendList } from '@/metas/types';
+import { consumes, defaultValue as defaultConsume } from './consumes';
+import { groups, defaultValue as defaultGroup } from './groups';
+import { clusters, defaultValue as defaultCluster } from './clusters';
+import { nodes, defaultValue as defaultNode } from './nodes';
+import { streams, defaultValue as defaultStream } from './streams';
+import { sources, defaultValue as defaultSource } from './sources';
+
+export interface UseLoadMetaResult {
+ loading: boolean;
+ Entity: MetaExportWithBackend;
+}
+
+export type MetaTypeKeys = 'consume' | 'group' | 'cluster' | 'node' | 'stream' | 'source';
+
+const metasMap: Record<MetaTypeKeys, [MetaExportWithBackendList, string?]> = {
+ consume: [consumes, defaultConsume],
+ group: [groups, defaultGroup],
+ cluster: [clusters, defaultCluster],
+ node: [nodes, defaultNode],
+ stream: [streams, defaultStream],
+ source: [sources, defaultSource],
+};
+
+export const useDefaultMeta = (metaType: MetaTypeKeys) => {
+ const [options = [], defaultValue] = metasMap[metaType];
+ return {
+ defaultValue: defaultValue || options[0].value,
+ options: options.map(item => ({ label: item.label, value: item.value })),
+ };
+};
+
+export const useLoadMeta = (metaType: MetaTypeKeys, subType: string): UseLoadMetaResult => {
+ const [loading, setLoading] = useState<boolean>(false);
+ const [Entity, setEntity] = useState<{ default: MetaExportWithBackend }>();
+
+ const load = useCallback(
+ async subType => {
+ const subList = metasMap[metaType]?.[0];
+ const LoadEntity = subList?.find(item => item.value === subType)?.LoadEntity;
+ if (LoadEntity) {
+ setLoading(true);
+ try {
+ const result = await LoadEntity();
+ setEntity(result);
+ } finally {
+ setLoading(false);
+ }
+ }
+ },
+ [metaType],
+ );
+
+ useEffect(() => {
+ load(subType);
+ }, [subType, load]);
+
+ return {
+ loading,
+ Entity: Entity?.default,
+ };
+};
diff --git a/inlong-dashboard/src/metas/nodes/common/NodeDefaultInfo.ts b/inlong-dashboard/src/metas/nodes/common/NodeDefaultInfo.ts
new file mode 100644
index 000000000..4024634cc
--- /dev/null
+++ b/inlong-dashboard/src/metas/nodes/common/NodeDefaultInfo.ts
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import UserSelect from '@/components/UserSelect';
+import { nodes, defaultValue } from '..';
+
+const { I18n, FormField, TableColumn } = DataWithBackend;
+
+export class NodeDefaultInfo extends DataWithBackend {
+ readonly id: number;
+
+ @FormField({
+ type: 'input',
+ rules: [{ required: true }],
+ props: {
+ maxLength: 128,
+ },
+ })
+ @TableColumn()
+ @I18n('meta.Nodes.Name')
+ name: string;
+
+ @FormField({
+ type: nodes.length > 3 ? 'select' : 'radio',
+ initialValue: defaultValue,
+ rules: [{ required: true }],
+ props: {
+ options: nodes
+ .filter(item => item.value)
+ .map(item => ({
+ label: item.label,
+ value: item.value,
+ })),
+ },
+ })
+ @TableColumn()
+ @I18n('meta.Nodes.Type')
+ type: string;
+
+ @FormField({
+ type: UserSelect,
+ rules: [{ required: true }],
+ props: {
+ mode: 'multiple',
+ currentUserClosable: false,
+ },
+ })
+ @TableColumn()
+ @I18n('meta.Nodes.Owners')
+ inCharges: string;
+
+ clusterTags: string;
+
+ @FormField({
+ type: 'textarea',
+ props: {
+ maxLength: 256,
+ },
+ })
+ @I18n('meta.Nodes.Description')
+ description?: string;
+
+ readonly version?: number;
+
+ parse(data) {
+ return data;
+ }
+
+ stringify(data) {
+ return data;
+ }
+}
diff --git a/inlong-dashboard/src/metas/stream/extends/index.tsx b/inlong-dashboard/src/metas/nodes/common/NodeInfo.ts
similarity index 84%
rename from inlong-dashboard/src/metas/stream/extends/index.tsx
rename to inlong-dashboard/src/metas/nodes/common/NodeInfo.ts
index e278d9701..dea21b5fb 100644
--- a/inlong-dashboard/src/metas/stream/extends/index.tsx
+++ b/inlong-dashboard/src/metas/nodes/common/NodeInfo.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { NodeDefaultInfo } from './NodeDefaultInfo';
-export const fieldsExtends: FieldItemType[] = [
- // You can extended fields here...
-];
+export class NodeInfo extends NodeDefaultInfo {
+ // You can extends NodeInfo at here...
+}
diff --git a/inlong-dashboard/src/metas/nodes/common/dao.ts b/inlong-dashboard/src/metas/nodes/common/dao.ts
new file mode 100644
index 000000000..93c643ed2
--- /dev/null
+++ b/inlong-dashboard/src/metas/nodes/common/dao.ts
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { useRequest } from '@/hooks';
+import request from '@/utils/request';
+import type { NodeInfo } from './NodeInfo';
+import { nodes } from '..';
+
+export const useListNodeDao = ({ options }) => {
+ return useRequest<{
+ total: number;
+ list: NodeInfo[];
+ }>(
+ {
+ url: '/node/list',
+ method: 'POST',
+ data: {
+ ...options,
+ },
+ },
+ {
+ refreshDeps: [options],
+ },
+ );
+};
+
+export const useFindNodeDao = ({ onSuccess }) => {
+ return useRequest<NodeInfo, [string]>(
+ async id => {
+ const result = await request(`/node/get/${id}`);
+ const LoadEntity = nodes.find(item => item.value === result.type)?.LoadEntity;
+ const Entity = (await LoadEntity())?.default;
+ const parseData = new Entity().parse(result);
+
+ return {
+ ...parseData,
+ inCharges: result.inCharges?.split(','),
+ clusterTags: result.clusterTags?.split(','),
+ };
+ },
+ {
+ manual: true,
+ onSuccess,
+ },
+ );
+};
+
+export const useSaveNodeDao = () => {
+ return {
+ runAsync: async data => {
+ const LoadEntity = nodes.find(item => item.value === data.type)?.LoadEntity;
+ const Entity = (await LoadEntity())?.default;
+ const stringifyData = new Entity().stringify(data);
+ const result = await request({
+ url: `/node/${Boolean(data.id) ? 'update' : 'save'}`,
+ method: 'POST',
+ data: {
+ ...stringifyData,
+ inCharges: (data.inCharges as any)?.join(','),
+ clusterTags: (data.clusterTags as any)?.join(','),
+ },
+ });
+
+ return result;
+ },
+ };
+};
+
+export const useDeleteNodeDao = () => {
+ return {
+ runAsync: id =>
+ request({
+ url: `/node/delete/${id}`,
+ method: 'DELETE',
+ }),
+ };
+};
diff --git a/inlong-dashboard/src/metas/nodes/hive.tsx b/inlong-dashboard/src/metas/nodes/defaults/Hive.ts
similarity index 73%
rename from inlong-dashboard/src/metas/nodes/hive.tsx
rename to inlong-dashboard/src/metas/nodes/defaults/Hive.ts
index 74436f2dc..35dd66a57 100644
--- a/inlong-dashboard/src/metas/nodes/hive.tsx
+++ b/inlong-dashboard/src/metas/nodes/defaults/Hive.ts
@@ -18,30 +18,35 @@
*/
import i18n from '@/i18n';
-import type { FieldItemType } from '@/metas/common';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import { NodeInfo } from '../common/NodeInfo';
-export const hive: FieldItemType[] = [
- {
+const { I18n, FormField } = DataWithBackend;
+
+export default class HiveNode extends NodeInfo implements DataWithBackend {
+ @FormField({
type: 'input',
- label: 'JDBC URL',
- name: 'jdbcUrl',
rules: [{ required: true }],
initialValue: 'jdbc:hive2://127.0.0.1:10000',
- },
- {
+ })
+ @I18n('JDBC URL')
+ jdbcUrl: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sinks.Hive.DataPath'),
- name: 'dataPath',
rules: [{ required: true }],
tooltip: i18n.t('meta.Sinks.DataPathHelp'),
initialValue: 'hdfs://127.0.0.1:9000/user/hive/warehouse/default',
- },
- {
+ })
+ @I18n('meta.Sinks.Hive.DataPath')
+ dataPath: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sinks.Hive.ConfDir'),
- name: 'hiveConfDir',
rules: [{ required: true }],
tooltip: i18n.t('meta.Sinks.Hive.ConfDirHelp'),
initialValue: '/usr/hive/conf',
- },
-];
+ })
+ @I18n('meta.Sinks.Hive.ConfDir')
+ hiveConfDir: string;
+}
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/nodes/defaults/index.ts
similarity index 70%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/nodes/defaults/index.ts
index 8a7c0bd8e..6af7c9114 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/nodes/defaults/index.ts
@@ -17,8 +17,17 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
+export const allDefaultNodes: MetaExportWithBackendList = [
+ {
+ label: 'ALL',
+ value: '',
+ LoadEntity: () => import('../common/NodeInfo').then(r => ({ default: r.NodeInfo })),
+ },
+ {
+ label: 'Hive',
+ value: 'HIVE',
+ LoadEntity: () => import('./Hive'),
+ },
];
diff --git a/inlong-dashboard/src/metas/group/extends/index.tsx b/inlong-dashboard/src/metas/nodes/extends/index.ts
similarity index 83%
rename from inlong-dashboard/src/metas/group/extends/index.tsx
rename to inlong-dashboard/src/metas/nodes/extends/index.ts
index 7f5f1eab7..8824d752a 100644
--- a/inlong-dashboard/src/metas/group/extends/index.tsx
+++ b/inlong-dashboard/src/metas/nodes/extends/index.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const groupExtends: FieldItemType[] = [
- // You can extended group fields here...
+export const allExtendsNodes: MetaExportWithBackendList = [
+ // You can extends at here...
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/nodes/index.ts
similarity index 77%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/nodes/index.ts
index 8a7c0bd8e..b8ddbb30d 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/nodes/index.ts
@@ -17,8 +17,11 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { allDefaultNodes } from './defaults';
+import { allExtendsNodes } from './extends';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export * as dao from './common/dao';
+
+export const nodes = allDefaultNodes.concat(allExtendsNodes);
+
+export const defaultValue = nodes[0].value;
diff --git a/inlong-dashboard/src/metas/nodes/index.tsx b/inlong-dashboard/src/metas/nodes/index.tsx
deleted file mode 100644
index c2d47b5fa..000000000
--- a/inlong-dashboard/src/metas/nodes/index.tsx
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import React from 'react';
-import i18n from '@/i18n';
-import UserSelect from '@/components/UserSelect';
-import type { FieldItemType } from '@/metas/common';
-import { genFields, genForm, genTable } from '@/metas/common';
-import { hive } from './hive';
-
-const allNodes = [
- {
- label: 'Hive',
- value: 'HIVE',
- fields: hive,
- },
-];
-
-const defaultCommonFields: FieldItemType[] = [
- {
- type: 'input',
- label: i18n.t('meta.Nodes.Name'),
- name: 'name',
- rules: [{ required: true }],
- props: {
- maxLength: 128,
- },
- _renderTable: true,
- },
- {
- type: 'select',
- label: i18n.t('meta.Nodes.Type'),
- name: 'type',
- initialValue: allNodes[0].value,
- rules: [{ required: true }],
- props: {
- options: allNodes.map(item => ({
- label: item.label,
- value: item.value,
- })),
- },
- _renderTable: true,
- },
- {
- type: <UserSelect mode="multiple" currentUserClosable={false} />,
- label: i18n.t('meta.Nodes.Owners'),
- name: 'inCharges',
- rules: [{ required: true }],
- _renderTable: true,
- },
- {
- type: 'textarea',
- label: i18n.t('meta.Nodes.Description'),
- name: 'description',
- props: {
- maxLength: 256,
- },
- },
-];
-
-export const nodes = allNodes.map(item => {
- const itemFields = defaultCommonFields.concat(item.fields);
- const fields = genFields(itemFields);
-
- return {
- ...item,
- fields,
- form: genForm(fields),
- table: genTable(fields),
- };
-});
diff --git a/inlong-dashboard/src/metas/sources/common/SourceDefaultInfo.ts b/inlong-dashboard/src/metas/sources/common/SourceDefaultInfo.ts
new file mode 100644
index 000000000..c39ce9d4a
--- /dev/null
+++ b/inlong-dashboard/src/metas/sources/common/SourceDefaultInfo.ts
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import { statusList, genStatusTag } from './status';
+import { sources, defaultValue } from '..';
+
+const { I18n, FormField, TableColumn } = DataWithBackend;
+
+export class SourceDefaultInfo extends DataWithBackend {
+ readonly id: number;
+
+ @FormField({
+ // This field is not visible or editable, but form value should exists.
+ type: 'text',
+ hidden: true,
+ })
+ @I18n('inlongGroupId')
+ readonly inlongGroupId: string;
+
+ @FormField({
+ type: 'select',
+ props: values => ({
+ disabled: Boolean(values.id),
+ options: {
+ requestService: {
+ url: '/stream/list',
+ method: 'POST',
+ data: {
+ pageNum: 1,
+ pageSize: 1000,
+ inlongGroupId: values.inlongGroupId,
+ },
+ },
+ requestParams: {
+ formatResult: result =>
+ result?.list.map(item => ({
+ label: item.inlongStreamId,
+ value: item.inlongStreamId,
+ })) || [],
+ },
+ },
+ }),
+ rules: [{ required: true }],
+ })
+ @TableColumn()
+ @I18n('pages.GroupDetail.Sources.DataStreams')
+ inlongStreamId: string;
+
+ @FormField({
+ type: 'input',
+ rules: [{ required: true }],
+ props: values => ({
+ disabled: Boolean(values.id),
+ maxLength: 128,
+ }),
+ })
+ @TableColumn()
+ @I18n('meta.Sources.Name')
+ sourceName: string;
+
+ @FormField({
+ type: sources.length > 3 ? 'select' : 'radio',
+ rules: [{ required: true }],
+ initialValue: defaultValue,
+ props: values => ({
+ disabled: Boolean(values.id),
+ options: sources
+ .filter(item => item.value)
+ .map(item => ({
+ label: item.label,
+ value: item.value,
+ })),
+ }),
+ })
+ @TableColumn()
+ @I18n('meta.Sources.Type')
+ sourceType: string;
+
+ @FormField({
+ type: 'select',
+ props: {
+ allowClear: true,
+ options: statusList,
+ dropdownMatchSelectWidth: false,
+ },
+ visible: false,
+ })
+ @TableColumn({
+ render: text => genStatusTag(text),
+ })
+ @I18n('basic.Status')
+ readonly status: string;
+
+ parse(data) {
+ return data;
+ }
+
+ stringify(data) {
+ return data;
+ }
+}
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/sources/common/SourceInfo.ts
similarity index 84%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/sources/common/SourceInfo.ts
index 8a7c0bd8e..6e19c7b79 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/sources/common/SourceInfo.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { SourceDefaultInfo } from './SourceDefaultInfo';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export class SourceInfo extends SourceDefaultInfo {
+ // You can extends SourceInfo at here...
+}
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/sources/defaults/AutoPush.ts
similarity index 80%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/sources/defaults/AutoPush.ts
index 8a7c0bd8e..b1bc5dc98 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/sources/defaults/AutoPush.ts
@@ -17,8 +17,7 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { DataWithBackend } from '@/metas/DataWithBackend';
+import { SourceInfo } from '../common/SourceInfo';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export default class AutoPushSource extends SourceInfo implements DataWithBackend {}
diff --git a/inlong-dashboard/src/metas/sources/file.ts b/inlong-dashboard/src/metas/sources/defaults/File.ts
similarity index 73%
rename from inlong-dashboard/src/metas/sources/file.ts
rename to inlong-dashboard/src/metas/sources/defaults/File.ts
index cff1696c0..1e2b9e115 100644
--- a/inlong-dashboard/src/metas/sources/file.ts
+++ b/inlong-dashboard/src/metas/sources/defaults/File.ts
@@ -17,15 +17,16 @@
* under the License.
*/
+import { DataWithBackend } from '@/metas/DataWithBackend';
import i18n from '@/i18n';
import rulesPattern from '@/utils/pattern';
-import type { FieldItemType } from '@/metas/common';
+import { SourceInfo } from '../common/SourceInfo';
-export const file: FieldItemType[] = [
- {
+const { I18n, FormField, TableColumn } = DataWithBackend;
+
+export default class PulsarSource extends SourceInfo implements DataWithBackend {
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.File.DataSourceIP'),
- name: 'agentIp',
rules: [
{
pattern: rulesPattern.ip,
@@ -36,26 +37,30 @@ export const file: FieldItemType[] = [
props: values => ({
disabled: values?.status === 101,
}),
- _renderTable: true,
- },
- {
+ })
+ @TableColumn()
+ @I18n('meta.Sources.File.DataSourceIP')
+ agentIp: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.File.FilePath'),
- name: 'pattern',
tooltip: i18n.t('meta.Sources.File.FilePathHelp'),
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
- _renderTable: true,
- },
- {
+ })
+ @TableColumn()
+ @I18n('meta.Sources.File.FilePath')
+ pattern: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.File.TimeOffset'),
- name: 'timeOffset',
tooltip: i18n.t('meta.Sources.File.TimeOffsetHelp'),
props: values => ({
disabled: values?.status === 101,
}),
- },
-];
+ })
+ @I18n('meta.Sources.File.TimeOffset')
+ timeOffset: string;
+}
diff --git a/inlong-dashboard/src/metas/sources/binLog.ts b/inlong-dashboard/src/metas/sources/defaults/MysqlBinlog.ts
similarity index 71%
rename from inlong-dashboard/src/metas/sources/binLog.ts
rename to inlong-dashboard/src/metas/sources/defaults/MysqlBinlog.ts
index 28c3c59c8..63d34e074 100644
--- a/inlong-dashboard/src/metas/sources/binLog.ts
+++ b/inlong-dashboard/src/metas/sources/defaults/MysqlBinlog.ts
@@ -17,24 +17,26 @@
* under the License.
*/
+import { DataWithBackend } from '@/metas/DataWithBackend';
import i18n from '@/i18n';
-import type { FieldItemType } from '@/metas/common';
+import { SourceInfo } from '../common/SourceInfo';
-export const binLog: FieldItemType[] = [
- {
- name: 'hostname',
+const { I18n, FormField, TableColumn } = DataWithBackend;
+
+export default class TubeMqSource extends SourceInfo implements DataWithBackend {
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.Db.Server'),
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
- _renderTable: true,
- },
- {
- name: 'port',
+ })
+ @TableColumn()
+ @I18n('meta.Sources.Db.Server')
+ hostname: string;
+
+ @FormField({
type: 'inputnumber',
- label: i18n.t('meta.Sources.Db.Port'),
initialValue: 3306,
rules: [{ required: true }],
props: values => ({
@@ -42,52 +44,56 @@ export const binLog: FieldItemType[] = [
min: 0,
max: 65535,
}),
- _renderTable: true,
- },
- {
- name: 'user',
+ })
+ @TableColumn()
+ @I18n('meta.Sources.Db.Port')
+ port: number;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.Db.User'),
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
- },
- {
- name: 'password',
+ })
+ @I18n('meta.Sources.Db.User')
+ user: string;
+
+ @FormField({
type: 'password',
- label: i18n.t('meta.Sources.Db.Password'),
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
- },
- {
- name: 'historyFilename',
+ })
+ @I18n('meta.Sources.Db.Password')
+ password: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.Db.HistoryFilename'),
rules: [{ required: true }],
initialValue: '/data/inlong-agent/.history',
props: values => ({
disabled: values?.status === 101,
}),
- _renderTable: true,
- },
- {
- name: 'serverTimezone',
+ })
+ @I18n('meta.Sources.Db.HistoryFilename')
+ historyFilename: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.Db.ServerTimezone'),
tooltip: 'UTC, UTC+8, Asia/Shanghai, ...',
initialValue: 'UTC',
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
- },
- {
- name: 'intervalMs',
+ })
+ @I18n('meta.Sources.Db.ServerTimezone')
+ serverTimezone: string;
+
+ @FormField({
type: 'inputnumber',
- label: i18n.t('meta.Sources.Db.IntervalMs'),
initialValue: 1000,
rules: [{ required: true }],
suffix: 'ms',
@@ -96,11 +102,12 @@ export const binLog: FieldItemType[] = [
min: 1000,
max: 3600000,
}),
- },
- {
- name: 'allMigration',
+ })
+ @I18n('meta.Sources.Db.IntervalMs')
+ intervalMs: number;
+
+ @FormField({
type: 'radio',
- label: i18n.t('meta.Sources.Db.AllMigration'),
rules: [{ required: true }],
initialValue: false,
props: values => ({
@@ -116,16 +123,19 @@ export const binLog: FieldItemType[] = [
},
],
}),
- },
- {
- name: 'tableWhiteList',
+ })
+ @I18n('meta.Sources.Db.AllMigration')
+ allMigration: boolean;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Sources.Db.TableWhiteList'),
tooltip: i18n.t('meta.Sources.Db.TableWhiteListHelp'),
rules: [{ required: true }],
props: values => ({
disabled: values?.status === 101,
}),
visible: values => !values?.allMigration,
- },
-];
+ })
+ @I18n('meta.Sources.Db.TableWhiteList')
+ tableWhiteList: boolean;
+}
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx b/inlong-dashboard/src/metas/sources/defaults/index.ts
similarity index 59%
copy from inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
copy to inlong-dashboard/src/metas/sources/defaults/index.ts
index 9641bacd1..c3988449f 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
+++ b/inlong-dashboard/src/metas/sources/defaults/index.ts
@@ -17,18 +17,28 @@
* under the License.
*/
-import { streamForm } from '@/metas/stream';
-import { pickObjectArray } from '@/utils';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const getFilterFormContent = (defaultValues = {} as any) => [
+export const allDefaultSources: MetaExportWithBackendList = [
{
- type: 'inputsearch',
- name: 'keyword',
- initialValue: defaultValues.keyword,
+ label: 'ALL',
+ value: '',
+ LoadEntity: () => import('../common/SourceInfo').then(r => ({ default: r.SourceInfo })),
+ },
+
+ {
+ label: 'Auto Push',
+ value: 'AUTO_PUSH',
+ LoadEntity: () => import('./AutoPush'),
+ },
+ {
+ label: 'MySQL BinLog',
+ value: 'MYSQL_BINLOG',
+ LoadEntity: () => import('./MysqlBinlog'),
+ },
+ {
+ label: 'File',
+ value: 'FILE',
+ LoadEntity: () => import('./File'),
},
- ...pickObjectArray(['status'], streamForm).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/sources/extends/index.ts
similarity index 83%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/sources/extends/index.ts
index 8a7c0bd8e..38e4eb2d9 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/sources/extends/index.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
+export const allExtendsSources: MetaExportWithBackendList = [
+ // You can extends at here...
];
diff --git a/inlong-dashboard/src/metas/sources/index.ts b/inlong-dashboard/src/metas/sources/index.ts
index e6817cf82..58928e352 100644
--- a/inlong-dashboard/src/metas/sources/index.ts
+++ b/inlong-dashboard/src/metas/sources/index.ts
@@ -17,84 +17,9 @@
* under the License.
*/
-import i18n from '@/i18n';
-import type { FieldItemType } from '@/metas/common';
-import { genFields, genForm, genTable } from '@/metas/common';
-import { statusList, genStatusTag } from './common/status';
-import { autoPush } from './autoPush';
-import { binLog } from './binLog';
-import { file } from './file';
+import { allDefaultSources } from './defaults';
+import { allExtendsSources } from './extends';
-const allSources = [
- {
- label: 'MySQL BinLog',
- value: 'MYSQL_BINLOG',
- fields: binLog,
- },
- {
- label: 'File',
- value: 'FILE',
- fields: file,
- },
- {
- label: 'Auto Push',
- value: 'AUTO_PUSH',
- fields: autoPush,
- },
-];
+export const sources = allDefaultSources.concat(allExtendsSources);
-const defaultCommonFields: FieldItemType[] = [
- {
- name: 'sourceName',
- type: 'input',
- label: i18n.t('meta.Sources.Name'),
- rules: [{ required: true }],
- props: values => ({
- disabled: !!values.id,
- maxLength: 128,
- }),
- _renderTable: true,
- },
- {
- name: 'sourceType',
- type: 'select',
- label: i18n.t('meta.Sources.Type'),
- rules: [{ required: true }],
- initialValue: allSources[0].value,
- props: values => ({
- disabled: !!values.id,
- options: allSources.map(item => ({
- label: item.label,
- value: item.value,
- })),
- }),
- },
- {
- name: 'status',
- type: 'select',
- label: i18n.t('basic.Status'),
- props: {
- allowClear: true,
- options: statusList,
- dropdownMatchSelectWidth: false,
- },
- visible: false,
- _renderTable: {
- render: text => genStatusTag(text),
- },
- },
-];
-
-export const sources = allSources.map(item => {
- const itemFields = defaultCommonFields.concat(item.fields);
- const fields = genFields(itemFields);
-
- return {
- ...item,
- fields,
- form: genForm(fields),
- table: genTable(fields),
- toFormValues: null,
- toSubmitValues: null,
- };
-});
+export const defaultValue = sources[0].value;
diff --git a/inlong-dashboard/src/metas/stream/index.tsx b/inlong-dashboard/src/metas/streams/common/StreamDefaultInfo.ts
similarity index 75%
rename from inlong-dashboard/src/metas/stream/index.tsx
rename to inlong-dashboard/src/metas/streams/common/StreamDefaultInfo.ts
index 5fbddffbf..87f153467 100644
--- a/inlong-dashboard/src/metas/stream/index.tsx
+++ b/inlong-dashboard/src/metas/streams/common/StreamDefaultInfo.ts
@@ -17,19 +17,19 @@
* under the License.
*/
-import EditableTable from '@/components/EditableTable';
+import { DataWithBackend } from '@/metas/DataWithBackend';
import i18n from '@/i18n';
+import EditableTable from '@/components/EditableTable';
import { fieldTypes as sourceFieldsTypes } from '@/metas/sinks/common/sourceFields';
-import type { FieldItemType } from '@/metas/common';
-import { genFields, genForm, genTable } from '@/metas/common';
import { statusList, genStatusTag } from './status';
-import { fieldsExtends } from './extends';
-const fieldsDefault: FieldItemType[] = [
- {
+const { I18n, FormField, TableColumn } = DataWithBackend;
+
+export class StreamDefaultInfo extends DataWithBackend {
+ readonly id: number;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Stream.StreamId'),
- name: 'inlongStreamId',
props: {
maxLength: 32,
},
@@ -40,55 +40,53 @@ const fieldsDefault: FieldItemType[] = [
message: i18n.t('meta.Stream.StreamIdRules'),
},
],
- _renderTable: true,
- },
- {
+ })
+ @TableColumn()
+ @I18n('meta.Stream.StreamId')
+ inlongStreamId: string;
+
+ @FormField({
type: 'input',
- label: i18n.t('meta.Stream.StreamName'),
- name: 'name',
- _renderTable: true,
- },
- {
+ })
+ @TableColumn()
+ @I18n('meta.Stream.StreamName')
+ name: string;
+
+ @FormField({
type: 'textarea',
- label: i18n.t('meta.Stream.Description'),
- name: 'description',
props: {
showCount: true,
maxLength: 256,
},
- },
- {
- type: 'text',
- label: i18n.t('basic.Creator'),
- name: 'creator',
- visible: false,
- _renderTable: true,
- },
- {
- type: 'text',
- label: i18n.t('basic.CreateTime'),
- name: 'createTime',
- visible: false,
- _renderTable: true,
- },
- {
+ })
+ @I18n('meta.Stream.Description')
+ description: string;
+
+ @TableColumn()
+ @I18n('basic.Creator')
+ readonly creator: string;
+
+ @TableColumn()
+ @I18n('basic.CreateTime')
+ readonly createTime: string;
+
+ @FormField({
type: 'select',
- label: i18n.t('basic.Status'),
- name: 'status',
props: {
allowClear: true,
options: statusList,
dropdownMatchSelectWidth: false,
},
visible: false,
- _renderTable: {
- render: text => genStatusTag(text),
- },
- },
- {
+ })
+ @TableColumn({
+ render: text => genStatusTag(text),
+ })
+ @I18n('basic.Status')
+ status: string;
+
+ @FormField({
type: 'radio',
- label: i18n.t('meta.Stream.DataType'),
- name: 'dataType',
initialValue: 'CSV',
tooltip: i18n.t('meta.Stream.DataTypeCsvHelp'),
props: {
@@ -112,11 +110,12 @@ const fieldsDefault: FieldItemType[] = [
],
},
rules: [{ required: true }],
- },
- {
+ })
+ @I18n('meta.Stream.DataType')
+ dataType: string;
+
+ @FormField({
type: 'radio',
- label: i18n.t('meta.Stream.DataEncoding'),
- name: 'dataEncoding',
initialValue: 'UTF-8',
props: {
options: [
@@ -131,11 +130,12 @@ const fieldsDefault: FieldItemType[] = [
],
},
rules: [{ required: true }],
- },
- {
+ })
+ @I18n('meta.Stream.DataEncoding')
+ dataEncoding: string;
+
+ @FormField({
type: 'select',
- label: i18n.t('meta.Stream.DataSeparator'),
- name: 'dataSeparator',
initialValue: '124',
props: {
dropdownMatchSelectWidth: false,
@@ -180,11 +180,12 @@ const fieldsDefault: FieldItemType[] = [
max: 127,
},
],
- },
- {
+ })
+ @I18n('meta.Stream.DataSeparator')
+ dataSeparator: string;
+
+ @FormField({
type: EditableTable,
- label: i18n.t('meta.Stream.SourceDataField'),
- name: 'rowTypeFields',
props: {
size: 'small',
columns: [
@@ -215,11 +216,15 @@ const fieldsDefault: FieldItemType[] = [
},
],
},
- },
-];
-
-export const stream = genFields(fieldsDefault, fieldsExtends);
+ })
+ @I18n('meta.Stream.SourceDataField')
+ rowTypeFields: Record<string, string>[];
-export const streamForm = genForm(stream);
+ parse(data) {
+ return data;
+ }
-export const streamTable = genTable(stream);
+ stringify(data) {
+ return data;
+ }
+}
diff --git a/inlong-dashboard/src/metas/sources/autoPush.ts b/inlong-dashboard/src/metas/streams/common/StreamInfo.ts
similarity index 84%
rename from inlong-dashboard/src/metas/sources/autoPush.ts
rename to inlong-dashboard/src/metas/streams/common/StreamInfo.ts
index 6fe579a35..80114c739 100644
--- a/inlong-dashboard/src/metas/sources/autoPush.ts
+++ b/inlong-dashboard/src/metas/streams/common/StreamInfo.ts
@@ -17,6 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { StreamDefaultInfo } from './StreamDefaultInfo';
-export const autoPush: FieldItemType[] = [];
+export class StreamInfo extends StreamDefaultInfo {
+ // You can extends StreamInfo at here...
+}
diff --git a/inlong-dashboard/src/metas/stream/status.tsx b/inlong-dashboard/src/metas/streams/common/status.tsx
similarity index 100%
rename from inlong-dashboard/src/metas/stream/status.tsx
rename to inlong-dashboard/src/metas/streams/common/status.tsx
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/streams/defaults/index.ts
similarity index 75%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/streams/defaults/index.ts
index 8a7c0bd8e..7d92d260d 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/streams/defaults/index.ts
@@ -17,8 +17,12 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
+export const allDefaultStreams: MetaExportWithBackendList = [
+ {
+ label: 'ALL',
+ value: '',
+ LoadEntity: () => import('../common/StreamInfo').then(r => ({ default: r.StreamInfo })),
+ },
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/streams/extends/index.ts
similarity index 83%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/streams/extends/index.ts
index 8a7c0bd8e..309324157 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/streams/extends/index.ts
@@ -17,8 +17,8 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import type { MetaExportWithBackendList } from '@/metas/types';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
+export const allExtendsStreams: MetaExportWithBackendList = [
+ // You can extends at here...
];
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/streams/index.ts
similarity index 79%
copy from inlong-dashboard/src/metas/consume/extends/index.tsx
copy to inlong-dashboard/src/metas/streams/index.ts
index 8a7c0bd8e..2b7f10519 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/streams/index.ts
@@ -17,8 +17,9 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { allDefaultStreams } from './defaults';
+import { allExtendsStreams } from './extends';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+export const streams = allDefaultStreams.concat(allExtendsStreams);
+
+export const defaultValue = streams[0].value;
diff --git a/inlong-dashboard/src/metas/consume/extends/index.tsx b/inlong-dashboard/src/metas/types.ts
similarity index 53%
rename from inlong-dashboard/src/metas/consume/extends/index.tsx
rename to inlong-dashboard/src/metas/types.ts
index 8a7c0bd8e..00c8c1548 100644
--- a/inlong-dashboard/src/metas/consume/extends/index.tsx
+++ b/inlong-dashboard/src/metas/types.ts
@@ -17,8 +17,32 @@
* under the License.
*/
-import type { FieldItemType } from '@/metas/common';
+import { DataStatic } from './DataStatic';
+import { DataWithBackend } from './DataWithBackend';
-export const consumeExtends: FieldItemType[] = [
- // You can extended consume fields here...
-];
+class MetaClassStatic implements DataStatic {}
+
+export type MetaExportStatic = typeof MetaClassStatic;
+
+export type MetaExportStaticList = {
+ label: string;
+ value: string;
+ LoadEntity: () => Promise<{ default: MetaExportStatic }>;
+}[];
+
+class MetaClassWithBackend extends DataWithBackend implements DataWithBackend {
+ parse(data) {
+ return data;
+ }
+ stringify(data) {
+ return data;
+ }
+}
+
+export type MetaExportWithBackend = typeof MetaClassWithBackend;
+
+export type MetaExportWithBackendList = {
+ label: string;
+ value: string;
+ LoadEntity: () => Promise<{ default: MetaExportWithBackend }>;
+}[];
diff --git a/inlong-dashboard/src/pages/Clusters/CreateModal.tsx b/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
index 6e8ff38c8..3618f1914 100644
--- a/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
+++ b/inlong-dashboard/src/pages/Clusters/CreateModal.tsx
@@ -23,7 +23,7 @@ import { ModalProps } from 'antd/es/modal';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { useRequest, useUpdateEffect } from '@/hooks';
import request from '@/utils/request';
-import { clusters } from '@/metas/clusters';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
import i18n from '@/i18n';
export interface Props extends ModalProps {
@@ -34,7 +34,9 @@ export interface Props extends ModalProps {
const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
const [form] = useForm();
- const [type, setType] = useState(clusters[0].value);
+ const { defaultValue } = useDefaultMeta('cluster');
+
+ const [type, setType] = useState(defaultValue);
const { data: savedData, run: getData } = useRequest(
id => ({
@@ -82,14 +84,15 @@ const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
}
} else {
form.resetFields();
- setType(clusters[0].value);
+ setType(defaultValue);
}
}, [modalProps.visible]);
+ const { Entity } = useLoadMeta('cluster', type);
+
const content = useMemo(() => {
- const current = clusters.find(item => item.value === type);
- return current?.form;
- }, [type]);
+ return Entity ? Entity.FieldList : [];
+ }, [Entity]);
return (
<Modal
diff --git a/inlong-dashboard/src/pages/Clusters/index.tsx b/inlong-dashboard/src/pages/Clusters/index.tsx
index 594b79b9a..0ef46ce1d 100644
--- a/inlong-dashboard/src/pages/Clusters/index.tsx
+++ b/inlong-dashboard/src/pages/Clusters/index.tsx
@@ -25,37 +25,19 @@ import HighTable from '@/components/HighTable';
import { PageContainer } from '@/components/PageContainer';
import { defaultSize } from '@/configs/pagination';
import { useRequest } from '@/hooks';
-import { clusters } from '@/metas/clusters';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
import CreateModal from './CreateModal';
import request from '@/utils/request';
import { timestampFormat } from '@/utils';
-const getFilterFormContent = defaultValues => [
- {
- type: 'inputsearch',
- name: 'keyword',
- },
- {
- type: 'radiobutton',
- name: 'type',
- label: i18n.t('pages.Clusters.Type'),
- initialValue: defaultValues.type,
- props: {
- buttonStyle: 'solid',
- options: clusters.map(item => ({
- label: item.label,
- value: item.value,
- })),
- },
- },
-];
-
const Comp: React.FC = () => {
+ const { defaultValue, options: clusters } = useDefaultMeta('cluster');
+
const [options, setOptions] = useState({
keyword: '',
pageSize: defaultSize,
pageNum: 1,
- type: clusters[0].value,
+ type: defaultValue,
});
const [createModal, setCreateModal] = useState<Record<string, unknown>>({
@@ -122,11 +104,32 @@ const Comp: React.FC = () => {
total: data?.total,
};
+ const getFilterFormContent = useCallback(
+ defaultValues => [
+ {
+ type: 'inputsearch',
+ name: 'keyword',
+ },
+ {
+ type: 'radiobutton',
+ name: 'type',
+ label: i18n.t('pages.Clusters.Type'),
+ initialValue: defaultValues.type,
+ props: {
+ buttonStyle: 'solid',
+ options: clusters,
+ },
+ },
+ ],
+ [clusters],
+ );
+
+ const { Entity } = useLoadMeta('cluster', options.type);
+
const columns = useMemo(() => {
- const current = clusters.find(item => item.value === options.type);
- if (!current?.table) return [];
+ if (!Entity) return [];
- return current.table.concat([
+ return Entity.ColumnList?.concat([
{
title: i18n.t('pages.Clusters.LastModifier'),
dataIndex: 'modifier',
@@ -159,7 +162,7 @@ const Comp: React.FC = () => {
),
} as any,
]);
- }, [options.type, onDelete]);
+ }, [Entity, onDelete]);
return (
<PageContainer useDefaultBreadcrumb={false}>
diff --git a/inlong-dashboard/src/pages/ConsumeDashboard/config.tsx b/inlong-dashboard/src/pages/ConsumeDashboard/config.tsx
index 48b9a2df6..486a31d38 100644
--- a/inlong-dashboard/src/pages/ConsumeDashboard/config.tsx
+++ b/inlong-dashboard/src/pages/ConsumeDashboard/config.tsx
@@ -22,8 +22,8 @@ import { Button } from 'antd';
import { Link } from 'react-router-dom';
import i18n from '@/i18n';
import { DashTotal, DashToBeAssigned, DashPending, DashRejected } from '@/components/Icons';
-import { consumeForm, consumeTable } from '@/metas/consume';
-import { pickObjectArray } from '@/utils';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
+import { statusList, lastConsumerStatusList } from '@/metas/consumes/common/status';
export const dashCardList = [
{
@@ -48,55 +48,72 @@ export const dashCardList = [
},
];
-export const getFilterFormContent = defaultValues =>
- [
- {
- type: 'inputsearch',
- name: 'keyword',
- initialValue: defaultValues.keyword,
- props: {
- allowClear: true,
- },
+export const getFilterFormContent = defaultValues => [
+ {
+ type: 'inputsearch',
+ name: 'keyword',
+ initialValue: defaultValues.keyword,
+ props: {
+ allowClear: true,
+ },
+ },
+ {
+ type: 'select',
+ name: 'status',
+ label: i18n.t('basic.Status'),
+ initialValue: defaultValues.status,
+ props: {
+ allowClear: true,
+ options: statusList,
+ dropdownMatchSelectWidth: false,
+ },
+ },
+ {
+ type: 'select',
+ name: 'lastConsumeStatus',
+ label: i18n.t('pages.ConsumeDashboard.config.OperatingStatus'),
+ initialValue: defaultValues.lastConsumeStatus,
+ props: {
+ allowClear: true,
+ options: lastConsumerStatusList,
+ dropdownMatchSelectWidth: false,
},
- ].concat(
- pickObjectArray(['status', 'lastConsumeStatus'], consumeForm).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
- );
+ },
+];
+
+export const useColumns = ({ onDelete }) => {
+ const { defaultValue } = useDefaultMeta('consume');
+
+ const { Entity } = useLoadMeta('consume', defaultValue);
-export const getColumns = ({ onDelete }) => {
const genCreateUrl = record => `/consume/create/${record.id}`;
const genDetailUrl = record =>
[0, 10].includes(record.status) ? genCreateUrl(record) : `/consume/detail/${record.id}`;
- return consumeTable
- .map(item => {
- if (item.dataIndex === 'consumerGroup') {
- return { ...item, render: (text, record) => <Link to={genDetailUrl(record)}>{text}</Link> };
- }
- return item;
- })
- .concat([
- {
- title: i18n.t('basic.Operating'),
- dataIndex: 'action',
- render: (text, record) => (
- <>
+ return Entity?.ColumnList?.map(item => {
+ if (item.dataIndex === 'consumerGroup') {
+ return { ...item, render: (text, record) => <Link to={genDetailUrl(record)}>{text}</Link> };
+ }
+ return item;
+ }).concat([
+ {
+ title: i18n.t('basic.Operating'),
+ dataIndex: 'action',
+ render: (text, record) => (
+ <>
+ <Button type="link">
+ <Link to={genDetailUrl(record)}>{i18n.t('basic.Detail')}</Link>
+ </Button>
+ {[20, 22].includes(record?.status) && (
<Button type="link">
- <Link to={genDetailUrl(record)}>{i18n.t('basic.Detail')}</Link>
- </Button>
- {[20, 22].includes(record?.status) && (
- <Button type="link">
- <Link to={genCreateUrl(record)}>{i18n.t('basic.Edit')}</Link>
- </Button>
- )}
- <Button type="link" onClick={() => onDelete(record)}>
- {i18n.t('basic.Delete')}
+ <Link to={genCreateUrl(record)}>{i18n.t('basic.Edit')}</Link>
</Button>
- </>
- ),
- },
- ]);
+ )}
+ <Button type="link" onClick={() => onDelete(record)}>
+ {i18n.t('basic.Delete')}
+ </Button>
+ </>
+ ),
+ },
+ ]);
};
diff --git a/inlong-dashboard/src/pages/ConsumeDashboard/index.tsx b/inlong-dashboard/src/pages/ConsumeDashboard/index.tsx
index 6c25382e2..d47c55678 100644
--- a/inlong-dashboard/src/pages/ConsumeDashboard/index.tsx
+++ b/inlong-dashboard/src/pages/ConsumeDashboard/index.tsx
@@ -26,7 +26,7 @@ import { useRequest, useHistory } from '@/hooks';
import { useTranslation } from 'react-i18next';
import request from '@/utils/request';
import { defaultSize } from '@/configs/pagination';
-import { dashCardList, getFilterFormContent, getColumns } from './config';
+import { dashCardList, getFilterFormContent, useColumns } from './config';
const Comp: React.FC = () => {
const { t } = useTranslation();
@@ -97,6 +97,8 @@ const Comp: React.FC = () => {
title: summary[item.dataIndex] || 0,
}));
+ const columns = useColumns({ onDelete });
+
return (
<PageContainer useDefaultBreadcrumb={false} useDefaultContainer={false}>
<Container>
@@ -116,7 +118,7 @@ const Comp: React.FC = () => {
onFilter,
}}
table={{
- columns: getColumns({ onDelete }),
+ columns,
rowKey: 'id',
dataSource: data?.list,
pagination,
diff --git a/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx b/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx
index 157d81313..c9feafaea 100644
--- a/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx
+++ b/inlong-dashboard/src/pages/ConsumeDetail/Info/config.tsx
@@ -17,12 +17,14 @@
* under the License.
*/
-import { consumeForm } from '@/metas/consume';
+import { useLoadMeta } from '@/metas';
import { excludeObjectArray } from '@/utils';
-export const getFormContent = ({ editing, isCreate }) => {
+export const useFormContent = ({ mqType, editing, isCreate }) => {
+ const { Entity } = useLoadMeta('consume', mqType);
+
const excludeKeys = isCreate ? ['masterUrl'] : [];
- const fields = excludeObjectArray(excludeKeys, consumeForm);
+ const fields = excludeObjectArray(excludeKeys, Entity?.FieldList || []);
return isCreate
? fields
diff --git a/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx b/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx
index c8279f040..5ca8fde8c 100644
--- a/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx
+++ b/inlong-dashboard/src/pages/ConsumeDetail/Info/index.tsx
@@ -17,14 +17,15 @@
* under the License.
*/
-import React, { forwardRef, useImperativeHandle, useMemo } from 'react';
+import React, { forwardRef, useImperativeHandle, useMemo, useState } from 'react';
import { Button, message, Space } from 'antd';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { useBoolean, useRequest } from '@/hooks';
import request from '@/utils/request';
import { useTranslation } from 'react-i18next';
+import { useDefaultMeta } from '@/metas';
import { CommonInterface } from '../common';
-import { getFormContent } from './config';
+import { useFormContent } from './config';
type Props = CommonInterface;
@@ -32,6 +33,10 @@ const Comp = ({ id, readonly, isCreate }: Props, ref) => {
const { t } = useTranslation();
const [editing, { setTrue, setFalse }] = useBoolean(false);
+ const { defaultValue } = useDefaultMeta('consume');
+
+ const [mqType, setMqType] = useState(defaultValue);
+
const [form] = useForm();
const isUpdate = useMemo(() => {
@@ -47,6 +52,7 @@ const Comp = ({ id, readonly, isCreate }: Props, ref) => {
}),
onSuccess: data => {
form.setFieldsValue(data);
+ setMqType(data.mqType);
},
});
@@ -86,15 +92,19 @@ const Comp = ({ id, readonly, isCreate }: Props, ref) => {
setFalse();
};
+ const formContent = useFormContent({
+ mqType,
+ editing,
+ isCreate,
+ });
+
return (
<div style={{ position: 'relative' }}>
<FormGenerator
form={form}
- content={getFormContent({
- editing,
- isCreate,
- })}
+ content={formContent}
initialValues={data}
+ onValuesChange={(c, values) => setMqType(values.mqType)}
useMaxWidth={800}
/>
diff --git a/inlong-dashboard/src/pages/GroupDashboard/config.tsx b/inlong-dashboard/src/pages/GroupDashboard/config.tsx
index d6e3731df..9707d6ea7 100644
--- a/inlong-dashboard/src/pages/GroupDashboard/config.tsx
+++ b/inlong-dashboard/src/pages/GroupDashboard/config.tsx
@@ -22,8 +22,8 @@ import { Link } from 'react-router-dom';
import i18n from '@/i18n';
import { DashTotal, DashToBeAssigned, DashPending, DashRejected } from '@/components/Icons';
import { Button } from 'antd';
-import { groupForm, groupTable } from '@/metas/group';
-import { pickObjectArray } from '@/utils';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
+import { statusList } from '@/metas/groups/common/status';
export const dashCardList = [
{
@@ -48,62 +48,68 @@ export const dashCardList = [
},
];
-export const getFilterFormContent = defaultValues =>
- [
- {
- type: 'inputsearch',
- name: 'keyword',
- initialValue: defaultValues.keyword,
- props: {
- allowClear: true,
- },
+export const getFilterFormContent = defaultValues => [
+ {
+ type: 'inputsearch',
+ name: 'keyword',
+ initialValue: defaultValues.keyword,
+ props: {
+ allowClear: true,
+ },
+ },
+ {
+ type: 'select',
+ name: 'status',
+ label: i18n.t('basic.Status'),
+ initialValue: defaultValues.status,
+ props: {
+ allowClear: true,
+ options: statusList,
+ dropdownMatchSelectWidth: false,
},
- ].concat(
- pickObjectArray(['status'], groupForm).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
- );
+ },
+];
+
+export const useColumns = ({ onDelete, openModal }) => {
+ const { defaultValue } = useDefaultMeta('group');
+
+ const { Entity } = useLoadMeta('group', defaultValue);
-export const getColumns = ({ onDelete, openModal }) => {
const genCreateUrl = record => `/group/create/${record.inlongGroupId}`;
const genDetailUrl = record =>
[0, 100].includes(record.status)
? genCreateUrl(record)
: `/group/detail/${record.inlongGroupId}`;
- return groupTable
- .map(item => {
- if (item.dataIndex === 'inlongGroupId') {
- return { ...item, render: (text, record) => <Link to={genDetailUrl(record)}>{text}</Link> };
- }
- return item;
- })
- .concat([
- {
- title: i18n.t('basic.Operating'),
- dataIndex: 'action',
- render: (text, record) => (
- <>
+ return Entity?.ColumnList?.map(item => {
+ if (item.dataIndex === 'inlongGroupId') {
+ return { ...item, render: (text, record) => <Link to={genDetailUrl(record)}>{text}</Link> };
+ }
+ return item;
+ }).concat([
+ {
+ title: i18n.t('basic.Operating'),
+ dataIndex: 'action',
+ render: (text, record) => (
+ <>
+ <Button type="link">
+ <Link to={genDetailUrl(record)}>{i18n.t('basic.Detail')}</Link>
+ </Button>
+ {[102].includes(record?.status) && (
<Button type="link">
- <Link to={genDetailUrl(record)}>{i18n.t('basic.Detail')}</Link>
+ <Link to={genCreateUrl(record)}>{i18n.t('basic.Edit')}</Link>
</Button>
- {[102].includes(record?.status) && (
- <Button type="link">
- <Link to={genCreateUrl(record)}>{i18n.t('basic.Edit')}</Link>
- </Button>
- )}
- <Button type="link" onClick={() => onDelete(record)}>
- {i18n.t('basic.Delete')}
+ )}
+ <Button type="link" onClick={() => onDelete(record)}>
+ {i18n.t('basic.Delete')}
+ </Button>
+ {record?.status && (record?.status === 120 || record?.status === 130) && (
+ <Button type="link" onClick={() => openModal(record)}>
+ {i18n.t('pages.GroupDashboard.config.ExecuteLog')}
</Button>
- {record?.status && (record?.status === 120 || record?.status === 130) && (
- <Button type="link" onClick={() => openModal(record)}>
- {i18n.t('pages.GroupDashboard.config.ExecuteLog')}
- </Button>
- )}
- </>
- ),
- },
- ]);
+ )}
+ </>
+ ),
+ },
+ ]);
};
diff --git a/inlong-dashboard/src/pages/GroupDashboard/index.tsx b/inlong-dashboard/src/pages/GroupDashboard/index.tsx
index 2df87be92..605407436 100644
--- a/inlong-dashboard/src/pages/GroupDashboard/index.tsx
+++ b/inlong-dashboard/src/pages/GroupDashboard/index.tsx
@@ -27,7 +27,7 @@ import { useTranslation } from 'react-i18next';
import { useRequest, useHistory } from '@/hooks';
import { defaultSize } from '@/configs/pagination';
import ExecutionLogModal from './ExecutionLogModal';
-import { dashCardList, getFilterFormContent, getColumns } from './config';
+import { dashCardList, getFilterFormContent, useColumns } from './config';
const Comp: React.FC = () => {
const { t } = useTranslation();
@@ -108,6 +108,8 @@ const Comp: React.FC = () => {
title: summary[item.dataIndex] || 0,
}));
+ const columns = useColumns({ onDelete, openModal });
+
return (
<PageContainer useDefaultBreadcrumb={false} useDefaultContainer={false}>
<Container>
@@ -127,7 +129,7 @@ const Comp: React.FC = () => {
onFilter,
}}
table={{
- columns: getColumns({ onDelete, openModal }),
+ columns,
rowKey: 'id',
dataSource: data?.list,
pagination,
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx b/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx
index 22fad1916..3cd253ea6 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataSources/DetailModal.tsx
@@ -17,14 +17,13 @@
* under the License.
*/
-import React, { useCallback, useMemo, useState } from 'react';
+import React, { useMemo, useState } from 'react';
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 } from '@/metas/sources';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
import request from '@/utils/request';
export interface Props extends ModalProps {
@@ -33,46 +32,23 @@ export interface Props extends ModalProps {
inlongGroupId?: string;
}
-const sourcesMap: Record<string, typeof sources[0]> = sources.reduce(
- (acc, cur) => ({
- ...acc,
- [cur.value]: cur,
- }),
- {},
-);
-
const Comp: React.FC<Props> = ({ id, inlongGroupId, ...modalProps }) => {
const [form] = useForm();
const { t } = useTranslation();
- const [type, setType] = useState(sources[0].value);
+ const { defaultValue } = useDefaultMeta('source');
- const toFormVals = useCallback(
- v => {
- const mapFunc = sourcesMap[type]?.toFormValues;
- return mapFunc ? mapFunc(v) : v;
- },
- [type],
- );
+ const [type, setType] = useState(defaultValue);
- const toSubmitVals = useCallback(
- v => {
- const mapFunc = sourcesMap[type]?.toSubmitValues;
- return mapFunc ? mapFunc(v) : v;
- },
- [type],
- );
+ const { Entity } = useLoadMeta('source', type);
const { data, run: getData } = useRequest(
id => ({
url: `/source/get/${id}`,
- params: {
- sourceType: type,
- },
}),
{
manual: true,
- formatResult: result => toFormVals(result),
+ formatResult: result => new Entity()?.parse(result) || result,
onSuccess: result => {
form.setFieldsValue(result);
setType(result.sourceType);
@@ -82,7 +58,7 @@ const Comp: React.FC<Props> = ({ id, inlongGroupId, ...modalProps }) => {
const onOk = async () => {
const values = await form.validateFields();
- const submitData = toSubmitVals(values);
+ const submitData = new Entity()?.stringify(values) || values;
const isUpdate = Boolean(id);
if (isUpdate) {
submitData.id = id;
@@ -105,53 +81,26 @@ const Comp: React.FC<Props> = ({ id, inlongGroupId, ...modalProps }) => {
// open
if (id) {
getData(id);
+ } else {
+ form.setFieldsValue({ inlongGroupId });
}
} else {
form.resetFields();
- setType(sources[0].value);
+ setType(defaultValue);
}
}, [modalProps.visible]);
const formContent = useMemo(() => {
- const currentForm = sourcesMap[type]?.form;
- 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 }],
- } as FormItemProps,
- ].concat(currentForm);
- }, [type, id, t, inlongGroupId]);
+ return Entity ? Entity.FieldList : [];
+ }, [Entity]);
return (
<>
- <Modal {...modalProps} title={sourcesMap[type]?.label} width={666} onOk={onOk}>
+ <Modal {...modalProps} title="Source" width={666} onOk={onOk}>
<FormGenerator
content={formContent}
onValuesChange={(c, values) => setType(values.sourceType)}
- initialValues={id ? data : {}}
+ initialValues={id ? data : { inlongGroupId }}
form={form}
useMaxWidth
/>
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx b/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx
index ffb358263..980c0325d 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataSources/index.tsx
@@ -17,13 +17,13 @@
* under the License.
*/
-import React, { useState, forwardRef, useMemo } from 'react';
+import React, { useState, forwardRef, useMemo, useCallback } from 'react';
import { Button, Modal, message } from 'antd';
import HighTable from '@/components/HighTable';
import { defaultSize } from '@/configs/pagination';
import { useRequest } from '@/hooks';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
import DetailModal from './DetailModal';
-import { sources } from '@/metas/sources';
import i18n from '@/i18n';
import request from '@/utils/request';
import { pickObjectArray } from '@/utils';
@@ -31,30 +31,14 @@ import { CommonInterface } from '../common';
type Props = CommonInterface;
-const getFilterFormContent = defaultValues =>
- [
- {
- type: 'inputsearch',
- name: 'keyword',
- initialValue: defaultValues.keyword,
- props: {
- allowClear: true,
- },
- },
- ].concat(
- pickObjectArray(['sourceType', 'status'], sources[0].form).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
- );
-
const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
+ const { defaultValue } = useDefaultMeta('source');
+
const [options, setOptions] = useState({
// keyword: '',
pageSize: defaultSize,
pageNum: 1,
- sourceType: sources[0].value,
+ sourceType: defaultValue,
});
const [createModal, setCreateModal] = useState<Record<string, unknown>>({
@@ -78,42 +62,45 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
},
);
- const onEdit = ({ id }) => {
+ const onEdit = useCallback(({ id }) => {
setCreateModal({ visible: true, id });
- };
-
- const onDelete = ({ id }) => {
- Modal.confirm({
- title: i18n.t('pages.GroupDetail.Sources.DeleteConfirm'),
- onOk: async () => {
- await request({
- url: `/source/delete/${id}`,
- method: 'DELETE',
- params: {
- sourceType: options.sourceType,
- },
- });
- await getList();
- message.success(i18n.t('pages.GroupDetail.Sources.DeleteSuccessfully'));
- },
- });
- };
+ }, []);
+
+ const onDelete = useCallback(
+ ({ id }) => {
+ Modal.confirm({
+ title: i18n.t('pages.GroupDetail.Sources.DeleteConfirm'),
+ onOk: async () => {
+ await request({
+ url: `/source/delete/${id}`,
+ method: 'DELETE',
+ params: {
+ sourceType: options.sourceType,
+ },
+ });
+ await getList();
+ message.success(i18n.t('pages.GroupDetail.Sources.DeleteSuccessfully'));
+ },
+ });
+ },
+ [getList, options.sourceType],
+ );
- const onChange = ({ current: pageNum, pageSize }) => {
+ const onChange = useCallback(({ current: pageNum, pageSize }) => {
setOptions(prev => ({
...prev,
pageNum,
pageSize,
}));
- };
+ }, []);
- const onFilter = allValues => {
+ const onFilter = useCallback(allValues => {
setOptions(prev => ({
...prev,
...allValues,
pageNum: 1,
}));
- };
+ }, []);
const pagination = {
pageSize: options.pageSize,
@@ -121,26 +108,33 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
total: data?.total,
};
- const columnsMap = useMemo(
- () =>
- sources.reduce(
- (acc, cur) => ({
- ...acc,
- [cur.value]: cur.table,
- }),
- {},
+ const { Entity } = useLoadMeta('source', options.sourceType);
+
+ const getFilterFormContent = useCallback(
+ defaultValues =>
+ [
+ {
+ type: 'inputsearch',
+ name: 'keyword',
+ initialValue: defaultValues.keyword,
+ props: {
+ allowClear: true,
+ },
+ },
+ ].concat(
+ pickObjectArray(['sourceType', 'status'], Entity?.FieldList).map(item => ({
+ ...item,
+ visible: true,
+ initialValue: defaultValues[item.name],
+ })),
),
- [],
+ [Entity?.FieldList],
);
- const columns = [
- {
- title: i18n.t('pages.GroupDetail.Sources.DataStreams'),
- dataIndex: 'inlongStreamId',
- },
- ]
- .concat(columnsMap[options.sourceType])
- .concat([
+ const columns = useMemo(() => {
+ if (!Entity) return [];
+
+ return Entity.ColumnList?.concat([
{
title: i18n.t('basic.Operating'),
dataIndex: 'action',
@@ -157,8 +151,9 @@ const Comp = ({ inlongGroupId, readonly }: Props, ref) => {
</Button>
</>
),
- } as any,
+ },
]);
+ }, [Entity, onDelete, onEdit, readonly]);
return (
<>
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/StreamItemModal.tsx b/inlong-dashboard/src/pages/GroupDetail/DataStream/StreamItemModal.tsx
index a2c32dd9d..46a704fbe 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/StreamItemModal.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataStream/StreamItemModal.tsx
@@ -17,16 +17,14 @@
* under the License.
*/
-import React from 'react';
+import React, { useCallback } from 'react';
import { Modal, message } from 'antd';
import { ModalProps } from 'antd/es/modal';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { useUpdateEffect, useRequest } from '@/hooks';
import i18n from '@/i18n';
-import { groupForm } from '@/metas/group';
-import { streamForm } from '@/metas/stream';
+import { useLoadMeta, useDefaultMeta } from '@/metas';
import request from '@/utils/request';
-import { pickObjectArray } from '@/utils';
import { dataToValues, valuesToData } from './helper';
export interface Props extends ModalProps {
@@ -36,28 +34,77 @@ export interface Props extends ModalProps {
mqType: string;
}
-export const genFormContent = (isCreate, mqType) => {
- return [
- ...streamForm,
- ...pickObjectArray(['dailyRecords', 'dailyStorage', 'peakRecords', 'maxLength'], groupForm).map(
- item => ({
- ...item,
- visible: mqType === 'PULSAR',
- }),
- ),
- ].map(item => {
- const obj = { ...item };
+const Comp: React.FC<Props> = ({ inlongGroupId, inlongStreamId, mqType, ...modalProps }) => {
+ const [form] = useForm();
- if (!isCreate && (obj.name === 'inlongStreamId' || obj.name === 'dataType')) {
- obj.type = 'text';
- }
+ const { defaultValue } = useDefaultMeta('stream');
- return obj;
- });
-};
+ const { Entity } = useLoadMeta('stream', defaultValue);
-const Comp: React.FC<Props> = ({ inlongGroupId, inlongStreamId, mqType, ...modalProps }) => {
- const [form] = useForm();
+ const genFormContent = useCallback(
+ (isCreate, mqType) => {
+ return [
+ ...(Entity?.FieldList || []),
+ {
+ type: 'inputnumber',
+ label: i18n.t('meta.Group.NumberOfAccess'),
+ name: 'dailyRecords',
+ rules: [{ required: true }],
+ suffix: i18n.t('meta.Group.TenThousand/Day'),
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ visible: mqType === 'PULSAR',
+ },
+ {
+ type: 'inputnumber',
+ label: i18n.t('meta.Group.AccessSize'),
+ name: 'dailyStorage',
+ rules: [{ required: true }],
+ suffix: i18n.t('meta.Group.GB/Day'),
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ visible: mqType === 'PULSAR',
+ },
+ {
+ type: 'inputnumber',
+ label: i18n.t('meta.Group.AccessPeakPerSecond'),
+ name: 'peakRecords',
+ rules: [{ required: true }],
+ suffix: i18n.t('meta.Group.Stripe/Second'),
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ visible: mqType === 'PULSAR',
+ },
+ {
+ type: 'inputnumber',
+ label: i18n.t('meta.Group.SingleStripMaximumLength'),
+ name: 'maxLength',
+ rules: [{ required: true }],
+ suffix: 'Byte',
+ props: {
+ min: 1,
+ precision: 0,
+ },
+ visible: mqType === 'PULSAR',
+ },
+ ].map(item => {
+ const obj = { ...item };
+
+ if (!isCreate && (obj.name === 'inlongStreamId' || obj.name === 'dataType')) {
+ obj.type = 'text';
+ }
+
+ return obj;
+ });
+ },
+ [Entity?.FieldList],
+ );
const { data: savedData, run: getStreamData } = useRequest(
{
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx b/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
index 9641bacd1..a86a11b7d 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataStream/config.tsx
@@ -17,8 +17,8 @@
* under the License.
*/
-import { streamForm } from '@/metas/stream';
-import { pickObjectArray } from '@/utils';
+import i18n from '@/i18n';
+import { statusList } from '@/metas/streams/common/status';
export const getFilterFormContent = (defaultValues = {} as any) => [
{
@@ -26,9 +26,15 @@ export const getFilterFormContent = (defaultValues = {} as any) => [
name: 'keyword',
initialValue: defaultValues.keyword,
},
- ...pickObjectArray(['status'], streamForm).map(item => ({
- ...item,
- visible: true,
- initialValue: defaultValues[item.name],
- })),
+ {
+ type: 'select',
+ name: 'status',
+ label: i18n.t('basic.Status'),
+ initialValue: defaultValues.status,
+ props: {
+ allowClear: true,
+ options: statusList,
+ dropdownMatchSelectWidth: false,
+ },
+ },
];
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx b/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx
index e17cf2d09..0a93524e4 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx
@@ -24,7 +24,7 @@ import { defaultSize } from '@/configs/pagination';
import { useRequest } from '@/hooks';
import request from '@/utils/request';
import { useTranslation } from 'react-i18next';
-import { streamTable } from '@/metas/stream';
+import { useLoadMeta, useDefaultMeta } from '@/metas';
import { CommonInterface } from '../common';
import StreamItemModal from './StreamItemModal';
import { getFilterFormContent } from './config';
@@ -34,6 +34,8 @@ type Props = CommonInterface;
const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
const { t } = useTranslation();
+ const { defaultValue } = useDefaultMeta('stream');
+
const [options, setOptions] = useState({
pageSize: defaultSize,
pageNum: 1,
@@ -123,7 +125,9 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
total: data?.total,
};
- const columns = streamTable.concat([
+ const { Entity } = useLoadMeta('stream', defaultValue);
+
+ const columns = Entity?.ColumnList?.concat([
{
title: t('basic.Operating'),
dataIndex: 'action',
diff --git a/inlong-dashboard/src/pages/GroupDetail/Info/config.tsx b/inlong-dashboard/src/pages/GroupDetail/Info/config.tsx
index 5c9245e9c..bea9d36b8 100644
--- a/inlong-dashboard/src/pages/GroupDetail/Info/config.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/Info/config.tsx
@@ -17,13 +17,14 @@
* under the License.
*/
-// import React from 'react';
-import { groupForm } from '@/metas/group';
+import { useLoadMeta } from '@/metas';
import { excludeObjectArray } from '@/utils';
-export const getFormContent = ({ editing, isCreate, isUpdate }) => {
+export const useFormContent = ({ mqType, editing, isCreate, isUpdate }) => {
+ const { Entity } = useLoadMeta('group', mqType);
+
const excludeKeys = ['ensemble'].concat(isCreate ? 'mqResource' : '');
- const fields = excludeObjectArray(excludeKeys, groupForm);
+ const fields = excludeObjectArray(excludeKeys, Entity?.FieldList || []);
return isCreate
? fields.map(item => {
diff --git a/inlong-dashboard/src/pages/GroupDetail/Info/index.tsx b/inlong-dashboard/src/pages/GroupDetail/Info/index.tsx
index 78c9f81fe..3947acb2a 100644
--- a/inlong-dashboard/src/pages/GroupDetail/Info/index.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/Info/index.tsx
@@ -17,15 +17,16 @@
* under the License.
*/
-import React, { useEffect, useMemo, useImperativeHandle, forwardRef } from 'react';
+import React, { useEffect, useMemo, useImperativeHandle, forwardRef, useState } from 'react';
import { Button, Space, message } from 'antd';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { useRequest, useBoolean, useSelector } from '@/hooks';
import { useTranslation } from 'react-i18next';
+import { useDefaultMeta } from '@/metas';
import request from '@/utils/request';
import { State } from '@/models';
import { CommonInterface } from '../common';
-import { getFormContent } from './config';
+import { useFormContent } from './config';
type Props = CommonInterface;
@@ -33,6 +34,10 @@ const Comp = ({ inlongGroupId, readonly, isCreate }: Props, ref) => {
const { t } = useTranslation();
const [editing, { setTrue, setFalse }] = useBoolean(isCreate);
+ const { defaultValue } = useDefaultMeta('consume');
+
+ const [mqType, setMqType] = useState(defaultValue);
+
const { userName } = useSelector<State, State>(state => state);
const [form] = useForm();
@@ -48,7 +53,10 @@ const Comp = ({ inlongGroupId, readonly, isCreate }: Props, ref) => {
...data,
inCharges: data.inCharges.split(','),
}),
- onSuccess: data => form.setFieldsValue(data),
+ onSuccess: data => {
+ form.setFieldsValue(data);
+ setMqType(data.mqType);
+ },
});
const onOk = async () => {
@@ -100,16 +108,20 @@ const Comp = ({ inlongGroupId, readonly, isCreate }: Props, ref) => {
setFalse();
};
+ const formContent = useFormContent({
+ mqType,
+ editing,
+ isCreate,
+ isUpdate,
+ });
+
return (
<div style={{ position: 'relative' }}>
<FormGenerator
form={form}
- content={getFormContent({
- editing,
- isCreate,
- isUpdate,
- })}
+ content={formContent}
initialValues={data}
+ onValuesChange={(c, values) => setMqType(values.mqType)}
useMaxWidth={600}
/>
diff --git a/inlong-dashboard/src/pages/Nodes/DetailModal.tsx b/inlong-dashboard/src/pages/Nodes/DetailModal.tsx
index c4426a3e0..1c89bdc5c 100644
--- a/inlong-dashboard/src/pages/Nodes/DetailModal.tsx
+++ b/inlong-dashboard/src/pages/Nodes/DetailModal.tsx
@@ -21,11 +21,13 @@ import React, { useState, useMemo } from 'react';
import { Modal, message } from 'antd';
import { ModalProps } from 'antd/es/modal';
import FormGenerator, { useForm } from '@/components/FormGenerator';
-import { useRequest, useUpdateEffect } from '@/hooks';
-import request from '@/utils/request';
-import { nodes } from '@/metas/nodes';
+import { useUpdateEffect } from '@/hooks';
+import { dao } from '@/metas/nodes';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
import i18n from '@/i18n';
+const { useFindNodeDao, useSaveNodeDao } = dao;
+
export interface Props extends ModalProps {
// Require when edit
id?: string;
@@ -34,44 +36,29 @@ export interface Props extends ModalProps {
const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
const [form] = useForm();
- const [type, setType] = useState(nodes[0].value);
+ const { defaultValue } = useDefaultMeta('node');
+
+ const [type, setType] = useState(defaultValue);
- const { data: savedData, run: getData } = useRequest(
- id => ({
- url: `/node/get/${id}`,
- }),
- {
- manual: true,
- formatResult: result => ({
- ...result,
- inCharges: result.inCharges?.split(','),
- clusterTags: result.clusterTags?.split(','),
- }),
- onSuccess: result => {
- form.setFieldsValue(result);
- setType(result.type);
- },
+ const { data: savedData, run: getData } = useFindNodeDao({
+ onSuccess: result => {
+ form.setFieldsValue(result);
+ setType(result.type);
},
- );
+ });
- const onOk = async () => {
+ const { runAsync: save } = useSaveNodeDao();
+
+ const onOk = async e => {
const values = await form.validateFields();
- const isUpdate = id;
- const submitData = {
- ...values,
- inCharges: values.inCharges?.join(','),
- clusterTags: values.clusterTags?.join(','),
- };
+ const isUpdate = Boolean(id);
+ const data = { ...values };
if (isUpdate) {
- submitData.id = id;
- submitData.version = savedData?.version;
+ data.id = id;
+ data.version = savedData?.version;
}
- await request({
- url: `/node/${isUpdate ? 'update' : 'save'}`,
- method: 'POST',
- data: submitData,
- });
- await modalProps?.onOk(submitData);
+ await save(data);
+ await modalProps?.onOk(e);
message.success(i18n.t('basic.OperatingSuccess'));
};
@@ -83,14 +70,15 @@ const Comp: React.FC<Props> = ({ id, ...modalProps }) => {
}
} else {
form.resetFields();
- setType(nodes[0].value);
+ setType(defaultValue);
}
}, [modalProps.visible]);
+ const { Entity } = useLoadMeta('node', type);
+
const content = useMemo(() => {
- const current = nodes.find(item => item.value === type);
- return current?.form;
- }, [type]);
+ return Entity ? Entity.FieldList : [];
+ }, [Entity]);
return (
<Modal {...modalProps} title={id ? i18n.t('basic.Detail') : i18n.t('basic.Create')} onOk={onOk}>
diff --git a/inlong-dashboard/src/pages/Nodes/index.tsx b/inlong-dashboard/src/pages/Nodes/index.tsx
index 03c69e3e3..fd2c279ae 100644
--- a/inlong-dashboard/src/pages/Nodes/index.tsx
+++ b/inlong-dashboard/src/pages/Nodes/index.tsx
@@ -23,59 +23,29 @@ import i18n from '@/i18n';
import HighTable from '@/components/HighTable';
import { PageContainer } from '@/components/PageContainer';
import { defaultSize } from '@/configs/pagination';
-import { useRequest } from '@/hooks';
-import { nodes } from '@/metas/nodes';
+import { dao } from '@/metas/nodes';
+import { useDefaultMeta, useLoadMeta } from '@/metas';
import DetailModal from './DetailModal';
-import request from '@/utils/request';
-
-const getFilterFormContent = defaultValues => [
- {
- type: 'inputsearch',
- name: 'keyword',
- },
- {
- type: 'radiobutton',
- name: 'type',
- label: i18n.t('meta.Nodes.Type'),
- initialValue: defaultValues.type,
- props: {
- buttonStyle: 'solid',
- options: nodes.map(item => ({
- label: item.label,
- value: item.value,
- })),
- },
- },
-];
+
+const { useListNodeDao, useDeleteNodeDao } = dao;
const Comp: React.FC = () => {
+ const { defaultValue, options: nodes } = useDefaultMeta('node');
+
const [options, setOptions] = useState({
keyword: '',
pageSize: defaultSize,
pageNum: 1,
- type: nodes[0].value,
+ type: defaultValue,
});
const [detailModal, setDetailModal] = useState<Record<string, unknown>>({
visible: false,
});
- const {
- data,
- loading,
- run: getList,
- } = useRequest(
- {
- url: '/node/list',
- method: 'POST',
- data: {
- ...options,
- },
- },
- {
- refreshDeps: [options],
- },
- );
+ const { data, loading, run: getList } = useListNodeDao({ options });
+
+ const { runAsync: destory } = useDeleteNodeDao();
const onEdit = ({ id }) => {
setDetailModal({ visible: true, id });
@@ -86,16 +56,13 @@ const Comp: React.FC = () => {
Modal.confirm({
title: i18n.t('basic.DeleteConfirm'),
onOk: async () => {
- await request({
- url: `/node/delete/${id}`,
- method: 'DELETE',
- });
+ await destory(id);
await getList();
message.success(i18n.t('basic.DeleteSuccess'));
},
});
},
- [getList],
+ [getList, destory],
);
const onChange = ({ current: pageNum, pageSize }) => {
@@ -120,33 +87,52 @@ const Comp: React.FC = () => {
total: data?.total,
};
+ const getFilterFormContent = useCallback(
+ defaultValues => [
+ {
+ type: 'inputsearch',
+ name: 'keyword',
+ },
+ {
+ type: 'radiobutton',
+ name: 'type',
+ label: i18n.t('meta.Nodes.Type'),
+ initialValue: defaultValues.type,
+ props: {
+ buttonStyle: 'solid',
+ options: nodes,
+ },
+ },
+ ],
+ [nodes],
+ );
+
+ const { Entity } = useLoadMeta('node', options.type);
+
const columns = useMemo(() => {
- const current = nodes.find(item => item.value === options.type);
- if (!current?.table) return [];
-
- return current.table
- .map(item => ({
- ...item,
- ellipsisMulti: 2,
- }))
- .concat([
- {
- title: i18n.t('basic.Operating'),
- dataIndex: 'action',
- width: 200,
- render: (text, record) => (
- <>
- <Button type="link" onClick={() => onEdit(record)}>
- {i18n.t('basic.Edit')}
- </Button>
- <Button type="link" onClick={() => onDelete(record)}>
- {i18n.t('basic.Delete')}
- </Button>
- </>
- ),
- } as any,
- ]);
- }, [options.type, onDelete]);
+ if (!Entity) return [];
+
+ return Entity.ColumnList?.map(item => ({
+ ...item,
+ ellipsisMulti: 2,
+ })).concat([
+ {
+ title: i18n.t('basic.Operating'),
+ dataIndex: 'action',
+ width: 200,
+ render: (text, record) => (
+ <>
+ <Button type="link" onClick={() => onEdit(record)}>
+ {i18n.t('basic.Edit')}
+ </Button>
+ <Button type="link" onClick={() => onDelete(record)}>
+ {i18n.t('basic.Delete')}
+ </Button>
+ </>
+ ),
+ } as any,
+ ]);
+ }, [Entity, onDelete]);
return (
<PageContainer useDefaultBreadcrumb={false}>
diff --git a/inlong-dashboard/src/pages/ProcessDetail/Access.tsx b/inlong-dashboard/src/pages/ProcessDetail/Access.tsx
index 6b35401f7..b3afabeb9 100644
--- a/inlong-dashboard/src/pages/ProcessDetail/Access.tsx
+++ b/inlong-dashboard/src/pages/ProcessDetail/Access.tsx
@@ -20,7 +20,7 @@
import React, { useMemo, forwardRef, useImperativeHandle, useEffect } from 'react';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { CommonInterface } from './common';
-import { getFormContent } from './AccessConfig';
+import { useGroupFormContent, getFormContent } from './AccessConfig';
export type Props = CommonInterface;
@@ -57,6 +57,12 @@ const Comp = ({ defaultData, isViwer, suffixContent, noExtraForm, isFinished }:
onOk,
}));
+ const groupFormContent = useGroupFormContent({
+ mqType: defaultData?.processInfo?.formData?.groupInfo?.mqType,
+ isViwer,
+ isFinished,
+ });
+
// Easy to set some default values of the form
const dataLoaded = useMemo(() => {
return !!(defaultData && Object.keys(defaultData).length);
@@ -74,6 +80,7 @@ const Comp = ({ defaultData, isViwer, suffixContent, noExtraForm, isFinished }:
suffixContent,
noExtraForm,
isFinished,
+ groupFormContent,
})}
/>
)
diff --git a/inlong-dashboard/src/pages/ProcessDetail/AccessConfig.tsx b/inlong-dashboard/src/pages/ProcessDetail/AccessConfig.tsx
index e9ac2e02c..f025e0637 100644
--- a/inlong-dashboard/src/pages/ProcessDetail/AccessConfig.tsx
+++ b/inlong-dashboard/src/pages/ProcessDetail/AccessConfig.tsx
@@ -20,10 +20,12 @@
import React from 'react';
import { Divider, Table } from 'antd';
import i18n from '@/i18n';
-import { groupForm } from '@/metas/group';
+import { useLoadMeta } from '@/metas';
-const getContent = (isFinished, isViwer) =>
- groupForm.map(item => {
+export const useGroupFormContent = ({ mqType = '', isFinished, isViwer }) => {
+ const { Entity } = useLoadMeta('group', mqType);
+
+ return Entity?.FieldList?.map(item => {
const obj = { ...item };
const canEditSet = new Set([
@@ -52,8 +54,16 @@ const getContent = (isFinished, isViwer) =>
return obj;
});
+};
-export const getFormContent = ({ isViwer, formData, suffixContent, noExtraForm, isFinished }) => {
+export const getFormContent = ({
+ isViwer,
+ formData,
+ suffixContent,
+ noExtraForm,
+ isFinished,
+ groupFormContent = [],
+}) => {
const array = [
{
type: (
@@ -62,7 +72,7 @@ export const getFormContent = ({ isViwer, formData, suffixContent, noExtraForm,
</Divider>
),
},
- ...(getContent(isFinished, isViwer) || []),
+ ...groupFormContent,
{
type: (
<Divider orientation="left">
diff --git a/inlong-dashboard/src/pages/ProcessDetail/Consume.tsx b/inlong-dashboard/src/pages/ProcessDetail/Consume.tsx
index 700d7f7ed..6dc2f57f8 100644
--- a/inlong-dashboard/src/pages/ProcessDetail/Consume.tsx
+++ b/inlong-dashboard/src/pages/ProcessDetail/Consume.tsx
@@ -20,7 +20,7 @@
import React, { forwardRef, useEffect, useImperativeHandle } from 'react';
import FormGenerator, { useForm } from '@/components/FormGenerator';
import { CommonInterface } from './common';
-import { getFormContent } from './ConsumeConfig';
+import { useConsumeFormContent, getFormContent } from './ConsumeConfig';
type Props = CommonInterface;
@@ -53,6 +53,10 @@ const Comp = (
onOk,
}));
+ const consumeFormContent = useConsumeFormContent(
+ defaultData?.processInfo?.formData?.consumeInfo?.mqType,
+ );
+
return (
Object.keys(defaultData).length && (
<FormGenerator
@@ -64,6 +68,7 @@ const Comp = (
noExtraForm,
defaultData?.processInfo?.formData,
suffixContent,
+ consumeFormContent,
)}
/>
)
diff --git a/inlong-dashboard/src/pages/ProcessDetail/ConsumeConfig.tsx b/inlong-dashboard/src/pages/ProcessDetail/ConsumeConfig.tsx
index ce5b71ee8..b4245f4d7 100644
--- a/inlong-dashboard/src/pages/ProcessDetail/ConsumeConfig.tsx
+++ b/inlong-dashboard/src/pages/ProcessDetail/ConsumeConfig.tsx
@@ -20,10 +20,12 @@
import React from 'react';
import { Divider } from 'antd';
import i18n from '@/i18n';
-import { consumeForm } from '@/metas/consume';
+import { useLoadMeta } from '@/metas';
-const getContent = () => {
- return consumeForm.map(item => {
+export const useConsumeFormContent = (mqType = '') => {
+ const { Entity } = useLoadMeta('consume', mqType);
+
+ return Entity?.FieldList?.map(item => {
const obj = { ...item };
if (typeof obj.suffix !== 'string') {
delete obj.suffix;
@@ -45,6 +47,7 @@ export const getFormContent = (
noExtraForm: boolean,
formData: Record<string, any> = {},
suffixContent,
+ consumeFormContent = [],
) => {
const array = [
{
@@ -54,7 +57,7 @@ export const getFormContent = (
</Divider>
),
},
- ...(getContent() || []),
+ ...consumeFormContent,
];
const extraForm =
diff --git a/inlong-dashboard/tsconfig.json b/inlong-dashboard/tsconfig.json
index 67f1e4818..03bfa1b28 100644
--- a/inlong-dashboard/tsconfig.json
+++ b/inlong-dashboard/tsconfig.json
@@ -25,7 +25,8 @@
"isolatedModules": true,
"noEmit": true,
"jsx": "react",
- "noFallthroughCasesInSwitch": true
+ "noFallthroughCasesInSwitch": true,
+ "experimentalDecorators": true
},
"exclude": [
"build",