windmill-components 1.55.2 → 1.56.1

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 (69) hide show
  1. package/components/Dropdown.svelte +7 -13
  2. package/components/FlowPreviewContent.svelte +1 -1
  3. package/components/FlowStatusViewer.svelte +57 -5
  4. package/components/FlowStatusViewer.svelte.d.ts +2 -0
  5. package/components/InputTransformForm.svelte +11 -4
  6. package/components/InputTransformForm.svelte.d.ts +0 -2
  7. package/components/ModulePreview.svelte +6 -2
  8. package/components/ModulePreview.svelte.d.ts +1 -1
  9. package/components/RunForm.svelte +10 -8
  10. package/components/ScheduleEditor.svelte +2 -2
  11. package/components/TemplateEditor.svelte +13 -1
  12. package/components/TestJobLoader.svelte +1 -1
  13. package/components/apps/components/DisplayComponent.svelte +1 -1
  14. package/components/apps/components/buttons/AppButton.svelte +19 -1
  15. package/components/apps/components/form/AppForm.svelte +18 -1
  16. package/components/apps/components/helpers/InputValue.svelte +0 -4
  17. package/components/apps/components/helpers/MissingConnectionWarning.svelte +11 -0
  18. package/components/apps/components/helpers/MissingConnectionWarning.svelte.d.ts +17 -0
  19. package/components/apps/components/helpers/RunnableComponent.svelte +82 -29
  20. package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +1 -1
  21. package/components/apps/components/helpers/RunnableWrapper.svelte +1 -1
  22. package/components/apps/components/selectInputs/AppSelect.svelte +14 -3
  23. package/components/apps/components/table/AppTable.svelte +5 -5
  24. package/components/apps/editor/AppEditor.svelte +5 -7
  25. package/components/apps/editor/ComponentEditor.svelte +1 -0
  26. package/components/apps/editor/GridEditor.svelte +6 -2
  27. package/components/apps/editor/SettingsPanel.svelte +13 -0
  28. package/components/apps/editor/SettingsPanel.svelte.d.ts +14 -0
  29. package/components/apps/editor/TablePanel.svelte +16 -0
  30. package/components/apps/editor/TablePanel.svelte.d.ts +17 -0
  31. package/components/apps/editor/componentsPanel/ComponentList.svelte +25 -7
  32. package/components/apps/editor/contextPanel/ComponentOutputViewer.svelte +1 -1
  33. package/components/apps/editor/contextPanel/ContextPanel.svelte +3 -0
  34. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +1 -1
  35. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte +63 -46
  36. package/components/apps/editor/inlineScriptsPanel/InlineScriptEditorPanel.svelte.d.ts +2 -2
  37. package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +16 -2
  38. package/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte.d.ts +9 -0
  39. package/components/apps/editor/settingsPanel/ComponentPanel.svelte +37 -2
  40. package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +7 -4
  41. package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte.d.ts +1 -0
  42. package/components/apps/editor/settingsPanel/Recompute.svelte +6 -2
  43. package/components/apps/editor/settingsPanel/TableActions.svelte +9 -32
  44. package/components/apps/editor/settingsPanel/inputEditor/StaticInputEditor.svelte +25 -8
  45. package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +10 -1
  46. package/components/apps/inputType.d.ts +2 -1
  47. package/components/apps/rx.js +1 -1
  48. package/components/apps/utils.js +5 -2
  49. package/components/common/drawer/Drawer.svelte +2 -1
  50. package/components/common/drawer/Drawer.svelte.d.ts +1 -0
  51. package/components/common/menu/Menu.svelte +3 -1
  52. package/components/common/table/Row.svelte +9 -11
  53. package/components/common/table/RowIcon.svelte +3 -2
  54. package/components/common/table/RowIcon.svelte.d.ts +1 -0
  55. package/components/flows/common/FlowCardHeader.svelte +29 -2
  56. package/components/flows/content/FlowModuleComponent.svelte +1 -1
  57. package/components/flows/content/FlowModuleScript.svelte +8 -3
  58. package/components/flows/content/FlowModuleScript.svelte.d.ts +1 -0
  59. package/components/flows/header/FlowPreviewButtons.svelte +2 -1
  60. package/components/flows/pickers/WorkspaceScriptPicker.svelte +1 -1
  61. package/components/flows/previousResults.d.ts +1 -1
  62. package/components/flows/previousResults.js +15 -3
  63. package/components/propertyPicker/PropPicker.svelte +2 -1
  64. package/gen/core/OpenAPI.js +1 -1
  65. package/gen/services/JobService.d.ts +10 -0
  66. package/gen/services/JobService.js +17 -0
  67. package/package.json +488 -485
  68. package/utils.d.ts +1 -0
  69. package/utils.js +4 -2
@@ -20,8 +20,7 @@ const dispatch = createEventDispatcher();
20
20
  {#each dropdownItems as item, i}
21
21
  {#if item.action}
22
22
  <button
23
- on:click={(event) => {
24
- event.preventDefault()
23
+ on:click|preventDefault|stopPropagation={(event) => {
25
24
  if (!item.disabled) {
26
25
  close()
27
26
  item.action && item.action(event)
@@ -30,7 +29,7 @@ const dispatch = createEventDispatcher();
30
29
  }}
31
30
  class="block w-full whitespace-nowrap hover:drop-shadow-sm hover:bg-gray-50 hover:bg-opacity-30
32
31
  px-4 py-2 text-sm text-gray-700 text-left
33
- {item.disabled ? 'bg-gray-100' : ''}
32
+ {item.disabled ? 'bg-gray-200' : ''}
34
33
  {item.separatorTop ? 'border-t' : ''} {item.separatorBottom ? 'border-b' : ''} {item.type ==
35
34
  'delete'
36
35
  ? 'text-red-500'
@@ -52,14 +51,9 @@ const dispatch = createEventDispatcher();
52
51
  {:else if item.href && !item.disabled}
53
52
  <a
54
53
  href={item.href}
55
- on:click={(e) => {
56
- if (!item.disabled) {
57
- close()
58
- } else {
59
- e.preventDefault()
60
- }
61
- }}
62
- class="block w-full px-4 font-semibold py-2 text-sm text-gray-700 hover:drop-shadow-sm hover:bg-gray-50 hover:bg-opacity-30"
54
+ on:click|stopPropagation
55
+ class="block w-full px-4 font-semibold text-left py-2 text-sm text-gray-700 hover:drop-shadow-sm hover:bg-gray-50 hover:bg-opacity-30
56
+ {item.disabled ? 'bg-gray-200' : ''}"
63
57
  role="menuitem"
64
58
  tabindex="-1"
65
59
  id="user-menu-item-{name}-{i}}"
@@ -77,11 +71,11 @@ const dispatch = createEventDispatcher();
77
71
  {:else}
78
72
  <span
79
73
  class:bg-gray-50={item.disabled}
80
- class="block px-4 py-2 text-sm text-gray-700 cursor-auto"
74
+ class="block text-left px-4 py-2 text-sm text-gray-700 cursor-auto"
81
75
  role="menuitem"
82
76
  tabindex="-1"
83
77
  id="user-menu-item-{name}-{i}}"
84
- on:click|preventDefault
78
+ on:click|preventDefault|stopPropagation
85
79
  >
86
80
  {#if item.icon}
87
81
  <Icon
@@ -89,7 +89,7 @@ $: if (job?.type === 'CompletedJob') {
89
89
  <div class="flex flex-row justify-between w-full items-center gap-x-2">
90
90
  <button
91
91
  on:click={() => dispatch('close')}
92
- class="hover:bg-gray-200 bg-gray-100 rounded-full w-8 h-8 flex items-center justify-center transition-all"
92
+ class="hover:bg-gray-200 bg-gray-100 rounded-full w-16 h-8 flex items-center justify-center transition-all"
93
93
  >
94
94
  <Icon data={faClose} class="text-gray-500" />
95
95
  </button>
@@ -1,9 +1,9 @@
1
1
  <script>import { FlowStatusModule, Job, JobService } from '../gen';
2
- import { workspaceStore } from '../stores';
2
+ import { userStore, workspaceStore } from '../stores';
3
3
  import FlowJobResult from './FlowJobResult.svelte';
4
4
  import FlowPreviewStatus from './preview/FlowPreviewStatus.svelte';
5
5
  import Icon from 'svelte-awesome';
6
- import { faChevronDown, faChevronUp, faHourglassHalf } from '@fortawesome/free-solid-svg-icons';
6
+ import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
7
7
  import { createEventDispatcher } from 'svelte';
8
8
  import { onDestroy } from 'svelte';
9
9
  import { Button, Tab } from './common';
@@ -11,8 +11,10 @@ import DisplayResult from './DisplayResult.svelte';
11
11
  import Tabs from './common/tabs/Tabs.svelte';
12
12
  import { FlowGraph } from './graph';
13
13
  import ModuleStatus from './ModuleStatus.svelte';
14
- import { displayDate, truncateRev } from '../utils';
14
+ import { displayDate, isOwner, pluralize, truncateRev } from '../utils';
15
15
  import JobArgs from './JobArgs.svelte';
16
+ import Tooltip from './Tooltip.svelte';
17
+ import SimpleEditor from './SimpleEditor.svelte';
16
18
  const dispatch = createEventDispatcher();
17
19
  export let jobId;
18
20
  export let flowState = undefined;
@@ -21,6 +23,8 @@ export let job = undefined;
21
23
  export let flowModuleStates = {};
22
24
  let localFlowModuleStates = {};
23
25
  export let retry_status = {};
26
+ export let suspend_status = undefined;
27
+ export let is_owner = false;
24
28
  let selectedNode = undefined;
25
29
  let jobResults = [];
26
30
  let jobFailures = [];
@@ -44,6 +48,7 @@ $: {
44
48
  }
45
49
  }
46
50
  $: updateFailCount(job?.flow_status?.retry?.fail_count);
51
+ $: suspend_status = job?.flow_status?.modules?.[job?.flow_status.step]?.count;
47
52
  function updateFailCount(count) {
48
53
  if (count) {
49
54
  retry_status[jobId ?? ''] = count;
@@ -103,11 +108,12 @@ async function loadJobInProgress() {
103
108
  }
104
109
  }
105
110
  $: job && dispatch('jobsLoaded', job);
106
- function updateJobId() {
111
+ async function updateJobId() {
107
112
  if (jobId !== job?.id) {
108
113
  retry_status = {};
109
114
  localFlowModuleStates = {};
110
- loadJobInProgress();
115
+ await loadJobInProgress();
116
+ job?.script_path && loadOwner(job.script_path);
111
117
  }
112
118
  }
113
119
  $: jobId && updateJobId();
@@ -115,7 +121,11 @@ $: isListJob = flowJobIds && Array.isArray(flowJobIds?.flowJobs);
115
121
  onDestroy(() => {
116
122
  timeout && clearTimeout(timeout);
117
123
  });
124
+ async function loadOwner(path) {
125
+ is_owner = await isOwner(path, $userStore, $workspaceStore);
126
+ }
118
127
  let selected = 'graph';
128
+ let payload = '"a test payload in json"';
119
129
  </script>
120
130
 
121
131
  {#if job}
@@ -134,6 +144,41 @@ let selected = 'graph';
134
144
  <div class="w-full h-full">
135
145
  <FlowJobResult result={job.result} logs={job.logs ?? ''} />
136
146
  </div>
147
+ {:else if job.flow_status?.modules?.[job?.flow_status?.step].type === FlowStatusModule.type.WAITING_FOR_EVENTS}
148
+ <div class="w-full h-full mt-2 text-sm text-gray-600">
149
+ <p>Waiting for approval from the previous step</p>
150
+ <div>
151
+ {#if is_owner}
152
+ <div class="flex flex-row gap-2 mt-2">
153
+ <div>
154
+ <Button
155
+ color="green"
156
+ variant="border"
157
+ on:click={async () =>
158
+ await JobService.resumeSuspendedFlowAsOwner({
159
+ workspace: $workspaceStore ?? '',
160
+ id: job?.id ?? '',
161
+ requestBody: JSON.parse(payload)
162
+ })}
163
+ >Resume <Tooltip
164
+ >Since you are an owner of this flow, you can send resume events without
165
+ necessarily knowing the resume id sent by the approval step</Tooltip
166
+ ></Button
167
+ >
168
+ </div>
169
+ <div class="w-full border rounded-lg border-gray-600 p-2">
170
+ <SimpleEditor automaticLayout lang="json" bind:code={payload} autoHeight />
171
+ </div>
172
+ <Tooltip
173
+ >The payload is optional, it is passed to the following step through the
174
+ `resume` variable</Tooltip
175
+ >
176
+ </div>
177
+ {:else}
178
+ You cannot resume the job without the resume id since you are not an owner of {job.script_path}
179
+ {/if}
180
+ </div>
181
+ </div>
137
182
  {:else if job.logs}
138
183
  <div class="text-xs p-4 bg-gray-50 overflow-auto max-h-80 border">
139
184
  <pre class="w-full">{job.logs}</pre>
@@ -183,6 +228,7 @@ let selected = 'graph';
183
228
  </Button>
184
229
  <div class="border p-6" class:hidden={forloop_selected != loopJobId}>
185
230
  <svelte:self
231
+ bind:suspend_status
186
232
  bind:retry_status
187
233
  bind:flowState
188
234
  bind:flowModuleStates={localFlowModuleStates}
@@ -254,6 +300,7 @@ let selected = 'graph';
254
300
  <li class="w-full border border-gray-600 p-6 space-y-2 bg-blue-50/50">
255
301
  {#if [FlowStatusModule.type.IN_PROGRESS, FlowStatusModule.type.SUCCESS, FlowStatusModule.type.FAILURE].includes(mod.type)}
256
302
  <svelte:self
303
+ bind:suspend_status
257
304
  bind:retry_status
258
305
  bind:flowState
259
306
  bind:flowModuleStates={localFlowModuleStates}
@@ -314,6 +361,11 @@ let selected = 'graph';
314
361
  Retry in progress, # of failed attempts: {count}
315
362
  </span>
316
363
  {/each}
364
+ {#if suspend_status}
365
+ <span class="text-sm">
366
+ Flow suspended, waiting for {pluralize(suspend_status, 'approval')}
367
+ </span>
368
+ {/if}
317
369
  </div>
318
370
 
319
371
  <FlowGraph
@@ -13,6 +13,8 @@ declare const __propDef: {
13
13
  job?: Job | undefined;
14
14
  flowModuleStates?: Record<string, GraphModuleState> | undefined;
15
15
  retry_status?: Record<string, number> | undefined;
16
+ suspend_status?: number | undefined;
17
+ is_owner?: boolean | undefined;
16
18
  };
17
19
  events: {
18
20
  jobsLoaded: CustomEvent<any>;
@@ -8,7 +8,6 @@ import { Button, ToggleButton, ToggleButtonGroup } from './common';
8
8
  import { faCode } from '@fortawesome/free-solid-svg-icons';
9
9
  import TemplateEditor from './TemplateEditor.svelte';
10
10
  import Tooltip from './Tooltip.svelte';
11
- import { escape } from 'svelte/internal';
12
11
  export let schema;
13
12
  export let arg;
14
13
  export let argName;
@@ -18,7 +17,8 @@ export let previousModuleId;
18
17
  export let pickForField = undefined;
19
18
  export let variableEditor = undefined;
20
19
  export let itemPicker = undefined;
21
- export let monaco = undefined;
20
+ let monaco = undefined;
21
+ let monacoTemplate = undefined;
22
22
  let argInput = undefined;
23
23
  let inputCat = 'object';
24
24
  let propertyType = getPropertyType(arg);
@@ -58,6 +58,7 @@ function connectProperty(rawValue) {
58
58
  if (isStaticTemplate(inputCat)) {
59
59
  arg.value = `\$\{${rawValue}}`;
60
60
  setPropertyType(arg.value);
61
+ monacoTemplate?.setCode(arg.value);
61
62
  }
62
63
  else {
63
64
  arg.expr = getDefaultExpr(undefined, previousModuleId, rawValue);
@@ -71,6 +72,7 @@ function onFocus() {
71
72
  focusProp(argName, 'append', (path) => {
72
73
  const toAppend = `\$\{${path}}`;
73
74
  arg.value = `${arg.value ?? ''}${toAppend}`;
75
+ monacoTemplate?.setCode(arg.value);
74
76
  setPropertyType(arg.value);
75
77
  argInput?.focus();
76
78
  return false;
@@ -203,8 +205,13 @@ const closeBracket = '}';
203
205
  </span>
204
206
  {/if}
205
207
  {#if isStaticTemplate(inputCat) && propertyType == 'static'}
206
- <div class="py-1">
207
- <TemplateEditor {extraLib} on:focus={onFocus} bind:code={arg.value} />
208
+ <div class="py-1 rounded border border-1 border-gray-500">
209
+ <TemplateEditor
210
+ bind:this={monacoTemplate}
211
+ {extraLib}
212
+ on:focus={onFocus}
213
+ bind:code={arg.value}
214
+ />
208
215
  </div>
209
216
  {:else if propertyType === undefined || propertyType == 'static'}
210
217
  <ArgInput
@@ -1,6 +1,5 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { Schema } from '../common';
3
- import SimpleEditor from './SimpleEditor.svelte';
4
3
  import type VariableEditor from './VariableEditor.svelte';
5
4
  import type ItemPicker from './ItemPicker.svelte';
6
5
  import type { InputTransform } from '../gen';
@@ -15,7 +14,6 @@ declare const __propDef: {
15
14
  pickForField?: string | undefined;
16
15
  variableEditor?: VariableEditor | undefined;
17
16
  itemPicker?: ItemPicker | undefined;
18
- monaco?: SimpleEditor | undefined;
19
17
  };
20
18
  events: {
21
19
  [evt: string]: CustomEvent<any>;
@@ -1,4 +1,5 @@
1
- <script>import { getScriptByPath, sendUserToast, truncateRev } from '../utils';
1
+ <script>import { ScriptService } from '../gen';
2
+ import { getScriptByPath, sendUserToast, truncateRev } from '../utils';
2
3
  import { Pane, Splitpanes } from 'svelte-splitpanes';
3
4
  import RunForm from './RunForm.svelte';
4
5
  import TestJobLoader from './TestJobLoader.svelte';
@@ -9,6 +10,7 @@ import { faRotateRight } from '@fortawesome/free-solid-svg-icons';
9
10
  import { flowStateStore } from './flows/flowState';
10
11
  import { flowStore } from './flows/flowStore';
11
12
  import { Alert } from './common';
13
+ import { workspaceStore } from '../stores';
12
14
  let testJobLoader;
13
15
  // Test
14
16
  let testIsLoading = false;
@@ -25,7 +27,9 @@ export async function runTest(args) {
25
27
  await testJobLoader?.runPreview(val.path, val.content, val.language, args);
26
28
  }
27
29
  else if (val.type == 'script') {
28
- const script = await getScriptByPath(val.path);
30
+ const script = val.hash
31
+ ? await ScriptService.getScriptByHash({ workspace: $workspaceStore, hash: val.hash })
32
+ : await getScriptByPath(val.path);
29
33
  await testJobLoader?.runPreview(val.path, script.content, script.language, args);
30
34
  }
31
35
  else {
@@ -1,6 +1,6 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { Schema } from '../common';
3
- import type { FlowModule } from '../gen';
3
+ import { type FlowModule } from '../gen';
4
4
  declare const __propDef: {
5
5
  props: {
6
6
  mod: FlowModule;
@@ -120,7 +120,7 @@ let invisible_to_owner;
120
120
  </div>
121
121
  {/if}
122
122
  {#if schedulable}
123
- <div class="flex justify-between mt-2 md:mt-6 mb-6">
123
+ <div class="flex gap-2 items-center flex-wrap justify-between mt-2 md:mt-6 mb-6">
124
124
  <Button
125
125
  color="light"
126
126
  size="sm"
@@ -142,13 +142,15 @@ let invisible_to_owner;
142
142
  >
143
143
  </div>
144
144
  {/if}
145
- <Button
146
- btnClasses="!px-6 !py-1"
147
- disabled={!isValid}
148
- on:click={() => runAction(scheduledForStr, args, invisible_to_owner)}
149
- >
150
- {scheduledForStr ? 'Schedule run to a later time' : buttonText}
151
- </Button>
145
+ <div class="flex-row-reverse flex grow">
146
+ <Button
147
+ btnClasses="!px-6 !py-1"
148
+ disabled={!isValid}
149
+ on:click={() => runAction(scheduledForStr, args, invisible_to_owner)}
150
+ >
151
+ {scheduledForStr ? 'Schedule run to a later time' : buttonText}
152
+ </Button>
153
+ </div>
152
154
  </div>
153
155
  {:else if !topButton}
154
156
  <Button
@@ -6,7 +6,7 @@
6
6
  }
7
7
  </script>
8
8
 
9
- <script>import { sendUserToast, formatCron, canWrite } from '../utils';
9
+ <script>import { sendUserToast, formatCron, canWrite, emptyString } from '../utils';
10
10
  import { ScriptService, Script, ScheduleService, FlowService } from '../gen';
11
11
  import Toggle from './Toggle.svelte';
12
12
  import Path from './Path.svelte';
@@ -151,7 +151,7 @@ let drawer;
151
151
  {/if}
152
152
  <Button
153
153
  startIcon={{ icon: faSave }}
154
- disabled={!allowSchedule || pathError != ''}
154
+ disabled={!allowSchedule || pathError != '' || emptyString(script_path)}
155
155
  on:click={scheduleScript}
156
156
  >
157
157
  {edit ? 'Save' : 'Schedule'}
@@ -346,6 +346,17 @@ if (browser) {
346
346
  };
347
347
  }
348
348
  }
349
+ export function insertAtCursor(code) {
350
+ if (editor) {
351
+ editor.trigger('keyboard', 'type', { text: code });
352
+ }
353
+ }
354
+ export function setCode(ncode) {
355
+ code = ncode;
356
+ if (editor) {
357
+ editor.setValue(ncode);
358
+ }
359
+ }
349
360
  export function getCode() {
350
361
  return editor?.getValue() ?? '';
351
362
  }
@@ -359,7 +370,8 @@ async function loadMonaco() {
359
370
  ...editorConfig(model, code, lang, automaticLayout, fixedOverflowWidgets),
360
371
  lineNumbers: 'off',
361
372
  fontSize: 16,
362
- suggestOnTriggerCharacters: true
373
+ suggestOnTriggerCharacters: true,
374
+ lineDecorationsWidth: 20
363
375
  });
364
376
  const stdLib = { content: libStdContent, filePath: 'es5.d.ts' };
365
377
  if (extraLib != '') {
@@ -120,7 +120,7 @@ async function loadTestJob(id) {
120
120
  if (err.status === 404) {
121
121
  notfound = true;
122
122
  }
123
- console.error(err);
123
+ console.warn(err);
124
124
  }
125
125
  return isCompleted;
126
126
  }
@@ -2,8 +2,8 @@
2
2
  import RunnableWrapper from './helpers/RunnableWrapper.svelte';
3
3
  export let id;
4
4
  export let componentInput;
5
- export const staticOutputs = [];
6
5
  let result = undefined;
6
+ export const staticOutputs = ['result', 'loading'];
7
7
  </script>
8
8
 
9
9
  <RunnableWrapper bind:result bind:componentInput {id}>
@@ -1,4 +1,5 @@
1
1
  <script>import { Button } from '../../../common';
2
+ import { faArrowRight, faRefresh } from '@fortawesome/free-solid-svg-icons';
2
3
  import { getContext } from 'svelte';
3
4
  import AlignWrapper from '../helpers/AlignWrapper.svelte';
4
5
  import InputValue from '../helpers/InputValue.svelte';
@@ -11,11 +12,23 @@ export let extraQueryParams = {};
11
12
  export let horizontalAlignment = undefined;
12
13
  export let verticalAlignment = undefined;
13
14
  export const staticOutputs = ['loading', 'result'];
14
- const { runnableComponents } = getContext('AppEditorContext');
15
+ const { runnableComponents, worldStore } = getContext('AppEditorContext');
15
16
  let labelValue = 'Default label';
16
17
  let color;
17
18
  let size;
18
19
  let runnableComponent;
20
+ let isLoading = false;
21
+ let ownClick = false;
22
+ $: outputs = $worldStore?.outputsById[id];
23
+ $: outputs?.loading.subscribe({
24
+ next: (value) => {
25
+ isLoading = value;
26
+ if (ownClick && !value) {
27
+ ownClick = false;
28
+ }
29
+ }
30
+ });
31
+ $: loading = isLoading && ownClick;
19
32
  </script>
20
33
 
21
34
  <InputValue {id} input={configuration.label} bind:value={labelValue} />
@@ -32,6 +45,7 @@ let runnableComponent;
32
45
  <AlignWrapper {horizontalAlignment} {verticalAlignment}>
33
46
  <Button
34
47
  on:click={() => {
48
+ ownClick = true
35
49
  runnableComponent?.runComponent()
36
50
 
37
51
  if (recomputeIds) {
@@ -42,6 +56,10 @@ let runnableComponent;
42
56
  }}
43
57
  {size}
44
58
  {color}
59
+ endIcon={{
60
+ icon: loading ? faRefresh : faArrowRight,
61
+ classes: loading ? 'animate-spin w-4' : 'w-4'
62
+ }}
45
63
  >
46
64
  {labelValue}
47
65
  </Button>
@@ -1,4 +1,5 @@
1
1
  <script>import { Button } from '../../../common';
2
+ import { faArrowRight, faRefresh } from '@fortawesome/free-solid-svg-icons';
2
3
  import { getContext } from 'svelte';
3
4
  import AlignWrapper from '../helpers/AlignWrapper.svelte';
4
5
  import InputValue from '../helpers/InputValue.svelte';
@@ -10,11 +11,23 @@ export let recomputeIds = undefined;
10
11
  export let extraQueryParams = {};
11
12
  export let horizontalAlignment = undefined;
12
13
  export const staticOutputs = ['loading', 'result'];
13
- const { runnableComponents } = getContext('AppEditorContext');
14
+ const { runnableComponents, worldStore } = getContext('AppEditorContext');
14
15
  let labelValue = 'Default label';
15
16
  let color;
16
17
  let size;
17
18
  let runnableComponent;
19
+ let isLoading = false;
20
+ let ownClick = false;
21
+ $: outputs = $worldStore?.outputsById[id];
22
+ $: outputs?.loading.subscribe({
23
+ next: (value) => {
24
+ isLoading = value;
25
+ if (ownClick && !value) {
26
+ ownClick = false;
27
+ }
28
+ }
29
+ });
30
+ $: loading = isLoading && ownClick;
18
31
  </script>
19
32
 
20
33
  <InputValue {id} input={configuration.label} bind:value={labelValue} />
@@ -42,6 +55,10 @@ let runnableComponent;
42
55
  }}
43
56
  {size}
44
57
  {color}
58
+ endIcon={{
59
+ icon: loading ? faRefresh : faArrowRight,
60
+ classes: loading ? 'animate-spin w-4' : 'w-4'
61
+ }}
45
62
  >
46
63
  {labelValue}
47
64
  </Button>
@@ -20,9 +20,6 @@ function handleConnection() {
20
20
  }
21
21
  }
22
22
  function computeGlobalContext() {
23
- Object.prototype.toString = function () {
24
- return JSON.stringify(this);
25
- };
26
23
  return Object.fromEntries(Object.entries($worldStore?.outputsById ?? {})
27
24
  .filter(([k, _]) => k != id)
28
25
  .map(([key, value]) => {
@@ -33,7 +30,6 @@ function computeGlobalContext() {
33
30
  }));
34
31
  }
35
32
  function setValue() {
36
- console.log(computeGlobalContext());
37
33
  if (input.type === 'template' && isCodeInjection(input.eval)) {
38
34
  try {
39
35
  value = eval_like('`' + input.eval + '`', computeGlobalContext());
@@ -0,0 +1,11 @@
1
+ <script>export let input;
2
+ </script>
3
+
4
+ {#if input.type === 'connected'}
5
+ <div class="flex gap-2 flex-col">
6
+ <div>This component is expecting a connected input: </div>
7
+ <div>
8
+ <code class="bg-gray-50 border text-gray-600">{input.connection?.path} </code>
9
+ </div>
10
+ </div>
11
+ {/if}
@@ -0,0 +1,17 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { AppInput } from '../../inputType';
3
+ declare const __propDef: {
4
+ props: {
5
+ input: AppInput;
6
+ };
7
+ events: {
8
+ [evt: string]: CustomEvent<any>;
9
+ };
10
+ slots: {};
11
+ };
12
+ export type MissingConnectionWarningProps = typeof __propDef.props;
13
+ export type MissingConnectionWarningEvents = typeof __propDef.events;
14
+ export type MissingConnectionWarningSlots = typeof __propDef.slots;
15
+ export default class MissingConnectionWarning extends SvelteComponentTyped<MissingConnectionWarningProps, MissingConnectionWarningEvents, MissingConnectionWarningSlots> {
16
+ }
17
+ export {};