Compare commits

...

4 Commits

Author SHA1 Message Date
hcourdent
36882f2fc9 Message triggers clarification 2024-09-25 16:32:12 +02:00
Ruben Fiszel
9909b8989e chore(main): release 1.400.0 (#4438)
* chore(main): release 1.400.0

* Apply automatic changes

---------

Co-authored-by: rubenfiszel <rubenfiszel@users.noreply.github.com>
2024-09-25 16:26:07 +02:00
Faton Ramadani
84eefadfcf feat(frontend): Catch flow errors in the UI (#4429)
* feat(frontend): Catch flow errors in the UI

* feat(frontend): typo
2024-09-25 16:22:02 +02:00
wendrul
a1ac583f05 fix: remove autocomplete for searchbar (#4440) 2024-09-25 16:03:03 +02:00
21 changed files with 585 additions and 496 deletions

View File

@@ -1,5 +1,18 @@
# Changelog
## [1.400.0](https://github.com/windmill-labs/windmill/compare/v1.399.0...v1.400.0) (2024-09-25)
### Features
* add static variable and resources support to ansible ([#4435](https://github.com/windmill-labs/windmill/issues/4435)) ([398a09b](https://github.com/windmill-labs/windmill/commit/398a09b7419c7adafa76e5f9f5a981bec6f0611d))
* **frontend:** Catch flow errors in the UI ([#4429](https://github.com/windmill-labs/windmill/issues/4429)) ([84eefad](https://github.com/windmill-labs/windmill/commit/84eefadfcf06b4f38117b6c4c534f47fb2ef7cc7))
### Bug Fixes
* remove autocomplete for searchbar ([#4440](https://github.com/windmill-labs/windmill/issues/4440)) ([a1ac583](https://github.com/windmill-labs/windmill/commit/a1ac583f05c34a534c4ae78ca7d2a6850723ce85))
## [1.399.0](https://github.com/windmill-labs/windmill/compare/v1.398.1...v1.399.0) (2024-09-25)

44
backend/Cargo.lock generated
View File

@@ -10426,7 +10426,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windmill"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"axum",
@@ -10468,7 +10468,7 @@ dependencies = [
[[package]]
name = "windmill-api"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"argon2",
@@ -10553,7 +10553,7 @@ dependencies = [
[[package]]
name = "windmill-api-client"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"base64 0.21.7",
"chrono",
@@ -10571,7 +10571,7 @@ dependencies = [
[[package]]
name = "windmill-audit"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"chrono",
"serde",
@@ -10584,7 +10584,7 @@ dependencies = [
[[package]]
name = "windmill-common"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"async-stream",
@@ -10628,7 +10628,7 @@ dependencies = [
[[package]]
name = "windmill-git-sync"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"regex",
"rsmq_async",
@@ -10643,7 +10643,7 @@ dependencies = [
[[package]]
name = "windmill-indexer"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"bytes",
@@ -10664,7 +10664,7 @@ dependencies = [
[[package]]
name = "windmill-parser"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"convert_case 0.6.0",
"serde",
@@ -10673,7 +10673,7 @@ dependencies = [
[[package]]
name = "windmill-parser-bash"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"lazy_static",
@@ -10685,7 +10685,7 @@ dependencies = [
[[package]]
name = "windmill-parser-go"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"gosyn",
@@ -10697,7 +10697,7 @@ dependencies = [
[[package]]
name = "windmill-parser-graphql"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"lazy_static",
@@ -10709,7 +10709,7 @@ dependencies = [
[[package]]
name = "windmill-parser-php"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"itertools 0.13.0",
@@ -10720,7 +10720,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"itertools 0.13.0",
@@ -10731,7 +10731,7 @@ dependencies = [
[[package]]
name = "windmill-parser-py-imports"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"async-recursion",
@@ -10749,7 +10749,7 @@ dependencies = [
[[package]]
name = "windmill-parser-rust"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"convert_case 0.6.0",
@@ -10766,7 +10766,7 @@ dependencies = [
[[package]]
name = "windmill-parser-sql"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"lazy_static",
@@ -10778,7 +10778,7 @@ dependencies = [
[[package]]
name = "windmill-parser-ts"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"lazy_static",
@@ -10796,7 +10796,7 @@ dependencies = [
[[package]]
name = "windmill-parser-wasm"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"getrandom 0.2.15",
@@ -10817,7 +10817,7 @@ dependencies = [
[[package]]
name = "windmill-parser-yaml"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"serde_json",
@@ -10827,7 +10827,7 @@ dependencies = [
[[package]]
name = "windmill-queue"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"async-recursion",
@@ -10860,7 +10860,7 @@ dependencies = [
[[package]]
name = "windmill-sql-datatype-parser-wasm"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"wasm-bindgen",
"wasm-bindgen-test",
@@ -10870,7 +10870,7 @@ dependencies = [
[[package]]
name = "windmill-worker"
version = "1.399.0"
version = "1.400.0"
dependencies = [
"anyhow",
"async-recursion",

View File

@@ -1,6 +1,6 @@
[package]
name = "windmill"
version = "1.399.0"
version = "1.400.0"
authors.workspace = true
edition.workspace = true
@@ -27,7 +27,7 @@ members = [
]
[workspace.package]
version = "1.399.0"
version = "1.400.0"
authors = ["Ruben Fiszel <ruben@windmill.dev>"]
edition = "2021"

View File

@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.399.0
version: 1.400.0
title: Windmill API
contact:

View File

@@ -2,7 +2,7 @@ import { sleep } from "https://deno.land/x/sleep@v1.2.1/mod.ts";
import * as windmill from "https://deno.land/x/windmill@v1.174.0/mod.ts";
import * as api from "https://deno.land/x/windmill@v1.174.0/windmill-api/index.ts";
export const VERSION = "v1.399.0";
export const VERSION = "v1.400.0";
export async function login(email: string, password: string): Promise<string> {
return await windmill.UserService.login({

View File

@@ -56,7 +56,7 @@ export {
// }
// });
export const VERSION = "1.399.0";
export const VERSION = "1.400.0";
const command = new Command()
.name("wmill")

View File

@@ -1,12 +1,12 @@
{
"name": "windmill-components",
"version": "1.399.0",
"version": "1.400.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "windmill-components",
"version": "1.399.0",
"version": "1.400.0",
"license": "AGPL-3.0",
"dependencies": {
"@aws-crypto/sha256-js": "^4.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "windmill-components",
"version": "1.399.0",
"version": "1.400.0",
"scripts": {
"dev": "vite dev",
"build": "vite build",

View File

@@ -121,7 +121,7 @@
</Alert>
{/if}
{/if}
{#each steps as [args, filter, m] (m.id)}
{#each steps as [args, filter, m], index (m.id + index)}
{#if filter.length > 0}
<div class="relative h-full border-t p-4">
<h2 class="sticky w-full top-0 z-10 inline-flex items-center py-2">

View File

@@ -96,10 +96,11 @@
<div class="p-4">
<Alert
type="info"
title="Preprocessor is called when the flow is triggered by API or email"
title="Preprocessor step is called when the flow is triggered by API or email"
>
It prepares arguments for the flow. Besides request arguments, the preprocessor receives a
`wm_trigger` argument with trigger details.
`wm_trigger` argument with trigger details. Learn more about all flow triggers
<a href="https://www.windmill.dev/docs/getting_started/trigger_flows" target="_blank" rel="noopener noreferrer">here</a>.
</Alert>
</div>
{/if}

View File

@@ -32,6 +32,9 @@
import { encodeState } from '$lib/utils'
import BranchOneStart from './renderers/nodes/BranchOneStart.svelte'
import NoBranchNode from './renderers/nodes/NoBranchNode.svelte'
import { Alert, Drawer } from '../common'
import Button from '../common/button/Button.svelte'
import FlowYamlEditor from '../flows/header/FlowYamlEditor.svelte'
export let success: boolean | undefined = undefined
export let modules: FlowModule[] | undefined = []
@@ -178,6 +181,10 @@
let height = 0
function updateStores() {
if (graph.error) {
return
}
$nodes = layoutNodes(graph?.nodes)
$edges = graph.edges
@@ -236,69 +243,87 @@
onMount(() => {
centerViewport(width)
})
let yamlEditorDrawer: Drawer | undefined = undefined
</script>
<div style={`height: ${height}px; max-height: ${maxHeight}px;`} bind:clientWidth={width}>
<SvelteFlow
{nodes}
{edges}
{edgeTypes}
{nodeTypes}
{viewport}
{height}
minZoom={0.5}
connectionLineType={ConnectionLineType.SmoothStep}
defaultEdgeOptions={{ type: 'smoothstep' }}
preventScrolling={scroll}
zoomOnDoubleClick={false}
elementsSelectable={false}
{proOptions}
nodesDraggable={false}
>
<div class="absolute inset-0 !bg-surface-secondary" />
<Controls position="top-right" orientation="horizontal" showLock={false}>
{#if download}
<ControlButton
on:click={() => {
try {
localStorage.setItem(
'svelvet',
encodeState({ modules, failureModule, preprocessorModule })
)
} catch (e) {
console.error('error interacting with local storage', e)
}
window.open('/view_graph', '_blank')
}}
class="!bg-surface"
>
<Expand size="14" />
</ControlButton>
{/if}
</Controls>
<FlowYamlEditor bind:drawer={yamlEditorDrawer} />
<Controls
position="top-left"
orientation="horizontal"
showLock={false}
showZoom={false}
showFitView={false}
class="!shadow-none"
>
{#if showDataflow}
<Toggle
value={$useDataflow}
on:change={() => {
$useDataflow = !$useDataflow
}}
<div style={`height: ${height}px; max-height: ${maxHeight}px;`} bind:clientWidth={width}>
{#if graph?.error}
<div class="center-center">
<Alert title="Error parsing the flow" type="error" class="max-w-1/2">
{graph.error}
<Button
color="red"
size="xs"
options={{
right: 'Dataflow'
}}
/>
{/if}
</Controls>
</SvelteFlow>
btnClasses="mt-2 w-min"
on:click={() => yamlEditorDrawer?.openDrawer()}>Open YAML editor</Button
>
</Alert>
</div>
{:else}
<SvelteFlow
{nodes}
{edges}
{edgeTypes}
{nodeTypes}
{viewport}
{height}
minZoom={0.5}
connectionLineType={ConnectionLineType.SmoothStep}
defaultEdgeOptions={{ type: 'smoothstep' }}
preventScrolling={scroll}
zoomOnDoubleClick={false}
elementsSelectable={false}
{proOptions}
nodesDraggable={false}
>
<div class="absolute inset-0 !bg-surface-secondary" />
<Controls position="top-right" orientation="horizontal" showLock={false}>
{#if download}
<ControlButton
on:click={() => {
try {
localStorage.setItem(
'svelvet',
encodeState({ modules, failureModule, preprocessorModule })
)
} catch (e) {
console.error('error interacting with local storage', e)
}
window.open('/view_graph', '_blank')
}}
class="!bg-surface"
>
<Expand size="14" />
</ControlButton>
{/if}
</Controls>
<Controls
position="top-left"
orientation="horizontal"
showLock={false}
showZoom={false}
showFitView={false}
class="!shadow-none"
>
{#if showDataflow}
<Toggle
value={$useDataflow}
on:change={() => {
$useDataflow = !$useDataflow
}}
size="xs"
options={{
right: 'Dataflow'
}}
/>
{/if}
</Controls>
</SvelteFlow>
{/if}
</div>
<style lang="postcss">

View File

@@ -29,190 +29,205 @@ export default function graphBuilder(
): {
nodes: Node[]
edges: Edge[]
error?: string | undefined
} {
const nodes: Node[] = []
const edges: Edge[] = []
if (!modules) {
return { nodes, edges }
}
try {
if (!modules) {
return { nodes, edges }
}
function addNode(module: FlowModule, offset: number, type: string, subModules?: FlowModule[]) {
nodes.push({
id: module.id,
function addNode(module: FlowModule, offset: number, type: string, subModules?: FlowModule[]) {
if (nodes.some((n) => n.id === module.id)) {
throw new Error(`Duplicated node detected: ${module.id}`)
}
nodes.push({
id: module.id,
data: {
value: module.value,
offset: offset,
module: module,
modules: subModules ?? modules,
parentIds: [],
eventHandlers: eventHandlers,
moving: moving,
...extra
},
position: { x: -1, y: -1 },
type: type
})
return module.id
}
const parents: { [key: string]: string[] } = {}
//
function detectCycle(nodeId: string, visited: Set<string>, currentPath: Set<string>): boolean {
// If the node hasn't been visited yet
if (!visited.has(nodeId)) {
visited.add(nodeId)
currentPath.add(nodeId)
// If the current node has parent nodes
if (parents[nodeId]) {
// Check each parent node
// Nodes can have multiple parents: the node that gathers the result for branches or loops for instance
for (const parentNode of parents[nodeId]) {
// If the parentNode hasn't been visited and a cycle is detected in its path
if (!visited.has(parentNode) && detectCycle(parentNode, visited, currentPath)) {
return true // Cycle detected
}
// If the parentNode is already in the current path, it's a cycle
else if (currentPath.has(parentNode)) {
return true // Cycle detected
}
}
}
}
// Remove the node from the current path as we're done processing it
currentPath.delete(nodeId)
// No cycle detected for this path
return false
}
function addEdge(
sourceId: string,
targetId: string,
options?: {
customId?: string
type?: string
subModules?: FlowModule[]
disableMoveIds?: string[]
}
) {
parents[targetId] = [...(parents[targetId] ?? []), sourceId]
const mods = options?.subModules ?? modules
let index = mods?.findIndex((m) => m.id === targetId) ?? -1
const visited = new Set<string>()
const recStack = new Set<string>()
if (detectCycle(sourceId, visited, recStack)) {
throw new Error(
`Cycle detected: adding edge from '${sourceId}' to '${targetId}' would create a cycle.`
)
}
edges.push({
id: options?.customId || `edge:${sourceId}->${targetId}`,
source: sourceId,
target: targetId,
type: options?.type ?? 'edge',
data: {
insertable: extra.insertable,
modules: options?.subModules ?? modules,
sourceId,
targetId,
moving,
eventHandlers,
disableMoveIds: options?.disableMoveIds,
enableTrigger: sourceId === 'Input',
// If the index is -1, it means that the target module is not in the modules array, so we set it to the length of the array
index: index >= 0 ? index : mods?.length ?? 0,
...extra
}
})
}
const inputNode: Node = {
id: 'Input',
position: { x: -1, y: -1 },
type: 'input2',
data: {
value: module.value,
offset: offset,
module: module,
modules: subModules ?? modules,
parentIds: [],
eventHandlers: eventHandlers,
moving: moving,
modules: modules,
hasPreprocessor: !!preprocessorModule,
...extra
}
}
const resultNode: Node = {
id: 'result',
data: {
eventHandlers: eventHandlers,
modules: modules,
success: success,
...extra
},
position: { x: -1, y: -1 },
type: type
})
return module.id
}
const parents: { [key: string]: string[] } = {}
function addEdge(
sourceId: string,
targetId: string,
options?: {
customId?: string
type?: string
subModules?: FlowModule[]
disableMoveIds?: string[]
type: 'result'
}
) {
parents[targetId] = [...(parents[targetId] ?? []), sourceId]
// Find the index of the target module in the modules array
const mods = options?.subModules ?? modules
nodes.push(inputNode)
nodes.push(resultNode)
// Index of the target module in the modules array
let index = mods?.findIndex((m) => m.id === targetId) ?? -1
function processModules(
modules: FlowModule[],
beforeNode: Node,
nextNode: Node,
currentOffset = 0,
disableMoveIds: string[] = [],
parentIndex?: string
) {
let previousId: string | undefined = undefined
edges.push({
id: options?.customId || `edge:${sourceId}->${targetId}`,
source: sourceId,
target: targetId,
type: options?.type ?? 'edge',
data: {
insertable: extra.insertable,
modules: options?.subModules ?? modules,
sourceId,
targetId,
moving,
eventHandlers,
disableMoveIds: options?.disableMoveIds,
enableTrigger: sourceId === 'Input',
// If the index is -1, it means that the target module is not in the modules array, so we set it to the length of the array
index: index >= 0 ? index : mods?.length ?? 0,
...extra
}
})
}
if (modules.length === 0) {
addEdge(beforeNode.id, nextNode.id, {
subModules: modules,
disableMoveIds
})
} else {
modules.forEach((module, index) => {
const localDisableMoveIds = [...disableMoveIds, module.id]
const inputNode: Node = {
id: 'Input',
position: { x: -1, y: -1 },
type: 'input2',
data: {
eventHandlers: eventHandlers,
modules: modules,
hasPreprocessor: !!preprocessorModule,
...extra
}
}
const resultNode: Node = {
id: 'result',
data: {
eventHandlers: eventHandlers,
modules: modules,
success: success,
...extra
},
position: { x: -1, y: -1 },
type: 'result'
}
nodes.push(inputNode)
nodes.push(resultNode)
function processModules(
modules: FlowModule[],
beforeNode: Node,
nextNode: Node,
currentOffset = 0,
disableMoveIds: string[] = [],
parentIndex?: string
) {
let previousId: string | undefined = undefined
if (modules.length === 0) {
addEdge(beforeNode.id, nextNode.id, {
subModules: modules,
disableMoveIds
})
} else {
modules.forEach((module, index) => {
const localDisableMoveIds = [...disableMoveIds, module.id]
// Add the edge between the previous node and the current one
if (index > 0 && previousId) {
addEdge(previousId, module.id, {
subModules: modules,
disableMoveIds
})
}
if (module.value.type === 'branchall') {
// Start
addNode(module, currentOffset, 'module', modules)
// "Collect result of each branch" node
const endNode = {
id: `${module.id}-end`,
data: {
offset: currentOffset,
id: module.id,
module: module,
modules: modules,
...extra
},
position: { x: -1, y: -1 },
type: 'branchAllEnd'
// Add the edge between the previous node and the current one
if (index > 0 && previousId) {
addEdge(previousId, module.id, {
subModules: modules,
disableMoveIds
})
}
nodes.push(endNode)
if (module.value.type === 'branchall') {
// Start
addNode(module, currentOffset, 'module', modules)
if (module.value.branches.length === 0) {
// Add a "No branches" node
const startNode = {
id: `${module.id}-branch-0`,
// "Collect result of each branch" node
const endNode = {
id: `${module.id}-end`,
data: {
offset: currentOffset,
id: module.id,
branchIndex: -1,
module: module,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'noBranch'
type: 'branchAllEnd'
}
nodes.push(startNode)
addEdge(module.id, startNode.id, {
type: 'empty'
})
addEdge(startNode.id, endNode.id, {
type: 'empty'
})
} else {
module.value.branches.forEach((branch, branchIndex) => {
// Start node by branch
nodes.push(endNode)
if (module.value.branches.length === 0) {
// Add a "No branches" node
const startNode = {
id: `${module.id}-branch-${branchIndex}`,
id: `${module.id}-branch-0`,
data: {
offset: currentOffset,
label: defaultIfEmptyString(branch.summary, `Branch ${branchIndex + 1}`),
id: module.id,
branchIndex: branchIndex,
branchIndex: -1,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'branchAllStart'
type: 'noBranch'
}
nodes.push(startNode)
@@ -220,6 +235,204 @@ export default function graphBuilder(
addEdge(module.id, startNode.id, {
type: 'empty'
})
addEdge(startNode.id, endNode.id, {
type: 'empty'
})
} else {
module.value.branches.forEach((branch, branchIndex) => {
// Start node by branch
const startNode = {
id: `${module.id}-branch-${branchIndex}`,
data: {
offset: currentOffset,
label: defaultIfEmptyString(branch.summary, `Branch ${branchIndex + 1}`),
id: module.id,
branchIndex: branchIndex,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'branchAllStart'
}
nodes.push(startNode)
addEdge(module.id, startNode.id, {
type: 'empty'
})
processModules(
branch.modules,
startNode,
endNode,
currentOffset,
localDisableMoveIds,
parentIndex ? `${parentIndex}-${index}-${branchIndex}` : `${index}-${branchIndex}`
)
})
}
previousId = endNode.id
} else if (module.value.type === 'forloopflow') {
addNode(module, currentOffset, 'module', modules)
const startNode = {
id: `${module.id}-start`,
data: {
offset: currentOffset + 25,
id: module.id,
module: module,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'forLoopStart'
}
addEdge(module.id, startNode.id, {
type: 'empty'
})
const endNode = {
id: `${module.id}-end`,
data: {
offset: currentOffset,
id: module.id,
module: module,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'forLoopEnd'
}
nodes.push(startNode)
nodes.push(endNode)
const selectedIterIndex = extra.flowModuleStates?.[module.id]?.selectedForloopIndex
processModules(
module.value.modules,
startNode,
endNode,
currentOffset + 25,
localDisableMoveIds,
parentIndex
? `${parentIndex}-${index}-${selectedIterIndex ?? '?'}`
: `${index}-${selectedIterIndex ?? '?'}`
)
previousId = endNode.id
} else if (module.value.type === 'whileloopflow') {
addNode(module, currentOffset, 'module', modules)
const startNode = {
id: `${module.id}-start`,
data: {
offset: currentOffset + 25,
module: module,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'whileLoopStart'
}
addEdge(module.id, startNode.id, {
type: 'empty'
})
const endNode = {
id: `${module.id}-end`,
data: { offset: currentOffset, module: module, modules: modules, ...extra },
position: { x: -1, y: -1 },
type: 'whileLoopEnd'
}
nodes.push(startNode)
nodes.push(endNode)
const selectedIterIndex = extra.flowModuleStates?.[module.id]?.selectedForloopIndex
processModules(
module.value.modules,
startNode,
endNode,
currentOffset + 25,
localDisableMoveIds,
parentIndex
? `${parentIndex}-${index}-${selectedIterIndex ?? '?'}`
: `${index}-${selectedIterIndex ?? '?'}`
)
previousId = endNode.id
} else if (module.value.type === 'branchone') {
addNode(module, currentOffset, 'module', modules)
const endNode = {
id: `${module.id}-end`,
data: { offset: currentOffset, eventHandlers: eventHandlers },
position: { x: -1, y: -1 },
type: 'branchOneEnd'
}
nodes.push(endNode)
// Add default branch
const defaultBranch = {
id: `${module.id}-default`,
data: {
offset: currentOffset,
label: 'Default',
id: module.id,
branchIndex: -1,
modules: module.value.default,
eventHandlers: eventHandlers,
branchOne: true,
...extra
},
position: { x: -1, y: -1 },
type: 'noBranch'
}
nodes.push(defaultBranch)
addEdge(module.id, defaultBranch.id, { type: 'empty' })
processModules(
module.value.default,
defaultBranch,
endNode,
currentOffset,
localDisableMoveIds,
parentIndex ? `${parentIndex}-${index}` : index.toString()
)
module.value.branches.forEach((branch, branchIndex) => {
// Start node by branch
const startNode = {
id: `${module.id}-branch-${branchIndex}`,
data: {
offset: currentOffset,
label: defaultIfEmptyString(branch.summary, 'Branch ' + (branchIndex + 1)),
preLabel: branch.summary ? '' : branch.expr,
id: module.id,
branchIndex: branchIndex,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'branchOneStart'
}
nodes.push(startNode)
addEdge(module.id, startNode.id, { type: 'empty' })
processModules(
branch.modules,
@@ -227,277 +440,113 @@ export default function graphBuilder(
endNode,
currentOffset,
localDisableMoveIds,
parentIndex ? `${parentIndex}-${index}-${branchIndex}` : `${index}-${branchIndex}`
parentIndex ? `${parentIndex}-${index}` : index.toString()
)
})
previousId = endNode.id
} else {
addNode(module, currentOffset, 'module', modules)
previousId = module.id
}
if (index === 0) {
addEdge(beforeNode.id, module.id, {
subModules: modules,
disableMoveIds
})
}
previousId = endNode.id
} else if (module.value.type === 'forloopflow') {
addNode(module, currentOffset, 'module', modules)
const startNode = {
id: `${module.id}-start`,
data: {
offset: currentOffset + 25,
id: module.id,
module: module,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'forLoopStart'
if (index === modules.length - 1 && previousId) {
addEdge(previousId, nextNode.id, {
subModules: modules,
disableMoveIds
})
}
})
addEdge(module.id, startNode.id, {
type: 'empty'
})
if (failureModule) {
const id = parentIndex ? `failure-${parentIndex}` : 'failure'
const failureState = extra.flowModuleStates?.[id] as GraphModuleState | undefined
const endNode = {
id: `${module.id}-end`,
data: {
offset: currentOffset,
id: module.id,
module: module,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'forLoopEnd'
}
nodes.push(startNode)
nodes.push(endNode)
const selectedIterIndex = extra.flowModuleStates?.[module.id]?.selectedForloopIndex
processModules(
module.value.modules,
startNode,
endNode,
currentOffset + 25,
localDisableMoveIds,
parentIndex
? `${parentIndex}-${index}-${selectedIterIndex ?? '?'}`
: `${index}-${selectedIterIndex ?? '?'}`
)
previousId = endNode.id
} else if (module.value.type === 'whileloopflow') {
addNode(module, currentOffset, 'module', modules)
const startNode = {
id: `${module.id}-start`,
data: {
offset: currentOffset + 25,
module: module,
modules: modules,
eventHandlers: eventHandlers,
...extra
},
position: { x: -1, y: -1 },
type: 'whileLoopStart'
}
addEdge(module.id, startNode.id, {
type: 'empty'
})
const endNode = {
id: `${module.id}-end`,
data: { offset: currentOffset, module: module, modules: modules, ...extra },
position: { x: -1, y: -1 },
type: 'whileLoopEnd'
}
nodes.push(startNode)
nodes.push(endNode)
const selectedIterIndex = extra.flowModuleStates?.[module.id]?.selectedForloopIndex
processModules(
module.value.modules,
startNode,
endNode,
currentOffset + 25,
localDisableMoveIds,
parentIndex
? `${parentIndex}-${index}-${selectedIterIndex ?? '?'}`
: `${index}-${selectedIterIndex ?? '?'}`
)
previousId = endNode.id
} else if (module.value.type === 'branchone') {
addNode(module, currentOffset, 'module', modules)
const endNode = {
id: `${module.id}-end`,
data: { offset: currentOffset, eventHandlers: eventHandlers },
position: { x: -1, y: -1 },
type: 'branchOneEnd'
}
nodes.push(endNode)
// Add default branch
const defaultBranch = {
id: `${module.id}-default`,
data: {
offset: currentOffset,
label: 'Default',
id: module.id,
branchIndex: -1,
modules: module.value.default,
eventHandlers: eventHandlers,
branchOne: true,
...extra
},
position: { x: -1, y: -1 },
type: 'noBranch'
}
nodes.push(defaultBranch)
addEdge(module.id, defaultBranch.id, { type: 'empty' })
processModules(
module.value.default,
defaultBranch,
endNode,
currentOffset,
localDisableMoveIds,
parentIndex ? `${parentIndex}-${index}` : index.toString()
)
module.value.branches.forEach((branch, branchIndex) => {
// Start node by branch
const startNode = {
id: `${module.id}-branch-${branchIndex}`,
data: {
offset: currentOffset,
label: defaultIfEmptyString(branch.summary, 'Branch ' + (branchIndex + 1)),
preLabel: branch.summary ? '' : branch.expr,
id: module.id,
branchIndex: branchIndex,
modules: modules,
eventHandlers: eventHandlers,
...extra
if (failureState && failureState.parent_module) {
addNode(
{
...failureModule,
id: id
},
position: { x: -1, y: -1 },
type: 'branchOneStart'
}
nodes.push(startNode)
addEdge(module.id, startNode.id, { type: 'empty' })
processModules(
branch.modules,
startNode,
endNode,
currentOffset,
localDisableMoveIds,
parentIndex ? `${parentIndex}-${index}` : index.toString()
0,
'module'
)
})
previousId = endNode.id
} else {
addNode(module, currentOffset, 'module', modules)
previousId = module.id
}
if (index === 0) {
addEdge(beforeNode.id, module.id, {
subModules: modules,
disableMoveIds
})
}
if (index === modules.length - 1 && previousId) {
addEdge(previousId, nextNode.id, {
subModules: modules,
disableMoveIds
})
}
})
if (failureModule) {
const id = parentIndex ? `failure-${parentIndex}` : 'failure'
const failureState = extra.flowModuleStates?.[id] as GraphModuleState | undefined
if (failureState && failureState.parent_module) {
addNode(
{
...failureModule,
id: id
},
0,
'module'
)
addEdge(failureState.parent_module, id, { type: 'empty' })
addEdge(failureState.parent_module, id, { type: 'empty' })
}
}
}
}
}
processModules(modules, inputNode, resultNode)
processModules(modules, inputNode, resultNode)
if (preprocessorModule) {
addNode(preprocessorModule, 0, 'module')
const id = JSON.parse(JSON.stringify(preprocessorModule.id))
addEdge(id, 'Input', { type: 'empty' })
}
if (failureModule && !extra.flowModuleStates) {
addNode(failureModule, 0, 'module')
}
Object.keys(parents).forEach((key) => {
const node = nodes.find((n) => n.id === key)
if (node) {
node.data.parentIds = parents[key]
if (preprocessorModule) {
addNode(preprocessorModule, 0, 'module')
const id = JSON.parse(JSON.stringify(preprocessorModule.id))
addEdge(id, 'Input', { type: 'empty' })
}
})
if (useDataflow && selectedId) {
let deps = getDependeeAndDependentComponents(selectedId, modules ?? [], failureModule)
if (failureModule && !extra.flowModuleStates) {
addNode(failureModule, 0, 'module')
}
if (deps) {
Object.entries(deps.dependees).forEach((x, i) => {
const inputs = x[1]
Object.keys(parents).forEach((key) => {
const node = nodes.find((n) => n.id === key)
inputs?.forEach((input, index) => {
if (node) {
node.data.parentIds = parents[key]
}
})
if (useDataflow && selectedId) {
let deps = getDependeeAndDependentComponents(selectedId, modules ?? [], failureModule)
if (deps) {
Object.entries(deps.dependees).forEach((x, i) => {
const inputs = x[1]
inputs?.forEach((input, index) => {
let pid = x[0]
if (input?.startsWith('flow_input.iter')) {
const parent = dfsByModule(selectedId!, modules ?? [])?.pop()
if (parent?.id) {
pid = parent.id
}
}
addEdge(pid, selectedId!, {
customId: `dep-${pid}-${selectedId}-${input}-${index}`,
type: 'dataflowedge'
})
})
})
Object.entries(deps.dependents).forEach((x, i) => {
let pid = x[0]
if (input?.startsWith('flow_input.iter')) {
const parent = dfsByModule(selectedId!, modules ?? [])?.pop()
if (parent?.id) {
pid = parent.id
}
}
addEdge(pid, selectedId!, {
customId: `dep-${pid}-${selectedId}-${input}-${index}`,
addEdge(selectedId!, pid, {
customId: `dep-${selectedId}-${pid}-${i}`,
type: 'dataflowedge'
})
})
})
}
}
Object.entries(deps.dependents).forEach((x, i) => {
let pid = x[0]
addEdge(selectedId!, pid, {
customId: `dep-${selectedId}-${pid}-${i}`,
type: 'dataflowedge'
})
})
return { nodes, edges }
} catch (e) {
return {
nodes: [],
edges: [],
error: e
}
}
return { nodes, edges }
}

View File

@@ -521,8 +521,9 @@
id="quickSearchInput"
bind:this={textInput}
type="text"
class="quick-search-input"
class="quick-search-input !bg-surface"
bind:value={searchTerm}
autocomplete="off"
/>
<label
for="quickSearchInput"

View File

@@ -4,8 +4,8 @@ verify_ssl = true
name = "pypi"
[packages]
wmill = ">=1.399.0"
wmill_pg = ">=1.399.0"
wmill = ">=1.400.0"
wmill_pg = ">=1.400.0"
sendgrid = "*"
mysql-connector-python = "*"
pymongo = "*"

View File

@@ -1,7 +1,7 @@
openapi: "3.0.3"
info:
version: 1.399.0
version: 1.400.0
title: OpenFlow Spec
contact:
name: Ruben Fiszel

View File

@@ -12,7 +12,7 @@
RootModule = 'WindmillClient.psm1'
# Version number of this module.
ModuleVersion = '1.399.0'
ModuleVersion = '1.400.0'
# Supported PSEditions
# CompatiblePSEditions = @()

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "wmill"
version = "1.399.0"
version = "1.400.0"
description = "A client library for accessing Windmill server wrapping the Windmill client API"
license = "Apache-2.0"
homepage = "https://windmill.dev"

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "wmill-pg"
version = "1.399.0"
version = "1.400.0"
description = "An extension client for the wmill client library focused on pg"
license = "Apache-2.0"
homepage = "https://windmill.dev"

View File

@@ -1,6 +1,6 @@
{
"name": "@windmill/windmill",
"version": "1.399.0",
"version": "1.400.0",
"exports": "./src/index.ts",
"publish": {
"exclude": ["!src", "./s3Types.ts", "./client.ts"]

View File

@@ -1,7 +1,7 @@
{
"name": "windmill-client",
"description": "Windmill SDK client for browsers and Node.js",
"version": "1.399.0",
"version": "1.400.0",
"author": "Ruben Fiszel",
"license": "Apache 2.0",
"devDependencies": {

View File

@@ -1 +1 @@
1.399.0
1.400.0