You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dolphinscheduler.apache.org by zh...@apache.org on 2022/02/09 15:32:21 UTC
[dolphinscheduler] branch dev updated: [Feature][UI Next] DAG backfill (#8325)
This is an automated email from the ASF dual-hosted git repository.
zhongjiajie pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git
The following commit(s) were added to refs/heads/dev by this push:
new 480492d [Feature][UI Next] DAG backfill (#8325)
480492d is described below
commit 480492db732fc4511f50be9708727fdf040501e0
Author: wangyizhi <wa...@cmss.chinamobile.com>
AuthorDate: Wed Feb 9 23:32:11 2022 +0800
[Feature][UI Next] DAG backfill (#8325)
* [Feature][UI Next] Dag backfill
* [Feature][UI Next] Add license header
---
.../src/locales/modules/en_US.ts | 3 +-
.../src/locales/modules/zh_CN.ts | 3 +-
.../service/modules/process-definition/index.ts | 6 +-
.../src/views/projects/task/constants/task-type.ts | 4 +-
.../workflow/components/dag/dag-canvas.tsx | 42 ++-----
.../projects/workflow/components/dag/dag-hooks.ts | 20 ++--
.../workflow/components/dag/dag-sidebar.tsx | 36 ++----
.../workflow/components/dag/dag-toolbar.tsx | 111 ++++++++++++------
.../workflow/components/dag/dag.module.scss | 4 +
.../projects/workflow/components/dag/index.tsx | 83 ++++++++++----
.../projects/workflow/components/dag/types.ts | 95 ++++++++++++++++
.../workflow/components/dag/use-canvas-init.ts | 2 +-
.../dag/{use-node-search.ts => use-cell-query.ts} | 42 ++++---
.../workflow/components/dag/use-cell-update.ts | 76 +++++++++++++
...ph-operations.ts => use-custom-cell-builder.ts} | 126 ++++++++-------------
.../{use-canvas-drop.ts => use-dag-drag-drop.ts} | 46 ++++++--
.../{use-sidebar-drag.ts => use-graph-backfill.ts} | 36 +++---
.../workflow/components/dag/use-node-search.ts | 47 +++++---
.../dag/{use-sidebar-drag.ts => use-text-copy.ts} | 36 +++---
.../definition/components/version-modal.tsx | 6 +-
.../projects/workflow/definition/create/index.tsx | 7 +-
.../detail/{index.tsx => index.module.scss} | 32 ++++--
.../projects/workflow/definition/detail/index.tsx | 37 +++++-
.../views/projects/workflow/definition/index.tsx | 15 ++-
.../definition/{use-table.ts => use-table.tsx} | 25 ++--
25 files changed, 608 insertions(+), 332 deletions(-)
diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
index 206684b..1bd8caa 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
@@ -495,7 +495,8 @@ const project = {
grid_layout: 'Grid',
dagre_layout: 'Dagre',
rows: 'Rows',
- cols: 'Cols'
+ cols: 'Cols',
+ copy_success: 'Copy Success'
}
}
diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
index d9fe1bc..00cefaa 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
@@ -494,7 +494,8 @@ const project = {
grid_layout: '网格布局',
dagre_layout: '层次布局',
rows: '行数',
- cols: '列数'
+ cols: '列数',
+ copy_success: '复制成功'
}
}
diff --git a/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts b/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts
index c2a8885..a6d1313 100644
--- a/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/process-definition/index.ts
@@ -148,11 +148,11 @@ export function verifyName(params: NameReq, code: CodeReq): any {
}
export function queryProcessDefinitionByCode(
- code: CodeReq,
- processCode: CodeReq
+ code: number,
+ projectCode: number
): any {
return axios({
- url: `/projects/${code}/process-definition/${processCode}`,
+ url: `/projects/${projectCode}/process-definition/${code}`,
method: 'get'
})
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/task/constants/task-type.ts b/dolphinscheduler-ui-next/src/views/projects/task/constants/task-type.ts
index 260cbc9..52878ab 100644
--- a/dolphinscheduler-ui-next/src/views/projects/task/constants/task-type.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/task/constants/task-type.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-export const ALL_TASK_TYPES: any = {
+export const TASK_TYPES_MAP = {
SHELL: {
alias: 'SHELL'
},
@@ -65,3 +65,5 @@ export const ALL_TASK_TYPES: any = {
alias: 'WATERDROP'
}
}
+
+export type TaskType = keyof typeof TASK_TYPES_MAP
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-canvas.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-canvas.tsx
index 221bc8e..b6771f1 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-canvas.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-canvas.tsx
@@ -17,53 +17,33 @@
import { defineComponent, ref, inject } from 'vue'
import Styles from './dag.module.scss'
-import type { PropType, Ref } from 'vue'
-import type { Dragged } from './index'
-import { useCanvasInit, useCellActive, useCanvasDrop } from './dag-hooks'
-import { useRoute } from 'vue-router'
-
-const props = {
- dragged: {
- type: Object as PropType<Ref<Dragged>>,
- default: ref({
- x: 0,
- y: 0,
- type: ''
- })
- }
-}
+import { useCanvasInit, useCellActive } from './dag-hooks'
export default defineComponent({
name: 'workflow-dag-canvas',
- props,
+ emits: ['drop'],
setup(props, context) {
const readonly = inject('readonly', ref(false))
const graph = inject('graph', ref())
- const route = useRoute()
- const projectCode = route.params.projectCode as string
const { paper, minimap, container } = useCanvasInit({ readonly, graph })
// Change the style on cell hover and select
useCellActive({ graph })
-
- // Drop sidebar item in canvas
- const { onDrop, onDragenter, onDragover, onDragleave } = useCanvasDrop({
- readonly,
- dragged: props.dragged,
- graph,
- container,
- projectCode
- })
+ const preventDefault = (e: DragEvent) => {
+ e.preventDefault()
+ }
return () => (
<div
ref={container}
class={Styles.canvas}
- onDrop={onDrop}
- onDragenter={onDragenter}
- onDragover={onDragover}
- onDragleave={onDragleave}
+ onDrop={(e) => {
+ context.emit('drop', e)
+ }}
+ onDragenter={preventDefault}
+ onDragover={preventDefault}
+ onDragleave={preventDefault}
>
<div ref={paper} class={Styles.paper}></div>
<div ref={minimap} class={Styles.minimap}></div>
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-hooks.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-hooks.ts
index a2d57e2..303ae1f 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-hooks.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-hooks.ts
@@ -16,19 +16,25 @@
*/
import { useCanvasInit } from './use-canvas-init'
-import { useGraphOperations } from './use-graph-operations'
+import { useCellQuery } from './use-cell-query'
import { useCellActive } from './use-cell-active'
-import { useSidebarDrag } from './use-sidebar-drag'
-import { useCanvasDrop } from './use-canvas-drop'
+import { useCellUpdate } from './use-cell-update'
import { useNodeSearch } from './use-node-search'
import { useGraphAutoLayout } from './use-graph-auto-layout'
+import { useTextCopy } from './use-text-copy'
+import { useCustomCellBuilder } from './use-custom-cell-builder'
+import { useGraphBackfill } from './use-graph-backfill'
+import { useDagDragAndDrop } from './use-dag-drag-drop'
export {
useCanvasInit,
- useGraphOperations,
+ useCellQuery,
useCellActive,
- useSidebarDrag,
- useCanvasDrop,
useNodeSearch,
- useGraphAutoLayout
+ useGraphAutoLayout,
+ useTextCopy,
+ useCustomCellBuilder,
+ useGraphBackfill,
+ useCellUpdate,
+ useDagDragAndDrop
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-sidebar.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-sidebar.tsx
index 420d4eb..2ecd498 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-sidebar.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-sidebar.tsx
@@ -15,37 +15,17 @@
* limitations under the License.
*/
-import type { PropType, Ref } from 'vue'
-import type { Dragged } from './index'
-import { defineComponent, ref, inject } from 'vue'
-import { ALL_TASK_TYPES } from '../../../task/constants/task-type'
-import { useSidebarDrag } from './dag-hooks'
+import { defineComponent } from 'vue'
+import { TASK_TYPES_MAP, TaskType } from '../../../task/constants/task-type'
import Styles from './dag.module.scss'
-const props = {
- dragged: {
- type: Object as PropType<Ref<Dragged>>,
- default: ref({
- x: 0,
- y: 0,
- type: ''
- })
- }
-}
-
export default defineComponent({
name: 'workflow-dag-sidebar',
- props,
- setup(props) {
- const readonly = inject('readonly', ref(false))
- const dragged = props.dragged
- const { onDragStart } = useSidebarDrag({
- readonly,
- dragged
- })
- const allTaskTypes = Object.keys(ALL_TASK_TYPES).map((type) => ({
+ emits: ['dragStart'],
+ setup(props, context) {
+ const allTaskTypes = Object.keys(TASK_TYPES_MAP).map((type) => ({
type,
- ...ALL_TASK_TYPES[type]
+ ...TASK_TYPES_MAP[type as TaskType]
}))
return () => (
@@ -54,7 +34,9 @@ export default defineComponent({
<div
class={Styles.draggable}
draggable='true'
- onDragstart={(e) => onDragStart(e, task.type)}
+ onDragstart={(e) => {
+ context.emit('dragStart', e, task.type)
+ }}
>
<em
class={[
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-toolbar.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-toolbar.tsx
index b1081ce..1edcf19 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-toolbar.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag-toolbar.tsx
@@ -15,19 +15,29 @@
* limitations under the License.
*/
-import { defineComponent, ref, inject, PropType } from 'vue'
+import {
+ defineComponent,
+ ref,
+ inject,
+ PropType,
+ onMounted,
+ watch,
+ computed
+} from 'vue'
+import type { Ref } from 'vue'
import { useI18n } from 'vue-i18n'
import Styles from './dag.module.scss'
-import { NTooltip, NIcon, NButton, NSelect } from 'naive-ui'
+import { NTooltip, NIcon, NButton, NSelect, useMessage } from 'naive-ui'
import {
SearchOutlined,
DownloadOutlined,
FullscreenOutlined,
FullscreenExitOutlined,
InfoCircleOutlined,
- FormatPainterOutlined
+ FormatPainterOutlined,
+ CopyOutlined
} from '@vicons/antd'
-import { useNodeSearch } from './dag-hooks'
+import { useNodeSearch, useTextCopy, useCellQuery } from './dag-hooks'
import { DataUri } from '@antv/x6'
import { useFullscreen } from '@vueuse/core'
import { useRouter } from 'vue-router'
@@ -37,12 +47,19 @@ const props = {
layoutToggle: {
type: Function as PropType<(bool?: boolean) => void>,
default: () => {}
+ },
+ // If this prop is passed, it means from definition detail
+ definition: {
+ // The same as the structure responsed by the queryProcessDefinitionByCode api
+ type: Object as PropType<any>,
+ default: null
}
}
export default defineComponent({
name: 'workflow-dag-toolbar',
props,
+ emits: ['versionToggle'],
setup(props, context) {
const { t } = useI18n()
@@ -55,11 +72,11 @@ export default defineComponent({
* Node search and navigate
*/
const {
- searchNode,
- getAllNodes,
- allNodes,
+ navigateTo,
toggleSearchInput,
- searchInputVisible
+ searchInputVisible,
+ reQueryNodes,
+ nodesDropdown
} = useNodeSearch({ graph })
/**
@@ -94,7 +111,7 @@ export default defineComponent({
* Open workflow version modal
*/
const openVersionModal = () => {
- //TODO, same as the version popup in the workflow list page
+ context.emit('versionToggle', true)
}
/**
@@ -111,6 +128,11 @@ export default defineComponent({
router.go(-1)
}
+ /**
+ * Copy workflow name
+ */
+ const { copy } = useTextCopy()
+
return () => (
<div
class={[
@@ -118,7 +140,24 @@ export default defineComponent({
Styles[themeStore.darkTheme ? 'toolbar-dark' : 'toolbar-light']
]}
>
- <span class={Styles['workflow-name']}>{t('project.dag.create')}</span>
+ <div>
+ <span class={Styles['workflow-name']}>
+ {props.definition?.processDefinition?.name ||
+ t('project.dag.create')}
+ </span>
+ {props.definition?.processDefinition?.name && (
+ <NButton
+ quaternary
+ circle
+ onClick={() => copy(props.definition?.processDefinition?.name)}
+ class={Styles['copy-btn']}
+ >
+ <NIcon>
+ <CopyOutlined />
+ </NIcon>
+ </NButton>
+ )}
+ </div>
<div class={Styles['toolbar-right-part']}>
{/* Search node */}
<NTooltip
@@ -150,9 +189,9 @@ export default defineComponent({
>
<NSelect
size='small'
- options={allNodes.value}
- onFocus={getAllNodes}
- onUpdateValue={searchNode}
+ options={nodesDropdown.value}
+ onFocus={reQueryNodes}
+ onUpdateValue={navigateTo}
filterable
/>
</div>
@@ -233,28 +272,30 @@ export default defineComponent({
}}
></NTooltip>
{/* Version info */}
- <NTooltip
- v-slots={{
- trigger: () => (
- <NButton
- class={Styles['toolbar-right-item']}
- strong
- secondary
- circle
- type='info'
- onClick={openVersionModal}
- v-slots={{
- icon: () => (
- <NIcon>
- <InfoCircleOutlined />
- </NIcon>
- )
- }}
- />
- ),
- default: () => t('project.workflow.version_info')
- }}
- ></NTooltip>
+ {!!props.definition && (
+ <NTooltip
+ v-slots={{
+ trigger: () => (
+ <NButton
+ class={Styles['toolbar-right-item']}
+ strong
+ secondary
+ circle
+ type='info'
+ onClick={openVersionModal}
+ v-slots={{
+ icon: () => (
+ <NIcon>
+ <InfoCircleOutlined />
+ </NIcon>
+ )
+ }}
+ />
+ ),
+ default: () => t('project.workflow.version_info')
+ }}
+ ></NTooltip>
+ )}
{/* Save workflow */}
<NButton
class={Styles['toolbar-right-item']}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag.module.scss b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag.module.scss
index 7fae7ae..d338520 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag.module.scss
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/dag.module.scss
@@ -76,6 +76,10 @@ $bgLight: #ffffff;
font-size: 14px;
}
+.copy-btn {
+ margin-left: 5px;
+}
+
.draggable {
display: flex;
width: 100%;
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx
index fc4665e..6c54a8c 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/index.tsx
@@ -16,48 +16,48 @@
*/
import type { Graph } from '@antv/x6'
-import { defineComponent, ref, provide } from 'vue'
+import { defineComponent, ref, provide, PropType, toRef } from 'vue'
import DagToolbar from './dag-toolbar'
import DagCanvas from './dag-canvas'
import DagSidebar from './dag-sidebar'
import Styles from './dag.module.scss'
import DagAutoLayoutModal from './dag-auto-layout-modal'
-import { useGraphAutoLayout } from './dag-hooks'
+import {
+ useGraphAutoLayout,
+ useGraphBackfill,
+ useDagDragAndDrop
+} from './dag-hooks'
import { useThemeStore } from '@/store/theme/theme'
+import VersionModal from '../../definition/components/version-modal'
+import { WorkflowDefinition } from './types'
import './x6-style.scss'
-export interface Dragged {
- x: number
- y: number
- type: string
+const props = {
+ // If this prop is passed, it means from definition detail
+ definition: {
+ type: Object as PropType<WorkflowDefinition>,
+ default: undefined
+ },
+ readonly: {
+ type: Boolean as PropType<boolean>,
+ default: false
+ }
}
export default defineComponent({
name: 'workflow-dag',
+ props,
+ emits: ['refresh'],
setup(props, context) {
const theme = useThemeStore()
// Whether the graph can be operated
- const readonly = ref(false)
- provide('readonly', readonly)
+ provide('readonly', toRef(props, 'readonly'))
const graph = ref<Graph>()
provide('graph', graph)
- // The sidebar slots
- const toolbarSlots = {
- left: context.slots.toolbarLeft,
- right: context.slots.toolbarRight
- }
-
- // The element currently being dragged up
- const dragged = ref<Dragged>({
- x: 0,
- y: 0,
- type: ''
- })
-
- // Auto layout
+ // Auto layout modal
const {
visible: layoutVisible,
toggle: layoutToggle,
@@ -67,6 +67,28 @@ export default defineComponent({
cancel
} = useGraphAutoLayout({ graph })
+ const { onDragStart, onDrop } = useDagDragAndDrop({
+ graph,
+ readonly: toRef(props, 'readonly')
+ })
+
+ // backfill
+ useGraphBackfill({ graph, definition: toRef(props, 'definition') })
+
+ // version modal
+ const versionModalShow = ref(false)
+ const versionToggle = (bool: boolean) => {
+ if (typeof bool === 'boolean') {
+ versionModalShow.value = bool
+ } else {
+ versionModalShow.value = !versionModalShow.value
+ }
+ }
+ const refreshDetail = () => {
+ context.emit('refresh')
+ versionModalShow.value = false
+ }
+
return () => (
<div
class={[
@@ -74,10 +96,14 @@ export default defineComponent({
Styles[`dag-${theme.darkTheme ? 'dark' : 'light'}`]
]}
>
- <DagToolbar v-slots={toolbarSlots} layoutToggle={layoutToggle} />
+ <DagToolbar
+ layoutToggle={layoutToggle}
+ definition={props.definition}
+ onVersionToggle={versionToggle}
+ />
<div class={Styles.content}>
- <DagSidebar dragged={dragged} />
- <DagCanvas dragged={dragged} />
+ <DagSidebar onDragStart={onDragStart} />
+ <DagCanvas onDrop={onDrop} />
</div>
<DagAutoLayoutModal
visible={layoutVisible.value}
@@ -86,6 +112,13 @@ export default defineComponent({
formValue={formValue}
formRef={formRef}
/>
+ {!!props.definition && (
+ <VersionModal
+ v-model:row={props.definition.processDefinition}
+ v-model:show={versionModalShow.value}
+ onUpdateList={refreshDetail}
+ />
+ )}
</div>
)
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/types.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/types.ts
new file mode 100644
index 0000000..77f97db
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/types.ts
@@ -0,0 +1,95 @@
+/*
+ * 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 ProcessDefinition {
+ id: number
+ code: number
+ name: string
+ version: number
+ releaseState: string
+ projectCode: number
+ description: string
+ globalParams: string
+ globalParamList: any[]
+ globalParamMap: any
+ createTime: string
+ updateTime: string
+ flag: string
+ userId: number
+ userName?: any
+ projectName?: any
+ locations: string
+ scheduleReleaseState?: any
+ timeout: number
+ tenantId: number
+ tenantCode: string
+ modifyBy?: any
+ warningGroupId: number
+}
+
+export interface ProcessTaskRelationList {
+ id: number
+ name: string
+ processDefinitionVersion: number
+ projectCode: any
+ processDefinitionCode: any
+ preTaskCode: number
+ preTaskVersion: number
+ postTaskCode: any
+ postTaskVersion: number
+ conditionType: string
+ conditionParams: any
+ createTime: string
+ updateTime: string
+}
+
+export interface TaskDefinitionList {
+ id: number
+ code: any
+ name: string
+ version: number
+ description: string
+ projectCode: any
+ userId: number
+ taskType: string
+ taskParams: any
+ taskParamList: any[]
+ taskParamMap: any
+ flag: string
+ taskPriority: string
+ userName?: any
+ projectName?: any
+ workerGroup: string
+ environmentCode: number
+ failRetryTimes: number
+ failRetryInterval: number
+ timeoutFlag: string
+ timeoutNotifyStrategy: string
+ timeout: number
+ delayTime: number
+ resourceIds: string
+ createTime: string
+ updateTime: string
+ modifyBy?: any
+ dependence: string
+}
+
+export interface WorkflowDefinition {
+ processDefinition: ProcessDefinition
+ processTaskRelationList: ProcessTaskRelationList[]
+ taskDefinitionList: TaskDefinitionList[]
+}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-canvas-init.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-canvas-init.ts
index 8ec8d12..ffd5dc2 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-canvas-init.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-canvas-init.ts
@@ -16,7 +16,7 @@
*/
import type { Node } from '@antv/x6'
-import { ref, onMounted, Ref, onUnmounted } from 'vue'
+import { ref, onMounted, Ref } from 'vue'
import { Graph } from '@antv/x6'
import { NODE, EDGE, X6_NODE_NAME, X6_EDGE_NAME } from './dag-config'
import { debounce } from 'lodash'
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-node-search.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-cell-query.ts
similarity index 58%
copy from dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-node-search.ts
copy to dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-cell-query.ts
index 59d96e8..243e6c7 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-node-search.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-cell-query.ts
@@ -15,44 +15,40 @@
* limitations under the License.
*/
+import type { Ref } from 'vue'
import type { Graph } from '@antv/x6'
-import { ref, Ref } from 'vue'
-import { useGraphOperations } from './dag-hooks'
+import { TaskType } from '../../../task/constants/task-type'
interface Options {
graph: Ref<Graph | undefined>
}
/**
- * Node search and navigate
+ * Expose some cell-related query methods and refs
+ * @param {Options} options
*/
-export function useNodeSearch(options: Options) {
+export function useCellQuery(options: Options) {
const { graph } = options
- const searchInputVisible = ref(false)
- const allNodes = ref<any>([])
- const toggleSearchInput = () => {
- searchInputVisible.value = !searchInputVisible.value
- }
- const { getNodes, navigateTo } = useGraphOperations({ graph })
- const searchNode = (val: string) => {
- navigateTo(val)
- }
- const getAllNodes = () => {
- const nodes = getNodes()
- allNodes.value = nodes.map((node) => {
+ /**
+ * Get all nodes
+ */
+ function getNodes() {
+ const nodes = graph.value?.getNodes()
+ if (!nodes) return []
+ return nodes.map((node) => {
+ const position = node.getPosition()
+ const data = node.getData()
return {
- label: node.name,
- value: node.code
+ code: node.id,
+ position: position,
+ name: data.taskName as string,
+ type: data.taskType as TaskType
}
})
}
return {
- searchNode,
- getAllNodes,
- allNodes,
- toggleSearchInput,
- searchInputVisible
+ getNodes
}
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-cell-update.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-cell-update.ts
new file mode 100644
index 0000000..b69033f
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-cell-update.ts
@@ -0,0 +1,76 @@
+/*
+ * 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 type { Ref } from 'vue'
+import type { Graph } from '@antv/x6'
+import type { TaskType } from '@/views/projects/task/constants/task-type'
+import { TASK_TYPES_MAP } from '@/views/projects/task/constants/task-type'
+import { useCustomCellBuilder } from './dag-hooks'
+import type { Coordinate } from './use-custom-cell-builder'
+import utils from '@/utils'
+
+interface Options {
+ graph: Ref<Graph | undefined>
+}
+
+/**
+ * Expose some cell query
+ * @param {Options} options
+ */
+export function useCellUpdate(options: Options) {
+ const { graph } = options
+
+ const { buildNode } = useCustomCellBuilder()
+
+ /**
+ * Set node name by id
+ * @param {string} id
+ * @param {string} name
+ */
+ function setNodeName(id: string, newName: string) {
+ const node = graph.value?.getCellById(id)
+ if (node) {
+ const truncation = utils.truncateText(newName, 18)
+ node.attr('title/text', truncation)
+ node.setData({ taskName: newName })
+ }
+ }
+
+ /**
+ * Add a node to the graph
+ * @param {string} id
+ * @param {string} taskType
+ * @param {Coordinate} coordinate Default is { x: 100, y: 100 }
+ */
+ function addNode(
+ id: string,
+ type: string,
+ coordinate: Coordinate = { x: 100, y: 100 }
+ ) {
+ if (!TASK_TYPES_MAP[type as TaskType]) {
+ console.warn(`taskType:${type} is invalid!`)
+ return
+ }
+ const node = buildNode(id, type, '', coordinate)
+ graph.value?.addNode(node)
+ }
+
+ return {
+ setNodeName,
+ addNode
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-graph-operations.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-custom-cell-builder.ts
similarity index 51%
rename from dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-graph-operations.ts
rename to dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-custom-cell-builder.ts
index 2ec36a3..390b28c 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-graph-operations.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-custom-cell-builder.ts
@@ -15,24 +15,27 @@
* limitations under the License.
*/
-import type { Ref } from 'vue'
-import type { Node, Graph, Edge } from '@antv/x6'
+import type { Node, Edge } from '@antv/x6'
import { X6_NODE_NAME, X6_EDGE_NAME } from './dag-config'
-import { ALL_TASK_TYPES } from '../../../task/constants/task-type'
import utils from '@/utils'
+import { WorkflowDefinition } from './types'
-interface Options {
- graph: Ref<Graph | undefined>
-}
-
-type Coordinate = { x: number; y: number }
+export type Coordinate = { x: number; y: number }
-/**
- * Expose some graph operation methods
- * @param {Options} options
- */
-export function useGraphOperations(options: Options) {
- const { graph } = options
+export function useCustomCellBuilder() {
+ /**
+ * Convert locationStr to JSON
+ * @param {string} locationStr
+ * @returns
+ */
+ function parseLocationStr(locationStr: string) {
+ let locations = null
+ if (!locationStr) return locations
+ try {
+ locations = JSON.parse(locationStr)
+ } catch (error) {}
+ return Array.isArray(locations) ? locations : null
+ }
/**
* Build edge metadata
@@ -40,7 +43,7 @@ export function useGraphOperations(options: Options) {
* @param {string} targetId
* @param {string} label
*/
- function buildEdgeMetadata(
+ function buildEdge(
sourceId: string,
targetId: string,
label: string = ''
@@ -63,7 +66,7 @@ export function useGraphOperations(options: Options) {
* @param {string} taskType
* @param {Coordinate} coordinate Default is { x: 100, y: 100 }
*/
- function buildNodeMetadata(
+ function buildNode(
id: string,
type: string,
taskName: string,
@@ -92,74 +95,43 @@ export function useGraphOperations(options: Options) {
}
/**
- * Add a node to the graph
- * @param {string} id
- * @param {string} taskType
- * @param {Coordinate} coordinate Default is { x: 100, y: 100 }
+ * Build graph JSON
+ * @param {WorkflowDefinition} definition
+ * @returns
*/
- function addNode(
- id: string,
- type: string,
- coordinate: Coordinate = { x: 100, y: 100 }
- ) {
- if (!ALL_TASK_TYPES[type]) {
- console.warn(`taskType:${type} is invalid!`)
- return
- }
- const node = buildNodeMetadata(id, type, '', coordinate)
- graph.value?.addNode(node)
- }
+ function buildGraph(definition: WorkflowDefinition) {
+ const nodes: Node.Metadata[] = []
+ const edges: Edge.Metadata[] = []
- /**
- * Set node name by id
- * @param {string} id
- * @param {string} name
- */
- function setNodeName(id: string, newName: string) {
- const node = graph.value?.getCellById(id)
- if (node) {
- const truncation = utils.truncateText(newName, 18)
- node.attr('title/text', truncation)
- node.setData({ taskName: newName })
- }
- }
+ const locations =
+ parseLocationStr(definition.processDefinition.locations) || []
+ const tasks = definition.taskDefinitionList
+ const connects = definition.processTaskRelationList
- /**
- * Get nodes
- */
- function getNodes() {
- const nodes = graph.value?.getNodes()
- if (!nodes) return []
- return nodes.map((node) => {
- const position = node.getPosition()
- const data = node.getData()
- return {
- code: node.id,
- position: position,
- name: data.taskName,
- type: data.taskType
- }
+ tasks.forEach((task) => {
+ const location = locations.find((l) => l.taskCode === task.code) || {}
+ const node = buildNode(task.code, task.taskType, task.name, {
+ x: location.x,
+ y: location.y
+ })
+ nodes.push(node)
})
- }
- /**
- * Navigate to cell
- * @param {string} code
- */
- function navigateTo(code: string) {
- if (!graph.value) return
- const cell = graph.value.getCellById(code)
- graph.value.scrollToCell(cell, { animation: { duration: 600 } })
- graph.value.cleanSelection()
- graph.value.select(cell)
+ connects
+ .filter((r) => !!r.preTaskCode)
+ .forEach((c) => {
+ const edge = buildEdge(c.preTaskCode + '', c.postTaskCode, c.name)
+ edges.push(edge)
+ })
+ return {
+ nodes,
+ edges
+ }
}
return {
- buildEdgeMetadata,
- buildNodeMetadata,
- addNode,
- setNodeName,
- getNodes,
- navigateTo
+ buildNode,
+ buildEdge,
+ buildGraph
}
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-canvas-drop.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-dag-drag-drop.ts
similarity index 64%
rename from dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-canvas-drop.ts
rename to dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-dag-drag-drop.ts
index 7036052..3aa8811 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-canvas-drop.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-dag-drag-drop.ts
@@ -15,39 +15,60 @@
* limitations under the License.
*/
+import { ref } from 'vue'
import type { Ref } from 'vue'
import type { Graph } from '@antv/x6'
-import type { Dragged } from './dag'
+import type { Dragged } from '.'
import { genTaskCodeList } from '@/service/modules/task-definition'
-import { useGraphOperations } from './dag-hooks'
+import { useCellUpdate } from './dag-hooks'
+import { useRoute } from 'vue-router'
interface Options {
readonly: Ref<boolean>
graph: Ref<Graph | undefined>
- container: Ref<HTMLElement | undefined>
- dragged: Ref<Dragged>
- projectCode: string
}
/**
- * Drop sidebar item in canvas
+ * Sidebar item drag && drop in canvas
*/
-export function useCanvasDrop(options: Options) {
- const { readonly, graph, container, dragged, projectCode } = options
+export function useDagDragAndDrop(options: Options) {
+ const { readonly, graph } = options
- const { addNode } = useGraphOperations({ graph })
+ const route = useRoute()
+ const projectCode = Number(route.params.projectCode)
- const onDrop = (e: DragEvent) => {
+ const { addNode } = useCellUpdate({ graph })
+
+ // The element currently being dragged up
+ const dragged = ref<Dragged>({
+ x: 0,
+ y: 0,
+ type: ''
+ })
+
+ function onDragStart(e: DragEvent, type: string) {
+ if (readonly.value) {
+ e.preventDefault()
+ return
+ }
+ dragged.value = {
+ x: e.offsetX,
+ y: e.offsetY,
+ type: type
+ }
+ }
+
+ function onDrop(e: DragEvent) {
e.stopPropagation()
e.preventDefault()
if (readonly.value) {
return
}
- if (dragged.value && graph.value && container.value && projectCode) {
+ if (dragged.value && graph.value && projectCode) {
const { type, x: eX, y: eY } = dragged.value
const { x, y } = graph.value.clientToLocal(e.clientX, e.clientY)
const genNums = 1
- genTaskCodeList(genNums, Number(projectCode)).then((res) => {
+ genTaskCodeList(genNums, projectCode).then((res) => {
const [code] = res
addNode(code + '', type, { x: x - eX, y: y - eY })
// openTaskConfigModel(code, type)
@@ -60,6 +81,7 @@ export function useCanvasDrop(options: Options) {
}
return {
+ onDragStart,
onDrop,
onDragenter: preventDefault,
onDragover: preventDefault,
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-sidebar-drag.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-graph-backfill.ts
similarity index 59%
copy from dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-sidebar-drag.ts
copy to dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-graph-backfill.ts
index d7b6c53..4cd19d3 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-sidebar-drag.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-graph-backfill.ts
@@ -15,33 +15,29 @@
* limitations under the License.
*/
-import type { Ref } from 'vue'
-import type { Dragged } from './dag'
+import { Ref, watch } from 'vue'
+import { useCustomCellBuilder } from './dag-hooks'
+import type { Graph } from '@antv/x6'
+import { WorkflowDefinition } from './types'
interface Options {
- readonly: Ref<boolean>
- dragged: Ref<Dragged>
+ graph: Ref<Graph | undefined>
+ definition: Ref<WorkflowDefinition | undefined>
}
/**
- * Sidebar drag
+ * Backfill workflow into graph
*/
-export function useSidebarDrag(options: Options) {
- const { readonly, dragged } = options
+export function useGraphBackfill(options: Options) {
+ const { graph, definition } = options
- const onDragStart = (e: DragEvent, type: string) => {
- if (readonly.value) {
- e.preventDefault()
- return
- }
- dragged.value = {
- x: e.offsetX,
- y: e.offsetY,
- type: type
+ const { buildGraph } = useCustomCellBuilder()
+
+ watch([graph, definition], () => {
+ if (graph.value && definition.value) {
+ graph.value.fromJSON(buildGraph(definition.value))
}
- }
+ })
- return {
- onDragStart
- }
+ return {}
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-node-search.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-node-search.ts
index 59d96e8..27eae9f 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-node-search.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-node-search.ts
@@ -17,7 +17,7 @@
import type { Graph } from '@antv/x6'
import { ref, Ref } from 'vue'
-import { useGraphOperations } from './dag-hooks'
+import { useCellQuery } from './dag-hooks'
interface Options {
graph: Ref<Graph | undefined>
@@ -29,30 +29,43 @@ interface Options {
export function useNodeSearch(options: Options) {
const { graph } = options
+ /**
+ * Search input visible control
+ */
const searchInputVisible = ref(false)
- const allNodes = ref<any>([])
const toggleSearchInput = () => {
searchInputVisible.value = !searchInputVisible.value
}
- const { getNodes, navigateTo } = useGraphOperations({ graph })
- const searchNode = (val: string) => {
- navigateTo(val)
+
+ /**
+ * Search dropdown control
+ */
+ const { getNodes } = useCellQuery({ graph })
+ const nodesDropdown = ref<{ label: string; value: string }[]>([])
+ const reQueryNodes = () => {
+ nodesDropdown.value = getNodes().map((node) => ({
+ label: node.name,
+ value: node.code
+ }))
}
- const getAllNodes = () => {
- const nodes = getNodes()
- allNodes.value = nodes.map((node) => {
- return {
- label: node.name,
- value: node.code
- }
- })
+
+ /**
+ * Navigate to cell
+ * @param {string} code
+ */
+ function navigateTo(code: string) {
+ if (!graph.value) return
+ const cell = graph.value.getCellById(code)
+ graph.value.scrollToCell(cell, { animation: { duration: 600 } })
+ graph.value.cleanSelection()
+ graph.value.select(cell)
}
return {
- searchNode,
- getAllNodes,
- allNodes,
+ navigateTo,
toggleSearchInput,
- searchInputVisible
+ searchInputVisible,
+ reQueryNodes,
+ nodesDropdown
}
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-sidebar-drag.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-text-copy.ts
similarity index 63%
rename from dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-sidebar-drag.ts
rename to dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-text-copy.ts
index d7b6c53..4bd5450 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-sidebar-drag.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/components/dag/use-text-copy.ts
@@ -15,33 +15,23 @@
* limitations under the License.
*/
-import type { Ref } from 'vue'
-import type { Dragged } from './dag'
-
-interface Options {
- readonly: Ref<boolean>
- dragged: Ref<Dragged>
-}
+import { useClipboard } from '@vueuse/core'
+import { useMessage } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
/**
- * Sidebar drag
+ * Text copy with success message
*/
-export function useSidebarDrag(options: Options) {
- const { readonly, dragged } = options
-
- const onDragStart = (e: DragEvent, type: string) => {
- if (readonly.value) {
- e.preventDefault()
- return
- }
- dragged.value = {
- x: e.offsetX,
- y: e.offsetY,
- type: type
- }
+export function useTextCopy() {
+ const { t } = useI18n()
+ const { copy } = useClipboard()
+ const message = useMessage()
+ const copyText = (text: string) => {
+ copy(text).then((res) => {
+ message.success(t('project.dag.copy_success'))
+ })
}
-
return {
- onDragStart
+ copy: copyText
}
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/components/version-modal.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/components/version-modal.tsx
index 31e1ae3..cf104a5 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/components/version-modal.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/components/version-modal.tsx
@@ -58,9 +58,11 @@ export default defineComponent({
}
watch(
- () => props.row.code,
+ () => props.show,
() => {
- getTableData(props.row)
+ if (props.show && props.row?.code) {
+ getTableData(props.row)
+ }
}
)
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx
index 7e2de1b6..7462b42 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/create/index.tsx
@@ -25,11 +25,6 @@ export default defineComponent({
setup() {
const theme = useThemeStore()
- const slots = {
- toolbarLeft: () => <span>left-operations</span>,
- toolbarRight: () => <span>right-operations</span>
- }
-
return () => (
<div
class={[
@@ -37,7 +32,7 @@ export default defineComponent({
theme.darkTheme ? Styles['dark'] : Styles['light']
]}
>
- <Dag v-slots={slots} />
+ <Dag />
</div>
)
}
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.module.scss
similarity index 64%
copy from dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
copy to dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.module.scss
index ebcf900..baab217 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.module.scss
@@ -15,11 +15,27 @@
* limitations under the License.
*/
-import { defineComponent } from 'vue'
-
-export default defineComponent({
- name: 'WorkflowDefinitionDetails',
- setup() {
- return () => <div>WorkflowDefinitionDetails</div>
- }
-})
+ $borderDark: rgba(255, 255, 255, 0.09);
+ $borderLight: rgb(239, 239, 245);
+ $bgDark: rgb(24, 24, 28);
+ $bgLight: #ffffff;
+
+ .container {
+ width: 100%;
+ padding: 20px;
+ box-sizing: border-box;
+ height: calc(100vh - 100px);
+ overflow: hidden;
+ display: block;
+ }
+
+ .dark {
+ border: solid 1px $borderDark;
+ background-color: $bgDark;
+ }
+
+ .light {
+ border: solid 1px $borderLight;
+ background-color: $bgLight;
+ }
+
\ No newline at end of file
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
index ebcf900..fd7200d 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/detail/index.tsx
@@ -15,11 +15,44 @@
* limitations under the License.
*/
-import { defineComponent } from 'vue'
+import { defineComponent, onMounted, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import { useThemeStore } from '@/store/theme/theme'
+import Dag from '../../components/dag'
+import { queryProcessDefinitionByCode } from '@/service/modules/process-definition'
+import { WorkflowDefinition } from '../../components/dag/types'
+import Styles from './index.module.scss'
export default defineComponent({
name: 'WorkflowDefinitionDetails',
setup() {
- return () => <div>WorkflowDefinitionDetails</div>
+ const theme = useThemeStore()
+ const route = useRoute()
+ const projectCode = Number(route.params.projectCode)
+ const code = Number(route.params.code)
+
+ const definition = ref<WorkflowDefinition>()
+
+ const refresh = () => {
+ queryProcessDefinitionByCode(code, projectCode).then((res: any) => {
+ definition.value = res
+ })
+ }
+
+ onMounted(() => {
+ if (!code || !projectCode) return
+ refresh()
+ })
+
+ return () => (
+ <div
+ class={[
+ Styles.container,
+ theme.darkTheme ? Styles['dark'] : Styles['light']
+ ]}
+ >
+ <Dag definition={definition.value} onRefresh={refresh} />
+ </div>
+ )
}
})
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/index.tsx b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/index.tsx
index 3bcc8f3..792a4f4 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/index.tsx
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/index.tsx
@@ -32,11 +32,17 @@ import ImportModal from './components/import-modal'
import StartModal from './components/start-modal'
import TimingModal from './components/timing-modal'
import VersionModal from './components/version-modal'
+import { useRouter, useRoute } from 'vue-router'
+import type { Router } from 'vue-router'
import styles from './index.module.scss'
export default defineComponent({
name: 'WorkflowDefinitionList',
setup() {
+ const router: Router = useRouter()
+ const route = useRoute()
+ const projectCode = Number(route.params.projectCode)
+
const { variables, getTableData } = useTable()
const requestData = () => {
@@ -61,6 +67,12 @@ export default defineComponent({
requestData()
}
+ const createDefinition = () => {
+ router.push({
+ path: `/projects/${projectCode}/workflow/definitions/create`
+ })
+ }
+
onMounted(() => {
requestData()
})
@@ -69,6 +81,7 @@ export default defineComponent({
requestData,
handleSearch,
handleUpdateList,
+ createDefinition,
handleChangePageSize,
...toRefs(variables)
}
@@ -81,7 +94,7 @@ export default defineComponent({
<Card class={styles.card}>
<div class={styles.header}>
<NSpace>
- <NButton type='primary' /* TODO: Create workflow */>
+ <NButton type='primary' onClick={this.createDefinition}>
{t('project.workflow.create_workflow')}
</NButton>
<NButton strong secondary onClick={() => (this.showRef = true)}>
diff --git a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/use-table.ts b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/use-table.tsx
similarity index 95%
rename from dolphinscheduler-ui-next/src/views/projects/workflow/definition/use-table.ts
rename to dolphinscheduler-ui-next/src/views/projects/workflow/definition/use-table.tsx
index f2e3044..351cecf 100644
--- a/dolphinscheduler-ui-next/src/views/projects/workflow/definition/use-table.ts
+++ b/dolphinscheduler-ui-next/src/views/projects/workflow/definition/use-table.tsx
@@ -17,7 +17,7 @@
import { h, ref, reactive } from 'vue'
import { useI18n } from 'vue-i18n'
-import { useRouter } from 'vue-router'
+import { useRouter, RouterLink } from 'vue-router'
import type { Router } from 'vue-router'
import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
import { useAsyncState } from '@vueuse/core'
@@ -49,14 +49,21 @@ export function useTable() {
title: t('project.workflow.workflow_name'),
key: 'name',
width: 200,
- render: (_row) =>
- h(
- NEllipsis,
- { style: 'max-width: 200px' },
- {
- default: () => _row.name
- }
- )
+ render: (_row) => (
+ <NEllipsis
+ style={{
+ maxWidth: '200px'
+ }}
+ >
+ <RouterLink
+ to={{
+ path: `/projects/${_row.projectCode}/workflow/definitions/${_row.code}`
+ }}
+ >
+ {_row.name}
+ </RouterLink>
+ </NEllipsis>
+ )
},
{
title: t('project.workflow.status'),