windmill-components 1.501.22 → 1.501.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package/components/FlowWrapper.svelte +3 -3
  2. package/package/components/ScriptBuilder.svelte +81 -50
  3. package/package/components/ScriptEditor.svelte +2 -2
  4. package/package/components/ScriptEditor.svelte.d.ts +1 -0
  5. package/package/components/ScriptWrapper.svelte +3 -3
  6. package/package/components/WorkerTagPicker.svelte +5 -7
  7. package/package/components/WorkerTagPicker.svelte.d.ts +6 -19
  8. package/package/components/WorkerTagSelect.svelte +4 -3
  9. package/package/components/WorkerTagSelect.svelte.d.ts +4 -0
  10. package/package/components/copilot/chat/AiChatLayout.svelte +68 -55
  11. package/package/components/copilot/chat/AiChatLayout.svelte.d.ts +1 -0
  12. package/package/components/custom_ui.d.ts +4 -0
  13. package/package/components/flows/common/FlowCardHeader.svelte +29 -11
  14. package/package/components/flows/common/FlowCardHeader.svelte.d.ts +8 -15
  15. package/package/components/flows/content/FlowEditorPanel.svelte +1 -1
  16. package/package/components/flows/content/FlowModuleComponent.svelte +7 -4
  17. package/package/components/flows/content/FlowModuleHeader.svelte +5 -0
  18. package/package/components/flows/content/FlowModuleScript.svelte +64 -32
  19. package/package/components/flows/content/FlowModuleScript.svelte.d.ts +6 -18
  20. package/package/components/flows/content/FlowModuleWorkerTagSelect.svelte +8 -2
  21. package/package/components/flows/content/FlowModuleWorkerTagSelect.svelte.d.ts +3 -1
  22. package/package/components/flows/content/FlowSettings.svelte +2 -2
  23. package/package/components/flows/content/FlowSettings.svelte.d.ts +1 -0
  24. package/package/components/graph/FlowGraphV2.svelte +1 -2
  25. package/package/components/schema/EditableSchemaSdkWrapper.svelte.d.ts +1 -0
  26. package/package/components/schema/EditableSchemaWrapper.svelte +5 -7
  27. package/package/components/schema/EditableSchemaWrapper.svelte.d.ts +3 -27
  28. package/package/components/schema/editable_schema_wrapper.d.ts +11 -0
  29. package/package/components/schema/editable_schema_wrapper.js +1 -1
  30. package/package/components/script_builder.d.ts +8 -1
  31. package/package/components/select/Select.svelte +1 -1
  32. package/package/components/select/utils.svelte.d.ts +1 -1
  33. package/package/components/select/utils.svelte.js +4 -1
  34. package/package.json +1 -1
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">import AiChatLayout from './copilot/chat/AiChatLayout.svelte';
2
2
  import FlowBuilder from './FlowBuilder.svelte';
3
- let { flowStore: oldFlowStore, ...props } = $props();
3
+ let { flowStore: oldFlowStore, disableAi, ...props } = $props();
4
4
  let flowStore = $state(oldFlowStore);
5
5
  </script>
6
6
 
7
- <AiChatLayout noPadding={true}>
8
- <FlowBuilder {flowStore} {...props} />
7
+ <AiChatLayout noPadding={true} {disableAi}>
8
+ <FlowBuilder {flowStore} {disableAi} {...props} />
9
9
  </AiChatLayout>
@@ -1,10 +1,10 @@
1
1
  <script lang="ts">import { createBubbler } from 'svelte/legacy';
2
2
  const bubble = createBubbler();
3
- import { DraftService, ScriptService, PostgresTriggerService, CaptureService } from '../gen';
3
+ import { DraftService, ScriptService, PostgresTriggerService, CaptureService, WorkerService } from '../gen';
4
4
  import { inferArgs } from '../infer';
5
5
  import { initialCode } from '../script_helpers';
6
6
  import AIFormSettings from './copilot/AIFormSettings.svelte';
7
- import { defaultScripts, enterpriseLicense, usedTriggerKinds, userStore, workspaceStore } from '../stores';
7
+ import { defaultScripts, enterpriseLicense, usedTriggerKinds, userStore, workerTags, workspaceStore } from '../stores';
8
8
  import { cleanValueProperties, emptySchema, emptyString, encodeState, generateRandomString, orderedJsonStringify, replaceFalseWithUndefined } from '../utils';
9
9
  import Path from './Path.svelte';
10
10
  import ScriptEditor from './ScriptEditor.svelte';
@@ -40,7 +40,8 @@ import DeployButton from './DeployButton.svelte';
40
40
  import { deployTriggers, filterDraftTriggers, handleSelectTriggerFromKind } from './triggers/utils';
41
41
  import DraftTriggersConfirmationModal from './common/confirmationModal/DraftTriggersConfirmationModal.svelte';
42
42
  import { Triggers } from './triggers/triggers.svelte';
43
- let { script, fullyLoaded = true, initialPath = $bindable(''), template = $bindable('script'), initialArgs = {}, lockedLanguage = false, showMeta = false, neverShowMeta = false, diffDrawer = undefined, savedScript = $bindable(undefined), searchParams = new URLSearchParams(), disableHistoryChange = false, replaceStateFn = (url) => window.history.replaceState(null, '', url), customUi = {}, savedPrimarySchedule = undefined, functionExports = undefined, children, onDeploy, onDeployError, onSaveInitial, onSeeDetails, onSaveDraftError, onSaveDraft } = $props();
43
+ import WorkerTagSelect from './WorkerTagSelect.svelte';
44
+ let { script, fullyLoaded = true, initialPath = $bindable(''), template = $bindable('script'), initialArgs = {}, lockedLanguage = false, showMeta = false, neverShowMeta = false, diffDrawer = undefined, savedScript = $bindable(undefined), searchParams = new URLSearchParams(), disableHistoryChange = false, replaceStateFn = (url) => window.history.replaceState(null, '', url), customUi = {}, savedPrimarySchedule = undefined, functionExports = undefined, children, onDeploy, onDeployError, onSaveInitial, onSeeDetails, onSaveDraftError, onSaveDraft, disableAi } = $props();
44
45
  export function getInitialAndModifiedValues() {
45
46
  return {
46
47
  savedValue: savedScript,
@@ -714,6 +715,12 @@ $effect(() => {
714
715
  $effect(() => {
715
716
  !disableHistoryChange && untrack(() => encodeScriptState(script));
716
717
  });
718
+ loadWorkerTags();
719
+ async function loadWorkerTags() {
720
+ if (!$workerTags) {
721
+ $workerTags = await WorkerService.getCustomTags({ workspace: $workspaceStore });
722
+ }
723
+ }
717
724
  </script>
718
725
 
719
726
  <svelte:window onkeydown={onKeyDown} />
@@ -850,7 +857,7 @@ $effect(() => {
850
857
  }}
851
858
  />
852
859
  </Label>
853
- {#if script.schema}
860
+ {#if script.schema && !disableAi && !customUi?.settingsPanel?.metadata?.disableAiFilling}
854
861
  <div class="mt-3">
855
862
  <AIFormSettings
856
863
  bind:prompt={script.schema.prompt_for_ai as string | undefined}
@@ -860,52 +867,52 @@ $effect(() => {
860
867
  {/if}
861
868
  </div>
862
869
  </Section>
863
-
864
- <Section label="Language">
865
- {#snippet action()}
866
- <DefaultScripts />
867
- {/snippet}
868
- {#if lockedLanguage}
869
- <div class="text-sm text-tertiary italic mb-2">
870
- As a forked script, the language '{script.language}' cannot be modified.
871
- </div>
872
- {/if}
873
- <div class=" grid grid-cols-3 gap-2">
874
- {#each langs as [label, lang] (lang)}
875
- {@const isPicked =
876
- (lang == script.language && template == 'script') ||
877
- (template == 'bunnative' && lang == 'bunnative') ||
878
- (template == 'docker' && lang == 'docker')}
879
- <Popover
880
- disablePopup={!enterpriseLangs.includes(lang) || !!$enterpriseLicense}
881
- >
882
- <Button
883
- aiId={`create-script-language-button-${lang}`}
884
- aiDescription={`Choose ${lang} as the language of the script`}
885
- size="sm"
886
- variant="border"
887
- color={isPicked ? 'blue' : 'light'}
888
- btnClasses={isPicked
889
- ? '!border-2 !bg-blue-50/75 dark:!bg-frost-900/75'
890
- : 'm-[1px]'}
891
- on:click={() => onScriptLanguageTrigger(lang)}
892
- disabled={lockedLanguage ||
893
- (enterpriseLangs.includes(lang) && !$enterpriseLicense)}
870
+ {#if !customUi?.settingsPanel?.metadata?.languages || customUi?.settingsPanel?.metadata?.languages?.length > 1}
871
+ <Section label="Language">
872
+ {#snippet action()}
873
+ <DefaultScripts />
874
+ {/snippet}
875
+ {#if lockedLanguage}
876
+ <div class="text-sm text-tertiary italic mb-2">
877
+ As a forked script, the language '{script.language}' cannot be modified.
878
+ </div>
879
+ {/if}
880
+ <div class=" grid grid-cols-3 gap-2">
881
+ {#each langs as [label, lang] (lang)}
882
+ {@const isPicked =
883
+ (lang == script.language && template == 'script') ||
884
+ (template == 'bunnative' && lang == 'bunnative') ||
885
+ (template == 'docker' && lang == 'docker')}
886
+ <Popover
887
+ disablePopup={!enterpriseLangs.includes(lang) || !!$enterpriseLicense}
894
888
  >
895
- <LanguageIcon {lang} />
896
- <span class="ml-2 py-2 truncate">{label}</span>
897
- {#if lang === 'nu'}
898
- <span class="text-tertiary !text-xs"> BETA </span>
899
- {/if}
900
- </Button>
901
- {#snippet text()}
902
- {label} is only available with an enterprise license
903
- {/snippet}
904
- </Popover>
905
- {/each}
906
- </div>
907
- </Section>
908
-
889
+ <Button
890
+ aiId={`create-script-language-button-${lang}`}
891
+ aiDescription={`Choose ${lang} as the language of the script`}
892
+ size="sm"
893
+ variant="border"
894
+ color={isPicked ? 'blue' : 'light'}
895
+ btnClasses={isPicked
896
+ ? '!border-2 !bg-blue-50/75 dark:!bg-frost-900/75'
897
+ : 'm-[1px]'}
898
+ on:click={() => onScriptLanguageTrigger(lang)}
899
+ disabled={lockedLanguage ||
900
+ (enterpriseLangs.includes(lang) && !$enterpriseLicense)}
901
+ >
902
+ <LanguageIcon {lang} />
903
+ <span class="ml-2 py-2 truncate">{label}</span>
904
+ {#if lang === 'nu'}
905
+ <span class="text-tertiary !text-xs"> BETA </span>
906
+ {/if}
907
+ </Button>
908
+ {#snippet text()}
909
+ {label} is only available with an enterprise license
910
+ {/snippet}
911
+ </Popover>
912
+ {/each}
913
+ </div>
914
+ </Section>
915
+ {/if}
909
916
  {#if customUi?.settingsPanel?.metadata?.disableScriptKind !== true}
910
917
  <Section label="Script kind">
911
918
  {#snippet header()}
@@ -941,6 +948,14 @@ $effect(() => {
941
948
  </ToggleButtonGroup>
942
949
  </Section>
943
950
  {/if}
951
+ {#if customUi?.settingsPanel?.disableRuntime}
952
+ <Section label="Worker group tag (queue)">
953
+ <WorkerTagPicker
954
+ bind:tag={script.tag}
955
+ placeholder={customUi?.tagSelectPlaceholder}
956
+ />
957
+ </Section>
958
+ {/if}
944
959
  </div>
945
960
  </TabContent>
946
961
  <TabContent value="runtime">
@@ -1008,7 +1023,10 @@ $effect(() => {
1008
1023
  group tag (queue). For instance, you could setup an "highmem", or "gpu" tag.
1009
1024
  </Tooltip>
1010
1025
  {/snippet}
1011
- <WorkerTagPicker bind:tag={script.tag} />
1026
+ <WorkerTagPicker
1027
+ bind:tag={script.tag}
1028
+ placeholder={customUi?.tagSelectPlaceholder}
1029
+ />
1012
1030
  </Section>
1013
1031
  <Section label="Cache">
1014
1032
  {#snippet header()}
@@ -1462,6 +1480,18 @@ $effect(() => {
1462
1480
  {/if}
1463
1481
 
1464
1482
  <div class="flex flex-row gap-x-1 lg:gap-x-2">
1483
+ {#if $workerTags}
1484
+ {#if $workerTags?.length ?? 0 > 0}
1485
+ <div class="max-w-[200px] pr-8">
1486
+ <WorkerTagSelect
1487
+ inputClass="text-sm text-secondary !placeholder-secondary"
1488
+ nullTag={script.language}
1489
+ placeholder={customUi?.tagSelectPlaceholder}
1490
+ bind:tag={script.tag}
1491
+ />
1492
+ </div>
1493
+ {/if}
1494
+ {/if}
1465
1495
  {#if customUi?.topBar?.settings != false}
1466
1496
  <Button
1467
1497
  aiId="script-builder-settings"
@@ -1502,6 +1532,7 @@ $effect(() => {
1502
1532
  </div>
1503
1533
 
1504
1534
  <ScriptEditor
1535
+ {disableAi}
1505
1536
  bind:selectedTab={selectedInputTab}
1506
1537
  {customUi}
1507
1538
  collabMode
@@ -33,7 +33,7 @@ import { SUPPORTED_CHAT_SCRIPT_LANGUAGES } from './copilot/chat/script/core';
33
33
  import { getStringError } from './copilot/chat/utils';
34
34
  import { aiChatManager, AIMode } from './copilot/chat/AIChatManager.svelte';
35
35
  import { triggerableByAI } from '../actions/triggerableByAI.svelte';
36
- let { schema = $bindable(), code = $bindable(), path, lang, kind = undefined, template = 'script', tag, fixedOverflowWidgets = true, noSyncFromGithub = false, editor = $bindable(undefined), diffEditor = $bindable(undefined), collabMode = false, edit = true, noHistory = false, saveToWorkspace = false, watchChanges = false, customUi = undefined, args = $bindable(), selectedTab = $bindable('main'), hasPreprocessor = $bindable(false), captureTable = $bindable(undefined), showCaptures = true, stablePathForCaptures = '', lastSavedCode = undefined, lastDeployedCode = undefined, editor_bar_right } = $props();
36
+ let { schema = $bindable(), code = $bindable(), path, lang, kind = undefined, template = 'script', tag, fixedOverflowWidgets = true, noSyncFromGithub = false, editor = $bindable(undefined), diffEditor = $bindable(undefined), collabMode = false, edit = true, noHistory = false, saveToWorkspace = false, watchChanges = false, customUi = undefined, args = $bindable(), selectedTab = $bindable('main'), hasPreprocessor = $bindable(false), captureTable = $bindable(undefined), showCaptures = true, stablePathForCaptures = '', lastSavedCode = undefined, lastDeployedCode = undefined, disableAi = false, editor_bar_right } = $props();
37
37
  $effect.pre(() => {
38
38
  if (schema == undefined) {
39
39
  schema = emptySchema();
@@ -394,7 +394,7 @@ $effect(() => {
394
394
  color="marine"
395
395
  />
396
396
  {/if}
397
- {#if !aiChatManager.open}
397
+ {#if !aiChatManager.open && !disableAi}
398
398
  {#if customUi?.editorBar?.aiGen != false && SUPPORTED_CHAT_SCRIPT_LANGUAGES.includes(lang ?? '')}
399
399
  <HideButton
400
400
  hidden={true}
@@ -31,6 +31,7 @@ interface Props {
31
31
  stablePathForCaptures?: string;
32
32
  lastSavedCode?: string | undefined;
33
33
  lastDeployedCode?: string | undefined;
34
+ disableAi?: boolean;
34
35
  editor_bar_right?: import('svelte').Snippet;
35
36
  }
36
37
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">import ScriptBuilder from './ScriptBuilder.svelte';
2
2
  import AiChatLayout from './copilot/chat/AiChatLayout.svelte';
3
- let { script: oldScript, ...props } = $props();
3
+ let { script: oldScript, disableAi, ...props } = $props();
4
4
  let script = $state(oldScript);
5
5
  </script>
6
6
 
7
- <AiChatLayout noPadding>
8
- <ScriptBuilder {script} {...props} />
7
+ <AiChatLayout noPadding {disableAi}>
8
+ <ScriptBuilder {script} {disableAi} {...props} />
9
9
  </AiChatLayout>
@@ -4,11 +4,9 @@ import { workerTags, workspaceStore } from '../stores';
4
4
  import AssignableTags from './AssignableTags.svelte';
5
5
  import { WorkerService } from '../gen';
6
6
  import WorkerTagSelect from './WorkerTagSelect.svelte';
7
- export let tag;
8
- export let popupPlacement = 'bottom-end';
9
- export let disabled = false;
10
- loadWorkerGroups();
11
- async function loadWorkerGroups() {
7
+ let { tag = $bindable(), popupPlacement = 'bottom-end', disabled = false, placeholder } = $props();
8
+ loadWorkerTags();
9
+ async function loadWorkerTags() {
12
10
  if (!$workerTags) {
13
11
  $workerTags = await WorkerService.getCustomTags({ workspace: $workspaceStore });
14
12
  }
@@ -19,7 +17,7 @@ async function loadWorkerGroups() {
19
17
  <div class="max-w-sm grow">
20
18
  {#if $workerTags}
21
19
  {#if $workerTags?.length ?? 0 > 0}
22
- <WorkerTagSelect noLabel bind:tag {disabled} />
20
+ <WorkerTagSelect {placeholder} noLabel bind:tag {disabled} />
23
21
  {:else}
24
22
  <div class="text-sm text-secondary flex flex-row gap-2">
25
23
  No custom worker group tag defined on this instance in "Workers {'->'} Custom tags"
@@ -45,7 +43,7 @@ async function loadWorkerGroups() {
45
43
  color="light"
46
44
  on:click={() => {
47
45
  $workerTags = undefined
48
- loadWorkerGroups()
46
+ loadWorkerTags()
49
47
  }}
50
48
  startIcon={{ icon: RotateCw }}
51
49
  {disabled}
@@ -1,22 +1,9 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: Props & {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const WorkerTagPicker: $$__sveltets_2_IsomorphicComponent<{
1
+ interface Props {
15
2
  tag: string | undefined;
16
- popupPlacement?: "bottom-end" | "top-end";
3
+ popupPlacement?: 'bottom-end' | 'top-end';
17
4
  disabled?: boolean;
18
- }, {
19
- [evt: string]: CustomEvent<any>;
20
- }, {}, {}, string>;
21
- type WorkerTagPicker = InstanceType<typeof WorkerTagPicker>;
5
+ placeholder?: string;
6
+ }
7
+ declare const WorkerTagPicker: import("svelte").Component<Props, {}, "tag">;
8
+ type WorkerTagPicker = ReturnType<typeof WorkerTagPicker>;
22
9
  export default WorkerTagPicker;
@@ -3,7 +3,7 @@ import { WorkerService } from '../gen';
3
3
  import { createEventDispatcher } from 'svelte';
4
4
  import Select from './select/Select.svelte';
5
5
  import { safeSelectItems } from './select/utils.svelte';
6
- let { tag = $bindable(), noLabel = false, nullTag = undefined, disabled = false } = $props();
6
+ let { tag = $bindable(), noLabel = false, nullTag = undefined, disabled = false, placeholder, inputClass } = $props();
7
7
  loadWorkerGroups();
8
8
  const dispatch = createEventDispatcher();
9
9
  async function loadWorkerGroups() {
@@ -20,13 +20,14 @@ let items = $derived([
20
20
 
21
21
  <div class="flex gap-1 items-center">
22
22
  {#if !noLabel}
23
- <div class="text-tertiary text-2xs">tag</div>
23
+ <div class="text-tertiary text-2xs">{placeholder ?? 'tag'}</div>
24
24
  {/if}
25
25
  <Select
26
26
  clearable
27
27
  class="w-full"
28
+ {inputClass}
28
29
  {disabled}
29
- placeholder={nullTag ? `default: ${nullTag}` : 'lang default'}
30
+ placeholder={nullTag ? nullTag : (placeholder ?? 'lang default')}
30
31
  items={safeSelectItems(items)}
31
32
  bind:value={() => tag, (value) => ((tag = value), dispatch('change', value))}
32
33
  />
@@ -3,6 +3,10 @@ type $$ComponentProps = {
3
3
  noLabel?: boolean;
4
4
  nullTag?: string | undefined;
5
5
  disabled?: boolean;
6
+ placeholder?: string;
7
+ language?: string;
8
+ class?: string;
9
+ inputClass?: string;
6
10
  };
7
11
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
8
12
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
@@ -4,65 +4,78 @@ import AiChat from './AIChat.svelte';
4
4
  import { zIndexes } from '../../../zIndexes';
5
5
  import { loadCopilot, userStore, workspaceStore } from '../../../stores';
6
6
  import { chatState } from './sharedChatState.svelte';
7
- let { noPadding: noBorder = false, isCollapsed = false, children, onMenuOpen } = $props();
8
- workspaceStore.subscribe(async (workspace) => {
9
- if (workspace) {
10
- loadCopilot(workspace);
7
+ let { noPadding: noBorder = false, isCollapsed = false, children, onMenuOpen, disableAi } = $props();
8
+ $effect(() => {
9
+ if (disableAi) {
10
+ chatState.size = 0;
11
+ }
12
+ });
13
+ $effect(() => {
14
+ if ($workspaceStore && !disableAi) {
15
+ loadCopilot($workspaceStore);
11
16
  }
12
17
  });
13
18
  </script>
14
19
 
15
- <Splitpanes horizontal={false} class="flex-1 min-h-0">
16
- <Pane size={99.8 - chatState.size} minSize={50} class="flex flex-col min-h-0">
17
- <div
18
- id="content"
19
- class={classNames(
20
- 'w-full flex-1 flex flex-col overflow-y-auto',
21
- noBorder || $userStore?.operator ? '!pl-0' : isCollapsed ? 'md:pl-12' : 'md:pl-40',
22
- 'transition-all ease-in-out duration-200'
23
- )}
24
- >
25
- <main class="flex-1 flex flex-col">
26
- <div class="relative w-full flex-1 flex flex-col">
27
- <div
28
- class={classNames(
29
- 'pt-2 px-4 sm:px-4 flex flex-row justify-between items-center shadow-sm max-w-7xl md:hidden',
30
- noBorder || $userStore?.operator ? 'hidden' : ''
31
- )}
32
- >
33
- <button
34
- aria-label="Menu"
35
- type="button"
36
- onclick={() => {
37
- onMenuOpen?.()
38
- }}
39
- class="h-8 w-8 inline-flex items-center justify-center rounded-md text-tertiary hover:text-primary focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
20
+ {#if !disableAi}
21
+ <Splitpanes horizontal={false} class="flex-1 min-h-0">
22
+ <Pane size={99.8 - chatState.size} minSize={50} class="flex flex-col min-h-0">
23
+ <div
24
+ id="content"
25
+ class={classNames(
26
+ 'w-full flex-1 flex flex-col overflow-y-auto',
27
+ noBorder || $userStore?.operator ? '!pl-0' : isCollapsed ? 'md:pl-12' : 'md:pl-40',
28
+ 'transition-all ease-in-out duration-200'
29
+ )}
30
+ >
31
+ <main class="flex-1 flex flex-col">
32
+ <div class="relative w-full flex-1 flex flex-col">
33
+ <div
34
+ class={classNames(
35
+ 'pt-2 px-4 sm:px-4 flex flex-row justify-between items-center shadow-sm max-w-7xl md:hidden',
36
+ noBorder || $userStore?.operator ? 'hidden' : ''
37
+ )}
40
38
  >
41
- <svg
42
- class="h-6 w-6"
43
- xmlns="http://www.w3.org/2000/svg"
44
- fill="none"
45
- viewBox="0 0 24 24"
46
- stroke-width="2"
47
- stroke="currentColor"
48
- aria-hidden="true"
39
+ <button
40
+ aria-label="Menu"
41
+ type="button"
42
+ onclick={() => {
43
+ onMenuOpen?.()
44
+ }}
45
+ class="h-8 w-8 inline-flex items-center justify-center rounded-md text-tertiary hover:text-primary focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
49
46
  >
50
- <path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
51
- </svg>
52
- </button>
47
+ <svg
48
+ class="h-6 w-6"
49
+ xmlns="http://www.w3.org/2000/svg"
50
+ fill="none"
51
+ viewBox="0 0 24 24"
52
+ stroke-width="2"
53
+ stroke="currentColor"
54
+ aria-hidden="true"
55
+ >
56
+ <path
57
+ stroke-linecap="round"
58
+ stroke-linejoin="round"
59
+ d="M4 6h16M4 12h16M4 18h16"
60
+ />
61
+ </svg>
62
+ </button>
63
+ </div>
64
+ <div class="flex-1">
65
+ {@render children?.()}
66
+ </div>
53
67
  </div>
54
- <div class="flex-1">
55
- {@render children?.()}
56
- </div>
57
- </div>
58
- </main>
59
- </div>
60
- </Pane>
61
- <Pane
62
- bind:size={chatState.size}
63
- minSize={15}
64
- class={`flex flex-col min-h-0 z-[${zIndexes.aiChat}]`}
65
- >
66
- <AiChat />
67
- </Pane>
68
- </Splitpanes>
68
+ </main>
69
+ </div>
70
+ </Pane>
71
+ <Pane
72
+ bind:size={chatState.size}
73
+ minSize={15}
74
+ class={`flex flex-col min-h-0 z-[${zIndexes.aiChat}]`}
75
+ >
76
+ <AiChat />
77
+ </Pane>
78
+ </Splitpanes>
79
+ {:else}
80
+ {@render children?.()}
81
+ {/if}
@@ -3,6 +3,7 @@ interface Props {
3
3
  isCollapsed?: boolean;
4
4
  children: any;
5
5
  onMenuOpen?: () => void;
6
+ disableAi?: boolean;
6
7
  }
7
8
  declare const AiChatLayout: import("svelte").Component<Props, {}, "">;
8
9
  type AiChatLayout = ReturnType<typeof AiChatLayout>;
@@ -39,6 +39,8 @@ export type FlowBuilderWhitelabelCustomUi = {
39
39
  tagEdit?: boolean;
40
40
  editorBar?: EditorBarUi;
41
41
  downloadLogs?: boolean;
42
+ tagSelectPlaceholder?: string;
43
+ tagSelectNoLabel?: boolean;
42
44
  };
43
45
  export type DisplayResultUi = {
44
46
  disableAiFix?: boolean;
@@ -77,6 +79,7 @@ export type SettingsPanelMetadataUi = {
77
79
  disableScriptKind?: boolean;
78
80
  editableSchemaForm?: EditableSchemaFormUi;
79
81
  disableMute?: boolean;
82
+ disableAiFilling?: boolean;
80
83
  };
81
84
  export type SettingsPanelUi = {
82
85
  metadata?: SettingsPanelMetadataUi;
@@ -103,4 +106,5 @@ export type ScriptBuilderWhitelabelCustomUi = {
103
106
  disableTooltips?: boolean;
104
107
  editorBar?: EditorBarUi;
105
108
  previewPanel?: PreviewPanelUi;
109
+ tagSelectPlaceholder?: string;
106
110
  };
@@ -1,3 +1,7 @@
1
+ <script lang="ts" module>"use strict";
2
+ let cachedValues = {};
3
+ </script>
4
+
1
5
  <script lang="ts">import Badge from '../../common/badge/Badge.svelte';
2
6
  import Button from '../../common/button/Button.svelte';
3
7
  import LanguageIcon from '../../common/languageIcons/LanguageIcon.svelte';
@@ -6,24 +10,38 @@ import IconedPath from '../../IconedPath.svelte';
6
10
  import { ScriptService } from '../../../gen';
7
11
  import { workspaceStore } from '../../../stores';
8
12
  import { Lock, RefreshCw, Unlock } from 'lucide-svelte';
9
- import { createEventDispatcher } from 'svelte';
10
- export let flowModuleValue = undefined;
11
- export let title = undefined;
12
- export let summary = undefined;
13
- let latestHash = undefined;
13
+ import { createEventDispatcher, untrack } from 'svelte';
14
+ let { flowModuleValue = undefined, title = undefined, summary = $bindable(undefined), children } = $props();
15
+ let latestHash = $state(undefined);
16
+ function getCachedKey(path) {
17
+ return `${$workspaceStore}-${path}`;
18
+ }
19
+ function getCachedValues(path) {
20
+ const key = getCachedKey(path);
21
+ latestHash = cachedValues[key]?.latestHash;
22
+ }
23
+ if (flowModuleValue?.type === 'script' && flowModuleValue.path) {
24
+ getCachedValues(flowModuleValue.path);
25
+ }
14
26
  async function loadLatestHash(value) {
15
27
  let script = await ScriptService.getScriptByPath({
16
28
  workspace: $workspaceStore,
17
29
  path: value.path
18
30
  });
31
+ const key = getCachedKey(value.path);
32
+ cachedValues[key] = {
33
+ latestHash: script.hash
34
+ };
19
35
  latestHash = script.hash;
20
36
  }
21
37
  const dispatch = createEventDispatcher();
22
- $: $workspaceStore &&
23
- flowModuleValue?.type === 'script' &&
24
- flowModuleValue.path &&
25
- !flowModuleValue.path.startsWith('hub/') &&
26
- loadLatestHash(flowModuleValue);
38
+ $effect.pre(() => {
39
+ $workspaceStore &&
40
+ flowModuleValue?.type === 'script' &&
41
+ flowModuleValue.path &&
42
+ !flowModuleValue.path.startsWith('hub/') &&
43
+ untrack(() => loadLatestHash(flowModuleValue));
44
+ });
27
45
  </script>
28
46
 
29
47
  <div
@@ -109,5 +127,5 @@ $: $workspaceStore &&
109
127
  {#if title}
110
128
  <div class="text-sm font-bold text-primary pr-2">{title}</div>
111
129
  {/if}
112
- <slot />
130
+ {@render children?.()}
113
131
  </div>
@@ -1,4 +1,10 @@
1
1
  import { type FlowModuleValue } from '../../../gen';
2
+ interface Props {
3
+ flowModuleValue?: FlowModuleValue | undefined;
4
+ title?: string | undefined;
5
+ summary?: string | undefined;
6
+ children?: import('svelte').Snippet;
7
+ }
2
8
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
9
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
10
  $$bindings?: Bindings;
@@ -12,24 +18,11 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
12
18
  };
13
19
  z_$$bindings?: Bindings;
14
20
  }
15
- type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
16
- default: any;
17
- } ? Props extends Record<string, never> ? any : {
18
- children?: any;
19
- } : {});
20
- declare const FlowCardHeader: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<{
21
- flowModuleValue?: FlowModuleValue | undefined;
22
- title?: string | undefined;
23
- summary?: string | undefined;
24
- }, {
25
- default: {};
26
- }>, {
21
+ declare const FlowCardHeader: $$__sveltets_2_IsomorphicComponent<Props, {
27
22
  setHash: CustomEvent<any>;
28
23
  reload: CustomEvent<any>;
29
24
  } & {
30
25
  [evt: string]: CustomEvent<any>;
31
- }, {
32
- default: {};
33
- }, {}, string>;
26
+ }, {}, {}, "summary">;
34
27
  type FlowCardHeader = InstanceType<typeof FlowCardHeader>;
35
28
  export default FlowCardHeader;
@@ -28,7 +28,7 @@ $effect(() => {
28
28
  </script>
29
29
 
30
30
  {#if $selectedId?.startsWith('settings')}
31
- <FlowSettings {noEditor} />
31
+ <FlowSettings {enableAi} {noEditor} />
32
32
  {:else if $selectedId === 'Input'}
33
33
  <FlowInput
34
34
  {noEditor}
@@ -50,7 +50,8 @@ import { refreshStateStore } from '../../../svelte5Utils.svelte';
50
50
  import { getStepHistoryLoaderContext } from '../../stepHistoryLoader.svelte';
51
51
  const { selectedId, currentEditor, previewArgs, flowStateStore, flowStore, pathStore, saveDraft, customUi, executionCount } = getContext('FlowEditorContext');
52
52
  let { flowModule = $bindable(), failureModule = false, preprocessorModule = false, parentModule = $bindable(), previousModule, scriptKind = 'script', scriptTemplate = 'script', noEditor, enableAi, savedModule = undefined, forceTestTab = false, highlightArg = undefined } = $props();
53
- let tag = $state(undefined);
53
+ let workspaceScriptTag = $state(undefined);
54
+ let workspaceScriptLang = $state(undefined);
54
55
  let diffMode = $state(false);
55
56
  let editor = $state();
56
57
  let diffEditor = $state();
@@ -172,7 +173,7 @@ let lastDeployedCode = $derived(onModulesChange(savedModule, flowModule));
172
173
  let stepPropPicker = $derived($executionCount != undefined && failureModule
173
174
  ? getFailureStepPropPicker($flowStateStore, flowStore.val, previewArgs.val)
174
175
  : getStepPropPicker($flowStateStore, parentModule, previousModule, flowModule.id, flowStore.val, previewArgs.val, false));
175
- $effect(() => {
176
+ $effect.pre(() => {
176
177
  $selectedId && untrack(() => onSelectedIdChange());
177
178
  });
178
179
  $effect(() => {
@@ -220,6 +221,7 @@ $effect(() => {
220
221
  }, 100);
221
222
  }
222
223
  });
224
+ let rawScriptLang = $derived(flowModule.value.type == 'rawscript' ? flowModule.value.language : undefined);
223
225
  </script>
224
226
 
225
227
  <svelte:window onkeydown={onKeyDown} />
@@ -242,7 +244,7 @@ $effect(() => {
242
244
  >
243
245
  {#snippet header()}
244
246
  <FlowModuleHeader
245
- {tag}
247
+ tag={workspaceScriptTag ?? rawScriptLang ?? workspaceScriptLang}
246
248
  module={flowModule}
247
249
  on:tagChange={(e) => {
248
250
  console.log('tagChange', e.detail)
@@ -392,7 +394,8 @@ $effect(() => {
392
394
  <div class="border-t">
393
395
  {#key forceReload}
394
396
  <FlowModuleScript
395
- bind:tag
397
+ bind:tag={workspaceScriptTag}
398
+ bind:language={workspaceScriptLang}
396
399
  showAllCode={false}
397
400
  path={flowModule.value.path}
398
401
  hash={flowModule.value.hash}
@@ -124,6 +124,8 @@ let customUi = getContext('customUi');
124
124
  {/if}
125
125
  {#if customUi?.tagEdit != false}
126
126
  <FlowModuleWorkerTagSelect
127
+ placeholder={customUi?.tagSelectPlaceholder}
128
+ noLabel={customUi?.tagSelectNoLabel}
127
129
  nullTag={tag}
128
130
  tag={module.value.tag_override}
129
131
  on:change={(e) => dispatch('tagChange', e.detail)}
@@ -169,6 +171,9 @@ let customUi = getContext('customUi');
169
171
  <div class="px-0.5"></div>
170
172
  {#if module.value.type === 'rawscript'}
171
173
  <FlowModuleWorkerTagSelect
174
+ placeholder={customUi?.tagSelectPlaceholder}
175
+ noLabel={customUi?.tagSelectNoLabel}
176
+ nullTag={tag}
172
177
  tag={module.value.tag}
173
178
  on:change={(e) => dispatch('tagChange', e.detail)}
174
179
  />
@@ -1,21 +1,55 @@
1
+ <script lang="ts" module>"use strict";
2
+ let cachedValues = {};
3
+ </script>
4
+
1
5
  <script lang="ts">import HighlightCode from '../../HighlightCode.svelte';
2
6
  import TimeAgo from '../../TimeAgo.svelte';
3
7
  import { ScriptService } from '../../../gen';
4
8
  import { getScriptByPath, scriptLangToEditorLang } from '../../../scripts';
5
9
  import { workspaceStore } from '../../../stores';
6
10
  import { Loader2 } from 'lucide-svelte';
7
- export let path;
8
- export let hash = undefined;
9
- export let previousHash = undefined;
10
- export let showDate = false;
11
- export let showAllCode = true;
12
- export let tag = undefined;
13
- let code;
14
- let previousCode;
15
- let language;
16
- let lock = undefined;
17
- let date = undefined;
18
- let notFound = false;
11
+ import { untrack } from 'svelte';
12
+ let { path, hash = undefined, previousHash = undefined, showDate = false, showAllCode = $bindable(true), tag = $bindable(undefined), showDiff = false, language = $bindable(undefined) } = $props();
13
+ let code = $state();
14
+ let previousCode = $state();
15
+ let lock = $state(undefined);
16
+ let date = $state(undefined);
17
+ let notFound = $state(false);
18
+ function getCachedKey(path, hash) {
19
+ return `${$workspaceStore}-${path}-${hash ?? ''}`;
20
+ }
21
+ function getCachedValues(path, hash) {
22
+ const key = getCachedKey(path, hash);
23
+ code = cachedValues[key]?.code;
24
+ language = cachedValues[key]?.language;
25
+ lock = cachedValues[key]?.lock;
26
+ date = cachedValues[key]?.date;
27
+ previousCode = cachedValues[key]?.previousCode;
28
+ tag = cachedValues[key]?.tag;
29
+ notFound = cachedValues[key]?.notFound ?? false;
30
+ console.log('cachedValues', cachedValues, code);
31
+ }
32
+ getCachedValues(path, hash);
33
+ async function loadPreviousCode(previousHash) {
34
+ try {
35
+ const previousScript = await ScriptService.getScriptByHash({
36
+ workspace: $workspaceStore,
37
+ hash: previousHash
38
+ });
39
+ previousCode = previousScript.content;
40
+ const key = getCachedKey(path, previousHash);
41
+ cachedValues[key] = {
42
+ ...(cachedValues[key] ?? {}),
43
+ previousCode: previousScript.content
44
+ };
45
+ }
46
+ catch (e) {
47
+ console.error(e);
48
+ }
49
+ }
50
+ function toggleShowAll() {
51
+ showAllCode = !showAllCode;
52
+ }
19
53
  async function loadCode(path, hash) {
20
54
  try {
21
55
  notFound = false;
@@ -27,30 +61,28 @@ async function loadCode(path, hash) {
27
61
  lock = script.lock;
28
62
  date = script.created_at;
29
63
  tag = script.tag;
64
+ const key = getCachedKey(path, hash);
65
+ cachedValues[key] = {
66
+ ...(cachedValues[key] ?? {}),
67
+ code: script.content,
68
+ language: script.language,
69
+ lock: script.lock,
70
+ date: script.created_at,
71
+ tag: script.tag
72
+ };
30
73
  }
31
74
  catch (e) {
32
75
  notFound = true;
33
76
  console.error(e);
34
77
  }
35
78
  }
36
- async function loadPreviousCode(previousHash) {
37
- try {
38
- const previousScript = await ScriptService.getScriptByHash({
39
- workspace: $workspaceStore,
40
- hash: previousHash
41
- });
42
- previousCode = previousScript.content;
43
- }
44
- catch (e) {
45
- console.error(e);
46
- }
47
- }
48
- $: path && loadCode(path, hash);
49
- $: path && previousHash && loadPreviousCode(previousHash);
50
- function toggleShowAll() {
51
- showAllCode = !showAllCode;
52
- }
53
- export let showDiff = false;
79
+ $effect.pre(() => {
80
+ hash;
81
+ path && untrack(() => loadCode(path, hash));
82
+ });
83
+ $effect.pre(() => {
84
+ path && previousHash && untrack(() => loadPreviousCode(previousHash));
85
+ });
54
86
  </script>
55
87
 
56
88
  <div class="flex flex-col flex-1 h-full overflow-auto p-2">
@@ -64,7 +96,7 @@ export let showDiff = false;
64
96
  <div class="text-red-400">script not found at {path} in workspace {$workspaceStore}</div>
65
97
  {:else if showAllCode}
66
98
  {#if showDiff}
67
- {#key previousCode + code}
99
+ {#key (previousCode ?? '') + (code ?? '')}
68
100
  {#await import('../../DiffEditor.svelte')}
69
101
  <Loader2 class="animate-spin" />
70
102
  {:then Module}
@@ -86,7 +118,7 @@ export let showDiff = false;
86
118
  <div class="code-container h-full">
87
119
  <HighlightCode {language} code={code?.split('\n').slice(0, 10).join('\n')} />
88
120
  </div>
89
- <button on:click={toggleShowAll}>Show all</button>
121
+ <button onclick={toggleShowAll}>Show all</button>
90
122
  {/if}
91
123
 
92
124
  {#if lock}
@@ -1,26 +1,14 @@
1
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
- $$bindings?: Bindings;
4
- } & Exports;
5
- (internal: unknown, props: Props & {
6
- $$events?: Events;
7
- $$slots?: Slots;
8
- }): Exports & {
9
- $set?: any;
10
- $on?: any;
11
- };
12
- z_$$bindings?: Bindings;
13
- }
14
- declare const FlowModuleScript: $$__sveltets_2_IsomorphicComponent<{
1
+ import { type ScriptLang } from '../../../gen';
2
+ interface Props {
15
3
  path: string;
16
4
  hash?: string | undefined;
17
5
  previousHash?: string | undefined;
18
6
  showDate?: boolean;
19
7
  showAllCode?: boolean;
20
8
  tag?: string | undefined;
9
+ language?: ScriptLang | undefined;
21
10
  showDiff?: boolean;
22
- }, {
23
- [evt: string]: CustomEvent<any>;
24
- }, {}, {}, string>;
25
- type FlowModuleScript = InstanceType<typeof FlowModuleScript>;
11
+ }
12
+ declare const FlowModuleScript: import("svelte").Component<Props, {}, "language" | "tag" | "showAllCode">;
13
+ type FlowModuleScript = ReturnType<typeof FlowModuleScript>;
26
14
  export default FlowModuleScript;
@@ -2,7 +2,7 @@
2
2
  import { workerTags, workspaceStore } from '../../../stores';
3
3
  import { WorkerService } from '../../../gen';
4
4
  import WorkerTagSelect from '../../WorkerTagSelect.svelte';
5
- let { tag = $bindable(), nullTag = $bindable() } = $props();
5
+ let { tag = $bindable(), nullTag, placeholder, noLabel } = $props();
6
6
  const { flowStore, selectedId } = getContext('FlowEditorContext');
7
7
  const dispatch = createEventDispatcher();
8
8
  loadWorkerGroups();
@@ -17,7 +17,13 @@ async function loadWorkerGroups() {
17
17
  {#if $workerTags?.length > 0}
18
18
  <div class="w-40">
19
19
  {#if flowStore.val.tag == undefined}
20
- <WorkerTagSelect {nullTag} bind:tag on:change={(e) => dispatch('change', e.detail)} />
20
+ <WorkerTagSelect
21
+ {noLabel}
22
+ {placeholder}
23
+ {nullTag}
24
+ bind:tag
25
+ on:change={(e) => dispatch('change', e.detail)}
26
+ />
21
27
  {:else}
22
28
  <button
23
29
  title="Worker Group is defined at the flow level"
@@ -1,6 +1,8 @@
1
1
  type $$ComponentProps = {
2
2
  tag: string | undefined;
3
3
  nullTag?: string | undefined;
4
+ placeholder?: string;
5
+ noLabel?: boolean;
4
6
  };
5
7
  interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
6
8
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
@@ -19,6 +21,6 @@ declare const FlowModuleWorkerTagSelect: $$__sveltets_2_IsomorphicComponent<$$Co
19
21
  change: CustomEvent<any>;
20
22
  } & {
21
23
  [evt: string]: CustomEvent<any>;
22
- }, {}, {}, "tag" | "nullTag">;
24
+ }, {}, {}, "tag">;
23
25
  type FlowModuleWorkerTagSelect = InstanceType<typeof FlowModuleWorkerTagSelect>;
24
26
  export default FlowModuleWorkerTagSelect;
@@ -18,7 +18,7 @@ import MetadataGen from '../../copilot/MetadataGen.svelte';
18
18
  import Badge from '../../Badge.svelte';
19
19
  import { AlertTriangle } from 'lucide-svelte';
20
20
  import AIFormSettings from '../../copilot/AIFormSettings.svelte';
21
- let { noEditor } = $props();
21
+ let { noEditor, enableAi } = $props();
22
22
  const { flowStore, initialPathStore, previewArgs, pathStore, customUi } = getContext('FlowEditorContext');
23
23
  function asSchema(x) {
24
24
  return x;
@@ -106,7 +106,7 @@ let activeAdvancedOptionNames = $derived(activeAdvancedOptions.filter((option) =
106
106
  />
107
107
  </Label>
108
108
 
109
- {#if flowStore.val.schema}
109
+ {#if flowStore.val.schema && enableAi}
110
110
  <AIFormSettings
111
111
  bind:prompt={flowStore.val.schema.prompt_for_ai as string | undefined}
112
112
  type="flow"
@@ -1,5 +1,6 @@
1
1
  interface Props {
2
2
  noEditor: boolean;
3
+ enableAi?: boolean;
3
4
  }
4
5
  declare const FlowSettings: import("svelte").Component<Props, {}, "">;
5
6
  type FlowSettings = ReturnType<typeof FlowSettings>;
@@ -185,8 +185,7 @@ let lastModules = structuredClone($state.snapshot(modules));
185
185
  let moduleCounter = $state(0);
186
186
  function onModulesChange2(modules) {
187
187
  if (!deepEqual(modules, lastModules)) {
188
- console.log('modules changed', modules);
189
- lastModules = structuredClone($state.snapshot(modules));
188
+ lastModules = $state.snapshot(modules);
190
189
  moduleCounter++;
191
190
  }
192
191
  }
@@ -1,3 +1,4 @@
1
+ import type { EditableSchemaWrapperProps } from './editable_schema_wrapper';
1
2
  declare const EditableSchemaSdkWrapper: import("svelte").Component<EditableSchemaWrapperProps, {}, "">;
2
3
  type EditableSchemaSdkWrapper = ReturnType<typeof EditableSchemaSdkWrapper>;
3
4
  export default EditableSchemaSdkWrapper;
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">import { twMerge } from 'tailwind-merge';
2
2
  import EditableSchemaForm from '../EditableSchemaForm.svelte';
3
- import { createEventDispatcher } from 'svelte';
4
3
  import Toggle from '../Toggle.svelte';
5
4
  import { emptySchema, validateFileExtension } from '../../utils';
6
5
  import { Alert } from '../common';
@@ -8,11 +7,10 @@ import AddPropertyV2 from './AddPropertyV2.svelte';
8
7
  import { Plus } from 'lucide-svelte';
9
8
  import Select from '../select/Select.svelte';
10
9
  import { safeSelectItems } from '../select/utils.svelte';
11
- let { schema = $bindable(), uiOnly = false, noPreview = false, fullHeight = true, formatExtension = $bindable(undefined) } = $props();
10
+ let { schema = $bindable(), uiOnly = false, noPreview = false, fullHeight = true, formatExtension = $bindable(undefined), onSchemaChange } = $props();
12
11
  let resourceIsTextFile = $state(false);
13
12
  let addPropertyComponent = $state(undefined);
14
13
  let editableSchemaForm = $state(undefined);
15
- const dispatch = createEventDispatcher();
16
14
  $effect(() => {
17
15
  if (!resourceIsTextFile && formatExtension !== undefined) {
18
16
  formatExtension = undefined;
@@ -37,7 +35,7 @@ function switchResourceIsFile() {
37
35
  }
38
36
  };
39
37
  }
40
- dispatch('change', schema);
38
+ onSchemaChange?.({ schema: $state.snapshot(schema) });
41
39
  }
42
40
  let suggestedFileExtensions = $state([
43
41
  'json',
@@ -65,7 +63,7 @@ let suggestedFileExtensions = $state([
65
63
  <AddPropertyV2
66
64
  bind:schema
67
65
  bind:this={addPropertyComponent}
68
- on:change={() => dispatch('change', schema)}
66
+ on:change={() => onSchemaChange?.({ schema: $state.snapshot(schema) })}
69
67
  on:addNew={(e) => {
70
68
  editableSchemaForm?.openField(e.detail)
71
69
  }}
@@ -83,7 +81,7 @@ let suggestedFileExtensions = $state([
83
81
  onlyMaskPassword
84
82
  bind:this={editableSchemaForm}
85
83
  bind:schema
86
- on:change={() => dispatch('change', schema)}
84
+ on:change={() => onSchemaChange?.({ schema: $state.snapshot(schema) })}
87
85
  isFlowInput
88
86
  on:edit={(e) => {
89
87
  addPropertyComponent?.openDrawer(e.detail)
@@ -100,7 +98,7 @@ let suggestedFileExtensions = $state([
100
98
  <AddPropertyV2
101
99
  bind:schema
102
100
  bind:this={addPropertyComponent}
103
- on:change={() => dispatch('change', schema)}
101
+ on:change={() => onSchemaChange?.({ schema })}
104
102
  >
105
103
  {#snippet trigger()}
106
104
  <div
@@ -1,28 +1,4 @@
1
- import type { Schema } from '../../common';
2
- interface Props {
3
- schema: Schema | undefined | any;
4
- uiOnly?: boolean;
5
- noPreview?: boolean;
6
- fullHeight?: boolean;
7
- formatExtension?: string | undefined;
8
- }
9
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
10
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
11
- $$bindings?: Bindings;
12
- } & Exports;
13
- (internal: unknown, props: Props & {
14
- $$events?: Events;
15
- $$slots?: Slots;
16
- }): Exports & {
17
- $set?: any;
18
- $on?: any;
19
- };
20
- z_$$bindings?: Bindings;
21
- }
22
- declare const EditableSchemaWrapper: $$__sveltets_2_IsomorphicComponent<Props, {
23
- change: CustomEvent<any>;
24
- } & {
25
- [evt: string]: CustomEvent<any>;
26
- }, {}, {}, "schema" | "formatExtension">;
27
- type EditableSchemaWrapper = InstanceType<typeof EditableSchemaWrapper>;
1
+ import type { EditableSchemaWrapperProps } from './editable_schema_wrapper';
2
+ declare const EditableSchemaWrapper: import("svelte").Component<EditableSchemaWrapperProps, {}, "schema" | "formatExtension">;
3
+ type EditableSchemaWrapper = ReturnType<typeof EditableSchemaWrapper>;
28
4
  export default EditableSchemaWrapper;
@@ -0,0 +1,11 @@
1
+ import type { Schema } from '../../common';
2
+ export type EditableSchemaWrapperProps = {
3
+ schema: Schema | undefined | any;
4
+ uiOnly?: boolean;
5
+ noPreview?: boolean;
6
+ fullHeight?: boolean;
7
+ formatExtension?: string | undefined;
8
+ onSchemaChange?: ({ schema }: {
9
+ schema: Schema;
10
+ }) => void;
11
+ };
@@ -1 +1 @@
1
- "use strict";
1
+ export {};
@@ -1,7 +1,14 @@
1
+ import type { NewScript } from '../gen';
2
+ import type { ScriptBuilderWhitelabelCustomUi } from './custom_ui';
3
+ import type { DiffDrawerI } from './diff_drawer';
4
+ import type { ScriptBuilderFunctionExports } from './scriptBuilder';
5
+ import type { ScheduleTrigger } from './triggers';
6
+ import type { NewScriptWithDraftAndDraftTriggers, Trigger } from './triggers/utils';
1
7
  export interface ScriptBuilderProps {
2
8
  script: NewScript & {
3
9
  draft_triggers?: Trigger[];
4
10
  };
11
+ disableAi?: boolean;
5
12
  fullyLoaded?: boolean;
6
13
  initialPath?: string;
7
14
  template?: 'docker' | 'bunnative' | 'script';
@@ -9,7 +16,7 @@ export interface ScriptBuilderProps {
9
16
  lockedLanguage?: boolean;
10
17
  showMeta?: boolean;
11
18
  neverShowMeta?: boolean;
12
- diffDrawer?: DiffDrawer | undefined;
19
+ diffDrawer?: DiffDrawerI | undefined;
13
20
  savedScript?: NewScriptWithDraftAndDraftTriggers | undefined;
14
21
  searchParams?: URLSearchParams;
15
22
  disableHistoryChange?: boolean;
@@ -54,7 +54,7 @@ function clearValue() {
54
54
  </div>
55
55
  {:else if clearable && !disabled && value}
56
56
  <div class="absolute z-10 right-2 h-full flex items-center">
57
- <CloseButton noBg small on:close={clearValue} />
57
+ <CloseButton class="text-secondary" noBg small on:close={clearValue} />
58
58
  </div>
59
59
  {:else if RightIcon}
60
60
  <div class="absolute z-10 right-2 h-full flex items-center">
@@ -19,7 +19,7 @@ export type ProcessedItem<T> = {
19
19
  export declare function getLabel<T>(item: {
20
20
  label?: string;
21
21
  value: T;
22
- } | undefined): string;
22
+ } | undefined): string | undefined;
23
23
  export declare function safeSelectItems<T>(list: (T | {
24
24
  value: T;
25
25
  label?: string;
@@ -1,7 +1,7 @@
1
1
  export function processItems({ items, filterText, groupBy, sortBy, onCreateItem, createText }) {
2
2
  let items2 = items?.map((item) => ({
3
3
  ...item,
4
- label: getLabel(item)
4
+ label: getLabel(item) ?? ''
5
5
  })) ?? [];
6
6
  if (groupBy) {
7
7
  items2 =
@@ -31,6 +31,9 @@ export function getLabel(item) {
31
31
  return item.value;
32
32
  if (typeof item.value == 'number' || typeof item.value == 'boolean')
33
33
  return item.value.toString();
34
+ if (item.value == null) {
35
+ return undefined;
36
+ }
34
37
  return JSON.stringify(item.value);
35
38
  }
36
39
  export function safeSelectItems(list) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windmill-components",
3
- "version": "1.501.22",
3
+ "version": "1.501.24",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build",