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.
- package/package/assets/app.css +20 -0
- package/package/components/AppConnectLightweightResourcePicker.svelte +66 -0
- package/package/components/AppConnectLightweightResourcePicker.svelte.d.ts +21 -0
- package/package/components/ArgInput.svelte +6 -2
- package/package/components/ArgInput.svelte.d.ts +1 -0
- package/package/components/CustomPopover.svelte +1 -1
- package/package/components/DisplayResult.svelte +1 -1
- package/package/components/FlowBuilder.svelte +2 -0
- package/package/components/FlowBuilder.svelte.d.ts +1 -0
- package/package/components/FlowInputViewer.svelte +25 -0
- package/package/components/FlowInputViewer.svelte.d.ts +19 -0
- package/package/components/FlowJobResult.svelte +8 -1
- package/package/components/FlowJobResult.svelte.d.ts +1 -0
- package/package/components/FlowMetadata.svelte +2 -2
- package/package/components/FlowStatusViewer.svelte +3 -1
- package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
- package/package/components/FlowStatusViewerInner.svelte +4 -1
- package/package/components/FlowViewer.svelte +2 -21
- package/package/components/LightweightResourcePicker.svelte +34 -30
- package/package/components/LogViewer.svelte +4 -3
- package/package/components/LogViewer.svelte.d.ts +1 -0
- package/package/components/ManualPopover.svelte +1 -1
- package/package/components/ObjectResourceInput.svelte +5 -2
- package/package/components/ObjectResourceInput.svelte.d.ts +2 -0
- package/package/components/Popover.svelte +1 -1
- package/package/components/Portal.svelte +7 -8
- package/package/components/Portal.svelte.d.ts +3 -7
- package/package/components/QueueMetricsDrawer.svelte +368 -3
- package/package/components/QueueMetricsDrawer.svelte.d.ts +2 -0
- package/package/components/ResourceEditor.svelte +4 -5
- package/package/components/ResourcePicker.svelte +14 -9
- package/package/components/ResourcePicker.svelte.d.ts +1 -0
- package/package/components/RunForm.svelte +1 -1
- package/package/components/SavedInputs.svelte +2 -2
- package/package/components/ScriptVersionHistory.svelte +54 -59
- package/package/components/TestConnection.svelte +1 -0
- package/package/components/TimeAgo.svelte +5 -6
- package/package/components/TimeAgo.svelte.d.ts +1 -1
- package/package/components/apps/components/buttons/AppButton.svelte +1 -1
- package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +1 -1
- package/package/components/apps/components/inputs/AppMultiSelect.svelte +1 -1
- package/package/components/apps/components/inputs/AppMultiSelectV2.svelte +1 -1
- package/package/components/apps/components/layout/AppDrawer.svelte +1 -1
- package/package/components/apps/components/layout/AppModal.svelte +1 -1
- package/package/components/apps/editor/AppEditor.svelte +11 -3
- package/package/components/apps/editor/GridEditor.svelte +57 -4
- package/package/components/apps/editor/GridEditor.svelte.d.ts +8 -0
- package/package/components/apps/editor/GridEditorMenu.svelte +1 -1
- package/package/components/apps/editor/SubGridEditor.svelte +82 -3
- package/package/components/apps/editor/SubGridEditor.svelte.d.ts +16 -0
- package/package/components/apps/editor/appUtils.d.ts +19 -2
- package/package/components/apps/editor/appUtils.js +103 -7
- package/package/components/apps/editor/component/Component.svelte +36 -8
- package/package/components/apps/editor/component/Component.svelte.d.ts +3 -1
- package/package/components/apps/editor/contextPanel/components/OutputHeader.svelte +1 -1
- package/package/components/apps/svelte-grid/Grid.svelte +235 -12
- package/package/components/apps/svelte-grid/Grid.svelte.d.ts +7 -7
- package/package/components/apps/svelte-grid/MoveResize.svelte +104 -11
- package/package/components/apps/svelte-grid/MoveResize.svelte.d.ts +7 -0
- package/package/components/apps/svelte-grid/utils/item.d.ts +4 -1
- package/package/components/apps/svelte-grid/utils/item.js +2 -3
- package/package/components/apps/svelte-select/lib/ConditionalPortal.svelte +1 -1
- package/package/components/apps/svelte-select/lib/ConditionalPortalGlobal.svelte +1 -1
- package/package/components/common/button/ButtonDropdown.svelte +1 -1
- package/package/components/common/drawer/ConditionalPortal.svelte +1 -1
- package/package/components/common/menu/MenuV2.svelte +1 -1
- package/package/components/common/modal/AlwaysMountedModal.svelte +1 -1
- package/package/components/common/popup/PopupV2.svelte +1 -1
- package/package/components/copilot/StepGenQuick.svelte +3 -2
- package/package/components/copilot/StepGenQuick.svelte.d.ts +1 -0
- package/package/components/details/Menu.svelte +1 -1
- package/package/components/flows/CreateActionsApp.svelte +1 -1
- package/package/components/flows/FlowEditor.svelte +2 -1
- package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
- package/package/components/flows/FlowHistory.svelte +10 -195
- package/package/components/flows/FlowHistory.svelte.d.ts +0 -1
- package/package/components/flows/FlowHistoryInner.svelte +200 -0
- package/package/components/flows/FlowHistoryInner.svelte.d.ts +19 -0
- package/package/components/flows/content/FlowEditorPanel.svelte +2 -1
- package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
- package/package/components/flows/content/FlowInput.svelte +66 -58
- package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
- package/package/components/flows/content/FlowModuleScript.svelte +1 -1
- package/package/components/flows/map/FlowModuleSchemaMap.svelte +3 -2
- package/package/components/flows/map/InsertModuleButton.svelte +1 -1
- package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte +1 -1
- package/package/components/graph/model.d.ts +1 -0
- package/package/components/icons/WindmillIcon.svelte +119 -105
- package/package/components/icons/store.d.ts +4 -0
- package/package/components/icons/store.js +1 -0
- package/package/components/multiselect/MultiSelectWrapper.svelte +1 -1
- package/package/components/propertyPicker/ObjectViewer.svelte +1 -1
- package/package/components/runs/RunRow.svelte +3 -7
- package/package/components/schema/FlowPropertyEditor.svelte +1 -0
- package/package/components/search/GlobalSearchModal.svelte +1 -1
- package/package/script_helpers.d.ts +37 -38
- package/package/script_helpers.js +100 -38
- package/package.json +23 -1
- package/package/init_scripts/python_failure_module.d.ts +0 -2
- package/package/init_scripts/python_failure_module.js +0 -8
- package/package/init_scripts/python_init_code.d.ts +0 -2
- package/package/init_scripts/python_init_code.js +0 -40
- package/package/init_scripts/python_init_code_clear.d.ts +0 -2
- package/package/init_scripts/python_init_code_clear.js +0 -5
- package/package/init_scripts/python_init_code_trigger.d.ts +0 -2
- 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 {
|
|
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
|
-
<
|
|
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>
|
|
@@ -73,7 +73,7 @@ export async function editResource() {
|
|
|
73
73
|
dispatch('refresh', path);
|
|
74
74
|
}
|
|
75
75
|
else {
|
|
76
|
-
throw Error('Cannot edit undefined
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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
|
|
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="
|
|
138
|
-
size="
|
|
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="
|
|
151
|
-
size="
|
|
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="
|
|
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="
|
|
177
|
+
variant="contained"
|
|
174
178
|
color="light"
|
|
175
|
-
|
|
179
|
+
btnClasses="w-8 px-0.5 py-1.5"
|
|
180
|
+
size="sm"
|
|
176
181
|
on:click={() => {
|
|
177
182
|
loadResources(resourceType)
|
|
178
183
|
}}
|
|
@@ -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
|
|
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
|
-
<
|
|
56
|
-
|
|
57
|
-
{#if
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
if (showDiff && versions && selectedVersionIndex === versions.length - 1) {
|
|
72
|
+
showDiff = false
|
|
73
|
+
}
|
|
78
74
|
|
|
79
|
-
|
|
75
|
+
const availableVersions = versions?.slice(selectedVersionIndex + 1)
|
|
80
76
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
if (
|
|
78
|
+
previousHash &&
|
|
79
|
+
!availableVersions?.find((v) => v.script_hash === previousHash)
|
|
80
|
+
) {
|
|
81
|
+
previousHash = availableVersions?.[0]?.script_hash
|
|
82
|
+
}
|
|
87
83
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
<
|
|
108
|
+
<div class="text-sm text-tertiary">No items</div>
|
|
116
109
|
{/if}
|
|
117
|
-
|
|
118
|
-
|
|
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">
|