Remove Schedule Poll Node

This commit is contained in:
Guilhem
2024-10-15 22:06:22 +02:00
parent d71832c831
commit b578824c54
7 changed files with 243 additions and 381 deletions
@@ -85,6 +85,7 @@ export async function createInlineScriptModule(
value: { type: 'rawscript', content: code, language, input_transforms: {} },
isTrigger: kind === 'trigger'
}
console.log('flowModule', flowModule)
return [flowModule, await loadFlowModuleState(flowModule)]
}
@@ -45,8 +45,6 @@
let flowTutorials: FlowTutorials | undefined = undefined
let hasSchedulePoll = false
const { selectedId, moving, history, flowStateStore, flowStore, flowInputsStore, pathStore } =
getContext<FlowEditorContext>('FlowEditorContext')
@@ -102,6 +100,7 @@
module.stop_after_if = { skip_if_stopped: false, expr: 'true' }
}
if (inlineScript) {
console.log('inlineScript', inlineScript)
const { language, kind, subkind } = inlineScript
;[module, state] = await createInlineScriptModule(
language,
@@ -256,7 +255,6 @@
}
}
}
$: console.log('has schedule poll', hasSchedulePoll)
</script>
<Portal name="flow-module">
@@ -321,7 +319,6 @@
preprocessorModule={$flowStore.value?.preprocessor_module}
{selectedId}
{flowInputsStore}
{hasSchedulePoll}
on:delete={({ detail }) => {
let e = detail.detail
dependents = getDependentComponents(e.id, $flowStore)
@@ -330,9 +327,6 @@
if (e.id === 'preprocessor') {
$selectedId = 'Input'
$flowStore.value.preprocessor_module = undefined
} else if (e.id === 'schedulePoll') {
$selectedId = 'Triggers'
hasSchedulePoll = false
} else {
selectNextId(e.id)
removeAtId($flowStore.value.modules, e.id)
@@ -381,7 +375,7 @@
detail.flow,
detail.inlineScript
)
$selectedId = detail.modules[detail.index ?? 0].id
//$selectedId = detail.modules[detail.index ?? 0].id
console.log('Modules', detail.modules)
}
}
@@ -457,12 +451,6 @@
on:openSchedules={() => {
$selectedId = 'settings-schedule'
}}
on:addSchedulePoll={() => {
hasSchedulePoll = true
}}
on:removeSchedulePoll={() => {
hasSchedulePoll = false
}}
/>
</div>
<div
@@ -37,7 +37,6 @@
import { Alert, Drawer } from '../common'
import Button from '../common/button/Button.svelte'
import FlowYamlEditor from '../flows/header/FlowYamlEditor.svelte'
import SchedulePollNode from './renderers/nodes/ShedulePollNode.svelte'
export let success: boolean | undefined = undefined
export let modules: FlowModule[] | undefined = []
export let failureModule: FlowModule | undefined = undefined
@@ -51,7 +50,6 @@
export let path: string | undefined = undefined
export let isEditor: boolean = false
export let newFlow: boolean = false
export let hasSchedulePoll: boolean = true
export let insertable = false
export let scroll = false
export let moving: string | undefined = undefined
@@ -77,7 +75,15 @@
let fullWidth = 0
let width = 0
let forloopEdge: Edge | undefined = undefined
export let simplifyFlow: boolean = false
let flowIsSimplifiable: boolean | { triggerNode: any; forLoopNode: any } = false
function updateFlowSimplifiability() {
flowIsSimplifiable = isSimplifiable(graph)
}
$: if (graph) updateFlowSimplifiability()
function layoutNodes(nodes: Node[]): Node[] {
let seenId: string[] = []
@@ -177,11 +183,9 @@
selectedIteration: (detail, moduleId) => {
dispatch('selectedIteration', { ...detail, moduleId: moduleId })
},
addSchedulePoll: () => {
dispatch('addSchedulePoll')
},
removeSchedulePoll: () => {
dispatch('removeSchedulePoll')
simplifyFlow: (detail) => {
simplifyFlow = detail
console.log('simplifyFlow', detail)
}
},
success,
@@ -196,9 +200,9 @@
dispatch('triggerDetail', e)
},
isEditor: isEditor,
path
},
hasSchedulePoll
path,
flowIsSimplifiable: !!flowIsSimplifiable
}
)
const nodes = writable<Node[]>([])
@@ -261,109 +265,67 @@
return { nodes: updatedNodes, edges: updatedEdges }
}
function removeForLoopNodes(nodes, edges) {
let updatedGraph = {
nodes: [...nodes],
edges: [...edges]
}
let forloopNode = updatedGraph.nodes.find((node) => node?.data?.value?.type === 'forloopflow')
if (!forloopNode) {
return updatedGraph
}
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
}
forloopEdge = updatedGraph.edges.find((edge) => edge.source === forloopNode.id)
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 removeTriggerScriptModule(nodes, edges) {
let updatedGraph = {
nodes: [...nodes],
edges: [...edges]
}
let triggerScriptModule = updatedGraph.nodes.find((node) => node?.data?.module?.isTrigger)
console.log('triggerScriptModule', triggerScriptModule)
if (!triggerScriptModule) {
return updatedGraph
}
return removeInputNode(updatedGraph.nodes, updatedGraph.edges, triggerScriptModule.id)
}
function processGraph(graph) {
function processGraph(graph, simplifiable) {
let newGraph = { nodes: graph.nodes, edges: graph.edges }
newGraph = removeInputNode(newGraph.nodes, newGraph.edges, 'Input')
newGraph = removeForLoopNodes(newGraph.nodes, newGraph.edges)
newGraph = removeForLoopStartNodes(newGraph.nodes, newGraph.edges)
newGraph = removeForLoopEndNodes(newGraph.nodes, newGraph.edges)
newGraph = removeTriggerScriptModule(newGraph.nodes, newGraph.edges)
newGraph.edges = replaceEdge(newGraph.edges, forloopEdge)
newGraph = removeInputNode(newGraph.nodes, newGraph.edges, simplifiable.forLoopNode.id)
newGraph = removeInputNode(newGraph.nodes, newGraph.edges, simplifiable.triggerNode.id)
//newGraph.edges = replaceEdge(newGraph.edges, forloopEdge)
return newGraph
}
function replaceEdge(edges, edge) {
if (!edge) {
return edges
function isSimplifiable(graph): boolean | { triggerNode: any; forLoopNode: any } {
if (!graph || !graph.nodes || graph.nodes.length < 6) {
return false
}
const schedulePollEdge = edges.find((edge) => edge.source === 'SchedulePoll')
if (!schedulePollEdge) {
return edges
}
const targetNode = schedulePollEdge.target
edge.source = 'SchedulePoll'
edge.target = targetNode
edges.push(edge)
// Remove the original SchedulePoll edge
return edges.filter((e) => e !== schedulePollEdge)
// Find the node that has 'Input' as parent in parentIds
const triggerNode = graph.nodes.find(
(node) =>
node.data?.parentIds &&
node.data.parentIds.includes('Input') &&
node.data?.module?.isTrigger
)
console.log('dbg', triggerNode)
if (!triggerNode) {
return false
}
// Check if there's a node which parent is triggerNode and that is a for loop
const forLoopNode = graph.nodes.find(
(node) =>
node.data?.parentIds &&
node.data.parentIds.includes(triggerNode.id) &&
node.data.value?.type === 'forloopflow'
)
if (!forLoopNode) {
return false
}
return { triggerNode: triggerNode, forLoopNode: forLoopNode }
}
$: console.log('isSimplifiable', isSimplifiable(graph))
function updateStores() {
if (graph.error) {
return
}
let newGraph = graph
if (hasSchedulePoll) {
graph = processGraph(graph)
if (flowIsSimplifiable && simplifyFlow) {
console.log('simplifying flow')
newGraph = processGraph(graph, flowIsSimplifiable)
}
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
$nodes = layoutNodes(newGraph.nodes)
$edges = newGraph.edges
console.log('nodes', $nodes)
height = Math.max(...$nodes.map((n) => n.position.y + NODE.height + 40), minHeight)
}
$: graph && updateStores()
$: (graph || simplifyFlow) && updateStores()
const nodeTypes = {
input2: InputNode,
@@ -378,8 +340,7 @@
branchOneStart: BranchOneStart,
branchOneEnd: BranchAllEndNode,
noBranch: NoBranchNode,
trigger: TriggersNode,
schedulePoll: SchedulePollNode
trigger: TriggersNode
} as any
const edgeTypes = {
@@ -14,8 +14,7 @@ export type GraphEventHandlers = {
move: (module: FlowModule, modules: FlowModule[]) => void
selectedIteration: (detail, moduleId: string) => void
changeId: (newId: string) => void
addSchedulePoll: () => void
removeSchedulePoll: () => void
simplifyFlow: (detail: boolean) => void
}
export default function graphBuilder(
@@ -33,8 +32,8 @@ export default function graphBuilder(
openSchedules?: () => void
triggerDetail?: (e) => void
isEditor?: boolean
},
hasSchedulePoll?: boolean
flowIsSimplifiable?: boolean
}
): {
nodes: Node[]
edges: Edge[]
@@ -162,54 +161,32 @@ export default function graphBuilder(
}
if (extra.path) {
if (hasSchedulePoll) {
const schedulePollNode: Node = {
id: 'SchedulePoll',
position: { x: -1, y: -1 },
type: 'schedulePoll',
data: {
eventHandlers: eventHandlers,
modules: modules,
...extra
}
}
nodes.push(schedulePollNode)
if (!!preprocessorModule) {
addEdge('SchedulePoll', preprocessorModule.id, {
type: 'empty'
})
} else {
addEdge('SchedulePoll', 'Input', {
type: 'empty'
})
}
} else {
const triggerNode: Node = {
id: 'Trigger',
position: { x: -1, y: -1 },
type: 'trigger',
data: {
path: triggerProps?.path,
openSchedules: triggerProps?.openSchedules,
triggerDetail: triggerProps?.triggerDetail,
isEditor: triggerProps?.isEditor,
newFlow: extra.newFlow,
eventHandlers: eventHandlers,
modules: modules,
...extra
}
const triggerNode: Node = {
id: 'Trigger',
position: { x: -1, y: -1 },
type: 'trigger',
data: {
flowIsSimplifiable: triggerProps?.flowIsSimplifiable,
path: triggerProps?.path,
openSchedules: triggerProps?.openSchedules,
triggerDetail: triggerProps?.triggerDetail,
isEditor: triggerProps?.isEditor,
newFlow: extra.newFlow,
eventHandlers: eventHandlers,
modules: modules,
...extra
}
}
nodes.push(triggerNode)
if (!!preprocessorModule) {
addEdge('Trigger', preprocessorModule.id, {
type: 'empty'
})
} else {
addEdge('Trigger', 'Input', {
type: 'empty'
})
}
nodes.push(triggerNode)
if (!!preprocessorModule) {
addEdge('Trigger', preprocessorModule.id, {
type: 'empty'
})
} else {
addEdge('Trigger', 'Input', {
type: 'empty'
})
}
}
@@ -1,111 +0,0 @@
<script lang="ts">
import NodeWrapper from './NodeWrapper.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 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')
/* async function deleteSchedulePoll(e) {
data.eventHandlers.delete(e.detail, '')
} */
let componentHeight = NODE.height
let hover = false
console.log('Modules', data.modules)
let triggerScriptModule: FlowModule | undefined = undefined
function getTriggerScriptModule() {
triggerScriptModule = data.modules.find((mod) => mod.isTrigger)
console.log('Trigger Module', triggerScriptModule)
}
$: getTriggerScriptModule(), data.modules
</script>
<NodeWrapper wrapperClass="!shadow-none">
<div
class="flex flex-row"
style="width: {NODE.width}px; min-height: {NODE.height}px; transform: translate(0, calc({NODE.height}px - {componentHeight}px));"
>
<button
class={twMerge(
'flex flex-row gap-2 rounded-sm p-2 border absolute grow w-full items-center',
$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">
<Repeat class="w-4 h-4 text-secondary" />
</div>
{#if triggerScriptModule}
<div
class="text-2xs text-secondary min-w-0 font-normal text-center rounded-sm shrink shadow-md w-full border bg-surface"
>
<MapItem
mod={triggerScriptModule}
insertable={false}
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 (triggerScriptModule) {
data.eventHandlers.move(triggerScriptModule, data.modules)
}
}}
on:newBranch={(e) => {
if (triggerScriptModule) {
data.eventHandlers.newBranch(triggerScriptModule)
}
}}
on:select={(e) => {
data.eventHandlers.select(e.detail)
}}
/>
</div>
{:else}
<div> loading ... </div>
{/if}
<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>
@@ -15,6 +15,7 @@
modules: FlowModule[]
index: number
disableAi: boolean
flowIsSimplifiable: boolean
}
</script>
@@ -23,6 +24,7 @@
{data}
path={data.path}
on:new={(e) => {
console.log('new', e)
data?.eventHandlers.insert({
modules: data.modules,
index: 0,
@@ -35,7 +37,6 @@
kind: 'forloop',
light: true
})
data?.eventHandlers.addSchedulePoll()
}}
on:pickScript={(e) => {
data?.eventHandlers.insert({
@@ -49,7 +50,6 @@
kind: 'forloop',
light: true
})
data?.eventHandlers.addSchedulePoll()
}}
on:openSchedules={() => data.openSchedules()}
on:triggerDetail={(e) => {
@@ -15,6 +15,8 @@
import type { FlowModule } from '$lib/gen'
import type { GraphEventHandlers } from '../../graphBuilder'
import { twMerge } from 'tailwind-merge'
import MapItem from '../../../flows/map/MapItem.svelte'
import Toggle from '$lib/components/Toggle.svelte'
export let path: string
export let isEditor: boolean
@@ -24,6 +26,7 @@
index: number
eventHandlers: GraphEventHandlers
disableAi: boolean
flowIsSimplifiable: boolean
}
const dispatch = createEventDispatcher()
@@ -74,6 +77,13 @@
const { httpTriggers, selectedId, selectedTrigger, schedules, primarySchedule } =
getContext<FlowEditorContext>('FlowEditorContext') ?? {}
let simplifiedTriggers = false
let triggerScriptModule: FlowModule | undefined = undefined
$: triggerScriptModule = data.modules.find((mod) => mod.isTrigger)
$: data.eventHandlers.simplifyFlow(simplifiedTriggers)
</script>
{#if isEditor}
@@ -85,81 +95,83 @@
)
? 'outline outline-offset-1 outline-2 outline-slate-900 dark:bg-white/5 dark:outline-slate-800/60 dark:border-gray-400'
: ''}"
on:click={() => ($selectedId = 'triggers')}
on:click|self={() => ($selectedId = 'triggers')}
>
<div class="flex flex-col">
<div class="flex flex-row items-center text-2xs font-normal"> Triggers </div>
</div>
{#if !simplifiedTriggers}
<div class="flex flex-col">
<div class="flex flex-row items-center text-2xs font-normal"> Triggers </div>
</div>
<Popover>
<svelte:fragment slot="text">
{#if newFlow}
Deploy the flow to see webhooks triggers
{:else}
See default webhooks triggers
{/if}
</svelte:fragment>
<TriggerButton
on:click={() => {
if (isEditor) {
$selectedTrigger = 'webhooks'
$selectedId = 'webhooks'
} else {
dispatch('triggerDetail', 'webhooks')
}
}}
disabled={newFlow}
>
<Webhook size={12} />
</TriggerButton>
</Popover>
<Popover>
<svelte:fragment slot="text">
{#if newFlow}
Deploy the flow to see webhooks triggers
{:else}
See default webhooks triggers
{/if}
</svelte:fragment>
<TriggerButton
on:click={() => {
if (isEditor) {
$selectedTrigger = 'webhooks'
$selectedId = 'triggers'
} else {
dispatch('triggerDetail', 'webhooks')
}
}}
disabled={newFlow}
>
<Webhook size={12} />
</TriggerButton>
</Popover>
<Popover>
<svelte:fragment slot="text">
{#if newFlow}
Deploy the flow to see email triggers
{:else}
See all email triggers
{/if}
</svelte:fragment>
<TriggerButton
on:click={() => {
if (isEditor) {
$selectedTrigger = 'mail'
$selectedId = 'mail'
} else {
dispatch('triggerDetail', 'mail')
}
}}
disabled={newFlow}
>
<Mail size={12} />
</TriggerButton>
</Popover>
<Popover>
<svelte:fragment slot="text">
{#if newFlow}
Deploy the flow to see email triggers
{:else}
See all email triggers
{/if}
</svelte:fragment>
<TriggerButton
on:click={() => {
if (isEditor) {
$selectedTrigger = 'mail'
$selectedId = 'triggers'
} else {
dispatch('triggerDetail', 'mail')
}
}}
disabled={newFlow}
>
<Mail size={12} />
</TriggerButton>
</Popover>
<Popover>
<svelte:fragment slot="text">
{#if newFlow}
Deploy the flow to add routes triggers
{:else}
See all routes triggers
{/if}
</svelte:fragment>
<TriggerButton
on:click={() => {
if (isEditor) {
$selectedTrigger = 'routes'
$selectedId = 'routes'
} else {
dispatch('triggerDetail', 'routes')
}
}}
disabled={newFlow}
>
<TriggerCount count={$httpTriggers?.length} />
<Route size={12} />
</TriggerButton>
</Popover>
<Popover>
<svelte:fragment slot="text">
{#if newFlow}
Deploy the flow to add routes triggers
{:else}
See all routes triggers
{/if}
</svelte:fragment>
<TriggerButton
on:click={() => {
if (isEditor) {
$selectedTrigger = 'routes'
$selectedId = 'triggers'
} else {
dispatch('triggerDetail', 'routes')
}
}}
disabled={newFlow}
>
<TriggerCount count={$httpTriggers?.length} />
<Route size={12} />
</TriggerButton>
</Popover>
{/if}
<Popover>
<svelte:fragment slot="text">See all schedules triggers</svelte:fragment>
@@ -167,7 +179,7 @@
on:click={() => {
if (isEditor) {
$selectedTrigger = 'schedules'
$selectedId = 'schedules'
$selectedId = 'triggers'
} else {
dispatch('triggerDetail', 'schedule')
}
@@ -182,43 +194,77 @@
<!-- index={data.index ?? 0}
allowTrigger={data.enableTrigger}
modules={data?.modules ?? []} -->
<InsertModuleButton
disableAi={data.disableAi}
on:new={(e) => {
// console.log('new', e)
data?.eventHandlers.insert({
modules: data.modules,
index: data.index,
kind: e.detail.kind,
inlineScript: e.detail.inlineScript
})
}}
on:pickScript={(e) => {
// console.log('pickScript', e)
data?.eventHandlers.insert({
modules: data.modules,
index: data.index,
script: e.detail
})
}}
on:pickFlow={(e) => {
// console.log('pickFlow', e)
data?.eventHandlers.insert({
modules: data.modules,
index: data.index,
flow: e.detail
})
}}
kind="trigger"
index={data?.index ?? 0}
modules={data?.modules ?? []}
buttonClasses={twMerge(
'bg-surface-secondary hover:bg-surface-hover rounded-md border text-xs',
'w-6 h-6',
'relative center-center',
newFlow ? 'cursor-not-allowed bg-surface-disabled' : 'cursor-pointer'
)}
/>
{#if !simplifiedTriggers && !data.flowIsSimplifiable}
<InsertModuleButton
disableAi={data.disableAi}
on:new={(e) => {
dispatch('new', e.detail)
simplifiedTriggers = true
}}
on:pickScript={(e) => {
dispatch('pickScript', e.detail)
simplifiedTriggers = true
}}
kind="trigger"
index={data?.index ?? 0}
modules={data?.modules ?? []}
buttonClasses={twMerge(
'bg-surface-secondary hover:bg-surface-hover rounded-md border text-xs',
'w-6 h-6',
'relative center-center',
newFlow ? 'cursor-not-allowed bg-surface-disabled' : 'cursor-pointer'
)}
/>
{/if}
{#if triggerScriptModule && simplifiedTriggers}
<div
class="text-2xs text-secondary min-w-0 font-normal text-center rounded-sm shrink shadow-md w-full border bg-surface"
>
<MapItem
mod={triggerScriptModule}
insertable={false}
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 (triggerScriptModule) {
data.eventHandlers.move(triggerScriptModule, data.modules)
}
}}
on:newBranch={(e) => {
if (triggerScriptModule) {
data.eventHandlers.newBranch(triggerScriptModule)
}
}}
on:select={(e) => {
data.eventHandlers.select(e.detail)
}}
/>
</div>
{/if}
{#if data.flowIsSimplifiable}
<Toggle
size="xs"
label="Simplify view"
bind:checked={simplifiedTriggers}
on:change={(e) => {
e.stopPropagation()
}}
/>
{/if}
</button>
</div>
</div>