windmill-components 1.28.6 → 1.35.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 (158) hide show
  1. package/common.d.ts +3 -0
  2. package/components/AppConnect.svelte +29 -13
  3. package/components/ArgInput.svelte +28 -14
  4. package/components/ArgInput.svelte.d.ts +4 -0
  5. package/components/CenteredPage.svelte +2 -2
  6. package/components/DisplayResult.svelte +3 -3
  7. package/components/Editor.svelte +97 -97
  8. package/components/Editor.svelte.d.ts +3 -0
  9. package/components/EditorBar.svelte +57 -38
  10. package/components/FlowBuilder.svelte +40 -32
  11. package/components/FlowEditor.svelte +19 -57
  12. package/components/FlowEditor.svelte.d.ts +1 -0
  13. package/components/FlowJobResult.svelte +16 -16
  14. package/components/FlowModulesViewer.svelte +97 -0
  15. package/components/FlowModulesViewer.svelte.d.ts +17 -0
  16. package/components/FlowPreview.svelte +47 -68
  17. package/components/FlowPreview.svelte.d.ts +2 -6
  18. package/components/FlowPreviewContent.svelte +59 -44
  19. package/components/FlowPreviewContent.svelte.d.ts +0 -1
  20. package/components/FlowStatusViewer.svelte +104 -204
  21. package/components/FlowStatusViewer.svelte.d.ts +7 -4
  22. package/components/FlowViewer.svelte +60 -155
  23. package/components/FlowViewer.svelte.d.ts +0 -1
  24. package/components/IconedPath.svelte +12 -0
  25. package/components/IconedPath.svelte.d.ts +16 -0
  26. package/components/IconedResourceType.svelte +21 -2
  27. package/components/IconedResourceType.svelte.d.ts +1 -0
  28. package/components/InputTransformForm.svelte +9 -8
  29. package/components/InputTransformForm.svelte.d.ts +1 -1
  30. package/components/InviteGlobalUser.svelte +1 -1
  31. package/components/ItemPicker.svelte +6 -1
  32. package/components/JobStatus.svelte +1 -1
  33. package/components/ModuleStep.svelte +74 -96
  34. package/components/ModuleStep.svelte.d.ts +7 -4
  35. package/components/Multiselect.svelte +1 -1
  36. package/components/Path.svelte +62 -40
  37. package/components/Path.svelte.d.ts +2 -0
  38. package/components/ProgressBar.svelte +31 -0
  39. package/components/ProgressBar.svelte.d.ts +17 -0
  40. package/components/ProgressBarPart.svelte +20 -0
  41. package/components/ProgressBarPart.svelte.d.ts +20 -0
  42. package/components/ResourceEditor.svelte +2 -1
  43. package/components/ResourcePicker.svelte +9 -0
  44. package/components/SchemaForm.svelte +9 -4
  45. package/components/SchemaForm.svelte.d.ts +1 -1
  46. package/components/SchemaModal.svelte +20 -3
  47. package/components/SchemaViewer.svelte +58 -68
  48. package/components/ScriptBuilder.svelte +145 -122
  49. package/components/ScriptBuilder.svelte.d.ts +1 -0
  50. package/components/ScriptEditor.svelte +118 -339
  51. package/components/ScriptEditor.svelte.d.ts +0 -2
  52. package/components/ScriptSchema.svelte +45 -44
  53. package/components/SharedBadge.svelte +8 -3
  54. package/components/VariableEditor.svelte +1 -1
  55. package/components/common/drawer/Drawer.svelte +108 -0
  56. package/components/common/drawer/Drawer.svelte.d.ts +23 -0
  57. package/components/common/drawer/DrawerContent.svelte +19 -0
  58. package/components/common/drawer/DrawerContent.svelte.d.ts +20 -0
  59. package/components/common/menu/Menu.svelte +57 -0
  60. package/components/common/menu/Menu.svelte.d.ts +23 -0
  61. package/components/common/menu/MenuItem.svelte +9 -0
  62. package/components/common/menu/MenuItem.svelte.d.ts +27 -0
  63. package/components/common/tabs/Tab.svelte +17 -0
  64. package/components/common/tabs/Tab.svelte.d.ts +18 -0
  65. package/components/common/tabs/TabContent.svelte +12 -0
  66. package/components/common/tabs/TabContent.svelte.d.ts +19 -0
  67. package/components/common/tabs/Tabs.svelte +20 -0
  68. package/components/common/tabs/Tabs.svelte.d.ts +24 -0
  69. package/components/flows/CopyFirstStepSchema.svelte +4 -3
  70. package/components/flows/DynamicInputHelpBox.svelte +6 -4
  71. package/components/flows/DynamicInputHelpBox.svelte.d.ts +1 -1
  72. package/components/flows/FlowBox.svelte +15 -2
  73. package/components/flows/FlowBox.svelte.d.ts +14 -14
  74. package/components/flows/FlowBoxHeader.svelte +10 -3
  75. package/components/flows/FlowBoxHeader.svelte.d.ts +3 -0
  76. package/components/flows/FlowInput.svelte +14 -12
  77. package/components/flows/FlowInputs.svelte +56 -22
  78. package/components/flows/FlowInputs.svelte.d.ts +3 -1
  79. package/components/flows/FlowModuleHeader.svelte +69 -54
  80. package/components/flows/FlowModuleHeader.svelte.d.ts +6 -6
  81. package/components/flows/FlowSettings.svelte +82 -92
  82. package/components/flows/FlowSettings.svelte.d.ts +1 -1
  83. package/components/flows/FlowTimeline.svelte +169 -0
  84. package/components/flows/FlowTimeline.svelte.d.ts +21 -0
  85. package/components/flows/flowState.d.ts +14 -0
  86. package/components/flows/flowState.js +52 -0
  87. package/components/flows/flowStateUtils.d.ts +37 -0
  88. package/components/flows/flowStateUtils.js +220 -0
  89. package/components/flows/flowStore.d.ts +1 -16
  90. package/components/flows/flowStore.js +26 -203
  91. package/components/flows/pickers/FlowScriptPicker.svelte +5 -9
  92. package/components/flows/pickers/FlowScriptPicker.svelte.d.ts +0 -1
  93. package/components/flows/pickers/PickHubScript.svelte +1 -1
  94. package/components/flows/pickers/PickHubScript.svelte.d.ts +1 -1
  95. package/components/flows/pickers/PickScript.svelte +1 -1
  96. package/components/flows/pickers/PickScript.svelte.d.ts +1 -1
  97. package/components/flows/scheduleUtils.d.ts +7 -0
  98. package/components/flows/scheduleUtils.js +21 -0
  99. package/components/flows/stepOpenedStore.d.ts +1 -0
  100. package/components/flows/stepOpenedStore.js +6 -0
  101. package/components/flows/utils.d.ts +6 -13
  102. package/components/flows/utils.js +47 -119
  103. package/components/icons/DiscordIcon.svelte +16 -0
  104. package/components/icons/DiscordIcon.svelte.d.ts +17 -0
  105. package/components/icons/HttpIcon.svelte +21 -0
  106. package/components/icons/HttpIcon.svelte.d.ts +17 -0
  107. package/components/icons/MastodonIcon.svelte +16 -0
  108. package/components/icons/MastodonIcon.svelte.d.ts +17 -0
  109. package/components/icons/MatrixIcon.svelte +16 -0
  110. package/components/icons/MatrixIcon.svelte.d.ts +17 -0
  111. package/components/icons/S3Icon.svelte +16 -0
  112. package/components/icons/S3Icon.svelte.d.ts +17 -0
  113. package/components/icons/WindmillIcon.svelte +68 -0
  114. package/components/icons/WindmillIcon.svelte.d.ts +17 -0
  115. package/components/jobs/JobDetail.svelte +176 -0
  116. package/components/jobs/JobDetail.svelte.d.ts +17 -0
  117. package/components/landing/FlowGettingStarted.svelte +95 -0
  118. package/components/landing/FlowGettingStarted.svelte.d.ts +19 -0
  119. package/components/landing/FlowLandingBox.svelte +69 -0
  120. package/components/landing/FlowLandingBox.svelte.d.ts +17 -0
  121. package/components/landing/RessourceGettingStarted.svelte +51 -0
  122. package/components/landing/RessourceGettingStarted.svelte.d.ts +19 -0
  123. package/components/landing/ScriptBox.svelte +81 -0
  124. package/components/landing/ScriptBox.svelte.d.ts +17 -0
  125. package/components/landing/ScriptGettingStarted.svelte +93 -0
  126. package/components/landing/ScriptGettingStarted.svelte.d.ts +19 -0
  127. package/components/preview/FlowPreviewStatus.svelte +28 -0
  128. package/components/preview/FlowPreviewStatus.svelte.d.ts +17 -0
  129. package/components/propertyPicker/ObjectViewer.svelte +13 -13
  130. package/components/propertyPicker/utils.js +3 -2
  131. package/components/script_editor/LogPanel.svelte +172 -0
  132. package/components/script_editor/LogPanel.svelte.d.ts +22 -0
  133. package/components/sidebar/MenuLink.svelte +49 -0
  134. package/components/sidebar/MenuLink.svelte.d.ts +21 -0
  135. package/components/sidebar/SidebarContent.svelte +55 -0
  136. package/components/sidebar/SidebarContent.svelte.d.ts +16 -0
  137. package/components/sidebar/UserMenu.svelte +62 -0
  138. package/components/sidebar/UserMenu.svelte.d.ts +16 -0
  139. package/components/sidebar/WorkspaceMenu.svelte +66 -0
  140. package/components/sidebar/WorkspaceMenu.svelte.d.ts +16 -0
  141. package/gen/core/OpenAPI.js +1 -1
  142. package/gen/core/request.js +1 -0
  143. package/gen/models/FlowModule.d.ts +5 -3
  144. package/gen/models/ForloopFlow.d.ts +2 -2
  145. package/gen/models/MainArgSignature.d.ts +14 -3
  146. package/gen/services/JobService.d.ts +10 -2
  147. package/gen/services/JobService.js +4 -2
  148. package/gen/services/ScriptService.d.ts +18 -0
  149. package/gen/services/ScriptService.js +30 -0
  150. package/infer.js +47 -24
  151. package/logout.js +1 -1
  152. package/package.json +57 -23
  153. package/script_helpers.d.ts +4 -1
  154. package/script_helpers.js +68 -17
  155. package/stores.d.ts +0 -2
  156. package/stores.js +0 -4
  157. package/utils.d.ts +5 -2
  158. package/utils.js +37 -6
@@ -1,36 +1,28 @@
1
- <script>import { Job, JobService } from '../gen';
2
- import { workspaceStore } from '../stores';
3
- import { sendUserToast, truncateRev } from '../utils';
1
+ <script>import { sendUserToast, truncateRev } from '../utils';
4
2
  import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
5
- import { createEventDispatcher, onDestroy } from 'svelte';
6
3
  import Icon from 'svelte-awesome';
7
- import FlowJobResult from './FlowJobResult.svelte';
8
- import { flowToMode, runFlowPreview } from './flows/utils';
4
+ import { flowStateStore, flowStateToFlow } from './flows/flowState';
5
+ import { mapJobResultsToFlowState } from './flows/flowStateUtils';
6
+ import { runFlowPreview } from './flows/utils';
9
7
  import FlowStatusViewer from './FlowStatusViewer.svelte';
10
8
  import RunForm from './RunForm.svelte';
11
- import Tabs from './Tabs.svelte';
12
- const dispatch = createEventDispatcher();
9
+ import Tab from './common/tabs/Tab.svelte';
10
+ import TabContent from './common/tabs/TabContent.svelte';
11
+ import Tabs from './common/tabs/Tabs.svelte';
13
12
  export let i;
14
13
  export let flow;
15
- export let schemas = [];
16
- export let mode;
14
+ export let schema;
17
15
  export let args = {};
18
16
  let stepArgs = {};
19
17
  let tab = 'upto';
20
18
  let viewPreview = false;
21
- let intervalId;
22
19
  let uptoText = i >= flow.value.modules.length - 1 ? 'Preview whole flow' : 'Preview up to this step';
23
- let job;
24
- let jobs = [];
25
20
  let jobId;
26
- $: dispatch('change', jobs);
27
21
  export async function runPreview(args) {
28
22
  viewPreview = true;
29
- intervalId && clearInterval(intervalId);
23
+ flow = flowStateToFlow($flowStateStore, flow);
30
24
  let newFlow = tab == 'upto' ? truncateFlow(flow) : setInputTransformFromArgs(extractStep(flow), args);
31
25
  jobId = await runFlowPreview(args, newFlow);
32
- jobs = [];
33
- intervalId = setInterval(loadJob, 1000);
34
26
  sendUserToast(`started preview ${truncateRev(jobId, 10)}`);
35
27
  }
36
28
  function truncateFlow(flow) {
@@ -41,35 +33,20 @@ function truncateFlow(flow) {
41
33
  function extractStep(flow) {
42
34
  const localFlow = JSON.parse(JSON.stringify(flow));
43
35
  localFlow.value.modules = flow.value.modules.slice(i, i + 1);
44
- localFlow.schema = schemas[i];
36
+ localFlow.schema = schema;
45
37
  return localFlow;
46
38
  }
47
39
  function setInputTransformFromArgs(flow, args) {
48
- let input_transform = {};
40
+ let input_transforms = {};
49
41
  Object.entries(args).forEach(([key, value]) => {
50
- input_transform[key] = {
42
+ input_transforms[key] = {
51
43
  type: 'static',
52
44
  value: value
53
45
  };
54
46
  });
55
- flow.value.modules[0].input_transform = input_transform;
47
+ flow.value.modules[0].input_transforms = input_transforms;
56
48
  return flow;
57
49
  }
58
- async function loadJob() {
59
- try {
60
- job = await JobService.getJob({ workspace: $workspaceStore, id: jobId });
61
- if (job?.type == 'CompletedJob') {
62
- //only CompletedJob has success property
63
- clearInterval(intervalId);
64
- }
65
- }
66
- catch (err) {
67
- sendUserToast(err, true);
68
- }
69
- }
70
- onDestroy(() => {
71
- intervalId && clearInterval(intervalId);
72
- });
73
50
  </script>
74
51
 
75
52
  <button
@@ -88,41 +65,43 @@ onDestroy(() => {
88
65
 
89
66
  {#if viewPreview}
90
67
  {#if i != flow.value.modules.length}
91
- <Tabs
92
- tabs={[
93
- ['upto', uptoText],
94
- ['justthis', 'preview just this step']
95
- ]}
96
- bind:tab
97
- />
98
- {/if}
99
- <div class="my-2" />
100
- {#if tab == 'upto'}
101
- <RunForm
102
- runnable={truncateFlow(flow)}
103
- runAction={(_, args) => runPreview(args)}
104
- schedulable={false}
105
- buttonText={uptoText}
106
- detailed={false}
107
- bind:args
108
- />
109
- {:else}
110
- <RunForm
111
- runnable={extractStep(flow)}
112
- runAction={(_, args) => runPreview(args)}
113
- schedulable={false}
114
- buttonText="Preview just this step"
115
- detailed={false}
116
- args={stepArgs}
117
- />
68
+ <div class="mt-2">
69
+ <Tabs bind:selected={tab}>
70
+ <Tab value="upto">{uptoText}</Tab>
71
+ <Tab value="justthis">Preview just this step</Tab>
72
+ <svelte:fragment slot="content">
73
+ <TabContent value="upto">
74
+ <RunForm
75
+ runnable={truncateFlow(flow)}
76
+ runAction={(_, args) => runPreview(args)}
77
+ schedulable={false}
78
+ buttonText={uptoText}
79
+ detailed={false}
80
+ bind:args
81
+ />
82
+ </TabContent>
83
+ <TabContent value="justthis">
84
+ <RunForm
85
+ runnable={extractStep(flow)}
86
+ runAction={(_, args) => runPreview(args)}
87
+ schedulable={false}
88
+ buttonText="Preview just this step"
89
+ detailed={false}
90
+ args={stepArgs}
91
+ />
92
+ </TabContent>
93
+ </svelte:fragment>
94
+ </Tabs>
95
+ </div>
118
96
  {/if}
119
97
 
120
- {#if job}
98
+ {#if jobId}
121
99
  <div class="w-full flex justify-center">
122
- <FlowStatusViewer {job} bind:jobs />
100
+ <FlowStatusViewer
101
+ {jobId}
102
+ on:jobsLoaded={(e) => mapJobResultsToFlowState(e.detail, tab, i)}
103
+ root={true}
104
+ />
123
105
  </div>
124
- {#if `result` in job}
125
- <FlowJobResult {job} />
126
- {/if}
127
106
  {/if}
128
107
  {/if}
@@ -1,19 +1,15 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { Schema } from '../common';
3
- import { type Flow } from '../gen';
4
- import type { FlowMode } from './flows/flowStore';
3
+ import type { Flow } from '../gen';
5
4
  declare const __propDef: {
6
5
  props: {
7
6
  i: number;
8
7
  flow: Flow;
9
- schemas?: Schema[] | undefined;
10
- mode: FlowMode;
8
+ schema: Schema;
11
9
  args?: Record<string, any> | undefined;
12
10
  runPreview?: ((args: any) => Promise<void>) | undefined;
13
11
  };
14
12
  events: {
15
- change: CustomEvent<any>;
16
- } & {
17
13
  [evt: string]: CustomEvent<any>;
18
14
  };
19
15
  slots: {};
@@ -1,68 +1,83 @@
1
- <script>import { Job, JobService } from '../gen';
1
+ <script>import { JobService } from '../gen';
2
2
  import { workspaceStore } from '../stores';
3
- import { sendUserToast, truncateRev } from '../utils';
4
- import { faClose } from '@fortawesome/free-solid-svg-icons';
3
+ import { faClose, faPlay } from '@fortawesome/free-solid-svg-icons';
5
4
  import { Button } from 'flowbite-svelte';
6
5
  import { createEventDispatcher, onDestroy } from 'svelte';
7
6
  import Icon from 'svelte-awesome';
8
- import FlowJobResult from './FlowJobResult.svelte';
7
+ import { flowStateStore, flowStateToFlow } from './flows/flowState';
8
+ import { mapJobResultsToFlowState } from './flows/flowStateUtils';
9
9
  import { flowStore } from './flows/flowStore';
10
10
  import { runFlowPreview } from './flows/utils';
11
11
  import FlowStatusViewer from './FlowStatusViewer.svelte';
12
12
  import SchemaForm from './SchemaForm.svelte';
13
- const dispatch = createEventDispatcher();
14
13
  export let args = {};
15
- let intervalId;
16
- let job;
17
- let jobs = [];
18
- let jobId;
14
+ let jobId = undefined;
19
15
  let isValid = false;
20
- $: dispatch('change', jobs);
16
+ let intervalState = 'idle';
17
+ $: newFlow = flowStateToFlow($flowStateStore, $flowStore);
18
+ $: steps = newFlow?.value.modules.length ?? 0;
19
+ const dispatch = createEventDispatcher();
21
20
  export async function runPreview(args) {
22
- intervalId && clearInterval(intervalId);
23
- jobId = await runFlowPreview(args, $flowStore);
24
- jobs = [];
25
- intervalId = setInterval(loadJob, 1000);
26
- sendUserToast(`started preview ${truncateRev(jobId, 10)}`);
27
- }
28
- async function loadJob() {
29
- try {
30
- job = await JobService.getJob({ workspace: $workspaceStore, id: jobId });
31
- if (job?.type == 'CompletedJob') {
32
- clearInterval(intervalId);
33
- }
34
- }
35
- catch (err) {
36
- sendUserToast(err, true);
37
- }
21
+ jobId = await runFlowPreview(args, newFlow);
22
+ intervalState = 'running';
38
23
  }
39
24
  onDestroy(() => {
40
- intervalId && clearInterval(intervalId);
25
+ intervalState = 'done';
41
26
  });
42
27
  </script>
43
28
 
44
- <div class="flex flex-col space-y-4 h-screen bg-white">
45
- <div class="flex flex-col space-y-4 p-6 border-b-2 overflow-y-auto grow">
46
- <div class="flex justify-between">
47
- <h3 class="text-lg leading-6 font-bold text-gray-900">Flow Preview</h3>
29
+ <div class="flex divide-y flex-col space-y-2 h-screen bg-white p-6 w-full">
30
+ <div class="flex justify-between">
31
+ <div class="flex flex-row justify-center items-center">
32
+ <div class="flex justify-center p-2 w-8 h-8 bg-blue-200 rounded-lg mr-2">
33
+ <Icon data={faPlay} scale={1} class="text-blue-500" />
34
+ </div>
48
35
 
49
- <Button color="alternative" on:click={() => dispatch('close')}>
50
- <Icon data={faClose} />
51
- </Button>
36
+ <h3 class="text-lg leading-6 font-bold text-gray-900">Flow preview</h3>
52
37
  </div>
38
+ <Button color="alternative" on:click={() => dispatch('close')}>
39
+ <Icon data={faClose} />
40
+ </Button>
41
+ </div>
42
+ <div class="max-h-80 overflow-y-auto">
53
43
  <SchemaForm schema={$flowStore.schema} bind:isValid bind:args />
54
44
  </div>
55
- <Button disabled={!isValid} class="blue-button mx-4" on:click={() => runPreview(args)} size="md">
56
- Preview
57
- </Button>
45
+ {#if intervalState === 'running'}
46
+ <Button
47
+ disabled={!isValid}
48
+ color="red"
49
+ on:click={async () => {
50
+ intervalState = 'canceled'
51
+ try {
52
+ jobId &&
53
+ (await JobService.cancelQueuedJob({
54
+ workspace: $workspaceStore ?? '',
55
+ id: jobId,
56
+ requestBody: {}
57
+ }))
58
+ } catch {}
59
+ jobId = undefined
60
+ }}
61
+ size="md"
62
+ >
63
+ Cancel
64
+ </Button>
65
+ {:else}
66
+ <Button disabled={!isValid} class="blue-button" on:click={() => runPreview(args)} size="md">
67
+ {`Run${intervalState === 'done' ? ' again' : ''}`}
68
+ </Button>
69
+ {/if}
70
+
58
71
  <div class="h-full overflow-y-auto mb-16 grow">
59
- {#if job}
60
- <div class="w-full">
61
- <FlowStatusViewer {job} bind:jobs />
62
- </div>
63
- {#if `result` in job}
64
- <FlowJobResult {job} />
65
- {/if}
72
+ {#if jobId}
73
+ <FlowStatusViewer
74
+ {jobId}
75
+ on:jobsLoaded={(e) => {
76
+ intervalState = 'done'
77
+ mapJobResultsToFlowState(e.detail, 'upto', steps - 1)
78
+ }}
79
+ root={true}
80
+ />
66
81
  {/if}
67
82
  </div>
68
83
  </div>
@@ -6,7 +6,6 @@ declare const __propDef: {
6
6
  };
7
7
  events: {
8
8
  close: CustomEvent<any>;
9
- change: CustomEvent<any>;
10
9
  } & {
11
10
  [evt: string]: CustomEvent<any>;
12
11
  };
@@ -1,218 +1,118 @@
1
- <script>import { scriptPathToHref, truncateRev } from '../utils';
2
- import { faHourglassHalf, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
3
- import Icon from 'svelte-awesome';
4
- import { check } from 'svelte-awesome/icons';
5
- import { CompletedJob, FlowStatusModule, Job, JobService, QueuedJob } from '../gen';
1
+ <script>import { JobService } from '../gen';
6
2
  import { workspaceStore } from '../stores';
7
3
  import FlowJobResult from './FlowJobResult.svelte';
8
- import JobStatus from './JobStatus.svelte';
9
- export let job;
10
- export let jobs = [];
11
- export let fullyRetrieved = -1;
12
- let lastJobid;
4
+ import FlowPreviewStatus from './preview/FlowPreviewStatus.svelte';
5
+ import { Button } from 'flowbite-svelte';
6
+ import Icon from 'svelte-awesome';
7
+ import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
8
+ import { createEventDispatcher } from 'svelte';
9
+ import { onDestroy } from 'svelte';
10
+ const dispatch = createEventDispatcher();
11
+ export let jobId;
12
+ export let root = false;
13
+ export let forloopJobIds = undefined;
14
+ export let jobResult = {
15
+ job: undefined,
16
+ innerJobs: [],
17
+ loopJobs: []
18
+ };
13
19
  let forloop_selected = '';
14
- let pres = {};
15
- async function loadResults() {
16
- if (!('success' in job)) {
17
- const mods = job?.flow_status?.modules;
18
- if (mods) {
19
- let i = mods?.findIndex((x) => x.type == FlowStatusModule.type.IN_PROGRESS);
20
- if (i != -1) {
21
- let last = mods[i];
22
- jobs[i] = await JobService.getJob({
23
- workspace: $workspaceStore ?? '',
24
- id: last.job ?? ''
25
- });
26
- jobs = jobs;
27
- pres[i]?.scroll({ top: pres[i]?.scrollHeight, behavior: 'smooth' });
28
- }
29
- }
20
+ let timeout;
21
+ async function loadJobInProgress() {
22
+ const job = await JobService.getJob({
23
+ workspace: $workspaceStore ?? '',
24
+ id: jobId ?? ''
25
+ });
26
+ jobResult.job = job;
27
+ jobResult = jobResult;
28
+ if (job?.type !== 'CompletedJob') {
29
+ timeout = setTimeout(() => loadJobInProgress(), 500);
30
30
  }
31
- if (job.id != lastJobid) {
32
- lastJobid = job.id;
33
- jobs = [];
34
- fullyRetrieved = -1;
31
+ else if (root) {
32
+ dispatch('jobsLoaded', jobResult);
35
33
  }
36
- job?.flow_status?.modules?.forEach(async (x, i) => {
37
- if ((i > fullyRetrieved && x.type == FlowStatusModule.type.SUCCESS) ||
38
- x.type == FlowStatusModule.type.FAILURE) {
39
- if (x.forloop_jobs) {
40
- const forloop_jobs = [];
41
- for (let j of x.forloop_jobs) {
42
- forloop_jobs.push(await JobService.getCompletedJob({ workspace: $workspaceStore, id: j }));
43
- }
44
- jobs[i] = forloop_jobs;
45
- }
46
- else {
47
- jobs[i] = await JobService.getCompletedJob({ workspace: $workspaceStore, id: x.job });
48
- }
49
- jobs = jobs;
50
- fullyRetrieved = i;
51
- }
52
- });
53
34
  }
54
- function toJob(x) {
55
- return x;
56
- }
57
- function toCompletedJob(x) {
58
- return x;
59
- }
60
- function toCompletedJobs(x) {
61
- return x;
35
+ $: hasModules =
36
+ jobResult.job &&
37
+ Array.isArray(jobResult.job?.raw_flow?.modules) &&
38
+ jobResult.job?.raw_flow?.modules.length > 1;
39
+ function updateJobId() {
40
+ if (jobId !== jobResult.job?.id) {
41
+ loadJobInProgress();
42
+ }
62
43
  }
63
- $: $workspaceStore && job && loadResults();
44
+ $: jobId && updateJobId();
45
+ onDestroy(() => {
46
+ timeout && clearTimeout(timeout);
47
+ });
64
48
  </script>
65
49
 
66
- <div class="flow-root w-full p-6">
67
- <div class="flex ">
68
- {#if job}
69
- <div class="flex-col">
70
- <a href="/run/{job?.id}" class="font-medium text-blue-600">
71
- {truncateRev(job?.id ?? '', 10)}
72
- </a>
50
+ {#if jobResult.job}
51
+ <div class="flow-root w-full space-y-4">
52
+ <h3 class="text-md leading-6 font-bold text-gray-900 border-b pb-2">Preview results</h3>
53
+ <FlowPreviewStatus job={jobResult.job} />
54
+ {#if `result` in jobResult.job}
55
+ <FlowJobResult job={jobResult.job} />
56
+ {:else if jobResult.job.logs}
57
+ <div class="text-xs p-4 bg-gray-50 overflow-auto max-h-80 border">
58
+ <pre class="w-full">{jobResult.job.logs}</pre>
73
59
  </div>
74
60
  {/if}
75
- </div>
76
- <JobStatus {job} />
77
61
 
78
- <p class="text-gray-500 mb-6 w-full text-center">
79
- Step
80
- <span class="font-medium text-gray-900">
81
- {Math.min((job?.flow_status?.step ?? 0) + 1, job?.raw_flow?.modules.length ?? 0)}
82
- </span>
83
- out of <span class="font-medium text-gray-900">{job?.raw_flow?.modules.length}</span>
84
- <span class="mt-4" />
85
- </p>
62
+ {#if Array.isArray(forloopJobIds) && forloopJobIds?.length > 0 && Array.isArray(jobResult.loopJobs)}
63
+ <h3 class="text-md leading-6 font-bold text-gray-900 border-b mb-4">
64
+ Loop results ({forloopJobIds.length} items)
65
+ </h3>
66
+ {#each forloopJobIds as loopJobId, j}
67
+ <Button
68
+ color={forloop_selected == loopJobId ? 'dark' : 'light'}
69
+ class="flex justify-between w-full"
70
+ on:click={() => {
71
+ if (forloop_selected == loopJobId) {
72
+ forloop_selected = ''
73
+ } else {
74
+ forloop_selected = loopJobId
75
+ }
76
+ }}
77
+ >
78
+ Iteration: #{j}: {loopJobId}
86
79
 
87
- <ul class="w-full">
88
- {#each job?.raw_flow?.modules ?? [] as mod, i}
89
- <li class="w-full">
90
- <div class="relative w-full">
91
- {#if i < (job?.raw_flow?.modules ?? []).length - 1}
92
- <span
93
- class="absolute top-4 left-4 -ml-px h-full w-0.5 bg-gray-200"
94
- aria-hidden="true"
95
- />
96
- {/if}
97
- <div class="relative flex space-x-3">
98
- <div>
99
- {#if job.flow_status?.modules[i].type == FlowStatusModule.type.SUCCESS}
100
- <span
101
- class="h-8 w-8 rounded-full bg-green-600 flex items-center justify-center ring-8 ring-white"
102
- >
103
- <Icon
104
- class="text-white"
105
- data={check}
106
- scale={0.8}
107
- label="Job completed successfully"
108
- />
109
- </span>
110
- {:else if job.flow_status?.modules[i].type == FlowStatusModule.type.FAILURE}
111
- <span
112
- class="h-8 w-8 rounded-full bg-red-600 flex items-center justify-center ring-8 ring-white"
113
- >
114
- <Icon class="text-white" data={faTimes} scale={0.8} label="Job failed" />
115
- </span>
116
- {:else if job.flow_status?.modules[i].type == FlowStatusModule.type.IN_PROGRESS}
117
- <span
118
- class="h-8 w-8 rounded-full bg-yellow-500 flex items-center justify-center ring-8 ring-white"
119
- >
120
- <Icon
121
- class="text-white animate-spin"
122
- data={faSpinner}
123
- scale={1}
124
- label="Job failed"
125
- />
126
- </span>
127
- {:else}
128
- <span
129
- class="h-8 w-8 rounded-full bg-gray-400 flex items-center justify-center ring-8 ring-white"
130
- >
131
- <Icon class="text-white" data={faHourglassHalf} scale={1} label="Job failed" />
132
- </span>
133
- {/if}
134
- </div>
135
- <div class="min-w-0 flex-1 pt-1.5 flex justify-between space-x-4 w-full">
136
- <div class="w-full">
137
- <p class="text-sm text-gray-500">
138
- {#if mod.value.type == 'script'}
139
- Script at path <a
140
- target="_blank"
141
- href={scriptPathToHref(mod.value.path ?? '')}
142
- class="font-medium text-gray-900">{mod.value.path}</a
143
- >
144
- {/if}
145
- </p>
146
- </div>
147
- <div class="text-right text-sm whitespace-nowrap text-gray-500">
148
- {job.flow_status?.modules[i].type}
149
- <div class=" max-h-40 overflow-y-auto">
150
- {#if job.flow_status?.modules[i].forloop_jobs}
151
- {#each job.flow_status?.modules[i].forloop_jobs ?? [] as job}
152
- <div class="flex flex-col">
153
- <a href="/run/{job}" class="font-medium text-blue-600">
154
- {truncateRev(job ?? '', 10)}
155
- </a>
156
- </div>
157
- {/each}
158
- {:else if job.flow_status?.modules[i].job}
159
- <a
160
- href="/run/{job.flow_status?.modules[i].job}"
161
- class="font-medium text-blue-600"
162
- >
163
- {truncateRev(job.flow_status?.modules[i].job ?? '', 10)}
164
- </a>
165
- {/if}
166
- </div>
167
- </div>
168
- </div>
169
- </div>
170
- {#if jobs[i]}
171
- {#if Array.isArray(jobs[i])}
172
- <div class="flex flex-col mt-2 space-y-2 max-h-60 overflow-y-auto shadow-inner">
173
- {#each toCompletedJobs(jobs[i]) as job, i}
174
- <button
175
- class="underline text-blue-600 hover:text-blue-700"
176
- class:text-red-600={!job.success}
177
- on:click={() => {
178
- if (forloop_selected == job.id) {
179
- forloop_selected = ''
180
- } else {
181
- forloop_selected = job.id
182
- }
183
- }}
184
- >Iteration: #{i}: {job.id} {forloop_selected == job.id ? '(-)' : '(+)'}</button
185
- >
186
- {#if forloop_selected == job.id}
187
- <svelte:self {job} />
188
- {#if `result` in job}
189
- <FlowJobResult {job} />
190
- {/if}
191
- {/if}
192
- {/each}
193
- </div>
194
- {:else if toJob(jobs[i]).type == 'CompletedJob'}
195
- <FlowJobResult job={toCompletedJob(jobs[i])} />
196
- {:else if jobs[i]}
197
- {#if toJob(jobs[i])?.raw_flow}
198
- <div class="border-2">
199
- <h2>Forloop current iteration</h2>
200
- <svelte:self job={jobs[i]} />
201
- </div>
202
- {:else}
203
- <div class="max-w-2xl mt-2 h-full">
204
- <pre
205
- bind:this={pres[i]}
206
- class="break-all p-4 relative h-full mx-2 bg-gray-50 text-xs max-h-40 overflow-y-auto border">{toJob(
207
- jobs[i]
208
- ).logs ?? ''}
209
- </pre>
210
- </div>
211
- {/if}
212
- {/if}
213
- {/if}
80
+ <Icon
81
+ class="ml-2"
82
+ data={forloop_selected == loopJobId ? faChevronUp : faChevronDown}
83
+ scale={0.8}
84
+ />
85
+ </Button>
86
+ <div class="border p-6" class:hidden={forloop_selected != loopJobId}>
87
+ <svelte:self jobId={loopJobId} bind:jobResult={jobResult.loopJobs[j]} />
214
88
  </div>
215
- </li>
216
- {/each}
217
- </ul>
218
- </div>
89
+ {/each}
90
+ {:else if hasModules && Array.isArray(jobResult.innerJobs)}
91
+ <ul class="w-full">
92
+ <h3 class="text-md leading-6 font-bold text-gray-900 border-b mb-4 py-2">
93
+ Detailed results
94
+ </h3>
95
+
96
+ {#each jobResult.job?.flow_status?.modules ?? [] as module, i}
97
+ <p class="text-gray-500 mb-6 w-full ">
98
+ Step
99
+ <span class="font-medium text-gray-900"> {i + 1} </span> out of
100
+ <span class="font-medium text-gray-900">{jobResult.job?.raw_flow?.modules.length}</span>
101
+ </p>
102
+
103
+ {#if ['InProgress', 'Success', 'Error'].includes(module.type)}
104
+ <li class="w-full border p-6 space-y-2">
105
+ <svelte:self
106
+ jobId={module.job}
107
+ bind:jobResult={jobResult.innerJobs[i]}
108
+ forloopJobIds={module.forloop_jobs}
109
+ />
110
+ </li>
111
+ {/if}
112
+ {/each}
113
+ </ul>
114
+ {/if}
115
+ </div>
116
+ {:else}
117
+ No script selected
118
+ {/if}
@@ -1,12 +1,15 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
- import { CompletedJob, Job, QueuedJob } from '../gen';
2
+ import type { JobResult } from './flows/flowStateUtils';
3
3
  declare const __propDef: {
4
4
  props: {
5
- job: QueuedJob | CompletedJob;
6
- jobs?: (Job | Job[] | undefined)[] | undefined;
7
- fullyRetrieved?: number | undefined;
5
+ jobId: string;
6
+ root?: boolean | undefined;
7
+ forloopJobIds?: string[] | undefined;
8
+ jobResult?: JobResult | undefined;
8
9
  };
9
10
  events: {
11
+ jobsLoaded: CustomEvent<any>;
12
+ } & {
10
13
  [evt: string]: CustomEvent<any>;
11
14
  };
12
15
  slots: {};