Browse Source

[Feature][UI Next] Add udf function manage (#8126)

3.0.0/version-upgrade
Devosend 3 years ago committed by GitHub
parent
commit
62198fda24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 32
      dolphinscheduler-ui-next/src/locales/modules/en_US.ts
  2. 31
      dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
  3. 8
      dolphinscheduler-ui-next/src/router/modules/resources.ts
  4. 10
      dolphinscheduler-ui-next/src/service/modules/resources/index.ts
  5. 2
      dolphinscheduler-ui-next/src/service/modules/resources/types.ts
  6. 269
      dolphinscheduler-ui-next/src/views/resource/udf/function/components/function-modal.tsx
  7. 102
      dolphinscheduler-ui-next/src/views/resource/udf/function/components/use-form.ts
  8. 184
      dolphinscheduler-ui-next/src/views/resource/udf/function/components/use-modal.ts
  9. 73
      dolphinscheduler-ui-next/src/views/resource/udf/function/index.module.scss
  10. 144
      dolphinscheduler-ui-next/src/views/resource/udf/function/index.tsx
  11. 38
      dolphinscheduler-ui-next/src/views/resource/udf/function/types.ts
  12. 182
      dolphinscheduler-ui-next/src/views/resource/udf/function/use-table.ts

32
dolphinscheduler-ui-next/src/locales/modules/en_US.ts

@ -215,6 +215,38 @@ const resource = {
enter_name_tips: 'Please enter name',
enter_description_tips: 'Please enter description'
},
function: {
udf_function: 'UDF Function',
create_udf_function: 'Create UDF Function',
edit_udf_function: 'Create UDF Function',
id: '#',
udf_function_name: 'UDF Function Name',
class_name: 'Class Name',
type: 'Type',
description: 'Description',
jar_package: 'Jar Package',
update_time: 'Update Time',
operation: 'Operation',
rename: 'Rename',
edit: 'Edit',
delete: 'Delete',
success: 'Success',
package_name: 'Package Name',
udf_resources: 'UDF Resources',
instructions: 'Instructions',
upload_resources: 'Upload Resources',
udf_resources_directory: 'UDF resources directory',
delete_confirm: 'Delete?',
enter_keyword_tips: 'Please enter keyword',
enter_udf_unction_name_tips: 'Please enter a UDF function name',
enter_package_name_tips: 'Please enter a Package name',
enter_select_udf_resources_tips: 'Please select UDF resources',
enter_select_udf_resources_directory_tips:
'Please select UDF resources directory',
enter_instructions_tips: 'Please enter a instructions',
enter_name_tips: 'Please enter name',
enter_description_tips: 'Please enter description'
},
task_group_option: {
id: 'No.',
manage: 'Task group manage',

31
dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts

@ -217,6 +217,37 @@ const resource = {
enter_name_tips: '请输入名称',
enter_description_tips: '请输入描述'
},
function: {
udf_function: 'UDF函数',
create_udf_function: '创建UDF函数',
edit_udf_function: '编辑UDF函数',
id: '编号',
udf_function_name: 'UDF函数名称',
class_name: '类名',
type: '类型',
description: '描述',
jar_package: 'jar包',
update_time: '更新时间',
operation: '操作',
rename: '重命名',
edit: '编辑',
delete: '删除',
success: '成功',
package_name: '包名类名',
udf_resources: 'UDF资源',
instructions: '使用说明',
upload_resources: '上传资源',
udf_resources_directory: 'UDF资源目录',
delete_confirm: '确定删除吗?',
enter_keyword_tips: '请输入关键词',
enter_udf_unction_name_tips: '请输入UDF函数名称',
enter_package_name_tips: '请输入包名类名',
enter_select_udf_resources_tips: '请选择UDF资源',
enter_select_udf_resources_directory_tips: '请选择UDF资源目录',
enter_instructions_tips: '请输入使用说明',
enter_name_tips: '请输入名称',
enter_description_tips: '请输入描述'
},
task_group_option: {
id: '编号',
manage: '任务组管理',

8
dolphinscheduler-ui-next/src/router/modules/resources.ts

@ -101,6 +101,14 @@ export default {
showSide: true
}
},
{
path: '/resource/function-manage',
name: 'function-manage',
component: components['function'],
meta: {
title: '函数管理'
}
},
{
path: '/resource/task-group',
name: 'task-group-manage',

10
dolphinscheduler-ui-next/src/service/modules/resources/index.ts

@ -118,9 +118,7 @@ export function onlineCreateResource(
})
}
export function queryResourceByProgramType(
params: ResourceTypeReq & ProgramTypeReq
): any {
export function queryResourceByProgramType(params: ResourceTypeReq): any {
return axios({
url: '/resources/query-by-type',
method: 'get',
@ -136,7 +134,7 @@ export function queryUdfFuncListPaging(params: ListReq): any {
})
}
export function queryUdfFuncList(params: UdfTypeReq): any {
export function queryUdfFuncList(params: IdReq & ListReq): any {
return axios({
url: '/resources/udf-func/list',
method: 'get',
@ -152,7 +150,7 @@ export function verifyUdfFuncName(params: NameReq): any {
})
}
export function deleteUdfFunc(id: IdReq): any {
export function deleteUdfFunc(id: number): any {
return axios({
url: `/resources/udf-func/${id}`,
method: 'delete'
@ -245,7 +243,7 @@ export function createUdfFunc(
export function updateUdfFunc(
data: UdfFuncReq,
resourceId: ResourceIdReq,
id: IdReq
id: number
): any {
return axios({
url: `/resources/${resourceId}/udf-func/${id}`,

2
dolphinscheduler-ui-next/src/service/modules/resources/types.ts

@ -83,7 +83,7 @@ interface ResourceIdReq {
resourceId: number
}
interface UdfFuncReq extends UdfTypeReq, DescriptionReq {
interface UdfFuncReq extends UdfTypeReq, DescriptionReq, ResourceIdReq {
className: string
funcName: string
argTypes?: string

269
dolphinscheduler-ui-next/src/views/resource/udf/function/components/function-modal.tsx

@ -0,0 +1,269 @@
/*
* 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, toRefs, PropType, watch, onMounted, ref } from 'vue'
import {
NUpload,
NIcon,
NForm,
NFormItem,
NInput,
NInputGroup,
NRadio,
NTreeSelect,
NButton,
NRadioGroup
} from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { CloudUploadOutlined } from '@vicons/antd'
import Modal from '@/components/modal'
import { useForm } from './use-form'
import { useModal } from './use-modal'
import type { IUdf } from '../types'
const props = {
row: {
type: Object as PropType<IUdf>,
default: {}
},
show: {
type: Boolean as PropType<boolean>,
default: false
}
}
export default defineComponent({
name: 'ResourceFileFolder',
props,
emits: ['update:show', 'updateList'],
setup(props, ctx) {
const treeRef = ref()
const { state, uploadState } = useForm()
const {
variables,
handleCreateFunc,
handleRenameFunc,
getUdfList,
handleUploadFile
} = useModal(state, uploadState, ctx)
const hideModal = () => {
ctx.emit('update:show')
}
const handleCreate = () => {
handleCreateFunc()
}
const handleRename = () => {
handleRenameFunc(props.row.id)
}
const handleUpload = () => {
uploadState.uploadForm.currentDir = `/${treeRef.value.selectedOption?.fullName}`
handleUploadFile()
}
const customRequest = ({ file }: any) => {
uploadState.uploadForm.name = file.name
uploadState.uploadForm.file = file.file
}
onMounted(() => {
getUdfList()
})
watch(
() => props.row,
() => {
variables.uploadShow = false
state.functionForm.type = props.row.type
state.functionForm.funcName = props.row.funcName
state.functionForm.className = props.row.className
state.functionForm.resourceId = props.row.resourceId || -1
state.functionForm.description = props.row.description
}
)
return {
treeRef,
hideModal,
handleCreate,
handleRename,
customRequest,
handleUpload,
...toRefs(state),
...toRefs(uploadState),
...toRefs(variables)
}
},
render() {
const { t } = useI18n()
return (
<Modal
show={this.$props.show}
title={
this.row.id
? t('resource.function.edit_udf_function')
: t('resource.function.create_udf_function')
}
onCancel={this.hideModal}
onConfirm={this.row.id ? this.handleRename : this.handleCreate}
>
<NForm
rules={this.rules}
ref='functionFormRef'
label-placement='left'
label-width='160'
>
<NFormItem label={t('resource.function.type')} path='type'>
<NRadioGroup
v-model={[this.functionForm.type, 'value']}
name='type'
>
<NRadio value='HIVE'>HIVE UDF</NRadio>
</NRadioGroup>
</NFormItem>
<NFormItem
label={t('resource.function.udf_function_name')}
path='funcName'
>
<NInput
v-model={[this.functionForm.funcName, 'value']}
placeholder={t('resource.function.enter_udf_unction_name_tips')}
/>
</NFormItem>
<NFormItem
label={t('resource.function.package_name')}
path='className'
>
<NInput
v-model={[this.functionForm.className, 'value']}
placeholder={t('resource.function.enter_package_name_tips')}
/>
</NFormItem>
<NFormItem
label={t('resource.function.udf_resources')}
path='resourceId'
>
<NInputGroup>
<NTreeSelect
options={this.udfResourceList}
label-field='fullName'
key-field='id'
v-model={[this.functionForm.resourceId, 'value']}
placeholder={t(
'resource.function.enter_select_udf_resources_tips'
)}
defaultValue={this.functionForm.resourceId}
disabled={this.uploadShow}
showPath={false}
></NTreeSelect>
<NButton
type='primary'
ghost
onClick={() => (this.uploadShow = !this.uploadShow)}
>
{t('resource.function.upload_resources')}
</NButton>
</NInputGroup>
</NFormItem>
{this.uploadShow && (
<NForm
rules={this.uploadRules}
ref='uploadFormRef'
label-placement='left'
label-width='160'
>
<NFormItem
label={t('resource.function.udf_resources_directory')}
path='pid'
show-feedback={false}
style={{ marginBottom: '5px' }}
>
<NTreeSelect
ref='treeRef'
options={this.udfResourceDirList}
label-field='fullName'
key-field='id'
v-model={[this.uploadForm.pid, 'value']}
placeholder={t(
'resource.function.enter_select_udf_resources_directory_tips'
)}
defaultValue={this.uploadForm.pid}
></NTreeSelect>
</NFormItem>
<NFormItem
label=' '
show-feedback={false}
style={{ marginBottom: '5px' }}
>
<NInputGroup>
<NInput
v-model={[this.uploadForm.name, 'value']}
placeholder={t('resource.function.enter_name_tips')}
/>
<NButton>
<NUpload
v-model={[this.uploadForm.file, 'value']}
customRequest={this.customRequest}
showFileList={false}
>
<NButton text>
<NIcon>
<CloudUploadOutlined />
</NIcon>
</NButton>
</NUpload>
</NButton>
</NInputGroup>
</NFormItem>
<NFormItem
label=' '
path='description'
show-feedback={false}
style={{ marginBottom: '5px' }}
>
<NInput
type='textarea'
v-model={[this.uploadForm.description, 'value']}
placeholder={t('resource.function.enter_description_tips')}
/>
</NFormItem>
<NFormItem label=' '>
<NButton onClick={this.handleUpload}>UDF资源</NButton>
</NFormItem>
</NForm>
)}
<NFormItem
label={t('resource.function.instructions')}
path='description'
>
<NInput
type='textarea'
v-model={[this.functionForm.description, 'value']}
placeholder={t('resource.function.enter_instructions_tips')}
/>
</NFormItem>
</NForm>
</Modal>
)
}
})

102
dolphinscheduler-ui-next/src/views/resource/udf/function/components/use-form.ts

@ -0,0 +1,102 @@
/*
* 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 } from 'vue'
import { useI18n } from 'vue-i18n'
import type { FormRules } from 'naive-ui'
export const useForm = () => {
const { t } = useI18n()
const state = reactive({
functionFormRef: ref(),
functionForm: {
type: 'HIVE',
funcName: '',
className: '',
argTypes: '',
database: '',
description: '',
resourceId: -1
},
rules: {
type: {
required: true,
trigger: ['input', 'blur'],
validator() {
if (!state.functionForm.type) {
return new Error(t('resource.function.enter_name_tips'))
}
}
},
funcName: {
required: true,
trigger: ['input', 'blur'],
validator() {
if (!state.functionForm.funcName) {
return new Error(t('resource.function.enter_name_tips'))
}
}
},
className: {
required: true,
trigger: ['input', 'blur'],
validator() {
if (!state.functionForm.className) {
return new Error(t('resource.function.enter_name_tips'))
}
}
},
resourceId: {
required: true,
trigger: ['input', 'blur'],
validator() {
if (state.functionForm.resourceId === -1) {
return new Error(t('resource.function.enter_name_tips'))
}
}
}
} as FormRules
})
const uploadState = reactive({
uploadFormRef: ref(),
uploadForm: {
name: '',
file: '',
description: '',
pid: -1,
currentDir: '/'
},
uploadRules: {
pid: {
required: true,
trigger: ['input', 'blur'],
validator() {
if (uploadState.uploadForm.pid === -1) {
return new Error(t('resource.function.enter_name_tips'))
}
}
}
} as FormRules
})
return {
state,
uploadState
}
}

184
dolphinscheduler-ui-next/src/views/resource/udf/function/components/use-modal.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 _ from 'lodash'
import { ref, reactive, SetupContext } from 'vue'
import { useI18n } from 'vue-i18n'
import {
createResource,
createUdfFunc,
queryResourceList,
updateUdfFunc
} from '@/service/modules/resources'
import { useAsyncState } from '@vueuse/core'
export function useModal(
state: any,
uploadState: any,
ctx: SetupContext<('update:show' | 'updateList')[]>
) {
const { t } = useI18n()
const handleCreateFunc = async () => {
submitRequest(
async () =>
await createUdfFunc(
{
...state.functionForm
},
state.functionForm.resourceId
)
)
}
const handleRenameFunc = async (id: number) => {
submitRequest(async () => {
await updateUdfFunc(
{
...state.functionForm,
id
},
state.functionForm.resourceId,
id
)
})
}
const submitRequest = (serviceHandle: any) => {
state.functionFormRef.validate(async (valid: any) => {
if (!valid) {
try {
await serviceHandle()
window.$message.success(t('resource.udf.success'))
ctx.emit('updateList')
ctx.emit('update:show')
} catch (error: any) {
window.$message.error(error.message)
}
}
})
}
const variables = reactive({
uploadShow: ref(false),
udfResourceList: [],
udfResourceDirList: []
})
const filterEmptyDirectory = (list: any) => {
for (const item of list) {
if (item.children) {
if (!/\.jar$/.test(item.name)) {
item.disabled = true
}
filterEmptyDirectory(item.children)
}
}
return list.filter(
(n: any) =>
(/\.jar$/.test(n.name) && n.children.length === 0) ||
(!/\.jar$/.test(n.name) && n.children.length > 0)
)
}
// filterJarFile
const filterJarFile = (array: any) => {
for (const item of array) {
if (item.children) {
item.children = filterJarFile(item.children)
}
}
return array.filter((n: any) => !/\.jar$/.test(n.name))
}
// recursiveTree
const recursiveTree = (item: any) => {
// Recursive convenience tree structure
item.forEach((item: any) => {
item.children === '' ||
item.children === undefined ||
item.children === null ||
item.children.length === 0
? delete item.children
: recursiveTree(item.children)
})
}
const getUdfList = () => {
const { state } = useAsyncState(
queryResourceList({ type: 'UDF' }).then((res: any) => {
let item = res
let item1 = _.cloneDeep(res)
filterEmptyDirectory(item)
item = filterEmptyDirectory(item)
recursiveTree(item)
recursiveTree(filterJarFile(item1))
item1 = item1.filter((item: any) => {
if (item.dirctory) {
return item
}
})
variables.udfResourceList = item
variables.udfResourceDirList = item1
}),
{}
)
return state
}
const resetUploadForm = () => {
uploadState.uploadForm.name = ''
uploadState.uploadForm.file = ''
uploadState.uploadForm.pid = -1
uploadState.uploadForm.currentDir = '/'
uploadState.uploadForm.description = ''
}
const handleUploadFile = () => {
uploadState.uploadFormRef.validate(async (valid: any) => {
if (!valid) {
const formData = new FormData()
formData.append('file', uploadState.uploadForm.file)
formData.append('type', 'UDF')
formData.append('name', uploadState.uploadForm.name)
formData.append('pid', uploadState.uploadForm.pid)
formData.append('currentDir', uploadState.uploadForm.currentDir)
formData.append('description', uploadState.uploadForm.description)
try {
const res = await createResource(formData as any)
window.$message.success(t('resource.function.success'))
variables.uploadShow = false
resetUploadForm()
getUdfList()
state.functionForm.resourceId = res.id
} catch (error: any) {
window.$message.error(error.message)
}
}
})
}
return {
variables,
getUdfList,
handleCreateFunc,
handleRenameFunc,
handleUploadFile
}
}

73
dolphinscheduler-ui-next/src/views/resource/udf/function/index.module.scss

@ -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.
*/
.content {
width: 100%;
.card {
margin-bottom: 8px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
.right {
> .search {
.list {
float: right;
margin: 3px 0 3px 4px;
}
}
}
}
.table {
table {
width: 100%;
tr {
height: 40px;
font-size: 12px;
th,
td {
&:nth-child(1) {
width: 50px;
text-align: center;
}
}
th {
&:nth-child(1) {
width: 60px;
text-align: center;
}
> span {
font-size: 12px;
color: #555;
}
}
}
}
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
}

144
dolphinscheduler-ui-next/src/views/resource/udf/function/index.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, toRefs, onMounted, toRef } from 'vue'
import {
NIcon,
NSpace,
NDataTable,
NButton,
NPagination,
NInput
} from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { SearchOutlined } from '@vicons/antd'
import Card from '@/components/card'
import FolderModal from './components/function-modal'
import { useTable } from './use-table'
import styles from './index.module.scss'
export default defineComponent({
name: 'function-manage',
setup() {
const { variables, getTableData } = useTable()
const requestData = () => {
getTableData({
id: variables.id,
pageSize: variables.pageSize,
pageNo: variables.page,
searchVal: variables.searchVal
})
}
const handleUpdateList = () => {
requestData()
}
const handleChangePageSize = () => {
variables.page = 1
requestData()
}
const handleSearch = () => {
variables.page = 1
requestData()
}
const handleShowModal = (showRef: Ref<Boolean>) => {
showRef.value = true
}
const handleCreateFolder = () => {
variables.row = {}
handleShowModal(toRef(variables, 'showRef'))
}
onMounted(() => {
requestData()
})
return {
requestData,
handleSearch,
handleUpdateList,
handleCreateFolder,
handleChangePageSize,
...toRefs(variables)
}
},
render() {
const { t } = useI18n()
return (
<div class={styles.content}>
<Card class={styles.card}>
<div class={styles.header}>
<NSpace>
<NButton type='primary' onClick={this.handleCreateFolder}>
{t('resource.function.create_udf_function')}
</NButton>
</NSpace>
<div class={styles.right}>
<div class={styles.search}>
<div class={styles.list}>
<NButton type='primary' onClick={this.handleSearch}>
<NIcon>
<SearchOutlined />
</NIcon>
</NButton>
</div>
<div class={styles.list}>
<NInput
placeholder={t('resource.function.enter_keyword_tips')}
v-model={[this.searchVal, 'value']}
/>
</div>
</div>
</div>
</div>
</Card>
<Card title={t('resource.function.udf_function')}>
<NDataTable
columns={this.columns}
data={this.tableData}
striped
size={'small'}
class={styles.table}
/>
<div class={styles.pagination}>
<NPagination
v-model:page={this.page}
v-model:page-size={this.pageSize}
page-count={this.totalPage}
show-size-picker
page-sizes={[10, 30, 50]}
show-quick-jumper
onUpdatePage={this.requestData}
onUpdatePageSize={this.handleChangePageSize}
/>
</div>
</Card>
<FolderModal
v-model:row={this.row}
v-model:show={this.showRef}
onUpdateList={this.handleUpdateList}
/>
</div>
)
}
})

38
dolphinscheduler-ui-next/src/views/resource/udf/function/types.ts

@ -0,0 +1,38 @@
/*
* 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 interface IUdfFunctionParam {
id: number
pageSize: number
pageNo: number
searchVal: string | undefined
}
export interface IUdf {
id: number
userId: number
type: 'HIVE'
funcName: string
className: string
resourceId: number
resourceName: string
argTypes: string
database: string
description: string
createTime: string
updateTime: string
}

182
dolphinscheduler-ui-next/src/views/resource/udf/function/use-table.ts

@ -0,0 +1,182 @@
/*
* 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, reactive } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import type { Router } from 'vue-router'
import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
import { NSpace, NTooltip, NButton, NPopconfirm } from 'naive-ui'
import { EditOutlined, DeleteOutlined } from '@vicons/antd'
import { useAsyncState } from '@vueuse/core'
import {
queryUdfFuncListPaging,
deleteUdfFunc
} from '@/service/modules/resources'
import { IUdfFunctionParam } from './types'
export function useTable() {
const { t } = useI18n()
const router: Router = useRouter()
const columns: TableColumns<any> = [
{
title: t('resource.function.id'),
key: 'id',
width: 50,
render: (_row, index) => index + 1
},
{
title: t('resource.function.udf_function_name'),
key: 'funcName'
},
{
title: t('resource.function.class_name'),
key: 'className'
},
{
title: t('resource.function.type'),
key: 'type'
},
{
title: t('resource.function.description'),
key: 'description'
},
{
title: t('resource.function.jar_package'),
key: 'resourceName'
},
{
title: t('resource.function.update_time'),
key: 'updateTime'
},
{
title: t('resource.function.operation'),
key: 'operation',
render: (row) => {
return h(NSpace, null, {
default: () => [
h(
NTooltip,
{},
{
trigger: () =>
h(
NButton,
{
circle: true,
type: 'info',
size: 'tiny',
onClick: () => {
handleEdit(row)
}
},
{
icon: () => h(EditOutlined)
}
),
default: () => t('resource.function.edit')
}
),
h(
NPopconfirm,
{
onPositiveClick: () => {
handleDelete(row.id)
}
},
{
trigger: () =>
h(
NTooltip,
{},
{
trigger: () =>
h(
NButton,
{
circle: true,
type: 'error',
size: 'tiny'
},
{
icon: () => h(DeleteOutlined)
}
),
default: () => t('resource.function.delete')
}
),
default: () => t('resource.function.delete_confirm')
}
)
]
})
}
}
]
const variables = reactive({
columns,
row: {},
tableData: [],
id: ref(Number(router.currentRoute.value.params.id) || -1),
page: ref(1),
pageSize: ref(10),
searchVal: ref(),
totalPage: ref(1),
showRef: ref(false)
})
const getTableData = (params: IUdfFunctionParam) => {
const { state } = useAsyncState(
queryUdfFuncListPaging({ ...params }).then((res: any) => {
variables.totalPage = res.totalPage
variables.tableData = res.totalList.map((item: any) => {
return { ...item }
})
}),
{ total: 0, table: [] }
)
return state
}
const handleEdit = (row: any) => {
variables.showRef = true
variables.row = row
}
const handleDelete = (id: number) => {
/* after deleting data from the current page, you need to jump forward when the page is empty. */
if (variables.tableData.length === 1 && variables.page > 1) {
variables.page -= 1
}
deleteUdfFunc(id).then(() =>
getTableData({
id: variables.id,
pageSize: variables.pageSize,
pageNo: variables.page,
searchVal: variables.searchVal
})
)
}
return {
variables,
getTableData
}
}
Loading…
Cancel
Save