Browse Source

[Feature][UI Next] Add workflow relation layout and format. (#8125)

3.0.0/version-upgrade
songjianet 3 years ago committed by GitHub
parent
commit
8ef72fcffc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      dolphinscheduler-ui-next/src/components/chart/modules/Graph.tsx
  2. 4
      dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
  3. 7
      dolphinscheduler-ui-next/src/locales/modules/en_US.ts
  4. 7
      dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
  5. 16
      dolphinscheduler-ui-next/src/router/modules/projects.ts
  6. 5
      dolphinscheduler-ui-next/src/service/modules/task-definition/index.ts
  7. 2
      dolphinscheduler-ui-next/src/store/menu/menu.ts
  8. 4
      dolphinscheduler-ui-next/src/store/menu/types.ts
  9. 2
      dolphinscheduler-ui-next/src/utils/index.ts
  10. 6
      dolphinscheduler-ui-next/src/views/projects/index.tsx
  11. 0
      dolphinscheduler-ui-next/src/views/projects/list/components/project-modal.tsx
  12. 0
      dolphinscheduler-ui-next/src/views/projects/list/components/table-action.tsx
  13. 0
      dolphinscheduler-ui-next/src/views/projects/list/index.module.scss
  14. 0
      dolphinscheduler-ui-next/src/views/projects/list/index.tsx
  15. 0
      dolphinscheduler-ui-next/src/views/projects/list/use-form.ts
  16. 0
      dolphinscheduler-ui-next/src/views/projects/list/use-table.ts
  17. 34
      dolphinscheduler-ui-next/src/views/projects/task/config.ts
  18. 6
      dolphinscheduler-ui-next/src/views/projects/task/task-config.tsx
  19. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/components/definition-card.tsx
  20. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/components/state-card.tsx
  21. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/index.tsx
  22. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/types.ts
  23. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-process-definition.ts
  24. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-process-state.ts
  25. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-table.ts
  26. 0
      dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-task-state.ts
  27. 54
      dolphinscheduler-ui-next/src/views/projects/workflow-relation/index.tsx
  28. 42
      dolphinscheduler-ui-next/src/views/projects/workflow/dag-canvas.tsx
  29. 12
      dolphinscheduler-ui-next/src/views/projects/workflow/dag-config.ts
  30. 14
      dolphinscheduler-ui-next/src/views/projects/workflow/dag-hooks.ts
  31. 38
      dolphinscheduler-ui-next/src/views/projects/workflow/dag-sidebar.tsx
  32. 171
      dolphinscheduler-ui-next/src/views/projects/workflow/dag-toolbar.tsx
  33. 32
      dolphinscheduler-ui-next/src/views/projects/workflow/dag.tsx
  34. 8
      dolphinscheduler-ui-next/src/views/projects/workflow/hook-demo.ts
  35. 40
      dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-drop.ts
  36. 30
      dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-init.ts
  37. 32
      dolphinscheduler-ui-next/src/views/projects/workflow/use-cell-active.ts
  38. 42
      dolphinscheduler-ui-next/src/views/projects/workflow/use-graph-operations.ts
  39. 24
      dolphinscheduler-ui-next/src/views/projects/workflow/use-node-search.ts
  40. 11
      dolphinscheduler-ui-next/src/views/projects/workflow/use-sidebar-drag.ts
  41. 11
      dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.tsx
  42. 6
      dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-details.tsx
  43. 6
      dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-list.tsx
  44. 6
      dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-details.tsx
  45. 6
      dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-list.tsx

12
dolphinscheduler-ui-next/src/components/chart/modules/Graph.tsx

@ -80,13 +80,16 @@ const GraphChart = defineComponent({
}
}
},
legend: [{
legend: [
{
orient: 'horizontal',
top: 6,
left: 6,
data: props.legendData
}],
series: [{
}
],
series: [
{
type: 'graph',
layout: 'force',
nodeScaleRatio: 1.2,
@ -124,7 +127,8 @@ const GraphChart = defineComponent({
lineStyle: {
color: '#999999'
}
}]
}
]
}
initChart(graphChartRef, option)

4
dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts

@ -92,8 +92,8 @@ export function useDataList() {
icon: renderIcon(FundProjectionScreenOutlined)
},
{
label: t('menu.workflow_relationships'),
key: 'workflow-relationships',
label: t('menu.workflow_relation'),
key: 'workflow-relation',
icon: renderIcon(PartitionOutlined)
},
{

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

@ -48,7 +48,7 @@ const menu = {
monitor: 'Monitor',
security: 'Security',
workflow_monitoring: 'Workflow Monitoring',
workflow_relationships: 'Workflow Relationships',
workflow_relation: 'Workflow Relation',
workflow: 'Workflow',
workflow_definition: 'Workflow Definition',
workflow_instance: 'Workflow Instance',
@ -287,8 +287,11 @@ const project = {
cancel: 'Cancel',
delete_confirm: 'Delete?'
},
workflow_relation: {
workflow_relation: 'Workflow Relation'
},
dag: {
createWorkflow: "Create Workflow",
createWorkflow: 'Create Workflow',
search: 'Search',
download_png: 'Download PNG',
fullscreen_open: 'Open Fullscreen',

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

@ -48,7 +48,7 @@ const menu = {
monitor: '监控中心',
security: '安全中心',
workflow_monitoring: '工作流监控',
workflow_relationships: '工作流关系',
workflow_relation: '工作流关系',
workflow: '工作流',
workflow_definition: '工作流定义',
workflow_instance: '工作流实例',
@ -287,8 +287,11 @@ const project = {
cancel: '取消',
delete_confirm: '确定删除吗?'
},
workflow_relation: {
workflow_relation: '工作流关系'
},
dag: {
createWorkflow: "创建工作流",
createWorkflow: '创建工作流',
search: '搜索',
download_png: '下载工作流图片',
fullscreen_open: '全屏',

16
dolphinscheduler-ui-next/src/router/modules/projects.ts

@ -47,21 +47,29 @@ export default {
showSide: true
}
},
{
path: '/projects/:projectCode/workflow-relation',
name: 'workflow-relation',
component: components['workflow-relation'],
meta: {
title: '工作流定义'
}
},
{
path: '/projects/:projectCode/workflow/definitions/create',
name: 'workflow-definition-create',
component: components['workflow-definition-create'],
meta: {
title: '创建工作流定义',
},
title: '创建工作流定义'
}
},
{
path: '/projects/:projectCode/workflow/definitions/:code',
name: 'workflow-definition-details',
component: components['workflow-definition-details'],
meta: {
title: '工作流定义详情',
},
title: '工作流定义详情'
}
}
]
}

5
dolphinscheduler-ui-next/src/service/modules/task-definition/index.ts

@ -49,10 +49,7 @@ export function save(
})
}
export function genTaskCodeList(
num: number,
projectCode: number
) {
export function genTaskCodeList(num: number, projectCode: number) {
return axios.request<unknown, number[]>({
url: `/projects/${projectCode}/task-definition/gen-task-codes`,
method: 'get',

2
dolphinscheduler-ui-next/src/store/menu/menu.ts

@ -46,6 +46,6 @@ export const useMenuStore = defineStore({
},
setSideMenuKey(sideMenuKey: string): void {
this.sideMenuKey = sideMenuKey
},
}
}
})

4
dolphinscheduler-ui-next/src/store/menu/types.ts

@ -16,8 +16,8 @@
*/
interface MenuState {
menuKey: string,
isShowSide: boolean,
menuKey: string
isShowSide: boolean
sideMenuKey: string
}

2
dolphinscheduler-ui-next/src/utils/index.ts

@ -22,7 +22,7 @@ import truncateText from './truncate-text'
const utils = {
mapping,
regex,
truncateText,
truncateText
}
export default utils

6
dolphinscheduler-ui-next/src/views/projects/index.tsx

@ -18,10 +18,8 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: "Projects",
name: 'Projects',
setup() {
return () => (
<div>Projects</div>
)
return () => <div>Projects</div>
}
})

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

0
dolphinscheduler-ui-next/src/views/project/list/components/table-action.tsx → dolphinscheduler-ui-next/src/views/projects/list/components/table-action.tsx

0
dolphinscheduler-ui-next/src/views/project/list/index.module.scss → dolphinscheduler-ui-next/src/views/projects/list/index.module.scss

0
dolphinscheduler-ui-next/src/views/project/list/index.tsx → dolphinscheduler-ui-next/src/views/projects/list/index.tsx

0
dolphinscheduler-ui-next/src/views/project/list/use-form.ts → dolphinscheduler-ui-next/src/views/projects/list/use-form.ts

0
dolphinscheduler-ui-next/src/views/project/list/use-table.ts → dolphinscheduler-ui-next/src/views/projects/list/use-table.ts

34
dolphinscheduler-ui-next/src/views/projects/task/config.ts

@ -17,51 +17,51 @@
export const ALL_TASK_TYPES: any = {
SHELL: {
alias: 'SHELL',
alias: 'SHELL'
},
SUB_PROCESS: {
alias: 'SUB_PROCESS',
alias: 'SUB_PROCESS'
},
PROCEDURE: {
alias: 'PROCEDURE',
alias: 'PROCEDURE'
},
SQL: {
alias: 'SQL',
alias: 'SQL'
},
SPARK: {
alias: 'SPARK',
alias: 'SPARK'
},
FLINK: {
alias: 'FLINK',
alias: 'FLINK'
},
MR: {
alias: 'MapReduce',
alias: 'MapReduce'
},
PYTHON: {
alias: 'PYTHON',
alias: 'PYTHON'
},
DEPENDENT: {
alias: 'DEPENDENT',
alias: 'DEPENDENT'
},
HTTP: {
alias: 'HTTP',
alias: 'HTTP'
},
DATAX: {
alias: 'DataX',
alias: 'DataX'
},
PIGEON: {
alias: 'PIGEON',
alias: 'PIGEON'
},
SQOOP: {
alias: 'SQOOP',
alias: 'SQOOP'
},
CONDITIONS: {
alias: 'CONDITIONS',
alias: 'CONDITIONS'
},
SWITCH: {
alias: 'SWITCH',
alias: 'SWITCH'
},
SEATUNNEL: {
alias: 'WATERDROP',
alias: 'WATERDROP'
}
}
};

6
dolphinscheduler-ui-next/src/views/projects/task/task-config.tsx

@ -18,10 +18,8 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: "TaskConfigModal",
name: 'TaskConfigModal',
setup() {
return () => (
<div>TaskConfigModal</div>
)
return () => <div>TaskConfigModal</div>
}
})

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/components/definition-card.tsx → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/components/definition-card.tsx

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/components/state-card.tsx → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/components/state-card.tsx

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/index.tsx → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/index.tsx

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/types.ts → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/types.ts

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/use-process-definition.ts → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-process-definition.ts

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/use-process-state.ts → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-process-state.ts

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/use-table.ts → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-table.ts

0
dolphinscheduler-ui-next/src/views/project/workflow-monitor/use-task-state.ts → dolphinscheduler-ui-next/src/views/projects/workflow-monitor/use-task-state.ts

54
dolphinscheduler-ui-next/src/views/projects/workflow-relation/index.tsx

@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { defineComponent } from 'vue'
import { useI18n } from 'vue-i18n'
import { NSelect, NButton, NIcon } from 'naive-ui'
import { ReloadOutlined, EyeOutlined } from '@vicons/antd'
import Card from '@/components/card'
const workflowRelation = defineComponent({
name: 'workflow-relation',
setup() {
const { t } = useI18n()
return { t }
},
render() {
const { t } = this
return (
<Card title={t('project.workflow_relation.workflow_relation')}>
<div>
<NSelect />
<NButton strong secondary circle type='info'>
<NIcon>
<ReloadOutlined />
</NIcon>
</NButton>
<NButton strong secondary circle type='info'>
<NIcon>
<EyeOutlined />
</NIcon>
</NButton>
</div>
</Card>
)
}
})
export default workflowRelation

42
dolphinscheduler-ui-next/src/views/projects/workflow/dag-canvas.tsx

@ -19,7 +19,12 @@ import { defineComponent, ref, inject } from 'vue'
import Styles from './dag.module.scss'
import type { PropType, Ref } from 'vue'
import type { Dragged } from './dag'
import { useCanvasInit, useGraphOperations, useCellActive, useCanvasDrop } from './dag-hooks';
import {
useCanvasInit,
useGraphOperations,
useCellActive,
useCanvasDrop
} from './dag-hooks'
import { useRoute } from 'vue-router'
const props = {
@ -29,32 +34,45 @@ const props = {
x: 0,
y: 0,
type: ''
}),
})
}
}
export default defineComponent({
name: "workflow-dag-canvas",
name: 'workflow-dag-canvas',
props,
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 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 });
const { paper, minimap, container } = useCanvasInit({ readonly, graph })
// Change the style on cell hover and select
useCellActive({ graph });
useCellActive({ graph })
// Drop sidebar item in canvas
const { onDrop, onDragenter, onDragover, onDragleave } = useCanvasDrop({ readonly, dragged: props.dragged, graph, container, projectCode });
const { onDrop, onDragenter, onDragover, onDragleave } = useCanvasDrop({
readonly,
dragged: props.dragged,
graph,
container,
projectCode
})
return () => (
<div ref={container} class={Styles.canvas} onDrop={onDrop} onDragenter={onDragenter} onDragover={onDragover} onDragleave={onDragleave}>
<div
ref={container}
class={Styles.canvas}
onDrop={onDrop}
onDragenter={onDragenter}
onDragover={onDragover}
onDragleave={onDragleave}
>
<div ref={paper} class={Styles.paper}></div>
<div ref={minimap} class={Styles.minimap}></div>
</div>
);
)
}
})

12
dolphinscheduler-ui-next/src/views/projects/workflow/dag-config.ts

@ -119,7 +119,8 @@ export const PORT_SELECTED = {
}
}
export const NODE_STATUS_MARKUP = [{
export const NODE_STATUS_MARKUP = [
{
tagName: 'foreignObject',
selector: 'fo',
children: [
@ -127,13 +128,16 @@ export const NODE_STATUS_MARKUP = [{
tagName: 'body',
selector: 'fo-body',
ns: 'http://www.w3.org/1999/xhtml',
children: [{
children: [
{
tagName: 'div',
selector: 'status'
}]
}
]
}]
}
]
}
]
export const NODE = {
width: 220,

14
dolphinscheduler-ui-next/src/views/projects/workflow/dag-hooks.ts

@ -15,12 +15,12 @@
* limitations under the License.
*/
import { useCanvasInit } from './use-canvas-init';
import { useGraphOperations } from './use-graph-operations';
import { useCellActive } from './use-cell-active';
import { useSidebarDrag } from './use-sidebar-drag';
import { useCanvasDrop } from './use-canvas-drop';
import { useNodeSearch } from './use-node-search';
import { useCanvasInit } from './use-canvas-init'
import { useGraphOperations } from './use-graph-operations'
import { useCellActive } from './use-cell-active'
import { useSidebarDrag } from './use-sidebar-drag'
import { useCanvasDrop } from './use-canvas-drop'
import { useNodeSearch } from './use-node-search'
export {
useCanvasInit,
@ -28,5 +28,5 @@ export {
useCellActive,
useSidebarDrag,
useCanvasDrop,
useNodeSearch,
useNodeSearch
}

38
dolphinscheduler-ui-next/src/views/projects/workflow/dag-sidebar.tsx

@ -15,12 +15,12 @@
* limitations under the License.
*/
import type { PropType, Ref } from 'vue';
import type { Dragged } from './dag';
import type { PropType, Ref } from 'vue'
import type { Dragged } from './dag'
import { defineComponent, ref, inject } from 'vue'
import { ALL_TASK_TYPES } from '../task/config';
import { useSidebarDrag } from './dag-hooks';
import Styles from './dag.module.scss';
import { ALL_TASK_TYPES } from '../task/config'
import { useSidebarDrag } from './dag-hooks'
import Styles from './dag.module.scss'
const props = {
dragged: {
@ -29,39 +29,41 @@ const props = {
x: 0,
y: 0,
type: ''
}),
},
})
}
}
export default defineComponent({
name: "workflow-dag-sidebar",
name: 'workflow-dag-sidebar',
props,
setup(props) {
const readonly = inject('readonly', ref(false))
const dragged = props.dragged;
const dragged = props.dragged
const { onDragStart } = useSidebarDrag({
readonly,
dragged
});
const allTaskTypes = Object.keys(ALL_TASK_TYPES).map(type => ({
})
const allTaskTypes = Object.keys(ALL_TASK_TYPES).map((type) => ({
type,
...ALL_TASK_TYPES[type]
}));
}))
return () => (
<div class={Styles.sidebar}>
{
allTaskTypes.map(task => (
{allTaskTypes.map((task) => (
<div
class={Styles.draggable}
draggable="true"
draggable='true'
onDragstart={(e) => onDragStart(e, task.type)}
>
<em class={`${Styles['sidebar-icon']} ${Styles['icon-' + task.type.toLocaleLowerCase()]}`}></em>
<em
class={`${Styles['sidebar-icon']} ${
Styles['icon-' + task.type.toLocaleLowerCase()]
}`}
></em>
<span>{task.alias}</span>
</div>
))
}
))}
</div>
)
}

171
dolphinscheduler-ui-next/src/views/projects/workflow/dag-toolbar.tsx

@ -18,19 +18,26 @@
import { defineComponent, ref, inject } from 'vue'
import { useI18n } from 'vue-i18n'
import Styles from './dag.module.scss'
import { NTooltip, NIcon, NButton, NSelect } from 'naive-ui';
import { SearchOutlined, DownloadOutlined, FullscreenOutlined, FullscreenExitOutlined, InfoCircleOutlined, FormatPainterOutlined } from '@vicons/antd';
import { useNodeSearch } from './dag-hooks';
import { NTooltip, NIcon, NButton, NSelect } from 'naive-ui'
import {
SearchOutlined,
DownloadOutlined,
FullscreenOutlined,
FullscreenExitOutlined,
InfoCircleOutlined,
FormatPainterOutlined
} from '@vicons/antd'
import { useNodeSearch } from './dag-hooks'
import { DataUri } from '@antv/x6'
import { useFullscreen } from '@vueuse/core';
import { useRouter } from 'vue-router';
import { useFullscreen } from '@vueuse/core'
import { useRouter } from 'vue-router'
export default defineComponent({
name: "workflow-dag-toolbar",
name: 'workflow-dag-toolbar',
setup(props, context) {
const { t } = useI18n();
const graph = inject('graph', ref());
const router = useRouter();
const { t } = useI18n()
const graph = inject('graph', ref())
const router = useRouter()
/**
* Node search and navigate
@ -41,7 +48,7 @@ export default defineComponent({
allNodes,
toggleSearchInput,
searchInputVisible
} = useNodeSearch({ graph });
} = useNodeSearch({ graph })
/**
* Download Workflow Image
@ -49,7 +56,7 @@ export default defineComponent({
* @param {string} bgColor
*/
const downloadPNG = (options = { fileName: 'dag', bgColor: '#f2f3f7' }) => {
const { fileName, bgColor } = options;
const { fileName, bgColor } = options
graph.value?.toPNG(
(dataUri: string) => {
DataUri.downloadDataUri(dataUri, `${fileName}.png`)
@ -69,8 +76,7 @@ export default defineComponent({
/**
* Toggle fullscreen
*/
const { isFullscreen, toggle } = useFullscreen();
const { isFullscreen, toggle } = useFullscreen()
/**
* Open workflow version modal
@ -82,9 +88,7 @@ export default defineComponent({
/**
* Open DAG format modal
*/
const openDagFormatModal = () => {
}
const openDagFormatModal = () => {}
const onClose = () => {
router.go(-1)
@ -92,87 +96,158 @@ export default defineComponent({
return () => (
<div class={Styles.toolbar}>
<span class={Styles['workflow-name']}>{t("project.dag.createWorkflow")}</span>
<span class={Styles['workflow-name']}>
{t('project.dag.createWorkflow')}
</span>
<div class={Styles['toolbar-right-part']}>
{/* Search node */}
<NTooltip v-slots={{
<NTooltip
v-slots={{
trigger: () => (
<NButton class={Styles['toolbar-right-item']} strong secondary circle type="info" onClick={toggleSearchInput} v-slots={{
<NButton
class={Styles['toolbar-right-item']}
strong
secondary
circle
type='info'
onClick={toggleSearchInput}
v-slots={{
icon: () => (
<NIcon>
<SearchOutlined />
</NIcon>
)
}} />
}}
/>
),
default: () => t('project.dag.search')
}}>
</NTooltip>
}}
></NTooltip>
<div
class={`${Styles['toolbar-right-item']} ${Styles['node-selector']} ${searchInputVisible.value ? Styles['visible'] : ''}`}
class={`${Styles['toolbar-right-item']} ${
Styles['node-selector']
} ${searchInputVisible.value ? Styles['visible'] : ''}`}
>
<NSelect size="small" options={allNodes.value} onFocus={getAllNodes} onUpdateValue={searchNode} filterable />
<NSelect
size='small'
options={allNodes.value}
onFocus={getAllNodes}
onUpdateValue={searchNode}
filterable
/>
</div>
{/* Download workflow PNG */}
<NTooltip v-slots={{
<NTooltip
v-slots={{
trigger: () => (
<NButton class={Styles['toolbar-right-item']} strong secondary circle type="info" onClick={() => downloadPNG()} v-slots={{
<NButton
class={Styles['toolbar-right-item']}
strong
secondary
circle
type='info'
onClick={() => downloadPNG()}
v-slots={{
icon: () => (
<NIcon>
<DownloadOutlined />
</NIcon>
)
}} />
}}
/>
),
default: () => t('project.dag.download_png')
}}>
</NTooltip>
}}
></NTooltip>
{/* Toggle fullscreen */}
<NTooltip v-slots={{
<NTooltip
v-slots={{
trigger: () => (
<NButton class={Styles['toolbar-right-item']} strong secondary circle type="info" onClick={toggle} v-slots={{
<NButton
class={Styles['toolbar-right-item']}
strong
secondary
circle
type='info'
onClick={toggle}
v-slots={{
icon: () => (
<NIcon>
{isFullscreen.value ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
{isFullscreen.value ? (
<FullscreenExitOutlined />
) : (
<FullscreenOutlined />
)}
</NIcon>
)
}} />
}}
/>
),
default: () => isFullscreen.value ? t('project.dag.fullscreen_close') : t('project.dag.fullscreen_open')
}}>
</NTooltip>
default: () =>
isFullscreen.value
? t('project.dag.fullscreen_close')
: t('project.dag.fullscreen_open')
}}
></NTooltip>
{/* DAG Format */}
<NTooltip v-slots={{
<NTooltip
v-slots={{
trigger: () => (
<NButton class={Styles['toolbar-right-item']} strong secondary circle type="info" onClick={openDagFormatModal} v-slots={{
<NButton
class={Styles['toolbar-right-item']}
strong
secondary
circle
type='info'
onClick={openDagFormatModal}
v-slots={{
icon: () => (
<NIcon>
<FormatPainterOutlined />
</NIcon>
)
}} />
}}
/>
),
default: () => t('project.dag.format')
}}>
</NTooltip>
}}
></NTooltip>
{/* Version info */}
<NTooltip v-slots={{
<NTooltip
v-slots={{
trigger: () => (
<NButton class={Styles['toolbar-right-item']} strong secondary circle type="info" onClick={openVersionModal} v-slots={{
<NButton
class={Styles['toolbar-right-item']}
strong
secondary
circle
type='info'
onClick={openVersionModal}
v-slots={{
icon: () => (
<NIcon>
<InfoCircleOutlined />
</NIcon>
)
}} />
}}
/>
),
default: () => t('project.dag.workflow_version')
}}>
</NTooltip>
}}
></NTooltip>
{/* Save workflow */}
<NButton class={Styles['toolbar-right-item']} type="info" secondary round>{t('project.dag.save')}</NButton>
<NButton
class={Styles['toolbar-right-item']}
type='info'
secondary
round
>
{t('project.dag.save')}
</NButton>
{/* Return to previous page */}
<NButton secondary round onClick={onClose}>{t('project.dag.close')}</NButton>
<NButton secondary round onClick={onClose}>
{t('project.dag.close')}
</NButton>
</div>
</div>
)

32
dolphinscheduler-ui-next/src/views/projects/workflow/dag.tsx

@ -15,31 +15,29 @@
* limitations under the License.
*/
import type { Graph } from '@antv/x6';
import type { Graph } from '@antv/x6'
import { defineComponent, ref, provide } from 'vue'
import DagToolbar from './dag-toolbar';
import DagCanvas from './dag-canvas';
import DagSidebar from './dag-sidebar';
import Styles from './dag.module.scss';
import "./x6-style.scss";
import DagToolbar from './dag-toolbar'
import DagCanvas from './dag-canvas'
import DagSidebar from './dag-sidebar'
import Styles from './dag.module.scss'
import './x6-style.scss'
export interface Dragged {
x: number;
y: number;
type: string;
x: number
y: number
type: string
}
export default defineComponent({
name: "workflow-dag",
name: 'workflow-dag',
setup(props, context) {
// Whether the graph can be operated
const readonly = ref(false);
provide('readonly', readonly);
const readonly = ref(false)
provide('readonly', readonly)
const graph = ref<Graph>();
provide('graph', graph);
const graph = ref<Graph>()
provide('graph', graph)
// The sidebar slots
const toolbarSlots = {
@ -52,7 +50,7 @@ export default defineComponent({
x: 0,
y: 0,
type: ''
});
})
return () => (
<div class={Styles.dag}>

8
dolphinscheduler-ui-next/src/views/projects/workflow/hook-demo.ts

@ -29,12 +29,8 @@ interface Options {
* 3. Register custom graphics
*/
export function useCanvasInit(options: Options) {
// Whether the graph can be operated
const { } = options;
const {} = options
return {
}
return {}
}

40
dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-drop.ts

@ -15,41 +15,39 @@
* limitations under the License.
*/
import type { Ref } from 'vue';
import type { Ref } from 'vue'
import type { Graph } from '@antv/x6'
import type { Dragged } from './dag'
import { genTaskCodeList } from '@/service/modules/task-definition';
import { useGraphOperations } from './dag-hooks';
import { genTaskCodeList } from '@/service/modules/task-definition'
import { useGraphOperations } from './dag-hooks'
interface Options {
readonly: Ref<boolean>;
graph: Ref<Graph | undefined>;
container: Ref<HTMLElement | undefined>;
dragged: Ref<Dragged>;
projectCode: string;
readonly: Ref<boolean>
graph: Ref<Graph | undefined>
container: Ref<HTMLElement | undefined>
dragged: Ref<Dragged>
projectCode: string
}
/**
* Drop sidebar item in canvas
*/
export function useCanvasDrop(options: Options) {
const { readonly, graph, container, dragged, projectCode } = options
const { readonly, graph, container, dragged, projectCode } = options;
const { addNode } = useGraphOperations({ graph });
const { addNode } = useGraphOperations({ graph })
const onDrop = (e: DragEvent) => {
e.stopPropagation();
e.preventDefault();
e.stopPropagation()
e.preventDefault()
if (readonly.value) {
return;
return
}
if (dragged.value && graph.value && container.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) => {
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) => {
const [code] = res
addNode(code + '', type, { x: x - eX, y: y - eY })
// openTaskConfigModel(code, type)
@ -58,13 +56,13 @@ export function useCanvasDrop(options: Options) {
}
const preventDefault = (e: DragEvent) => {
e.preventDefault();
e.preventDefault()
}
return {
onDrop,
onDragenter: preventDefault,
onDragover: preventDefault,
onDragleave: preventDefault,
onDragleave: preventDefault
}
}

30
dolphinscheduler-ui-next/src/views/projects/workflow/use-canvas-init.ts

@ -15,20 +15,15 @@
* limitations under the License.
*/
import type { Node } from '@antv/x6';
import type { Node } from '@antv/x6'
import { ref, onMounted, Ref, onUnmounted } from 'vue'
import { Graph } from '@antv/x6'
import {
NODE,
EDGE,
X6_NODE_NAME,
X6_EDGE_NAME,
} from './dag-config'
import { debounce } from 'lodash';
import { NODE, EDGE, X6_NODE_NAME, X6_EDGE_NAME } from './dag-config'
import { debounce } from 'lodash'
interface Options {
readonly: Ref<boolean>;
graph: Ref<Graph | undefined>;
readonly: Ref<boolean>
graph: Ref<Graph | undefined>
}
/**
@ -38,13 +33,12 @@ interface Options {
* 3. Register custom graphics
*/
export function useCanvasInit(options: Options) {
// Whether the graph can be operated
const { readonly, graph } = options;
const { readonly, graph } = options
const paper = ref<HTMLElement>(); // The graph mount HTMLElement
const minimap = ref<HTMLElement>(); // The minimap mount HTMLElement
const container = ref<HTMLElement>(); // The container of paper and minimap
const paper = ref<HTMLElement>() // The graph mount HTMLElement
const minimap = ref<HTMLElement>() // The minimap mount HTMLElement
const container = ref<HTMLElement>() // The container of paper and minimap
/**
* Graph Init, bind graph to the dom
@ -129,7 +123,7 @@ export function useCanvasInit(options: Options) {
}
onMounted(() => {
graph.value = graphInit();
graph.value = graphInit()
// Make sure the edge starts with node, not port
graph.value.on('edge:connected', ({ isNew, edge }) => {
if (isNew) {
@ -143,10 +137,10 @@ export function useCanvasInit(options: Options) {
* Redraw when the page is resized
*/
const paperResize = debounce(() => {
if (!container.value) return;
if (!container.value) return
const w = container.value.offsetWidth
const h = container.value.offsetHeight
graph.value?.resize(w, h);
graph.value?.resize(w, h)
}, 200)
onMounted(() => {
window.addEventListener('resize', paperResize)

32
dolphinscheduler-ui-next/src/views/projects/workflow/use-cell-active.ts

@ -16,9 +16,9 @@
*/
import type { Ref } from 'vue'
import { onMounted, ref } from 'vue';
import { onMounted, ref } from 'vue'
import type { Node, Graph, Edge, Cell } from '@antv/x6'
import _ from 'lodash';
import _ from 'lodash'
import {
X6_PORT_OUT_NAME,
PORT_HOVER,
@ -30,7 +30,7 @@ import {
EDGE,
EDGE_SELECTED,
EDGE_HOVER
} from './dag-config';
} from './dag-config'
interface Options {
graph: Ref<Graph | undefined>
@ -40,17 +40,19 @@ interface Options {
* Change the style on cell hover and select
*/
export function useCellActive(options: Options) {
const { graph } = options;
const hoverCell = ref();
const { graph } = options
const hoverCell = ref()
const isStatusIcon = (tagName: string) => {
if (!tagName) return false;
return tagName.toLocaleLowerCase() === 'em' || tagName.toLocaleLowerCase() === 'body'
if (!tagName) return false
return (
tagName.toLocaleLowerCase() === 'em' ||
tagName.toLocaleLowerCase() === 'body'
)
}
function setEdgeStyle(edge: Edge) {
const isHover = edge === hoverCell.value;
const isHover = edge === hoverCell.value
const isSelected = graph.value?.isSelected(edge)
// TODO
// const labelName = this.getEdgeLabelName ? this.getEdgeLabelName(edge) : ''
@ -70,7 +72,7 @@ export function useCellActive(options: Options) {
..._.merge(
{
attrs: _.cloneDeep(edgeProps.defaultLabel.attrs)
},
}
// {
// attrs: { label: { text: labelName } }
// }
@ -83,7 +85,9 @@ export function useCellActive(options: Options) {
const isHover = node === hoverCell.value
const isSelected = graph.value?.isSelected(node)
const portHover = _.cloneDeep(PORT_HOVER.groups[X6_PORT_OUT_NAME].attrs)
const portSelected = _.cloneDeep(PORT_SELECTED.groups[X6_PORT_OUT_NAME].attrs)
const portSelected = _.cloneDeep(
PORT_SELECTED.groups[X6_PORT_OUT_NAME].attrs
)
const portDefault = _.cloneDeep(PORT.groups[X6_PORT_OUT_NAME].attrs)
const nodeHover = _.merge(_.cloneDeep(NODE.attrs), NODE_HOVER.attrs)
const nodeSelected = _.merge(_.cloneDeep(NODE.attrs), NODE_SELECTED.attrs)
@ -108,11 +112,7 @@ export function useCellActive(options: Options) {
}
node.setAttrByPath('image/xlink:href', img)
node.setAttrs(nodeAttrs)
node.setPortProp(
X6_PORT_OUT_NAME,
'attrs',
portAttrs
)
node.setPortProp(X6_PORT_OUT_NAME, 'attrs', portAttrs)
}
function updateCellStyle(cell: Cell) {

42
dolphinscheduler-ui-next/src/views/projects/workflow/use-graph-operations.ts

@ -17,27 +17,22 @@
import type { Ref } from 'vue'
import type { Node, Graph, Edge } from '@antv/x6'
import {
X6_NODE_NAME,
X6_EDGE_NAME,
} from './dag-config'
import { ALL_TASK_TYPES } from '../task/config';
import utils from '@/utils';
import { X6_NODE_NAME, X6_EDGE_NAME } from './dag-config'
import { ALL_TASK_TYPES } from '../task/config'
import utils from '@/utils'
interface Options {
graph: Ref<Graph | undefined>
}
type Coordinate = { x: number; y: number; }
type Coordinate = { x: number; y: number }
/**
* Expose some graph operation methods
* @param {Options} options
*/
export function useGraphOperations(options: Options) {
const { graph } = options;
const { graph } = options
/**
* Build edge metadata
@ -45,7 +40,11 @@ export function useGraphOperations(options: Options) {
* @param {string} targetId
* @param {string} label
*/
function buildEdgeMetadata(sourceId: string, targetId: string, label: string = ''): Edge.Metadata {
function buildEdgeMetadata(
sourceId: string,
targetId: string,
label: string = ''
): Edge.Metadata {
return {
shape: X6_EDGE_NAME,
source: {
@ -64,8 +63,13 @@ export function useGraphOperations(options: Options) {
* @param {string} taskType
* @param {Coordinate} coordinate Default is { x: 100, y: 100 }
*/
function buildNodeMetadata(id: string, type: string, taskName: string, coordinate: Coordinate = { x: 100, y: 100 }): Node.Metadata {
const truncation = taskName ? utils.truncateText(taskName, 18) : id;
function buildNodeMetadata(
id: string,
type: string,
taskName: string,
coordinate: Coordinate = { x: 100, y: 100 }
): Node.Metadata {
const truncation = taskName ? utils.truncateText(taskName, 18) : id
return {
id: id,
shape: X6_NODE_NAME,
@ -93,7 +97,11 @@ export function useGraphOperations(options: Options) {
* @param {string} taskType
* @param {Coordinate} coordinate Default is { x: 100, y: 100 }
*/
function addNode(id: string, type: string, coordinate: Coordinate = { x: 100, y: 100 }) {
function addNode(
id: string,
type: string,
coordinate: Coordinate = { x: 100, y: 100 }
) {
if (!ALL_TASK_TYPES[type]) {
console.warn(`taskType:${type} is invalid!`)
return
@ -139,12 +147,12 @@ export function useGraphOperations(options: Options) {
* @param {string} code
*/
function navigateTo(code: string) {
if (!graph.value) return;
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 {
buildEdgeMetadata,
@ -152,6 +160,6 @@ export function useGraphOperations(options: Options) {
addNode,
setNodeName,
getNodes,
navigateTo,
navigateTo
}
}

24
dolphinscheduler-ui-next/src/views/projects/workflow/use-node-search.ts

@ -15,34 +15,32 @@
* limitations under the License.
*/
import type { Graph } from '@antv/x6';
import type { Graph } from '@antv/x6'
import { ref, Ref } from 'vue'
import { useGraphOperations } from './dag-hooks';
import { useGraphOperations } from './dag-hooks'
interface Options {
graph: Ref<Graph | undefined>;
graph: Ref<Graph | undefined>
}
/**
* Node search and navigate
*/
export function useNodeSearch(options: Options) {
const { graph } = options
const { graph } = options;
const searchInputVisible = ref(false);
const allNodes = ref<any>([]);
const searchInputVisible = ref(false)
const allNodes = ref<any>([])
const toggleSearchInput = () => {
searchInputVisible.value = !searchInputVisible.value;
searchInputVisible.value = !searchInputVisible.value
}
const { getNodes, navigateTo } = useGraphOperations({ graph });
const { getNodes, navigateTo } = useGraphOperations({ graph })
const searchNode = (val: string) => {
navigateTo(val)
}
const getAllNodes = () => {
const nodes = getNodes();
allNodes.value = nodes.map(node => {
const nodes = getNodes()
allNodes.value = nodes.map((node) => {
return {
label: node.name,
value: node.code
@ -55,6 +53,6 @@ export function useNodeSearch(options: Options) {
getAllNodes,
allNodes,
toggleSearchInput,
searchInputVisible,
searchInputVisible
}
}

11
dolphinscheduler-ui-next/src/views/projects/workflow/use-sidebar-drag.ts

@ -15,20 +15,19 @@
* limitations under the License.
*/
import type { Ref } from 'vue';
import type { Dragged } from './dag';
import type { Ref } from 'vue'
import type { Dragged } from './dag'
interface Options {
readonly: Ref<boolean>;
dragged: Ref<Dragged>;
readonly: Ref<boolean>
dragged: Ref<Dragged>
}
/**
* Sidebar drag
*/
export function useSidebarDrag(options: Options) {
const { readonly, dragged } = options;
const { readonly, dragged } = options
const onDragStart = (e: DragEvent, type: string) => {
if (readonly.value) {

11
dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-create.tsx

@ -16,18 +16,17 @@
*/
import { defineComponent } from 'vue'
import Dag from './dag';
import { NCard } from 'naive-ui';
import styles from './workflow-definition-create.module.scss';
import Dag from './dag'
import { NCard } from 'naive-ui'
import styles from './workflow-definition-create.module.scss'
export default defineComponent({
name: "WorkflowDefinitionCreate",
name: 'WorkflowDefinitionCreate',
setup() {
const slots = {
toolbarLeft: () => <span>left-operations</span>,
toolbarRight: () => <span>right-operations</span>
};
}
return () => (
<NCard class={styles.container}>

6
dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-details.tsx

@ -18,10 +18,8 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: "WorkflowDefinitionDetails",
name: 'WorkflowDefinitionDetails',
setup() {
return () => (
<div>WorkflowDefinitionDetails</div>
)
return () => <div>WorkflowDefinitionDetails</div>
}
})

6
dolphinscheduler-ui-next/src/views/projects/workflow/workflow-definition-list.tsx

@ -18,10 +18,8 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: "WorkflowDefinitionList",
name: 'WorkflowDefinitionList',
setup() {
return () => (
<div>WorkflowDefinitionList</div>
)
return () => <div>WorkflowDefinitionList</div>
}
})

6
dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-details.tsx

@ -18,10 +18,8 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: "WorkflowInstanceDetails",
name: 'WorkflowInstanceDetails',
setup() {
return () => (
<div>WorkflowInstanceDetails</div>
)
return () => <div>WorkflowInstanceDetails</div>
}
})

6
dolphinscheduler-ui-next/src/views/projects/workflow/workflow-instance-list.tsx

@ -18,10 +18,8 @@
import { defineComponent } from 'vue'
export default defineComponent({
name: "WorkflowInstanceList",
name: 'WorkflowInstanceList',
setup() {
return () => (
<div>WorkflowInstanceList</div>
)
return () => <div>WorkflowInstanceList</div>
}
})
Loading…
Cancel
Save