Add graph logic to simplify display

This commit is contained in:
Guilhem
2024-10-15 16:24:31 +02:00
parent 48834f46ba
commit b7485cf5ab
6 changed files with 261 additions and 54 deletions
@@ -139,7 +139,7 @@
style="width: 275px; height: 34px; background-color: {bgColor};"
on:mouseenter={() => (hover = true)}
on:mouseleave={() => (hover = false)}
on:click
on:click|preventDefault|stopPropagation
>
<div class="absolute text-sm right-12 -bottom-3 flex flex-row gap-1 z-10">
{#if retry}
@@ -256,6 +256,7 @@
}
}
}
$: console.log('has schedule poll', hasSchedulePoll)
</script>
<Portal name="flow-module">
@@ -458,6 +459,9 @@
on:addSchedulePoll={() => {
hasSchedulePoll = true
}}
on:removeSchedulePoll={() => {
hasSchedulePoll = false
}}
/>
</div>
<div
@@ -38,6 +38,7 @@
import Button from '../common/button/Button.svelte'
import FlowYamlEditor from '../flows/header/FlowYamlEditor.svelte'
import SchedulePollNode from './renderers/nodes/ShedulePollNode.svelte'
import tr from 'date-fns/locale/tr'
export let success: boolean | undefined = undefined
export let modules: FlowModule[] | undefined = []
export let failureModule: FlowModule | undefined = undefined
@@ -177,6 +178,9 @@
},
addSchedulePoll: () => {
dispatch('addSchedulePoll')
},
removeSchedulePoll: () => {
dispatch('removeSchedulePoll')
}
},
success,
@@ -201,12 +205,139 @@
let height = 0
function removeInputNode(nodes, edges, id) {
const inputNode = nodes.find((node) => node.id === id)
if (!inputNode) return { nodes, edges }
// Find edges connected to the input node
const connectedEdges = edges.filter((edge) => edge.source === id || edge.target === id)
// Remove the input node
let updatedNodes = nodes.filter((node) => node.id !== id)
// Remove edges connected to the input node
let updatedEdges = edges.filter((edge) => edge.source !== id && edge.target !== id)
// Create new edges from the input node's parent to its children
const inputEdges = connectedEdges.filter((edge) => edge.target === id)
const outputEdges = connectedEdges.filter((edge) => edge.source === id)
inputEdges.forEach((inputEdge) => {
outputEdges.forEach((outputEdge) => {
const newEdge = {
id: `edge:${inputEdge.source}->${outputEdge.target}`,
source: inputEdge.source,
target: outputEdge.target,
type: 'empty',
data: {
...outputEdge.data,
sourceId: inputEdge.source,
targetId: outputEdge.target
}
}
updatedEdges.push(newEdge)
})
})
// Update parent ids of the nodes
updatedNodes = updatedNodes.map((node) => {
if (node.data && node.data.parentIds && node.data.parentIds.includes(id)) {
const updatedParentIds = node.data.parentIds.filter((parentId) => parentId !== id)
if (inputNode.data && inputNode.data.parentIds) {
updatedParentIds.push(...inputNode.data.parentIds)
}
return {
...node,
data: {
...node.data,
parentIds: [...new Set(updatedParentIds)] // Remove duplicates
}
}
}
return node
})
return { nodes: updatedNodes, edges: updatedEdges }
}
function removeTriggerForLoopNodes(nodes, edges) {
let updatedGraph = {
nodes: [...nodes],
edges: [...edges]
}
let forloopNode = updatedGraph.nodes.find((node) => node?.data?.value?.type === 'forloopflow')
if (!forloopNode) {
return updatedGraph
}
if (forloopNode?.data?.value?.parentsIds?.length > 0) {
console.log('triggerScript', forloopNode?.data?.value?.parentsIds[0])
}
let forloopModules = forloopNode?.data?.value?.modules
if (!forloopModules) {
return updatedGraph
}
for (let i = 0; i < forloopModules.length; i++) {
const module = forloopModules[i]
console.log(`Processing module ${i}:`, module)
updatedGraph = removeInputNode(updatedGraph.nodes, updatedGraph.edges, module.id)
}
updatedGraph = removeInputNode(updatedGraph.nodes, updatedGraph.edges, forloopNode.id)
return updatedGraph
}
function removeForLoopStartNodes(nodes, edges) {
let updatedGraph = {
nodes: [...nodes],
edges: [...edges]
}
let forloopNode = updatedGraph.nodes.find((node) => node?.type === 'forLoopStart')
if (!forloopNode) {
return updatedGraph
}
return removeInputNode(updatedGraph.nodes, updatedGraph.edges, forloopNode.id)
}
function removeForLoopEndNodes(nodes, edges) {
let updatedGraph = {
nodes: [...nodes],
edges: [...edges]
}
let forloopNode = updatedGraph.nodes.find((node) => node?.type === 'forLoopEnd')
if (!forloopNode) {
return updatedGraph
}
return removeInputNode(updatedGraph.nodes, updatedGraph.edges, forloopNode.id)
}
function processGraph(graph) {
let newGraph = { nodes: graph.nodes, edges: graph.edges }
newGraph = removeInputNode(newGraph.nodes, newGraph.edges, 'Input')
newGraph = removeTriggerForLoopNodes(newGraph.nodes, newGraph.edges)
newGraph = removeForLoopStartNodes(newGraph.nodes, newGraph.edges)
newGraph = removeForLoopEndNodes(newGraph.nodes, newGraph.edges)
return newGraph
}
function updateStores() {
if (graph.error) {
return
}
$nodes = layoutNodes(graph?.nodes)
if (hasSchedulePoll) {
graph = processGraph(graph)
}
console.log('graph nodes after removal', graph.nodes)
console.log('graph edges after removal', graph.edges)
console.log('graph nodes', graph.nodes)
console.log('graph edges', graph.edges)
$nodes = layoutNodes(graph.nodes)
$edges = graph.edges
console.log('nodes', $nodes)
@@ -15,6 +15,7 @@ export type GraphEventHandlers = {
selectedIteration: (detail, moduleId: string) => void
changeId: (newId: string) => void
addSchedulePoll: () => void
removeSchedulePoll: () => void
}
export default function graphBuilder(
@@ -168,7 +169,8 @@ export default function graphBuilder(
type: 'schedulePoll',
data: {
eventHandlers: eventHandlers,
modules: modules
modules: modules,
...extra
}
}
nodes.push(schedulePollNode)
@@ -1,77 +1,149 @@
<script lang="ts">
import NodeWrapper from './NodeWrapper.svelte'
import FlowModuleSchemaItem from '../../../flows/map/FlowModuleSchemaItem.svelte'
import { Repeat } from 'lucide-svelte'
import { getContext, createEventDispatcher } from 'svelte'
import { Repeat, X } from 'lucide-svelte'
import { getContext } from 'svelte'
import type { Writable } from 'svelte/store'
import type { GraphEventHandlers } from '../../graphBuilder'
import { twMerge } from 'tailwind-merge'
import { NODE } from '../../util'
import InsertModuleButton from '../../../flows/map/InsertModuleButton.svelte'
const dispatch = createEventDispatcher()
import type { FlowModule } from '$lib/gen'
import MapItem from '../../../flows/map/MapItem.svelte'
export let data: {
bgColor: string
eventHandlers: GraphEventHandlers
modules: FlowModule[]
}
const { selectedId } = getContext<{ selectedId: Writable<string> }>('FlowGraphContext')
$: itemProps = {
selected: $selectedId === 'stepid'
}
/* async function deleteSchedulePoll(e) {
data.eventHandlers.delete(e.detail, '')
} */
let componentHeight = 0
let componentHeight = NODE.height
let hover = false
console.log('Modules', data.modules)
let forloopModules: FlowModule[] = []
let triggerModule: FlowModule | undefined = undefined
function getSchedulePollModules() {
let forloopModule = data.modules.find((mod) => mod.value.type === 'forloopflow')
if (forloopModule) {
forloopModules = forloopModule.value.modules
}
console.log('Forloop Modules', forloopModules)
if (data.modules.length > 0) {
triggerModule = data.modules[0]
}
console.log('Trigger Module', triggerModule)
}
$: getSchedulePollModules()
</script>
<NodeWrapper>
<button
class={twMerge(
'flex flex-col gap-2 rounded-sm p-1 z-10 border absolute',
$selectedId === 'schedulePoll'
? 'outline outline-offset-0 outline-2 outline-slate-500 dark:outline-gray-400'
: ''
)}
<NodeWrapper wrapperClass="!shadow-none">
<div
style="width: {NODE.width}px; min-height: {NODE.height}px; transform: translate(0, calc({NODE.height}px - {componentHeight}px));"
on:click={() => data.eventHandlers.select('schedulePoll')}
bind:clientHeight={componentHeight}
>
<div
class="text-2xs text-secondary font-normal text-center rounded-sm w-[80%] border bg-surface"
<button
class={twMerge(
'flex flex-col gap-2 rounded-sm p-1 border absolute grow w-full',
$selectedId === 'schedulePoll'
? 'outline outline-offset-0 outline-2 outline-slate-500 dark:outline-gray-400'
: ''
)}
on:click={() => ($selectedId = 'schedulePoll')}
bind:clientHeight={componentHeight}
on:mouseenter={() => (hover = true)}
on:mouseleave={() => (hover = false)}
>
<div class="flex flex-row gap-2 p-2">
<div>
<Repeat size={16} />
{#if triggerModule}
<div
class="text-2xs text-secondary font-normal text-center rounded-sm shadow-md w-[80%] border bg-surface"
>
<MapItem
mod={triggerModule}
insertable={true}
bgColor={'#ffffff'}
modules={data.modules ?? []}
moving={''}
flowJobs={undefined}
on:delete={(e) => {
data.eventHandlers.delete(e.detail, '')
}}
on:insert={(e) => {
data.eventHandlers.insert(e.detail)
}}
on:changeId={(e) => {
data.eventHandlers.changeId(e.detail)
}}
on:move={(e) => {
if (triggerModule) {
data.eventHandlers.move(triggerModule, data.modules)
}
}}
on:newBranch={(e) => {
if (triggerModule) {
data.eventHandlers.newBranch(triggerModule)
}
}}
on:select={(e) => {
data.eventHandlers.select(e.detail)
}}
/>
</div>
{/if}
{#each forloopModules as mod}
<div class="text-2xs text-secondary font-normal w-[80%] ml-auto shadow-sm">
<MapItem
{mod}
insertable={true}
bgColor={'#ffffff'}
modules={data.modules ?? []}
moving={''}
flowJobs={undefined}
on:delete={(e) => {
data.eventHandlers.delete(e.detail, '')
}}
on:insert={(e) => {
data.eventHandlers.insert(e.detail)
}}
on:changeId={(e) => {
data.eventHandlers.changeId(e.detail)
}}
on:move={(e) => {
data.eventHandlers.move(mod, data.modules)
}}
on:newBranch={(e) => {
data.eventHandlers.newBranch(mod)
}}
on:select={(e) => {
data.eventHandlers.select(e.detail)
}}
/>
</div>
{/each}
<div class="flex grow justify-center items-center">
<span class="text-center">Schedule Poll</span>
<div class="text-2xs text-secondary font-normal w-[80%] ml-auto">
<div class="flex justify-center items-center w-full">
<InsertModuleButton />
</div>
</div>
</div>
<div
class="text-2xs text-secondary font-normal text-center rounded-sm w-[80%] ml-auto border bg-surface"
>
<FlowModuleSchemaItem
deletable={true}
label={`Step`}
id="step id"
on:changeId
on:move={() => dispatch('move')}
on:delete
on:click={() => ($selectedId = 'stepid')}
{...itemProps}
bgColor={'#ffffff'}
/>
</div>
<div class="text-2xs text-secondary font-normal rounded-sm w-[80%] ml-auto">
<div class="flex justify-center items-center w-full">
<InsertModuleButton />
</div>
</div>
</button>
<button
class="absolute -top-[10px] -right-[10px] rounded-full h-[20px] w-[20px] trash center-center text-secondary
outline-[1px] outline dark:outline-gray-500 outline-gray-300 bg-surface duration-150 hover:bg-red-400 hover:text-white
{hover || $selectedId === 'schedulePoll' ? '' : '!hidden'}"
title="Delete"
on:click|preventDefault|stopPropagation={() => {
data.eventHandlers.removeSchedulePoll()
console.log('remove schedule Poll')
}}
>
<X class="mx-[3px]" size={12} strokeWidth={2} />
</button>
</button>
</div>
</NodeWrapper>
@@ -21,8 +21,6 @@
<TriggersWrapper
path={data.path}
on:new={(e) => {
console.log('Yes New script at index', data.index, e)
console.log('Event Handlers', data?.eventHandlers)
data?.eventHandlers.insert({
modules: data.modules,
index: 0,