windmill-components 1.405.0 → 1.405.5

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 (106) hide show
  1. package/package/assets/app.css +20 -0
  2. package/package/components/AppConnectLightweightResourcePicker.svelte +66 -0
  3. package/package/components/AppConnectLightweightResourcePicker.svelte.d.ts +21 -0
  4. package/package/components/ArgInput.svelte +6 -2
  5. package/package/components/ArgInput.svelte.d.ts +1 -0
  6. package/package/components/CustomPopover.svelte +1 -1
  7. package/package/components/DisplayResult.svelte +1 -1
  8. package/package/components/FlowBuilder.svelte +2 -0
  9. package/package/components/FlowBuilder.svelte.d.ts +1 -0
  10. package/package/components/FlowInputViewer.svelte +25 -0
  11. package/package/components/FlowInputViewer.svelte.d.ts +19 -0
  12. package/package/components/FlowJobResult.svelte +8 -1
  13. package/package/components/FlowJobResult.svelte.d.ts +1 -0
  14. package/package/components/FlowMetadata.svelte +2 -2
  15. package/package/components/FlowStatusViewer.svelte +3 -1
  16. package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
  17. package/package/components/FlowStatusViewerInner.svelte +4 -1
  18. package/package/components/FlowViewer.svelte +2 -21
  19. package/package/components/LightweightResourcePicker.svelte +34 -30
  20. package/package/components/LogViewer.svelte +4 -3
  21. package/package/components/LogViewer.svelte.d.ts +1 -0
  22. package/package/components/ManualPopover.svelte +1 -1
  23. package/package/components/ObjectResourceInput.svelte +5 -2
  24. package/package/components/ObjectResourceInput.svelte.d.ts +2 -0
  25. package/package/components/Popover.svelte +1 -1
  26. package/package/components/Portal.svelte +7 -8
  27. package/package/components/Portal.svelte.d.ts +3 -7
  28. package/package/components/QueueMetricsDrawer.svelte +368 -3
  29. package/package/components/QueueMetricsDrawer.svelte.d.ts +2 -0
  30. package/package/components/ResourceEditor.svelte +4 -5
  31. package/package/components/ResourcePicker.svelte +14 -9
  32. package/package/components/ResourcePicker.svelte.d.ts +1 -0
  33. package/package/components/RunForm.svelte +1 -1
  34. package/package/components/SavedInputs.svelte +2 -2
  35. package/package/components/ScriptVersionHistory.svelte +54 -59
  36. package/package/components/TestConnection.svelte +1 -0
  37. package/package/components/TimeAgo.svelte +5 -6
  38. package/package/components/TimeAgo.svelte.d.ts +1 -1
  39. package/package/components/apps/components/buttons/AppButton.svelte +1 -1
  40. package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +1 -1
  41. package/package/components/apps/components/inputs/AppMultiSelect.svelte +1 -1
  42. package/package/components/apps/components/inputs/AppMultiSelectV2.svelte +1 -1
  43. package/package/components/apps/components/layout/AppDrawer.svelte +1 -1
  44. package/package/components/apps/components/layout/AppModal.svelte +1 -1
  45. package/package/components/apps/editor/AppEditor.svelte +11 -3
  46. package/package/components/apps/editor/GridEditor.svelte +57 -4
  47. package/package/components/apps/editor/GridEditor.svelte.d.ts +8 -0
  48. package/package/components/apps/editor/GridEditorMenu.svelte +1 -1
  49. package/package/components/apps/editor/SubGridEditor.svelte +82 -3
  50. package/package/components/apps/editor/SubGridEditor.svelte.d.ts +16 -0
  51. package/package/components/apps/editor/appUtils.d.ts +19 -2
  52. package/package/components/apps/editor/appUtils.js +103 -7
  53. package/package/components/apps/editor/component/Component.svelte +36 -8
  54. package/package/components/apps/editor/component/Component.svelte.d.ts +3 -1
  55. package/package/components/apps/editor/contextPanel/components/OutputHeader.svelte +1 -1
  56. package/package/components/apps/svelte-grid/Grid.svelte +235 -12
  57. package/package/components/apps/svelte-grid/Grid.svelte.d.ts +7 -7
  58. package/package/components/apps/svelte-grid/MoveResize.svelte +104 -11
  59. package/package/components/apps/svelte-grid/MoveResize.svelte.d.ts +7 -0
  60. package/package/components/apps/svelte-grid/utils/item.d.ts +4 -1
  61. package/package/components/apps/svelte-grid/utils/item.js +2 -3
  62. package/package/components/apps/svelte-select/lib/ConditionalPortal.svelte +1 -1
  63. package/package/components/apps/svelte-select/lib/ConditionalPortalGlobal.svelte +1 -1
  64. package/package/components/common/button/ButtonDropdown.svelte +1 -1
  65. package/package/components/common/drawer/ConditionalPortal.svelte +1 -1
  66. package/package/components/common/menu/MenuV2.svelte +1 -1
  67. package/package/components/common/modal/AlwaysMountedModal.svelte +1 -1
  68. package/package/components/common/popup/PopupV2.svelte +1 -1
  69. package/package/components/copilot/StepGenQuick.svelte +3 -2
  70. package/package/components/copilot/StepGenQuick.svelte.d.ts +1 -0
  71. package/package/components/details/Menu.svelte +1 -1
  72. package/package/components/flows/CreateActionsApp.svelte +1 -1
  73. package/package/components/flows/FlowEditor.svelte +2 -1
  74. package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
  75. package/package/components/flows/FlowHistory.svelte +10 -195
  76. package/package/components/flows/FlowHistory.svelte.d.ts +0 -1
  77. package/package/components/flows/FlowHistoryInner.svelte +200 -0
  78. package/package/components/flows/FlowHistoryInner.svelte.d.ts +19 -0
  79. package/package/components/flows/content/FlowEditorPanel.svelte +2 -1
  80. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
  81. package/package/components/flows/content/FlowInput.svelte +66 -58
  82. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
  83. package/package/components/flows/content/FlowModuleScript.svelte +1 -1
  84. package/package/components/flows/map/FlowModuleSchemaMap.svelte +3 -2
  85. package/package/components/flows/map/InsertModuleButton.svelte +1 -1
  86. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte +1 -1
  87. package/package/components/graph/model.d.ts +1 -0
  88. package/package/components/icons/WindmillIcon.svelte +119 -105
  89. package/package/components/icons/store.d.ts +4 -0
  90. package/package/components/icons/store.js +1 -0
  91. package/package/components/multiselect/MultiSelectWrapper.svelte +1 -1
  92. package/package/components/propertyPicker/ObjectViewer.svelte +1 -1
  93. package/package/components/runs/RunRow.svelte +3 -7
  94. package/package/components/schema/FlowPropertyEditor.svelte +1 -0
  95. package/package/components/search/GlobalSearchModal.svelte +1 -1
  96. package/package/script_helpers.d.ts +37 -38
  97. package/package/script_helpers.js +100 -38
  98. package/package.json +23 -1
  99. package/package/init_scripts/python_failure_module.d.ts +0 -2
  100. package/package/init_scripts/python_failure_module.js +0 -8
  101. package/package/init_scripts/python_init_code.d.ts +0 -2
  102. package/package/init_scripts/python_init_code.js +0 -40
  103. package/package/init_scripts/python_init_code_clear.d.ts +0 -2
  104. package/package/init_scripts/python_init_code_clear.js +0 -5
  105. package/package/init_scripts/python_init_code_trigger.d.ts +0 -2
  106. package/package/init_scripts/python_init_code_trigger.js +0 -14
@@ -1,10 +1,4 @@
1
- /**
2
- * Usage: <div use:portal={'css selector'}> or <div use:portal={document.body}>
3
- *
4
- * @param {HTMLElement} el
5
- * @param {HTMLElement|string} target DOM Element or CSS Selector
6
- */
7
- export function portal(el: HTMLElement, target?: HTMLElement | string): {
1
+ export function portal(el: any, options: any): {
8
2
  update: (newTarget: any) => Promise<void>;
9
3
  destroy: () => void;
10
4
  };
@@ -12,6 +6,7 @@ export function portal(el: HTMLElement, target?: HTMLElement | string): {
12
6
  /** @typedef {typeof __propDef.events} PortalEvents */
13
7
  /** @typedef {typeof __propDef.slots} PortalSlots */
14
8
  export default class Portal extends SvelteComponent<{
9
+ name?: any;
15
10
  target?: string | HTMLElement | undefined;
16
11
  }, {
17
12
  [evt: string]: CustomEvent<any>;
@@ -25,6 +20,7 @@ export type PortalSlots = typeof __propDef.slots;
25
20
  import { SvelteComponent } from "svelte";
26
21
  declare const __propDef: {
27
22
  props: {
23
+ name?: any;
28
24
  target?: string | HTMLElement | undefined;
29
25
  };
30
26
  events: {
@@ -1,13 +1,378 @@
1
- <script>import { Drawer, DrawerContent } from './common';
1
+ <script>import { onMount } from 'svelte';
2
+ import { Drawer, DrawerContent, Button } from './common';
2
3
  import QueueMetricsDrawerInner from './QueueMetricsDrawerInner.svelte';
4
+ import { ConfigService } from '../gen';
5
+ import Section from './Section.svelte';
6
+ import { sendUserToast } from '../toast';
7
+ import { Pencil, Trash, Check, PlusCircle, SaveIcon } from 'lucide-svelte';
8
+ import Tooltip from './Tooltip.svelte';
9
+ import { enterpriseLicense } from '../stores';
3
10
  let drawer;
4
11
  export function openDrawer() {
5
12
  drawer?.openDrawer();
6
13
  }
14
+ let alerts = [];
15
+ let configName = 'alert__job_queue_waiting';
16
+ let originalAlerts = [];
17
+ let newTag = '';
18
+ let editingIndex = -1;
19
+ let changesMade = false;
20
+ let removedAlerts = [];
21
+ let stagedNewAlert = false;
22
+ let workerTags = [];
23
+ let filteredTags = [];
24
+ $: removedAlerts;
25
+ onMount(async () => {
26
+ await fetchConfig();
27
+ workerTags = await fetchWorkerTags();
28
+ });
29
+ async function fetchConfig() {
30
+ try {
31
+ const response = (await ConfigService.getConfig({ name: configName }));
32
+ alerts = response.alerts || [];
33
+ originalAlerts = JSON.parse(JSON.stringify(alerts));
34
+ }
35
+ catch (error) {
36
+ console.error('Failed to fetch config:', error);
37
+ }
38
+ }
39
+ async function fetchWorkerTags() {
40
+ try {
41
+ const response = await ConfigService.listConfigs();
42
+ const workerTagsSet = new Set();
43
+ response.forEach((config) => {
44
+ if (config.name.startsWith('worker__') && Array.isArray(config.config?.worker_tags)) {
45
+ config?.config?.worker_tags.forEach((tag) => workerTagsSet.add(tag));
46
+ }
47
+ });
48
+ return Array.from(workerTagsSet);
49
+ }
50
+ catch (error) {
51
+ console.error('Failed to fetch worker tags:', error);
52
+ return [];
53
+ }
54
+ }
55
+ function startEditing(index) {
56
+ editingIndex = index;
57
+ updateWorkerTags();
58
+ }
59
+ function saveAlert(index) {
60
+ const newAlert = alerts[index];
61
+ if (newAlert.tags_to_monitor.length === 0) {
62
+ sendUserToast('Please add at least one tag before saving.', true);
63
+ return;
64
+ }
65
+ if (newAlert.jobs_num_threshold <= 0 ||
66
+ newAlert.alert_cooldown_seconds <= 0 ||
67
+ newAlert.alert_time_threshold_seconds <= 0) {
68
+ sendUserToast('All numeric values must be strictly positive.', true);
69
+ return;
70
+ }
71
+ const alertExists = originalAlerts.some((alert) => originalAlerts.indexOf(alert) !== index &&
72
+ JSON.stringify(alert.tags_to_monitor.sort()) ===
73
+ JSON.stringify(newAlert.tags_to_monitor.sort()));
74
+ if (alertExists) {
75
+ sendUserToast('An identical alert already exists.', true);
76
+ return;
77
+ }
78
+ editingIndex = -1;
79
+ changesMade = JSON.stringify(alerts) !== JSON.stringify(originalAlerts);
80
+ stagedNewAlert = false;
81
+ }
82
+ function stageDeleteAlert(index) {
83
+ const alert = alerts[index];
84
+ removedAlerts = [...removedAlerts, alert];
85
+ changesMade =
86
+ removedAlerts.length > 0 || JSON.stringify(alerts) !== JSON.stringify(originalAlerts);
87
+ }
88
+ function filterTags(event) {
89
+ const input = event.target.value;
90
+ filteredTags = workerTags.filter((tag) => tag.toLowerCase().includes(input.toLowerCase()));
91
+ }
92
+ function addTag(alertIndex, tag) {
93
+ if (workerTags.includes(tag) && !alerts[alertIndex].tags_to_monitor.includes(tag)) {
94
+ alerts[alertIndex].tags_to_monitor = [...alerts[alertIndex].tags_to_monitor, tag];
95
+ }
96
+ newTag = '';
97
+ filteredTags = [];
98
+ }
99
+ function removeTag(alertIndex, tag) {
100
+ alerts[alertIndex].tags_to_monitor = alerts[alertIndex].tags_to_monitor.filter((t) => t !== tag);
101
+ }
102
+ async function applyConfig() {
103
+ if (stagedNewAlert) {
104
+ sendUserToast('New alert staged. Please save or cancel the changes before applying.', true);
105
+ return;
106
+ }
107
+ try {
108
+ await ConfigService.updateConfig({ name: configName, requestBody: { alerts } });
109
+ sendUserToast('Configuration updated successfully');
110
+ alerts = alerts.filter((alert) => !removedAlerts.includes(alert));
111
+ originalAlerts = JSON.parse(JSON.stringify(alerts));
112
+ removedAlerts = [];
113
+ changesMade = false;
114
+ stagedNewAlert = false;
115
+ }
116
+ catch (error) {
117
+ console.error('Failed to update config:', error);
118
+ }
119
+ }
120
+ async function cancelChanges() {
121
+ alerts = [...alerts, ...removedAlerts];
122
+ alerts = JSON.parse(JSON.stringify(originalAlerts));
123
+ removedAlerts = [];
124
+ editingIndex = -1;
125
+ changesMade = false;
126
+ stagedNewAlert = false;
127
+ }
128
+ function addNewAlert() {
129
+ // alert already being added
130
+ if (stagedNewAlert) {
131
+ return;
132
+ }
133
+ const newAlert = {
134
+ name: 'New Alert',
135
+ tags_to_monitor: [],
136
+ jobs_num_threshold: 3,
137
+ alert_cooldown_seconds: 600,
138
+ alert_time_threshold_seconds: 30
139
+ };
140
+ alerts = [...alerts, newAlert];
141
+ editingIndex = alerts.length - 1;
142
+ stagedNewAlert = true;
143
+ updateWorkerTags();
144
+ }
145
+ async function updateWorkerTags() {
146
+ workerTags = await fetchWorkerTags();
147
+ }
148
+ function addAllTags(alertIndex) {
149
+ alerts[alertIndex].tags_to_monitor = [
150
+ ...new Set([...alerts[alertIndex].tags_to_monitor, ...workerTags])
151
+ ];
152
+ alerts = alerts; // Trigger reactivity
153
+ }
7
154
  </script>
8
155
 
9
- <Drawer bind:this={drawer}>
156
+ <Drawer bind:this={drawer} size="800px">
10
157
  <DrawerContent title="Queue Metrics" on:close={drawer.closeDrawer}>
11
- <QueueMetricsDrawerInner />
158
+ <Section
159
+ label="Queue Alert Settings"
160
+ collapsable={true}
161
+ tooltip="Manage queue alerts for monitoring queue metrics. These alerts will trigger a critical alert notification if the queue metrics are met."
162
+ eeOnly={true}
163
+ >
164
+ {#if $enterpriseLicense}
165
+ {#if changesMade}
166
+ <div class="text-red-600 text-xs whitespace-nowrap pb-2">Non applied changes</div>
167
+ <div class="flex gap-2 pb-2">
168
+ <Button color="blue" size="xs" on:click={applyConfig}>
169
+ <SaveIcon size={16} /> Apply Config
170
+ </Button>
171
+ <Button color="light" size="xs" on:click={cancelChanges}>Cancel</Button>
172
+ </div>
173
+ {/if}
174
+
175
+ {#if alerts.length > 0}
176
+ <div>
177
+ <form on:submit|preventDefault>
178
+ <table class="w-full border-collapse mb-2 text-xs table-auto">
179
+ <thead class="bg-gray-200 text-left text-xs">
180
+ <tr>
181
+ <th class="p-2 min-w-[120px]">
182
+ Name
183
+ <Tooltip
184
+ markdownTooltip="The name of the alert. This will be used in the crticial alert notification and help identify the alert."
185
+ />
186
+ </th>
187
+ <th class="p-2 w-full">
188
+ Queue Tags to Monitor
189
+ <Tooltip markdownTooltip="Queue tags to monitor for this alert." />
190
+ </th>
191
+ <th class="p-2 min-w-[65px]">
192
+ Jobs
193
+ <Tooltip
194
+ markdownTooltip="Number of jobs threshold. An alert will be triggerd if more than this number of jobs are in the queue for at least the time threshold."
195
+ />
196
+ </th>
197
+ <th class="p-2 min-w-[115px]">
198
+ Cooldown (s)
199
+ <Tooltip
200
+ markdownTooltip="Cooldown period in seconds. The cooldown period is the time after an alert is triggered that no new alerts will be triggered."
201
+ />
202
+ </th>
203
+ <th class="p-2 min-w-[105px]">
204
+ Time (s)
205
+ <Tooltip
206
+ markdownTooltip="Time threshold in seconds. An alert will be triggered if more than 'n jobs threshold' have been in the queue for at least this amount of time."
207
+ />
208
+ </th>
209
+ <th class="p-2 min-w-[100px]"> Actions </th>
210
+ </tr>
211
+ </thead>
212
+ <tbody>
213
+ {#each alerts as alert, index}
214
+ <tr
215
+ class:staged-for-deletion={removedAlerts.includes(alert)}
216
+ class:non-interactable={removedAlerts.includes(alert)}
217
+ >
218
+ <td class="border p-2">
219
+ {#if editingIndex === index}
220
+ <input type="text" bind:value={alert.name} class="w-full p-1" />
221
+ {:else}
222
+ {alert.name}
223
+ {/if}
224
+ </td>
225
+ <td class="border p-2">
226
+ {#if editingIndex === index}
227
+ <div class="flex flex-wrap gap-1 mb-2">
228
+ {#each alert.tags_to_monitor as tag}
229
+ <span class="inline-block bg-blue-100 rounded px-2 py-1 text-xs">
230
+ {tag}
231
+ <button
232
+ on:click={() => removeTag(index, tag)}
233
+ aria-label="Remove Tag"
234
+ class="ml-1 text-black text-xs">x</button
235
+ >
236
+ </span>
237
+ {/each}
238
+ </div>
239
+ <div class="flex items-center">
240
+ <input
241
+ type="text"
242
+ bind:value={newTag}
243
+ placeholder="Add tag"
244
+ on:input={(e) => filterTags(e)}
245
+ class="p-1 flex-grow mr-1"
246
+ />
247
+ <button on:click={() => addTag(index, newTag)} aria-label="Add Tag">
248
+ <PlusCircle size={16} />
249
+ </button>
250
+ </div>
251
+ <!-- Add the new "Add All Tags" button here -->
252
+ <button
253
+ on:click={() => addAllTags(index)}
254
+ class="text-xs hover:bg-gray-200 rounded px-2 py-1 mt-1"
255
+ >
256
+ Add All Tags
257
+ </button>
258
+ {#if filteredTags.length > 0}
259
+ <ul class="autocomplete-list">
260
+ {#each filteredTags as tag}
261
+ <li>
262
+ <button type="button" on:click={() => addTag(index, tag)}
263
+ >{tag}</button
264
+ >
265
+ </li>
266
+ {/each}
267
+ </ul>
268
+ {/if}
269
+ {:else}
270
+ <div class="flex flex-wrap gap-1">
271
+ {#each alert.tags_to_monitor as tag}
272
+ <span class="inline-block bg-blue-100 rounded px-2 py-1 text-xs"
273
+ >{tag}</span
274
+ >
275
+ {/each}
276
+ </div>
277
+ {/if}
278
+ </td>
279
+ <td class="border p-2">
280
+ {#if editingIndex === index}
281
+ <input
282
+ type="number"
283
+ bind:value={alert.jobs_num_threshold}
284
+ class="w-full p-1"
285
+ />
286
+ {:else}
287
+ {alert.jobs_num_threshold}
288
+ {/if}
289
+ </td>
290
+ <td class="border p-2">
291
+ {#if editingIndex === index}
292
+ <input
293
+ type="number"
294
+ bind:value={alert.alert_cooldown_seconds}
295
+ class="w-full p-1"
296
+ />
297
+ {:else}
298
+ {alert.alert_cooldown_seconds}
299
+ {/if}
300
+ </td>
301
+ <td class="border p-2">
302
+ {#if editingIndex === index}
303
+ <input
304
+ type="number"
305
+ bind:value={alert.alert_time_threshold_seconds}
306
+ class="w-full p-1"
307
+ />
308
+ {:else}
309
+ {alert.alert_time_threshold_seconds}
310
+ {/if}
311
+ </td>
312
+ <td class="border p-2">
313
+ <div class="flex gap-3 justify-center items-center">
314
+ {#if editingIndex === index}
315
+ <button on:click={() => saveAlert(index)} aria-label="Save">
316
+ <Check size={16} />
317
+ </button>
318
+ {:else}
319
+ <button on:click={() => startEditing(index)} aria-label="Edit">
320
+ <Pencil size={16} />
321
+ </button>
322
+ <button on:click={() => stageDeleteAlert(index)} aria-label="Delete">
323
+ <Trash size={16} />
324
+ </button>
325
+ {/if}
326
+ </div>
327
+ </td>
328
+ </tr>
329
+ {/each}
330
+ </tbody>
331
+ </table>
332
+ </form>
333
+ </div>
334
+ {/if}
335
+
336
+ <!-- Button to Add New Alert at the Bottom of the Table -->
337
+ <div class="flex">
338
+ <Button color="blue" size="xs" on:click={addNewAlert}>
339
+ <PlusCircle size={16} />
340
+ Add New Alert
341
+ </Button>
342
+ </div>
343
+ {:else}
344
+ <p class="text-gray-600 text-sm">
345
+ Queue Metric Alerts are an enterprise feature allowing you to monitor queues for waiting jobs. Please upgrade to access this functionality.
346
+ <a href="https://www.windmill.dev/docs/misc/plans_details" target="_blank" class="text-blue-500 underline">Learn more about our plans.</a>
347
+ </p>
348
+ {/if}
349
+ </Section>
350
+ <div class="p-8">
351
+ <QueueMetricsDrawerInner />
352
+ </div>
12
353
  </DrawerContent>
13
354
  </Drawer>
355
+
356
+ <style>
357
+ .staged-for-deletion {
358
+ background-color: #f8d7da; /* Light red background for staged deletion */
359
+ }
360
+ .non-interactable {
361
+ pointer-events: none; /* Disable pointer events */
362
+ opacity: 0.5; /* Reduce opacity */
363
+ }
364
+ .autocomplete-list {
365
+ border: 1px solid #ccc;
366
+ max-height: 150px;
367
+ overflow-y: auto;
368
+ background-color: white;
369
+ position: absolute;
370
+ z-index: 1000;
371
+ }
372
+ .autocomplete-list li {
373
+ padding: 8px;
374
+ cursor: pointer;
375
+ }
376
+ .autocomplete-list li:hover {
377
+ background-color: #f0f0f0;
378
+ }</style>
@@ -4,6 +4,8 @@ declare const __propDef: {
4
4
  openDrawer?: (() => void) | undefined;
5
5
  };
6
6
  events: {
7
+ submit: SubmitEvent;
8
+ } & {
7
9
  [evt: string]: CustomEvent<any>;
8
10
  };
9
11
  slots: {};
@@ -73,7 +73,7 @@ export async function editResource() {
73
73
  dispatch('refresh', path);
74
74
  }
75
75
  else {
76
- throw Error('Cannot edit undefined resourceToEdit');
76
+ throw Error('Cannot edit undefined resource');
77
77
  }
78
78
  }
79
79
  export async function createResource() {
@@ -214,11 +214,10 @@ function parseTextFileContent() {
214
214
  <Skeleton layout={[[4]]} />
215
215
  {:else if !viewJsonSchema && resourceSchema && resourceSchema?.properties}
216
216
  {#if resourceTypeInfo?.format_extension}
217
- <h5 class="mt-4 inline-flex items-center gap-4 pb-2">
218
- File content ({resourceTypeInfo.format_extension})
219
- </h5>
217
+ <h5 class="mt-4 inline-flex items-center gap-4 pb-2">
218
+ File content ({resourceTypeInfo.format_extension})
219
+ </h5>
220
220
  <div class="h-full w-full border p-1 rounded">
221
-
222
221
  <SimpleEditor
223
222
  autoHeight
224
223
  class="editor"
@@ -101,7 +101,7 @@ let darkMode = false;
101
101
  />
102
102
 
103
103
  <div class="flex flex-col w-full items-start">
104
- <div class="flex flex-row gap-x-1 w-full items-center">
104
+ <div class="flex flex-row w-full items-center">
105
105
  {#if collection?.length > 0}
106
106
  <Select
107
107
  {disabled}
@@ -113,9 +113,11 @@ let darkMode = false;
113
113
  valueSelect = e.detail
114
114
  }}
115
115
  on:clear={() => {
116
+ initialValue = undefined
116
117
  value = undefined
117
118
  valueType = undefined
118
119
  valueSelect = undefined
120
+ dispatch('clear')
119
121
  }}
120
122
  items={collection}
121
123
  class="text-clip grow min-w-0"
@@ -128,14 +130,15 @@ let darkMode = false;
128
130
  {:else if !loading}
129
131
  <div class="text-2xs text-tertiary mr-2">0 found</div>
130
132
  {/if}
131
-
132
133
  {#if !loading}
134
+ <div class="mx-0.5" />
133
135
  {#if value && value != ''}
134
136
  <Button
135
137
  {disabled}
136
138
  color="light"
137
- variant="border"
138
- size="xs"
139
+ variant="contained"
140
+ size="sm"
141
+ btnClasses="w-8 px-0.5 py-1.5"
139
142
  on:click={() => resourceEditor?.initEdit?.(value ?? '')}
140
143
  startIcon={{ icon: Pen }}
141
144
  iconOnly
@@ -147,8 +150,9 @@ let darkMode = false;
147
150
  <Button
148
151
  {disabled}
149
152
  color="light"
150
- variant="border"
151
- size="xs"
153
+ variant="contained"
154
+ size="sm"
155
+ btnClasses="w-8 px-0.5 py-1.5"
152
156
  on:click={() => appConnect?.open?.(rt)}
153
157
  startIcon={{ icon: Plus }}>{rt}</Button
154
158
  >
@@ -158,7 +162,7 @@ let darkMode = false;
158
162
  {disabled}
159
163
  color="light"
160
164
  variant="border"
161
- size="xs"
165
+ size="sm"
162
166
  on:click={() => appConnect?.open?.(resourceType, expressOAuthSetup)}
163
167
  startIcon={{ icon: Plus }}
164
168
  iconOnly={collection?.length > 0}
@@ -170,9 +174,10 @@ let darkMode = false;
170
174
  {/if}
171
175
 
172
176
  <Button
173
- variant="border"
177
+ variant="contained"
174
178
  color="light"
175
- size="xs"
179
+ btnClasses="w-8 px-0.5 py-1.5"
180
+ size="sm"
176
181
  on:click={() => {
177
182
  loadResources(resourceType)
178
183
  }}
@@ -13,6 +13,7 @@ declare const __propDef: {
13
13
  askNewResource?: (() => Promise<void>) | undefined;
14
14
  };
15
15
  events: {
16
+ clear: CustomEvent<any>;
16
17
  change: CustomEvent<any>;
17
18
  } & {
18
19
  [evt: string]: CustomEvent<any>;
@@ -71,7 +71,7 @@ function onArgsChange(args) {
71
71
  <div class="flex items-center gap-2">
72
72
  <span class="text-sm text-tertiary">
73
73
  {#if runnable}
74
- Edited <TimeAgo withDate agoOnlyIfRecent date={runnable.created_at || ''} /> by {runnable.created_by ||
74
+ Edited <TimeAgo agoOnlyIfRecent date={runnable.created_at || ''} /> by {runnable.created_by ||
75
75
  'unknown'}
76
76
  {/if}
77
77
  </span>
@@ -333,7 +333,7 @@ async function loadLargeArgs(id, input, allowLarge) {
333
333
  <div
334
334
  class="whitespace-nowrap col-span-3 !text-tertiary !text-2xs overflow-hidden text-ellipsis flex-shrink text-center"
335
335
  >
336
- <TimeAgo date={i.started_at ?? ''} />
336
+ <TimeAgo noDate date={i.started_at ?? ''} />
337
337
  </div>
338
338
  <div class="col-span-2">
339
339
  <a
@@ -394,7 +394,7 @@ async function loadLargeArgs(id, input, allowLarge) {
394
394
  <div
395
395
  class="whitespace-nowrap col-span-2 !text-tertiary !text-2xs overflow-hidden text-ellipsis flex-shrink text-center"
396
396
  >
397
- <TimeAgo date={i.created_at ?? ''} />
397
+ <TimeAgo noDate date={i.created_at ?? ''} />
398
398
  </div>
399
399
  <div class="col-span-1">
400
400
  <a
@@ -1,5 +1,4 @@
1
1
  <script>import { Pane, Splitpanes } from 'svelte-splitpanes';
2
- import PanelSection from './apps/editor/settingsPanel/common/PanelSection.svelte';
3
2
  import { classNames, emptyString } from '../utils';
4
3
  import { ScriptService } from '../gen';
5
4
  import { workspaceStore } from '../stores';
@@ -52,70 +51,66 @@ let previousHash = undefined;
52
51
 
53
52
  <Splitpanes class="!overflow-visible">
54
53
  <Pane size={20}>
55
- <PanelSection title="Past Versions">
56
- <div class="flex flex-col gap-2 w-full">
57
- {#if !loading}
58
- {#if versions && versions.length > 0}
59
- <div class="flex gap-2 flex-col">
60
- {#each versions ?? [] as version, versionIndex}
61
- <!-- svelte-ignore a11y-click-events-have-key-events -->
62
- <!-- svelte-ignore a11y-no-static-element-interactions -->
63
- <div
64
- class={classNames(
65
- 'border flex gap-1 truncate justify-between flex-row w-full items-center p-2 rounded-md cursor-pointer ',
66
- selectedVersion?.script_hash == version.script_hash
67
- ? 'bg-surface-selected'
68
- : '',
69
- 'hover:bg-surface-hover'
70
- )}
71
- on:click={() => {
72
- selectedVersion = version
73
- selectedVersionIndex = versionIndex
54
+ <div class="flex flex-col gap-2 px-2 pt-2 w-full">
55
+ {#if !loading}
56
+ {#if versions && versions.length > 0}
57
+ <div class="flex gap-2 flex-col">
58
+ {#each versions ?? [] as version, versionIndex}
59
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
60
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
61
+ <div
62
+ class={classNames(
63
+ 'border flex gap-1 truncate justify-between flex-row w-full items-center p-2 rounded-md cursor-pointer ',
64
+ selectedVersion?.script_hash == version.script_hash ? 'bg-surface-selected' : '',
65
+ 'hover:bg-surface-hover'
66
+ )}
67
+ on:click={() => {
68
+ selectedVersion = version
69
+ selectedVersionIndex = versionIndex
74
70
 
75
- if (showDiff && versions && selectedVersionIndex === versions.length - 1) {
76
- showDiff = false
77
- }
71
+ if (showDiff && versions && selectedVersionIndex === versions.length - 1) {
72
+ showDiff = false
73
+ }
78
74
 
79
- const availableVersions = versions?.slice(selectedVersionIndex + 1)
75
+ const availableVersions = versions?.slice(selectedVersionIndex + 1)
80
76
 
81
- if (
82
- previousHash &&
83
- !availableVersions?.find((v) => v.script_hash === previousHash)
84
- ) {
85
- previousHash = availableVersions?.[0]?.script_hash
86
- }
77
+ if (
78
+ previousHash &&
79
+ !availableVersions?.find((v) => v.script_hash === previousHash)
80
+ ) {
81
+ previousHash = availableVersions?.[0]?.script_hash
82
+ }
87
83
 
88
- deploymentMsgUpdate = undefined
89
- deploymentMsgUpdateMode = false
90
- }}
91
- >
92
- <span class="text-xs truncate">
93
- {#if emptyString(version.deployment_msg)}Version {version.script_hash}{:else}{version.deployment_msg}{/if}
94
- </span>
95
- {#if openDetails}
96
- <Button
97
- on:click={() => {
98
- dispatch('openDetails', { version: version.script_hash })
99
- }}
100
- class="ml-2 inline-flex gap-1 text-xs items-center"
101
- size="xs"
102
- color="light"
103
- variant="border"
104
- >
105
- Run page<ExternalLink size={14} />
106
- </Button>
107
- {/if}
108
- </div>
109
- {/each}
110
- </div>
111
- {:else}
112
- <div class="text-sm text-tertiary">No items</div>
113
- {/if}
84
+ deploymentMsgUpdate = undefined
85
+ deploymentMsgUpdateMode = false
86
+ }}
87
+ >
88
+ <span class="text-xs truncate">
89
+ {#if emptyString(version.deployment_msg)}Version {version.script_hash}{:else}{version.deployment_msg}{/if}
90
+ </span>
91
+ {#if openDetails}
92
+ <Button
93
+ on:click={() => {
94
+ dispatch('openDetails', { version: version.script_hash })
95
+ }}
96
+ class="ml-2 inline-flex gap-1 text-xs items-center"
97
+ size="xs"
98
+ color="light"
99
+ variant="border"
100
+ >
101
+ Run page<ExternalLink size={14} />
102
+ </Button>
103
+ {/if}
104
+ </div>
105
+ {/each}
106
+ </div>
114
107
  {:else}
115
- <Skeleton layout={[[40], [40], [40], [40], [40]]} />
108
+ <div class="text-sm text-tertiary">No items</div>
116
109
  {/if}
117
- </div>
118
- </PanelSection>
110
+ {:else}
111
+ <Skeleton layout={[[40], [40], [40], [40], [40]]} />
112
+ {/if}
113
+ </div>
119
114
  </Pane>
120
115
  <Pane size={80}>
121
116
  <div class="h-full w-full overflow-auto">