From f9e4d84297065dd666108a3ec83eb217c22afae5 Mon Sep 17 00:00:00 2001
From: braks <78412429+bcakmakoglu@users.noreply.github.com>
Date: Tue, 6 Feb 2024 23:36:49 +0100
Subject: [PATCH] chore(docs): update layout example styles
---
docs/examples/layout/App.vue | 47 ++++++--
docs/examples/layout/ProcessNode.vue | 35 +++---
docs/examples/layout/initial-elements.js | 1 +
docs/examples/layout/useRunProcess.js | 100 ++++++++++++------
.../vite/src/Layouting/LayoutingExample.vue | 55 ++++++++--
examples/vite/src/Layouting/ProcessNode.vue | 34 +++---
.../vite/src/Layouting/initial-elements.ts | 2 +-
examples/vite/src/Layouting/useRunProcess.ts | 100 ++++++++++++------
8 files changed, 252 insertions(+), 122 deletions(-)
diff --git a/docs/examples/layout/App.vue b/docs/examples/layout/App.vue
index 53a50541..1ccc05ac 100644
--- a/docs/examples/layout/App.vue
+++ b/docs/examples/layout/App.vue
@@ -14,9 +14,7 @@ const edges = ref(initialEdges)
const dagreGraph = ref(new dagre.graphlib.Graph())
-dagreGraph.value.setDefaultEdgeLabel(() => ({}))
-
-const { run } = useRunProcess()
+const { run, stop, isRunning } = useRunProcess(dagreGraph)
const { findNode, fitView } = useVueFlow()
@@ -69,11 +67,14 @@ function handleLayout(direction) {
-
+
+
-
+
+
+
@@ -81,12 +82,42 @@ function handleLayout(direction) {
diff --git a/docs/examples/layout/ProcessNode.vue b/docs/examples/layout/ProcessNode.vue
index f97c3c3b..d0f297cd 100644
--- a/docs/examples/layout/ProcessNode.vue
+++ b/docs/examples/layout/ProcessNode.vue
@@ -24,12 +24,11 @@ const bgColor = toRef(() => {
return '#10b981'
}
- if (props.data.isRunning || props.data.isSkipped) {
- // pick me a lighter color please
- return '#6b7280'
+ if (props.data.isCancelled) {
+ return '#fbbf24'
}
- return '#1a192b'
+ return '#4b5563'
})
@@ -38,12 +37,12 @@ const bgColor = toRef(() => {
-
+
+ ❌
+ 🚧
+ 😎
+ 🚫
+ 📦
@@ -51,22 +50,22 @@ const bgColor = toRef(() => {
.process-node {
padding: 10px;
color: white;
- border: 1px solid #1a192b;
border-radius: 99px;
- font-size: 10px;
- width: 15px;
- height: 15px;
+ font-size: 12px;
+ width: 18px;
+ height: 18px;
display: flex;
align-items: center;
justify-content: center;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.spinner {
- border: 2px solid #f3f3f3;
- border-top: 2px solid #3498db;
+ border: 3px solid #f3f3f3;
+ border-top: 3px solid #10b981;
border-radius: 50%;
- width: 8px;
- height: 8px;
+ width: 10px;
+ height: 10px;
animation: spin 1s linear infinite;
}
diff --git a/docs/examples/layout/initial-elements.js b/docs/examples/layout/initial-elements.js
index 84d6b8aa..80b104cd 100644
--- a/docs/examples/layout/initial-elements.js
+++ b/docs/examples/layout/initial-elements.js
@@ -67,6 +67,7 @@ export const initialEdges = [
{ id: 'e2-2b', source: '2', target: '2b', type: 'smoothstep', animated: true },
{ id: 'e2-2c', source: '2', target: '2c', type: 'smoothstep', animated: true },
{ id: 'e2c-2d', source: '2c', target: '2d', type: 'smoothstep', animated: true },
+ { id: 'e3-7', source: '3', target: '4', type: 'smoothstep', animated: true },
{ id: 'e4-5', source: '4', target: '5', type: 'smoothstep', animated: true },
{ id: 'e5-6', source: '5', target: '6', type: 'smoothstep', animated: true },
{ id: 'e5-7', source: '5', target: '7', type: 'smoothstep', animated: true },
diff --git a/docs/examples/layout/useRunProcess.js b/docs/examples/layout/useRunProcess.js
index b3f7163c..eb48410f 100644
--- a/docs/examples/layout/useRunProcess.js
+++ b/docs/examples/layout/useRunProcess.js
@@ -1,4 +1,4 @@
-import { ref } from 'vue'
+import { ref, toRef, toValue } from 'vue'
import { useVueFlow } from '@vue-flow/core'
/**
@@ -9,80 +9,112 @@ import { useVueFlow } from '@vue-flow/core'
*
* When a node has multiple descendants, it will run them in parallel.
*/
-export function useRunProcess() {
+export function useRunProcess(dagreGraph) {
const { updateNodeData } = useVueFlow()
- const running = ref(false)
- const executedNodes = new Set()
+ const graph = toRef(() => toValue(dagreGraph))
- async function runNode(node, dagreGraph) {
+ const isRunning = ref(false)
+ const executedNodes = new Set()
+ const runningTasks = new Map()
+
+ async function runNode(node) {
if (executedNodes.has(node.id)) {
return
}
executedNodes.add(node.id)
- updateNodeData(node.id, { isRunning: true, isFinished: false, hasError: false })
+ updateNodeData(node.id, { isRunning: true, isFinished: false, hasError: false, isCancelled: false })
// Simulate an async process with a random timeout between 1 and 3 seconds
const delay = Math.floor(Math.random() * 2000) + 1000
- await new Promise((resolve) => setTimeout(resolve, delay))
+ return new Promise((resolve) => {
+ const timeout = setTimeout(async () => {
+ const children = graph.value.successors(node.id)
- const children = dagreGraph.successors(node.id)
+ // Randomly decide whether the node will throw an error
+ const willThrowError = Math.random() < 0.15
- // Randomly decide whether the node will throw an error
- const willThrowError = Math.random() < 0.15
+ if (willThrowError) {
+ updateNodeData(node.id, { isRunning: false, hasError: true })
- if (willThrowError) {
- updateNodeData(node.id, { isRunning: false, hasError: true })
+ await skipDescendants(node.id)
+ runningTasks.delete(node.id)
- await skipDescendants(node.id, dagreGraph)
- return
- }
+ resolve()
+ return
+ }
- updateNodeData(node.id, { isRunning: false, isFinished: true })
+ updateNodeData(node.id, { isRunning: false, isFinished: true })
- // Run the process on the children in parallel
- await Promise.all(
- children.map((id) => {
- return runNode({ id }, dagreGraph)
- }),
- )
+ runningTasks.delete(node.id)
+
+ if (children.length > 0) {
+ // Run the process on the children in parallel
+ await Promise.all(children.map((id) => runNode({ id })))
+ }
+
+ resolve()
+ }, delay)
+
+ runningTasks.set(node.id, timeout)
+ })
}
- async function run(nodes, dagreGraph) {
- if (running.value) {
+ async function run(nodes) {
+ if (isRunning.value) {
return
}
reset(nodes)
- running.value = true
+ isRunning.value = true
// Get all starting nodes (nodes with no predecessors)
- const startingNodes = nodes.filter((node) => dagreGraph.predecessors(node.id)?.length === 0)
+ const startingNodes = nodes.filter((node) => graph.value.predecessors(node.id)?.length === 0)
// Run the process on all starting nodes in parallel
- await Promise.all(startingNodes.map((node) => runNode(node, dagreGraph)))
+ await Promise.all(startingNodes.map(runNode))
- running.value = false
- executedNodes.clear()
+ clear()
}
function reset(nodes) {
+ clear()
+
for (const node of nodes) {
- updateNodeData(node.id, { isRunning: false, isFinished: false, hasError: false, isSkipped: false })
+ updateNodeData(node.id, { isRunning: false, isFinished: false, hasError: false, isSkipped: false, isCancelled: false })
}
}
- async function skipDescendants(nodeId, dagreGraph) {
- const children = dagreGraph.successors(nodeId)
+ async function skipDescendants(nodeId) {
+ const children = graph.value.successors(nodeId)
for (const child of children) {
updateNodeData(child, { isRunning: false, isSkipped: true })
- await skipDescendants(child, dagreGraph)
+ await skipDescendants(child)
}
}
- return { run, running }
+ function stop() {
+ isRunning.value = false
+
+ for (const [nodeId, task] of runningTasks) {
+ clearTimeout(task)
+ runningTasks.delete(nodeId)
+ updateNodeData(nodeId, { isRunning: false, isFinished: false, hasError: false, isSkipped: false, isCancelled: true })
+ skipDescendants(nodeId)
+ }
+
+ executedNodes.clear()
+ }
+
+ function clear() {
+ isRunning.value = false
+ executedNodes.clear()
+ runningTasks.clear()
+ }
+
+ return { run, stop, reset, isRunning }
}
diff --git a/examples/vite/src/Layouting/LayoutingExample.vue b/examples/vite/src/Layouting/LayoutingExample.vue
index d6707b0f..32a6f706 100644
--- a/examples/vite/src/Layouting/LayoutingExample.vue
+++ b/examples/vite/src/Layouting/LayoutingExample.vue
@@ -1,9 +1,6 @@
@@ -26,12 +26,12 @@ const bgColor = toRef(() => {
-
+
+ ❌
+ 🚧
+ 😎
+ 🚫
+ 📦
@@ -39,22 +39,22 @@ const bgColor = toRef(() => {
.process-node {
padding: 10px;
color: white;
- border: 1px solid #1a192b;
+ border: 1px solid #4b5563;
border-radius: 99px;
- font-size: 10px;
- width: 15px;
- height: 15px;
+ font-size: 12px;
+ width: 18px;
+ height: 18px;
display: flex;
align-items: center;
justify-content: center;
}
.spinner {
- border: 2px solid #f3f3f3;
- border-top: 2px solid #3498db;
+ border: 3px solid #f3f3f3;
+ border-top: 3px solid #10b981;
border-radius: 50%;
- width: 8px;
- height: 8px;
+ width: 10px;
+ height: 10px;
animation: spin 1s linear infinite;
}
diff --git a/examples/vite/src/Layouting/initial-elements.ts b/examples/vite/src/Layouting/initial-elements.ts
index 962746cc..ee7af56b 100644
--- a/examples/vite/src/Layouting/initial-elements.ts
+++ b/examples/vite/src/Layouting/initial-elements.ts
@@ -6,7 +6,6 @@ const type: string = 'process'
export const initialNodes: Node[] = [
{
id: '1',
- label: 'Start',
position,
type,
},
@@ -69,6 +68,7 @@ export const initialEdges: Edge[] = [
{ id: 'e2-2b', source: '2', target: '2b', type: 'smoothstep', animated: true },
{ id: 'e2-2c', source: '2', target: '2c', type: 'smoothstep', animated: true },
{ id: 'e2c-2d', source: '2c', target: '2d', type: 'smoothstep', animated: true },
+ { id: 'e3-7', source: '3', target: '4', type: 'smoothstep', animated: true },
{ id: 'e4-5', source: '4', target: '5', type: 'smoothstep', animated: true },
{ id: 'e5-6', source: '5', target: '6', type: 'smoothstep', animated: true },
{ id: 'e5-7', source: '5', target: '7', type: 'smoothstep', animated: true },
diff --git a/examples/vite/src/Layouting/useRunProcess.ts b/examples/vite/src/Layouting/useRunProcess.ts
index add31528..960c8f9c 100644
--- a/examples/vite/src/Layouting/useRunProcess.ts
+++ b/examples/vite/src/Layouting/useRunProcess.ts
@@ -1,5 +1,7 @@
+import type dagre from 'dagre'
import type { Node } from '@vue-flow/core'
import { useVueFlow } from '@vue-flow/core'
+import type { MaybeRefOrGetter } from 'vue'
/**
* Composable to simulate running a process tree.
@@ -9,80 +11,112 @@ import { useVueFlow } from '@vue-flow/core'
*
* When a node has multiple descendants, it will run them in parallel.
*/
-export function useRunProcess() {
+export function useRunProcess(dagreGraph: MaybeRefOrGetter) {
const { updateNodeData } = useVueFlow()
- const running = ref(false)
- const executedNodes = new Set()
+ const graph = toRef(() => toValue(dagreGraph))
- async function runNode(node: { id: string }, dagreGraph: dagre.graphlib.Graph) {
+ const isRunning = ref(false)
+ const executedNodes = new Set()
+ const runningTasks = new Map()
+
+ async function runNode(node: { id: string }) {
if (executedNodes.has(node.id)) {
return
}
executedNodes.add(node.id)
- updateNodeData(node.id, { isRunning: true, isFinished: false, hasError: false })
+ updateNodeData(node.id, { isRunning: true, isFinished: false, hasError: false, isCancelled: false })
// Simulate an async process with a random timeout between 1 and 3 seconds
const delay = Math.floor(Math.random() * 2000) + 1000
- await new Promise((resolve) => setTimeout(resolve, delay))
+ return new Promise((resolve) => {
+ const timeout = setTimeout(async () => {
+ const children = graph.value.successors(node.id) as unknown as string[]
- const children = dagreGraph.successors(node.id) as unknown as string[]
+ // Randomly decide whether the node will throw an error
+ const willThrowError = Math.random() < 0.15
- // Randomly decide whether the node will throw an error
- const willThrowError = Math.random() < 0.15
+ if (willThrowError) {
+ updateNodeData(node.id, { isRunning: false, hasError: true })
- if (willThrowError) {
- updateNodeData(node.id, { isRunning: false, hasError: true })
+ await skipDescendants(node.id)
+ runningTasks.delete(node.id)
- await skipDescendants(node.id, dagreGraph)
- return
- }
+ resolve()
+ return
+ }
- updateNodeData(node.id, { isRunning: false, isFinished: true })
+ updateNodeData(node.id, { isRunning: false, isFinished: true })
+ console.log(`Node ${node.id} finished`)
+ runningTasks.delete(node.id)
- // Run the process on the children in parallel
- await Promise.all(
- children.map((id) => {
- return runNode({ id }, dagreGraph)
- }),
- )
+ if (children.length > 0) {
+ // Run the process on the children in parallel
+ await Promise.all(children.map((id) => runNode({ id })))
+ }
+
+ resolve()
+ }, delay)
+
+ runningTasks.set(node.id, timeout)
+ })
}
- async function run(nodes: Node[], dagreGraph: dagre.graphlib.Graph) {
- if (running.value) {
+ async function run(nodes: Node[]) {
+ if (isRunning.value) {
return
}
reset(nodes)
- running.value = true
+ isRunning.value = true
// Get all starting nodes (nodes with no predecessors)
- const startingNodes = nodes.filter((node) => dagreGraph.predecessors(node.id)?.length === 0)
+ const startingNodes = nodes.filter((node) => graph.value.predecessors(node.id)?.length === 0)
// Run the process on all starting nodes in parallel
- await Promise.all(startingNodes.map((node) => runNode(node, dagreGraph)))
+ await Promise.all(startingNodes.map(runNode))
- running.value = false
- executedNodes.clear()
+ clear()
}
function reset(nodes: Node[]) {
+ clear()
+
for (const node of nodes) {
- updateNodeData(node.id, { isRunning: false, isFinished: false, hasError: false, isSkipped: false })
+ updateNodeData(node.id, { isRunning: false, isFinished: false, hasError: false, isSkipped: false, isCancelled: false })
}
}
- async function skipDescendants(nodeId: string, dagreGraph: dagre.graphlib.Graph) {
- const children = dagreGraph.successors(nodeId) as unknown as string[]
+ async function skipDescendants(nodeId: string) {
+ const children = graph.value.successors(nodeId) as unknown as string[]
for (const child of children) {
updateNodeData(child, { isRunning: false, isSkipped: true })
- await skipDescendants(child, dagreGraph)
+ await skipDescendants(child)
}
}
- return { run, running }
+ function stop() {
+ isRunning.value = false
+
+ for (const [nodeId, task] of runningTasks) {
+ clearTimeout(task)
+ runningTasks.delete(nodeId)
+ updateNodeData(nodeId, { isRunning: false, isFinished: false, hasError: false, isSkipped: false, isCancelled: true })
+ skipDescendants(nodeId)
+ }
+
+ executedNodes.clear()
+ }
+
+ function clear() {
+ isRunning.value = false
+ executedNodes.clear()
+ runningTasks.clear()
+ }
+
+ return { run, stop, reset, isRunning }
}