Browse Source

[Feature][UI Next] Feat worker group manage (#8087)

* [Feature][UI Next] Add worker group manage.

* [Feature][UI Next] Add worker group manage table tag.
3.0.0/version-upgrade
songjianet 3 years ago committed by GitHub
parent
commit
2a773802ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      dolphinscheduler-ui-next/src/locales/modules/en_US.ts
  2. 16
      dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
  3. 8
      dolphinscheduler-ui-next/src/router/modules/security.ts
  4. 5
      dolphinscheduler-ui-next/src/service/modules/worker-groups/index.ts
  5. 20
      dolphinscheduler-ui-next/src/service/modules/worker-groups/types.ts
  6. 120
      dolphinscheduler-ui-next/src/views/security/worker-group-manage/components/use-modal.ts
  7. 142
      dolphinscheduler-ui-next/src/views/security/worker-group-manage/components/worker-group-modal.tsx
  8. 43
      dolphinscheduler-ui-next/src/views/security/worker-group-manage/index.module.scss
  9. 158
      dolphinscheduler-ui-next/src/views/security/worker-group-manage/index.tsx
  10. 193
      dolphinscheduler-ui-next/src/views/security/worker-group-manage/use-table.ts

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

@ -326,6 +326,21 @@ const security = {
edit: 'Edit',
delete: 'Delete'
},
worker_group: {
create_worker_group: 'Create Worker Group',
edit_worker_group: 'Edit Worker Group',
search_tips: 'Please enter keywords',
operation: 'Operation',
delete_confirm: 'Delete?',
edit: 'Edit',
delete: 'Delete',
group_name: 'Group Name',
group_name_tips: 'Please enter your group name',
worker_addresses: 'Worker Addresses',
worker_addresses_tips: 'Please select worker addresses',
create_time: 'Create Time',
update_time: 'Update Time'
},
yarn_queue: {
create_queue: 'Create Queue',
edit_queue: 'Edit Queue',

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

@ -321,12 +321,26 @@ const security = {
alarm_group_description: '告警组描述',
create_time: '创建时间',
update_time: '更新时间',
actions: '操作',
operation: '操作',
delete_confirm: '确定删除吗?',
edit: '编辑',
delete: '删除'
},
worker_group: {
create_worker_group: '创建Worker分组',
edit_worker_group: '编辑Worker分组',
search_tips: '请输入关键词',
operation: '操作',
delete_confirm: '确定删除吗?',
edit: '编辑',
delete: '删除',
group_name: '分组名称',
group_name_tips: '请输入分组名称',
worker_addresses: 'Worker地址',
worker_addresses_tips: '请选择Worker地址',
create_time: '创建时间',
update_time: '更新时间'
},
yarn_queue: {
create_queue: '创建队列',
edit_queue: '编辑队列',

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

@ -53,6 +53,14 @@ export default {
title: '告警组管理'
}
},
{
path: '/security/worker-group-manage',
name: 'worker-group-manage',
component: components['worker-group-manage'],
meta: {
title: 'Worker分组管理'
}
},
{
path: '/security/yarn-queue-manage',
name: 'yarn-queue-manage',

5
dolphinscheduler-ui-next/src/service/modules/worker-groups/index.ts

@ -50,7 +50,8 @@ export function queryWorkerAddressList(): any {
export function deleteById(id: IdReq): any {
return axios({
url: `/worker-groups/${id}`,
method: 'delete'
url: `/worker-groups/${id.id}`,
method: 'delete',
params: id
})
}

20
dolphinscheduler-ui-next/src/service/modules/worker-groups/types.ts

@ -31,4 +31,22 @@ interface IdReq {
id: number
}
export { ListReq, WorkerGroupReq, IdReq }
interface WorkerGroupItem {
id: number
name: string
addrList: string
createTime: string
updateTime: string
systemDefault: boolean
}
interface WorkerGroupRes {
totalList: WorkerGroupItem[]
total: number
totalPage: number
pageSize: number
currentPage: number
start: number
}
export { ListReq, WorkerGroupReq, IdReq, WorkerGroupItem, WorkerGroupRes }

120
dolphinscheduler-ui-next/src/views/security/worker-group-manage/components/use-modal.ts

@ -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 { reactive, ref, SetupContext } from 'vue'
import { useI18n } from 'vue-i18n'
import { useAsyncState } from '@vueuse/core'
import {
queryWorkerAddressList,
saveWorkerGroup
} from '@/service/modules/worker-groups'
export function useModal(
props: any,
ctx: SetupContext<('cancelModal' | 'confirmModal')[]>
) {
const { t } = useI18n()
const variables = reactive({
workerGroupFormRef: ref(),
model: {
id: ref<number>(-1),
name: ref(''),
addrList: ref<Array<number>>([]),
generalOptions: []
},
rules: {
name: {
required: true,
trigger: ['input', 'blur'],
validator() {
if (variables.model.name === '') {
return new Error(t('security.worker_group.group_name_tips'))
}
}
},
addrList: {
required: true,
trigger: ['input', 'blur'],
validator() {
if (variables.model.addrList.length < 1) {
return new Error(t('security.worker_group.worker_addresses_tips'))
}
}
}
}
})
const getListData = () => {
const { state } = useAsyncState(
queryWorkerAddressList().then((res: Array<string>) => {
variables.model.generalOptions = res.map(
(item): { label: string; value: string } => {
return {
label: item,
value: item
}
}
) as any
}),
{}
)
return state
}
const handleValidate = (statusRef: number) => {
variables.workerGroupFormRef.validate((errors: any) => {
if (!errors) {
statusRef === 0 ? submitWorkerGroupModal() : updateWorkerGroupModal()
} else {
return
}
})
}
const submitWorkerGroupModal = () => {
const data = {
name: variables.model.name,
addrList: variables.model.addrList.toString()
}
saveWorkerGroup(data).then(() => {
variables.model.name = ''
variables.model.addrList = []
ctx.emit('confirmModal', props.showModalRef)
})
}
const updateWorkerGroupModal = () => {
const data = {
id: variables.model.id,
name: variables.model.name,
addrList: variables.model.addrList.toString()
}
saveWorkerGroup(data).then(() => {
ctx.emit('confirmModal', props.showModalRef)
})
}
return {
variables,
handleValidate,
getListData
}
}

142
dolphinscheduler-ui-next/src/views/security/worker-group-manage/components/worker-group-modal.tsx

@ -0,0 +1,142 @@
/*
* 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, toRefs, watch } from 'vue'
import Modal from '@/components/modal'
import { NForm, NFormItem, NInput, NSelect } from 'naive-ui'
import { useModal } from './use-modal'
import { useI18n } from 'vue-i18n'
const WorkerGroupModal = defineComponent({
name: 'WorkerQueueModal',
props: {
showModalRef: {
type: Boolean as PropType<boolean>,
default: false
},
statusRef: {
type: Number as PropType<number>,
default: 0
},
row: {
type: Object as PropType<any>,
default: {}
}
},
emits: ['cancelModal', 'confirmModal'],
setup(props, ctx) {
const { variables, handleValidate, getListData } = useModal(props, ctx)
const { t } = useI18n()
const cancelModal = () => {
if (props.statusRef === 0) {
variables.model.name = ''
variables.model.addrList = []
}
ctx.emit('cancelModal', props.showModalRef)
}
const confirmModal = () => {
handleValidate(props.statusRef)
}
watch(
() => props.showModalRef,
() => {
props.showModalRef && getListData()
}
)
watch(
() => props.statusRef,
() => {
if (props.statusRef === 0) {
variables.model.name = ''
variables.model.addrList = []
} else {
variables.model.id = props.row.id
variables.model.name = props.row.name
variables.model.addrList = props.row.addrList.split(',')
}
}
)
watch(
() => props.row,
() => {
variables.model.id = props.row.id
variables.model.name = props.row.name
variables.model.addrList = props.row.addrList.split(',')
}
)
return { t, ...toRefs(variables), cancelModal, confirmModal }
},
render() {
const { t } = this
return (
<div>
<Modal
title={
this.statusRef === 0
? t('security.worker_group.create_worker_group')
: t('security.worker_group.edit_worker_group')
}
show={this.showModalRef}
onCancel={this.cancelModal}
onConfirm={this.confirmModal}
confirmDisabled={!this.model.name || this.model.addrList.length < 1}
>
{{
default: () => (
<NForm
model={this.model}
rules={this.rules}
ref='workerGroupFormRef'
>
<NFormItem
label={t('security.worker_group.group_name')}
path='name'
>
<NInput
placeholder={t('security.worker_group.group_name_tips')}
v-model={[this.model.name, 'value']}
/>
</NFormItem>
<NFormItem
label={t('security.worker_group.worker_addresses')}
path='addrList'
>
<NSelect
multiple
placeholder={t(
'security.worker_group.worker_addresses_tips'
)}
options={this.model.generalOptions}
v-model={[this.model.addrList, 'value']}
/>
</NFormItem>
</NForm>
)
}}
</Modal>
</div>
)
}
})
export default WorkerGroupModal

43
dolphinscheduler-ui-next/src/views/security/worker-group-manage/index.module.scss

@ -0,0 +1,43 @@
/*
* 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.
*/
.search-card {
display: flex;
justify-content: space-between;
align-items: center;
.box {
display: flex;
justify-content: flex-end;
align-items: center;
width: 300px;
button {
margin-left: 10px;
}
}
}
.table-card {
margin-top: 8px;
.pagination {
margin-top: 20px;
display: flex;
justify-content: center;
}
}

158
dolphinscheduler-ui-next/src/views/security/worker-group-manage/index.tsx

@ -0,0 +1,158 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { defineComponent, onMounted, toRefs, watch } from 'vue'
import {
NButton,
NCard,
NDataTable,
NIcon,
NInput,
NPagination
} from 'naive-ui'
import { SearchOutlined } from '@vicons/antd'
import { useI18n } from 'vue-i18n'
import { useTable } from './use-table'
import Card from '@/components/card'
import WorkerGroupModal from './components/worker-group-modal'
import styles from './index.module.scss'
const workerGroupManage = defineComponent({
name: 'worker-group-manage',
setup() {
const { t } = useI18n()
const { variables, getTableData, createColumns } = useTable()
const requestData = () => {
getTableData({
pageSize: variables.pageSize,
pageNo: variables.page,
searchVal: variables.searchVal
})
}
const onUpdatePageSize = () => {
variables.page = 1
requestData()
}
const onSearch = () => {
variables.page = 1
requestData()
}
const handleModalChange = () => {
variables.showModalRef = true
variables.statusRef = 0
}
const onCancelModal = () => {
variables.showModalRef = false
}
const onConfirmModal = () => {
variables.showModalRef = false
requestData()
}
onMounted(() => {
createColumns(variables)
requestData()
})
watch(useI18n().locale, () => {
createColumns(variables)
})
return {
t,
...toRefs(variables),
requestData,
onCancelModal,
onConfirmModal,
onUpdatePageSize,
handleModalChange,
onSearch
}
},
render() {
const {
t,
requestData,
onUpdatePageSize,
onCancelModal,
onConfirmModal,
handleModalChange,
onSearch
} = this
return (
<div>
<NCard>
<div class={styles['search-card']}>
<div>
<NButton size='small' type='primary' onClick={handleModalChange}>
{t('security.worker_group.create_worker_group')}
</NButton>
</div>
<div class={styles.box}>
<NInput
size='small'
clearable
v-model={[this.searchVal, 'value']}
placeholder={t('security.worker_group.search_tips')}
/>
<NButton size='small' type='primary' onClick={onSearch}>
{{
icon: () => (
<NIcon>
<SearchOutlined />
</NIcon>
)
}}
</NButton>
</div>
</div>
</NCard>
<Card class={styles['table-card']}>
<NDataTable columns={this.columns} data={this.tableData} />
<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={requestData}
onUpdatePageSize={onUpdatePageSize}
/>
</div>
</Card>
<WorkerGroupModal
showModalRef={this.showModalRef}
statusRef={this.statusRef}
row={this.row}
onCancelModal={onCancelModal}
onConfirmModal={onConfirmModal}
/>
</div>
)
}
})
export default workerGroupManage

193
dolphinscheduler-ui-next/src/views/security/worker-group-manage/use-table.ts

@ -0,0 +1,193 @@
/*
* 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 { useAsyncState } from '@vueuse/core'
import { reactive, h, ref } from 'vue'
import { NButton, NPopconfirm, NSpace, NTag, NTooltip } from 'naive-ui'
import { useI18n } from 'vue-i18n'
import { DeleteOutlined, EditOutlined } from '@vicons/antd'
import {
queryAllWorkerGroupsPaging,
deleteById
} from '@/service/modules/worker-groups'
import type {
WorkerGroupRes,
WorkerGroupItem
} from '@/service/modules/worker-groups/types'
export function useTable() {
const { t } = useI18n()
const handleEdit = (row: any) => {
variables.showModalRef = true
variables.statusRef = 1
variables.row = row
}
const createColumns = (variables: any) => {
variables.columns = [
{
title: '#',
key: 'index'
},
{
title: t('security.worker_group.group_name'),
key: 'name'
},
{
title: t('security.worker_group.worker_addresses'),
key: 'addrList',
render: (row: WorkerGroupItem) =>
h(NSpace, null, {
default: () =>
row.addrList
.split(',')
.map((item: string) =>
h(
NTag,
{ type: 'success', size: 'small' },
{ default: () => item }
)
)
})
},
{
title: t('security.worker_group.create_time'),
key: 'createTime'
},
{
title: t('security.worker_group.update_time'),
key: 'updateTime'
},
{
title: t('security.worker_group.operation'),
key: 'operation',
render(row: any) {
if (row.systemDefault) {
return false
}
return h(NSpace, null, {
default: () => [
h(
NTooltip,
{},
{
trigger: () =>
h(
NButton,
{
circle: true,
type: 'info',
size: 'small',
onClick: () => {
handleEdit(row)
}
},
{
icon: () => h(EditOutlined)
}
),
default: () => t('security.worker_group.edit')
}
),
h(
NPopconfirm,
{
onPositiveClick: () => {
handleDelete(row)
}
},
{
trigger: () =>
h(
NTooltip,
{},
{
trigger: () =>
h(
NButton,
{
circle: true,
type: 'error',
size: 'small'
},
{
icon: () => h(DeleteOutlined)
}
),
default: () => t('security.worker_group.delete')
}
),
default: () => t('security.worker_group.delete_confirm')
}
)
]
})
}
}
]
}
const variables = reactive({
columns: [],
tableData: [],
page: ref(1),
pageSize: ref(10),
searchVal: ref(null),
totalPage: ref(1),
showModalRef: ref(false),
statusRef: ref(0),
row: {}
})
const handleDelete = (row: any) => {
deleteById({ id: row.id }).then(() => {
getTableData({
pageSize: variables.pageSize,
pageNo:
variables.tableData.length === 1 && variables.page > 1
? variables.page - 1
: variables.page,
searchVal: variables.searchVal
})
})
}
const getTableData = (params: any) => {
const { state } = useAsyncState(
queryAllWorkerGroupsPaging({ ...params }).then((res: WorkerGroupRes) => {
variables.tableData = res.totalList.map((item, index) => {
return {
index: index + 1,
...item
}
}) as any
variables.totalPage = res.totalPage
}),
{}
)
return state
}
return {
variables,
getTableData,
createColumns
}
}
Loading…
Cancel
Save