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 153e7b4f [Feat][UI] Add virtual table function. 153e7b4f is described below commit 153e7b4f7e0124092fdf8f4a765d0aad6f580cf0 Author: songjianet <1778651...@qq.com> AuthorDate: Wed Jun 7 09:38:58 2023 +0800 [Feat][UI] Add virtual table function. --- .../src/layouts/dashboard/header/menu/use-menu.ts | 4 + seatunnel-ui/src/locales/en_US/datasource.ts | 1 + seatunnel-ui/src/locales/en_US/index.ts | 4 +- seatunnel-ui/src/locales/en_US/menu.ts | 3 +- seatunnel-ui/src/locales/en_US/virtual-tables.ts | 63 ++++ seatunnel-ui/src/locales/zh_CN/datasource.ts | 1 + seatunnel-ui/src/locales/zh_CN/index.ts | 4 +- seatunnel-ui/src/locales/zh_CN/menu.ts | 3 +- seatunnel-ui/src/locales/zh_CN/virtual-tables.ts | 62 ++++ seatunnel-ui/src/router/routes.ts | 4 +- .../zh_CN/index.ts => router/virtual-tables.ts} | 42 +-- .../menu.ts => service/virtual-tables/index.ts} | 17 +- .../menu.ts => service/virtual-tables/types.ts} | 11 - seatunnel-ui/src/views/datasource/list/index.tsx | 2 +- .../src/views/datasource/list/use-columns.ts | 2 + seatunnel-ui/src/views/virtual-tables/detail.tsx | 198 +++++++++++++ .../src/views/virtual-tables/index.module.scss | 81 +++++ .../src/views/virtual-tables/list/index.tsx | 120 ++++++++ .../src/views/virtual-tables/list/use-columns.ts | 115 ++++++++ .../src/views/virtual-tables/list/use-table.ts | 114 +++++++ .../src/views/virtual-tables/step-one-form.tsx | 144 +++++++++ .../virtual-tables/step-three-params.tsx} | 55 ++-- .../src/views/virtual-tables/step-two-form.tsx | 117 ++++++++ .../src/views/virtual-tables/step-two-table.tsx | 327 +++++++++++++++++++++ .../menu.ts => views/virtual-tables/types.ts} | 19 +- .../src/views/virtual-tables/use-detail.ts | 184 ++++++++++++ 26 files changed, 1619 insertions(+), 78 deletions(-) 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 ebdc7994..509bc8b5 100644 --- a/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts +++ b/seatunnel-ui/src/layouts/dashboard/header/menu/use-menu.ts @@ -39,6 +39,10 @@ export function useMenu() { label: () => h(NEllipsis, null, { default: () => t('menu.datasource') }), key: 'datasource' }, + { + label: () => h(NEllipsis, null, { default: () => t('menu.virtual_tables') }), + key: 'virtual-tables' + }, { 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 index 6edf737c..e811af28 100644 --- a/seatunnel-ui/src/locales/en_US/datasource.ts +++ b/seatunnel-ui/src/locales/en_US/datasource.ts @@ -16,6 +16,7 @@ */ export default { + id: 'Id', datasource: 'DataSource', create_datasource: 'Create DataSource', choose_datasource_type: 'Choose DataSource Type', diff --git a/seatunnel-ui/src/locales/en_US/index.ts b/seatunnel-ui/src/locales/en_US/index.ts index 6d57ce9d..6a25d3dc 100644 --- a/seatunnel-ui/src/locales/en_US/index.ts +++ b/seatunnel-ui/src/locales/en_US/index.ts @@ -25,6 +25,7 @@ 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' +import virtual_tables from '@/locales/en_US/virtual-tables' export default { login, @@ -36,5 +37,6 @@ export default { jobs, tasks, setting, - datasource + datasource, + virtual_tables } diff --git a/seatunnel-ui/src/locales/en_US/menu.ts b/seatunnel-ui/src/locales/en_US/menu.ts index 800541f5..f3bd9587 100644 --- a/seatunnel-ui/src/locales/en_US/menu.ts +++ b/seatunnel-ui/src/locales/en_US/menu.ts @@ -23,5 +23,6 @@ export default { setting: 'Setting', logout: 'Logout', tasks: 'Tasks', - datasource: 'Datasource' + datasource: 'Datasource', + virtual_tables: 'Virtual Tables' } diff --git a/seatunnel-ui/src/locales/en_US/virtual-tables.ts b/seatunnel-ui/src/locales/en_US/virtual-tables.ts new file mode 100644 index 00000000..9b0650ce --- /dev/null +++ b/seatunnel-ui/src/locales/en_US/virtual-tables.ts @@ -0,0 +1,63 @@ +/* + * 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 { + virtual_tables: 'Virtual Tables', + create_virtual_tables: 'Create Virtual Tables', + edit_virtual_tables: 'Edit Virtual Tables', + source_type: 'Source Type', + source_type_tips: 'Please select a source type', + source_name: 'Source Name', + source_name_tips: 'Please enter source name', + table_name: 'Table Name', + database_name: 'Database Name', + creator: 'Creator', + creation_time: 'Creation Time', + updater: 'Updater', + update_time: 'Update Time', + operation: 'Operation', + edit: 'Edit', + delete: 'Delete', + confirm: 'Confirm', + delete_confirm: 'Delete?', + cancel: 'Cancel', + configure: 'Configure', + model: 'Model', + complete: 'Complete', + virtual_tables_name: 'Virtual Table Name', + virtual_tables_name_tips: 'Please enter a virtual table name', + next_step: 'Next Step', + previous_step: 'Previous Step', + table_structure: 'Table Structure', + add: 'Add a row', + field_name: 'Field Name', + field_name_tips: 'Please enter a field name', + field_type: 'Field Type', + is_null: 'Null', + is_primary_key: 'Primary Key', + description: 'Field Description', + yes: 'Yes', + no: 'No', + warning: 'Warning', + close_confirm_tips: + 'This operation will lose the currently created virtual table', + save_data_tips: 'Please save the data in the table', + table_data_required_tips: 'Please add a record to the table', + default_value: 'Default Value', + create: 'Create', + search: 'Search' +} diff --git a/seatunnel-ui/src/locales/zh_CN/datasource.ts b/seatunnel-ui/src/locales/zh_CN/datasource.ts index 6aaf46bd..f8321b5f 100644 --- a/seatunnel-ui/src/locales/zh_CN/datasource.ts +++ b/seatunnel-ui/src/locales/zh_CN/datasource.ts @@ -16,6 +16,7 @@ */ export default { + id: 'Id', datasource: '数据源', create_datasource: '创建源', choose_datasource_type: '选择源类型', diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts b/seatunnel-ui/src/locales/zh_CN/index.ts index c3e11f4a..8ecf70c4 100644 --- a/seatunnel-ui/src/locales/zh_CN/index.ts +++ b/seatunnel-ui/src/locales/zh_CN/index.ts @@ -25,6 +25,7 @@ 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' +import virtual_tables from '@/locales/zh_CN/virtual-tables' export default { login, @@ -36,5 +37,6 @@ export default { jobs, tasks, setting, - datasource + datasource, + virtual_tables } diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts b/seatunnel-ui/src/locales/zh_CN/menu.ts index 5270249f..1ab59deb 100644 --- a/seatunnel-ui/src/locales/zh_CN/menu.ts +++ b/seatunnel-ui/src/locales/zh_CN/menu.ts @@ -23,5 +23,6 @@ export default { setting: '设置', logout: '登出', tasks: '任务', - datasource: '数据源' + datasource: '数据源', + virtual_tables: '虚拟表' } diff --git a/seatunnel-ui/src/locales/zh_CN/virtual-tables.ts b/seatunnel-ui/src/locales/zh_CN/virtual-tables.ts new file mode 100644 index 00000000..f7adb43f --- /dev/null +++ b/seatunnel-ui/src/locales/zh_CN/virtual-tables.ts @@ -0,0 +1,62 @@ +/* + * 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 { + virtual_tables: '虚拟表', + create_virtual_tables: '创建虚拟表', + edit_virtual_tables: '编辑虚拟表', + source_type: '源类型', + source_type_tips: '请选择源类型', + source_name: '源名称', + source_name_tips: '请输入源名称', + table_name: '表名', + database_name: '库名', + creator: '创建人', + creation_time: '创建时间', + updater: '修改人', + update_time: '修改时间', + operation: '操作', + edit: '编辑', + delete: '删除', + confirm: '确定', + delete_confirm: '删除?', + cancel: '取消', + configure: '配置', + model: '模型', + complete: '完成', + virtual_tables_name: '虚拟表名', + virtual_tables_name_tips: '请输入虚拟表名', + next_step: '下一步', + previous_step: '上一步', + table_structure: '表结构', + add: '添加一行', + field_name: '字段名称', + field_name_tips: '请输入字段名称', + field_type: '字段类型', + is_null: '非空', + is_primary_key: '主键', + description: '字段描述', + yes: '是', + no: '否', + warning: '警告', + close_confirm_tips: '此操作会丢失当前创建的虚拟表', + save_data_tips: '请保存表格中的数据', + table_data_required_tips: '请在表结构中添加数据', + default_value: '默认值', + create: '创建', + search: '搜索' +} diff --git a/seatunnel-ui/src/router/routes.ts b/seatunnel-ui/src/router/routes.ts index 15d9eeff..121ba1ec 100644 --- a/seatunnel-ui/src/router/routes.ts +++ b/seatunnel-ui/src/router/routes.ts @@ -21,6 +21,7 @@ import jobs from '@/router/jobs' import tasks from '@/router/tasks' import userManage from '@/router/user-manage' import datasource from '@/router/datasource' +import virtualTables from '@/router/virtual-tables' import type { RouteRecordRaw } from 'vue-router' import type { Component } from 'vue' @@ -36,7 +37,8 @@ const basePage: RouteRecordRaw[] = [ jobs, tasks, userManage, - datasource + datasource, + virtualTables ] const loginPage: RouteRecordRaw[] = [ diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts b/seatunnel-ui/src/router/virtual-tables.ts similarity index 57% copy from seatunnel-ui/src/locales/zh_CN/index.ts copy to seatunnel-ui/src/router/virtual-tables.ts index c3e11f4a..9224d206 100644 --- a/seatunnel-ui/src/locales/zh_CN/index.ts +++ b/seatunnel-ui/src/router/virtual-tables.ts @@ -15,26 +15,28 @@ * 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 datasource from '@/locales/zh_CN/datasource' +import utils from '@/utils' +import type { Component } from 'vue' + +const modules = import.meta.glob('/src/views/**/**.tsx') +const components: { [key: string]: Component } = utils.mapping(modules) export default { - login, - menu, - modal, - user_manage, - data_pipes, - log, - jobs, - tasks, - setting, - datasource + path: '/virtual-tables', + name: 'virtual-tables', + meta: { + title: 'virtual-tables' + }, + redirect: { name: 'virtual-tables-list' }, + component: () => import('@/layouts/dashboard'), + children: [ + { + path: '/virtual-tables/list', + name: 'virtual-tables-list', + component: components['virtual-tables-list'], + meta: { + title: 'virtual-tables-list' + } + } + ] } diff --git a/seatunnel-ui/src/locales/en_US/menu.ts b/seatunnel-ui/src/service/virtual-tables/index.ts similarity index 80% copy from seatunnel-ui/src/locales/en_US/menu.ts copy to seatunnel-ui/src/service/virtual-tables/index.ts index 800541f5..1943eab2 100644 --- a/seatunnel-ui/src/locales/en_US/menu.ts +++ b/seatunnel-ui/src/service/virtual-tables/index.ts @@ -15,13 +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', - datasource: 'Datasource' +import { axios } from '@/service/service' + +export function virtualTableList(params: any): any { + return axios({ + url: '/virtual_table/list', + method: 'get', + params + }) } diff --git a/seatunnel-ui/src/locales/en_US/menu.ts b/seatunnel-ui/src/service/virtual-tables/types.ts similarity index 80% copy from seatunnel-ui/src/locales/en_US/menu.ts copy to seatunnel-ui/src/service/virtual-tables/types.ts index 800541f5..3e7c6c26 100644 --- a/seatunnel-ui/src/locales/en_US/menu.ts +++ b/seatunnel-ui/src/service/virtual-tables/types.ts @@ -14,14 +14,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export default { - data_pipes: 'Data Pipes', - jobs: 'Jobs', - user_manage: 'User Manage', - help: 'Help', - setting: 'Setting', - logout: 'Logout', - tasks: 'Tasks', - datasource: 'Datasource' -} diff --git a/seatunnel-ui/src/views/datasource/list/index.tsx b/seatunnel-ui/src/views/datasource/list/index.tsx index 70232dd3..05275749 100644 --- a/seatunnel-ui/src/views/datasource/list/index.tsx +++ b/seatunnel-ui/src/views/datasource/list/index.tsx @@ -142,7 +142,7 @@ const DatasourceList = defineComponent({ ) }} </NCard> - <NCard title='' class={styles['mt-8']}> + <NCard> <NDataTable row-class-name='data-source-items' columns={columns} diff --git a/seatunnel-ui/src/views/datasource/list/use-columns.ts b/seatunnel-ui/src/views/datasource/list/use-columns.ts index a46df1c4..15bae636 100644 --- a/seatunnel-ui/src/views/datasource/list/use-columns.ts +++ b/seatunnel-ui/src/views/datasource/list/use-columns.ts @@ -19,11 +19,13 @@ import { h } from 'vue' import { useI18n } from 'vue-i18n' import { NPopover, NButton, NSpace } from 'naive-ui' import JsonHighlight from '../components/json-highlight' +import { getTableColumn } from '@/common/table' export function useColumns(onCallback: Function) { const { t } = useI18n() const getColumns = () => { return [ + ...getTableColumn([{ key: 'id', title: t('datasource.id') }]), { title: t('datasource.datasource_name'), key: 'datasourceName' diff --git a/seatunnel-ui/src/views/virtual-tables/detail.tsx b/seatunnel-ui/src/views/virtual-tables/detail.tsx new file mode 100644 index 00000000..7434d8dc --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/detail.tsx @@ -0,0 +1,198 @@ +/* + * 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 } from 'vue' +import { + NSpace, + NBreadcrumb, + NBreadcrumbItem, + NSteps, + NStep, + NButton, + NText, + NIcon, + NCard, + useDialog +} from 'naive-ui' +import StepOneForm from './StepOneForm' +import StepTwoForm from './StepTwoForm' +import StepTwoTable from './StepTwoTable' +import StepThreeParams from './StepThreeParams' +import { PlusOutlined } from '@vicons/antd' +import { useRoute, useRouter } from 'vue-router' +import { useI18n } from 'vue-i18n' +import { useDetail } from './use-detail' +import styles from './index.module.scss' + +const VirtualTablesDetail = defineComponent({ + name: 'VirtualTablesDetail', + setup() { + const { t } = useI18n() + const route = useRoute() + const router = useRouter() + const dialog = useDialog() + const { + state, + stepOneFormRef, + stepTwoFormRef, + onAddRecord, + onChangeStep, + createOrUpdate + } = useDetail(route.params.id as string) + + const onClose = () => { + dialog.warning({ + title: t('virtual_tables.warning'), + content: t('virtual_tables.close_confirm_tips'), + onPositiveClick: () => { + router.push({ + name: 'datasource-list', + query: { tab: 'virtual-tables' } + }) + }, + positiveText: t('virtual_tables.confirm'), + negativeText: t('virtual_tables.cancel') + }) + } + + return () => ( + <NSpace vertical> + <NBreadcrumb> + <NBreadcrumbItem + // @ts-ignore + onClick={onClose} + > + {t('virtual_tables.virtual_tables')} + </NBreadcrumbItem> + <NBreadcrumbItem> + {t( + route.params.id + ? 'virtualTables.edit_virtual_tables' + : 'virtualTables.create_virtual_tables' + )} + </NBreadcrumbItem> + </NBreadcrumb> + <NCard + title={t( + route.params.id + ? 'virtualTables.edit_virtual_tables' + : 'virtualTables.create_virtual_tables' + )} + > + <div class={styles['detail-content']}> + <NSteps current={state.current} class={styles['detail-step']}> + <NStep title={t('virtual_tables.configure')} /> + <NStep title={t('virtual_tables.model')} /> + <NStep title={t('virtual_tables.complete')} /> + </NSteps> + <div class={styles['width-100']} v-show={state.current === 1}> + <NSpace justify='center'> + <StepOneForm params={state.stepOne} ref={stepOneFormRef} /> + </NSpace> + </div> + <div class={styles['detail-step-two']} v-show={state.current === 2}> + <StepTwoForm ref={stepTwoFormRef} /> + <div class={styles['detail-table-header']}> + <NText class={styles['detail-table-title']}> + {t('virtual_tables.table_structure')} + </NText> + <NButton text type='primary' onClick={onAddRecord}> + {{ + icon: () => ( + <NIcon> + <PlusOutlined /> + </NIcon> + ), + default: () => t('virtual_tables.add') + }} + </NButton> + </div> + <StepTwoTable + //list={state.stepTwo.list} + fieldTypes={state.fieldTypes} + /> + </div> + <div + class={styles['detail-step-three']} + v-show={state.current === 3} + > + <div class={styles['detail-step-three-params']}> + <StepThreeParams + class={styles['detail-step-three-left']} + params={[ + { + label: t('virtual_tables.source_type'), + value: state.stepOne.pluginName || '' + }, + { + label: t('virtual_tables.source_name'), + value: state.stepOne.datasourceName || '' + }, + { + label: t('virtual_tables.virtual_tables_name'), + value: state.stepOne.tableName || '' + } + ]} + /> + <StepThreeParams + class={styles['detail-step-three-right']} + params={state.stepTwo.config} + cols={3} + /> + </div> + <StepTwoTable + class={styles['width-100']} + //list={state.stepTwo.list} + plain + fieldTypes={state.fieldTypes} + /> + </div> + </div> + <NSpace justify='end'> + <NButton + v-show={state.current !== 1} + type='primary' + onClick={() => void onChangeStep(-1)} + > + {t('virtual_tables.previous_step')} + </NButton> + <NButton onClick={onClose}>{t('virtual_tables.cancel')}</NButton> + + {state.current !== 3 && ( + <NButton + type='primary' + onClick={() => void onChangeStep(1)} + loading={state.goNexting} + > + {t('virtual_tables.next_step')} + </NButton> + )} + <NButton + v-show={state.current === 3} + onClick={createOrUpdate} + loading={state.saving} + type='primary' + > + {t('virtual_tables.confirm')} + </NButton> + </NSpace> + </NCard> + </NSpace> + ) + } +}) + +export default VirtualTablesDetail diff --git a/seatunnel-ui/src/views/virtual-tables/index.module.scss b/seatunnel-ui/src/views/virtual-tables/index.module.scss new file mode 100644 index 00000000..4139b9d7 --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/index.module.scss @@ -0,0 +1,81 @@ +/* + * 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. + */ + +.type-width { + width: 220px; +} +.width-100 { + width: 100%; +} +.detail-step { + width: 50vw; + margin-top: 20px; + margin-left: 16vw; + margin-bottom: 30px; +} +.detail-content { + display: flex; + flex-direction: column; + align-items: center; +} +.detail-step-two { + width: 100%; + padding-bottom: 20px; + padding-top: 10px; +} +.detail-step-three { + width: 100%; + padding-bottom: 20px; +} +.detail-table-header { + height: 30px; + display: flex; + justify-content: space-between; +} +.detail-table-title { + font-weight: bold; +} +.step-two-table { + :global { + .n-form-item-feedback-wrapper { + line-height: 14px; + min-height: 14px; + } + } +} +.table-cell-center { + text-align: center !important; +} +.edit-row { + :global { + td { + padding-bottom: 0px; + } + } +} +.detail-step-three-params { + display: flex; + margin-bottom: 10px; + justify-content: space-between; +} +.detail-step-three-left { + width: 33%; + margin-right: 10px; +} +.detail-step-three-right { + flex-grow: 1; +} diff --git a/seatunnel-ui/src/views/virtual-tables/list/index.tsx b/seatunnel-ui/src/views/virtual-tables/list/index.tsx new file mode 100644 index 00000000..03bfdea1 --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/list/index.tsx @@ -0,0 +1,120 @@ +/* + * 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 } from 'vue' +import { + NButton, + NInput, + NSelect, + NIcon, + NSpace, + NDataTable, + NPagination, + NCard, + SelectOption, + SelectGroupOption +} from 'naive-ui' +import { useI18n } from 'vue-i18n' +import { useRouter } from 'vue-router' +import { useTable } from './use-table' +import { useColumns } from './use-columns' +//import { useSource } from '../datasource/list/use-source' +import styles from '../index.module.scss' + +const VirtualTablesList = defineComponent({ + setup() { + const { t } = useI18n() + const router = useRouter() + //const { state: sourceState } = useSource(true) + const { columns } = useColumns( + (id: string, type: 'edit' | 'delete') => { + if (type === 'edit') { + router.push({ name: 'virtual-tables-editor', params: { id: id } }) + } else { + onDelete(id) + } + } + ) + const { + state, + onSearch, + onDelete, + onPageChange, + onPageSizeChange + } = useTable() + + return () => ( + <NSpace vertical> + <NCard title={t('virtual_tables.virtual_tables')}> + {{ + 'header-extra': () => <NSpace> + <NSelect + v-model:value={state.params.pluginName} + clearable + placeholder={t('virtual_tables.source_type_tips')} + //options={ + // sourceState.types as Array<SelectGroupOption | SelectOption> + //} + class={styles['type-width']} + /> + <NInput + v-model:value={state.params.datasourceName} + clearable + placeholder={t('virtual_tables.source_name_tips')} + /> + <NButton type='primary' onClick={onSearch}> + {t('virtual_tables.search')} + </NButton> + <NButton + onClick={() => { + router.push({ name: 'virtual-tables-create' }) + }} + type='success' + > + {t('virtual_tables.create')} + </NButton> + </NSpace> + }} + </NCard> + <NCard> + <NSpace vertical> + <NDataTable + columns={columns.value} + data={state.list} + loading={state.loading} + striped + /> + <NSpace justify='center'> + <NPagination + v-model:page={state.page} + v-model:page-size={state.pageSize} + item-count={state.itemCount} + show-size-picker + page-sizes={[10, 30, 50]} + show-quick-jumper + on-update:page={onPageChange} + on-update:page-size={onPageSizeChange} + /> + </NSpace> + </NSpace> + </NCard> + </NSpace> + ) + } +}) + +export default VirtualTablesList diff --git a/seatunnel-ui/src/views/virtual-tables/list/use-columns.ts b/seatunnel-ui/src/views/virtual-tables/list/use-columns.ts new file mode 100644 index 00000000..860dd000 --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/list/use-columns.ts @@ -0,0 +1,115 @@ +/* + * 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, ref, watch, onMounted } from 'vue' +import { useI18n } from 'vue-i18n' +import { EditOutlined } from '@vicons/antd' +import { NButton, NSpace } from 'naive-ui' +//import type { TableColumns, VirtualTableRecord } from '../types' + +export function useColumns(onCallback: Function) { + const { t } = useI18n() + const columns = ref() + const getColumns = () => { + const columns = [ + { + title: 'ID', + key: 'id', + render: (ignore: any, index: number) => index + 1 + }, + { + title: t('virtual_tables.table_name'), + key: 'tableName', + align: 'left' + }, + { + title: t('virtual_tables.database_name'), + key: 'databaseName', + align: 'left' + }, + { + title: t('virtual_tables.source_name'), + key: 'datasourceName', + align: 'left' + }, + { + title: t('virtual_tables.source_type'), + key: 'pluginName' + }, + { + title: t('virtual_tables.creator'), + key: 'createUserName' + }, + { + title: t('virtual_tables.creation_time'), + key: 'createTime' + //render: (rowData: VirtualTableRecord) => + // renderTableTime(rowData.createTime) + }, + { + title: t('virtual_tables.updater'), + key: 'updateUserName' + }, + { + title: t('virtual_tables.update_time'), + key: 'updateTime' + //render: (rowData: VirtualTableRecord) => + // renderTableTime(rowData.createTime) + }, + { + title: t('virtual_tables.operation'), + key: 'operation', + render: (row: any) => + h(NSpace, null, { + default: () => [ + h( + NButton, + { + text: true, + onClick: () => void onCallback(row.tableId, 'edit') + }, + { + default: () => t('virtual_tables.edit') + } + ), + h( + NButton, + { + text: true, + onClick: () => void onCallback(row.tableId, 'delete') + }, + { default: () => t('virtual_tables.delete') } + ) + ] + }) + } + ] + return columns + } + + watch(useI18n().locale, () => { + columns.value = getColumns() + }) + + onMounted(() => { + columns.value = getColumns() + }) + + return { + columns + } +} diff --git a/seatunnel-ui/src/views/virtual-tables/list/use-table.ts b/seatunnel-ui/src/views/virtual-tables/list/use-table.ts new file mode 100644 index 00000000..a75d9294 --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/list/use-table.ts @@ -0,0 +1,114 @@ +/* + * 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 { + virtualTableList + //deleteVirtualTable +} from '@/service/virtual-tables' +import { useRoute, useRouter } from 'vue-router' +//import type { Params } from '../types' + +export function useTable() { + const initialParams: any = { + pluginName: null, + datasourceName: null + } + const state = reactive({ + params: { ...initialParams }, + list: [], + loading: false, + page: 1, + pageSize: 10, + itemCount: 0 + }) + const route = useRoute() + const router = useRouter() + + const getList = async () => { + const result = await virtualTableList({ + pageNo: state.page, + pageSize: state.pageSize, + ...state.params + }) + console.log(result) + state.list = result?.data + state.itemCount = result?.total + } + + const updateList = () => { + if (state.list.length === 1 && state.page > 1) { + --state.page + } + getList() + } + + const onDelete = async (id: string) => { + //await deleteVirtualTable(id) + updateList() + } + + const initSearch = () => { + const { pluginName, datasourceName } = route.query + if (pluginName) { + state.params.pluginName = pluginName as string + if (datasourceName) { + state.params.datasourceName = datasourceName as string + } + } + } + + const onSearch = () => { + const query = ( + state.params.pluginName ? { pluginName: state.params.pluginName } : null + ) as any + + if (state.params.datasourceName) { + query.datasourceName = state.params.datasourceName + } + + if (query) { + router.replace({ query: { tab: route.query.tab, ...query } }) + } + + state.page = 1 + getList() + } + + const onPageChange = (page: number) => { + state.page = page + getList() + } + + const onPageSizeChange = (pageSize: number) => { + state.page = 1 + state.pageSize = pageSize + getList() + } + + onMounted(() => { + initSearch() + onSearch() + }) + + return { + state, + onSearch, + onDelete, + onPageChange, + onPageSizeChange + } +} diff --git a/seatunnel-ui/src/views/virtual-tables/step-one-form.tsx b/seatunnel-ui/src/views/virtual-tables/step-one-form.tsx new file mode 100644 index 00000000..632a32d5 --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/step-one-form.tsx @@ -0,0 +1,144 @@ +/* + * 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, toRef } from 'vue' +import { + NForm, + NFormItem, + NSelect, + NInput, + SelectOption, + SelectGroupOption +} from 'naive-ui' +import { useI18n } from 'vue-i18n' +//import { useSource } from '../datasource/list/use-source' +import { useTable } from '../datasource/list/use-table' +import styles from './index.module.scss' + +const StepOneForm = defineComponent({ + name: 'StepOneForm', + props: { + params: { + type: Object, + default: {} + } + }, + setup(props, { expose }) { + const { t } = useI18n() + //const { state: sourceState } = useSource(true) + const { data: datasourceState, getList } = useTable() + const rules = { + pluginName: { + required: true, + trigger: ['input', 'blur'], + message: t('virtual_tables.source_type_tips') + }, + datasourceName: { + required: true, + trigger: ['input', 'blur'], + message: t('virtual_tables.source_name_tips') + }, + tableName: { + required: true, + trigger: ['input', 'blur'], + message: t('virtual_tables.virtual_tables_name_tips') + } + } + const paramsRef = toRef(props, 'params') + const stepOneFormRef = ref() + + const handleUpdateType = (type: string) => { + if (type === paramsRef.value.pluginName) return + datasourceState.pageSize = 99999 + //getList(type) + paramsRef.value.datasourceName = null + paramsRef.value.tableName = null + } + + expose({ + validate: async () => { + await stepOneFormRef.value.validate() + } + }) + + return () => ( + <NForm + rules={rules} + ref={stepOneFormRef} + require-mark-placement='left' + label-align='right' + labelPlacement='left' + model={paramsRef.value} + labelWidth={100} + > + <NFormItem + label={t('virtual_tables.source_type')} + path='pluginName' + show-require-mark + > + <NSelect + v-model:value={props.params.pluginName} + filterable + placeholder={t('virtual_tables.source_type_tips')} + //options={ + // sourceState.types as Array<SelectGroupOption | SelectOption> + //} + //loading={sourceState.loading} + class={styles['type-width']} + onUpdateValue={(value) => void handleUpdateType(value)} + /> + </NFormItem> + <NFormItem + label={t('virtual_tables.source_name')} + path='datasourceName' + show-require-mark + > + <NSelect + v-model:value={paramsRef.value.datasourceName} + filterable + placeholder={t('virtual_tables.source_name_tips')} + options={datasourceState.list.map( + (item: { datasourceName: string; id: string }) => ({ + label: item.datasourceName, + value: item.datasourceName, + id: item.id + }) + )} + //loading={datasourceState.loading} + class={styles['type-width']} + onUpdateValue={(value, option: { id: string }) => { + paramsRef.value.datasourceId = option.id + }} + /> + </NFormItem> + <NFormItem + label={t('virtual_tables.virtual_tables_name')} + path='tableName' + show-require-mark + > + <NInput + v-model:value={paramsRef.value.tableName} + clearable + placeholder={t('virtual_tables.virtual_tables_name_tips')} + class={styles['type-width']} + /> + </NFormItem> + </NForm> + ) + } +}) + +export default StepOneForm diff --git a/seatunnel-ui/src/locales/zh_CN/index.ts b/seatunnel-ui/src/views/virtual-tables/step-three-params.tsx similarity index 52% copy from seatunnel-ui/src/locales/zh_CN/index.ts copy to seatunnel-ui/src/views/virtual-tables/step-three-params.tsx index c3e11f4a..92ee2b9c 100644 --- a/seatunnel-ui/src/locales/zh_CN/index.ts +++ b/seatunnel-ui/src/views/virtual-tables/step-three-params.tsx @@ -15,26 +15,37 @@ * 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 datasource from '@/locales/zh_CN/datasource' +import { defineComponent, PropType } from 'vue' +import { NCard, NGrid, NGi, NSpace } from 'naive-ui' -export default { - login, - menu, - modal, - user_manage, - data_pipes, - log, - jobs, - tasks, - setting, - datasource -} +const StepThreeParams = defineComponent({ + name: 'StepThreeParams', + props: { + params: { + type: Array as PropType<{ label: string; value: string }[]>, + default: [] + }, + cols: { + type: Number, + default: 1 + } + }, + setup(props) { + return () => ( + <NCard> + <NGrid cols={props.cols}> + {props.params.map((item) => ( + <NGi> + <NSpace> + <span>{item.label}:</span> + <span>{item.value}</span> + </NSpace> + </NGi> + ))} + </NGrid> + </NCard> + ) + } +}) + +export default StepThreeParams diff --git a/seatunnel-ui/src/views/virtual-tables/step-two-form.tsx b/seatunnel-ui/src/views/virtual-tables/step-two-form.tsx new file mode 100644 index 00000000..a14793dd --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/step-two-form.tsx @@ -0,0 +1,117 @@ +/* + * 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, reactive, ref } from 'vue' +import { NForm } from 'naive-ui' +import { useI18n } from 'vue-i18n' +import { DynamicFormItem } from '@/components/dynamic-form/dynamic-form-item' +//import { StructureItem } from '@/store/datasource/form-structures' +//import { getDynamicConfig } from '@/service/modules/virtual-table' +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' + +const StepTwoForm = defineComponent({ + name: 'StepTwoForm', + setup(props, { expose }) { + const { t } = useI18n() + const stepTwoFormRef = ref() + + const state = reactive({ + rules: {}, + //formStructure: [] as StructureItem[], + locales: {} as any, + formName: 'step-two-form', + detailForm: {} as { [key: string]: string }, + config: [] as { key: string; value: string; label: string }[] + }) + + const getFormItems = async (pluginName: string, datasourceName: string) => { + if (!pluginName || !datasourceName) return false + //const result = await getDynamicConfig({ + // pluginName, + // datasourceName + //}) + try { + //const res = JSON.parse(result) + // + //state.locales = res.locales + //Object.assign(state.detailForm, useFormField(res.forms)) + //Object.assign( + // state.rules, + // useFormValidate(res.forms, state.detailForm, t) + //) + //state.formStructure = useFormStructure( + // res.apis ? useFormRequest(res.apis, res.forms) : res.forms + //) as any + // + //state.formStructure = res.forms.map((item: any) => ({ + // ...item, + // span: 8 + //})) + return true + } catch (err) { + return false + } + } + + const getValues = async () => { + await stepTwoFormRef.value.validate() + //return state.formStructure.map((item) => { + // return { + // label: item.label, + // key: item.field, + // value: state.detailForm[item.field] + // } + //}) + } + + const setValues = (values: { [key: string]: string }) => { + Object.assign(state.detailForm, values) + } + + expose({ + validate: async () => { + await stepTwoFormRef.value.validate() + }, + getFormItems, + getValues, + setValues + }) + + return () => ( + <NForm + rules={state.rules} + ref={stepTwoFormRef} + require-mark-placement='left' + model={state.detailForm} + labelWidth={100} + > + {/*{state.formStructure.length > 0 && (*/} + {/* <DynamicFormItem*/} + {/* model={state.detailForm}*/} + {/* formStructure={state.formStructure}*/} + {/* name={state.formName}*/} + {/* locales={state.locales}*/} + {/* />*/} + {/*)}*/} + </NForm> + ) + } +}) + +export default StepTwoForm diff --git a/seatunnel-ui/src/views/virtual-tables/step-two-table.tsx b/seatunnel-ui/src/views/virtual-tables/step-two-table.tsx new file mode 100644 index 00000000..c90e85e3 --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/step-two-table.tsx @@ -0,0 +1,327 @@ +/* + * 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, toRef, ref, onMounted } from 'vue' +import { + NTable, + NText, + NTooltip, + NFormItem, + NInput, + NSelect, + NSpace, + NButton, + NPopconfirm, + NIcon, + NEmpty +} from 'naive-ui' +import { useI18n } from 'vue-i18n' +import { EditOutlined, DeleteOutlined } from '@vicons/antd' +import styles from './index.module.scss' +//import type { IDetailTableRecord } from './types' + +const EditRow = defineComponent({ + name: 'EditRow', + props: { + row: { + type: Object as PropType<any>, + default: {} + }, + plain: { + type: Boolean, + default: false + }, + fieldTypes: { + type: Array as PropType<string[]>, + default: [] + } + }, + emits: ['updateValue', 'delete'], + setup(props, { emit }) { + const { t } = useI18n() + const inputRef = ref() + const fieldTypeRef = ref() + const onUpdateValue = (field: keyof any, value: any) => { + emit('updateValue', field, value) + } + onMounted(() => { + inputRef.value.focus() + }) + return () => ( + <tr> + <td> + <NFormItem + showLabel={false} + feedback={ + props.row.fieldName ? '' : t('virtual_tables.field_name_tips') + } + validation-status={props.row.fieldName ? '' : 'error'} + > + <NInput + autofocus + value={props.row.fieldName} + clearable + onUpdateValue={(value) => void onUpdateValue('fieldName', value)} + ref={inputRef} + /> + </NFormItem> + </td> + <td> + <NFormItem showLabel={false} v-show={props.row.isEdit}> + <NSelect + ref={fieldTypeRef} + value={props.row.fieldType} + options={props.fieldTypes.map((item) => ({ + label: item, + value: item + }))} + filterable + onUpdateValue={(value) => void onUpdateValue('fieldType', value)} + /> + </NFormItem> + </td> + <td> + <NFormItem showLabel={false}> + <NSelect + value={props.row.nullable as number} + options={[ + { value: 1, label: t('virtual_tables.yes') }, + { value: 0, label: t('virtual_tables.no') } + ]} + onUpdateValue={(value) => void onUpdateValue('nullable', value)} + /> + </NFormItem> + </td> + <td> + <NFormItem showLabel={false}> + <NSelect + value={props.row.primaryKey as number} + options={[ + { value: 1, label: t('virtual_tables.yes') }, + { value: 0, label: t('virtual_tables.no') } + ]} + onUpdateValue={(value) => void onUpdateValue('primaryKey', value)} + /> + </NFormItem> + </td> + <td> + <NFormItem showLabel={false}> + <NInput + value={props.row.fieldComment} + clearable + onUpdateValue={(value) => + void onUpdateValue('fieldComment', value) + } + /> + </NFormItem> + </td> + <td> + <NFormItem showLabel={false}> + <NInput + value={props.row.defaultValue} + clearable + onUpdateValue={(value) => + void onUpdateValue('defaultValue', value) + } + /> + </NFormItem> + </td> + {!props.plain && ( + <td> + <NFormItem showLabel={false}> + <NSpace align='start'> + <NButton + size='small' + onClick={() => void onUpdateValue('isEdit', false)} + > + {t('virtual_tables.cancel')} + </NButton> + <NButton + type='primary' + size='small' + onClick={() => { + if (!props.row.fieldName) { + inputRef.value.focus() + return + } + if (!props.row.fieldType) { + fieldTypeRef.value.focus() + return + } + onUpdateValue('isEdit', false) + }} + > + {t('virtual_tables.confirm')} + </NButton> + </NSpace> + </NFormItem> + </td> + )} + </tr> + ) + } +}) + +const StepTwoTable = defineComponent({ + name: 'StepTwoTable', + props: { + list: { + type: Array as PropType<any[]>, + default: [] + }, + plain: { + type: Boolean, + default: false + }, + fieldTypes: { + type: Array as PropType<string[]>, + default: [] + } + }, + setup(props) { + const { t } = useI18n() + const listRef = toRef(props, 'list') + return () => ( + <NTable striped class={styles['step-two-table']}> + <thead> + <th> + <NText type='error'>*</NText> + {t('virtual_tables.field_name')} + </th> + <th class={styles['table-cell-center']}> + <NText type='error'>*</NText> + {t('virtual_tables.field_type')} + </th> + <th class={styles['table-cell-center']}> + <NText type='error'>*</NText> + {t('virtual_tables.is_null')} + </th> + <th class={styles['table-cell-center']}> + <NText type='error'>*</NText> + {t('virtual_tables.is_primary_key')} + </th> + <th>{t('virtual_tables.description')}</th> + <th>{t('virtual_tables.default_value')}</th> + {!props.plain && <th>{t('virtual_tables.operation')}</th>} + </thead> + <tbody> + {listRef.value.map((row, index) => + row.isEdit && !props.plain ? ( + <EditRow + key={row.key} + row={row} + plain={props.plain} + fieldTypes={props.fieldTypes} + onUpdateValue={( + field: keyof any, + value: any + ) => { + // @ts-ignore + listRef.value[index][field] = value + }} + class={styles[row.isEdit ? 'edit-row' : 'plain-row']} + /> + ) : ( + <tr> + <td> + <span>{row.fieldName}</span> + </td> + <td class={styles['table-cell-center']}> + <span>{row.fieldType}</span> + </td> + <td class={styles['table-cell-center']}> + <span> + {row.nullable + ? t('virtual_tables.yes') + : t('virtual_tables.no')} + </span> + </td> + <td class={styles['table-cell-center']}> + <span> + {row.primaryKey + ? t('virtual_tables.yes') + : t('virtual_tables.no')} + </span> + </td> + <td> + <span>{row.fieldComment}</span> + </td> + <td> + <span>{row.defaultValue}</span> + </td> + {!props.plain && ( + <td> + <NSpace align='start'> + <NTooltip> + {{ + trigger: () => ( + <NButton + type='primary' + circle + size='small' + onClick={() => { + listRef.value[index]['isEdit'] = true + }} + > + <NIcon> + <EditOutlined /> + </NIcon> + </NButton> + ), + default: () => t('virtual_tables.edit') + }} + </NTooltip> + <NTooltip> + {{ + trigger: () => ( + <NPopconfirm + onPositiveClick={() => { + listRef.value.splice(index, 1) + }} + > + {{ + trigger: () => ( + <NButton type='error' circle size='small'> + <NIcon> + <DeleteOutlined /> + </NIcon> + </NButton> + ), + default: () => t('virtual_tables.delete_confirm') + }} + </NPopconfirm> + ), + default: () => t('virtual_tables.delete') + }} + </NTooltip> + </NSpace> + </td> + )} + </tr> + ) + )} + <tr v-show={!listRef.value.length}> + <td colspan={6}> + <NEmpty /> + </td> + </tr> + </tbody> + </NTable> + ) + } +}) + +export default StepTwoTable diff --git a/seatunnel-ui/src/locales/zh_CN/menu.ts b/seatunnel-ui/src/views/virtual-tables/types.ts similarity index 65% copy from seatunnel-ui/src/locales/zh_CN/menu.ts copy to seatunnel-ui/src/views/virtual-tables/types.ts index 5270249f..09cee8c8 100644 --- a/seatunnel-ui/src/locales/zh_CN/menu.ts +++ b/seatunnel-ui/src/views/virtual-tables/types.ts @@ -14,14 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export type { TableColumns } from 'naive-ui/es/data-table/src/interface' +export type { DataTableColumns } from 'naive-ui' +//export type { +// VirtualTableDetail, +// VirtualTableRecord, +// IDetailTableRecord +//} from '@/service/modules/virtual-table/types' +//import type { VirtualTableListParameters } from '@/service/modules/virtual-table/types' -export default { - data_pipes: '数据管道', - jobs: '工作', - user_manage: '用户管理', - help: '帮助', - setting: '设置', - logout: '登出', - tasks: '任务', - datasource: '数据源' -} +//export type Params = Omit<VirtualTableListParameters, 'pageNo' | 'pageSize'> diff --git a/seatunnel-ui/src/views/virtual-tables/use-detail.ts b/seatunnel-ui/src/views/virtual-tables/use-detail.ts new file mode 100644 index 00000000..0c2f709b --- /dev/null +++ b/seatunnel-ui/src/views/virtual-tables/use-detail.ts @@ -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 { reactive, ref, onMounted } from 'vue' +import { useI18n } from 'vue-i18n' +//import { +// getVirtualTableDetail, +// createVirtualTable, +// updateVirtualTable, +// getFieldType +//} from '@/service/modules/virtual-table' +import { omit } from 'lodash' +import { useRouter } from 'vue-router' +//import type { IDetailTableRecord, VirtualTableDetail } from './types' + +export const useDetail = (id: string) => { + const state = reactive({ + current: 1, + loading: false, + saving: false, + stepOne: { + pluginName: null, + datasourceName: null, + tableName: '', + datasourceId: '' + }, + stepTwo: { + //list: [] as IDetailTableRecord[], + loading: false, + config: [] + }, + fieldTypes: [] as string[], + goNexting: false + }) + const { t } = useI18n() + let tempDatabaseProperties: any + const router = useRouter() + const defaultRecord = { + fieldName: '', + fieldType: '', + nullable: 0, + primaryKey: 0, + isEdit: true + } + const stepOneFormRef = ref() + const stepTwoFormRef = ref() + + const queryById = async () => { + if (state.loading) return {} + state.loading = true + //const res = await getVirtualTableDetail(id) + //state.stepOne.pluginName = res.pluginName + //state.stepOne.datasourceName = res.datasourceName + //state.stepOne.datasourceId = res.datasourceId + //state.stepOne.tableName = res.tableName + //state.stepTwo.list = res.fields.map((item: { [key: string]: any }) => ({ + // ...item, + // nullable: Number(item.nullable), + // primaryKey: Number(item.primaryKey) + //})) + //tempDatabaseProperties = res.datasourceProperties + state.loading = false + } + + const queryFieldsType = async () => { + //const res = await getFieldType() + //state.fieldTypes = res + //defaultRecord.fieldType = state.fieldTypes[0] + } + + const formatParams = () => { + const databaseProperties = {} as { [key: string]: string } + state.stepTwo.config.forEach((item: { key: string; value: string }) => { + databaseProperties[item.key] = item.value + }) + return { + datasourceId: state.stepOne.datasourceId, + datasourceName: state.stepOne.datasourceName || '', + pluginName: state.stepOne.pluginName || '', + tableName: state.stepOne.tableName, + //tableFields: state.stepTwo.list.map((item) => ({ + // ...omit(item, ['key', 'isEdit']), + // nullable: Boolean(item.nullable), + // primaryKey: Boolean(item.nullable) + //})), + databaseProperties, + databaseName: 'default' + } + } + + const createOrUpdate = async () => { + const values = formatParams() + if (state.saving) return false + state.saving = true + + try { + //id + // ? await updateVirtualTable(values, id) + // : await createVirtualTable(values) + + state.saving = false + router.push({ + name: 'datasource-list', + query: { tab: 'virtual-tables' } + }) + return true + } catch (err) { + state.saving = false + return false + } + } + + const onAddRecord = () => { + //state.stepTwo.list.unshift({ + // ...defaultRecord, + // key: Date.now() + Math.random() * 1000 + //}) + } + + const onChangeStep = async (step: -1 | 1) => { + if (state.current === 1 && step === 1) { + state.goNexting = true + try { + await stepOneFormRef.value.validate() + await stepTwoFormRef.value.getFormItems( + state.stepOne.pluginName, + state.stepOne.datasourceName + ) + if (tempDatabaseProperties) + stepTwoFormRef.value.setValues(tempDatabaseProperties) + } finally { + state.goNexting = false + } + } + if (state.current === 2 && step === 1) { + state.goNexting = true + try { + const values = await stepTwoFormRef.value.getValues() + state.stepTwo.config = values + //const flag = state.stepTwo.list.some((item) => item.isEdit) + //if (flag) { + // window.$message.error(t('virtual_tables.save_data_tips')) + // return + //} + //if (state.stepTwo.list.length === 0) { + // window.$message.error(t('virtual_tables.table_data_required_tips')) + // return + //} + } finally { + state.goNexting = false + } + } + state.current += step + } + + onMounted(() => { + if (id) { + queryById() + } + queryFieldsType() + }) + + return { + state, + stepOneFormRef, + stepTwoFormRef, + createOrUpdate, + onAddRecord, + onChangeStep + } +}