windmill-components 1.503.3 → 1.504.0

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 (76) hide show
  1. package/package/components/AppWrapper.svelte +3 -0
  2. package/package/components/Dev.svelte +94 -4
  3. package/package/components/FlowBuilder.svelte +92 -8
  4. package/package/components/FlowPreviewContent.svelte +309 -278
  5. package/package/components/FlowPreviewContent.svelte.d.ts +33 -19
  6. package/package/components/FlowPreviewResult.svelte +74 -0
  7. package/package/components/FlowPreviewResult.svelte.d.ts +21 -0
  8. package/package/components/FlowStatusViewer.svelte +3 -1
  9. package/package/components/FlowStatusViewer.svelte.d.ts +2 -0
  10. package/package/components/FlowStatusViewerInner.svelte +15 -70
  11. package/package/components/FlowStatusWaitingForEvents.svelte +5 -2
  12. package/package/components/FlowStatusWaitingForEvents.svelte.d.ts +1 -0
  13. package/package/components/FlowWrapper.svelte +3 -0
  14. package/package/components/ModuleTest.svelte +26 -24
  15. package/package/components/S3FilePicker.svelte +22 -1
  16. package/package/components/ScriptWrapper.svelte +3 -0
  17. package/package/components/common/button/Button.svelte +2 -1
  18. package/package/components/common/button/Button.svelte.d.ts +2 -1
  19. package/package/components/common/button/UndoRedo.svelte +2 -2
  20. package/package/components/common/button/UndoRedo.svelte.d.ts +6 -5
  21. package/package/components/flows/FlowEditor.svelte +23 -2
  22. package/package/components/flows/FlowEditor.svelte.d.ts +23 -3
  23. package/package/components/flows/content/FlowEditorPanel.svelte +4 -3
  24. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +12 -2
  25. package/package/components/flows/content/FlowInput.svelte +2 -2
  26. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -1
  27. package/package/components/flows/content/FlowResult.svelte +35 -0
  28. package/package/components/flows/content/FlowResult.svelte.d.ts +17 -0
  29. package/package/components/flows/header/FlowPreviewButtons.svelte +81 -46
  30. package/package/components/flows/map/FlowGraphPreviewButton.svelte +94 -0
  31. package/package/components/flows/map/FlowGraphPreviewButton.svelte.d.ts +17 -0
  32. package/package/components/flows/map/FlowModuleSchemaItem.svelte +296 -285
  33. package/package/components/flows/map/FlowModuleSchemaItem.svelte.d.ts +6 -0
  34. package/package/components/flows/map/FlowModuleSchemaMap.svelte +21 -2
  35. package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +20 -1
  36. package/package/components/flows/map/MapItem.svelte +25 -3
  37. package/package/components/flows/map/MapItem.svelte.d.ts +6 -1
  38. package/package/components/flows/map/VirtualItem.svelte +55 -3
  39. package/package/components/flows/map/VirtualItem.svelte.d.ts +13 -1
  40. package/package/components/flows/map/VirtualItemWrapper.svelte +33 -29
  41. package/package/components/flows/map/VirtualItemWrapper.svelte.d.ts +1 -0
  42. package/package/components/flows/propPicker/OutputPicker.svelte +17 -2
  43. package/package/components/flows/propPicker/OutputPicker.svelte.d.ts +4 -0
  44. package/package/components/flows/propPicker/OutputPickerInner.svelte +2 -2
  45. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +1 -0
  46. package/package/components/flows/types.d.ts +3 -0
  47. package/package/components/flows/utils.d.ts +9 -0
  48. package/package/components/flows/utils.js +39 -0
  49. package/package/components/graph/FlowGraphV2.svelte +27 -4
  50. package/package/components/graph/FlowGraphV2.svelte.d.ts +18 -2
  51. package/package/components/graph/ViewportResizer.svelte +33 -1
  52. package/package/components/graph/ViewportResizer.svelte.d.ts +5 -1
  53. package/package/components/graph/graphBuilder.svelte.d.ts +26 -1
  54. package/package/components/graph/graphBuilder.svelte.js +13 -3
  55. package/package/components/graph/renderers/edges/BaseEdge.svelte +69 -2
  56. package/package/components/graph/renderers/edges/BaseEdge.svelte.d.ts +10 -0
  57. package/package/components/graph/renderers/nodes/InputNode.svelte +19 -1
  58. package/package/components/graph/renderers/nodes/ModuleNode.svelte +17 -2
  59. package/package/components/graph/renderers/nodes/ResultNode.svelte +9 -8
  60. package/package/components/instanceSettings.js +2 -3
  61. package/package/components/modulesTest.svelte.d.ts +12 -0
  62. package/package/components/modulesTest.svelte.js +8 -0
  63. package/package/components/preview/FlowPreviewStatus.svelte +9 -4
  64. package/package/components/preview/FlowPreviewStatus.svelte.d.ts +6 -18
  65. package/package/components/schema/EditableSchemaSdkWrapper.svelte +3 -0
  66. package/package/gen/core/OpenAPI.js +1 -1
  67. package/package/gen/schemas.gen.d.ts +3 -0
  68. package/package/gen/schemas.gen.js +3 -0
  69. package/package/gen/services.gen.d.ts +9 -1
  70. package/package/gen/services.gen.js +16 -0
  71. package/package/gen/types.gen.d.ts +18 -0
  72. package/package/{history.js → history.svelte.js} +2 -2
  73. package/package/utils.js +2 -0
  74. package/package.json +1 -1
  75. package/package/components/flows/header/FlowPreviewButtons.svelte.d.ts +0 -26
  76. /package/package/{history.d.ts → history.svelte.d.ts} +0 -0
@@ -1,6 +1,9 @@
1
1
  <script lang="ts">import AppEditor from './apps/editor/AppEditor.svelte';
2
2
  let { app: oldApp, ...props } = $props();
3
3
  let app = $state(oldApp);
4
+ $effect(() => {
5
+ app = oldApp;
6
+ });
4
7
  </script>
5
8
 
6
9
  <AppEditor {app} {...props} />
@@ -28,6 +28,8 @@ import Tooltip from './Tooltip.svelte';
28
28
  import { workspaceAIClients } from './copilot/lib';
29
29
  import { Triggers } from './triggers/triggers.svelte';
30
30
  import { TestSteps } from './flows/testSteps.svelte';
31
+ import { ModulesTestStates } from './modulesTest.svelte';
32
+ import { updateDerivedModuleStatesFromTestJobs } from './flows/utils';
31
33
  let flowCopilotContext = {
32
34
  shouldUpdatePropertyType: writable({}),
33
35
  exprsToSet: writable({}),
@@ -74,6 +76,11 @@ let testIsLoading = $state(false);
74
76
  let testJob = $state();
75
77
  let pastPreviews = $state([]);
76
78
  let validCode = $state(true);
79
+ // Flow preview
80
+ let flowPreviewButtons = $state();
81
+ const job = $derived(flowPreviewButtons?.getJob());
82
+ let showJobStatus = $state(false);
83
+ let testModuleId = $state(undefined);
77
84
  let currentScript = $state(undefined);
78
85
  let schema = $state(emptySchema());
79
86
  const href = window.location.href;
@@ -363,6 +370,13 @@ const history = initHistory(flowStore.val);
363
370
  const testSteps = new TestSteps();
364
371
  const selectedIdStore = writable('settings-metadata');
365
372
  const triggersCount = writable(undefined);
373
+ const modulesTestStates = new ModulesTestStates((moduleId) => {
374
+ // Update the derived store with test job states
375
+ delete $derivedModuleStates[moduleId];
376
+ testModuleId = moduleId;
377
+ showJobStatus = false;
378
+ });
379
+ const outputPickerOpenFns = $state({});
366
380
  setContext('TriggerContext', {
367
381
  triggersCount: triggersCount,
368
382
  simplifiedPoll: writable(false),
@@ -391,7 +405,9 @@ setContext('FlowEditorContext', {
391
405
  editPanelSize: undefined,
392
406
  payloadData: undefined
393
407
  }),
394
- currentEditor: writable(undefined)
408
+ currentEditor: writable(undefined),
409
+ modulesTestStates,
410
+ outputPickerOpenFns
395
411
  });
396
412
  setContext('PropPickerContext', {
397
413
  flowPropPickerConfig: writable(undefined),
@@ -407,7 +423,6 @@ function updateFlow(flow) {
407
423
  window?.parent.postMessage({ type: 'flow', flow, uriPath: lastUriPath }, '*');
408
424
  }
409
425
  }
410
- let flowPreviewButtons = $state();
411
426
  let reload = $state(0);
412
427
  async function inferModuleArgs(selectedIdStore) {
413
428
  if (selectedIdStore == '') {
@@ -471,6 +486,53 @@ $effect(() => {
471
486
  $effect(() => {
472
487
  $selectedIdStore && untrack(() => inferModuleArgs($selectedIdStore));
473
488
  });
489
+ const localModuleStates = $derived(flowPreviewButtons?.getLocalModuleStates() ?? writable({}));
490
+ const localDurationStatuses = $derived(flowPreviewButtons?.getLocalDurationStatuses() ?? writable({}));
491
+ const suspendStatus = $derived(flowPreviewButtons?.getSuspendStatus() ?? writable({}));
492
+ // Create a derived store that only shows the module states when showModuleStatus is true
493
+ // this store can also be updated
494
+ let derivedModuleStates = writable({});
495
+ $effect(() => {
496
+ derivedModuleStates.update((currentStates) => {
497
+ return showJobStatus ? $localModuleStates : currentStates;
498
+ });
499
+ });
500
+ $effect(() => {
501
+ updateDerivedModuleStatesFromTestJobs(testModuleId, modulesTestStates, derivedModuleStates);
502
+ });
503
+ let flowModuleSchemaMap = $state();
504
+ function onJobDone() {
505
+ if (!job) {
506
+ return;
507
+ }
508
+ // job was running and is now stopped
509
+ if (!flowPreviewButtons?.getPreviewOpen()) {
510
+ if (job.type === 'CompletedJob' &&
511
+ job.success &&
512
+ flowPreviewButtons?.getPreviewMode() === 'whole') {
513
+ if (flowModuleSchemaMap?.isNodeVisible('result') && $selectedIdStore !== 'Result') {
514
+ outputPickerOpenFns['Result']?.();
515
+ }
516
+ }
517
+ else {
518
+ // Find last module with a job in flow_status
519
+ const lastModuleWithJob = job.flow_status?.modules
520
+ ?.slice()
521
+ .reverse()
522
+ .find((module) => 'job' in module);
523
+ if (lastModuleWithJob &&
524
+ lastModuleWithJob.id &&
525
+ flowModuleSchemaMap?.isNodeVisible(lastModuleWithJob.id)) {
526
+ outputPickerOpenFns[lastModuleWithJob.id]?.();
527
+ }
528
+ }
529
+ }
530
+ }
531
+ function resetModulesStates() {
532
+ derivedModuleStates.set({});
533
+ showJobStatus = false;
534
+ }
535
+ const individualStepTests = $derived(!(showJobStatus && job) && Object.keys($derivedModuleStates).length > 0);
474
536
  </script>
475
537
 
476
538
  <svelte:window onkeydown={onKeyDown} />
@@ -608,18 +670,40 @@ $effect(() => {
608
670
  {/if}
609
671
  </div>
610
672
 
611
- <div class="flex justify-center pt-1 z-50 absolute right-2 top-2 gap-2">
612
- <FlowPreviewButtons bind:this={flowPreviewButtons} />
673
+ <div class="flex justify-center pt-1 z-50 absolute -translate-x-[100%] right-2 top-2 gap-2">
674
+ <FlowPreviewButtons
675
+ bind:this={flowPreviewButtons}
676
+ {onJobDone}
677
+ onRunPreview={() => {
678
+ localModuleStates.set({})
679
+ showJobStatus = true
680
+ }}
681
+ />
613
682
  </div>
614
683
  <Splitpanes horizontal class="h-full max-h-screen grow">
615
684
  <Pane size={67}>
616
685
  {#if flowStore.val?.value?.modules}
617
686
  <div id="flow-editor"></div>
618
687
  <FlowModuleSchemaMap
688
+ bind:this={flowModuleSchemaMap}
619
689
  disableAi
620
690
  disableTutorials
621
691
  smallErrorHandler={true}
622
692
  disableStaticInputs
693
+ localModuleStates={derivedModuleStates}
694
+ onTestUpTo={flowPreviewButtons?.testUpTo}
695
+ isOwner={flowPreviewButtons?.getIsOwner()}
696
+ onTestFlow={flowPreviewButtons?.runPreview}
697
+ isRunning={flowPreviewButtons?.getIsRunning()}
698
+ onCancelTestFlow={flowPreviewButtons?.cancelTest}
699
+ onOpenPreview={flowPreviewButtons?.openPreview}
700
+ onHideJobStatus={resetModulesStates}
701
+ {individualStepTests}
702
+ flowJob={job}
703
+ {showJobStatus}
704
+ onDelete={(id) => {
705
+ delete $derivedModuleStates[id]
706
+ }}
623
707
  />
624
708
  {:else}
625
709
  <div class="text-red-400 mt-20">Missing flow modules</div>
@@ -639,6 +723,12 @@ $effect(() => {
639
723
  flowPreviewButtons?.openPreview()
640
724
  }
641
725
  }}
726
+ onTestFlow={flowPreviewButtons?.runPreview}
727
+ {job}
728
+ isOwner={flowPreviewButtons?.getIsOwner()}
729
+ {localDurationStatuses}
730
+ {suspendStatus}
731
+ onOpenDetails={flowPreviewButtons?.openPreview}
642
732
  />
643
733
  {/key}
644
734
  </Pane>
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">import { FlowService, DraftService, CaptureService } from '../gen';
2
- import { initHistory, redo, undo } from '../history';
2
+ import { initHistory, redo, undo } from '../history.svelte';
3
3
  import { enterpriseLicense, tutorialsToDo, userStore, workspaceStore, usedTriggerKinds } from '../stores';
4
4
  import { cleanValueProperties, encodeState, generateRandomString, orderedJsonStringify, readFieldsRecursively, replaceFalseWithUndefined } from '../utils';
5
5
  import { sendUserToast } from '../toast';
@@ -15,7 +15,7 @@ import ScriptEditorDrawer from './flows/content/ScriptEditorDrawer.svelte';
15
15
  import { dfs as dfsApply } from './flows/dfs';
16
16
  import FlowImportExportMenu from './flows/header/FlowImportExportMenu.svelte';
17
17
  import FlowPreviewButtons from './flows/header/FlowPreviewButtons.svelte';
18
- import { cleanInputs } from './flows/utils';
18
+ import { cleanInputs, updateDerivedModuleStatesFromTestJobs } from './flows/utils';
19
19
  import { Calendar, Pen, Save, DiffIcon, HistoryIcon, FileJson, Settings } from 'lucide-svelte';
20
20
  import Awareness from './Awareness.svelte';
21
21
  import { getAllModules } from './flows/flowExplorer';
@@ -36,6 +36,7 @@ import { Triggers } from './triggers/triggers.svelte';
36
36
  import { TestSteps } from './flows/testSteps.svelte';
37
37
  import { aiChatManager } from './copilot/chat/AIChatManager.svelte';
38
38
  import { setStepHistoryLoaderContext, StepHistoryLoader } from './stepHistoryLoader.svelte';
39
+ import { ModulesTestStates } from './modulesTest.svelte';
39
40
  let { initialPath = $bindable(''), pathStoreInit = undefined, newFlow, selectedId, initialArgs = {}, loading = false, flowStore, flowStateStore, savedFlow = $bindable(undefined), diffDrawer = undefined, customUi = {}, disableAi = false, disabledFlowInputs = false, savedPrimarySchedule = undefined, version = undefined, setSavedraftCb = undefined, draftTriggersFromUrl = undefined, selectedTriggerIndexFromUrl = undefined, children, loadedFromHistoryFromUrl, noInitial = false, onSaveInitial, onSaveDraft, onDeploy, onDeployError, onDetails, onSaveDraftError, onSaveDraftOnlyAtNewPath, onHistoryRestore } = $props();
40
41
  let initialPathStore = writable(initialPath);
41
42
  // used for new flows for captures
@@ -56,6 +57,11 @@ let confirmDeploymentCallback = () => { };
56
57
  // AI changes warning modal
57
58
  let aiChangesWarningOpen = $state(false);
58
59
  let aiChangesConfirmCallback = $state(() => { });
60
+ // Flow preview
61
+ let flowPreviewButtons = $state();
62
+ const flowPreviewContent = $derived(flowPreviewButtons?.getFlowPreviewContent());
63
+ const job = $derived(flowPreviewContent?.getJob());
64
+ let showJobStatus = $state(false);
59
65
  async function handleDraftTriggersConfirmed(event) {
60
66
  const { selectedTriggers } = event.detail;
61
67
  // Continue with saving the flow
@@ -438,6 +444,15 @@ function select(selectedId) {
438
444
  selectedIdStore.set(selectedId);
439
445
  }
440
446
  let insertButtonOpen = writable(false);
447
+ let testModuleId = $state(undefined);
448
+ let modulesTestStates = new ModulesTestStates((moduleId) => {
449
+ // Update the derived store with test job states
450
+ delete $derivedModuleStates[moduleId];
451
+ testModuleId = moduleId;
452
+ showJobStatus = false;
453
+ });
454
+ let outputPickerOpenFns = $state({});
455
+ let flowEditor = $state(undefined);
441
456
  setContext('FlowEditorContext', {
442
457
  selectedId: selectedIdStore,
443
458
  currentEditor: writable(undefined),
@@ -456,7 +471,9 @@ setContext('FlowEditorContext', {
456
471
  customUi,
457
472
  insertButtonOpen,
458
473
  executionCount: writable(0),
459
- flowInputEditorState: flowInputEditorStateStore
474
+ flowInputEditorState: flowInputEditorStateStore,
475
+ modulesTestStates,
476
+ outputPickerOpenFns
460
477
  });
461
478
  // Add triggers context store
462
479
  const triggersState = $state(new Triggers([
@@ -630,7 +647,6 @@ function handleDeployTrigger(trigger) {
630
647
  newSavedDraftTrigers.length > 0 ? newSavedDraftTrigers : undefined;
631
648
  }
632
649
  }
633
- let flowPreviewButtons = $state();
634
650
  let forceTestTab = $state({});
635
651
  let highlightArg = $state({});
636
652
  $effect.pre(() => {
@@ -670,6 +686,53 @@ export function setLoadedFromHistory(loadedFromHistoryUrl) {
670
686
  stepHistoryLoader.setFlowJobInitial(loadedFromHistoryUrl.flowJobInitial);
671
687
  stepHistoryLoader.stepStates = loadedFromHistoryUrl.stepsState;
672
688
  }
689
+ function onJobDone() {
690
+ if (!job) {
691
+ return;
692
+ }
693
+ // job was running and is now stopped
694
+ if (!flowPreviewButtons?.getPreviewOpen()) {
695
+ if (job.type === 'CompletedJob' &&
696
+ job.success &&
697
+ flowPreviewButtons?.getPreviewMode() === 'whole') {
698
+ if (flowEditor?.isNodeVisible('result') && $selectedIdStore !== 'Result') {
699
+ outputPickerOpenFns['Result']?.();
700
+ }
701
+ }
702
+ else {
703
+ // Find last module with a job in flow_status
704
+ const lastModuleWithJob = job.flow_status?.modules
705
+ ?.slice()
706
+ .reverse()
707
+ .find((module) => 'job' in module);
708
+ if (lastModuleWithJob &&
709
+ lastModuleWithJob.id &&
710
+ flowEditor?.isNodeVisible(lastModuleWithJob.id)) {
711
+ outputPickerOpenFns[lastModuleWithJob.id]?.();
712
+ }
713
+ }
714
+ }
715
+ }
716
+ const localModuleStates = $derived(flowPreviewContent?.getLocalModuleStates() ?? writable({}));
717
+ const localDurationStatuses = $derived(flowPreviewContent?.getLocalDurationStatuses() ?? writable({}));
718
+ const suspendStatus = $derived(flowPreviewContent?.getSuspendStatus() ?? writable({}));
719
+ // Create a derived store that only shows the module states when showModuleStatus is true
720
+ // this store can also be updated
721
+ let derivedModuleStates = writable({});
722
+ $effect(() => {
723
+ derivedModuleStates.update((currentStates) => {
724
+ return showJobStatus ? $localModuleStates : currentStates;
725
+ });
726
+ });
727
+ $effect(() => {
728
+ updateDerivedModuleStatesFromTestJobs(testModuleId, modulesTestStates, derivedModuleStates);
729
+ });
730
+ function resetModulesStates() {
731
+ derivedModuleStates.set({});
732
+ showJobStatus = false;
733
+ }
734
+ const individualStepTests = $derived(!(showJobStatus && job) && Object.keys($derivedModuleStates).length > 0);
735
+ const flowHasChanged = $derived(flowPreviewContent?.flowHasChanged());
673
736
  </script>
674
737
 
675
738
  <svelte:window onkeydown={onKeyDown} />
@@ -723,7 +786,9 @@ export function setLoadedFromHistory(loadedFromHistoryUrl) {
723
786
  on:undo={() => {
724
787
  const currentModules = flowStore.val?.value?.modules
725
788
 
789
+ console.log('debug before', $state.snapshot(flowStore.val))
726
790
  flowStore.val = undo(history, flowStore.val)
791
+ console.log('debug after', $state.snapshot(flowStore.val))
727
792
 
728
793
  const newModules = flowStore.val?.value?.modules
729
794
  const restoredModules = newModules?.filter(
@@ -862,8 +927,13 @@ export function setLoadedFromHistory(loadedFromHistoryUrl) {
862
927
  captureOn.set(true)
863
928
  showCaptureHint.set(true)
864
929
  }}
930
+ {onJobDone}
865
931
  bind:this={flowPreviewButtons}
866
932
  {loading}
933
+ onRunPreview={() => {
934
+ localModuleStates.set({})
935
+ showJobStatus = true
936
+ }}
867
937
  />
868
938
  <Button
869
939
  loading={loadingDraft}
@@ -890,6 +960,7 @@ export function setLoadedFromHistory(loadedFromHistoryUrl) {
890
960
  <!-- metadata -->
891
961
  {#if $flowStateStore}
892
962
  <FlowEditor
963
+ bind:this={flowEditor}
893
964
  {disabledFlowInputs}
894
965
  disableAi={disableAi || customUi?.stepInputs?.ai == false}
895
966
  disableSettings={customUi?.settingsPanel === false}
@@ -908,8 +979,8 @@ export function setLoadedFromHistory(loadedFromHistoryUrl) {
908
979
  previewArgsStore.val = JSON.parse(JSON.stringify(e.detail))
909
980
  flowPreviewButtons?.openPreview(true)
910
981
  }}
911
- onTestUpTo={() => {
912
- flowPreviewButtons?.testUpTo()
982
+ onTestUpTo={(id) => {
983
+ flowPreviewButtons?.testUpTo(id)
913
984
  }}
914
985
  {savedFlow}
915
986
  onDeployTrigger={handleDeployTrigger}
@@ -929,9 +1000,22 @@ export function setLoadedFromHistory(loadedFromHistoryUrl) {
929
1000
  aiChatOpen={aiChatManager.open}
930
1001
  showFlowAiButton={!disableAi && customUi?.topBar?.aiBuilder != false}
931
1002
  toggleAiChat={() => aiChatManager.toggleOpen()}
932
- onRunPreview={() => {
933
- flowPreviewButtons?.openPreview(true)
1003
+ onOpenPreview={flowPreviewButtons?.openPreview}
1004
+ localModuleStates={derivedModuleStates}
1005
+ isOwner={flowPreviewContent?.getIsOwner()}
1006
+ onTestFlow={flowPreviewButtons?.runPreview}
1007
+ isRunning={flowPreviewContent?.getIsRunning()}
1008
+ onCancelTestFlow={flowPreviewContent?.cancelTest}
1009
+ onHideJobStatus={resetModulesStates}
1010
+ {individualStepTests}
1011
+ {job}
1012
+ {localDurationStatuses}
1013
+ {suspendStatus}
1014
+ {showJobStatus}
1015
+ onDelete={(id) => {
1016
+ delete $derivedModuleStates[id]
934
1017
  }}
1018
+ {flowHasChanged}
935
1019
  />
936
1020
  {:else}
937
1021
  <CenteredPage>Loading...</CenteredPage>