From f31cdc46ffd7b5e8ddc2283d77e412347e22053d Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Sun, 3 Dec 2023 15:13:48 +0100 Subject: [PATCH] feat: save inline scripts of apps to workspace + search by path --- ...1203110120_add_more_script_config.down.sql | 5 ++ ...231203110120_add_more_script_config.up.sql | 5 ++ backend/tests/worker.rs | 4 ++ backend/windmill-api/openapi.yaml | 16 +++++ backend/windmill-api/src/workspaces.rs | 9 +++ backend/windmill-common/src/flows.rs | 3 + backend/windmill-common/src/scripts.rs | 9 +++ .../src/lib/components/ContentSearch.svelte | 49 +++++++++------ frontend/src/lib/components/EditorBar.svelte | 27 +++++++- frontend/src/lib/components/Path.svelte | 31 ++++++++- .../src/lib/components/ScriptEditor.svelte | 5 ++ .../InlineScriptEditor.svelte | 4 ++ .../InlineScriptEditorDrawer.svelte | 5 +- .../InlineScriptEditorPanel.svelte | 14 ++++- .../InlineScriptHiddenRunnable.svelte | 4 +- .../InlineScriptsPanel.svelte | 63 ++++++++++++++++++- .../InlineScriptsPanelWithTable.svelte | 3 + .../lib/components/flows/flowStateUtils.ts | 3 +- frontend/src/lib/components/flows/utils.ts | 22 ------- .../src/lib/components/home/ItemsList.svelte | 2 +- frontend/src/lib/path.ts | 25 ++++++++ openflow.openapi.yaml | 2 + 22 files changed, 257 insertions(+), 53 deletions(-) create mode 100644 backend/migrations/20231203110120_add_more_script_config.down.sql create mode 100644 backend/migrations/20231203110120_add_more_script_config.up.sql create mode 100644 frontend/src/lib/path.ts diff --git a/backend/migrations/20231203110120_add_more_script_config.down.sql b/backend/migrations/20231203110120_add_more_script_config.down.sql new file mode 100644 index 0000000000..8bd1e8c97c --- /dev/null +++ b/backend/migrations/20231203110120_add_more_script_config.down.sql @@ -0,0 +1,5 @@ +-- Add down migration script here +ALTER TABLE script DROP COLUMN timeout; +ALTER TABLE script DROP COLUMN delete_after_use; +ALTER TABLE script DROP COLUMN restart_unless_cancelled; +ALTER TABLE flow DROP COLUMN timeout; diff --git a/backend/migrations/20231203110120_add_more_script_config.up.sql b/backend/migrations/20231203110120_add_more_script_config.up.sql new file mode 100644 index 0000000000..f5440ca18f --- /dev/null +++ b/backend/migrations/20231203110120_add_more_script_config.up.sql @@ -0,0 +1,5 @@ +-- Add up migration script here +ALTER TABLE script ADD COLUMN timeout INTEGER; +ALTER TABLE flow ADD COLUMN timeout INTEGER; +ALTER TABLE script ADD COLUMN delete_after_use BOOLEAN; +ALTER TABLE script ADD COLUMN restart_unless_cancelled SMALLINT; diff --git a/backend/tests/worker.rs b/backend/tests/worker.rs index d7138afab3..5864930b39 100644 --- a/backend/tests/worker.rs +++ b/backend/tests/worker.rs @@ -2579,6 +2579,7 @@ async fn test_flow_lock_all(db: Pool) { ws_error_handler_muted: None, priority: None, dedicated_worker: None, + timeout: None, }, draft_only: None, }, @@ -3129,6 +3130,9 @@ async fn run_deployed_relative_imports(db: &Pool, script_content: Stri schema: std::collections::HashMap::new(), ws_error_handler_muted: Some(false), priority: None, + delete_after_use: None, + timeout: None, + restart_unless_cancelled: None, }, ).await.unwrap(); diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 62e61927e0..a80a66038a 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -6912,6 +6912,12 @@ components: type: boolean priority: type: integer + restart_unless_cancelled: + type: boolean + timeout: + type: integer + delete_after_use: + type: boolean required: - hash - path @@ -6990,6 +6996,12 @@ components: type: boolean priority: type: integer + restart_unless_cancelled: + type: boolean + timeout: + type: integer + delete_after_use: + type: boolean required: - path - summary @@ -8257,6 +8269,8 @@ components: type: integer dedicated_worker: type: boolean + timeout: + type: number required: - path - edited_by @@ -8279,6 +8293,8 @@ components: type: integer dedicated_worker: type: boolean + timeout: + type: number required: - path diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index 91cb330252..649d8b6a5c 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -1681,6 +1681,12 @@ struct ScriptMetadata { priority: Option, #[serde(skip_serializing_if = "Option::is_none")] tag: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub timeout: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub delete_after_use: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub restart_unless_cancelled: Option, } pub fn is_none_or_false(val: &Option) -> bool { @@ -1886,6 +1892,9 @@ async fn tarball_workspace( ws_error_handler_muted: script.ws_error_handler_muted, priority: script.priority, tag: script.tag, + timeout: script.timeout, + delete_after_use: script.delete_after_use, + restart_unless_cancelled: script.restart_unless_cancelled, }; let metadata_str = serde_json::to_string_pretty(&metadata).unwrap(); diff --git a/backend/windmill-common/src/flows.rs b/backend/windmill-common/src/flows.rs index 23292771ac..7467af9611 100644 --- a/backend/windmill-common/src/flows.rs +++ b/backend/windmill-common/src/flows.rs @@ -41,6 +41,8 @@ pub struct Flow { pub tag: Option, #[serde(skip_serializing_if = "Option::is_none")] pub ws_error_handler_muted: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub timeout: Option, } #[derive(Serialize)] @@ -74,6 +76,7 @@ pub struct NewFlow { pub tag: Option, pub ws_error_handler_muted: Option, pub dedicated_worker: Option, + pub timeout: Option, } #[derive(Deserialize, Serialize, Debug, Clone, Default)] diff --git a/backend/windmill-common/src/scripts.rs b/backend/windmill-common/src/scripts.rs index e1cd326224..c1177ca7e6 100644 --- a/backend/windmill-common/src/scripts.rs +++ b/backend/windmill-common/src/scripts.rs @@ -176,6 +176,12 @@ pub struct Script { pub priority: Option, #[serde(skip_serializing_if = "Option::is_none")] pub cache_ttl: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub timeout: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub delete_after_use: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub restart_unless_cancelled: Option, } #[derive(Serialize)] @@ -234,6 +240,9 @@ pub struct NewScript { pub dedicated_worker: Option, pub ws_error_handler_muted: Option, pub priority: Option, + pub timeout: Option, + pub delete_after_use: Option, + pub restart_unless_cancelled: Option, } #[derive(Deserialize)] diff --git a/frontend/src/lib/components/ContentSearch.svelte b/frontend/src/lib/components/ContentSearch.svelte index cd5509e5f9..39e5af81cc 100644 --- a/frontend/src/lib/components/ContentSearch.svelte +++ b/frontend/src/lib/components/ContentSearch.svelte @@ -11,15 +11,16 @@ import FlowIcon from './home/FlowIcon.svelte' import { Alert, Button } from './common' import { goto } from '$app/navigation' + import YAML from 'yaml' let search: string = '' - export function open() { + export async function open(nsearch?: string) { isOpen = true - loadScripts() - loadResources() - loadApps() - loadFlows() + await Promise.all([loadScripts(), loadResources(), loadApps(), loadFlows()]) + if (nsearch) { + search = nsearch + } } export async function loadScripts() { @@ -38,6 +39,8 @@ flows = await FlowService.listSearchFlow({ workspace: $workspaceStore ?? '' }) } + let searchKind: 'all' | 'scripts' | 'flows' | 'apps' | 'resources' = 'all' + let isOpen = false let scripts: undefined | { path: string; content: string }[] = undefined @@ -52,13 +55,19 @@ let apps: undefined | { path: string; value: any }[] = undefined let filteredAppItems: { path: string; value: any; marked: any }[] = [] - let searchKind: 'all' | 'scripts' | 'flows' | 'apps' | 'resources' = 'all' - function getCounts(n: number) { return ` (${n})` } $: counts = - search == '' || !scripts || !resources || !flows || !apps + search == '' || + !scripts || + !resources || + !flows || + !apps || + !filteredAppItems || + !filteredFlowItems || + !filteredResourceItems || + !filteredScriptItems ? { all: '', apps: '', @@ -93,7 +102,7 @@ filter={search} items={resources} f={(s) => { - return JSON.stringify(s.value, null, 4) + return YAML.stringify(s.value) }} bind:filteredItems={filteredResourceItems} /> @@ -102,7 +111,7 @@ filter={search} items={flows} f={(s) => { - return JSON.stringify(s.value, null, 4) + return YAML.stringify(s.value, null, 4) }} bind:filteredItems={filteredFlowItems} /> @@ -111,7 +120,7 @@ filter={search} items={apps} f={(s) => { - return JSON.stringify(s.value, null, 4) + return YAML.stringify(s.value, null, 4) }} bind:filteredItems={filteredAppItems} /> @@ -243,6 +252,8 @@
{#if !$enterpriseLicense} +
+ Without EE, content search will only search among 10 scripts, 3 flows, 3 apps and 3 resources. @@ -252,8 +263,8 @@ {#if search.length > 0}
- {#if (searchKind == 'all' || searchKind == 'scripts') && filteredScriptItems.length > 0} - {#each filteredScriptItems as item} + {#if (searchKind == 'all' || searchKind == 'scripts') && filteredScriptItems?.length > 0} + {#each filteredScriptItems ?? [] as item}
{/each} {/if} - {#if (searchKind == 'all' || searchKind == 'resources') && filteredResourceItems.length > 0} - {#each filteredResourceItems as item} + {#if (searchKind == 'all' || searchKind == 'resources') && filteredResourceItems?.length > 0} + {#each filteredResourceItems ?? [] as item}
Resource: {item.path}
@@ -292,8 +303,8 @@
{/each} {/if} - {#if (searchKind == 'all' || searchKind == 'flows') && filteredFlowItems.length > 0} - {#each filteredFlowItems as item} + {#if (searchKind == 'all' || searchKind == 'flows') && filteredFlowItems?.length > 0} + {#each filteredFlowItems ?? [] as item}
{/each} {/if} - {#if (searchKind == 'all' || searchKind == 'apps') && filteredAppItems.length > 0} - {#each filteredAppItems as item} + {#if (searchKind == 'all' || searchKind == 'apps') && filteredAppItems?.length > 0} + {#each filteredAppItems ?? [] as item}
+ export let noHistory = false + export let saveToWorkspace = false let contextualVariablePicker: ItemPicker let variablePicker: ItemPicker @@ -557,7 +569,7 @@
- {#if scriptPath} + {#if scriptPath && !noHistory} + {/if}
diff --git a/frontend/src/lib/components/Path.svelte b/frontend/src/lib/components/Path.svelte index b3cec11908..a72ea8579e 100644 --- a/frontend/src/lib/components/Path.svelte +++ b/frontend/src/lib/components/Path.svelte @@ -17,7 +17,7 @@ import { superadmin, userStore, workspaceStore } from '$lib/stores' import { createEventDispatcher } from 'svelte' import { writable } from 'svelte/store' - import { Button, Drawer, DrawerContent } from './common' + import { Alert, Button, Drawer, DrawerContent } from './common' import Badge from './common/badge/Badge.svelte' import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte' import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte' @@ -25,7 +25,8 @@ import { random_adj } from './random_positive_adjetive' import Required from './Required.svelte' import Tooltip from './Tooltip.svelte' - import { Eye, Folder, Plus, User } from 'lucide-svelte' + import { Eye, Folder, Plus, SearchCode, User } from 'lucide-svelte' + import ContentSearch from './ContentSearch.svelte' type PathKind = 'resource' | 'script' | 'variable' | 'flow' | 'schedule' | 'app' | 'raw_app' let meta: Meta | undefined = undefined @@ -261,8 +262,14 @@ function setDirty() { !dirty && (dirty = true) } + + let contentSearch: ContentSearch +{#if kind != 'app' && kind != 'schedule' && initialPath != '' && initialPath != undefined} + +{/if} +
{error}
+ + {#if kind != 'app' && kind != 'schedule' && initialPath != '' && initialPath != undefined && initialPath != path} + + You are renaming an item that may be depended upon by other items. This may break apps, flows + or resources. Find if it used elsewhere using the content search. Note that linked variables + and resources (having the same path) are automatically moved together. +
+ +
+
+ {/if}