windmill-components 1.13.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 (184) hide show
  1. package/LICENSE +661 -0
  2. package/common.d.ts +29 -0
  3. package/components/ArgInfo.svelte +48 -0
  4. package/components/ArgInput.svelte +277 -0
  5. package/components/AutosizedTextarea.svelte +34 -0
  6. package/components/Badge.svelte +12 -0
  7. package/components/Button.svelte +82 -0
  8. package/components/ButtonAndDropdown.svelte +25 -0
  9. package/components/CenteredPage.svelte +5 -0
  10. package/components/ChevronButton.svelte +21 -0
  11. package/components/DisplayResult.svelte +101 -0
  12. package/components/Dropdown.svelte +108 -0
  13. package/components/Editor.svelte +370 -0
  14. package/components/FieldHeader.svelte +21 -0
  15. package/components/FlowBuilder.svelte +202 -0
  16. package/components/FlowEditor.svelte +95 -0
  17. package/components/FlowPreview.svelte +141 -0
  18. package/components/FlowStatusViewer.svelte +137 -0
  19. package/components/GroupModal.svelte +90 -0
  20. package/components/IconedResourceType.svelte +32 -0
  21. package/components/InviteGlobalUser.svelte +56 -0
  22. package/components/InviteUser.svelte +48 -0
  23. package/components/ItemPicker.svelte +58 -0
  24. package/components/JobStatus.svelte +38 -0
  25. package/components/Modal.svelte +94 -0
  26. package/components/ModuleStep.svelte +64 -0
  27. package/components/Multiselect.svelte +327 -0
  28. package/components/ObjectResourceInput.svelte +62 -0
  29. package/components/ObjectTypeNarrowing.svelte +25 -0
  30. package/components/PageHeader.svelte +29 -0
  31. package/components/Password.svelte +45 -0
  32. package/components/Path.svelte +129 -0
  33. package/components/RadioButton.svelte +117 -0
  34. package/components/Required.svelte +11 -0
  35. package/components/ResourceEditor.svelte +260 -0
  36. package/components/ResourcePicker.svelte +21 -0
  37. package/components/ResourceTypePicker.svelte +71 -0
  38. package/components/RunForm.svelte +127 -0
  39. package/components/SchemaEditor.svelte +221 -0
  40. package/components/SchemaForm.svelte +166 -0
  41. package/components/SchemaModal.svelte +160 -0
  42. package/components/SchemaViewer.svelte +76 -0
  43. package/components/ScriptBuilder.svelte +293 -0
  44. package/components/ScriptEditor.svelte +669 -0
  45. package/components/ScriptPicker.svelte +110 -0
  46. package/components/ScriptSchema.svelte +71 -0
  47. package/components/ShareModal.svelte +135 -0
  48. package/components/SharedBadge.svelte +54 -0
  49. package/components/StringTypeNarrowing.svelte +101 -0
  50. package/components/Switch.svelte +61 -0
  51. package/components/TableCustom.svelte +39 -0
  52. package/components/TableSimple.svelte +66 -0
  53. package/components/Tabs.svelte +21 -0
  54. package/components/Tooltip.svelte +93 -0
  55. package/components/VariableEditor.svelte +159 -0
  56. package/components/icons/DbIcon.svelte +12 -0
  57. package/components/icons/Mail.svelte +62 -0
  58. package/components/icons/Mysql.svelte +77 -0
  59. package/components/icons/PostgresIcon.svelte +57 -0
  60. package/components/icons/Slack.svelte +26 -0
  61. package/gen/core/ApiError.d.ts +8 -0
  62. package/gen/core/ApiRequestOptions.d.ts +13 -0
  63. package/gen/core/ApiResult.d.ts +7 -0
  64. package/gen/core/CancelablePromise.d.ts +26 -0
  65. package/gen/core/OpenAPI.d.ts +16 -0
  66. package/gen/core/request.d.ts +13 -0
  67. package/gen/index.d.ts +59 -0
  68. package/gen/models/AuditLog.d.ts +32 -0
  69. package/gen/models/CompletedJob.d.ts +48 -0
  70. package/gen/models/ContextualVariable.d.ts +5 -0
  71. package/gen/models/CreateResource.d.ts +6 -0
  72. package/gen/models/CreateVariable.d.ts +6 -0
  73. package/gen/models/CreateWorkspace.d.ts +6 -0
  74. package/gen/models/EditResource.d.ts +5 -0
  75. package/gen/models/EditResourceType.d.ts +4 -0
  76. package/gen/models/EditSchedule.d.ts +7 -0
  77. package/gen/models/EditVariable.d.ts +6 -0
  78. package/gen/models/EditWorkspaceUser.d.ts +3 -0
  79. package/gen/models/Flow.d.ts +13 -0
  80. package/gen/models/FlowModule.d.ts +6 -0
  81. package/gen/models/FlowModuleValue.d.ts +10 -0
  82. package/gen/models/FlowPreview.d.ts +7 -0
  83. package/gen/models/FlowStatus.d.ts +6 -0
  84. package/gen/models/FlowStatusModule.d.ts +15 -0
  85. package/gen/models/FlowValue.d.ts +5 -0
  86. package/gen/models/GlobalUserInfo.d.ts +14 -0
  87. package/gen/models/Group.d.ts +6 -0
  88. package/gen/models/InputTransform.d.ts +12 -0
  89. package/gen/models/Job.d.ts +11 -0
  90. package/gen/models/ListableVariable.d.ts +8 -0
  91. package/gen/models/Login.d.ts +4 -0
  92. package/gen/models/MainArgSignature.d.ts +14 -0
  93. package/gen/models/NewSchedule.d.ts +9 -0
  94. package/gen/models/NewToken.d.ts +4 -0
  95. package/gen/models/NewUser.d.ts +5 -0
  96. package/gen/models/Preview.d.ts +13 -0
  97. package/gen/models/QueuedJob.d.ts +47 -0
  98. package/gen/models/Resource.d.ts +8 -0
  99. package/gen/models/ResourceType.d.ts +6 -0
  100. package/gen/models/Schedule.d.ts +13 -0
  101. package/gen/models/Script.d.ts +29 -0
  102. package/gen/models/ScriptArgs.d.ts +1 -0
  103. package/gen/models/TruncatedToken.d.ts +7 -0
  104. package/gen/models/User.d.ts +10 -0
  105. package/gen/models/UserWorkspaceList.d.ts +8 -0
  106. package/gen/models/WorkerPing.d.ts +8 -0
  107. package/gen/models/Workspace.d.ts +6 -0
  108. package/gen/models/WorkspaceInvite.d.ts +5 -0
  109. package/gen/services/AdminService.d.ts +35 -0
  110. package/gen/services/AuditService.d.ts +37 -0
  111. package/gen/services/FlowService.d.ts +82 -0
  112. package/gen/services/GranularAclService.d.ts +42 -0
  113. package/gen/services/GroupService.d.ts +94 -0
  114. package/gen/services/JobService.d.ts +217 -0
  115. package/gen/services/ResourceService.d.ts +116 -0
  116. package/gen/services/ScheduleService.d.ts +73 -0
  117. package/gen/services/ScriptService.d.ts +165 -0
  118. package/gen/services/SettingsService.d.ts +15 -0
  119. package/gen/services/UserService.d.ts +211 -0
  120. package/gen/services/VariableService.d.ts +66 -0
  121. package/gen/services/WorkerService.d.ts +15 -0
  122. package/gen/services/WorkspaceService.d.ts +137 -0
  123. package/infer.d.ts +2 -0
  124. package/lib/components/ArgInfo.svelte.d.ts +16 -0
  125. package/lib/components/ArgInput.svelte.d.ts +37 -0
  126. package/lib/components/AutosizedTextarea.svelte.d.ts +19 -0
  127. package/lib/components/Badge.svelte.d.ts +20 -0
  128. package/lib/components/Button.svelte.d.ts +23 -0
  129. package/lib/components/ButtonAndDropdown.svelte.d.ts +23 -0
  130. package/lib/components/CenteredPage.svelte.d.ts +23 -0
  131. package/lib/components/ChevronButton.svelte.d.ts +19 -0
  132. package/lib/components/DisplayResult.svelte.d.ts +16 -0
  133. package/lib/components/Dropdown.svelte.d.ts +22 -0
  134. package/lib/components/Editor.svelte.d.ts +38 -0
  135. package/lib/components/FieldHeader.svelte.d.ts +23 -0
  136. package/lib/components/FlowBuilder.svelte.d.ts +18 -0
  137. package/lib/components/FlowEditor.svelte.d.ts +19 -0
  138. package/lib/components/FlowPreview.svelte.d.ts +21 -0
  139. package/lib/components/FlowStatusViewer.svelte.d.ts +18 -0
  140. package/lib/components/GroupModal.svelte.d.ts +17 -0
  141. package/lib/components/IconedResourceType.svelte.d.ts +19 -0
  142. package/lib/components/InviteGlobalUser.svelte.d.ts +19 -0
  143. package/lib/components/InviteUser.svelte.d.ts +19 -0
  144. package/lib/components/ItemPicker.svelte.d.ts +24 -0
  145. package/lib/components/JobStatus.svelte.d.ts +17 -0
  146. package/lib/components/Modal.svelte.d.ts +28 -0
  147. package/lib/components/ModuleStep.svelte.d.ts +26 -0
  148. package/lib/components/Multiselect.svelte.d.ts +33 -0
  149. package/lib/components/ObjectResourceInput.svelte.d.ts +17 -0
  150. package/lib/components/ObjectTypeNarrowing.svelte.d.ts +16 -0
  151. package/lib/components/PageHeader.svelte.d.ts +20 -0
  152. package/lib/components/Password.svelte.d.ts +18 -0
  153. package/lib/components/Path.svelte.d.ts +26 -0
  154. package/lib/components/RadioButton.svelte.d.ts +21 -0
  155. package/lib/components/Required.svelte.d.ts +17 -0
  156. package/lib/components/ResourceEditor.svelte.d.ts +22 -0
  157. package/lib/components/ResourcePicker.svelte.d.ts +17 -0
  158. package/lib/components/ResourceTypePicker.svelte.d.ts +19 -0
  159. package/lib/components/RunForm.svelte.d.ts +22 -0
  160. package/lib/components/SchemaEditor.svelte.d.ts +22 -0
  161. package/lib/components/SchemaForm.svelte.d.ts +23 -0
  162. package/lib/components/SchemaModal.svelte.d.ts +44 -0
  163. package/lib/components/SchemaViewer.svelte.d.ts +17 -0
  164. package/lib/components/ScriptBuilder.svelte.d.ts +20 -0
  165. package/lib/components/ScriptEditor.svelte.d.ts +28 -0
  166. package/lib/components/ScriptPicker.svelte.d.ts +21 -0
  167. package/lib/components/ScriptSchema.svelte.d.ts +22 -0
  168. package/lib/components/ShareModal.svelte.d.ts +21 -0
  169. package/lib/components/SharedBadge.svelte.d.ts +17 -0
  170. package/lib/components/StringTypeNarrowing.svelte.d.ts +18 -0
  171. package/lib/components/Switch.svelte.d.ts +31 -0
  172. package/lib/components/TableCustom.svelte.d.ts +25 -0
  173. package/lib/components/TableSimple.svelte.d.ts +24 -0
  174. package/lib/components/Tabs.svelte.d.ts +20 -0
  175. package/lib/components/Tooltip.svelte.d.ts +20 -0
  176. package/lib/components/VariableEditor.svelte.d.ts +21 -0
  177. package/lib/components/icons/DbIcon.svelte.d.ts +17 -0
  178. package/lib/components/icons/Mail.svelte.d.ts +17 -0
  179. package/lib/components/icons/Mysql.svelte.d.ts +17 -0
  180. package/lib/components/icons/PostgresIcon.svelte.d.ts +17 -0
  181. package/lib/components/icons/Slack.svelte.d.ts +17 -0
  182. package/package.json +110 -0
  183. package/stores.d.ts +19 -0
  184. package/utils.d.ts +60 -0
@@ -0,0 +1,669 @@
1
+ <script>import { JobService, Job, CompletedJob, VariableService, ResourceService, ScriptService } from '../../gen';
2
+ import { sendUserToast, emptySchema, displayDate } from '../../utils';
3
+ import { fade } from 'svelte/transition';
4
+ import Icon from 'svelte-awesome';
5
+ import { faCheck, faChevronDown, faChevronUp, faExclamationTriangle, faMagic, faSearch, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
6
+ import Editor from './Editor.svelte';
7
+ import Tooltip from './Tooltip.svelte';
8
+ import { onDestroy, onMount } from 'svelte';
9
+ import { userStore, workspaceStore } from '../../stores';
10
+ import TableCustom from './TableCustom.svelte';
11
+ import { check } from 'svelte-awesome/icons';
12
+ import Modal from './Modal.svelte';
13
+ import { Highlight } from 'svelte-highlight';
14
+ import { json, python, typescript } from 'svelte-highlight/languages';
15
+ import github from 'svelte-highlight/styles/github';
16
+ import ItemPicker from './ItemPicker.svelte';
17
+ import VariableEditor from './VariableEditor.svelte';
18
+ import ResourceEditor from './ResourceEditor.svelte';
19
+ import { inferArgs } from '../../infer';
20
+ // @ts-ignore
21
+ import { VSplitPane } from 'svelte-split-pane';
22
+ import SchemaForm from './SchemaForm.svelte';
23
+ import DisplayResult from './DisplayResult.svelte';
24
+ // Exported
25
+ export let schema = emptySchema();
26
+ export let code;
27
+ export let path;
28
+ export let lang;
29
+ // Control Editor layout
30
+ export let viewPreview = true;
31
+ export let previewTab = 'logs';
32
+ let websocketAlive = { pyright: false, black: false, deno: false };
33
+ // Internal state
34
+ let editor;
35
+ // Preview args input
36
+ let args = {};
37
+ let isValid = true;
38
+ // Preview
39
+ let previewIsLoading = false;
40
+ let previewIntervalId;
41
+ let previewJob;
42
+ let pastPreviews = [];
43
+ let modalViewer;
44
+ let modalViewerTitle = '';
45
+ let modalViewerContent;
46
+ let modalViewerMode = 'logs';
47
+ let variablePicker;
48
+ let resourcePicker;
49
+ let scriptPicker;
50
+ let variableEditor;
51
+ let resourceEditor;
52
+ let syncIteration = 0;
53
+ let ITERATIONS_BEFORE_SLOW_REFRESH = 100;
54
+ let lastSave;
55
+ $: lastSave = localStorage.getItem(path ?? 'last_save');
56
+ export function getEditor() {
57
+ return editor;
58
+ }
59
+ export async function runPreview() {
60
+ try {
61
+ if (previewIntervalId) {
62
+ clearInterval(previewIntervalId);
63
+ }
64
+ if (previewIsLoading && previewJob) {
65
+ JobService.cancelQueuedJob({
66
+ workspace: $workspaceStore,
67
+ id: previewJob.id,
68
+ requestBody: {}
69
+ });
70
+ }
71
+ previewIsLoading = true;
72
+ const previewId = await JobService.runScriptPreview({
73
+ workspace: $workspaceStore,
74
+ requestBody: {
75
+ path,
76
+ content: editor.getCode(),
77
+ args: args,
78
+ language: lang
79
+ }
80
+ });
81
+ previewJob = undefined;
82
+ loadPreviewJob(previewId);
83
+ syncIteration = 0;
84
+ previewIntervalId = setInterval(() => {
85
+ syncer(previewId);
86
+ }, 500);
87
+ //TODO fetch preview, every x time, until it's completed
88
+ }
89
+ catch (err) {
90
+ previewIsLoading = false;
91
+ sendUserToast(`Could not run preview: ${err} `, true);
92
+ }
93
+ }
94
+ async function loadPastPreviews() {
95
+ pastPreviews = await JobService.listCompletedJobs({
96
+ workspace: $workspaceStore,
97
+ jobKinds: 'preview',
98
+ createdBy: $userStore?.username,
99
+ scriptPathExact: path
100
+ });
101
+ }
102
+ async function loadPreviewJob(id) {
103
+ try {
104
+ if (previewJob && `running` in previewJob) {
105
+ let previewJobUpdates = await JobService.getJobUpdates({
106
+ workspace: $workspaceStore,
107
+ id,
108
+ running: previewJob.running,
109
+ logOffset: previewJob.logs?.length ?? 0
110
+ });
111
+ if (previewJobUpdates.new_logs) {
112
+ previewJob.logs = (previewJob.logs ?? '').concat(previewJobUpdates.new_logs);
113
+ }
114
+ if ((previewJobUpdates.running ?? false) || (previewJobUpdates.completed ?? false)) {
115
+ previewJob = await JobService.getJob({ workspace: $workspaceStore, id });
116
+ }
117
+ }
118
+ else {
119
+ previewJob = await JobService.getJob({ workspace: $workspaceStore, id });
120
+ }
121
+ if (previewJob?.type === 'CompletedJob') {
122
+ //only CompletedJob has success property
123
+ clearInterval(previewIntervalId);
124
+ previewIsLoading = false;
125
+ loadPastPreviews();
126
+ }
127
+ }
128
+ catch (err) {
129
+ console.error(err);
130
+ }
131
+ }
132
+ async function inferSchema() {
133
+ let isDefault = [];
134
+ Object.entries(args).forEach(([k, v]) => {
135
+ if (schema.properties[k].default == v) {
136
+ isDefault.push(k);
137
+ }
138
+ });
139
+ await inferArgs(lang, editor.getCode(), schema);
140
+ schema = schema;
141
+ isDefault.forEach((key) => (args[key] = schema.properties[key].default));
142
+ for (const key of Object.keys(args)) {
143
+ if (schema.properties[key] == undefined) {
144
+ delete args[key];
145
+ }
146
+ }
147
+ }
148
+ function syncer(id) {
149
+ if (syncIteration > ITERATIONS_BEFORE_SLOW_REFRESH) {
150
+ loadPreviewJob(id);
151
+ if (previewIntervalId) {
152
+ clearInterval(previewIntervalId);
153
+ previewIntervalId = setInterval(() => loadPreviewJob(id), 5000);
154
+ }
155
+ }
156
+ else {
157
+ syncIteration++;
158
+ loadPreviewJob(id);
159
+ }
160
+ }
161
+ async function loadVariables() {
162
+ let r = [];
163
+ const variables = (await VariableService.listVariable({ workspace: $workspaceStore ?? 'NO_W' })).map((x) => {
164
+ return { name: x.path, ...x };
165
+ });
166
+ const rvariables = await VariableService.listContextualVariables({
167
+ workspace: $workspaceStore ?? 'NO_W'
168
+ });
169
+ r = r.concat(variables).concat(rvariables);
170
+ return r;
171
+ }
172
+ async function loadScripts() {
173
+ return await ScriptService.listScripts({ workspace: $workspaceStore ?? 'NO_W' });
174
+ }
175
+ let syncCode;
176
+ onMount(() => {
177
+ syncCode = setInterval(() => {
178
+ const newCode = editor?.getCode();
179
+ if (newCode && code != newCode) {
180
+ code = editor.getCode();
181
+ }
182
+ }, 3000);
183
+ });
184
+ onDestroy(() => {
185
+ if (editor) {
186
+ code = editor.getCode();
187
+ }
188
+ if (previewIntervalId) {
189
+ clearInterval(previewIntervalId);
190
+ }
191
+ if (syncCode) {
192
+ clearInterval(syncCode);
193
+ }
194
+ });
195
+ </script>
196
+
197
+ <svelte:head>
198
+ {@html github}
199
+ </svelte:head>
200
+
201
+ <ItemPicker
202
+ bind:this={scriptPicker}
203
+ pickCallback={async (path, _) => {
204
+ modalViewerMode = 'code'
205
+ modalViewerTitle = 'Script ' + path
206
+ modalViewerContent = (
207
+ await ScriptService.getScriptByPath({
208
+ workspace: $workspaceStore ?? '',
209
+ path
210
+ })
211
+ ).content
212
+ modalViewer.openModal()
213
+ }}
214
+ closeOnClick={false}
215
+ itemName="script"
216
+ extraField="summary"
217
+ loadItems={loadScripts}
218
+ />
219
+
220
+ <Modal bind:this={modalViewer}>
221
+ <div slot="title">{modalViewerTitle}</div>
222
+ <div slot="content">
223
+ {#if modalViewerMode === 'result'}
224
+ <Highlight language={json} code={JSON.stringify(modalViewerContent, null, 4)} />
225
+ {:else if modalViewerMode === 'logs'}
226
+ <pre class="overflow-x-auto break-all relative h-full m-2 text-xs bg-white shadow-inner">
227
+ {modalViewerContent}
228
+ </pre>
229
+ {:else if modalViewerMode === 'code'}
230
+ {#if lang == 'python3'}
231
+ <Highlight language={python} code={modalViewerContent} />
232
+ {:else if lang == 'deno'}
233
+ <Highlight language={typescript} code={modalViewerContent} />
234
+ {/if}
235
+ {/if}
236
+ </div></Modal
237
+ >
238
+
239
+ <ItemPicker
240
+ bind:this={variablePicker}
241
+ pickCallback={(path, name) => {
242
+ if (!path) {
243
+ if (lang == 'deno') {
244
+ getEditor().insertAtCursor(`Deno.env.get('${name}')`)
245
+ } else {
246
+ if (!getEditor().getCode().includes('import os')) {
247
+ getEditor().insertAtBeginning('import os\n')
248
+ }
249
+ getEditor().insertAtCursor(`os.environ.get("${name}")`)
250
+ }
251
+ sendUserToast(`${name} inserted at cursor`)
252
+ } else {
253
+ if (lang == 'deno') {
254
+ if (!getEditor().getCode().includes('import * as wmill from')) {
255
+ getEditor().insertAtBeginning(
256
+ `import * as wmill from 'https://deno.land/x/windmill@v${__pkg__.version}/index.ts'\n`
257
+ )
258
+ }
259
+ getEditor().insertAtCursor(`(await wmill.getVariable('${path}'))`)
260
+ } else {
261
+ if (!getEditor().getCode().includes('import wmill')) {
262
+ getEditor().insertAtBeginning('import wmill\n')
263
+ }
264
+ getEditor().insertAtCursor(`wmill.get_variable("${path}")`)
265
+ }
266
+ sendUserToast(`${name} inserted at cursor`)
267
+ }
268
+ }}
269
+ itemName="Variable"
270
+ extraField="name"
271
+ loadItems={loadVariables}
272
+ >
273
+ <div slot="submission" class="flex flex-row">
274
+ <div class="text-xs mr-2 align-middle">
275
+ The variable you were looking for does not exist yet?
276
+ </div>
277
+ <button
278
+ class="default-button-secondary"
279
+ type="button"
280
+ on:click={() => {
281
+ variableEditor.initNew()
282
+ }}
283
+ >
284
+ Create a new variable
285
+ </button>
286
+ </div>
287
+ </ItemPicker>
288
+
289
+ <ItemPicker
290
+ bind:this={resourcePicker}
291
+ pickCallback={(path, _) => {
292
+ if (lang == 'deno') {
293
+ if (!getEditor().getCode().includes('import * as wmill from')) {
294
+ getEditor().insertAtBeginning(
295
+ `import * as wmill from 'https://deno.land/x/windmill@v${__pkg__.version}/index.ts'\n`
296
+ )
297
+ }
298
+ getEditor().insertAtCursor(`(await wmill.getResource('${path})')`)
299
+ } else {
300
+ if (!getEditor().getCode().includes('import wmill')) {
301
+ getEditor().insertAtBeginning('import wmill\n')
302
+ }
303
+ getEditor().insertAtCursor(`wmill.get_resource("${path}")`)
304
+ }
305
+ sendUserToast(`${path} inserted at cursor`)
306
+ }}
307
+ itemName="Resource"
308
+ extraField="resource_type"
309
+ loadItems={async () =>
310
+ await ResourceService.listResource({ workspace: $workspaceStore ?? 'NO_W' })}
311
+ >
312
+ <div slot="submission" class="flex flex-row">
313
+ <div class="text-xs mr-2 align-middle">
314
+ The resource you were looking for does not exist yet?
315
+ </div>
316
+ <button
317
+ class="default-button-secondary"
318
+ type="button"
319
+ on:click={() => {
320
+ resourceEditor.initNew()
321
+ }}
322
+ >
323
+ Create a new resource
324
+ </button>
325
+ </div>
326
+ </ItemPicker>
327
+
328
+ <ResourceEditor bind:this={resourceEditor} on:refresh={resourcePicker.openModal} />
329
+
330
+ <VariableEditor bind:this={variableEditor} on:create={variablePicker.openModal} />
331
+
332
+ <VSplitPane
333
+ class="h-full"
334
+ topPanelSize={viewPreview ? '75%' : '90%'}
335
+ downPanelSize={viewPreview ? '25%' : '10%'}
336
+ updateCallback={() => {
337
+ if (!viewPreview) {
338
+ viewPreview = true
339
+ }
340
+ }}
341
+ >
342
+ <top slot="top">
343
+ <div class="flex flex-col h-full">
344
+ <div class="header">
345
+ <div class="flex flex-row justify-around w-full">
346
+ <button
347
+ class="default-button-secondary font-semibold py-px mr-2 text-xs align-middle max-h-8"
348
+ on:click|stopPropagation={() => {
349
+ variablePicker.openModal()
350
+ }}
351
+ >Variable picker <Icon data={faSearch} scale={0.7} />
352
+ </button>
353
+
354
+ <button
355
+ class="default-button-secondary font-semibold py-px text-xs mr-2 align-middle max-h-8"
356
+ on:click|stopPropagation={() => {
357
+ resourcePicker.openModal()
358
+ }}
359
+ >Resource picker <Icon data={faSearch} scale={0.7} />
360
+ </button>
361
+ <button
362
+ class="default-button-secondary font-semibold py-px text-xs mr-2 align-middle max-h-8"
363
+ on:click|stopPropagation={() => {
364
+ scriptPicker.openModal()
365
+ }}
366
+ >Script explorer <Icon data={faSearch} scale={0.7} />
367
+ </button>
368
+
369
+ <button
370
+ class="default-button-secondary py-px max-h-8 text-xs"
371
+ on:click|stopPropagation={() => {
372
+ editor.reloadWebsocket()
373
+ }}
374
+ >
375
+ Reload assistants (status: {#if lang == 'deno'}<span
376
+ class={websocketAlive.deno ? 'text-green-600' : 'text-red-600'}>deno</span
377
+ >{:else if lang == 'python3'}<span
378
+ class={websocketAlive.pyright ? 'text-green-600' : 'text-red-600'}>pyright</span
379
+ >
380
+ <span class={websocketAlive.black ? 'text-green-600' : 'text-red-600'}>
381
+ black</span
382
+ >{/if})
383
+ </button>
384
+ </div>
385
+ </div>
386
+ <div class="flex-1 overflow-hidden">
387
+ <Editor
388
+ {code}
389
+ bind:websocketAlive
390
+ bind:this={editor}
391
+ cmdEnterAction={() => {
392
+ runPreview()
393
+ viewPreview = true
394
+ }}
395
+ formatAction={() => {
396
+ code = getEditor().getCode()
397
+ localStorage.setItem(path ?? 'last_save', code)
398
+ }}
399
+ class="h-full"
400
+ deno={lang == 'deno'}
401
+ automaticLayout={true}
402
+ />
403
+ </div>
404
+ </div>
405
+ </top>
406
+ <down slot="down" class="flex flex-col h-full">
407
+ <div class="header">
408
+ <div
409
+ class="flex flex-row w-full cursor-pointer h-full"
410
+ on:click={() => {
411
+ viewPreview = !viewPreview
412
+ }}
413
+ >
414
+ <div class="flex flex-row items-baseline">
415
+ <div class="font-base py-0 mr-6">
416
+ Preview <Tooltip
417
+ ><span class="font-normal"
418
+ >Test your script by running a preview, passing inputs as if you were a user</span
419
+ ></Tooltip
420
+ >
421
+ <span style="min-width: 15px; display: inline-block;">
422
+ {#if previewIsLoading}
423
+ <span transition:fade>
424
+ <Icon class="animate-spin" data={faSpinner} scale={0.8} />
425
+ </span>
426
+ {/if}
427
+ </span>
428
+ </div>
429
+ <button
430
+ class="font-semibold my-0 py-0 h-full {previewTab === 'input'
431
+ ? 'underline drop-shadow-md'
432
+ : ''}"
433
+ on:click|stopPropagation={() => {
434
+ previewTab = 'input'
435
+ viewPreview = true
436
+ inferSchema()
437
+ }}
438
+ >
439
+ Inputs
440
+ </button>
441
+ <button
442
+ class="font-semibold my-0 py-0 h-full ml-3 {previewTab === 'logs' ? 'underline' : ''}"
443
+ on:click|stopPropagation={() => {
444
+ previewTab = 'logs'
445
+ viewPreview = true
446
+ }}
447
+ >
448
+ Logs
449
+ </button>
450
+ <button
451
+ class="font-semibold my-0 py-0 h-full ml-3 {previewTab === 'output' ? 'underline' : ''}"
452
+ on:click|stopPropagation={() => {
453
+ previewTab = 'output'
454
+ viewPreview = true
455
+ }}
456
+ >
457
+ Result
458
+ </button>
459
+ <button
460
+ class="font-semibold my-0 py-0 h-full ml-3 {previewTab === 'history'
461
+ ? 'underline'
462
+ : ''}"
463
+ on:click|stopPropagation={() => {
464
+ if (pastPreviews.length == 0) {
465
+ loadPastPreviews()
466
+ }
467
+ previewTab = 'history'
468
+ viewPreview = true
469
+ }}
470
+ >
471
+ History
472
+ </button>
473
+ <button
474
+ class="font-semibold my-0 py-0 h-full ml-3 {previewTab === 'last_save'
475
+ ? 'underline'
476
+ : ''}"
477
+ on:click|stopPropagation={() => {
478
+ previewTab = 'last_save'
479
+ viewPreview = true
480
+ }}
481
+ >
482
+ Local save
483
+ </button>
484
+ </div>
485
+ <div class="flex flex-row-reverse grow">
486
+ <button
487
+ class="mb-1 ml-2"
488
+ on:click|stopPropagation={() => {
489
+ viewPreview = !viewPreview
490
+ }}
491
+ ><Icon data={viewPreview ? faChevronDown : faChevronUp} scale={0.7} />
492
+ </button>
493
+ <button
494
+ class="default-button py-px text-xs mx-2 align-middle max-h-8"
495
+ on:click|stopPropagation={() => {
496
+ runPreview()
497
+ viewPreview = true
498
+ previewTab = 'logs'
499
+ }}
500
+ >Run preview
501
+ </button>
502
+ <div class="text-xs text-gray-700 min-w-max mx-2">
503
+ Shortcuts: <Tooltip>
504
+ Cmd/Ctrl+S: autoformat code and overwrite local save <br />
505
+ Cmd/Ctrl+Enter: run preview</Tooltip
506
+ >
507
+ </div>
508
+ </div>
509
+ </div>
510
+ </div>
511
+ <div class="preview flex-1 overflow-hidden p-3">
512
+ {#if previewTab === 'logs'}
513
+ <pre
514
+ class="break-all relative h-full mx-2">{#if previewJob && previewJob.logs}{previewJob.logs}
515
+ {:else if previewIsLoading}Starting preview ...
516
+ {:else}No preview is available yet{/if}
517
+ </pre>
518
+ {:else if previewTab === 'input'}
519
+ <div class="break-all relative h-full font-sans">
520
+ <div class="p-2 w-full">
521
+ <button class="default-button w-full" on:click|stopPropagation={inferSchema}
522
+ ><Icon data={faMagic} scale={0.7} /><span class="pl-1"
523
+ >Infer schema from main parameters</span
524
+ >
525
+ </button>
526
+ </div>
527
+ <div class="flex flex-row items-baseline text-2xs text-gray-700 p-2 ml-8 italic">
528
+ {#if isValid}
529
+ <Icon data={faCheck} class="text-green-600 mr-1" scale={0.6} /> The current preview input
530
+ matches requirements defined in arguments
531
+ {:else}
532
+ <Icon data={faExclamationTriangle} class="text-yellow-500 mr-1" scale={0.6} />The
533
+ current preview input doesn't match requirements defined in arguments. Are you sure?{/if}
534
+ </div>
535
+ <div class="sm:px-8">
536
+ <SchemaForm {schema} bind:args bind:isValid />
537
+ </div>
538
+ </div>
539
+ {:else if previewTab === 'output'}
540
+ <pre class="overflow-x-auto break-all relative h-full">
541
+ {#if previewJob && 'result' in previewJob && previewJob.result}
542
+ <DisplayResult result={previewJob.result} />
543
+ {:else if previewIsLoading}
544
+ Running...
545
+ {:else}
546
+ No output is available yet
547
+ {/if}
548
+ </pre>
549
+ {:else if previewTab === 'last_save'}
550
+ <div class="m-4">
551
+ {#if lastSave}
552
+ <a
553
+ href="#last_save"
554
+ class="text-xs"
555
+ on:click={() => {
556
+ modalViewerContent = lastSave
557
+ modalViewerMode = 'code'
558
+ modalViewer.openModal()
559
+ }}>View last local save for path {path}</a
560
+ >
561
+ {:else}No local save{/if}
562
+ </div>
563
+ {:else if previewTab === 'history'}
564
+ <TableCustom paginated={false}>
565
+ <tr slot="header-row">
566
+ <th class="text-xs">id</th>
567
+ <th class="text-xs">created at</th>
568
+ <th class="text-xs">success</th>
569
+ <th class="text-xs">result</th>
570
+ <th class="text-xs">code</th>
571
+ <th class="text-xs">logs</th>
572
+ </tr>
573
+ <tbody slot="body">
574
+ {#each pastPreviews as { id, created_at, success, result, logs }}
575
+ <tr class="">
576
+ <td class="text-xs"
577
+ ><a class="pr-3" href="/run/{id}" target="_blank">{id.substring(30)}</a></td
578
+ >
579
+ <td class="text-xs">{displayDate(created_at)}</td>
580
+ <td class="text-xs">
581
+ {#if success}
582
+ <Icon class="text-green-600" data={check} scale={0.6} />
583
+ {:else}
584
+ <Icon class="text-red-700" data={faTimes} scale={0.6} />
585
+ {/if}
586
+ </td>
587
+ <td class="text-xs">
588
+ <a
589
+ href="#result"
590
+ class="text-xs"
591
+ on:click={() => {
592
+ modalViewerContent = result
593
+ modalViewerMode = 'result'
594
+ modalViewer.openModal()
595
+ }}>{JSON.stringify(result).substring(0, 30)}...</a
596
+ ></td
597
+ >
598
+ <td class="text-xs"
599
+ ><a
600
+ href="#code"
601
+ class="text-xs"
602
+ on:click={async () => {
603
+ modalViewerContent = (
604
+ await JobService.getCompletedJob({
605
+ workspace: $workspaceStore ?? 'NO_W',
606
+ id
607
+ })
608
+ ).raw_code
609
+ modalViewerMode = 'code'
610
+ modalViewer.openModal()
611
+ }}
612
+ >View code
613
+ </a></td
614
+ >
615
+ <td
616
+ ><a
617
+ href="#logs"
618
+ class="text-xs"
619
+ on:click={async () => {
620
+ modalViewerContent = (
621
+ await JobService.getCompletedJob({
622
+ workspace: $workspaceStore ?? 'NO_W',
623
+ id
624
+ })
625
+ ).logs
626
+ modalViewerMode = 'logs'
627
+ modalViewer.openModal()
628
+ }}
629
+ >View logs
630
+ </a></td
631
+ >
632
+ </tr>
633
+ {/each}
634
+ </tbody>
635
+ </TableCustom>
636
+ {/if}
637
+ </div>
638
+ </down>
639
+ </VSplitPane>
640
+
641
+ <style>
642
+ .header {
643
+ max-height: 28px;
644
+ border-width: 1px;
645
+ padding-left: 0.5rem;
646
+ padding-right: 0.5rem;
647
+ padding-top: 0.25rem;
648
+ padding-bottom: 0.25rem;
649
+ border-left-width: 1px;
650
+ border-right-width: 1px;
651
+ --tw-bg-opacity: 1;
652
+ background-color: rgb(243 244 246 / var(--tw-bg-opacity));
653
+ font-size: 0.75rem;
654
+ line-height: 1rem;
655
+ --tw-text-opacity: 1;
656
+ color: rgb(55 65 81 / var(--tw-text-opacity));
657
+ }
658
+
659
+ .preview {
660
+ border-width: 1px;
661
+ overflow: auto;
662
+ border-left-width: 1px;
663
+ border-right-width: 1px;
664
+ --tw-bg-opacity: 1;
665
+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
666
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
667
+ font-size: 0.75rem;
668
+ line-height: 1rem;
669
+ }</style>