This is an automated email from the ASF dual-hosted git repository.
nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-paimon-webui.git
The following commit(s) were added to refs/heads/main by this push:
new a4932f2 [Feature] Introduce x6 dag component (#88)
a4932f2 is described below
commit a4932f2f2207c0e85238410d0847f328682cef1d
Author: labbomb <[email protected]>
AuthorDate: Tue Oct 31 11:08:26 2023 +0800
[Feature] Introduce x6 dag component (#88)
---
paimon-web-ui-new/package.json | 3 +
paimon-web-ui-new/pnpm-lock.yaml | 57 +++++++++-
paimon-web-ui-new/src/locales/en/modules/cdc.ts | 1 +
paimon-web-ui-new/src/locales/zh/modules/cdc.ts | 1 +
paimon-web-ui-new/src/main.ts | 13 ---
.../src/views/cdc/components/dag/custom-node.tsx | 63 +++++++++++
.../components/dag/{index.tsx => dag-canvas.tsx} | 23 +++-
.../src/views/cdc/components/dag/dag-slider.tsx | 121 +++++++++++++++++++++
.../src/views/cdc/components/dag/index.module.scss | 68 ++++++++++++
.../src/views/cdc/components/dag/index.tsx | 37 ++++++-
.../src/views/cdc/components/dag/node-config.ts | 106 ++++++++++++++++++
.../views/cdc/components/dag/use-canvas-init.ts | 113 +++++++++++++++++++
12 files changed, 585 insertions(+), 21 deletions(-)
diff --git a/paimon-web-ui-new/package.json b/paimon-web-ui-new/package.json
index 27fd659..ae38941 100644
--- a/paimon-web-ui-new/package.json
+++ b/paimon-web-ui-new/package.json
@@ -12,6 +12,9 @@
"format": "prettier --write src/"
},
"dependencies": {
+ "@antv/x6": "^2.15.3",
+ "@antv/x6-plugin-dnd": "^2.1.1",
+ "@antv/x6-vue-shape": "^2.1.1",
"dart-sass": "^1.25.0",
"lodash": "^4.17.21",
"mitt": "^3.0.1",
diff --git a/paimon-web-ui-new/pnpm-lock.yaml b/paimon-web-ui-new/pnpm-lock.yaml
index 6252459..918a970 100644
--- a/paimon-web-ui-new/pnpm-lock.yaml
+++ b/paimon-web-ui-new/pnpm-lock.yaml
@@ -20,6 +20,15 @@
lockfileVersion: '6.0'
dependencies:
+ '@antv/x6':
+ specifier: ^2.15.3
+ version: 2.15.3
+ '@antv/x6-plugin-dnd':
+ specifier: ^2.1.1
+ version: 2.1.1(@antv/[email protected])
+ '@antv/x6-vue-shape':
+ specifier: ^2.1.1
+ version: 2.1.1(@antv/[email protected])([email protected])
dart-sass:
specifier: ^1.25.0
version: 1.25.0
@@ -147,6 +156,48 @@ packages:
resolution: {integrity:
sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==}
dev: true
+ /@antv/[email protected]:
+ resolution: {integrity:
sha512-9ghYsxbT7WjQ0thqjcQwnjuBdL8DSTptEubf0DvBZOJ0wmapclXqYPOM+XYPNtC1dcKDqqxsw5mdcbcAmQ224Q==}
+ dependencies:
+ lodash-es: 4.17.21
+ utility-types: 3.10.0
+ dev: false
+
+ /@antv/[email protected]:
+ resolution: {integrity:
sha512-MId6riEQkxphBpVeTcL4ZNXL4lScyvDEPLyIafvWMcWNTGK0jgkK7N20XSzqt8ltJb0mGUso5s56mrk8ysHu2A==}
+ dev: false
+
+ /@antv/[email protected](@antv/[email protected]):
+ resolution: {integrity:
sha512-v0szzik1RkadPDn4Qi5mOSaB2AeI78D40/YuCYbPVzplG+HydGsHwO3MLTgJPQ+R5n0eM0W5F850p1VfTOHR7g==}
+ peerDependencies:
+ '@antv/x6': ^2.x
+ dependencies:
+ '@antv/x6': 2.15.3
+ dev: false
+
+ /@antv/[email protected](@antv/[email protected])([email protected]):
+ resolution: {integrity:
sha512-XQwKyQmKH1m12tQ7ybh/p3XXe/XKWEa6zihoIb/IQd+w5WyTTosVfgXbn1io3Nb6zXc2R853R6iGe+T1+tWhfg==}
+ peerDependencies:
+ '@antv/x6': ^2.x
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^2.0.0 || >=3.0.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dependencies:
+ '@antv/x6': 2.15.3
+ vue: 3.3.4
+ vue-demi: 0.14.6([email protected])
+ dev: false
+
+ /@antv/[email protected]:
+ resolution: {integrity:
sha512-mI8Aqc/0+/ZlXguibnKovGkKy3w7UFg+CMwAq5oYdBrMEgwgvQ/Rw9tK2LOTgKAINv+5QQ9zJTY058Kv1UfeRA==}
+ dependencies:
+ '@antv/x6-common': 2.0.15
+ '@antv/x6-geometry': 2.0.5
+ utility-types: 3.10.0
+ dev: false
+
/@babel/[email protected]:
resolution: {integrity:
sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
engines: {node: '>=6.9.0'}
@@ -2707,7 +2758,6 @@ packages:
/[email protected]:
resolution: {integrity:
sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
- dev: true
/[email protected]:
resolution: {integrity:
sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
@@ -3828,6 +3878,11 @@ packages:
resolution: {integrity:
sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: true
+ /[email protected]:
+ resolution: {integrity:
sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==}
+ engines: {node: '>= 4'}
+ dev: false
+
/[email protected]:
resolution: {integrity:
sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:
diff --git a/paimon-web-ui-new/src/locales/en/modules/cdc.ts
b/paimon-web-ui-new/src/locales/en/modules/cdc.ts
index b8d2ca3..5d51dcc 100644
--- a/paimon-web-ui-new/src/locales/en/modules/cdc.ts
+++ b/paimon-web-ui-new/src/locales/en/modules/cdc.ts
@@ -33,4 +33,5 @@ export default {
task_description: 'Task Description',
single_table_synchronization: 'Single Table Synchronization',
whole_database_synchronization: 'Whole Database Synchronization',
+ save: 'Save',
}
diff --git a/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
b/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
index f80b3d0..bf7e738 100644
--- a/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
+++ b/paimon-web-ui-new/src/locales/zh/modules/cdc.ts
@@ -33,4 +33,5 @@ export default {
task_description: '任务描述',
single_table_synchronization: '单表同步',
whole_database_synchronization: '整库同步',
+ save: '保存',
}
diff --git a/paimon-web-ui-new/src/main.ts b/paimon-web-ui-new/src/main.ts
index 303ab83..6c4a9b4 100644
--- a/paimon-web-ui-new/src/main.ts
+++ b/paimon-web-ui-new/src/main.ts
@@ -37,16 +37,3 @@ app.use(naive)
app.config.globalProperties.mittBus = mitt()
app.mount('#app')
-
-console.clear();
-
-console.log(
- `%c© Msi%c(Integration)\n%c${Setting.version}`,
- `padding:24px 0px 12px 0px;
- font-size:24px;
- color:#66CCFF;`,
- 'font-size:24px;color:#FFE212;',
- 'font-size:12px;color:#FFBFCB;padding-bottom:24px;',
-);
-
-console.group('%cConsole', 'font-size:12px;color:#39C5BB;font-weight:300;');
diff --git a/paimon-web-ui-new/src/views/cdc/components/dag/custom-node.tsx
b/paimon-web-ui-new/src/views/cdc/components/dag/custom-node.tsx
new file mode 100644
index 0000000..d90682c
--- /dev/null
+++ b/paimon-web-ui-new/src/views/cdc/components/dag/custom-node.tsx
@@ -0,0 +1,63 @@
+/* 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 styles from './index.module.scss'
+
+export default defineComponent({
+ name: 'CustomNode',
+ setup() {
+ const getNode = inject('getNode') as any
+ const node = getNode()
+ const data = node.data
+ const onMainMouseEnter = () => {
+ const ports = node.getPorts() || []
+ ports.forEach((port: { id: any }) => {
+ node.setPortProp(port.id, 'attrs/circle', {
+ fill: '#fff',
+ stroke: '#85A5FF',
+ })
+ })
+ }
+
+ const onMainMouseLeave = () => {
+ const ports = node.getPorts() || []
+ ports.forEach((port: { id: any }) => {
+ node.setPortProp(port.id, 'attrs/circle', {
+ fill: 'transparent',
+ stroke: 'transparent',
+ })
+ })
+ }
+
+ return {
+ data,
+ onMainMouseEnter,
+ onMainMouseLeave,
+ }
+ },
+ render() {
+ return (
+ <div
+ class={styles['custom-node']}
+ onMouseenter={this.onMainMouseEnter}
+ onMouseleave={this.onMainMouseLeave}
+ >
+ {this.data.name}
+ </div>
+ )
+ }
+})
diff --git a/paimon-web-ui-new/src/views/cdc/components/dag/index.tsx
b/paimon-web-ui-new/src/views/cdc/components/dag/dag-canvas.tsx
similarity index 68%
copy from paimon-web-ui-new/src/views/cdc/components/dag/index.tsx
copy to paimon-web-ui-new/src/views/cdc/components/dag/dag-canvas.tsx
index 94eef79..ede6799 100644
--- a/paimon-web-ui-new/src/views/cdc/components/dag/index.tsx
+++ b/paimon-web-ui-new/src/views/cdc/components/dag/dag-canvas.tsx
@@ -15,19 +15,34 @@ 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 styles from './index.module.scss'
+import DagSlider from './dag-slider'
+
export default defineComponent({
- name: 'DagPage',
+ name: 'DagCanvasPage',
setup() {
const { t } = useLocaleHooks()
-
+
+ const { graph, dnd } = useCanvasInit()
+
return {
t,
+ graph,
+ dnd
}
},
render() {
return (
- <div>
- DAG
+ <div class={styles.dag}>
+ <div
+ class={styles['dag-container']}
+ id="dag-container"
+ />
+ <DagSlider
+ graph={this.graph}
+ dnd={this.dnd}
+ />
</div>
)
}
diff --git a/paimon-web-ui-new/src/views/cdc/components/dag/dag-slider.tsx
b/paimon-web-ui-new/src/views/cdc/components/dag/dag-slider.tsx
new file mode 100644
index 0000000..982a474
--- /dev/null
+++ b/paimon-web-ui-new/src/views/cdc/components/dag/dag-slider.tsx
@@ -0,0 +1,121 @@
+/* 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 styles from './index.module.scss'
+import { getPortsByType } from './node-config'
+
+export default defineComponent({
+ name: 'DagSlider',
+ props: {
+ graph: {
+ type: Object,
+ default: () => {}
+ },
+ dnd: {
+ type: Object,
+ default: () => {}
+ }
+ },
+ setup(props) {
+ const { t } = useLocaleHooks()
+ const sliderVariables = reactive({
+ sourceList: [
+ {
+ name: 'MySQL',
+ value: 'mysql',
+ type: 'INPUT'
+ },
+ {
+ name: 'Kafka',
+ value: 'kafka',
+ type: 'INPUT'
+ },
+ {
+ name: 'MongoDB',
+ value: 'mongodb',
+ type: 'INPUT'
+ },
+ {
+ name: 'PostgreSQL',
+ value: 'postgresql',
+ type: 'INPUT'
+ }
+ ],
+ sinkList: [
+ {
+ name: 'Paimon',
+ value: 'paimon',
+ type: 'OUTPUT'
+ }
+ ]
+ })
+
+ const handleNodeMove = (e: any, item: any) => {
+ const node = props.graph.createNode({
+ id: item.name,
+ shape: 'custom-node',
+ data: item,
+ ports: getPortsByType(item.type, item.name),
+ })
+ props.dnd.start(node, e)
+ }
+
+ return {
+ t,
+ ...toRefs(sliderVariables),
+ handleNodeMove
+ }
+ },
+ render () {
+ return (
+ <div class={styles['dag-slider']} id="dag-slider">
+ <n-card class={styles.card} content-style={'overflow:scroll;'}>
+ <n-space vertical>
+ <div class={styles.source}>
+ <n-space vertical size={15}>
+ <div class={styles['title']}>Source</div>
+ {
+ this.sourceList.map((item) => {
+ return (
+ <n-button class={styles['list-item']} onMousedown={(e:
any) => this.handleNodeMove(e, item)}>
+ {item.name}
+ </n-button>
+ )
+ })
+ }
+ </n-space>
+ </div>
+ <div class={styles.sink}>
+ <n-space vertical size={15}>
+ <div class={styles['title']}>Sink</div>
+ {
+ this.sinkList.map((item) => {
+ return (
+ <n-button class={styles['list-item']} onMousedown={(e:
any) => this.handleNodeMove(e, item)}>
+ {item.name}
+ </n-button>
+ )
+ })
+ }
+ </n-space>
+ </div>
+ </n-space>
+ </n-card>
+ </div>
+ )
+ }
+})
diff --git a/paimon-web-ui-new/src/views/cdc/components/dag/index.module.scss
b/paimon-web-ui-new/src/views/cdc/components/dag/index.module.scss
new file mode 100644
index 0000000..d1dd006
--- /dev/null
+++ b/paimon-web-ui-new/src/views/cdc/components/dag/index.module.scss
@@ -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. */
+
+.title {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+}
+
+.dag {
+ position: relative;
+ width: 100%;
+ height: calc(100vh - 206px);
+
+ .dag-container {
+ border-radius: 5px;
+ }
+
+ .dag-slider {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 250px;
+ height: 100%;
+
+ .card {
+ height: 100%;
+ border-radius: 5px;
+
+ .title {
+ font-size: 18px;
+ }
+
+ .list-item {
+ font-size: 14px;
+ width: 100%;
+ cursor: move;
+ }
+ }
+ }
+}
+
+.custom-node {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ background-color: #fff;
+ border: 1px solid #c2c8d5;
+ border-left: 4px solid #5F95FF;
+ border-radius: 4px;
+ box-shadow: 0 2px 5px 1px rgba(0, 0, 0, 0.06);
+}
diff --git a/paimon-web-ui-new/src/views/cdc/components/dag/index.tsx
b/paimon-web-ui-new/src/views/cdc/components/dag/index.tsx
index 94eef79..8ea45a0 100644
--- a/paimon-web-ui-new/src/views/cdc/components/dag/index.tsx
+++ b/paimon-web-ui-new/src/views/cdc/components/dag/index.tsx
@@ -15,6 +15,10 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License. */
+import { Leaf, Save } from "@vicons/ionicons5"
+import styles from './index.module.scss';
+import DagCanvas from "./dag-canvas";
+
export default defineComponent({
name: 'DagPage',
setup() {
@@ -26,9 +30,36 @@ export default defineComponent({
},
render() {
return (
- <div>
- DAG
- </div>
+ <n-card>
+ <n-space vertical size={24}>
+ <n-card>
+ <div class={styles.title}>
+ <n-space align="center">
+ <n-icon component={Leaf} color="#2F7BEA" size="18" />
+ <span>{this.t('cdc.synchronization_job_definition')}</span>
+ </n-space>
+ <div class={styles.operation}>
+ <n-space>
+ <n-popover trigger="hover" placement="bottom"
+ v-slots={{
+ trigger: () => (
+ <n-button
+ v-slots={{
+ icon: () => <n-icon component={Save}></n-icon>
+ }}
+ >
+ </n-button>
+ )
+ }}>
+ <span>{this.t('cdc.save')}</span>
+ </n-popover>
+ </n-space>
+ </div>
+ </div>
+ </n-card>
+ <DagCanvas></DagCanvas>
+ </n-space>
+ </n-card>
)
}
})
diff --git a/paimon-web-ui-new/src/views/cdc/components/dag/node-config.ts
b/paimon-web-ui-new/src/views/cdc/components/dag/node-config.ts
new file mode 100644
index 0000000..697bb32
--- /dev/null
+++ b/paimon-web-ui-new/src/views/cdc/components/dag/node-config.ts
@@ -0,0 +1,106 @@
+/* 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 enum NodeType {
+ INPUT = 'INPUT', // 数据输入
+ OUTPUT = 'OUTPUT', // 数据输出
+}
+
+export const getPortsByType = (type: NodeType, nodeId: string) => {
+ let ports = []
+ switch (type) {
+ case NodeType.INPUT:
+ ports = [
+ {
+ id: `${nodeId}-out`,
+ group: 'out',
+ },
+ ]
+ break
+ case NodeType.OUTPUT:
+ ports = [
+ {
+ id: `${nodeId}-in`,
+ group: 'in',
+ },
+ ]
+ break
+ default:
+ ports = [
+ {
+ id: `${nodeId}-in`,
+ group: 'in',
+ },
+ {
+ id: `${nodeId}-out`,
+ group: 'out',
+ },
+ ]
+ break
+ }
+ return ports
+}
+
+export const PORT = {
+ groups: {
+ in: {
+ position: 'left',
+ attrs: {
+ circle: {
+ r: 4,
+ magnet: true,
+ stroke: 'transparent',
+ strokeWidth: 1,
+ fill: 'transparent',
+ },
+ },
+ },
+ out: {
+ position: {
+ name: 'right',
+ args: {
+ dx: 5,
+ },
+ },
+ attrs: {
+ circle: {
+ r: 4,
+ magnet: true,
+ stroke: 'transparent',
+ strokeWidth: 1,
+ fill: 'transparent',
+ },
+ },
+ },
+ },
+}
+
+export const EDGE = {
+ attrs: {
+ line: {
+ stroke: '#1890ff',
+ strokeDasharray: 5,
+ targetMarker: 'classic',
+ style: {
+ animation: 'ant-line 30s infinite linear',
+ },
+ },
+ },
+ connector: {
+ name: 'smooth'
+ }
+}
diff --git a/paimon-web-ui-new/src/views/cdc/components/dag/use-canvas-init.ts
b/paimon-web-ui-new/src/views/cdc/components/dag/use-canvas-init.ts
new file mode 100644
index 0000000..59791dc
--- /dev/null
+++ b/paimon-web-ui-new/src/views/cdc/components/dag/use-canvas-init.ts
@@ -0,0 +1,113 @@
+/* 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 { Graph } from '@antv/x6'
+import { Dnd } from '@antv/x6-plugin-dnd'
+import { register } from '@antv/x6-vue-shape'
+import CustomNode from './custom-node'
+import { EDGE, PORT } from './node-config'
+
+register({
+ shape: 'custom-node',
+ width: 150,
+ height: 40,
+ component: CustomNode,
+ ports: {
+ ...PORT
+ }
+})
+
+export function useCanvasInit() {
+ const graph = ref<Graph>()
+ const dnd = ref<Dnd>()
+
+ const graphInit = () => {
+ return new Graph({
+ container: document.getElementById('dag-container') || undefined,
+ // background: {
+ // color: '#F2F7FA',
+ // },
+ autoResize: true,
+ panning: true,
+ mousewheel: true,
+ grid: {
+ visible: true,
+ type: 'dot',
+ size: 20,
+ args: {
+ color: '#a0a0a0',
+ thickness: 1,
+ },
+ },
+ 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: true,
+ // Whether all available ports or nodes are highlighted when you drag
the edge
+ highlight: true,
+ createEdge() {
+ return graph.value?.createEdge({
+ shape: 'dag-edge'
+ })
+ },
+ anchor: {
+ name: 'left',
+ },
+ }
+ })
+ }
+
+ const dndInit = () => {
+ const actualGraph = graph.value // get the actual Graph object from the Ref
+ if (!actualGraph) {
+ throw new Error('Graph object is undefined')
+ }
+ return new Dnd({
+ target: actualGraph,
+ dndContainer: document.getElementById('dag-slider') || undefined,
+ getDragNode: (node) => node.clone({ keepId: true }),
+ getDropNode: (node) => node.clone({ keepId: true }),
+ })
+ }
+
+ const registerCustomCells = () => {
+ Graph.unregisterEdge('dag-edge')
+ Graph.registerEdge('dag-edge', { ...EDGE })
+ }
+
+ onMounted(() => {
+ const actualGraph = graphInit() // get the actual Graph object from the
function
+ graph.value = actualGraph // set the Ref to the actual Graph object
+ const actualDnd = dndInit() // get the actual Dnd object from the function
+ dnd.value = actualDnd // set the Ref to the actual Dnd object
+ registerCustomCells()
+ })
+
+ return {
+ graph,
+ dnd
+ }
+}