This is an automated email from the ASF dual-hosted git repository. zirui 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 e7c4678119 [INLONG-9140][Dashboard] Data synchronization sink supports table creation (#9141) e7c4678119 is described below commit e7c4678119b5b1c5f51b4a7d2a9993acef028c18 Author: Lizhen <88174078+bluew...@users.noreply.github.com> AuthorDate: Tue Dec 5 18:18:21 2023 +0800 [INLONG-9140][Dashboard] Data synchronization sink supports table creation (#9141) --- inlong-dashboard/src/plugins/RenderRow.ts | 7 + .../src/plugins/sinks/common/SinkDefaultInfo.ts | 17 +- .../src/plugins/sinks/defaults/ClickHouse.ts | 41 ++- .../src/plugins/sinks/defaults/Elasticsearch.ts | 3 +- .../src/plugins/sinks/defaults/Greenplum.ts | 75 +++-- .../src/plugins/sinks/defaults/Hive.ts | 35 ++- .../src/plugins/sinks/defaults/Hudi.ts | 30 +- .../src/plugins/sinks/defaults/Iceberg.ts | 29 +- .../src/plugins/sinks/defaults/Kudu.ts | 29 +- .../src/plugins/sinks/defaults/MySQL.ts | 67 +++-- .../src/plugins/sinks/defaults/Oracle.ts | 67 +++-- .../src/plugins/sinks/defaults/PostgreSQL.ts | 75 +++-- .../src/plugins/sinks/defaults/Redis.ts | 31 +- .../src/plugins/sinks/defaults/SQLServer.ts | 79 +++-- .../src/plugins/sinks/defaults/StarRocks.ts | 56 +++- .../src/plugins/sinks/defaults/TDSQLPostgreSQL.ts | 75 +++-- .../src/ui/components/CreateTable/DetailModal.tsx | 165 +++++++++++ .../src/ui/components/CreateTable/index.tsx | 86 ++++++ .../src/ui/components/FieldList/FieldTypeConf.tsx | 324 ++++++++++----------- inlong-dashboard/src/ui/locales/cn.json | 4 +- inlong-dashboard/src/ui/locales/en.json | 2 +- .../SynchronizeDetail/SyncSink/DetailModal.tsx | 22 +- .../src/ui/pages/SynchronizeDetail/SyncT/helper.ts | 17 +- 23 files changed, 971 insertions(+), 365 deletions(-) diff --git a/inlong-dashboard/src/plugins/RenderRow.ts b/inlong-dashboard/src/plugins/RenderRow.ts index c9f78d50d2..591f93f074 100644 --- a/inlong-dashboard/src/plugins/RenderRow.ts +++ b/inlong-dashboard/src/plugins/RenderRow.ts @@ -23,6 +23,7 @@ import merge from 'lodash/merge'; export abstract class RenderRow { static FieldList: FieldItemType[] = []; static SyncFieldSet = new Set<string>(); + static SyncCreateTableFieldSet = new Set<string>(); static FieldDecorator(config: FieldItemType): PropertyDecorator { return (target: any, propertyKey: string) => { @@ -53,6 +54,12 @@ export abstract class RenderRow { }; } + static SyncCreateTableField(): PropertyDecorator { + return (target: any, propertyKey: string) => { + target.constructor.SyncCreateTableFieldSet.add(propertyKey); + }; + } + abstract renderRow(fields?: FieldItemType[]): FieldItemType[]; } diff --git a/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts b/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts index 9e986caea6..fb9a1f297f 100644 --- a/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts +++ b/inlong-dashboard/src/plugins/sinks/common/SinkDefaultInfo.ts @@ -27,7 +27,7 @@ import { statusList, genStatusTag } from './status'; import { sinks, defaultValue } from '..'; const { I18nMap, I18n } = DataWithBackend; -const { FieldList, FieldDecorator, SyncField, SyncFieldSet } = RenderRow; +const { FieldList, FieldDecorator, SyncField, SyncFieldSet, SyncCreateTableFieldSet } = RenderRow; const { ColumnList, ColumnDecorator } = RenderList; export class SinkDefaultInfo implements DataWithBackend, RenderRow, RenderList { @@ -35,6 +35,7 @@ export class SinkDefaultInfo implements DataWithBackend, RenderRow, RenderList { static FieldList = FieldList; static ColumnList = ColumnList; static SyncFieldSet = SyncFieldSet; + static SyncCreateTableFieldSet = SyncCreateTableFieldSet; readonly id: number; @@ -159,8 +160,22 @@ export class SinkDefaultInfo implements DataWithBackend, RenderRow, RenderList { return FieldList.filter(item => SyncFieldSet.has(item.name as string)); } + renderSyncCreateTableRow() { + const constructor = this.constructor as typeof SinkDefaultInfo; + const { FieldList, SyncCreateTableFieldSet } = constructor; + return FieldList.filter(item => SyncCreateTableFieldSet.has(item.name as string)); + } + renderRow() { const constructor = this.constructor as typeof SinkDefaultInfo; + constructor.FieldList.filter(item => { + if (item.name === 'tableName' || item.name === 'primaryKey' || item.name === 'database') { + item.type = 'input'; + } + if (item.name === 'createTableField') { + item.hidden = true; + } + }); return constructor.FieldList; } diff --git a/inlong-dashboard/src/plugins/sinks/defaults/ClickHouse.ts b/inlong-dashboard/src/plugins/sinks/defaults/ClickHouse.ts index 3c03835e2a..d54792f061 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/ClickHouse.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/ClickHouse.ts @@ -25,9 +25,10 @@ import EditableTable from '@/ui/components/EditableTable'; import { SinkInfo } from '../common/SinkInfo'; import { sourceFields } from '../common/sourceFields'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const clickHouseTargetTypes = [ @@ -62,10 +63,17 @@ export default class ClickHouseSink dbName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -119,6 +127,7 @@ export default class ClickHouseSink suffix: i18n.t('meta.Sinks.ClickHouse.FlushIntervalUnit'), }) @I18n('meta.Sinks.ClickHouse.FlushInterval') + @SyncCreateTableField() @ColumnDecorator() flushInterval: number; @@ -134,6 +143,7 @@ export default class ClickHouseSink }) @I18n('meta.Sinks.ClickHouse.FlushRecord') @ColumnDecorator() + @SyncCreateTableField() flushRecord: number; @FieldDecorator({ @@ -148,7 +158,8 @@ export default class ClickHouseSink }) @I18n('meta.Sinks.ClickHouse.RetryTimes') @ColumnDecorator() - retryTime: number; + @SyncCreateTableField() + retryTimes: number; @FieldDecorator({ type: 'radio', @@ -170,6 +181,7 @@ export default class ClickHouseSink }) @I18n('meta.Sinks.ClickHouse.IsDistributed') @ColumnDecorator() + @SyncCreateTableField() isDistributed: number; @FieldDecorator({ @@ -197,6 +209,7 @@ export default class ClickHouseSink }) @I18n('meta.Sinks.ClickHouse.PartitionStrategy') @ColumnDecorator() + @SyncCreateTableField() partitionStrategy: string; @FieldDecorator({ @@ -209,6 +222,7 @@ export default class ClickHouseSink }) @I18n('meta.Sinks.ClickHouse.PartitionFields') @ColumnDecorator() + @SyncCreateTableField() partitionFields: string; @FieldDecorator({ @@ -235,6 +249,7 @@ export default class ClickHouseSink }) @I18n('meta.Sinks.ClickHouse.Engine') @ColumnDecorator() + @SyncCreateTableField() engine: string; @FieldDecorator({ @@ -244,6 +259,7 @@ export default class ClickHouseSink }), }) @I18n('meta.Sinks.ClickHouse.OrderBy') + @SyncCreateTableField() orderBy: string; @FieldDecorator({ @@ -254,6 +270,7 @@ export default class ClickHouseSink }) @I18n('meta.Sinks.ClickHouse.PartitionBy') @ColumnDecorator() + @SyncCreateTableField() partitionBy: string; @FieldDecorator({ @@ -273,6 +290,7 @@ export default class ClickHouseSink }), }) @I18n('meta.Sinks.ClickHouse.Cluster') + @SyncCreateTableField() @ColumnDecorator() cluster: string; @@ -328,6 +346,7 @@ export default class ClickHouseSink }) @I18n('Time To Live') @ColumnDecorator() + @SyncCreateTableField() ttl: number; @FieldDecorator({ @@ -341,6 +360,22 @@ export default class ClickHouseSink }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Elasticsearch.ts b/inlong-dashboard/src/plugins/sinks/defaults/Elasticsearch.ts index 6ac2902720..468f7ffcbb 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Elasticsearch.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Elasticsearch.ts @@ -25,9 +25,10 @@ import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const esTypes = [ diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Greenplum.ts b/inlong-dashboard/src/plugins/sinks/defaults/Greenplum.ts index 47ddf75965..c071fb16cc 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Greenplum.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Greenplum.ts @@ -22,35 +22,36 @@ import i18n from '@/i18n'; import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const fieldTypesConf = { - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - INT2: () => '', - SMALLSERIAL: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - SERIAL: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - SERIAL2: () => '', - INTEGER: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - BIGSERIAL: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - REAL: () => '', - FLOAT4: () => '', - FLOAT8: () => '', - DOUBLE: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - BOOLEAN: () => '', - DATE: () => '', - TIME: () => '', - TIMESTAMP: () => '', - CHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), - CHARACTER: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), - VARCHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), - TEXT: () => '', - BYTEA: () => '', + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + int2: () => '', + smallserial: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + serial: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + serial2: () => '', + integer: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + bigserial: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + real: () => '', + float4: () => '', + float8: () => '', + double: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + boolean: () => '', + date: () => '', + time: () => '', + timestamp: () => '', + char: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), + character: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), + varchar: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), + text: () => '', + bytea: () => '', }; const greenplumFieldTypes = Object.keys(fieldTypesConf).reduce( @@ -80,10 +81,17 @@ export default class GreenplumSink jdbcUrl: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -122,7 +130,6 @@ export default class GreenplumSink ], }), }) - @SyncField() @I18n('meta.Sinks.EnableCreateResource') enableCreateResource: number; @@ -161,6 +168,22 @@ export default class GreenplumSink }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Hive.ts b/inlong-dashboard/src/plugins/sinks/defaults/Hive.ts index 551feefc7c..7bc6a149e5 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Hive.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Hive.ts @@ -25,9 +25,10 @@ import EditableTable from '@/ui/components/EditableTable'; import { SinkInfo } from '../common/SinkInfo'; import { sourceFields } from '../common/sourceFields'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const hiveFieldTypes = [ @@ -66,10 +67,17 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende dbName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -96,7 +104,6 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende ], }), }) - @SyncField() @I18n('meta.Sinks.EnableCreateResource') enableCreateResource: number; @@ -169,7 +176,7 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende }), }) @I18n('meta.Sinks.Hive.FileFormat') - @SyncField() + @SyncCreateTableField() fileFormat: string; @FieldDecorator({ @@ -191,7 +198,7 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende rules: [{ required: true }], }) @I18n('meta.Sinks.Hive.DataEncoding') - @SyncField() + @SyncCreateTableField() dataEncoding: string; @FieldDecorator({ @@ -244,7 +251,7 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende ], }) @I18n('meta.Sinks.Hive.DataSeparator') - @SyncField() + @SyncCreateTableField() dataSeparator: string; @FieldDecorator({ @@ -259,6 +266,22 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende }) sinkFieldList: Record<string, unknown>[]; + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; + @FieldDecorator({ type: EditableTable, tooltip: i18n.t('meta.Sinks.Hive.PartitionFieldListHelp'), diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Hudi.ts b/inlong-dashboard/src/plugins/sinks/defaults/Hudi.ts index 4d096a17e3..ae66a218a0 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Hudi.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Hudi.ts @@ -25,9 +25,10 @@ import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const hudiFieldTypes = [ @@ -120,10 +121,17 @@ export default class HudiSink extends SinkInfo implements DataWithBackend, Rende dbName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -151,7 +159,6 @@ export default class HudiSink extends SinkInfo implements DataWithBackend, Rende }), }) @I18n('meta.Sinks.EnableCreateResource') - @SyncField() enableCreateResource: number; @FieldDecorator({ @@ -259,10 +266,25 @@ export default class HudiSink extends SinkInfo implements DataWithBackend, Rende }) sinkFieldList: Record<string, unknown>[]; + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; + @FieldDecorator({ type: 'input', tooltip: i18n.t('meta.Sinks.Hudi.PrimaryKeyHelper'), - rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), }), diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Iceberg.ts b/inlong-dashboard/src/plugins/sinks/defaults/Iceberg.ts index 2597f3c0ff..83fb8f7bfc 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Iceberg.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Iceberg.ts @@ -25,9 +25,10 @@ import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const icebergFieldTypes = [ @@ -123,10 +124,17 @@ export default class IcebergSink dbName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -154,7 +162,6 @@ export default class IcebergSink }), }) @I18n('meta.Sinks.EnableCreateResource') - @SyncField() enableCreateResource: number; @FieldDecorator({ @@ -281,6 +288,22 @@ export default class IcebergSink }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Kudu.ts b/inlong-dashboard/src/plugins/sinks/defaults/Kudu.ts index 5b6e5d5965..544b72924d 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Kudu.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Kudu.ts @@ -25,9 +25,10 @@ import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const kuduFieldTypes = [ @@ -86,10 +87,17 @@ export default class KuduSink extends SinkInfo implements DataWithBackend, Rende dataNodeName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -117,7 +125,6 @@ export default class KuduSink extends SinkInfo implements DataWithBackend, Rende }), }) @I18n('meta.Sinks.EnableCreateResource') - @SyncField() enableCreateResource: number; @FieldDecorator({ @@ -199,6 +206,22 @@ export default class KuduSink extends SinkInfo implements DataWithBackend, Rende }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/MySQL.ts b/inlong-dashboard/src/plugins/sinks/defaults/MySQL.ts index 39cc169280..95a18ffdd9 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/MySQL.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/MySQL.ts @@ -23,35 +23,36 @@ import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const fieldTypesConf = { - TINYINT: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), - MEDIUMINT: (m, d) => (1 <= m && m <= 9 ? '' : '1<=M<=9'), - INT: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), - FLOAT: (m, d) => + tinyint: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), + mediumint: (m, d) => (1 <= m && m <= 9 ? '' : '1<=M<=9'), + int: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), + float: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), - DOUBLE: (m, d) => + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), + double: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - NUMERIC: (m, d) => + numeric: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - DECIMAL: (m, d) => + decimal: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - BOOLEAN: () => '', - DATE: () => '', - TIME: () => '', - DATETIME: () => '', - CHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), - VARCHAR: (m, d) => (1 <= m && m <= 16383 ? '' : '1<=M<=16383'), - TEXT: () => '', - BINARY: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), - VARBINARY: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), - BLOB: () => '', + boolean: () => '', + date: () => '', + time: () => '', + datetime: () => '', + char: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), + varchar: (m, d) => (1 <= m && m <= 16383 ? '' : '1<=M<=16383'), + text: () => '', + binary: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), + varbinary: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), + blob: () => '', }; const fieldTypes = Object.keys(fieldTypesConf).reduce( @@ -77,10 +78,17 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende databaseName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -120,7 +128,6 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende }), }) @I18n('meta.Sinks.EnableCreateResource') - @SyncField() enableCreateResource: number; @FieldDecorator({ @@ -146,6 +153,22 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Oracle.ts b/inlong-dashboard/src/plugins/sinks/defaults/Oracle.ts index a405e03ef7..d932d7e58c 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Oracle.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Oracle.ts @@ -22,31 +22,32 @@ import i18n from '@/i18n'; import { SinkInfo } from '../common/SinkInfo'; import { sourceFields } from '../common/sourceFields'; import EditableTable from '@/ui/components/EditableTable'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const fieldTypesConf = { - BINARY_FLOAT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - BINARY_DOUBLE: (m, d) => (1 <= m && m <= 10 ? '' : '1 <= M <= 10'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - FLOAT: (m, d) => (1 <= m && m <= 126 ? '' : '1 <= M <= 126'), - FLOAT4: () => '', - FLOAT8: () => '', - DOUBLE: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - REAL: () => '', - NUMBER: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - DATE: () => '', - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - BOOLEAN: () => '', - TIMESTAMP: () => '', - CHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - VARCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - CLOB: () => '', - RAW: (m, d) => (1 <= m && m <= 2000 ? '' : ' 1 <= M <= 2000'), - BLOB: () => '', + binary_float: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + binary_double: (m, d) => (1 <= m && m <= 10 ? '' : '1 <= M <= 10'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + float: (m, d) => (1 <= m && m <= 126 ? '' : '1 <= M <= 126'), + float4: () => '', + float8: () => '', + double: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + real: () => '', + number: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + date: () => '', + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + boolean: () => '', + timestamp: () => '', + char: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + varchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + clob: () => '', + raw: (m, d) => (1 <= m && m <= 2000 ? '' : ' 1 <= M <= 2000'), + blob: () => '', }; const oracleFieldTypes = Object.keys(fieldTypesConf).reduce( @@ -73,10 +74,17 @@ export default class OracleSink extends SinkInfo implements DataWithBackend, Ren jdbcUrl: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -116,7 +124,6 @@ export default class OracleSink extends SinkInfo implements DataWithBackend, Ren }), }) @I18n('meta.Sinks.EnableCreateResource') - @SyncField() enableCreateResource: number; @FieldDecorator({ @@ -154,6 +161,22 @@ export default class OracleSink extends SinkInfo implements DataWithBackend, Ren }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/PostgreSQL.ts b/inlong-dashboard/src/plugins/sinks/defaults/PostgreSQL.ts index ae98ebac6e..2e65caa5c7 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/PostgreSQL.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/PostgreSQL.ts @@ -22,35 +22,36 @@ import i18n from '@/i18n'; import EditableTable from '@/ui/components/EditableTable'; import { SinkInfo } from '../common/SinkInfo'; import { sourceFields } from '../common/sourceFields'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const fieldTypesConf = { - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - INT2: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - SMALLSERIAL: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - SERIAL2: () => '', - INTEGER: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - SERIAL: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - BIGSERIAL: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - REAL: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - FLOAT4: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - FLOAT8: (m, d) => (24 < m && m <= 53 ? '' : '24 < M <= 53'), - DOUBLE: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - BOOLEAN: () => '', - DATE: () => '', - TIME: () => '', - TIMESTAMP: () => '', - CHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - CHARACTER: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - VARCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - TEXT: () => '', - BYTEA: () => '', + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + int2: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + smallserial: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + serial2: () => '', + integer: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + serial: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + bigserial: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + real: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + float4: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + float8: (m, d) => (24 < m && m <= 53 ? '' : '24 < M <= 53'), + double: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + boolean: () => '', + date: () => '', + time: () => '', + timestamp: () => '', + char: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + character: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + varchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + text: () => '', + bytea: () => '', }; const postgreSqlFieldTypes = Object.keys(fieldTypesConf).reduce( @@ -89,10 +90,17 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende dbName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -131,7 +139,6 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende ], }), }) - @SyncField() @I18n('meta.Sinks.EnableCreateResource') enableCreateResource: number; @@ -170,6 +177,22 @@ export default class HiveSink extends SinkInfo implements DataWithBackend, Rende }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/Redis.ts b/inlong-dashboard/src/plugins/sinks/defaults/Redis.ts index 35abaf41aa..d3344ebd85 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/Redis.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/Redis.ts @@ -25,9 +25,10 @@ import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const redisTargetTypes = [ @@ -252,12 +253,18 @@ export default class RedisSink extends SinkInfo implements DataWithBackend, Rend formatDataSeparator: string; @FieldDecorator({ - type: 'inputnumber', + type: CreateTable, rules: [{ required: false }], props: values => ({ disabled: [110].includes(values?.status), - min: 0, - placholder: '0', + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + useNumber: true, + fieldName: 'database', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -291,6 +298,22 @@ export default class RedisSink extends SinkInfo implements DataWithBackend, Rend }) sinkFieldList: Record<string, unknown>[]; + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; + @FieldDecorator({ type: EditableTable, rules: [{ required: false }], diff --git a/inlong-dashboard/src/plugins/sinks/defaults/SQLServer.ts b/inlong-dashboard/src/plugins/sinks/defaults/SQLServer.ts index be723b7bf7..93f6780246 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/SQLServer.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/SQLServer.ts @@ -22,36 +22,37 @@ import i18n from '@/i18n'; import EditableTable from '@/ui/components/EditableTable'; import { SinkInfo } from '../common/SinkInfo'; import { sourceFields } from '../common/sourceFields'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const fieldTypesConf = { - CHAR: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M <= 8000'), - VARCHAR: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M<= 8000'), - NCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - NVARCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - TEXT: () => '', - NTEXT: () => '', - XML: () => '', - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - BIGSERIAL: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - MONEY: (m, d) => (1 <= m && m <= 15 && 1 <= d && d <= 4 ? '' : '1 <= M <= 15, 1 <= D <= 4'), - SMALLMONEY: (m, d) => (1 <= m && m <= 7 && 1 <= d && d <= 4 ? '' : '1 <= M <= 7, 1 <= D <= 4'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D <= M'), - FLOAT: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - REAL: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - BIT: (m, d) => (1 <= m && m <= 64 ? '' : '1 <= M <= 64'), - INT: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - TINYINT: (m, d) => (1 <= m && m <= 4 ? '' : '1 <= M <= 4'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - TIME: () => '', - DATETIME: () => '', - DATETIME2: () => '', - SMALLDATETIME: () => '', - DATETIMEOFFSET: () => '', + char: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M <= 8000'), + varchar: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M<= 8000'), + nchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + nvarchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + text: () => '', + ntext: () => '', + xml: () => '', + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + bigserial: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + money: (m, d) => (1 <= m && m <= 15 && 1 <= d && d <= 4 ? '' : '1 <= M <= 15, 1 <= D <= 4'), + smallmoney: (m, d) => (1 <= m && m <= 7 && 1 <= d && d <= 4 ? '' : '1 <= M <= 7, 1 <= D <= 4'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D <= M'), + float: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + real: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + bit: (m, d) => (1 <= m && m <= 64 ? '' : '1 <= M <= 64'), + int: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + tinyint: (m, d) => (1 <= m && m <= 4 ? '' : '1 <= M <= 4'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + time: () => '', + datetime: () => '', + datetime2: () => '', + smalldatetime: () => '', + datetimeoffset: () => '', }; const sqlserverFieldTypes = Object.keys(fieldTypesConf).reduce( @@ -106,11 +107,17 @@ export default class SqlServerSink serverTimezone: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], - initialValue: 'UTC', props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -121,7 +128,6 @@ export default class SqlServerSink @FieldDecorator({ type: 'input', rules: [{ required: true }], - initialValue: 'UTC', props: values => ({ disabled: [110].includes(values?.status), }), @@ -150,7 +156,6 @@ export default class SqlServerSink ], }), }) - @SyncField() @I18n('meta.Sinks.EnableCreateResource') enableCreateResource: number; @@ -209,6 +214,22 @@ export default class SqlServerSink }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/StarRocks.ts b/inlong-dashboard/src/plugins/sinks/defaults/StarRocks.ts index 4f7694d5c2..42c96db88e 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/StarRocks.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/StarRocks.ts @@ -23,29 +23,30 @@ import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; import NodeSelect from '@/ui/components/NodeSelect'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const fieldTypesConf = { - CHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), - VARCHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), - DATE: () => '', - TINYINT: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), - INT: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), - LARGEINT: () => '', - STRING: () => '', - DATETIME: () => '', - FLOAT: (m, d) => + char: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), + varchar: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), + date: () => '', + tinyint: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), + int: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), + largeint: () => '', + string: () => '', + datetime: () => '', + float: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - DOUBLE: (m, d) => + double: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - DECIMAL: (m, d) => + decimal: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - BOOLEAN: () => '', + boolean: () => '', }; const fieldTypes = Object.keys(fieldTypesConf).reduce( @@ -86,10 +87,17 @@ export default class StarRocksSink databaseName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -119,6 +127,22 @@ export default class StarRocksSink }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/plugins/sinks/defaults/TDSQLPostgreSQL.ts b/inlong-dashboard/src/plugins/sinks/defaults/TDSQLPostgreSQL.ts index f3c956bf9c..5d87bb3f1f 100644 --- a/inlong-dashboard/src/plugins/sinks/defaults/TDSQLPostgreSQL.ts +++ b/inlong-dashboard/src/plugins/sinks/defaults/TDSQLPostgreSQL.ts @@ -22,35 +22,36 @@ import i18n from '@/i18n'; import EditableTable from '@/ui/components/EditableTable'; import { sourceFields } from '../common/sourceFields'; import { SinkInfo } from '../common/SinkInfo'; +import CreateTable from '@/ui/components/CreateTable'; const { I18n } = DataWithBackend; -const { FieldDecorator, SyncField } = RenderRow; +const { FieldDecorator, SyncField, SyncCreateTableField } = RenderRow; const { ColumnDecorator } = RenderList; const tdsqlPostgreSQLFieldTypes = [ - 'SMALLINT', - 'SMALLSERIAL', - 'INT2', - 'SERIAL2', - 'INTEGER', - 'SERIAL', - 'BIGINT', - 'BIGSERIAL', - 'REAL', - 'FLOAT4', - 'FLOAT8', - 'DOUBLE', - 'NUMERIC', - 'DECIMAL', - 'BOOLEAN', - 'DATE', - 'TIME', - 'TIMESTAMP', - 'CHAR', - 'CHARACTER', - 'VARCHAR', - 'TEXT', - 'BYTEA', + 'smallint', + 'smallserial', + 'int2', + 'serial2', + 'integer', + 'serial', + 'bigint', + 'bigserial', + 'real', + 'float4', + 'float8', + 'double', + 'numeric', + 'decimal', + 'boolean', + 'date', + 'time', + 'timestamp', + 'char', + 'character', + 'varchar', + 'text', + 'bytea', ].map(item => ({ label: item, value: item, @@ -86,10 +87,17 @@ export default class TDSQLPostgreSQLSink schemaName: string; @FieldDecorator({ - type: 'input', + type: CreateTable, rules: [{ required: true }], props: values => ({ disabled: [110].includes(values?.status), + sinkType: values.sinkType, + inlongGroupId: values.inlongGroupId, + inlongStreamId: values.inlongStreamId, + fieldName: 'tableName', + sinkObj: { + ...values, + }, }), }) @ColumnDecorator() @@ -128,7 +136,6 @@ export default class TDSQLPostgreSQLSink ], }), }) - @SyncField() @I18n('meta.Sinks.EnableCreateResource') enableCreateResource: number; @@ -165,6 +172,22 @@ export default class TDSQLPostgreSQLSink }), }) sinkFieldList: Record<string, unknown>[]; + + @FieldDecorator({ + type: EditableTable, + initialValue: [], + props: values => ({ + size: 'small', + editing: ![110].includes(values?.status), + columns: getFieldListColumns(values).filter( + item => item.dataIndex !== 'sourceFieldName' && item.dataIndex !== 'sourceFieldType', + ), + canBatchAdd: true, + upsertByFieldKey: true, + }), + }) + @SyncCreateTableField() + createTableField: Record<string, unknown>[]; } const getFieldListColumns = sinkValues => { diff --git a/inlong-dashboard/src/ui/components/CreateTable/DetailModal.tsx b/inlong-dashboard/src/ui/components/CreateTable/DetailModal.tsx new file mode 100644 index 0000000000..7f50af298d --- /dev/null +++ b/inlong-dashboard/src/ui/components/CreateTable/DetailModal.tsx @@ -0,0 +1,165 @@ +/* + * 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, { useEffect, useMemo } from 'react'; +import { Modal, message, Button } from 'antd'; +import { ModalProps } from 'antd/es/modal'; +import FormGenerator, { useForm } from '@/ui/components/FormGenerator'; +import { useRequest } from '@/ui/hooks'; +import { useTranslation } from 'react-i18next'; +import i18n from '@/i18n'; +import { SinkMetaType, useLoadMeta } from '@/plugins'; +import EditableTable from '../EditableTable'; +import { sinks } from '@/plugins/sinks'; +import { useLocalStorage } from '@/core/utils/localStorage'; + +export interface Props extends ModalProps { + sinkType: string; + inlongGroupId: string; + inlongStreamId: string; + sinkObj: any; +} + +const Comp: React.FC<Props> = ({ + sinkType, + inlongGroupId, + inlongStreamId, + sinkObj, + ...modalProps +}) => { + const [form] = useForm(); + const { t } = useTranslation(); + + const { loading, Entity } = useLoadMeta<SinkMetaType>('sink', sinkType); + + const [getLocalStorage, setLocalStorage, removeLocalStorage] = useLocalStorage('createTableData'); + + const { data, run: getData } = useRequest( + id => ({ + url: `/sink/get/${id}`, + }), + { + manual: true, + formatResult: result => new Entity()?.parse(result) || result, + onSuccess: result => { + form.setFieldsValue(result); + }, + }, + ); + + const { data: streamData, run: getStreamData } = useRequest( + streamId => ({ + url: `/stream/getBrief`, + params: { + groupId: inlongGroupId, + streamId, + }, + }), + { + manual: true, + }, + ); + + const onOk = async () => { + const values = await form.validateFields(); + const submitData = { + ...values, + enableCreateResource: 1, + sinkFieldList: values.createTableField, + }; + setLocalStorage(submitData); + modalProps?.onOk(values); + message.success(t('pages.GroupDetail.Sources.SaveSuccessfully')); + }; + + const getFormContent = [ + { + type: 'text', + label: i18n.t('components.CreateTable.TableType'), + name: 'createType', + initialValue: sinks.find(c => c.value === sinkType)?.label || sinkType, + }, + ]; + + const formContent = useMemo(() => { + if (Entity) { + const row = new Entity().renderSyncCreateTableRow(); + return [].concat(getFormContent, row).map(item => ({ + ...item, + col: item.type === EditableTable ? 24 : 12, + })); + } + }, [Entity]); + + useEffect(() => { + if ( + Entity && + streamData && + streamData.fieldList?.length && + Entity.FieldList?.some(item => item.name === 'sinkFieldList') + ) { + form.setFieldsValue({ + createTableField: streamData.fieldList.map(item => ({ + sourceFieldName: item.fieldName, + sourceFieldType: item.fieldType, + fieldName: item.fieldName, + fieldType: '', + })), + }); + } + }, [Entity, streamData, form]); + + useEffect(() => { + if (inlongStreamId && modalProps.open) { + getStreamData(inlongStreamId); + if (sinkObj?.id) { + getData(sinkObj?.id); + } + } + }, [getData, getStreamData, inlongStreamId, modalProps.open, sinkObj?.id]); + + return ( + <> + <Modal + {...modalProps} + title={i18n.t('components.CreateTable.Table')} + width={1200} + onOk={onOk} + footer={[ + <Button key="cancel" onClick={e => modalProps.onCancel(e)}> + {t('pages.GroupDetail.Sink.Cancel')} + </Button>, + <Button key="save" type="primary" onClick={() => onOk()}> + {t('pages.GroupDetail.Sink.Save')} + </Button>, + ]} + > + <FormGenerator + form={form} + col={12} + labelCol={{ flex: '0 0 200px' }} + wrapperCol={{ flex: '1' }} + content={formContent} + /> + </Modal> + </> + ); +}; + +export default Comp; diff --git a/inlong-dashboard/src/ui/components/CreateTable/index.tsx b/inlong-dashboard/src/ui/components/CreateTable/index.tsx new file mode 100644 index 0000000000..51a570c153 --- /dev/null +++ b/inlong-dashboard/src/ui/components/CreateTable/index.tsx @@ -0,0 +1,86 @@ +/* + * 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, { useState } from 'react'; +import { Button, Form, Input, InputNumber, Space } from 'antd'; +import DetailModal from './DetailModal'; +import i18n from '@/i18n'; + +export interface Props { + sinkType: string; + fieldName: string; + inlongGroupId?: string; + inlongStreamId?: string; + useNumber?: Boolean; + sinkObj?: React.RefObject<any>; +} + +const CreateTable: React.FC<Props> = ({ + sinkType, + fieldName, + inlongGroupId, + inlongStreamId, + useNumber, + sinkObj, +}) => { + const [createModal, setCreateModal] = useState<Record<string, unknown>>({ + open: false, + }); + + return ( + <Space> + {useNumber ? ( + <> + <Form.Item name={fieldName} rules={[{ required: true }]}> + <InputNumber min={0} /> + </Form.Item> + </> + ) : ( + <> + <Form.Item name={fieldName} rules={[{ required: true }]}> + <Input style={{ width: 200 }} /> + </Form.Item> + </> + )} + <Button + style={{ marginBottom: 20 }} + type="link" + onClick={() => { + setCreateModal({ open: true }); + console.log(sinkObj, 'cll'); + }} + > + {i18n.t('components.CreateTable.Table')} + </Button> + + <DetailModal + {...createModal} + sinkType={sinkType} + sinkObj={sinkObj} + inlongGroupId={inlongGroupId} + inlongStreamId={inlongStreamId} + open={createModal.open as boolean} + onOk={async () => { + setCreateModal({ open: false }); + }} + onCancel={() => setCreateModal({ open: false })} + /> + </Space> + ); +}; + +export default CreateTable; diff --git a/inlong-dashboard/src/ui/components/FieldList/FieldTypeConf.tsx b/inlong-dashboard/src/ui/components/FieldList/FieldTypeConf.tsx index aa0b8d92da..d1b4a00c24 100644 --- a/inlong-dashboard/src/ui/components/FieldList/FieldTypeConf.tsx +++ b/inlong-dashboard/src/ui/components/FieldList/FieldTypeConf.tsx @@ -43,23 +43,23 @@ const clickhouseFieldType = [ })); const dorisFieldTypes = [ - 'NULL_TYPE', - 'BOOLEAN', - 'TINYINT', - 'SMALLINT', - 'INT', - 'BIGINT', - 'FLOAT', - 'DOUBLE', - 'DATE', - 'DATETIME', - 'DECIMAL', - 'CHAR', - 'LARGEINT', - 'VARCHAR', - 'DECIMALV2', - 'TIME', - 'HLL', + 'null_type', + 'boolean', + 'tinyint', + 'smallint', + 'int', + 'bigint', + 'float', + 'double', + 'date', + 'datetime', + 'decimal', + 'char', + 'largeint', + 'varchar', + 'decimalv2', + 'time', + 'hll', ].map(item => ({ label: item, value: item, @@ -198,179 +198,179 @@ const redisFieldTypes = [ })); const tdsqlPgFieldTypes = [ - 'SMALLINT', - 'SMALLSERIAL', - 'INT2', - 'SERIAL2', - 'INTEGER', - 'SERIAL', - 'BIGINT', - 'BIGSERIAL', - 'REAL', - 'FLOAT4', - 'FLOAT8', - 'DOUBLE', - 'NUMERIC', - 'DECIMAL', - 'BOOLEAN', - 'DATE', - 'TIME', - 'TIMESTAMP', - 'CHAR', - 'CHARACTER', - 'VARCHAR', - 'TEXT', - 'BYTEA', + 'smallint', + 'smallserial', + 'int2', + 'serial2', + 'integer', + 'serial', + 'bigint', + 'bigserial', + 'real', + 'float4', + 'float8', + 'double', + 'numeric', + 'decimal', + 'boolean', + 'date', + 'time', + 'timestamp', + 'char', + 'character', + 'varchar', + 'text', + 'bytea', ].map(item => ({ label: item, value: item, })); const greenplumTypesConf = { - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - INT2: () => '', - SMALLSERIAL: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - SERIAL: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - SERIAL2: () => '', - INTEGER: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - BIGSERIAL: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - REAL: () => '', - FLOAT4: () => '', - FLOAT8: () => '', - DOUBLE: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - BOOLEAN: () => '', - DATE: () => '', - TIME: () => '', - TIMESTAMP: () => '', - CHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), - CHARACTER: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), - VARCHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), - TEXT: () => '', - BYTEA: () => '', + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + int2: () => '', + smallserial: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + serial: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + serial2: () => '', + integer: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + bigserial: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + real: () => '', + float4: () => '', + float8: () => '', + double: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + boolean: () => '', + date: () => '', + time: () => '', + timestamp: () => '', + char: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), + character: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), + varchar: (m, d) => (1 <= m && m <= 255 ? '' : '1 <= M <= 255'), + text: () => '', + bytea: () => '', }; const mysqlTypesConf = { - TINYINT: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), - MEDIUMINT: (m, d) => (1 <= m && m <= 9 ? '' : '1<=M<=9'), - INT: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), - FLOAT: (m, d) => + tinyint: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), + mediumint: (m, d) => (1 <= m && m <= 9 ? '' : '1<=M<=9'), + int: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), + float: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), - DOUBLE: (m, d) => + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), + double: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - NUMERIC: (m, d) => + numeric: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - DECIMAL: (m, d) => + decimal: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - BOOLEAN: () => '', - DATE: () => '', - TIME: () => '', - DATETIME: () => '', - CHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), - VARCHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), - TEXT: () => '', - BINARY: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), - VARBINARY: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), - BLOB: () => '', + boolean: () => '', + date: () => '', + time: () => '', + datetime: () => '', + char: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), + varchar: (m, d) => (1 <= m && m <= 16383 ? '' : '1<=M<=16383'), + text: () => '', + binary: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), + varbinary: (m, d) => (1 <= m && m <= 64 ? '' : '1<=M<=64'), + blob: () => '', }; const oracleTypesConf = { - BINARY_FLOAT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - BINARY_DOUBLE: (m, d) => (1 <= m && m <= 10 ? '' : '1 <= M <= 10'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - FLOAT: (m, d) => (1 <= m && m <= 126 ? '' : '1 <= M <= 126'), - FLOAT4: () => '', - FLOAT8: () => '', - DOUBLE: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - REAL: () => '', - NUMBER: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - DATE: () => '', - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - BOOLEAN: () => '', - TIMESTAMP: () => '', - CHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - VARCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - CLOB: () => '', - RAW: (m, d) => (1 <= m && m <= 2000 ? '' : ' 1 <= M <= 2000'), - BLOB: () => '', + binary_float: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + binary_double: (m, d) => (1 <= m && m <= 10 ? '' : '1 <= M <= 10'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + float: (m, d) => (1 <= m && m <= 126 ? '' : '1 <= M <= 126'), + float4: () => '', + float8: () => '', + double: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + real: () => '', + number: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + date: () => '', + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + boolean: () => '', + timestamp: () => '', + char: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + varchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + clob: () => '', + raw: (m, d) => (1 <= m && m <= 2000 ? '' : ' 1 <= M <= 2000'), + blob: () => '', }; const pgTypesConf = { - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - INT2: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - SMALLSERIAL: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - SERIAL2: () => '', - INTEGER: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - SERIAL: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - BIGSERIAL: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - REAL: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - FLOAT4: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - FLOAT8: (m, d) => (24 < m && m <= 53 ? '' : '24 < M <= 53'), - DOUBLE: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - BOOLEAN: () => '', - DATE: () => '', - TIME: () => '', - TIMESTAMP: () => '', - CHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - CHARACTER: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - VARCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - TEXT: () => '', - BYTEA: () => '', + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + int2: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + smallserial: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + serial2: () => '', + integer: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + serial: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + bigserial: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + real: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + float4: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + float8: (m, d) => (24 < m && m <= 53 ? '' : '24 < M <= 53'), + double: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + boolean: () => '', + date: () => '', + time: () => '', + timestamp: () => '', + char: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + character: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + varchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + text: () => '', + bytea: () => '', }; const sqlServerTypesConf = { - CHAR: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M <= 8000'), - VARCHAR: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M<= 8000'), - NCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - NVARCHAR: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), - TEXT: () => '', - NTEXT: () => '', - XML: () => '', - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - BIGSERIAL: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), - DECIMAL: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), - MONEY: (m, d) => (1 <= m && m <= 15 && 1 <= d && d <= 4 ? '' : '1 <= M <= 15, 1 <= D <= 4'), - SMALLMONEY: (m, d) => (1 <= m && m <= 7 && 1 <= d && d <= 4 ? '' : '1 <= M <= 7, 1 <= D <= 4'), - NUMERIC: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D <= M'), - FLOAT: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - REAL: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), - BIT: (m, d) => (1 <= m && m <= 64 ? '' : '1 <= M <= 64'), - INT: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), - TINYINT: (m, d) => (1 <= m && m <= 4 ? '' : '1 <= M <= 4'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), - TIME: () => '', - DATETIME: () => '', - DATETIME2: () => '', - SMALLDATETIME: () => '', - DATETIMEOFFSET: () => '', + char: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M <= 8000'), + varchar: (m, d) => (1 <= m && m <= 8000 ? '' : '1 <= M<= 8000'), + nchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + nvarchar: (m, d) => (1 <= m && m <= 4000 ? '' : '1 <= M <= 4000'), + text: () => '', + ntext: () => '', + xml: () => '', + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + bigserial: (m, d) => (1 <= m && m <= 20 ? '' : '1 <= M <= 20'), + decimal: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D < M'), + money: (m, d) => (1 <= m && m <= 15 && 1 <= d && d <= 4 ? '' : '1 <= M <= 15, 1 <= D <= 4'), + smallmoney: (m, d) => (1 <= m && m <= 7 && 1 <= d && d <= 4 ? '' : '1 <= M <= 7, 1 <= D <= 4'), + numeric: (m, d) => (1 <= m && m <= 38 && 0 <= d && d < m ? '' : '1 <= M <= 38, 0 <= D <= M'), + float: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + real: (m, d) => (1 <= m && m <= 24 ? '' : '1 <= M <= 24'), + bit: (m, d) => (1 <= m && m <= 64 ? '' : '1 <= M <= 64'), + int: (m, d) => (1 <= m && m <= 11 ? '' : '1 <= M <= 11'), + tinyint: (m, d) => (1 <= m && m <= 4 ? '' : '1 <= M <= 4'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1 <= M <= 6'), + time: () => '', + datetime: () => '', + datetime2: () => '', + smalldatetime: () => '', + datetimeoffset: () => '', }; const starRocksTypesConf = { - CHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), - VARCHAR: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), - DATE: () => '', - TINYINT: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), - SMALLINT: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), - INT: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), - BIGINT: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), - LARGEINT: () => '', - STRING: () => '', - DATETIME: () => '', - FLOAT: (m, d) => + char: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), + varchar: (m, d) => (1 <= m && m <= 255 ? '' : '1<=M<=255'), + date: () => '', + tinyint: (m, d) => (1 <= m && m <= 4 ? '' : '1<=M<=4'), + smallint: (m, d) => (1 <= m && m <= 6 ? '' : '1<=M<=6'), + int: (m, d) => (1 <= m && m <= 11 ? '' : '1<=M<=11'), + bigint: (m, d) => (1 <= m && m <= 20 ? '' : '1<=M<=20'), + largeint: () => '', + string: () => '', + datetime: () => '', + float: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - DOUBLE: (m, d) => + double: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - DECIMAL: (m, d) => + decimal: (m, d) => 1 <= m && m <= 255 && 1 <= d && d <= 30 && d <= m - 2 ? '' : '1<=M<=255,1<=D<=30,D<=M-2', - BOOLEAN: () => '', + boolean: () => '', }; const getFieldTypes = fieldTypesConf => { diff --git a/inlong-dashboard/src/ui/locales/cn.json b/inlong-dashboard/src/ui/locales/cn.json index bd228ed14d..4d88c28216 100644 --- a/inlong-dashboard/src/ui/locales/cn.json +++ b/inlong-dashboard/src/ui/locales/cn.json @@ -329,7 +329,7 @@ "meta.Sinks.Cls.IsMetaField": "是否为元字段", "meta.Sinks.Cls.FieldFormat": "字段格式", "meta.Group.InlongGroupId": "数据流组 ID", - "meta.Group.InlongGroupIdRules": "只能包含英文字母、数字、点号(.)、中划线(-)、下划线(_)", + "meta.Group.InlongGroupIdRules": "只能包含小写字母、数字、点号(.)、中划线(-)、下划线(_)", "meta.Group.InlongGroupName": "数据流组名称", "meta.Group.InlongGroupOwners": "责任人", "meta.Group.InlongGroupOwnersExtra": "责任人,可查看、修改数据流组信息", @@ -523,6 +523,8 @@ "components.FieldList.SinkFieldName": "目标字段", "components.FieldList.SinkFieldType": "目标类型", "components.FieldList.FieldComment": "目标字段描述", + "components.CreateTable.Table": "一键建表", + "components.CreateTable.TableType": "建表类型", "configs.pagination.Total": "共{{total}}项", "pages.GroupDashboard.ExecutionLogModal.Re-executingSuccess": "重新执行成功", "pages.GroupDashboard.ExecutionLogModal.TaskType": "任务类型", diff --git a/inlong-dashboard/src/ui/locales/en.json b/inlong-dashboard/src/ui/locales/en.json index 3b4de58092..00fbe020d0 100644 --- a/inlong-dashboard/src/ui/locales/en.json +++ b/inlong-dashboard/src/ui/locales/en.json @@ -297,7 +297,7 @@ "meta.Sinks.Redis.dataType": "Data type", "meta.Sinks.Redis.schemaMapMode": "Schema map mode", "meta.Sinks.Redis.TimeoutUnit": "s", - "meta.Sinks.Redis.SoTimeoutUnit": "s", + "meta.Sinks.Redis.SoTimeoutUnit": "s", "meta.Sinks.Redis.FormatDataType": "Format data type", "meta.Sinks.Redis.FormatIgnoreParseError": "Ignore parse error", "meta.Sinks.Redis.FormatDataEncoding": "Data encoding", diff --git a/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/DetailModal.tsx b/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/DetailModal.tsx index 872cb6564b..bf11190df4 100644 --- a/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/DetailModal.tsx +++ b/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncSink/DetailModal.tsx @@ -20,12 +20,15 @@ import React, { useMemo, useState } from 'react'; import { Button, Spin, Modal, message } from 'antd'; import { ModalProps } from 'antd/es/modal'; -import { useRequest, useUpdateEffect } from '@/ui/hooks'; +import { useRequest, useSelector, useUpdateEffect } from '@/ui/hooks'; import { useTranslation } from 'react-i18next'; import EditableTable from '@/ui/components/EditableTable'; import FormGenerator, { useForm } from '@/ui/components/FormGenerator'; import { useLoadMeta, SinkMetaType } from '@/plugins'; import request from '@/core/utils/request'; +import { State } from '@/core/stores'; +import { useLocalStorage } from '@/core/utils/localStorage'; +import { dataToMap } from '../SyncT/helper'; export interface DetailModalProps extends ModalProps { inlongGroupId: string; @@ -52,6 +55,8 @@ const Comp: React.FC<DetailModalProps> = ({ const { loading: pluginLoading, Entity } = useLoadMeta<SinkMetaType>('sink', sinkType); + const [getLocalStorage, setLocalStorage, removeLocalStorage] = useLocalStorage('createTableData'); + const { data: groupData, run: getGroupData } = useRequest(`/group/get/${inlongGroupId}`, { manual: true, ready: Boolean(inlongGroupId), @@ -83,7 +88,7 @@ const Comp: React.FC<DetailModalProps> = ({ getGroupData(); getData(id); } else { - form.setFieldsValue({ inlongGroupId, sinkType: defaultType }); + form.setFieldsValue({ inlongGroupId, inlongStreamId, sinkType: defaultType }); setSinkType(defaultType); } } else { @@ -108,6 +113,13 @@ const Comp: React.FC<DetailModalProps> = ({ const values = await form.validateFields(); const submitData = new Entity()?.stringify(values) || values; const isUpdate = Boolean(id); + const createData = getLocalStorage('createTableData'); + if (submitData?.properties !== undefined && submitData?.properties.length !== 0) { + submitData.properties = dataToMap(submitData.properties); + } else { + submitData.properties = {}; + } + if (startProcess) { submitData.startProcess = true; } @@ -115,16 +127,18 @@ const Comp: React.FC<DetailModalProps> = ({ submitData.id = id; submitData.version = data?.version; } + const sinkData = Object.assign(submitData, createData); await request({ url: isUpdate ? '/sink/update' : '/sink/save', method: 'POST', data: { - ...submitData, + ...sinkData, inlongGroupId, inlongStreamId, }, }); - modalProps?.onOk(submitData); + modalProps?.onOk(sinkData); + removeLocalStorage('createTableData'); message.success(t('basic.OperatingSuccess')); }; diff --git a/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncT/helper.ts b/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncT/helper.ts index 01e86e5bf3..a3b8769bd3 100644 --- a/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncT/helper.ts +++ b/inlong-dashboard/src/ui/pages/SynchronizeDetail/SyncT/helper.ts @@ -19,13 +19,13 @@ // Convert form data into interface submission data format export const valuesToData = (values, inlongGroupId) => { - const { inlongStreamId, predefinedFields = [], rowTypeFields = [], version, ...rest } = values; + const { inlongStreamId, predefinedField = [], rowTypeFields = [], version, ...rest } = values; - const fieldList = predefinedFields.concat(rowTypeFields).map((item, idx) => ({ + const fieldList = predefinedField.concat(rowTypeFields).map((item, idx) => ({ ...item, inlongGroupId, inlongStreamId, - isPredefinedField: idx < predefinedFields.length ? 1 : 0, + isPredefinedField: idx < predefinedField.length ? 1 : 0, })); const output = { @@ -44,11 +44,11 @@ export const valuesToData = (values, inlongGroupId) => { export const dataToValues = data => { const fieldList = data?.fieldList?.reduce( (acc, cur) => { - cur.isPredefinedField ? acc.predefinedFields.push(cur) : acc.rowTypeFields.push(cur); + cur.isPredefinedField ? acc.predefinedField.push(cur) : acc.rowTypeFields.push(cur); return acc; }, { - predefinedFields: [], + predefinedField: [], rowTypeFields: [], }, ); @@ -60,3 +60,10 @@ export const dataToValues = data => { return output; }; + +export const dataToMap = data => { + return data.reduce((amount, item) => { + amount[item.keyName] = item.keyValue; + return amount; + }, {}); +};