windmill-components 1.503.3 → 1.503.4

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 (64) hide show
  1. package/package/components/AppWrapper.svelte +3 -0
  2. package/package/components/Dev.svelte +94 -4
  3. package/package/components/FlowBuilder.svelte +89 -7
  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/ScriptWrapper.svelte +3 -0
  16. package/package/components/common/button/Button.svelte +2 -1
  17. package/package/components/common/button/Button.svelte.d.ts +2 -1
  18. package/package/components/flows/FlowEditor.svelte +23 -2
  19. package/package/components/flows/FlowEditor.svelte.d.ts +23 -3
  20. package/package/components/flows/content/FlowEditorPanel.svelte +4 -3
  21. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +12 -2
  22. package/package/components/flows/content/FlowInput.svelte +2 -2
  23. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -1
  24. package/package/components/flows/content/FlowResult.svelte +35 -0
  25. package/package/components/flows/content/FlowResult.svelte.d.ts +17 -0
  26. package/package/components/flows/header/FlowPreviewButtons.svelte +81 -46
  27. package/package/components/flows/map/FlowGraphPreviewButton.svelte +94 -0
  28. package/package/components/flows/map/FlowGraphPreviewButton.svelte.d.ts +17 -0
  29. package/package/components/flows/map/FlowModuleSchemaItem.svelte +296 -285
  30. package/package/components/flows/map/FlowModuleSchemaItem.svelte.d.ts +6 -0
  31. package/package/components/flows/map/FlowModuleSchemaMap.svelte +20 -1
  32. package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +20 -1
  33. package/package/components/flows/map/MapItem.svelte +25 -3
  34. package/package/components/flows/map/MapItem.svelte.d.ts +6 -1
  35. package/package/components/flows/map/VirtualItem.svelte +55 -3
  36. package/package/components/flows/map/VirtualItem.svelte.d.ts +13 -1
  37. package/package/components/flows/map/VirtualItemWrapper.svelte +33 -29
  38. package/package/components/flows/map/VirtualItemWrapper.svelte.d.ts +1 -0
  39. package/package/components/flows/propPicker/OutputPicker.svelte +17 -2
  40. package/package/components/flows/propPicker/OutputPicker.svelte.d.ts +4 -0
  41. package/package/components/flows/propPicker/OutputPickerInner.svelte +2 -2
  42. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +1 -0
  43. package/package/components/flows/types.d.ts +3 -0
  44. package/package/components/flows/utils.d.ts +9 -0
  45. package/package/components/flows/utils.js +39 -0
  46. package/package/components/graph/FlowGraphV2.svelte +27 -4
  47. package/package/components/graph/FlowGraphV2.svelte.d.ts +18 -2
  48. package/package/components/graph/ViewportResizer.svelte +33 -1
  49. package/package/components/graph/ViewportResizer.svelte.d.ts +5 -1
  50. package/package/components/graph/graphBuilder.svelte.d.ts +26 -1
  51. package/package/components/graph/graphBuilder.svelte.js +13 -3
  52. package/package/components/graph/renderers/edges/BaseEdge.svelte +69 -2
  53. package/package/components/graph/renderers/edges/BaseEdge.svelte.d.ts +10 -0
  54. package/package/components/graph/renderers/nodes/InputNode.svelte +19 -1
  55. package/package/components/graph/renderers/nodes/ModuleNode.svelte +17 -2
  56. package/package/components/graph/renderers/nodes/ResultNode.svelte +9 -8
  57. package/package/components/modulesTest.svelte.d.ts +12 -0
  58. package/package/components/modulesTest.svelte.js +8 -0
  59. package/package/components/preview/FlowPreviewStatus.svelte +9 -4
  60. package/package/components/preview/FlowPreviewStatus.svelte.d.ts +6 -18
  61. package/package/components/schema/EditableSchemaSdkWrapper.svelte +3 -0
  62. package/package/utils.js +2 -0
  63. package/package.json +1 -1
  64. package/package/components/flows/header/FlowPreviewButtons.svelte.d.ts +0 -26
@@ -1,4 +1,5 @@
1
- <script lang="ts">import { JobService } from '../gen';
1
+ <script lang="ts">import { run, stopPropagation } from 'svelte/legacy';
2
+ import { JobService } from '../gen';
2
3
  import { workspaceStore } from '../stores';
3
4
  import { Badge, Button } from './common';
4
5
  import Popover from './meltComponents/Popover.svelte';
@@ -20,36 +21,26 @@ import { writable } from 'svelte/store';
20
21
  import { getStepHistoryLoaderContext } from './stepHistoryLoader.svelte';
21
22
  import { aiChatManager } from './copilot/chat/AIChatManager.svelte';
22
23
  import { stateSnapshot } from '../svelte5Utils.svelte';
23
- export let previewMode;
24
- export let open;
25
- export let preventEscape = false;
26
- export let jobId = undefined;
27
- export let job = undefined;
28
- export let selectedJobStep = undefined;
29
- export let selectedJobStepIsTopLevel = undefined;
30
- export let selectedJobStepType = 'single';
31
- export let rightColumnSelect = 'timeline';
32
- export let branchOrIterationN = 0;
33
- export let scrollTop = 0;
34
- export let localModuleStates = writable({});
35
- export let localDurationStatuses = writable({});
24
+ let { previewMode = $bindable(), open, preventEscape = $bindable(false), jobId = $bindable(undefined), job = $bindable(undefined), initial = $bindable(false), selectedJobStep = $bindable(undefined), selectedJobStepIsTopLevel = $bindable(undefined), selectedJobStepType = $bindable('single'), rightColumnSelect = $bindable('timeline'), branchOrIterationN = $bindable(0), scrollTop = $bindable(0), localModuleStates = $bindable(writable({})), localDurationStatuses = $bindable(writable({})), onRunPreview, render = false, onJobDone, upToId = undefined } = $props();
36
25
  let restartBranchNames = [];
37
- let isRunning = false;
38
- let jobProgressReset;
39
- let jsonView = false;
40
- let jsonEditor;
41
- let schemaHeight = 0;
42
- let isValid = true;
26
+ let isRunning = $state(false);
27
+ let jsonView = $state(false);
28
+ let jsonEditor = $state(undefined);
29
+ let schemaHeight = $state(0);
30
+ let isValid = $state(true);
31
+ let suspendStatus = $state(writable({}));
32
+ let isOwner = $state(false);
43
33
  export function test() {
44
34
  renderCount++;
45
35
  runPreview(previewArgs.val, undefined);
46
36
  }
47
- const { selectedId, previewArgs, flowStateStore, flowStore, pathStore, initialPathStore, fakeInitialPath, customUi, executionCount } = getContext('FlowEditorContext');
37
+ const { selectedId, previewArgs, flowStateStore, flowStore, pathStore, initialPathStore, fakeInitialPath, customUi, executionCount } = $state(getContext('FlowEditorContext'));
48
38
  const dispatch = createEventDispatcher();
39
+ let renderCount = $state(0);
40
+ let schemaFormWithArgPicker = $state(undefined);
41
+ let currentJobId = $state(undefined);
49
42
  let stepHistoryLoader = getStepHistoryLoaderContext();
50
- let renderCount = 0;
51
- let schemaFormWithArgPicker = undefined;
52
- let currentJobId = undefined;
43
+ let flowProgressBar = $state(undefined);
53
44
  function extractFlow(previewMode) {
54
45
  const previewFlow = aiChatManager.flowAiChatHelpers?.getPreviewFlow();
55
46
  if (previewMode === 'whole') {
@@ -58,21 +49,21 @@ function extractFlow(previewMode) {
58
49
  else {
59
50
  const flow = previewFlow ?? stateSnapshot(flowStore).val;
60
51
  const idOrders = dfs(flow.value.modules, (x) => x.id);
61
- let upToIndex = idOrders.indexOf($selectedId);
52
+ let upToIndex = idOrders.indexOf(upToId ?? $selectedId);
62
53
  if (upToIndex != -1) {
63
54
  flow.value.modules = sliceModules(flow.value.modules, upToIndex, idOrders);
64
55
  }
65
56
  return flow;
66
57
  }
67
58
  }
68
- let lastPreviewFlow = undefined;
59
+ let lastPreviewFlow = $state(undefined);
69
60
  export async function runPreview(args, restartedFrom) {
70
61
  if (stepHistoryLoader?.flowJobInitial) {
71
62
  stepHistoryLoader?.setFlowJobInitial(false);
72
63
  }
73
64
  try {
74
65
  lastPreviewFlow = JSON.stringify(flowStore.val);
75
- jobProgressReset();
66
+ flowProgressBar?.reset();
76
67
  const newFlow = extractFlow(previewMode);
77
68
  jobId = await runFlowPreview(args, newFlow, $pathStore, restartedFrom);
78
69
  isRunning = true;
@@ -80,6 +71,7 @@ export async function runPreview(args, restartedFrom) {
80
71
  savedArgs = previewArgs.val;
81
72
  inputSelected = undefined;
82
73
  }
74
+ onRunPreview?.();
83
75
  }
84
76
  catch (e) {
85
77
  sendUserToast('Could not run preview', true, undefined, e.toString());
@@ -129,8 +121,8 @@ function onSelectedJobStepChange() {
129
121
  }
130
122
  }
131
123
  }
132
- let savedArgs = previewArgs.val;
133
- let inputSelected = undefined;
124
+ let savedArgs = $state(previewArgs.val);
125
+ let inputSelected = $state(undefined);
134
126
  async function selectInput(input, type) {
135
127
  if (!input) {
136
128
  previewArgs.val = savedArgs;
@@ -149,293 +141,327 @@ async function selectInput(input, type) {
149
141
  export function refresh() {
150
142
  renderCount++;
151
143
  }
152
- $: if (job?.type === 'CompletedJob') {
153
- isRunning = false;
154
- }
155
- $: selectedJobStep !== undefined && onSelectedJobStepChange();
156
144
  let scrollableDiv = undefined;
157
145
  function handleScroll() {
158
146
  scrollTop = scrollableDiv?.scrollTop ?? 0;
159
147
  }
160
- $: scrollableDiv && onScrollableDivChange();
161
148
  function onScrollableDivChange() {
162
149
  if (scrollTop != 0 && scrollableDiv) {
163
150
  scrollableDiv.scrollTop = scrollTop;
164
151
  }
165
152
  }
153
+ run(() => {
154
+ selectedJobStep !== undefined && onSelectedJobStepChange();
155
+ });
156
+ run(() => {
157
+ scrollableDiv && onScrollableDivChange();
158
+ });
159
+ export async function cancelTest() {
160
+ isRunning = false;
161
+ try {
162
+ jobId &&
163
+ (await JobService.cancelQueuedJob({
164
+ workspace: $workspaceStore ?? '',
165
+ id: jobId,
166
+ requestBody: {}
167
+ }));
168
+ }
169
+ catch { }
170
+ }
171
+ export function getLocalModuleStates() {
172
+ return localModuleStates;
173
+ }
174
+ export function getLocalDurationStatuses() {
175
+ return localDurationStatuses;
176
+ }
177
+ export function getSuspendStatus() {
178
+ return suspendStatus;
179
+ }
180
+ export function getIsRunning() {
181
+ return isRunning;
182
+ }
183
+ export function getIsOwner() {
184
+ return isOwner;
185
+ }
186
+ export function getJob() {
187
+ return job;
188
+ }
189
+ export function flowHasChanged() {
190
+ return !!lastPreviewFlow && JSON.stringify(flowStore.val) != lastPreviewFlow;
191
+ }
166
192
  </script>
167
193
 
168
- <svelte:window on:keydown={onKeyDown} />
194
+ <svelte:window onkeydown={onKeyDown} />
169
195
 
170
196
  <div class="flex flex-col space-y-2 h-screen bg-surface px-4 py-2 w-full" id="flow-preview-content">
171
- <div class="flex flex-row w-full items-center gap-x-2">
172
- <div class="w-8">
173
- <Button
174
- on:click={() => dispatch('close')}
175
- startIcon={{ icon: X }}
176
- iconOnly
177
- size="sm"
178
- color="light"
179
- btnClasses="hover:bg-surface-hover bg-surface-secondaryw-8 h-8 rounded-full p-0"
180
- />
181
- </div>
182
-
183
- {#if isRunning}
184
- <div class="mx-auto">
197
+ {#if render}
198
+ <div class="flex flex-row w-full items-center gap-x-2">
199
+ <div class="w-8">
185
200
  <Button
186
- color="red"
187
- on:click={async () => {
188
- isRunning = false
189
- try {
190
- jobId &&
191
- (await JobService.cancelQueuedJob({
192
- workspace: $workspaceStore ?? '',
193
- id: jobId,
194
- requestBody: {}
195
- }))
196
- } catch {}
197
- }}
201
+ on:click={() => dispatch('close')}
202
+ startIcon={{ icon: X }}
203
+ iconOnly
198
204
  size="sm"
199
- btnClasses="w-full max-w-lg"
200
- loading={true}
201
- clickableWhileLoading
202
- >
203
- Cancel
204
- </Button>
205
+ color="light"
206
+ btnClasses="hover:bg-surface-hover bg-surface-secondaryw-8 h-8 rounded-full p-0"
207
+ />
205
208
  </div>
206
- {:else}
207
- <div class="grow justify-center flex flex-row gap-4">
208
- {#if jobId !== undefined && selectedJobStep !== undefined && selectedJobStepIsTopLevel && aiChatManager.flowAiChatHelpers?.getModuleAction(selectedJobStep) !== 'removed'}
209
- {#if selectedJobStepType == 'single'}
210
- <Button
211
- size="xs"
212
- color="light"
213
- variant="border"
214
- title={`Re-start this flow from step ${selectedJobStep} (included).`}
215
- on:click={() => {
216
- runPreview(previewArgs.val, {
217
- flow_job_id: jobId,
218
- step_id: selectedJobStep,
219
- branch_or_iteration_n: 0
220
- })
221
- }}
222
- startIcon={{ icon: Play }}
223
- >
224
- Re-start from
225
- <Badge baseClass="ml-1" color="indigo">
226
- {selectedJobStep}
227
- </Badge>
228
- </Button>
229
- {:else}
230
- <Popover
231
- floatingConfig={{ strategy: 'absolute', placement: 'bottom-start' }}
232
- contentClasses="p-4"
233
- >
234
- <svelte:fragment slot="button">
235
- <Button
236
- title={`Re-start this flow from step ${selectedJobStep} (included).`}
237
- variant="border"
238
- color="blue"
239
- startIcon={{ icon: RefreshCw }}
240
- on:click={() => {
241
- runPreview(previewArgs.val, {
242
- flow_job_id: jobId,
243
- step_id: selectedJobStep,
244
- branch_or_iteration_n: 0
245
- })
246
- }}
247
- nonCaptureEvent={true}
248
- >
249
- Re-start from
250
- <Badge baseClass="ml-1" color="indigo">
251
- {selectedJobStep}
252
- </Badge>
253
- </Button>
254
- </svelte:fragment>
255
- <svelte:fragment slot="content">
256
- <label class="block text-primary p-4">
257
- <div class="pb-1 text-sm text-secondary"
258
- >{selectedJobStepType == 'forloop' ? 'From iteration #:' : 'From branch:'}</div
209
+
210
+ {#if isRunning}
211
+ <div class="mx-auto">
212
+ <Button
213
+ color="red"
214
+ on:click={async () => {
215
+ cancelTest()
216
+ }}
217
+ size="sm"
218
+ btnClasses="w-full max-w-lg"
219
+ loading={true}
220
+ clickableWhileLoading
221
+ >
222
+ Cancel
223
+ </Button>
224
+ </div>
225
+ {:else}
226
+ <div class="grow justify-center flex flex-row gap-4">
227
+ {#if jobId !== undefined && selectedJobStep !== undefined && selectedJobStepIsTopLevel && aiChatManager.flowAiChatHelpers?.getModuleAction(selectedJobStep) !== 'removed'}
228
+ {#if selectedJobStepType == 'single'}
229
+ <Button
230
+ size="xs"
231
+ color="light"
232
+ variant="border"
233
+ title={`Re-start this flow from step ${selectedJobStep} (included).`}
234
+ on:click={() => {
235
+ runPreview(previewArgs.val, {
236
+ flow_job_id: jobId,
237
+ step_id: selectedJobStep,
238
+ branch_or_iteration_n: 0
239
+ })
240
+ }}
241
+ startIcon={{ icon: Play }}
242
+ >
243
+ Re-start from
244
+ <Badge baseClass="ml-1" color="indigo">
245
+ {selectedJobStep}
246
+ </Badge>
247
+ </Button>
248
+ {:else}
249
+ <Popover
250
+ floatingConfig={{ strategy: 'absolute', placement: 'bottom-start' }}
251
+ contentClasses="p-4"
252
+ >
253
+ {#snippet button()}
254
+ <Button
255
+ title={`Re-start this flow from step ${selectedJobStep} (included).`}
256
+ variant="border"
257
+ color="blue"
258
+ startIcon={{ icon: RefreshCw }}
259
+ on:click={() => {
260
+ runPreview(previewArgs.val, {
261
+ flow_job_id: jobId,
262
+ step_id: selectedJobStep,
263
+ branch_or_iteration_n: 0
264
+ })
265
+ }}
266
+ nonCaptureEvent={true}
259
267
  >
260
- <div class="flex w-full">
261
- {#if selectedJobStepType === 'forloop'}
262
- <input
263
- type="number"
264
- min="0"
265
- bind:value={branchOrIterationN}
266
- class="!w-32 grow"
267
- on:click|stopPropagation={() => {}}
268
- />
269
- {:else}
270
- <select
271
- bind:value={branchOrIterationN}
272
- class="!w-32 grow"
273
- on:click|stopPropagation={() => {}}
274
- >
275
- {#each restartBranchNames as [branchIdx, branchName]}
276
- <option value={branchIdx}>{branchName}</option>
277
- {/each}
278
- </select>
279
- {/if}
280
- <Button
281
- size="xs"
282
- color="blue"
283
- buttonType="button"
284
- btnClasses="!p-1 !w-[34px] !ml-1"
285
- aria-label="Restart flow"
286
- on:click|once={() => {
287
- runPreview(previewArgs.val, {
288
- flow_job_id: jobId,
289
- step_id: selectedJobStep,
290
- branch_or_iteration_n: branchOrIterationN
291
- })
292
- }}
268
+ Re-start from
269
+ <Badge baseClass="ml-1" color="indigo">
270
+ {selectedJobStep}
271
+ </Badge>
272
+ </Button>
273
+ {/snippet}
274
+ {#snippet content()}
275
+ <label class="block text-primary p-4">
276
+ <div class="pb-1 text-sm text-secondary"
277
+ >{selectedJobStepType == 'forloop'
278
+ ? 'From iteration #:'
279
+ : 'From branch:'}</div
293
280
  >
294
- <ArrowRight size={18} />
295
- </Button>
296
- </div>
297
- </label>
298
- </svelte:fragment>
299
- </Popover>
300
- {/if}
301
- {/if}
302
- <Button
303
- variant="contained"
304
- startIcon={{ icon: isRunning ? RefreshCw : Play }}
305
- color="dark"
306
- size="sm"
307
- btnClasses="w-full max-w-lg"
308
- on:click={() => runPreview(previewArgs.val, undefined)}
309
- id="flow-editor-test-flow-drawer"
310
- shortCut={{ Icon: CornerDownLeft }}
311
- >
312
- {#if previewMode == 'upTo'}
313
- Test up to
314
- <Badge baseClass="ml-1" color="indigo">
315
- {$selectedId}
316
- </Badge>
317
- {:else}
318
- Test flow
281
+ <div class="flex w-full">
282
+ {#if selectedJobStepType === 'forloop'}
283
+ <input
284
+ type="number"
285
+ min="0"
286
+ bind:value={branchOrIterationN}
287
+ class="!w-32 grow"
288
+ onclick={stopPropagation(() => {})}
289
+ />
290
+ {:else}
291
+ <select
292
+ bind:value={branchOrIterationN}
293
+ class="!w-32 grow"
294
+ onclick={stopPropagation(() => {})}
295
+ >
296
+ {#each restartBranchNames as [branchIdx, branchName]}
297
+ <option value={branchIdx}>{branchName}</option>
298
+ {/each}
299
+ </select>
300
+ {/if}
301
+ <Button
302
+ size="xs"
303
+ color="blue"
304
+ buttonType="button"
305
+ btnClasses="!p-1 !w-[34px] !ml-1"
306
+ aria-label="Restart flow"
307
+ on:click|once={() => {
308
+ runPreview(previewArgs.val, {
309
+ flow_job_id: jobId,
310
+ step_id: selectedJobStep,
311
+ branch_or_iteration_n: branchOrIterationN
312
+ })
313
+ }}
314
+ >
315
+ <ArrowRight size={18} />
316
+ </Button>
317
+ </div>
318
+ </label>
319
+ {/snippet}
320
+ </Popover>
321
+ {/if}
319
322
  {/if}
320
- </Button>
321
- </div>
322
- {/if}
323
- </div>
324
- <div class="w-full flex flex-col gap-y-1">
325
- {#if lastPreviewFlow && JSON.stringify(flowStore.val) != lastPreviewFlow}
326
- <div class="pt-1">
327
- <div
328
- class="bg-orange-200 text-orange-600 border border-orange-600 p-2 flex items-center gap-2 rounded"
329
- >
330
- <AlertTriangle size={14} /> Flow changed since last preview
331
- <div class="flex"></div>
323
+ <Button
324
+ variant="contained"
325
+ startIcon={{ icon: isRunning ? RefreshCw : Play }}
326
+ color="dark"
327
+ size="sm"
328
+ btnClasses="w-full max-w-lg"
329
+ on:click={() => runPreview(previewArgs.val, undefined)}
330
+ id="flow-editor-test-flow-drawer"
331
+ shortCut={{ Icon: CornerDownLeft }}
332
+ >
333
+ {#if previewMode == 'upTo'}
334
+ Test up to
335
+ <Badge baseClass="ml-1" color="indigo">
336
+ {$selectedId}
337
+ </Badge>
338
+ {:else}
339
+ Test flow
340
+ {/if}
341
+ </Button>
332
342
  </div>
333
- </div>
334
- {/if}
335
- <FlowProgressBar {job} bind:reset={jobProgressReset} />
336
- </div>
343
+ {/if}
344
+ </div>
337
345
 
346
+ <div class="w-full flex flex-col gap-y-1">
347
+ {#if flowHasChanged()}
348
+ <div class="pt-1">
349
+ <div
350
+ class="bg-orange-200 text-orange-600 border border-orange-600 p-2 flex items-center gap-2 rounded"
351
+ >
352
+ <AlertTriangle size={14} /> Flow changed since last preview
353
+ <div class="flex"></div>
354
+ </div>
355
+ </div>
356
+ {/if}
357
+ <FlowProgressBar {job} bind:this={flowProgressBar} />
358
+ </div>
359
+ {/if}
338
360
  <div
339
361
  bind:this={scrollableDiv}
340
362
  class="overflow-y-auto grow flex flex-col pt-4"
341
- on:scroll={(e) => handleScroll()}
363
+ onscroll={(e) => handleScroll()}
342
364
  >
343
- <div class="border-b">
344
- <SchemaFormWithArgPicker
345
- bind:this={schemaFormWithArgPicker}
346
- runnableId={$initialPathStore}
347
- stablePathForCaptures={$initialPathStore || fakeInitialPath}
348
- runnableType={'FlowPath'}
349
- previewArgs={previewArgs.val}
350
- on:openTriggers
351
- on:select={(e) => {
352
- selectInput(e.detail.payload, e.detail?.type)
353
- }}
354
- {isValid}
355
- {jsonView}
356
- >
357
- <div class="w-full flex flex-row justify-between">
358
- <InputSelectedBadge
359
- onReject={() => schemaFormWithArgPicker?.resetSelected()}
360
- {inputSelected}
361
- />
362
- <div class="flex flex-row gap-2">
363
- <Toggle
364
- bind:checked={jsonView}
365
- label="JSON View"
366
- size="xs"
367
- options={{
368
- right: 'JSON',
369
- rightTooltip: 'Fill args from JSON'
370
- }}
371
- lightMode
372
- on:change={(e) => {
373
- jsonEditor?.setCode(JSON.stringify(previewArgs.val ?? {}, null, '\t'))
374
- refresh()
375
- }}
376
- />
377
- </div>
378
- </div>
379
- {#if jsonView}
380
- <div class="py-2" style="height: {Math.max(schemaHeight, 100)}px" data-schema-picker>
381
- <JsonInputs
382
- bind:this={jsonEditor}
383
- on:select={(e) => {
384
- if (e.detail) {
385
- previewArgs.val = e.detail
386
- }
387
- }}
388
- updateOnBlur={false}
389
- placeholder={`Write args as JSON.<br/><br/>Example:<br/><br/>{<br/>&nbsp;&nbsp;"foo": "12"<br/>}`}
365
+ {#if render}
366
+ <div class="border-b">
367
+ <SchemaFormWithArgPicker
368
+ bind:this={schemaFormWithArgPicker}
369
+ runnableId={$initialPathStore}
370
+ stablePathForCaptures={$initialPathStore || fakeInitialPath}
371
+ runnableType={'FlowPath'}
372
+ previewArgs={previewArgs.val}
373
+ on:openTriggers
374
+ on:select={(e) => {
375
+ selectInput(e.detail.payload, e.detail?.type)
376
+ }}
377
+ {isValid}
378
+ {jsonView}
379
+ >
380
+ <div class="w-full flex flex-row justify-between">
381
+ <InputSelectedBadge
382
+ onReject={() => schemaFormWithArgPicker?.resetSelected()}
383
+ {inputSelected}
390
384
  />
385
+ <div class="flex flex-row gap-2">
386
+ <Toggle
387
+ bind:checked={jsonView}
388
+ label="JSON View"
389
+ size="xs"
390
+ options={{
391
+ right: 'JSON',
392
+ rightTooltip: 'Fill args from JSON'
393
+ }}
394
+ lightMode
395
+ on:change={(e) => {
396
+ jsonEditor?.setCode(JSON.stringify(previewArgs.val ?? {}, null, '\t'))
397
+ refresh()
398
+ }}
399
+ />
400
+ </div>
391
401
  </div>
392
- {:else}
393
- {#key renderCount}
394
- <div bind:clientHeight={schemaHeight} class="min-h-[40vh]">
395
- <SchemaForm
396
- noVariablePicker
397
- compact
398
- schema={flowStore.val.schema}
399
- bind:args={previewArgs.val}
400
- on:change={() => {
401
- savedArgs = previewArgs.val
402
+ {#if jsonView}
403
+ <div class="py-2" style="height: {Math.max(schemaHeight, 100)}px" data-schema-picker>
404
+ <JsonInputs
405
+ bind:this={jsonEditor}
406
+ on:select={(e) => {
407
+ if (e.detail) {
408
+ previewArgs.val = e.detail
409
+ }
402
410
  }}
403
- bind:isValid
411
+ updateOnBlur={false}
412
+ placeholder={`Write args as JSON.<br/><br/>Example:<br/><br/>{<br/>&nbsp;&nbsp;"foo": "12"<br/>}`}
404
413
  />
405
414
  </div>
406
- {/key}
407
- {/if}
408
- </SchemaFormWithArgPicker>
409
- </div>
415
+ {:else}
416
+ {#key renderCount}
417
+ <div bind:clientHeight={schemaHeight} class="min-h-[40vh]">
418
+ <SchemaForm
419
+ noVariablePicker
420
+ compact
421
+ schema={flowStore.val.schema}
422
+ bind:args={previewArgs.val}
423
+ on:change={() => {
424
+ savedArgs = previewArgs.val
425
+ }}
426
+ bind:isValid
427
+ />
428
+ </div>
429
+ {/key}
430
+ {/if}
431
+ </SchemaFormWithArgPicker>
432
+ </div>
433
+ {/if}
410
434
  <div class="pt-4 flex flex-col grow relative">
411
435
  <div
412
436
  class="absolute top-[22px] right-2 border p-1.5 hover:bg-surface-hover rounded-md center-center"
413
437
  >
414
- <FlowHistoryJobPicker
415
- selectInitial={jobId == undefined}
416
- on:select={(e) => {
417
- if (!currentJobId) {
418
- currentJobId = jobId
419
- }
420
- const detail = e.detail
421
- jobId = detail.jobId
422
- if (detail.initial && stepHistoryLoader?.flowJobInitial === undefined) {
423
- stepHistoryLoader?.setFlowJobInitial(detail.initial)
424
- }
425
- }}
426
- on:unselect={() => {
427
- jobId = currentJobId
428
- currentJobId = undefined
429
- }}
430
- path={$initialPathStore == '' ? $pathStore : $initialPathStore}
431
- />
438
+ {#if render}
439
+ <FlowHistoryJobPicker
440
+ selectInitial={jobId == undefined}
441
+ on:select={(e) => {
442
+ if (!currentJobId) {
443
+ currentJobId = jobId
444
+ }
445
+ const detail = e.detail
446
+ jobId = detail.jobId
447
+ if (detail.initial && stepHistoryLoader?.flowJobInitial === undefined) {
448
+ stepHistoryLoader?.setFlowJobInitial(detail.initial)
449
+ }
450
+ }}
451
+ on:unselect={() => {
452
+ jobId = currentJobId
453
+ currentJobId = undefined
454
+ }}
455
+ path={$initialPathStore == '' ? $pathStore : $initialPathStore}
456
+ />
457
+ {/if}
432
458
  </div>
459
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
433
460
  {#if jobId}
434
461
  {#if stepHistoryLoader?.flowJobInitial}
435
- <!-- svelte-ignore a11y-click-events-have-key-events -->
436
- <!-- svelte-ignore a11y-no-static-element-interactions -->
462
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
437
463
  <div
438
- on:click={() => {
464
+ onclick={() => {
439
465
  stepHistoryLoader?.setFlowJobInitial(false)
440
466
  }}
441
467
  class="cursor-pointer h-full hover:bg-gray-500/20 dark:hover:bg-gray-500/20 dark:bg-gray-500/80 rounded bg-gray-500/40 absolute top-0 left-0 w-full z-50"
@@ -451,15 +477,20 @@ function onScrollableDivChange() {
451
477
  bind:job
452
478
  bind:localModuleStates
453
479
  bind:localDurationStatuses
480
+ bind:suspendStatus
454
481
  hideDownloadInGraph={customUi?.downloadLogs === false}
455
482
  wideResults
456
483
  {flowStateStore}
457
484
  {jobId}
458
485
  on:done={() => {
486
+ isRunning = false
459
487
  $executionCount = $executionCount + 1
488
+ onJobDone?.()
460
489
  }}
461
490
  bind:selectedJobStep
462
491
  bind:rightColumnSelect
492
+ bind:isOwner
493
+ {render}
463
494
  />
464
495
  {:else}
465
496
  <div class="italic text-tertiary h-full grow"> Flow status will be displayed here </div>