After Width: | Height: | Size: 812 B |
After Width: | Height: | Size: 736 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 743 B |
After Width: | Height: | Size: 745 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 707 B |
After Width: | Height: | Size: 709 B |
After Width: | Height: | Size: 930 B |
After Width: | Height: | Size: 862 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 747 B |
After Width: | Height: | Size: 745 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 896 B |
After Width: | Height: | Size: 897 B |
After Width: | Height: | Size: 692 B |
After Width: | Height: | Size: 693 B |
After Width: | Height: | Size: 885 B |
After Width: | Height: | Size: 825 B |
@ -0,0 +1,51 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
/** |
||||
* truncateText('ALongText', 4) => 'ALon...' |
||||
* @param {number} limit |
||||
* @param {string} text |
||||
* Each Chinese character is equal to two chars |
||||
*/ |
||||
export default function truncateText(text: string, n: number) { |
||||
const exp = /[\u4E00-\u9FA5]/ |
||||
let res = '' |
||||
let len = text.length |
||||
let chinese = text.match(new RegExp(exp, 'g')) |
||||
if (chinese) { |
||||
len += chinese.length |
||||
} |
||||
if (len > n) { |
||||
let i = 0 |
||||
let acc = 0 |
||||
while (true) { |
||||
let char = text[i] |
||||
if (exp.test(char)) { |
||||
acc += 2 |
||||
} else { |
||||
acc++ |
||||
} |
||||
if (acc > n) break |
||||
res += char |
||||
i++ |
||||
} |
||||
res += '...' |
||||
} else { |
||||
res = text |
||||
} |
||||
return res |
||||
} |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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' |
||||
|
||||
export default defineComponent({ |
||||
name: "Projects", |
||||
setup() { |
||||
return () => ( |
||||
<div>Projects</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,67 @@
|
||||
/* |
||||
* 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 const ALL_TASK_TYPES:any = { |
||||
SHELL: { |
||||
alias: 'SHELL', |
||||
}, |
||||
SUB_PROCESS: { |
||||
alias: 'SUB_PROCESS', |
||||
}, |
||||
PROCEDURE: { |
||||
alias: 'PROCEDURE', |
||||
}, |
||||
SQL: { |
||||
alias: 'SQL', |
||||
}, |
||||
SPARK: { |
||||
alias: 'SPARK', |
||||
}, |
||||
FLINK: { |
||||
alias: 'FLINK', |
||||
}, |
||||
MR: { |
||||
alias: 'MapReduce', |
||||
}, |
||||
PYTHON: { |
||||
alias: 'PYTHON', |
||||
}, |
||||
DEPENDENT: { |
||||
alias: 'DEPENDENT', |
||||
}, |
||||
HTTP: { |
||||
alias: 'HTTP', |
||||
}, |
||||
DATAX: { |
||||
alias: 'DataX', |
||||
}, |
||||
PIGEON: { |
||||
alias: 'PIGEON', |
||||
}, |
||||
SQOOP: { |
||||
alias: 'SQOOP', |
||||
}, |
||||
CONDITIONS: { |
||||
alias: 'CONDITIONS', |
||||
}, |
||||
SWITCH: { |
||||
alias: 'SWITCH', |
||||
}, |
||||
SEATUNNEL: { |
||||
alias: 'WATERDROP', |
||||
} |
||||
}; |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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' |
||||
|
||||
export default defineComponent({ |
||||
name: "TaskConfigModal", |
||||
setup() { |
||||
return () => ( |
||||
<div>TaskConfigModal</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,60 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
import { defineComponent, ref, 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 { useRoute } from 'vue-router' |
||||
|
||||
const props = { |
||||
dragged: { |
||||
type: Object as PropType<Ref<Dragged>>, |
||||
default: ref({ |
||||
x: 0, |
||||
y: 0, |
||||
type: '' |
||||
}), |
||||
} |
||||
} |
||||
|
||||
export default defineComponent({ |
||||
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 { 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 }); |
||||
|
||||
return () => ( |
||||
<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> |
||||
); |
||||
} |
||||
}) |
@ -0,0 +1,339 @@
|
||||
/* |
||||
* 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 const X6_NODE_NAME = 'dag-task' |
||||
export const X6_EDGE_NAME = 'dag-edge' |
||||
export const X6_PORT_OUT_NAME = 'dag-port-out' |
||||
|
||||
const EDGE_COLOR = '#999999' |
||||
const BG_BLUE = '#DFE9F7' |
||||
const BG_WHITE = '#FFFFFF' |
||||
const NODE_BORDER = '#CCCCCC' |
||||
const TITLE = '#333333' |
||||
const STROKE_BLUE = '#288FFF' |
||||
const NODE_SHADOW = 'drop-shadow(3px 3px 4px rgba(0, 0, 0, 0.2))' |
||||
const EDGE_SHADOW = 'drop-shadow(3px 3px 2px rgba(0, 0, 0, 0.2))' |
||||
|
||||
export const PORT = { |
||||
groups: { |
||||
[X6_PORT_OUT_NAME]: { |
||||
position: { |
||||
name: 'absolute', |
||||
args: { |
||||
x: 200, |
||||
y: 24 |
||||
} |
||||
}, |
||||
markup: [ |
||||
{ |
||||
tagName: 'g', |
||||
selector: 'body', |
||||
children: [ |
||||
{ |
||||
tagName: 'circle', |
||||
selector: 'circle-outer' |
||||
}, |
||||
{ |
||||
tagName: 'text', |
||||
selector: 'plus-text' |
||||
}, |
||||
{ |
||||
tagName: 'circle', |
||||
selector: 'circle-inner' |
||||
} |
||||
] |
||||
} |
||||
], |
||||
attrs: { |
||||
body: { |
||||
magnet: true |
||||
}, |
||||
'plus-text': { |
||||
fontSize: 12, |
||||
fill: NODE_BORDER, |
||||
text: '+', |
||||
textAnchor: 'middle', |
||||
x: 0, |
||||
y: 3 |
||||
}, |
||||
'circle-outer': { |
||||
stroke: NODE_BORDER, |
||||
strokeWidth: 1, |
||||
r: 6, |
||||
fill: BG_WHITE |
||||
}, |
||||
'circle-inner': { |
||||
r: 4, |
||||
fill: 'transparent' |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const PORT_HOVER = { |
||||
groups: { |
||||
[X6_PORT_OUT_NAME]: { |
||||
attrs: { |
||||
'circle-outer': { |
||||
stroke: STROKE_BLUE, |
||||
fill: BG_BLUE, |
||||
r: 8 |
||||
}, |
||||
'circle-inner': { |
||||
fill: STROKE_BLUE, |
||||
r: 6 |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const PORT_SELECTED = { |
||||
groups: { |
||||
[X6_PORT_OUT_NAME]: { |
||||
attrs: { |
||||
'plus-text': { |
||||
fill: STROKE_BLUE |
||||
}, |
||||
'circle-outer': { |
||||
stroke: STROKE_BLUE, |
||||
fill: BG_WHITE |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const NODE_STATUS_MARKUP = [{ |
||||
tagName: 'foreignObject', |
||||
selector: 'fo', |
||||
children: [ |
||||
{ |
||||
tagName: 'body', |
||||
selector: 'fo-body', |
||||
ns: 'http://www.w3.org/1999/xhtml', |
||||
children: [{ |
||||
tagName: 'div', |
||||
selector: 'status' |
||||
}] |
||||
} |
||||
] |
||||
}] |
||||
|
||||
export const NODE = { |
||||
width: 220, |
||||
height: 48, |
||||
markup: [ |
||||
{ |
||||
tagName: 'rect', |
||||
selector: 'body', |
||||
className: 'dag-task-body' |
||||
}, |
||||
{ |
||||
tagName: 'image', |
||||
selector: 'image' |
||||
}, |
||||
{ |
||||
tagName: 'text', |
||||
selector: 'title' |
||||
} |
||||
], |
||||
attrs: { |
||||
body: { |
||||
refWidth: '100%', |
||||
refHeight: '100%', |
||||
rx: 6, |
||||
ry: 6, |
||||
pointerEvents: 'visiblePainted', |
||||
fill: BG_WHITE, |
||||
stroke: NODE_BORDER, |
||||
strokeWidth: 1, |
||||
strokeDasharray: 'none', |
||||
filter: 'none' |
||||
}, |
||||
image: { |
||||
width: 30, |
||||
height: 30, |
||||
refX: 12, |
||||
refY: 9 |
||||
}, |
||||
title: { |
||||
refX: 45, |
||||
refY: 18, |
||||
fontFamily: 'Microsoft Yahei', |
||||
fontSize: 12, |
||||
fontWeight: 'bold', |
||||
fill: TITLE, |
||||
strokeWidth: 0 |
||||
}, |
||||
fo: { |
||||
refX: '46%', |
||||
refY: -25, |
||||
width: 18, |
||||
height: 18 |
||||
} |
||||
}, |
||||
ports: { |
||||
...PORT, |
||||
items: [ |
||||
{ |
||||
id: X6_PORT_OUT_NAME, |
||||
group: X6_PORT_OUT_NAME |
||||
} |
||||
] |
||||
} |
||||
} |
||||
|
||||
export const NODE_HOVER = { |
||||
attrs: { |
||||
body: { |
||||
fill: BG_BLUE, |
||||
stroke: STROKE_BLUE, |
||||
strokeDasharray: '5,2' |
||||
}, |
||||
title: { |
||||
fill: STROKE_BLUE |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const NODE_SELECTED = { |
||||
attrs: { |
||||
body: { |
||||
filter: NODE_SHADOW, |
||||
fill: BG_WHITE, |
||||
stroke: STROKE_BLUE, |
||||
strokeDasharray: '5,2', |
||||
strokeWidth: '1.5' |
||||
}, |
||||
title: { |
||||
fill: STROKE_BLUE |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const EDGE = { |
||||
attrs: { |
||||
line: { |
||||
stroke: EDGE_COLOR, |
||||
strokeWidth: 1, |
||||
targetMarker: { |
||||
tagName: 'path', |
||||
fill: EDGE_COLOR, |
||||
strokeWidth: 0, |
||||
d: 'M 6 -3 0 0 6 3 Z' |
||||
}, |
||||
filter: 'none' |
||||
} |
||||
}, |
||||
connector: { |
||||
name: 'rounded' |
||||
}, |
||||
router: { |
||||
name: 'manhattan', |
||||
args: { |
||||
endDirections: ['top', 'bottom', 'left'] |
||||
} |
||||
}, |
||||
defaultLabel: { |
||||
markup: [ |
||||
{ |
||||
tagName: 'rect', |
||||
selector: 'body' |
||||
}, |
||||
{ |
||||
tagName: 'text', |
||||
selector: 'label' |
||||
} |
||||
], |
||||
attrs: { |
||||
label: { |
||||
fill: EDGE_COLOR, |
||||
fontSize: 14, |
||||
textAnchor: 'middle', |
||||
textVerticalAnchor: 'middle', |
||||
pointerEvents: 'none' |
||||
}, |
||||
body: { |
||||
ref: 'label', |
||||
fill: BG_WHITE, |
||||
stroke: EDGE_COLOR, |
||||
strokeWidth: 1, |
||||
rx: 4, |
||||
ry: 4, |
||||
refWidth: '140%', |
||||
refHeight: '140%', |
||||
refX: '-20%', |
||||
refY: '-20%' |
||||
} |
||||
}, |
||||
position: { |
||||
distance: 0.5, |
||||
options: { |
||||
absoluteDistance: true, |
||||
reverseDistance: true |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const EDGE_HOVER = { |
||||
attrs: { |
||||
line: { |
||||
stroke: STROKE_BLUE, |
||||
targetMarker: { |
||||
fill: STROKE_BLUE |
||||
} |
||||
} |
||||
}, |
||||
defaultLabel: { |
||||
attrs: { |
||||
label: { |
||||
fill: STROKE_BLUE |
||||
}, |
||||
body: { |
||||
fill: BG_WHITE, |
||||
stroke: STROKE_BLUE |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const EDGE_SELECTED = { |
||||
attrs: { |
||||
line: { |
||||
stroke: STROKE_BLUE, |
||||
targetMarker: { |
||||
fill: STROKE_BLUE |
||||
}, |
||||
strokeWidth: 2, |
||||
filter: EDGE_SHADOW |
||||
} |
||||
}, |
||||
defaultLabel: { |
||||
attrs: { |
||||
label: { |
||||
fill: STROKE_BLUE |
||||
}, |
||||
body: { |
||||
fill: BG_WHITE, |
||||
stroke: STROKE_BLUE |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
|
||||
/* |
||||
* 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 { 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, |
||||
useGraphOperations, |
||||
useCellActive, |
||||
useSidebarDrag, |
||||
useCanvasDrop, |
||||
useNodeSearch, |
||||
} |
@ -0,0 +1,68 @@
|
||||
/* |
||||
* 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 { 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'; |
||||
|
||||
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 => ({ |
||||
type, |
||||
...ALL_TASK_TYPES[type] |
||||
})); |
||||
|
||||
return () => ( |
||||
<div class={Styles.sidebar}> |
||||
{ |
||||
allTaskTypes.map(task => ( |
||||
<div |
||||
class={Styles.draggable} |
||||
draggable="true" |
||||
onDragstart={(e) => onDragStart(e, task.type)} |
||||
> |
||||
<em class={`${Styles['sidebar-icon']} ${Styles['icon-' + task.type.toLocaleLowerCase()]}`}></em> |
||||
<span>{task.alias}</span> |
||||
</div> |
||||
)) |
||||
} |
||||
</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,180 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
import { defineComponent, ref, 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 { DataUri } from '@antv/x6' |
||||
import { useFullscreen } from '@vueuse/core'; |
||||
import { useRouter } from 'vue-router'; |
||||
|
||||
export default defineComponent({ |
||||
name: "workflow-dag-toolbar", |
||||
setup(props, context) { |
||||
const { t } = useI18n(); |
||||
const graph = inject('graph', ref()); |
||||
const router = useRouter(); |
||||
|
||||
/** |
||||
* Node search and navigate |
||||
*/ |
||||
const { |
||||
searchNode, |
||||
getAllNodes, |
||||
allNodes, |
||||
toggleSearchInput, |
||||
searchInputVisible |
||||
} = useNodeSearch({ graph }); |
||||
|
||||
/** |
||||
* Download Workflow Image |
||||
* @param {string} fileName |
||||
* @param {string} bgColor
|
||||
*/ |
||||
const downloadPNG = (options = { fileName: 'dag', bgColor: '#f2f3f7' }) => { |
||||
const { fileName, bgColor } = options; |
||||
graph.value?.toPNG( |
||||
(dataUri: string) => { |
||||
DataUri.downloadDataUri(dataUri, `${fileName}.png`) |
||||
}, |
||||
{ |
||||
padding: { |
||||
top: 50, |
||||
right: 50, |
||||
bottom: 50, |
||||
left: 50 |
||||
}, |
||||
backgroundColor: bgColor |
||||
} |
||||
) |
||||
} |
||||
|
||||
/** |
||||
* Toggle fullscreen |
||||
*/ |
||||
const { isFullscreen, toggle } = useFullscreen(); |
||||
|
||||
|
||||
/** |
||||
* Open workflow version modal |
||||
*/ |
||||
const openVersionModal = () => { |
||||
//TODO, same as the version popup in the workflow list page
|
||||
} |
||||
|
||||
/** |
||||
* Open DAG format modal |
||||
*/ |
||||
const openDagFormatModal = () => { |
||||
|
||||
} |
||||
|
||||
const onClose = () => { |
||||
router.go(-1) |
||||
} |
||||
|
||||
return () => ( |
||||
<div class={Styles.toolbar}> |
||||
<span class={Styles['workflow-name']}>{t("project.dag.createWorkflow")}</span> |
||||
<div class={Styles['toolbar-right-part']}> |
||||
{/* Search node */} |
||||
<NTooltip v-slots={{ |
||||
trigger: () => ( |
||||
<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> |
||||
<div |
||||
class={`${Styles['toolbar-right-item']} ${Styles['node-selector']} ${searchInputVisible.value ? Styles['visible'] : ''}`} |
||||
> |
||||
<NSelect size="small" options={allNodes.value} onFocus={getAllNodes} onUpdateValue={searchNode} filterable /> |
||||
</div> |
||||
{/* Download workflow PNG */} |
||||
<NTooltip v-slots={{ |
||||
trigger: () => ( |
||||
<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> |
||||
{/* Toggle fullscreen */} |
||||
<NTooltip v-slots={{ |
||||
trigger: () => ( |
||||
<NButton class={Styles['toolbar-right-item']} strong secondary circle type="info" onClick={toggle} v-slots={{ |
||||
icon: () => ( |
||||
<NIcon> |
||||
{isFullscreen.value ? <FullscreenExitOutlined /> : <FullscreenOutlined />} |
||||
</NIcon> |
||||
) |
||||
}} /> |
||||
), |
||||
default: () => isFullscreen.value ? t('project.dag.fullscreen_close') : t('project.dag.fullscreen_open') |
||||
}}> |
||||
</NTooltip> |
||||
{/* DAG Format */} |
||||
<NTooltip v-slots={{ |
||||
trigger: () => ( |
||||
<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> |
||||
{/* 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.dag.workflow_version') |
||||
}}> |
||||
</NTooltip> |
||||
{/* Save workflow */} |
||||
<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> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,217 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
$blue: #288fff; |
||||
$blueBg: rgba(40, 143, 255, 0.1); |
||||
$toolbarHeight: 50px; |
||||
|
||||
.dag { |
||||
height: 100%; |
||||
} |
||||
|
||||
.content { |
||||
display: flex; |
||||
height: calc(100% - $toolbarHeight - 20px); |
||||
margin-top: 20px; |
||||
} |
||||
|
||||
.toolbar { |
||||
height: $toolbarHeight; |
||||
display: flex; |
||||
align-items: center; |
||||
padding: 0 20px; |
||||
border: 1px solid var(--n-border-color); |
||||
border-radius: 4px; |
||||
justify-content: space-between; |
||||
} |
||||
|
||||
.canvas { |
||||
width: 100%; |
||||
height: 100%; |
||||
position: relative; |
||||
overflow: hidden; |
||||
display: flex; |
||||
} |
||||
|
||||
.paper { |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.sidebar { |
||||
width: 190px; |
||||
height: 100%; |
||||
margin-right: 20px; |
||||
} |
||||
|
||||
.workflow-name { |
||||
font-size: 14px; |
||||
} |
||||
|
||||
.draggable { |
||||
display: flex; |
||||
width: 100%; |
||||
height: 32px; |
||||
margin-bottom: 10px; |
||||
align-items: center; |
||||
border: 1px solid var(--n-border-color); |
||||
padding: 0 10px; |
||||
border-radius: 4px; |
||||
transform: translate(0, 0); |
||||
box-sizing: border-box; |
||||
cursor: move; |
||||
font-size: 12px; |
||||
|
||||
.sidebar-icon { |
||||
display: block; |
||||
width: 18px; |
||||
height: 18px; |
||||
background-size: 100% 100%; |
||||
margin-right: 10px; |
||||
&.icon-shell { |
||||
background-image: url("../../../assets/images/task-icons/shell.png"); |
||||
} |
||||
&.icon-sub_process { |
||||
background-image: url("../../../assets/images/task-icons/sub_process.png"); |
||||
} |
||||
&.icon-procedure { |
||||
background-image: url("../../../assets/images/task-icons/procedure.png"); |
||||
} |
||||
&.icon-sql { |
||||
background-image: url("../../../assets/images/task-icons/sql.png"); |
||||
} |
||||
&.icon-flink { |
||||
background-image: url("../../../assets/images/task-icons/flink.png"); |
||||
} |
||||
&.icon-mr { |
||||
background-image: url("../../../assets/images/task-icons/mr.png"); |
||||
} |
||||
&.icon-python { |
||||
background-image: url("../../../assets/images/task-icons/python.png"); |
||||
} |
||||
&.icon-dependent { |
||||
background-image: url("../../../assets/images/task-icons/dependent.png"); |
||||
} |
||||
&.icon-http { |
||||
background-image: url("../../../assets/images/task-icons/http.png"); |
||||
} |
||||
&.icon-datax { |
||||
background-image: url("../../../assets/images/task-icons/datax.png"); |
||||
} |
||||
&.icon-pigeon { |
||||
background-image: url("../../../assets/images/task-icons/pigeon.png"); |
||||
} |
||||
&.icon-sqoop { |
||||
background-image: url("../../../assets/images/task-icons/sqoop.png"); |
||||
} |
||||
&.icon-conditions { |
||||
background-image: url("../../../assets/images/task-icons/conditions.png"); |
||||
} |
||||
&.icon-seatunnel { |
||||
background-image: url("../../../assets/images/task-icons/seatunnel.png"); |
||||
} |
||||
&.icon-spark { |
||||
background-image: url("../../../assets/images/task-icons/spark.png"); |
||||
} |
||||
&.icon-switch { |
||||
background-image: url("../../../assets/images/task-icons/switch.png"); |
||||
} |
||||
} |
||||
|
||||
&:hover { |
||||
color: $blue; |
||||
border: 1px dashed $blue; |
||||
background-color: $blueBg; |
||||
.sidebar-icon { |
||||
&.icon-shell { |
||||
background-image: url("../../../assets/images/task-icons/shell_hover.png"); |
||||
} |
||||
&.icon-sub_process { |
||||
background-image: url("../../../assets/images/task-icons/sub_process_hover.png"); |
||||
} |
||||
&.icon-procedure { |
||||
background-image: url("../../../assets/images/task-icons/procedure_hover.png"); |
||||
} |
||||
&.icon-sql { |
||||
background-image: url("../../../assets/images/task-icons/sql_hover.png"); |
||||
} |
||||
&.icon-flink { |
||||
background-image: url("../../../assets/images/task-icons/flink_hover.png"); |
||||
} |
||||
&.icon-mr { |
||||
background-image: url("../../../assets/images/task-icons/mr_hover.png"); |
||||
} |
||||
&.icon-python { |
||||
background-image: url("../../../assets/images/task-icons/python_hover.png"); |
||||
} |
||||
&.icon-dependent { |
||||
background-image: url("../../../assets/images/task-icons/dependent_hover.png"); |
||||
} |
||||
&.icon-http { |
||||
background-image: url("../../../assets/images/task-icons/http_hover.png"); |
||||
} |
||||
&.icon-datax { |
||||
background-image: url("../../../assets/images/task-icons/datax_hover.png"); |
||||
} |
||||
&.icon-pigeon { |
||||
background-image: url("../../../assets/images/task-icons/pigeon_hover.png"); |
||||
} |
||||
&.icon-sqoop { |
||||
background-image: url("../../../assets/images/task-icons/sqoop_hover.png"); |
||||
} |
||||
&.icon-conditions { |
||||
background-image: url("../../../assets/images/task-icons/conditions_hover.png"); |
||||
} |
||||
&.icon-seatunnel { |
||||
background-image: url("../../../assets/images/task-icons/seatunnel_hover.png"); |
||||
} |
||||
&.icon-spark { |
||||
background-image: url("../../../assets/images/task-icons/spark_hover.png"); |
||||
} |
||||
&.icon-switch { |
||||
background-image: url("../../../assets/images/task-icons/switch_hover.png"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.minimap { |
||||
position: absolute; |
||||
right: 0px; |
||||
bottom: 0px; |
||||
border: dashed 1px #e4e4e4; |
||||
z-index: 9; |
||||
} |
||||
|
||||
.toolbar-right-part { |
||||
display: flex; |
||||
align-items: center; |
||||
.toolbar-right-item { |
||||
margin-right: 10px; |
||||
} |
||||
.node-selector { |
||||
width: 0; |
||||
overflow: hidden; |
||||
transition: all 0.5s; |
||||
margin-right: 0; |
||||
|
||||
&.visible { |
||||
width: 200px; |
||||
margin-right: 10px; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,67 @@
|
||||
/* |
||||
* 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 { 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"; |
||||
|
||||
|
||||
export interface Dragged { |
||||
x: number; |
||||
y: number; |
||||
type: string; |
||||
} |
||||
|
||||
export default defineComponent({ |
||||
name: "workflow-dag", |
||||
setup(props, context) { |
||||
|
||||
// Whether the graph can be operated
|
||||
const readonly = ref(false); |
||||
provide('readonly', 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: '' |
||||
}); |
||||
|
||||
return () => ( |
||||
<div class={Styles.dag}> |
||||
<DagToolbar v-slots={toolbarSlots} /> |
||||
<div class={Styles.content}> |
||||
<DagSidebar dragged={dragged} /> |
||||
<DagCanvas dragged={dragged} /> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,40 @@
|
||||
/* |
||||
* 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 { ref, onMounted, Ref, onUnmounted } from 'vue' |
||||
|
||||
interface Options { |
||||
// readonly: Ref<boolean>;
|
||||
// canvas: Ref<HTMLElement | undefined>;
|
||||
} |
||||
|
||||
/** |
||||
* Canvas Init |
||||
* 1. Bind the graph to the dom |
||||
* 2. Redraw when the page is resized |
||||
* 3. Register custom graphics |
||||
*/ |
||||
export function useCanvasInit(options: Options) { |
||||
|
||||
// Whether the graph can be operated
|
||||
const { } = options; |
||||
|
||||
|
||||
return { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,70 @@
|
||||
/* |
||||
* 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 { Dragged } from './dag' |
||||
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; |
||||
} |
||||
|
||||
/** |
||||
* Drop sidebar item in canvas |
||||
*/ |
||||
export function useCanvasDrop(options: Options) { |
||||
|
||||
const { readonly, graph, container, dragged, projectCode } = options; |
||||
|
||||
const { addNode } = useGraphOperations({ graph }); |
||||
|
||||
const onDrop = (e: DragEvent) => { |
||||
e.stopPropagation(); |
||||
e.preventDefault(); |
||||
if (readonly.value) { |
||||
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 [code] = res |
||||
addNode(code + '', type, { x: x - eX, y: y - eY }) |
||||
// openTaskConfigModel(code, type)
|
||||
}) |
||||
} |
||||
} |
||||
|
||||
const preventDefault = (e: DragEvent) => { |
||||
e.preventDefault(); |
||||
} |
||||
|
||||
return { |
||||
onDrop, |
||||
onDragenter: preventDefault, |
||||
onDragover: preventDefault, |
||||
onDragleave: preventDefault, |
||||
} |
||||
} |
@ -0,0 +1,177 @@
|
||||
/* |
||||
* 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 { 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'; |
||||
|
||||
interface Options { |
||||
readonly: Ref<boolean>; |
||||
graph: Ref<Graph | undefined>; |
||||
} |
||||
|
||||
/** |
||||
* Canvas Init |
||||
* 1. Bind the graph to the dom |
||||
* 2. Redraw when the page is resized |
||||
* 3. Register custom graphics |
||||
*/ |
||||
export function useCanvasInit(options: Options) { |
||||
|
||||
// Whether the graph can be operated
|
||||
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
|
||||
|
||||
/** |
||||
* Graph Init, bind graph to the dom |
||||
*/ |
||||
function graphInit() { |
||||
return new Graph({ |
||||
container: paper.value, |
||||
selecting: { |
||||
enabled: true, |
||||
multiple: true, |
||||
rubberband: true, |
||||
rubberEdge: true, |
||||
movable: true, |
||||
showNodeSelectionBox: false |
||||
}, |
||||
scaling: { |
||||
min: 0.2, |
||||
max: 2 |
||||
}, |
||||
mousewheel: { |
||||
enabled: true, |
||||
modifiers: ['ctrl', 'meta'] |
||||
}, |
||||
scroller: true, |
||||
grid: { |
||||
size: 10, |
||||
visible: true |
||||
}, |
||||
snapline: true, |
||||
minimap: { |
||||
enabled: true, |
||||
container: minimap.value, |
||||
scalable: false, |
||||
width: 200, |
||||
height: 120 |
||||
}, |
||||
interacting: { |
||||
edgeLabelMovable: false, |
||||
nodeMovable: !readonly.value, |
||||
magnetConnectable: !readonly.value |
||||
}, |
||||
connecting: { |
||||
// Whether multiple edges can be created between the same start node and end
|
||||
allowMulti: false, |
||||
// Whether a point is allowed to connect to a blank position on the canvas
|
||||
allowBlank: false, |
||||
// The start node and the end node are the same node
|
||||
allowLoop: false, |
||||
// Whether an edge is allowed to link to another edge
|
||||
allowEdge: false, |
||||
// Whether edges are allowed to link to nodes
|
||||
allowNode: true, |
||||
// Whether to allow edge links to ports
|
||||
allowPort: false, |
||||
// Whether all available ports or nodes are highlighted when you drag the edge
|
||||
highlight: true, |
||||
createEdge() { |
||||
return graph.value?.createEdge({ shape: X6_EDGE_NAME }) |
||||
} |
||||
}, |
||||
highlighting: { |
||||
nodeAvailable: { |
||||
name: 'className', |
||||
args: { |
||||
className: 'available' |
||||
} |
||||
}, |
||||
magnetAvailable: { |
||||
name: 'className', |
||||
args: { |
||||
className: 'available' |
||||
} |
||||
}, |
||||
magnetAdsorbed: { |
||||
name: 'className', |
||||
args: { |
||||
className: 'adsorbed' |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
|
||||
onMounted(() => { |
||||
graph.value = graphInit(); |
||||
// Make sure the edge starts with node, not port
|
||||
graph.value.on('edge:connected', ({ isNew, edge }) => { |
||||
if (isNew) { |
||||
const sourceNode = edge.getSourceNode() as Node |
||||
edge.setSource(sourceNode) |
||||
} |
||||
}) |
||||
}) |
||||
|
||||
/** |
||||
* Redraw when the page is resized |
||||
*/ |
||||
const paperResize = debounce(() => { |
||||
if (!container.value) return; |
||||
const w = container.value.offsetWidth |
||||
const h = container.value.offsetHeight |
||||
graph.value?.resize(w, h); |
||||
}, 200) |
||||
onMounted(() => { |
||||
window.addEventListener('resize', paperResize) |
||||
}) |
||||
onUnmounted(() => { |
||||
window.removeEventListener('resize', paperResize) |
||||
}) |
||||
|
||||
/** |
||||
* Register custom cells |
||||
*/ |
||||
function registerCustomCells() { |
||||
Graph.unregisterNode(X6_NODE_NAME) |
||||
Graph.unregisterEdge(X6_EDGE_NAME) |
||||
Graph.registerNode(X6_NODE_NAME, { ...NODE }) |
||||
Graph.registerEdge(X6_EDGE_NAME, { ...EDGE }) |
||||
} |
||||
onMounted(() => { |
||||
registerCustomCells() |
||||
}) |
||||
|
||||
return { |
||||
graph, |
||||
paper, |
||||
minimap, |
||||
container |
||||
} |
||||
} |
@ -0,0 +1,154 @@
|
||||
/* |
||||
* 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 { onMounted, ref } from 'vue'; |
||||
import type { Node, Graph, Edge, Cell } from '@antv/x6' |
||||
import _ from 'lodash'; |
||||
import { |
||||
X6_PORT_OUT_NAME, |
||||
PORT_HOVER, |
||||
PORT_SELECTED, |
||||
PORT, |
||||
NODE, |
||||
NODE_HOVER, |
||||
NODE_SELECTED, |
||||
EDGE, |
||||
EDGE_SELECTED, |
||||
EDGE_HOVER |
||||
} from './dag-config'; |
||||
|
||||
interface Options { |
||||
graph: Ref<Graph | undefined> |
||||
} |
||||
|
||||
/** |
||||
* Change the style on cell hover and select |
||||
*/ |
||||
export function useCellActive(options: Options) { |
||||
|
||||
const { graph } = options; |
||||
const hoverCell = ref(); |
||||
|
||||
const isStatusIcon = (tagName: string) => { |
||||
if (!tagName) return false; |
||||
return tagName.toLocaleLowerCase() === 'em' || tagName.toLocaleLowerCase() === 'body' |
||||
} |
||||
|
||||
function setEdgeStyle(edge: Edge) { |
||||
const isHover = edge === hoverCell.value; |
||||
const isSelected = graph.value?.isSelected(edge) |
||||
// TODO
|
||||
// const labelName = this.getEdgeLabelName ? this.getEdgeLabelName(edge) : ''
|
||||
let edgeProps = null |
||||
|
||||
if (isHover) { |
||||
edgeProps = _.merge(_.cloneDeep(EDGE), EDGE_HOVER) |
||||
} else if (isSelected) { |
||||
edgeProps = _.merge(_.cloneDeep(EDGE), EDGE_SELECTED) |
||||
} else { |
||||
edgeProps = _.cloneDeep(EDGE) |
||||
} |
||||
|
||||
edge.setAttrs(edgeProps.attrs) |
||||
edge.setLabels([ |
||||
{ |
||||
..._.merge( |
||||
{ |
||||
attrs: _.cloneDeep(edgeProps.defaultLabel.attrs) |
||||
}, |
||||
// {
|
||||
// attrs: { label: { text: labelName } }
|
||||
// }
|
||||
) |
||||
} |
||||
]) |
||||
} |
||||
|
||||
function setNodeStyle(node: Node) { |
||||
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 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) |
||||
|
||||
let img = null |
||||
let nodeAttrs = null |
||||
let portAttrs = null |
||||
|
||||
if (isHover || isSelected) { |
||||
img = `/src/assets/images/task-icons/${node.data.taskType.toLocaleLowerCase()}_hover.png` |
||||
if (isHover) { |
||||
nodeAttrs = nodeHover |
||||
portAttrs = _.merge(portDefault, portHover) |
||||
} else { |
||||
nodeAttrs = nodeSelected |
||||
portAttrs = _.merge(portDefault, portSelected) |
||||
} |
||||
} else { |
||||
img = `/src/assets/images/task-icons/${node.data.taskType.toLocaleLowerCase()}.png` |
||||
nodeAttrs = NODE.attrs |
||||
portAttrs = portDefault |
||||
} |
||||
node.setAttrByPath('image/xlink:href', img) |
||||
node.setAttrs(nodeAttrs) |
||||
node.setPortProp( |
||||
X6_PORT_OUT_NAME, |
||||
'attrs', |
||||
portAttrs |
||||
) |
||||
} |
||||
|
||||
function updateCellStyle(cell: Cell) { |
||||
if (cell.isEdge()) { |
||||
setEdgeStyle(cell) |
||||
} else if (cell.isNode()) { |
||||
setNodeStyle(cell) |
||||
} |
||||
} |
||||
|
||||
onMounted(() => { |
||||
if (graph.value) { |
||||
// hover
|
||||
graph.value.on('cell:mouseenter', (data) => { |
||||
const { cell, e } = data |
||||
if (!isStatusIcon(e.target.tagName)) { |
||||
hoverCell.value = cell |
||||
updateCellStyle(cell) |
||||
} |
||||
}) |
||||
graph.value.on('cell:mouseleave', ({ cell }) => { |
||||
hoverCell.value = undefined |
||||
updateCellStyle(cell) |
||||
}) |
||||
|
||||
// select
|
||||
graph.value.on('cell:selected', ({ cell }) => { |
||||
updateCellStyle(cell) |
||||
}) |
||||
graph.value.on('cell:unselected', ({ cell }) => { |
||||
updateCellStyle(cell) |
||||
}) |
||||
} |
||||
}) |
||||
|
||||
return { |
||||
hoverCell |
||||
} |
||||
} |
@ -0,0 +1,157 @@
|
||||
/* |
||||
* 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 { 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'; |
||||
|
||||
interface Options { |
||||
graph: Ref<Graph | undefined> |
||||
} |
||||
|
||||
type Coordinate = { x: number; y: number; } |
||||
|
||||
/** |
||||
* Expose some graph operation methods |
||||
* @param {Options} options |
||||
*/ |
||||
export function useGraphOperations(options: Options) { |
||||
|
||||
const { graph } = options; |
||||
|
||||
|
||||
/** |
||||
* Build edge metadata |
||||
* @param {string} sourceId |
||||
* @param {string} targetId |
||||
* @param {string} label |
||||
*/ |
||||
function buildEdgeMetadata(sourceId: string, targetId: string, label: string = ''): Edge.Metadata { |
||||
return { |
||||
shape: X6_EDGE_NAME, |
||||
source: { |
||||
cell: sourceId |
||||
}, |
||||
target: { |
||||
cell: targetId |
||||
}, |
||||
labels: label ? [label] : undefined |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Build node metadata |
||||
* @param {string} id |
||||
* @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; |
||||
return { |
||||
id: id, |
||||
shape: X6_NODE_NAME, |
||||
x: coordinate.x, |
||||
y: coordinate.y, |
||||
data: { |
||||
taskType: type, |
||||
taskName: taskName || id |
||||
}, |
||||
attrs: { |
||||
image: { |
||||
// Use href instead of xlink:href, you may lose the icon when downloadPNG
|
||||
'xlink:href': `/src/assets/images/task-icons/${type.toLocaleLowerCase()}.png` |
||||
}, |
||||
title: { |
||||
text: truncation |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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 (!ALL_TASK_TYPES[type]) { |
||||
console.warn(`taskType:${type} is invalid!`) |
||||
return |
||||
} |
||||
const node = buildNodeMetadata(id, type, '', coordinate) |
||||
graph.value?.addNode(node) |
||||
} |
||||
|
||||
/** |
||||
* 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 }) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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 |
||||
} |
||||
}) |
||||
} |
||||
|
||||
/** |
||||
* 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 { |
||||
buildEdgeMetadata, |
||||
buildNodeMetadata, |
||||
addNode, |
||||
setNodeName, |
||||
getNodes, |
||||
navigateTo, |
||||
} |
||||
} |
@ -0,0 +1,60 @@
|
||||
/* |
||||
* 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 { Graph } from '@antv/x6'; |
||||
import { ref, Ref } from 'vue' |
||||
import { useGraphOperations } from './dag-hooks'; |
||||
|
||||
|
||||
interface Options { |
||||
graph: Ref<Graph | undefined>; |
||||
} |
||||
|
||||
/** |
||||
* Node search and navigate |
||||
*/ |
||||
export function useNodeSearch(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 => { |
||||
return { |
||||
label: node.name, |
||||
value: node.code |
||||
} |
||||
}) |
||||
} |
||||
|
||||
return { |
||||
searchNode, |
||||
getAllNodes, |
||||
allNodes, |
||||
toggleSearchInput, |
||||
searchInputVisible, |
||||
} |
||||
} |
@ -0,0 +1,48 @@
|
||||
/* |
||||
* 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 { Dragged } from './dag'; |
||||
|
||||
interface Options { |
||||
readonly: Ref<boolean>; |
||||
dragged: Ref<Dragged>; |
||||
} |
||||
|
||||
/** |
||||
* Sidebar drag |
||||
*/ |
||||
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 |
||||
} |
||||
} |
||||
|
||||
return { |
||||
onDragStart |
||||
} |
||||
} |
@ -0,0 +1,22 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
.container{ |
||||
width: 100%; |
||||
box-sizing: border-box; |
||||
height: calc(100vh - 100px); |
||||
} |
@ -0,0 +1,38 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
import { defineComponent } from 'vue' |
||||
import Dag from './dag'; |
||||
import { NCard } from 'naive-ui'; |
||||
import styles from './workflow-definition-create.module.scss'; |
||||
|
||||
export default defineComponent({ |
||||
name: "WorkflowDefinitionCreate", |
||||
setup() { |
||||
|
||||
const slots = { |
||||
toolbarLeft: () => <span>left-operations</span>, |
||||
toolbarRight: () => <span>right-operations</span> |
||||
}; |
||||
|
||||
return () => ( |
||||
<NCard class={styles.container}> |
||||
<Dag v-slots={slots} /> |
||||
</NCard> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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' |
||||
|
||||
export default defineComponent({ |
||||
name: "WorkflowDefinitionDetails", |
||||
setup() { |
||||
return () => ( |
||||
<div>WorkflowDefinitionDetails</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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' |
||||
|
||||
export default defineComponent({ |
||||
name: "WorkflowDefinitionList", |
||||
setup() { |
||||
return () => ( |
||||
<div>WorkflowDefinitionList</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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' |
||||
|
||||
export default defineComponent({ |
||||
name: "WorkflowInstanceDetails", |
||||
setup() { |
||||
return () => ( |
||||
<div>WorkflowInstanceDetails</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,27 @@
|
||||
/* |
||||
* 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' |
||||
|
||||
export default defineComponent({ |
||||
name: "WorkflowInstanceList", |
||||
setup() { |
||||
return () => ( |
||||
<div>WorkflowInstanceList</div> |
||||
) |
||||
} |
||||
}) |
@ -0,0 +1,35 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
$STROKE_BLUE: #288fff; |
||||
$BG_WHITE: #ffffff; |
||||
|
||||
.x6-node[data-shape="dag-task"] { |
||||
&.available { |
||||
.dag-task-body { |
||||
stroke: $STROKE_BLUE; |
||||
stroke-width: 1; |
||||
stroke-dasharray: 5, 2; |
||||
} |
||||
&.adsorbed { |
||||
.dag-task-body { |
||||
stroke-width: 3; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|