diff --git a/backend/windmill-api/src/flows.rs b/backend/windmill-api/src/flows.rs index 200541db8b..af664cb340 100644 --- a/backend/windmill-api/src/flows.rs +++ b/backend/windmill-api/src/flows.rs @@ -426,6 +426,7 @@ mod tests { InputTransform::Static { value: serde_json::json!("test2") }, )] .into(), + hash: None, }, stop_after_if: None, summary: None, @@ -477,6 +478,7 @@ mod tests { value: FlowModuleValue::Script { path: "test".to_string(), input_transforms: HashMap::new(), + hash: None, }, stop_after_if: Some(StopAfterIf { expr: "previous.isEmpty()".to_string(), diff --git a/backend/windmill-common/src/flows.rs b/backend/windmill-common/src/flows.rs index 744a4e5a7b..832cdf89c0 100644 --- a/backend/windmill-common/src/flows.rs +++ b/backend/windmill-common/src/flows.rs @@ -12,7 +12,7 @@ use serde::{self, Deserialize, Serialize}; use crate::{ more_serde::{default_false, default_id, default_true, is_default}, - scripts::{Schema, ScriptLang}, + scripts::{Schema, ScriptHash, ScriptLang}, }; #[derive(Serialize)] @@ -200,6 +200,7 @@ pub enum FlowModuleValue { #[serde(alias = "input_transform")] input_transforms: HashMap, path: String, + hash: Option, }, ForloopFlow { iterator: InputTransform, diff --git a/backend/windmill-worker/src/worker_flow.rs b/backend/windmill-worker/src/worker_flow.rs index b6fef1a9f3..75d07eca47 100644 --- a/backend/windmill-worker/src/worker_flow.rs +++ b/backend/windmill-worker/src/worker_flow.rs @@ -816,19 +816,27 @@ async fn push_next_flow_job( if let Some(it) = sleep_input_transform { let json_value = match it { InputTransform::Static { value } => value, - InputTransform::Javascript { expr } => eval_timeout( - expr.to_string(), - [("result".to_string(), last_result.clone())].into(), - None, - None, - "".to_string(), - ) - .await - .map_err(|e| { - Error::ExecutionErr(format!( - "Error during isolated evaluation of expression `{expr}`:\n{e}" - )) - })?, + InputTransform::Javascript { expr } => { + let flow_input = flow_job.args.clone().unwrap_or_else(|| json!({})); + + eval_timeout( + expr.to_string(), + [ + ("result".to_string(), last_result.clone()), + ("flow_input".to_string(), flow_input), + ] + .into(), + None, + None, + "".to_string(), + ) + .await + .map_err(|e| { + Error::ExecutionErr(format!( + "Error during isolated evaluation of expression `{expr}`:\n{e}" + )) + })? + } }; match json_value { serde_json::Value::Number(n) => { @@ -1445,9 +1453,15 @@ async fn compute_next_flow_transform<'c>( tx, NextFlowTransform::Continue(vec![JobPayload::Identity], NextStatus::NextStep), )), - FlowModuleValue::Script { path: script_path, .. } => { - let payload = - script_path_to_payload(script_path, &mut tx, &flow_job.workspace_id).await?; + FlowModuleValue::Script { path: script_path, hash: script_hash, .. } => { + let payload = if script_hash.is_none() { + script_path_to_payload(script_path, &mut tx, &flow_job.workspace_id).await? + } else { + JobPayload::ScriptHash { + hash: script_hash.clone().unwrap(), + path: script_path.to_owned(), + } + }; Ok(( tx, NextFlowTransform::Continue(vec![payload], NextStatus::NextStep), diff --git a/frontend/src/lib/components/EditorBar.svelte b/frontend/src/lib/components/EditorBar.svelte index bf9a280ca3..6941e57b8e 100644 --- a/frontend/src/lib/components/EditorBar.svelte +++ b/frontend/src/lib/components/EditorBar.svelte @@ -270,21 +270,6 @@ +Resource - -
- -
-
+
+
- +
+ +
diff --git a/frontend/src/lib/components/IconedPath.svelte b/frontend/src/lib/components/IconedPath.svelte index 9911973ee6..6c94b3e5d8 100644 --- a/frontend/src/lib/components/IconedPath.svelte +++ b/frontend/src/lib/components/IconedPath.svelte @@ -1,18 +1,26 @@ -
+
{#if path.startsWith('hub/')}
- {path} + {path} {:else} - Workspace - {path} +
+ +
+ {path} + {#if hash} + {truncateHash(hash)} + {/if} {/if}
diff --git a/frontend/src/lib/components/LogViewer.svelte b/frontend/src/lib/components/LogViewer.svelte index 32a0ca9974..3edb923d4a 100644 --- a/frontend/src/lib/components/LogViewer.svelte +++ b/frontend/src/lib/components/LogViewer.svelte @@ -21,7 +21,7 @@ - +
{#if content}{content}{:else if isLoading}Waiting for job to start...{:else}No logs are available yet{/if}
= { [RawScript.language.GO]: 'dark-indigo', [RawScript.language.DENO]: 'dark-blue', @@ -22,18 +20,18 @@ class="flex items-center justify-between py-2 px-4 border-b border-gray-300 space-x-2 h-full max-h-12 flex-nowrap" > {#if flowModule} - +
- {#if shouldPick} - Select a step kind + {#if flowModule.value.type === 'identity'} + Identity (input copied to output) {:else if flowModule?.value.type === 'rawscript'} {flowModule?.value.language} - + {:else if flowModule?.value.type === 'script' && 'path' in flowModule.value && flowModule.value.path} - - + + {/if}
diff --git a/frontend/src/lib/components/flows/content/FlowInput.svelte b/frontend/src/lib/components/flows/content/FlowInput.svelte index e4d3a01481..6f064a854b 100644 --- a/frontend/src/lib/components/flows/content/FlowInput.svelte +++ b/frontend/src/lib/components/flows/content/FlowInput.svelte @@ -5,7 +5,6 @@ import SchemaForm from '$lib/components/SchemaForm.svelte' import FlowCard from '../common/FlowCard.svelte' import { copyFirstStepSchema, flowStore } from '../flowStore' - import { isEmptyFlowModule } from '../utils' import CapturePayload from './CapturePayload.svelte' let capturePayload: CapturePayload @@ -29,7 +28,7 @@ color="dark" size="sm" disabled={$flowStore.value.modules.length === 0 || - isEmptyFlowModule($flowStore.value.modules[0])} + $flowStore.value.modules[0].value.type == 'identity'} on:click={copyFirstStepSchema} > First step's inputs diff --git a/frontend/src/lib/components/flows/content/FlowInputs.svelte b/frontend/src/lib/components/flows/content/FlowInputs.svelte index 84a07a51b2..f67c5cb636 100644 --- a/frontend/src/lib/components/flows/content/FlowInputs.svelte +++ b/frontend/src/lib/components/flows/content/FlowInputs.svelte @@ -1,11 +1,10 @@
- {#if !shouldPick} - dispatch('toggleStopAfterIf')} > - - + + + {/if} - {#if module.value.type === 'script' && !shouldPick} + {#if module.value.type === 'script'} +
diff --git a/frontend/src/lib/components/flows/map/MapItem.svelte b/frontend/src/lib/components/flows/map/MapItem.svelte index 3388819a7e..9cd90f0d49 100644 --- a/frontend/src/lib/components/flows/map/MapItem.svelte +++ b/frontend/src/lib/components/flows/map/MapItem.svelte @@ -7,17 +7,11 @@ import InsertModuleButton from './InsertModuleButton.svelte' import FlowBranchOneMap from './FlowBranchOneMap.svelte' import FlowBranchAllMap from './FlowBranchAllMap.svelte' - import { - faArrowRotateForward, - faBuilding, - faCode, - faCodeBranch, - faLongArrowDown, - faRepeat - } from '@fortawesome/free-solid-svg-icons' + import { faCodeBranch, faLongArrowDown } from '@fortawesome/free-solid-svg-icons' import Icon from 'svelte-awesome' import IconedResourceType from '$lib/components/IconedResourceType.svelte' import LanguageIcon from '$lib/components/common/languageIcons/LanguageIcon.svelte' + import { Building, Repeat } from 'svelte-lucide' export let mod: FlowModule @@ -53,7 +47,7 @@ {...itemProps} >
- +
@@ -125,7 +119,7 @@ />
{:else} - + {/if} {/if}
diff --git a/frontend/src/lib/components/flows/pickers/WorkspaceScriptPicker.svelte b/frontend/src/lib/components/flows/pickers/WorkspaceScriptPicker.svelte index 9c385d445c..1a4136f2c0 100644 --- a/frontend/src/lib/components/flows/pickers/WorkspaceScriptPicker.svelte +++ b/frontend/src/lib/components/flows/pickers/WorkspaceScriptPicker.svelte @@ -6,15 +6,18 @@ import { Badge, Skeleton } from '$lib/components/common' import { fade } from 'svelte/transition' import { flip } from 'svelte/animate' - import { emptyString } from '$lib/utils' + import { emptyString, truncateHash } from '$lib/utils' + import Toggle from '$lib/components/Toggle.svelte' export let kind: 'script' | 'trigger' | 'approval' | 'failure' = 'script' export let isTemplate: boolean | undefined = undefined + export let displayLock = false type Item = { path: string summary?: string description?: string + hash?: string } let items: Item[] | undefined = undefined @@ -36,6 +39,7 @@ ).sort() const dispatch = createEventDispatcher() + let lockHash = displayLock
+ {/if} + {#if displayLock} +
+ +
+ {/if} {#if filter.length > 0 && filteredItems.length == 0}

No items found

{/if}
    - {#each filteredItems as { path, summary, description, marked }} + {#each filteredItems as { path, hash, summary, description, marked }}
+ {#if lockHash}{truncateHash(hash ?? '')}{/if} {/each} diff --git a/frontend/src/lib/components/flows/utils.ts b/frontend/src/lib/components/flows/utils.ts index 15709f397b..4ca7969f30 100644 --- a/frontend/src/lib/components/flows/utils.ts +++ b/frontend/src/lib/components/flows/utils.ts @@ -212,9 +212,6 @@ export function charsToNumber(n: string): number { return res - 1 } -export function isEmptyFlowModule(flowModule: FlowModule): boolean { - return flowModule.value.type === 'identity' -} export async function findNextAvailablePath(path: string): Promise { try { diff --git a/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte b/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte index 0017764745..c69e6573dc 100644 --- a/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte +++ b/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte @@ -1,8 +1,8 @@