Browse Source

[Refactor][UI Next][V1.0.0-Alpha] Refactor the list of projects under the project module (#8738)

3.0.0/version-upgrade
labbomb 2 years ago committed by GitHub
parent
commit
a6bfb5847e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 89
      dolphinscheduler-ui-next/src/views/projects/list/components/project-modal.tsx
  2. 121
      dolphinscheduler-ui-next/src/views/projects/list/components/table-action.tsx
  3. 40
      dolphinscheduler-ui-next/src/views/projects/list/components/use-form.ts
  4. 176
      dolphinscheduler-ui-next/src/views/projects/list/index.tsx
  5. 201
      dolphinscheduler-ui-next/src/views/projects/list/use-table.ts

89
dolphinscheduler-ui-next/src/views/projects/list/components/project-modal.tsx

@ -15,84 +15,95 @@
* limitations under the License.
*/
import { defineComponent, PropType, toRefs, onMounted } from 'vue'
import { defineComponent, PropType, toRefs, onMounted, watch } from 'vue'
import { NForm, NFormItem, NInput } from 'naive-ui'
import { useForm } from '../use-form'
import { useForm } from './use-form'
import Modal from '@/components/modal'
import { createProject, updateProject } from '@/service/modules/projects'
const props = {
show: {
showModalRef: {
type: Boolean as PropType<boolean>,
default: false
},
data: {
type: Object as PropType<any>
},
status: {
statusRef: {
type: Number as PropType<number>,
default: 0
},
row: {
type: Object as PropType<any>,
default: {}
}
}
const ProjectModal = defineComponent({
name: 'ProjectModal',
props,
emits: ['confirm', 'cancel'],
setup(props, { emit }) {
const { state, t } = useForm()
emits: ['cancelModal', 'confirmModal'],
setup(props, ctx) {
const { variables, t, handleValidate } = useForm(props, ctx)
onMounted(() => {
if (props.status === 1) {
state.projectForm.projectName = props.data.projectName
state.projectForm.description = props.data.description
const cancelModal = () => {
if (props.statusRef === 0) {
variables.model.projectName = ''
variables.model.description = ''
}
})
const onConfirm = () => {
;(props.status === 1
? updateProject(state.projectForm, props.data.code)
: createProject(state.projectForm)
).then(() => {
emit('confirm')
})
ctx.emit('cancelModal', props.showModalRef)
}
const onCancel = () => {
state.projectForm.projectName = ''
state.projectForm.description = ''
state.projectForm.userName = ''
emit('cancel')
const confirmModal = () => {
handleValidate(props.statusRef)
}
return { ...toRefs(state), t, onConfirm, onCancel }
watch(
() => props.statusRef,
() => {
if (props.statusRef === 0) {
variables.model.projectName = ''
variables.model.description = ''
} else {
variables.model.projectName = props.row.name
variables.model.description = props.row.description
}
}
)
watch(
() => props.row,
() => {
variables.model.projectName = props.row.name
variables.model.description = props.row.description
}
)
return { ...toRefs(variables), t, cancelModal, confirmModal }
},
render() {
const { t, onConfirm, onCancel, show, status } = this
const { t } = this
return (
<Modal
title={
status === 0
this.statusRef === 0
? t('project.list.create_project')
: t('project.list.edit_project')
}
show={show}
onConfirm={onConfirm}
onCancel={onCancel}
show={this.showModalRef}
onConfirm={this.confirmModal}
onCancel={this.cancelModal}
confirmDisabled={
!this.projectForm.projectName || !this.projectForm.userName
!this.model.projectName || !this.model.userName
}
>
<NForm rules={this.rules} ref='projectFormRef'>
<NFormItem label={t('project.list.project_name')} path='projectName'>
<NInput
v-model={[this.projectForm.projectName, 'value']}
v-model={[this.model.projectName, 'value']}
placeholder={t('project.list.project_tips')}
/>
</NFormItem>
<NFormItem label={t('project.list.owned_users')} path='userName'>
<NInput
v-model={[this.projectForm.userName, 'value']}
disabled={this.statusRef === 0}
v-model={[this.model.userName, 'value']}
placeholder={t('project.list.username_tips')}
/>
</NFormItem>
@ -101,7 +112,7 @@ const ProjectModal = defineComponent({
path='description'
>
<NInput
v-model={[this.projectForm.description, 'value']}
v-model={[this.model.description, 'value']}
type='textarea'
placeholder={t('project.list.description_tips')}
/>

121
dolphinscheduler-ui-next/src/views/projects/list/components/table-action.tsx

@ -1,121 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { defineComponent, PropType } from 'vue'
import { useI18n } from 'vue-i18n'
import { NSpace, NTooltip, NButton, NIcon, NPopconfirm } from 'naive-ui'
import { DeleteOutlined, EditOutlined, InfoCircleFilled } from '@vicons/antd'
import { deleteProject } from '@/service/modules/projects'
import type { ProjectList } from '@/service/modules/projects/types'
interface ProjectRow extends ProjectList {
index: number
}
const props = {
row: {
type: Object as PropType<ProjectRow>,
default: {}
}
}
const TableAction = defineComponent({
name: 'TableAction',
props,
emits: ['resetTableData', 'updateProjectItem'],
setup(props, { emit }) {
const { t } = useI18n()
const handleEditProject = (
code: number,
projectName: string,
description: string
) => {
emit('updateProjectItem', code, projectName, description)
}
const handleDeleteProject = (code: number) => {
deleteProject(code).then(() => {
emit('resetTableData')
})
}
return { t, handleEditProject, handleDeleteProject }
},
render() {
const { t, handleEditProject, handleDeleteProject } = this
return (
<NSpace>
<NTooltip trigger={'hover'}>
{{
default: () => t('project.list.edit'),
trigger: () => (
<NButton
size='small'
type='info'
tag='div'
onClick={() =>
handleEditProject(
this.row.code,
this.row.name,
this.row.description
)
}
circle
>
<NIcon>
<EditOutlined />
</NIcon>
</NButton>
)
}}
</NTooltip>
<NTooltip trigger={'hover'}>
{{
default: () => t('project.list.delete'),
trigger: () => (
<NButton size='small' type='error' circle>
<NPopconfirm
positive-text={t('project.list.confirm')}
negative-text={t('project.list.cancel')}
onPositiveClick={() => handleDeleteProject(this.row.code)}
>
{{
default: () => t('project.list.delete_confirm'),
icon: () => (
<NIcon>
<InfoCircleFilled />
</NIcon>
),
trigger: () => (
<NIcon>
<DeleteOutlined />
</NIcon>
)
}}
</NPopconfirm>
</NButton>
)
}}
</NTooltip>
</NSpace>
)
}
})
export default TableAction

40
dolphinscheduler-ui-next/src/views/projects/list/use-form.ts → dolphinscheduler-ui-next/src/views/projects/list/components/use-form.ts

@ -16,18 +16,22 @@
*/
import { useI18n } from 'vue-i18n'
import { reactive, ref } from 'vue'
import { reactive, ref, SetupContext } from 'vue'
import { useUserStore } from '@/store/user/user'
import type { FormRules } from 'naive-ui'
import type { UserInfoRes } from '@/service/modules/users/types'
import { createProject, updateProject } from '@/service/modules/projects'
export function useForm() {
export function useForm(
props: any,
ctx: SetupContext<('cancelModal' | 'confirmModal')[]>
) {
const { t } = useI18n()
const userStore = useUserStore()
const state = reactive({
const variables = reactive({
projectFormRef: ref(),
projectForm: {
model: {
projectName: '',
description: '',
userName: (userStore.getUserInfo as UserInfoRes).userName
@ -37,7 +41,7 @@ export function useForm() {
required: true,
trigger: ['input', 'blur'],
validator() {
if (state.projectForm.projectName === '') {
if (variables.model.projectName === '') {
return new Error(t('project.list.project_tips'))
}
}
@ -46,7 +50,7 @@ export function useForm() {
required: true,
trigger: ['input', 'blur'],
validator() {
if (state.projectForm.userName === '') {
if (variables.model.userName === '') {
return new Error(t('project.list.username_tips'))
}
}
@ -54,5 +58,27 @@ export function useForm() {
} as FormRules
})
return { state, t }
const handleValidate = (statusRef: number) => {
variables.projectFormRef.validate((errors: any) => {
if (!errors) {
statusRef === 0 ? submitProjectModal() : updateProjectModal()
} else {
return
}
})
}
const submitProjectModal = () => {
createProject(variables.model).then(() => {
ctx.emit('confirmModal', props.showModalRef)
})
}
const updateProjectModal = () => {
updateProject(variables.model, props.row.code).then(() => {
ctx.emit('confirmModal', props.showModalRef)
})
}
return { variables, t, handleValidate }
}

176
dolphinscheduler-ui-next/src/views/projects/list/index.tsx

@ -15,34 +15,21 @@
* limitations under the License.
*/
import { defineComponent, onMounted, ref, toRefs, reactive } from 'vue'
import {
NCard,
NButton,
NInput,
NIcon,
NDataTable,
NPagination
} from 'naive-ui'
import Card from '@/components/card'
import { SearchOutlined } from '@vicons/antd'
import { NButton, NCard, NDataTable, NIcon, NInput, NPagination, NSpace } from 'naive-ui'
import { defineComponent, onMounted, ref, toRefs, reactive, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useTable } from './use-table'
import styles from './index.module.scss'
import Card from '@/components/card'
import ProjectModal from './components/project-modal'
import styles from './index.module.scss'
import { useTable } from './use-table'
const list = defineComponent({
name: 'list',
setup() {
const showModalRef = ref(false)
const modelStatusRef = ref(0)
const { t } = useI18n()
const { variables, getTableData } = useTable()
let updateProjectData = reactive({
code: 0,
projectName: '',
description: ''
})
const { variables, getTableData, createColumns } = useTable()
const requestData = () => {
getTableData({
@ -52,120 +39,68 @@ const list = defineComponent({
})
}
const onCancel = () => {
showModalRef.value = false
const handleModalChange = () => {
variables.showModalRef = true
variables.statusRef = 0
}
const onConfirm = () => {
showModalRef.value = false
updateProjectData = {
code: 0,
projectName: '',
description: ''
}
resetTableData()
}
const onOpen = () => {
modelStatusRef.value = 0
showModalRef.value = true
const handleSearch = () => {
variables.page = 1
requestData()
}
const resetTableData = () => {
getTableData({
pageSize: variables.pageSize,
pageNo: variables.page,
searchVal: variables.searchVal
})
const onCancelModal = () => {
variables.showModalRef = false
}
const onSearch = () => {
variables.page = 1
getTableData({
pageSize: variables.pageSize,
pageNo: variables.page,
searchVal: variables.searchVal
})
const onConfirmModal = () => {
variables.showModalRef = false
requestData()
}
const onUpdatePageSize = () => {
const handleChangePageSize = () => {
variables.page = 1
resetTableData()
}
const updateProjectItem = (
code: number,
projectName: string,
description: string
) => {
modelStatusRef.value = 1
showModalRef.value = true
updateProjectData.code = code
updateProjectData.projectName = projectName
updateProjectData.description = description
requestData()
}
onMounted(() => {
createColumns(variables)
requestData()
})
return {
t,
showModalRef,
...toRefs(variables),
onCancel,
onConfirm,
onOpen,
updateProjectItem,
resetTableData,
onUpdatePageSize,
onSearch,
updateProjectData,
modelStatusRef
}
watch(useI18n().locale, () => {
createColumns(variables)
})
return { t, ...toRefs(variables), requestData, handleModalChange, handleSearch, onCancelModal, onConfirmModal, handleChangePageSize }
},
render() {
const {
t,
showModalRef,
onCancel,
onConfirm,
onOpen,
updateProjectItem,
resetTableData,
onUpdatePageSize,
onSearch,
updateProjectData,
modelStatusRef
} = this
const { columns } = useTable(updateProjectItem, resetTableData)
const { t } = this
return (
<div>
<NCard>
<div class={styles['search-card']}>
<div>
<NButton size='small' type='primary' onClick={onOpen}>
{t('project.list.create_project')}
</NButton>
</div>
<div class={styles.box}>
<NButton
size='small'
onClick={this.handleModalChange}
type='primary'
class='btn-create-tenant'
>
{t('project.list.create_project')}
</NButton>
<NSpace>
<NInput
size='small'
v-model:value={this.searchVal}
v-model={[this.searchVal, 'value']}
placeholder={t('project.list.project_tips')}
clearable
/>
<NButton size='small' type='primary' onClick={onSearch}>
{{
icon: () => (
<NIcon>
<SearchOutlined />
</NIcon>
)
}}
<NButton size='small' type='primary' onClick={this.handleSearch}>
<NIcon>
<SearchOutlined />
</NIcon>
</NButton>
</div>
</NSpace>
</div>
</NCard>
<Card
@ -173,10 +108,9 @@ const list = defineComponent({
class={styles['table-card']}
>
<NDataTable
columns={columns}
size={'small'}
columns={this.columns}
data={this.tableData}
striped
row-class-name='items'
/>
<div class={styles.pagination}>
<NPagination
@ -186,23 +120,21 @@ const list = defineComponent({
show-size-picker
page-sizes={[10, 30, 50]}
show-quick-jumper
onUpdatePage={resetTableData}
onUpdatePageSize={onUpdatePageSize}
onUpdatePage={this.requestData}
onUpdatePageSize={this.handleChangePageSize}
/>
</div>
</Card>
{showModalRef && (
<ProjectModal
show={showModalRef}
onCancel={onCancel}
onConfirm={onConfirm}
data={updateProjectData}
status={modelStatusRef}
/>
)}
<ProjectModal
showModalRef={this.showModalRef}
statusRef={this.statusRef}
row={this.row}
onCancelModal={this.onCancelModal}
onConfirmModal={this.onConfirmModal}
/>
</div>
)
}
})
export default list
export default list

201
dolphinscheduler-ui-next/src/views/projects/list/use-table.ts

@ -19,90 +19,161 @@ import { h, reactive, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAsyncState } from '@vueuse/core'
import { queryProjectListPaging } from '@/service/modules/projects'
import { parseTime } from '@/utils/common'
import { deleteProject } from '@/service/modules/projects'
import { format } from 'date-fns'
import { useRouter } from 'vue-router'
import { useMenuStore } from '@/store/menu/menu'
import { NEllipsis } from 'naive-ui'
import TableAction from './components/table-action'
import { parseTime } from '@/utils/common'
import { NButton, NEllipsis, NIcon, NPopconfirm, NSpace, NTooltip } from 'naive-ui'
import type { Router } from 'vue-router'
import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
import type { ProjectRes } from '@/service/modules/projects/types'
import { DeleteOutlined, EditOutlined } from '@vicons/antd'
export function useTable(
updateProjectItem = (
unusedCode: number,
unusedName: string,
unusedDescription: string
): void => {},
resetTableData = () => {}
) {
export function useTable() {
const { t } = useI18n()
const router: Router = useRouter()
const menuStore = useMenuStore()
const columns: TableColumns<any> = [
{ title: '#', key: 'index', render: (row, index) => index + 1 },
{
title: t('project.list.project_name'),
key: 'name',
render: (row) =>
h(
NEllipsis,
{ style: 'max-width: 200px; color: #2080f0' },
{
default: () =>
const handleEdit = (row: any) => {
variables.showModalRef = true
variables.statusRef = 1
variables.row = row
}
const handleDelete = (row: any) => {
deleteProject(row.code).then(() => {
getTableData({
pageSize: variables.pageSize,
pageNo:
variables.tableData.length === 1 && variables.page > 1
? variables.page - 1
: variables.page,
searchVal: variables.searchVal
})
})
}
const createColumns = (variables: any) => {
variables.columns = [
{ title: '#', key: 'index', render: (row: any, index: number) => index + 1 },
{
title: t('project.list.project_name'),
key: 'name',
render: (row: { code: string; name: any }) =>
h(
NEllipsis,
{ style: 'max-width: 200px; color: #2080f0' },
{
default: () =>
h(
'a',
{
onClick: () => {
menuStore.setProjectCode(row.code)
router.push({ path: `/projects/${row.code}` })
}
},
{
default: () => {
return row.name
}
}
),
tooltip: () => row.name
}
)
},
{ title: t('project.list.owned_users'), key: 'userName' },
{ title: t('project.list.workflow_define_count'), key: 'defCount' },
{
title: t('project.list.process_instance_running_count'),
key: 'instRunningCount'
},
{ title: t('project.list.description'), key: 'description' },
{ title: t('project.list.create_time'), key: 'createTime' },
{ title: t('project.list.update_time'), key: 'updateTime' },
{
title: t('project.list.operation'),
key: 'actions',
render(row: any) {
return h(NSpace, null, {
default: () => [
h(
'a',
NTooltip,
{},
{
onClick: () => {
menuStore.setProjectCode(row.code)
router.push({ path: `/projects/${row.code}` })
trigger: () =>
h(
NButton,
{
circle: true,
type: 'info',
size: 'small',
class: 'edit',
onClick: () => {
handleEdit(row)
}
},
{
icon: () =>
h(NIcon, null, { default: () => h(EditOutlined) })
}
),
default: () => t('project.list.edit')
}
),
h(
NPopconfirm,
{
onPositiveClick: () => {
handleDelete(row)
}
},
{
default: () => {
return row.name
}
trigger: () =>
h(
NTooltip,
{},
{
trigger: () =>
h(
NButton,
{
circle: true,
type: 'error',
size: 'small',
class: 'delete'
},
{
icon: () =>
h(NIcon, null, {
default: () => h(DeleteOutlined)
})
}
),
default: () => t('project.list.delete')
}
),
default: () => t('project.list.delete_confirm')
}
),
tooltip: () => row.name
}
)
},
{ title: t('project.list.owned_users'), key: 'userName' },
{ title: t('project.list.workflow_define_count'), key: 'defCount' },
{
title: t('project.list.process_instance_running_count'),
key: 'instRunningCount'
},
{ title: t('project.list.description'), key: 'description' },
{ title: t('project.list.create_time'), key: 'createTime' },
{ title: t('project.list.update_time'), key: 'updateTime' },
{
title: t('project.list.operation'),
key: 'actions',
render: (row: any) =>
h(TableAction, {
row,
onResetTableData: () => {
if (variables.page > 1 && variables.tableData.length === 1) {
variables.page -= 1
}
resetTableData()
},
onUpdateProjectItem: (code, name, description) =>
updateProjectItem(code, name, description)
})
}
]
)
]
})
}
}
]
}
const variables = reactive({
columns: [],
tableData: [],
page: ref(1),
pageSize: ref(10),
searchVal: ref(null),
totalPage: ref(1)
totalPage: ref(1),
showModalRef: ref(false),
statusRef: ref(0),
row: {}
})
const getTableData = (params: any) => {
@ -128,5 +199,9 @@ export function useTable(
return state
}
return { getTableData, variables, columns }
return {
variables,
getTableData,
createColumns
}
}

Loading…
Cancel
Save