mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 16:03:47 +00:00
UX nits + fix flow worker group
This commit is contained in:
@@ -488,6 +488,7 @@ pub struct FlowWDraft {
|
||||
pub draft: Option<serde_json::Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub draft_only: Option<bool>,
|
||||
pub tag: Option<String>,
|
||||
}
|
||||
|
||||
async fn get_flow_by_path_w_draft(
|
||||
@@ -499,7 +500,7 @@ async fn get_flow_by_path_w_draft(
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
let flow_o = sqlx::query_as::<_, FlowWDraft>(
|
||||
"SELECT flow.path, flow.summary, flow,description, flow.schema, flow.value, flow.extra_perms, flow.draft_only, draft.value as draft FROM flow
|
||||
"SELECT flow.path, flow.summary, flow,description, flow.schema, flow.value, flow.extra_perms, flow.draft_only, draft.value as draft, flow.tag FROM flow
|
||||
LEFT JOIN draft ON
|
||||
flow.path = draft.path AND flow.workspace_id = draft.workspace_id AND draft.typ = 'flow'
|
||||
WHERE flow.path = $1 AND flow.workspace_id = $2",
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
import { Code2, Globe } from 'lucide-svelte'
|
||||
import type { SupportedLanguage } from '$lib/common'
|
||||
import { faRotateRight } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faExternalLink, faRotateRight } from '@fortawesome/free-solid-svg-icons'
|
||||
import Icon from 'svelte-awesome'
|
||||
import FlowIcon from './home/FlowIcon.svelte'
|
||||
import DarkModeObserver from './DarkModeObserver.svelte'
|
||||
import { truncate } from '$lib/utils'
|
||||
|
||||
export let initialPath: string | undefined = undefined
|
||||
export let scriptPath: string | undefined = undefined
|
||||
@@ -44,13 +45,13 @@
|
||||
if (itemKind == 'flow') {
|
||||
items = (await FlowService.listFlows({ workspace: $workspaceStore! })).map((flow) => ({
|
||||
value: flow.path,
|
||||
label: `${flow.path}${flow.summary ? ` | ${flow.summary}` : ''}`
|
||||
label: `${flow.path}${flow.summary ? ` | ${truncate(flow.summary, 20)}` : ''}`
|
||||
}))
|
||||
} else if (itemKind == 'script') {
|
||||
items = (await ScriptService.listScripts({ workspace: $workspaceStore!, kind })).map(
|
||||
(script) => ({
|
||||
value: script.path,
|
||||
label: `${script.path}${script.summary ? ` | ${script.summary}` : ''}`
|
||||
label: `${script.path}${script.summary ? ` | ${truncate(script.summary, 20)}` : ''}`
|
||||
})
|
||||
)
|
||||
} else {
|
||||
@@ -108,7 +109,7 @@
|
||||
{:else}
|
||||
<Select
|
||||
value={items.find((x) => x.value == initialPath)}
|
||||
class="grow"
|
||||
class="grow shrink max-w-full"
|
||||
on:change={() => {
|
||||
dispatch('select', { path: scriptPath })
|
||||
}}
|
||||
@@ -136,28 +137,46 @@
|
||||
|
||||
{#if scriptPath !== undefined && scriptPath !== ''}
|
||||
{#if itemKind == 'flow'}
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={async () => {
|
||||
drawerFlowViewer.openDrawer()
|
||||
}}
|
||||
>
|
||||
Show flow
|
||||
</Button>
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
endIcon={{ icon: faExternalLink }}
|
||||
target="_blank"
|
||||
color="light"
|
||||
size="xs"
|
||||
href="/flows/edit/{scriptPath}">edit</Button
|
||||
>
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={async () => {
|
||||
drawerFlowViewer.openDrawer()
|
||||
}}
|
||||
>
|
||||
view
|
||||
</Button>
|
||||
</div>
|
||||
{:else}
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={async () => {
|
||||
const { language, content } = await getScriptByPath(scriptPath ?? '')
|
||||
code = content
|
||||
lang = language
|
||||
drawerViewer.openDrawer()
|
||||
}}
|
||||
>
|
||||
Show code
|
||||
</Button>
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
endIcon={{ icon: faExternalLink }}
|
||||
target="_blank"
|
||||
color="light"
|
||||
size="xs"
|
||||
href="/scripts/edit/{scriptPath}">edit</Button
|
||||
>
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
on:click={async () => {
|
||||
const { language, content } = await getScriptByPath(scriptPath ?? '')
|
||||
code = content
|
||||
lang = language
|
||||
drawerViewer.openDrawer()
|
||||
}}
|
||||
>
|
||||
view
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
return r
|
||||
} catch (e) {
|
||||
error = e.message
|
||||
console.error("Eval error in app input '" + id + "' with key '" + key, e)
|
||||
console.error("Eval error in app input '" + id + "' with key '" + key + "'", e)
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -181,7 +181,7 @@
|
||||
error = ''
|
||||
return r
|
||||
} catch (e) {
|
||||
console.debug("Eval error in app input '" + id + "' with key '" + key, e)
|
||||
console.debug("Eval error in app input '" + id + "' with key '" + key + "'", e)
|
||||
return e.message
|
||||
}
|
||||
} else if (input.type === 'static') {
|
||||
|
||||
@@ -49,6 +49,7 @@ function make_context_evaluator(
|
||||
closeModal
|
||||
) => Promise<any> {
|
||||
let template = create_context_function_template(eval_string, context, noReturn)
|
||||
console.debug(template)
|
||||
let functor = Function(template)
|
||||
return functor()
|
||||
}
|
||||
|
||||
@@ -46,7 +46,33 @@
|
||||
<Splitpanes horizontal class="!max-h-[calc(100%-48px)]">
|
||||
<Pane size={60} minSize={20} class="p-4">
|
||||
{#if mod.value.type === 'forloopflow'}
|
||||
<div class="mb-2 text-sm font-bold">
|
||||
<div class="flex flex-row gap-8 mt-2 mb-6">
|
||||
<div>
|
||||
<div class="mb-2 text-sm font-bold"
|
||||
>Skip failures <Tooltip
|
||||
>If disabled, the flow will fail as soon as one of the iteration fail. Otherwise,
|
||||
the error will be collected as the result of the iteration. Regardless of this
|
||||
setting, if an error handler is defined, it will process the error.</Tooltip
|
||||
></div
|
||||
>
|
||||
<Toggle
|
||||
bind:checked={mod.value.skip_failures}
|
||||
options={{
|
||||
right: 'Skip failures'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-2 text-sm font-bold">Run in parallel</div>
|
||||
<Toggle
|
||||
bind:checked={mod.value.parallel}
|
||||
options={{
|
||||
right: 'All iterations run in parallel'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-2 text-sm font-bold">
|
||||
Iterator expression
|
||||
<Tooltip>
|
||||
List to iterate over. For more information see the
|
||||
@@ -80,32 +106,6 @@
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex flex-row gap-8">
|
||||
<div>
|
||||
<div class="mt-6 mb-2 text-sm font-bold"
|
||||
>Skip failures <Tooltip
|
||||
>If disabled, the flow will fail as soon as one of the iteration fail. Otherwise,
|
||||
the error will be collected as the result of the iteration. Regardless of this
|
||||
setting, if an error handler is defined, it will process the error.</Tooltip
|
||||
></div
|
||||
>
|
||||
<Toggle
|
||||
bind:checked={mod.value.skip_failures}
|
||||
options={{
|
||||
right: 'Skip failures'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mt-6 mb-2 text-sm font-bold">Run in parallel</div>
|
||||
<Toggle
|
||||
bind:checked={mod.value.parallel}
|
||||
options={{
|
||||
right: 'All iterations run in parallel'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</Pane>
|
||||
<Pane size={40} minSize={20} class="flex flex-col flex-1">
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
'settings-retries',
|
||||
'settings-same-worker',
|
||||
'settings-graph',
|
||||
'settings-worker-group',
|
||||
'inputs',
|
||||
'schedules',
|
||||
'failure',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const aCharCode = 'a'.charCodeAt(0)
|
||||
|
||||
export const forbiddenIds: string[] = ['do', 'bg', 'ctx', 'state']
|
||||
export const forbiddenIds: string[] = ['do', 'bg', 'ctx', 'state', 'if', 'else', 'for']
|
||||
|
||||
export function numberToChars(n: number) {
|
||||
if (n < 0) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
export let deleteBranch: { module: FlowModule; index: number } | undefined = undefined
|
||||
export let id: string | undefined = undefined
|
||||
export let moving: string | undefined = undefined
|
||||
export let center = true
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
insert: {
|
||||
@@ -53,7 +54,7 @@
|
||||
selectable ? 'cursor-pointer' : '',
|
||||
selected ? 'outline outline-offset-1 outline-2 outline-gray-600' : ''
|
||||
)}
|
||||
style="min-width: 275px; height: 34px; background-color: {bgColor};"
|
||||
style="min-width: 275px; max-height: 80px; background-color: {bgColor};"
|
||||
on:click={() => {
|
||||
if (selectable) {
|
||||
if (id) {
|
||||
@@ -65,14 +66,16 @@
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class="flex gap-1 justify-between items-center w-full overflow-hidden rounded-sm border p-2 text-2xs module text-primary border-gray-400"
|
||||
class="flex gap-1 justify-between {center
|
||||
? 'items-center'
|
||||
: 'items-baseline'} w-full overflow-hidden rounded-sm border p-2 text-2xs module text-primary border-gray-400"
|
||||
>
|
||||
{#if $$slots.icon}
|
||||
<slot name="icon" />
|
||||
<span class="mr-2" />
|
||||
{/if}
|
||||
<div />
|
||||
<div class="flex-1 truncate">{label}</div>
|
||||
<div class="flex-1 truncate"><pre>{label}</pre></div>
|
||||
<div class="flex items-center space-x-2">
|
||||
{#if id}
|
||||
<Badge color="indigo">{id}</Badge>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
type NestedNodes,
|
||||
type GraphModuleState
|
||||
} from '.'
|
||||
import { defaultIfEmptyString, encodeState, truncateRev } from '$lib/utils'
|
||||
import { defaultIfEmptyString, encodeState } from '$lib/utils'
|
||||
import { createEventDispatcher, onMount, setContext } from 'svelte'
|
||||
import Svelvet from './svelvet/container/views/Svelvet.svelte'
|
||||
import type { UserEdgeType } from './svelvet/types'
|
||||
@@ -217,7 +217,7 @@
|
||||
const branches = [
|
||||
{ summary: 'Default Branch', modules: module.value.default, removable: false },
|
||||
...module.value.branches.map((b, i) => ({
|
||||
summary: defaultIfEmptyString(b.summary, 'Branch ' + (i + 1)),
|
||||
summary: defaultIfEmptyString(b.summary, 'Branch ' + (i + 1)) + '\n`' + b.expr + '`',
|
||||
modules: b.modules,
|
||||
removable: true
|
||||
}))
|
||||
@@ -226,7 +226,7 @@
|
||||
module,
|
||||
modules,
|
||||
branches,
|
||||
['', ...module.value.branches.map((x) => `${truncateRev(x.expr, 20)}`)],
|
||||
[], //['', ...module.value.branches.map((x) => `${truncateRev(x.expr, 20)}`)],
|
||||
parent,
|
||||
loopDepth,
|
||||
false
|
||||
@@ -483,7 +483,8 @@
|
||||
false,
|
||||
removable ? { module, index: i } : undefined,
|
||||
undefined,
|
||||
undefined
|
||||
undefined,
|
||||
false
|
||||
)
|
||||
)
|
||||
if (modules.length) {
|
||||
@@ -642,7 +643,8 @@
|
||||
selectable: boolean,
|
||||
deleteBranch: { module: FlowModule; index: number } | undefined,
|
||||
mid: string | undefined,
|
||||
fixed_id: string | undefined
|
||||
fixed_id: string | undefined,
|
||||
center: boolean = true
|
||||
): Node {
|
||||
const id = fixed_id ?? -idGenerator.next().value - 2 + (offset ?? 0)
|
||||
return {
|
||||
@@ -673,7 +675,8 @@
|
||||
whereInsert,
|
||||
deleteBranch,
|
||||
id: mid,
|
||||
moving
|
||||
moving,
|
||||
center
|
||||
},
|
||||
cb: (e: string, detail: any) => {
|
||||
if (e == 'insert') {
|
||||
|
||||
Reference in New Issue
Block a user