You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@seatunnel.apache.org by so...@apache.org on 2023/05/25 09:31:40 UTC
[seatunnel-web] branch add_canvas_job_define updated: [Feat][UI] Add datasource in this project.
This is an automated email from the ASF dual-hosted git repository.
songjian pushed a commit to branch add_canvas_job_define
in repository https://gitbox.apache.org/repos/asf/seatunnel-web.git
The following commit(s) were added to refs/heads/add_canvas_job_define by this push:
new f6fa0109 [Feat][UI] Add datasource in this project.
f6fa0109 is described below
commit f6fa0109d3983a6e8d8d24f329574758a1e419b5
Author: songjianet <17...@qq.com>
AuthorDate: Thu May 25 17:31:29 2023 +0800
[Feat][UI] Add datasource in this project.
---
seatunnel-ui/src/App.tsx | 5 +-
.../src/layouts/dashboard/header/menu/use-menu.ts | 4 +
seatunnel-ui/src/locales/en_US/datasource.ts | 88 ++++++++++
seatunnel-ui/src/locales/en_US/index.ts | 4 +-
seatunnel-ui/src/locales/en_US/menu.ts | 3 +-
seatunnel-ui/src/locales/zh_CN/datasource.ts | 84 ++++++++++
seatunnel-ui/src/locales/zh_CN/index.ts | 4 +-
seatunnel-ui/src/locales/zh_CN/menu.ts | 3 +-
.../src/router/{routes.ts => datasource.ts} | 68 ++++----
seatunnel-ui/src/router/routes.ts | 11 +-
seatunnel-ui/src/service/datasource/index.ts | 83 ++++++++++
.../zh_CN/index.ts => service/datasource/types.ts} | 46 +++---
.../{locales/zh_CN => store/datasource}/index.ts | 42 ++---
.../zh_CN/menu.ts => store/datasource/types.ts} | 20 ++-
seatunnel-ui/src/views/data-pipes/create/index.tsx | 2 +-
seatunnel-ui/src/views/data-pipes/list/index.tsx | 2 +-
.../components/json-highlight.module.scss} | 16 +-
.../views/datasource/components/json-highlight.tsx | 73 ++++++++
.../views/datasource/components/source-modal.tsx | 90 ++++++++++
.../components/source-model.module.scss} | 25 ++-
.../src/views/datasource/components/use-source.ts | 85 ++++++++++
seatunnel-ui/src/views/datasource/create/index.tsx | 184 +++++++++++++++++++++
.../src/views/datasource/create/use-detail.ts | 119 +++++++++++++
.../src/views/datasource/create/use-form.ts | 113 +++++++++++++
.../menu.ts => views/datasource/index.module.scss} | 40 ++++-
seatunnel-ui/src/views/datasource/list/index.tsx | 173 +++++++++++++++++++
.../src/views/datasource/list/use-columns.ts | 111 +++++++++++++
.../src/views/datasource/list/use-table.ts | 71 ++++++++
seatunnel-ui/src/views/user-manage/list/index.tsx | 2 +-
29 files changed, 1455 insertions(+), 116 deletions(-)
diff --git a/seatunnel-ui/src/App.tsx b/seatunnel-ui/src/App.tsx
index 0a006934..415f1ceb 100644
--- a/seatunnel-ui/src/App.tsx
+++ b/seatunnel-ui/src/App.tsx
@@ -19,6 +19,7 @@ import { defineComponent, computed, watch, ref } from 'vue'
import {
NConfigProvider,
NMessageProvider,
+ NDialogProvider,
darkTheme,
dateZhCN,
dateEnUS,
@@ -79,7 +80,9 @@ const App = defineComponent({
locale={this.settingStore.getLocales === 'zh_CN' ? zhCN : enUS}
>
<NMessageProvider>
- <router-view />
+ <NDialogProvider>
+ <router-view />
+ </NDialogProvider>
</NMessageProvider>
</NConfigProvider>
)
diff --git a/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts b/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts
index aa599ad6..ebdc7994 100644
--- a/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts
+++ b/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts
@@ -35,6 +35,10 @@ export function useMenu() {
label: () => h(NEllipsis, null, { default: () => t('menu.tasks') }),
key: 'tasks'
},
+ {
+ label: () => h(NEllipsis, null, { default: () => t('menu.datasource') }),
+ key: 'datasource'
+ },
{
label: () => h(NEllipsis, null, { default: () => t('menu.user_manage') }),
key: 'user-manage'
diff --git a/seatunnel-ui/src/locales/en_US/datasource.ts b/seatunnel-ui/src/locales/en_US/datasource.ts
new file mode 100644
index 00000000..6edf737c
--- /dev/null
+++ b/seatunnel-ui/src/locales/en_US/datasource.ts
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+export default {
+ datasource: 'DataSource',
+ create_datasource: 'Create DataSource',
+ choose_datasource_type: 'Choose DataSource Type',
+ search: 'Search',
+ search_input_tips: 'Please input the keywords',
+ select: 'Select',
+ datasource_name: 'Datasource Name',
+ datasource_name_tips: 'Please enter datasource name',
+ datasource_user_name: 'Owner',
+ datasource_type: 'Datasource Type',
+ datasource_parameter: 'Datasource Parameter',
+ description: 'Description',
+ description_tips: 'Please enter description',
+ create_time: 'Create Time',
+ update_time: 'Update Time',
+ operation: 'Operation',
+ click_to_view: 'Click to view',
+ delete: 'Delete',
+ confirm: 'Confirm',
+ cancel: 'Cancel',
+ create: 'Create',
+ edit: 'Edit',
+ edit_datasource: 'Edit DataSource',
+ success: 'Success',
+ test_connect: 'Test Connect',
+ test_connect_success: 'Test Connect Success',
+ ip: 'IP',
+ ip_tips: 'Please enter IP',
+ port: 'Port',
+ port_tips: 'Please enter port',
+ database_name: 'Database Name',
+ database_name_tips: 'Please enter database name',
+ oracle_connect_type: 'ServiceName or SID',
+ oracle_connect_type_tips: 'Please select serviceName or SID',
+ oracle_service_name: 'ServiceName',
+ oracle_sid: 'SID',
+ jdbc_connect_parameters: 'jdbc connect parameters',
+ principal_tips: 'Please enter Principal',
+ authentication_type: 'Authentication Type',
+ dm_server_authentication: 'DM Server Authentication',
+ ldap_authentication: 'LDAP Authentication',
+ operating_system_authentication: 'Operating System Authentication',
+ kerberos_authentication: 'Kerberos Authentication',
+ krb5_conf_tips:
+ 'Please enter the kerberos authentication parameter java.security.krb5.conf',
+ keytab_username_tips:
+ 'Please enter the kerberos authentication parameter login.user.keytab.username',
+ keytab_path_tips:
+ 'Please enter the kerberos authentication parameter login.user.keytab.path',
+ format_tips: 'Please enter format',
+ connection_parameter: 'connection parameter',
+ user_name: 'User Name',
+ user_name_tips: 'Please enter your username',
+ user_name_tips1: 'please enter “/”+username,for example:/username',
+ user_name_tips2: 'please enter “//”+username,for example://username',
+ user_name_tips3: 'please enter “///”+username,for example:///username',
+ user_password: 'Password',
+ user_password_tips: 'Please enter your password',
+ jdbc_format_tips: 'jdbc connection parameters is not a correct JSON format',
+ all: 'All',
+ warning: 'Warning',
+ close_confirm_tips:
+ 'This operation will lose the source currently being created',
+ database: 'Database',
+ file: 'File',
+ no_structured: 'NoSQLs',
+ storage: 'Storage',
+ data_analysis: 'Data Analysis',
+ remote_connection: 'Remote Connection'
+}
diff --git a/seatunnel-ui/src/locales/en_US/index.ts b/seatunnel-ui/src/locales/en_US/index.ts
index fefb82cb..6d57ce9d 100644
--- a/seatunnel-ui/src/locales/en_US/index.ts
+++ b/seatunnel-ui/src/locales/en_US/index.ts
@@ -24,6 +24,7 @@ import log from '@/locales/en_US/log'
import jobs from '@/locales/en_US/jobs'
import tasks from '@/locales/en_US/tasks'
import setting from '@/locales/en_US/setting'
+import datasource from '@/locales/en_US/datasource'
export default {
login,
@@ -34,5 +35,6 @@ export default {
log,
jobs,
tasks,
- setting
+ setting,
+ datasource
}
diff --git a/seatunnel-ui/src/locales/en_US/menu.ts b/seatunnel-ui/src/locales/en_US/menu.ts
index c5566870..800541f5 100644
--- a/seatunnel-ui/src/locales/en_US/menu.ts
+++ b/seatunnel-ui/src/locales/en_US/menu.ts
@@ -22,5 +22,6 @@ export default {
help: 'Help',
setting: 'Setting',
logout: 'Logout',
- tasks: 'Tasks'
+ tasks: 'Tasks',
+ datasource: 'Datasource'
}
diff --git a/seatunnel-ui/src/locales/zh_CN/datasource.ts b/seatunnel-ui/src/locales/zh_CN/datasource.ts
new file mode 100644
index 00000000..6aaf46bd
--- /dev/null
+++ b/seatunnel-ui/src/locales/zh_CN/datasource.ts
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+export default {
+ datasource: '数据源',
+ create_datasource: '创建源',
+ choose_datasource_type: '选择源类型',
+ search:'搜索',
+ search_input_tips: '请输入关键字',
+ select: '更改',
+ datasource_name: '源名称',
+ datasource_name_tips: '请输入数据源名称',
+ datasource_user_name: '所属用户',
+ datasource_type: '源类型',
+ datasource_parameter: '参数',
+ description: '描述',
+ description_tips: '请输入描述',
+ create_time: '创建时间',
+ update_time: '更新时间',
+ operation: '操作',
+ click_to_view: '点击查看',
+ delete: '删除',
+ confirm: '确定',
+ cancel: '取消',
+ create: '创建',
+ edit: '编辑',
+ edit_datasource: '编辑源',
+ success: '成功',
+ test_connect: '测试连接',
+ test_connect_success: '测试连接成功',
+ ip: 'IP主机名',
+ ip_tips: '请输入IP主机名',
+ port: '端口',
+ port_tips: '请输入端口',
+ database_name: '数据库名',
+ database_name_tips: '请输入数据库名',
+ oracle_connect_type: '服务名或SID',
+ oracle_connect_type_tips: '请选择服务名或SID',
+ oracle_service_name: '服务名',
+ oracle_sid: 'SID',
+ jdbc_connect_parameters: 'jdbc连接参数',
+ principal_tips: '请输入Principal',
+ authentication_type: '验证方式',
+ dm_server_authentication: '达梦服务器验证',
+ ldap_authentication: 'LDAP验证',
+ operating_system_authentication: '操作系统验证',
+ kerberos_authentication: 'Kerberos验证',
+ krb5_conf_tips: '请输入kerberos认证参数 java.security.krb5.conf',
+ keytab_username_tips: '请输入kerberos认证参数 login.user.keytab.username',
+ keytab_path_tips: '请输入kerberos认证参数 login.user.keytab.path',
+ format_tips: '请输入格式为',
+ connection_parameter: '连接参数',
+ user_name: '用户名',
+ user_name_tips: '请输入用户名',
+ user_name_tips1: '请输入“/”+用户名,例:/username',
+ user_name_tips2: '请输入“//”+用户名,例://username',
+ user_name_tips3: '请输入“//”+用户名,例:///username',
+ user_password: '密码',
+ user_password_tips: '请输入密码',
+ jdbc_format_tips: 'jdbc连接参数不是一个正确的JSON格式',
+ all: '所有',
+ warning: '警告',
+ close_confirm_tips: '此操作会丢失当前正在创建的源',
+ database: '传统数据库',
+ file: '文件',
+ no_structured: '非结构化',
+ storage: '存储',
+ data_analysis: '数据分析',
+ remote_connection: '远程连接'
+}
diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts b/seatunnel-ui/src/locales/zh_CN/index.ts
index 04351711..c3e11f4a 100644
--- a/seatunnel-ui/src/locales/zh_CN/index.ts
+++ b/seatunnel-ui/src/locales/zh_CN/index.ts
@@ -24,6 +24,7 @@ import log from '@/locales/zh_CN/log'
import jobs from '@/locales/zh_CN/jobs'
import tasks from '@/locales/zh_CN/tasks'
import setting from '@/locales/zh_CN/setting'
+import datasource from '@/locales/zh_CN/datasource'
export default {
login,
@@ -34,5 +35,6 @@ export default {
log,
jobs,
tasks,
- setting
+ setting,
+ datasource
}
diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts b/seatunnel-ui/src/locales/zh_CN/menu.ts
index e689b51e..5270249f 100644
--- a/seatunnel-ui/src/locales/zh_CN/menu.ts
+++ b/seatunnel-ui/src/locales/zh_CN/menu.ts
@@ -22,5 +22,6 @@ export default {
help: '帮助',
setting: '设置',
logout: '登出',
- tasks: '任务'
+ tasks: '任务',
+ datasource: '数据源'
}
diff --git a/seatunnel-ui/src/router/routes.ts b/seatunnel-ui/src/router/datasource.ts
similarity index 54%
copy from seatunnel-ui/src/router/routes.ts
copy to seatunnel-ui/src/router/datasource.ts
index 19fdd67e..9a8de1cc 100644
--- a/seatunnel-ui/src/router/routes.ts
+++ b/seatunnel-ui/src/router/datasource.ts
@@ -16,45 +16,43 @@
*/
import utils from '@/utils'
-import dataPipes from '@/router/data-pipes'
-import jobs from '@/router/jobs'
-import tasks from '@/router/tasks'
-import userManage from '@/router/user-manage'
-import type { RouteRecordRaw } from 'vue-router'
import type { Component } from 'vue'
const modules = import.meta.glob('/src/views/**/**.tsx')
const components: { [key: string]: Component } = utils.mapping(modules)
-const basePage: RouteRecordRaw[] = [{
- path: '/',
- redirect: { name: 'login' }
+export default {
+ path: '/datasource',
+ name: 'datasource',
+ meta: {
+ title: 'datasource'
},
- dataPipes, jobs, tasks, userManage]
-
-const loginPage: RouteRecordRaw[] = [
- {
- path: '/login',
- name: 'login',
- component: components['login']
- },
- {
- path: '/setting',
- redirect: { name: 'setting' },
- component: () => import('@/layouts/dashboard'),
- children: [
- {
- path: '/setting',
- name: 'setting',
- component: components['setting'],
- meta: {
- title: 'setting'
- }
+ redirect: { name: 'datasource-list' },
+ component: () => import('@/layouts/dashboard'),
+ children: [
+ {
+ path: '/datasource/list',
+ name: 'datasource-list',
+ component: components['datasource-list'],
+ meta: {
+ title: 'datasource-list'
}
- ]
- }
-]
-
-const routes: RouteRecordRaw[] = [...basePage, ...loginPage]
-
-export default routes
+ },
+ {
+ path: '/datasource/create',
+ name: 'datasource-create',
+ component: components['datasource-create'],
+ meta: {
+ title: 'datasource-create'
+ }
+ },
+ {
+ path: '/datasource/:id',
+ name: 'datasource-edit',
+ component: components['datasource-create'],
+ meta: {
+ title: 'datasource-edit'
+ }
+ }
+ ]
+}
diff --git a/seatunnel-ui/src/router/routes.ts b/seatunnel-ui/src/router/routes.ts
index 19fdd67e..15d9eeff 100644
--- a/seatunnel-ui/src/router/routes.ts
+++ b/seatunnel-ui/src/router/routes.ts
@@ -20,17 +20,24 @@ import dataPipes from '@/router/data-pipes'
import jobs from '@/router/jobs'
import tasks from '@/router/tasks'
import userManage from '@/router/user-manage'
+import datasource from '@/router/datasource'
import type { RouteRecordRaw } from 'vue-router'
import type { Component } from 'vue'
const modules = import.meta.glob('/src/views/**/**.tsx')
const components: { [key: string]: Component } = utils.mapping(modules)
-const basePage: RouteRecordRaw[] = [{
+const basePage: RouteRecordRaw[] = [
+ {
path: '/',
redirect: { name: 'login' }
},
- dataPipes, jobs, tasks, userManage]
+ dataPipes,
+ jobs,
+ tasks,
+ userManage,
+ datasource
+]
const loginPage: RouteRecordRaw[] = [
{
diff --git a/seatunnel-ui/src/service/datasource/index.ts b/seatunnel-ui/src/service/datasource/index.ts
new file mode 100644
index 00000000..0982eba0
--- /dev/null
+++ b/seatunnel-ui/src/service/datasource/index.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 { axios } from '@/service/service'
+
+export function datasourceList(params: any): any {
+ return axios({
+ url: '/datasource/list',
+ method: 'get',
+ params
+ })
+}
+
+export function datasourceDelete(id: string): any {
+ return axios({
+ url: '/datasource/' + id,
+ method: 'delete'
+ })
+}
+
+export function datasourceTypeList(params: {
+ showVirtualDataSource: boolean
+ source?: 'WS' | 'WT'
+}): any {
+ return axios({
+ url: '/datasource/support-datasources',
+ method: 'get',
+ params
+ })
+}
+
+export function datasourceDetail(id: string): any {
+ return axios({
+ url: '/datasource/' + id,
+ method: 'get'
+ })
+}
+
+export function datasourceAdd(data: any): any {
+ return axios({
+ url: '/datasource/create',
+ method: 'post',
+ data
+ })
+}
+
+export function datasourceUpdate(data: any, id: string): any {
+ return axios({
+ url: '/datasource/' + id,
+ method: 'put',
+ data
+ })
+}
+
+export function checkConnect(data: any): any {
+ return axios({
+ url: '/datasource/check/connect',
+ method: 'post',
+ data
+ })
+}
+
+export function dynamicFormItems(pluginName: string): any {
+ return axios({
+ url: '/datasource/dynamic-form',
+ method: 'get',
+ params: { pluginName }
+ })
+}
diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts b/seatunnel-ui/src/service/datasource/types.ts
similarity index 60%
copy from seatunnel-ui/src/locales/zh_CN/index.ts
copy to seatunnel-ui/src/service/datasource/types.ts
index 04351711..a3af0f25 100644
--- a/seatunnel-ui/src/locales/zh_CN/index.ts
+++ b/seatunnel-ui/src/service/datasource/types.ts
@@ -15,24 +15,32 @@
* limitations under the License.
*/
-import login from '@/locales/zh_CN/login'
-import menu from '@/locales/zh_CN/menu'
-import modal from '@/locales/zh_CN/modal'
-import user_manage from '@/locales/zh_CN/user-manage'
-import data_pipes from '@/locales/zh_CN/data-pipes'
-import log from '@/locales/zh_CN/log'
-import jobs from '@/locales/zh_CN/jobs'
-import tasks from '@/locales/zh_CN/tasks'
-import setting from '@/locales/zh_CN/setting'
+interface DatasourceConfig {}
-export default {
- login,
- menu,
- modal,
- user_manage,
- data_pipes,
- log,
- jobs,
- tasks,
- setting
+interface DatasourceList {
+ createUserName: string
+ createTime: string
+ updateUserName: string
+ updateTime: string
+ id: string
+ datasourceName: string
+ pluginName: string
+ pluginVersion: string
+ description: string
+ datasourceConfig: DatasourceConfig
+ createUserId: number
+ updateUserId: number
+}
+
+interface DatasourceTypeList {
+ name: string
+ icon: string
+ version: string
+ type: number
+ supportVirtualTables: boolean
+}
+
+export {
+ DatasourceList,
+ DatasourceTypeList
}
diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts b/seatunnel-ui/src/store/datasource/index.ts
similarity index 59%
copy from seatunnel-ui/src/locales/zh_CN/index.ts
copy to seatunnel-ui/src/store/datasource/index.ts
index 04351711..70bd5a27 100644
--- a/seatunnel-ui/src/locales/zh_CN/index.ts
+++ b/seatunnel-ui/src/store/datasource/index.ts
@@ -15,24 +15,26 @@
* limitations under the License.
*/
-import login from '@/locales/zh_CN/login'
-import menu from '@/locales/zh_CN/menu'
-import modal from '@/locales/zh_CN/modal'
-import user_manage from '@/locales/zh_CN/user-manage'
-import data_pipes from '@/locales/zh_CN/data-pipes'
-import log from '@/locales/zh_CN/log'
-import jobs from '@/locales/zh_CN/jobs'
-import tasks from '@/locales/zh_CN/tasks'
-import setting from '@/locales/zh_CN/setting'
+import { defineStore } from 'pinia'
+import { FormStructuresStore, StructureItem } from './types'
+export type { StructureItem }
-export default {
- login,
- menu,
- modal,
- user_manage,
- data_pipes,
- log,
- jobs,
- tasks,
- setting
-}
+export const useFormStructuresStore = defineStore({
+ id: 'form-structures',
+ state: (): FormStructuresStore => ({
+ items: new Map()
+ }),
+ persist: {
+ storage: sessionStorage
+ },
+ getters: {
+ getItem(state) {
+ return (key: string): StructureItem[] | undefined => state.items.get(key)
+ }
+ },
+ actions: {
+ setItem(key: string, item: StructureItem[]): void {
+ this.items.set(key, item)
+ }
+ }
+})
diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts b/seatunnel-ui/src/store/datasource/types.ts
similarity index 74%
copy from seatunnel-ui/src/locales/zh_CN/menu.ts
copy to seatunnel-ui/src/store/datasource/types.ts
index e689b51e..5709e275 100644
--- a/seatunnel-ui/src/locales/zh_CN/menu.ts
+++ b/seatunnel-ui/src/store/datasource/types.ts
@@ -15,12 +15,16 @@
* limitations under the License.
*/
-export default {
- data_pipes: '数据管道',
- jobs: '工作',
- user_manage: '用户管理',
- help: '帮助',
- setting: '设置',
- logout: '登出',
- tasks: '任务'
+interface SourceType {}
+
+interface DatasourceTypeStore {
+ types: SourceType[]
}
+
+type StructureItem = { [key: string]: any }
+
+interface FormStructuresStore {
+ items: Map<string, StructureItem[]>
+}
+
+export { DatasourceTypeStore, SourceType, FormStructuresStore, StructureItem }
diff --git a/seatunnel-ui/src/views/data-pipes/create/index.tsx b/seatunnel-ui/src/views/data-pipes/create/index.tsx
index 2699f08a..98ce5b12 100644
--- a/seatunnel-ui/src/views/data-pipes/create/index.tsx
+++ b/seatunnel-ui/src/views/data-pipes/create/index.tsx
@@ -82,7 +82,7 @@ const DataPipesCreate = defineComponent({
<NButton secondary onClick={this.handleClickDataPipes}>
{this.t('data_pipes.cancel')}
</NButton>
- <NButton secondary type='primary' onClick={this.handleAdd}>
+ <NButton secondary type='success' onClick={this.handleAdd}>
{this.t('data_pipes.save')}
</NButton>
</NSpace>
diff --git a/seatunnel-ui/src/views/data-pipes/list/index.tsx b/seatunnel-ui/src/views/data-pipes/list/index.tsx
index 53775995..81e68fa7 100644
--- a/seatunnel-ui/src/views/data-pipes/list/index.tsx
+++ b/seatunnel-ui/src/views/data-pipes/list/index.tsx
@@ -83,7 +83,7 @@ const DataPipesList = defineComponent({
<NCard title={this.t('data_pipes.data_pipes')}>
{{
'header-extra': () => (
- <NButton onClick={this.handleCreate} type='primary'>
+ <NButton onClick={this.handleCreate} type='success'>
{this.t('data_pipes.create')}
</NButton>
)
diff --git a/seatunnel-ui/src/locales/en_US/menu.ts b/seatunnel-ui/src/views/datasource/components/json-highlight.module.scss
similarity index 82%
copy from seatunnel-ui/src/locales/en_US/menu.ts
copy to seatunnel-ui/src/views/datasource/components/json-highlight.module.scss
index c5566870..a6f09f0f 100644
--- a/seatunnel-ui/src/locales/en_US/menu.ts
+++ b/seatunnel-ui/src/views/datasource/components/json-highlight.module.scss
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-export default {
- data_pipes: 'Data Pipes',
- jobs: 'Jobs',
- user_manage: 'User Manage',
- help: 'Help',
- setting: 'Setting',
- logout: 'Logout',
- tasks: 'Tasks'
+.json-highlight {
+ display: block;
+ line-height: 1.5;
+ font-size: 12px;
+ padding: 5px;
+}
+.line {
+ padding-left: 8px;
}
diff --git a/seatunnel-ui/src/views/datasource/components/json-highlight.tsx b/seatunnel-ui/src/views/datasource/components/json-highlight.tsx
new file mode 100644
index 00000000..873c4b84
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/components/json-highlight.tsx
@@ -0,0 +1,73 @@
+/*
+ * 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 { defineComponent, PropType } from 'vue'
+import { NText } from 'naive-ui'
+import { isBoolean, isNumber, isPlainObject } from 'lodash'
+import styles from './json-highlight.module.scss'
+
+const props = {
+ params: {
+ type: String as PropType<string>,
+ default: ''
+ }
+}
+
+const JsonHighlight = defineComponent({
+ name: 'JsonHighlight',
+ props,
+ render(props: { params: string }) {
+ return (
+ <pre class={styles['json-highlight']}>
+ {syntaxHighlight(props.params)}
+ </pre>
+ )
+ }
+})
+
+const syntaxHighlight = (json: string) => {
+ if (!isPlainObject(JSON.parse(json))) return ''
+ const lines = [<NText v-html={'{'}></NText>]
+ const entries = Object.entries(JSON.parse(json))
+ for (let i = 0, len = entries.length; i < len; i++) {
+ const [key, value] = entries[i]
+ let type = ''
+ if (isBoolean(value) || value === null) {
+ type = 'info'
+ } else if (isNumber(value)) {
+ type = 'warning'
+ } else {
+ type = 'success'
+ }
+ lines.push(
+ <NText tag='div' class={styles['line']}>
+ <NText type='error'>"{key}": </NText>
+ {isPlainObject(value) ? (
+ syntaxHighlight(JSON.stringify(value))
+ ) : (
+ <NText type={type}>
+ "{value}"{i !== len - 1 ? ',' : ''}
+ </NText>
+ )}
+ </NText>
+ )
+ }
+ lines.push(<NText v-html='}'></NText>)
+ return lines
+}
+
+export default JsonHighlight
diff --git a/seatunnel-ui/src/views/datasource/components/source-modal.tsx b/seatunnel-ui/src/views/datasource/components/source-modal.tsx
new file mode 100644
index 00000000..c0244524
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/components/source-modal.tsx
@@ -0,0 +1,90 @@
+/*
+ * 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 { defineComponent, PropType } from 'vue'
+import {
+ NSpace,
+ NModal,
+ NCard,
+ NButton,
+ NTabs,
+ NTabPane,
+ NEmpty
+} from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import { useSource } from './use-source'
+import styles from './source-model.module.scss'
+import type { SelectOption } from 'naive-ui'
+
+const props = {
+ show: {
+ type: Boolean as PropType<boolean>,
+ default: false
+ },
+ id: {
+ type: Number as PropType<number>
+ }
+}
+
+const SourceModal = defineComponent({
+ name: 'SourceModal',
+ props,
+ emits: ['change', 'cancel'],
+ setup(props, ctx) {
+ const { t } = useI18n()
+ const { state } = useSource(false)
+ const handleTypeSelect = (type: string) => {
+ ctx.emit('change', type)
+ }
+ const onCancel = () => {
+ ctx.emit('cancel')
+ }
+
+ return () => (
+ <NModal show={props.show} onMaskClick={onCancel} onEsc={onCancel}>
+ <NCard
+ class={styles.content}
+ title={t('datasource.choose_datasource_type')}
+ >
+ <NTabs>
+ {state.types.map((item) => (
+ <NTabPane name={item.key} tab={item.label} key={item.key}>
+ <div class={styles['types']}>
+ {item?.children.map((slip: SelectOption) => (
+ <div
+ class={styles.itemBox}
+ onClick={() => handleTypeSelect(slip.label as string)}
+ >
+ <div class='font-bold'>{slip.label}</div>
+ <div class='text-xs mt-1.5'>{item.label}</div>
+ </div>
+ ))}
+ </div>
+ {item.children.length === 0 && <NEmpty />}
+ </NTabPane>
+ ))}
+ </NTabs>
+ <NSpace justify='end'>
+ <NButton onClick={onCancel}>{t('datasource.cancel')}</NButton>
+ </NSpace>
+ </NCard>
+ </NModal>
+ )
+ }
+})
+
+export default SourceModal
diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts b/seatunnel-ui/src/views/datasource/components/source-model.module.scss
similarity index 74%
copy from seatunnel-ui/src/locales/zh_CN/menu.ts
copy to seatunnel-ui/src/views/datasource/components/source-model.module.scss
index e689b51e..037d8fb9 100644
--- a/seatunnel-ui/src/locales/zh_CN/menu.ts
+++ b/seatunnel-ui/src/views/datasource/components/source-model.module.scss
@@ -15,12 +15,21 @@
* limitations under the License.
*/
-export default {
- data_pipes: '数据管道',
- jobs: '工作',
- user_manage: '用户管理',
- help: '帮助',
- setting: '设置',
- logout: '登出',
- tasks: '任务'
+.content {
+ width: 800px;
+
+ .types {
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ .itemBox {
+ margin: 10px;
+ border-radius: 10px;
+ width: 110px;
+ padding: 30px 10px;
+ text-align: center;
+ cursor: pointer;
+ box-shadow: 0 0 6px 1px rgba(0, 0, 0, 0.1);
+ }
}
diff --git a/seatunnel-ui/src/views/datasource/components/use-source.ts b/seatunnel-ui/src/views/datasource/components/use-source.ts
new file mode 100644
index 00000000..8f85064b
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/components/use-source.ts
@@ -0,0 +1,85 @@
+/*
+ * 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 { onMounted, reactive, watch } from 'vue'
+import { datasourceTypeList } from '@/service/datasource'
+import { useI18n } from 'vue-i18n'
+import type { SelectOption } from 'naive-ui'
+import type { ResponseBasic } from '@/service/types'
+import type { DatasourceTypeList } from '@/service/datasource/types'
+
+type Key = '1' | '2' | '3' | '4' | '5'
+type IType = {
+ type: string
+ label: string
+ key: string
+ children: SelectOption[]
+}
+
+export const useSource = (showVirtualDataSource = false) => {
+ const i18n = useI18n()
+ const TYPE_MAP = {
+ 1: 'database',
+ 2: 'file',
+ 3: 'no_structured',
+ 4: 'storage',
+ 5: 'remote_connection'
+ }
+ const state = reactive({
+ types: [] as IType[]
+ })
+
+ const querySource = () => {
+ datasourceTypeList({
+ showVirtualDataSource,
+ source: 'WT'
+ }).then((res: ResponseBasic<Array<DatasourceTypeList> | Array<any>>) => {
+ const locales = {
+ zh_CN: {} as { [key: string]: string },
+ en_US: {} as { [key: string]: string }
+ }
+
+ state.types = Object.entries(res.data).map(([key, value]) => {
+ return {
+ type: 'group',
+ label: i18n.t(`datasource.${TYPE_MAP[key as Key]}`),
+ key: TYPE_MAP[key as Key],
+ children: (value as any).map((item: any) => {
+ locales.zh_CN[item.name] = item.chineseName
+ locales.en_US[item.name] = item.name
+ return {
+ label: item.name,
+ value: item.name
+ }
+ })
+ }
+ })
+
+ i18n.mergeLocaleMessage('zh_CN', locales.zh_CN)
+ i18n.mergeLocaleMessage('en_US', locales.en_US)
+ })
+ }
+
+ onMounted(() => {
+ querySource()
+ })
+
+ watch(useI18n().locale, () => {
+ querySource()
+ })
+
+ return { state }
+}
diff --git a/seatunnel-ui/src/views/datasource/create/index.tsx b/seatunnel-ui/src/views/datasource/create/index.tsx
new file mode 100644
index 00000000..5f932126
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/create/index.tsx
@@ -0,0 +1,184 @@
+/*
+ * 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 { defineComponent, ref } from 'vue'
+import {
+ NSpace,
+ NBreadcrumb,
+ NBreadcrumbItem,
+ NForm,
+ useDialog,
+ NInput,
+ NButton,
+ NFormItemGi,
+ NGrid,
+ NDivider,
+ NCard
+} from 'naive-ui'
+import { DynamicFormItem } from '@/components/dynamic-form/dynamic-form-item'
+import { useRoute, useRouter } from 'vue-router'
+import { useI18n } from 'vue-i18n'
+import { useDetail } from './use-detail'
+import { useForm } from './use-form'
+import styles from '../index.module.scss'
+import SourceModal from '../components/source-modal'
+
+const DatasourceCreate = defineComponent({
+ setup() {
+ const { t } = useI18n()
+ const route = useRoute()
+ const router = useRouter()
+ const dialog = useDialog()
+ const showSourceModal = ref(false)
+ const detailFormRef = ref(null)
+
+ const { state, changeType, getFieldsValue, setFieldsValue, getFormItems } =
+ useForm(route.query.type as string)
+
+ const { status, testConnect, createOrUpdate } = useDetail(
+ getFieldsValue,
+ setFieldsValue,
+ getFormItems,
+ detailFormRef,
+ route.params.id as string
+ )
+
+ const onClose = () => {
+ dialog.warning({
+ title: t('datasource.warning'),
+ content: t('datasource.close_confirm_tips'),
+ onPositiveClick: () => {
+ router.push({
+ name: 'datasource-list'
+ })
+ },
+ positiveText: t('datasource.confirm'),
+ negativeText: t('datasource.cancel')
+ })
+ }
+
+ return () => (
+ <NSpace vertical>
+ <NCard>
+ {{
+ header: () => <NBreadcrumb>
+ <NBreadcrumbItem onClick={onClose}>
+ {t('datasource.datasource')}
+ </NBreadcrumbItem>
+ <NBreadcrumbItem>
+ {t(
+ route.params.id
+ ? 'datasource.edit_datasource'
+ : 'datasource.create_datasource'
+ )}
+ </NBreadcrumbItem>
+ </NBreadcrumb>,
+ 'header-extra': () => <NSpace>
+ <NButton secondary type='primary' onClick={testConnect} loading={status.testing}>
+ {t('datasource.test_connect')}
+ </NButton>
+ <NButton secondary onClick={onClose}>
+ {t('datasource.cancel')}
+ </NButton>
+ <NButton type='success' onClick={createOrUpdate} loading={status.saving}>
+ {t('datasource.confirm')}
+ </NButton>
+ </NSpace>
+ }}
+ </NCard>
+ <NCard>
+ <NForm
+ rules={state.rules}
+ ref={detailFormRef}
+ class={styles['detail-content']}
+ >
+ <NGrid xGap={10}>
+ <NFormItemGi
+ label={t('datasource.datasource_type')}
+ path='type'
+ show-require-mark
+ span={24}
+ >
+ <NSpace
+ class={[
+ styles.typeBox,
+ !!route.params.id && styles.disabledBox
+ ]}
+ >
+ <div>{state.detailForm.pluginName}</div>
+ {!route.params.id && (
+ <NButton
+ text
+ type='primary'
+ onClick={() => void (showSourceModal.value = true)}
+ >
+ {t('datasource.select')}
+ </NButton>
+ )}
+ </NSpace>
+ </NFormItemGi>
+ <NFormItemGi
+ label={t('datasource.datasource_name')}
+ path='name'
+ show-require-mark
+ span={12}
+ >
+ <NInput
+ class='input-data-source-name'
+ v-model={[state.detailForm.datasourceName, 'value']}
+ maxlength={60}
+ placeholder={t('datasource.datasource_name_tips')}
+ />
+ </NFormItemGi>
+ <NFormItemGi
+ label={t('datasource.description')}
+ path='note'
+ span={12}
+ >
+ <NInput
+ class='input-data-source-description'
+ v-model={[state.detailForm.description, 'value']}
+ type='textarea'
+ placeholder={t('datasource.description_tips')}
+ rows={1}
+ />
+ </NFormItemGi>
+ </NGrid>
+ <NDivider style={{ marginTop: '0px' }} />
+ {state.formStructure.length > 0 && (
+ <DynamicFormItem
+ model={state.detailForm}
+ formStructure={state.formStructure}
+ name={state.formName}
+ locales={state.locales}
+ />
+ )}
+ </NForm>
+ </NCard>
+ <SourceModal
+ show={showSourceModal.value}
+ onChange={(type) => {
+ changeType(type)
+ showSourceModal.value = false
+ }}
+ onCancel={() => void (showSourceModal.value = false)}
+ />
+ </NSpace>
+ )
+ }
+})
+
+export default DatasourceCreate
diff --git a/seatunnel-ui/src/views/datasource/create/use-detail.ts b/seatunnel-ui/src/views/datasource/create/use-detail.ts
new file mode 100644
index 00000000..f18c1e0d
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/create/use-detail.ts
@@ -0,0 +1,119 @@
+/*
+ * 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 { onMounted, reactive, Ref } from 'vue'
+import {
+ datasourceDetail,
+ datasourceAdd,
+ datasourceUpdate,
+ checkConnect
+} from '@/service/datasource'
+import { useI18n } from 'vue-i18n'
+import { omit } from 'lodash'
+import { useRouter } from 'vue-router'
+
+export function useDetail(
+ getFieldsValue: Function,
+ setFieldsValue: Function,
+ getFormItems: Function,
+ detailFormRef: Ref,
+ id: string
+) {
+ const { t } = useI18n()
+ const router = useRouter()
+ const status = reactive({
+ saving: false,
+ testing: false,
+ loading: false
+ })
+
+ const formatParams = () => {
+ const values = getFieldsValue()
+ return {
+ datasourceName: values.datasourceName,
+ pluginName: values.pluginName,
+ description: values.description,
+ datasourceConfig: JSON.stringify(
+ omit(values, ['pluginName', 'datasourceName', 'description'])
+ )
+ }
+ }
+
+ const queryById = async () => {
+ try {
+ const result = await datasourceDetail(id)
+ await getFormItems(result.data.pluginName)
+ setFieldsValue({
+ datasourceName: result.data.datasourceName,
+ pluginName: result.data.pluginName,
+ description: result.data.description,
+ ...result.data.datasourceConfig
+ })
+ } finally {}
+ }
+
+ const testConnect = async () => {
+ await detailFormRef.value.validate()
+ if (status.testing) return
+ status.testing = true
+ const values = getFieldsValue()
+ try {
+ const result = await checkConnect({
+ pluginName: values.pluginName,
+ datasourceConfig: omit(values, ['pluginName', 'datasourceName', 'description'])
+ })
+ window.$message.success(
+ result.msg ? result.msg : `${t('datasource.test_connect_success')}`
+ )
+
+ status.testing = false
+ } catch (err) {
+ status.testing = false
+ }
+ }
+
+ const createOrUpdate = async () => {
+ await detailFormRef.value.validate()
+
+ if (status.saving) return false
+ status.saving = true
+
+ try {
+ id
+ ? await datasourceUpdate(formatParams(), id)
+ : await datasourceAdd(formatParams())
+
+ status.saving = false
+ router.push({
+ name: 'datasource-list',
+ query: {}
+ })
+ return true
+ } catch (err) {
+ status.saving = false
+ return false
+ }
+ }
+
+ onMounted(() => {
+ if (id) {
+ queryById()
+ }
+ })
+
+ return { status, testConnect, createOrUpdate }
+}
diff --git a/seatunnel-ui/src/views/datasource/create/use-form.ts b/seatunnel-ui/src/views/datasource/create/use-form.ts
new file mode 100644
index 00000000..5597800e
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/create/use-form.ts
@@ -0,0 +1,113 @@
+/*
+ * 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 { onMounted, reactive } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { useRouter } from 'vue-router'
+import {
+ useFormStructuresStore,
+ StructureItem
+} from '@/store/datasource'
+import { dynamicFormItems } from '@/service/datasource'
+import { useFormField } from '@/components/dynamic-form/use-form-field'
+import { useFormRequest } from '@/components/dynamic-form/use-form-request'
+import { useFormValidate } from '@/components/dynamic-form/use-form-validate'
+import { useFormStructure } from '@/components/dynamic-form/use-form-structure'
+import type { FormRules } from 'naive-ui'
+import type { ResponseBasic } from '@/service/types'
+
+export function useForm(type: string) {
+ const { t } = useI18n()
+ const router = useRouter()
+ const formStructuresStore = useFormStructuresStore()
+
+ const initialValues = {
+ pluginName: type,
+ datasourceName: '',
+ description: ''
+ }
+
+ const state = reactive({
+ detailForm: { ...initialValues },
+ formName: '',
+ formStructure: [] as StructureItem[],
+ locales: {},
+ rules: {
+ name: {
+ trigger: ['input'],
+ validator() {
+ if (!state.detailForm.datasourceName) {
+ return new Error(t('datasource.datasource_name_tips'))
+ }
+ }
+ }
+ } as FormRules
+ })
+
+ const getFormItems = async (value: string) => {
+ if (formStructuresStore.getItem(value)) {
+ state.formStructure = formStructuresStore.getItem(value) as StructureItem[]
+ return
+ }
+
+ const result: ResponseBasic<string> = await dynamicFormItems(value)
+
+ try {
+ const res = JSON.parse(result.data)
+ res.forms = res.forms.map((form: any) => ({ ...form, span: 12 }))
+ Object.assign(state.detailForm, useFormField(res.forms))
+ Object.assign(
+ state.rules,
+ useFormValidate(res.forms, state.detailForm, t)
+ )
+ state.locales = res.locales
+ state.formStructure = useFormStructure(
+ res.apis ? useFormRequest(res.apis, res.forms) : res.forms
+ ) as any
+ } finally {}
+ }
+
+ const changeType = (value: string) => {
+ router.replace({ name: 'datasource-create', query: { type: value } })
+ getFormItems(value)
+ }
+
+ const resetFieldsValue = () => {
+ state.detailForm = { ...initialValues }
+ }
+
+ const setFieldsValue = (values: any) => {
+ Object.assign(state.detailForm, values)
+ }
+
+ const getFieldsValue = () => state.detailForm
+
+ onMounted(() => {
+ if (type) {
+ getFormItems(type)
+ }
+ })
+
+ return {
+ state,
+ changeType,
+ resetFieldsValue,
+ getFieldsValue,
+ setFieldsValue,
+ getFormItems
+ }
+}
diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts b/seatunnel-ui/src/views/datasource/index.module.scss
similarity index 67%
copy from seatunnel-ui/src/locales/zh_CN/menu.ts
copy to seatunnel-ui/src/views/datasource/index.module.scss
index e689b51e..002c30f0 100644
--- a/seatunnel-ui/src/locales/zh_CN/menu.ts
+++ b/seatunnel-ui/src/views/datasource/index.module.scss
@@ -15,12 +15,36 @@
* limitations under the License.
*/
-export default {
- data_pipes: '数据管道',
- jobs: '工作',
- user_manage: '用户管理',
- help: '帮助',
- setting: '设置',
- logout: '登出',
- tasks: '任务'
+.conditions {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.pagination {
+ margin-top: 20px;
+ justify-content: center;
+}
+
+.mt-8 {
+ margin-top: 8px;
+}
+
+.typeBox {
+ display: flex;
+ padding: 5px 14px;
+
+ .text-color {
+ color: #1890ff;
+ cursor: pointer;
+ }
+}
+
+.disabledBox {
+ pointer-events: none;
+ opacity: 0.5;
+}
+
+.detail-content {
+ padding-top: 20px;
}
diff --git a/seatunnel-ui/src/views/datasource/list/index.tsx b/seatunnel-ui/src/views/datasource/list/index.tsx
new file mode 100644
index 00000000..70232dd3
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/list/index.tsx
@@ -0,0 +1,173 @@
+/*
+ * 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 { defineComponent, onMounted, ref, toRefs, watch } from 'vue'
+import {
+ NButton,
+ NInput,
+ NIcon,
+ NDataTable,
+ NPagination,
+ NSpace,
+ NCard
+} from 'naive-ui'
+import { SearchOutlined, ReloadOutlined } from '@vicons/antd'
+import { useRouter, useRoute } from 'vue-router'
+import { useI18n } from 'vue-i18n'
+import { useColumns } from './use-columns'
+import { useTable } from './use-table'
+import styles from '../index.module.scss'
+import SourceModal from '../components/source-modal'
+import type { Ref } from 'vue'
+import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
+
+const DatasourceList = defineComponent({
+ setup: function() {
+ const { t } = useI18n()
+ const showSourceModal = ref(false)
+ const columns: Ref<TableColumns> = ref([])
+ const router = useRouter()
+ const route = useRoute()
+ const { data, changePage, changePageSize, deleteRecord, updateList } =
+ useTable()
+
+ const handleSearch = () => {
+ updateList()
+ }
+
+ const { getColumns } = useColumns((id: string, type: 'edit' | 'delete') => {
+ if (type === 'edit') {
+ router.push({ name: 'datasource-edit', params: { id } })
+ } else {
+ deleteRecord(id)
+ }
+ })
+
+ const onCreate = () => {
+ showSourceModal.value = true
+ }
+
+ const closeSourceModal = () => {
+ showSourceModal.value = false
+ }
+
+ const handleSelectSourceType = (value: string) => {
+ router.push({ name: 'datasource-create', query: { type: value } })
+ closeSourceModal()
+ }
+
+ const initSearch = () => {
+ const { searchVal } = route.query
+ if (searchVal) {
+ data.searchVal = searchVal as string
+ }
+ }
+
+ onMounted(() => {
+ initSearch()
+ if (!route.query.tab || route.query.tab === 'datasource') {
+ changePage(1)
+ columns.value = getColumns()
+ }
+ })
+
+ watch(useI18n().locale, () => {
+ columns.value = getColumns()
+ })
+
+ return {
+ t,
+ showSourceModal,
+ columns,
+ ...toRefs(data),
+ changePage,
+ changePageSize,
+ onCreate,
+ handleSearch,
+ handleSelectSourceType,
+ closeSourceModal
+ }
+ },
+ render() {
+ const {
+ t,
+ showSourceModal,
+ columns,
+ list,
+ page,
+ pageSize,
+ itemCount,
+ changePage,
+ changePageSize,
+ onCreate,
+ handleSelectSourceType,
+ closeSourceModal
+ } = this
+
+ return (
+ <NSpace vertical>
+ <NCard title={t('datasource.datasource')}>
+ {{
+ 'header-extra': () => (
+ <NSpace>
+ <NInput
+ v-model={[this.searchVal, 'value']}
+ placeholder={t('datasource.search_input_tips')}
+ style={{ width: '200px' }}
+ />
+ <NButton onClick={this.handleSearch} type='primary'>
+ {this.t('datasource.search')}
+ </NButton>
+ <NButton
+ onClick={onCreate}
+ type='success'
+ >
+ {t('datasource.create')}
+ </NButton>
+ </NSpace>
+ )
+ }}
+ </NCard>
+ <NCard title='' class={styles['mt-8']}>
+ <NDataTable
+ row-class-name='data-source-items'
+ columns={columns}
+ data={list}
+ striped
+ />
+ <NPagination
+ page={page}
+ page-size={pageSize}
+ item-count={itemCount}
+ show-quick-jumper
+ show-size-picker
+ page-sizes={[10, 30, 50]}
+ class={styles['pagination']}
+ on-update:page={changePage}
+ on-update:page-size={changePageSize}
+ />
+ </NCard>
+ <SourceModal
+ show={showSourceModal}
+ onChange={handleSelectSourceType}
+ onCancel={closeSourceModal}
+ />
+ </NSpace>
+ )
+ }
+})
+export default DatasourceList
diff --git a/seatunnel-ui/src/views/datasource/list/use-columns.ts b/seatunnel-ui/src/views/datasource/list/use-columns.ts
new file mode 100644
index 00000000..a46df1c4
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/list/use-columns.ts
@@ -0,0 +1,111 @@
+/*
+ * 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 { h } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { NPopover, NButton, NSpace } from 'naive-ui'
+import JsonHighlight from '../components/json-highlight'
+
+export function useColumns(onCallback: Function) {
+ const { t } = useI18n()
+ const getColumns = () => {
+ return [
+ {
+ title: t('datasource.datasource_name'),
+ key: 'datasourceName'
+ },
+ {
+ title: t('datasource.datasource_user_name'),
+ key: 'createUserName'
+ },
+ {
+ title: t('datasource.datasource_type'),
+ key: 'pluginName',
+ width: 180
+ },
+ {
+ title: t('datasource.datasource_parameter'),
+ key: 'parameter',
+ width: 180,
+ render: (row: any) => {
+ return row.datasourceConfig
+ ? h(
+ NPopover,
+ { trigger: 'click' },
+ {
+ trigger: () =>
+ h(NButton, { text: true }, {
+ default: () => t('datasource.click_to_view')
+ }),
+ default: () =>
+ h(JsonHighlight, {
+ params: JSON.stringify(
+ row.datasourceConfig
+ ) as string
+ })
+ }
+ )
+ : '--'
+ }
+ },
+ {
+ title: t('datasource.description'),
+ key: 'description',
+ render: (row: any) => row.description || '-'
+ },
+ {
+ title: t('datasource.create_time'),
+ key: 'createTime',
+ },
+ {
+ title: t('datasource.update_time'),
+ key: 'updateTime',
+ },
+ {
+ title: t('data_pipes.operation'),
+ key: 'operation',
+ render: (row: any) =>
+ h(NSpace, null, {
+ default: () => [
+ h(
+ NButton,
+ {
+ text: true,
+ onClick: () => void onCallback(row.id, 'edit')
+ },
+ {
+ default: () => t('datasource.edit')
+ }
+ ),
+ h(
+ NButton,
+ {
+ text: true,
+ onClick: () => void onCallback(row.id, 'delete')
+ },
+ { default: () => t('datasource.delete') }
+ )
+ ]
+ })
+ }
+ ]
+ }
+
+ return {
+ getColumns
+ }
+}
diff --git a/seatunnel-ui/src/views/datasource/list/use-table.ts b/seatunnel-ui/src/views/datasource/list/use-table.ts
new file mode 100644
index 00000000..ba609eb2
--- /dev/null
+++ b/seatunnel-ui/src/views/datasource/list/use-table.ts
@@ -0,0 +1,71 @@
+/*
+ * 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 { reactive } from 'vue'
+import {
+ datasourceList,
+ datasourceDelete
+} from '@/service/datasource'
+import type { DatasourceList } from '@/service/datasource/types'
+import type { ResponseTable } from '@/service/types'
+
+export function useTable() {
+ const data = reactive({
+ page: 1,
+ pageSize: 10,
+ itemCount: 0,
+ searchVal: '',
+ list: []
+ })
+
+ const getList = () => {
+ datasourceList({
+ pageNo: data.page,
+ pageSize: data.pageSize,
+ searchVal: data.searchVal,
+ pluginName: ''
+ }).then((res: ResponseTable<Array<DatasourceList> | []>) => {
+ data.list = res.data.data as any
+ data.itemCount = res.data.totalCount
+ })
+ }
+
+ const updateList = () => {
+ if (data.list.length === 1 && data.page > 1) {
+ --data.page
+ }
+ getList()
+ }
+
+ const deleteRecord = async (id: string) => {
+ await datasourceDelete(id)
+ updateList()
+ }
+
+ const changePage = (page: number) => {
+ data.page = page
+ getList()
+ }
+
+ const changePageSize = (pageSize: number) => {
+ data.page = 1
+ data.pageSize = pageSize
+ getList()
+ }
+
+ return { data, getList, changePage, changePageSize, deleteRecord, updateList }
+}
diff --git a/seatunnel-ui/src/views/user-manage/list/index.tsx b/seatunnel-ui/src/views/user-manage/list/index.tsx
index 11a7d9fa..11a9cbe6 100644
--- a/seatunnel-ui/src/views/user-manage/list/index.tsx
+++ b/seatunnel-ui/src/views/user-manage/list/index.tsx
@@ -82,7 +82,7 @@ const UserManageList = defineComponent({
<NCard title={this.t('user_manage.user_manage')}>
{{
'header-extra': () => (
- <NButton onClick={this.handleFormModal} type='primary'>
+ <NButton onClick={this.handleFormModal} type='success'>
{this.t('user_manage.create')}
</NButton>
)