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.
- package/LICENSE +661 -0
- package/common.d.ts +29 -0
- package/components/ArgInfo.svelte +48 -0
- package/components/ArgInput.svelte +277 -0
- package/components/AutosizedTextarea.svelte +34 -0
- package/components/Badge.svelte +12 -0
- package/components/Button.svelte +82 -0
- package/components/ButtonAndDropdown.svelte +25 -0
- package/components/CenteredPage.svelte +5 -0
- package/components/ChevronButton.svelte +21 -0
- package/components/DisplayResult.svelte +101 -0
- package/components/Dropdown.svelte +108 -0
- package/components/Editor.svelte +370 -0
- package/components/FieldHeader.svelte +21 -0
- package/components/FlowBuilder.svelte +202 -0
- package/components/FlowEditor.svelte +95 -0
- package/components/FlowPreview.svelte +141 -0
- package/components/FlowStatusViewer.svelte +137 -0
- package/components/GroupModal.svelte +90 -0
- package/components/IconedResourceType.svelte +32 -0
- package/components/InviteGlobalUser.svelte +56 -0
- package/components/InviteUser.svelte +48 -0
- package/components/ItemPicker.svelte +58 -0
- package/components/JobStatus.svelte +38 -0
- package/components/Modal.svelte +94 -0
- package/components/ModuleStep.svelte +64 -0
- package/components/Multiselect.svelte +327 -0
- package/components/ObjectResourceInput.svelte +62 -0
- package/components/ObjectTypeNarrowing.svelte +25 -0
- package/components/PageHeader.svelte +29 -0
- package/components/Password.svelte +45 -0
- package/components/Path.svelte +129 -0
- package/components/RadioButton.svelte +117 -0
- package/components/Required.svelte +11 -0
- package/components/ResourceEditor.svelte +260 -0
- package/components/ResourcePicker.svelte +21 -0
- package/components/ResourceTypePicker.svelte +71 -0
- package/components/RunForm.svelte +127 -0
- package/components/SchemaEditor.svelte +221 -0
- package/components/SchemaForm.svelte +166 -0
- package/components/SchemaModal.svelte +160 -0
- package/components/SchemaViewer.svelte +76 -0
- package/components/ScriptBuilder.svelte +293 -0
- package/components/ScriptEditor.svelte +669 -0
- package/components/ScriptPicker.svelte +110 -0
- package/components/ScriptSchema.svelte +71 -0
- package/components/ShareModal.svelte +135 -0
- package/components/SharedBadge.svelte +54 -0
- package/components/StringTypeNarrowing.svelte +101 -0
- package/components/Switch.svelte +61 -0
- package/components/TableCustom.svelte +39 -0
- package/components/TableSimple.svelte +66 -0
- package/components/Tabs.svelte +21 -0
- package/components/Tooltip.svelte +93 -0
- package/components/VariableEditor.svelte +159 -0
- package/components/icons/DbIcon.svelte +12 -0
- package/components/icons/Mail.svelte +62 -0
- package/components/icons/Mysql.svelte +77 -0
- package/components/icons/PostgresIcon.svelte +57 -0
- package/components/icons/Slack.svelte +26 -0
- package/gen/core/ApiError.d.ts +8 -0
- package/gen/core/ApiRequestOptions.d.ts +13 -0
- package/gen/core/ApiResult.d.ts +7 -0
- package/gen/core/CancelablePromise.d.ts +26 -0
- package/gen/core/OpenAPI.d.ts +16 -0
- package/gen/core/request.d.ts +13 -0
- package/gen/index.d.ts +59 -0
- package/gen/models/AuditLog.d.ts +32 -0
- package/gen/models/CompletedJob.d.ts +48 -0
- package/gen/models/ContextualVariable.d.ts +5 -0
- package/gen/models/CreateResource.d.ts +6 -0
- package/gen/models/CreateVariable.d.ts +6 -0
- package/gen/models/CreateWorkspace.d.ts +6 -0
- package/gen/models/EditResource.d.ts +5 -0
- package/gen/models/EditResourceType.d.ts +4 -0
- package/gen/models/EditSchedule.d.ts +7 -0
- package/gen/models/EditVariable.d.ts +6 -0
- package/gen/models/EditWorkspaceUser.d.ts +3 -0
- package/gen/models/Flow.d.ts +13 -0
- package/gen/models/FlowModule.d.ts +6 -0
- package/gen/models/FlowModuleValue.d.ts +10 -0
- package/gen/models/FlowPreview.d.ts +7 -0
- package/gen/models/FlowStatus.d.ts +6 -0
- package/gen/models/FlowStatusModule.d.ts +15 -0
- package/gen/models/FlowValue.d.ts +5 -0
- package/gen/models/GlobalUserInfo.d.ts +14 -0
- package/gen/models/Group.d.ts +6 -0
- package/gen/models/InputTransform.d.ts +12 -0
- package/gen/models/Job.d.ts +11 -0
- package/gen/models/ListableVariable.d.ts +8 -0
- package/gen/models/Login.d.ts +4 -0
- package/gen/models/MainArgSignature.d.ts +14 -0
- package/gen/models/NewSchedule.d.ts +9 -0
- package/gen/models/NewToken.d.ts +4 -0
- package/gen/models/NewUser.d.ts +5 -0
- package/gen/models/Preview.d.ts +13 -0
- package/gen/models/QueuedJob.d.ts +47 -0
- package/gen/models/Resource.d.ts +8 -0
- package/gen/models/ResourceType.d.ts +6 -0
- package/gen/models/Schedule.d.ts +13 -0
- package/gen/models/Script.d.ts +29 -0
- package/gen/models/ScriptArgs.d.ts +1 -0
- package/gen/models/TruncatedToken.d.ts +7 -0
- package/gen/models/User.d.ts +10 -0
- package/gen/models/UserWorkspaceList.d.ts +8 -0
- package/gen/models/WorkerPing.d.ts +8 -0
- package/gen/models/Workspace.d.ts +6 -0
- package/gen/models/WorkspaceInvite.d.ts +5 -0
- package/gen/services/AdminService.d.ts +35 -0
- package/gen/services/AuditService.d.ts +37 -0
- package/gen/services/FlowService.d.ts +82 -0
- package/gen/services/GranularAclService.d.ts +42 -0
- package/gen/services/GroupService.d.ts +94 -0
- package/gen/services/JobService.d.ts +217 -0
- package/gen/services/ResourceService.d.ts +116 -0
- package/gen/services/ScheduleService.d.ts +73 -0
- package/gen/services/ScriptService.d.ts +165 -0
- package/gen/services/SettingsService.d.ts +15 -0
- package/gen/services/UserService.d.ts +211 -0
- package/gen/services/VariableService.d.ts +66 -0
- package/gen/services/WorkerService.d.ts +15 -0
- package/gen/services/WorkspaceService.d.ts +137 -0
- package/infer.d.ts +2 -0
- package/lib/components/ArgInfo.svelte.d.ts +16 -0
- package/lib/components/ArgInput.svelte.d.ts +37 -0
- package/lib/components/AutosizedTextarea.svelte.d.ts +19 -0
- package/lib/components/Badge.svelte.d.ts +20 -0
- package/lib/components/Button.svelte.d.ts +23 -0
- package/lib/components/ButtonAndDropdown.svelte.d.ts +23 -0
- package/lib/components/CenteredPage.svelte.d.ts +23 -0
- package/lib/components/ChevronButton.svelte.d.ts +19 -0
- package/lib/components/DisplayResult.svelte.d.ts +16 -0
- package/lib/components/Dropdown.svelte.d.ts +22 -0
- package/lib/components/Editor.svelte.d.ts +38 -0
- package/lib/components/FieldHeader.svelte.d.ts +23 -0
- package/lib/components/FlowBuilder.svelte.d.ts +18 -0
- package/lib/components/FlowEditor.svelte.d.ts +19 -0
- package/lib/components/FlowPreview.svelte.d.ts +21 -0
- package/lib/components/FlowStatusViewer.svelte.d.ts +18 -0
- package/lib/components/GroupModal.svelte.d.ts +17 -0
- package/lib/components/IconedResourceType.svelte.d.ts +19 -0
- package/lib/components/InviteGlobalUser.svelte.d.ts +19 -0
- package/lib/components/InviteUser.svelte.d.ts +19 -0
- package/lib/components/ItemPicker.svelte.d.ts +24 -0
- package/lib/components/JobStatus.svelte.d.ts +17 -0
- package/lib/components/Modal.svelte.d.ts +28 -0
- package/lib/components/ModuleStep.svelte.d.ts +26 -0
- package/lib/components/Multiselect.svelte.d.ts +33 -0
- package/lib/components/ObjectResourceInput.svelte.d.ts +17 -0
- package/lib/components/ObjectTypeNarrowing.svelte.d.ts +16 -0
- package/lib/components/PageHeader.svelte.d.ts +20 -0
- package/lib/components/Password.svelte.d.ts +18 -0
- package/lib/components/Path.svelte.d.ts +26 -0
- package/lib/components/RadioButton.svelte.d.ts +21 -0
- package/lib/components/Required.svelte.d.ts +17 -0
- package/lib/components/ResourceEditor.svelte.d.ts +22 -0
- package/lib/components/ResourcePicker.svelte.d.ts +17 -0
- package/lib/components/ResourceTypePicker.svelte.d.ts +19 -0
- package/lib/components/RunForm.svelte.d.ts +22 -0
- package/lib/components/SchemaEditor.svelte.d.ts +22 -0
- package/lib/components/SchemaForm.svelte.d.ts +23 -0
- package/lib/components/SchemaModal.svelte.d.ts +44 -0
- package/lib/components/SchemaViewer.svelte.d.ts +17 -0
- package/lib/components/ScriptBuilder.svelte.d.ts +20 -0
- package/lib/components/ScriptEditor.svelte.d.ts +28 -0
- package/lib/components/ScriptPicker.svelte.d.ts +21 -0
- package/lib/components/ScriptSchema.svelte.d.ts +22 -0
- package/lib/components/ShareModal.svelte.d.ts +21 -0
- package/lib/components/SharedBadge.svelte.d.ts +17 -0
- package/lib/components/StringTypeNarrowing.svelte.d.ts +18 -0
- package/lib/components/Switch.svelte.d.ts +31 -0
- package/lib/components/TableCustom.svelte.d.ts +25 -0
- package/lib/components/TableSimple.svelte.d.ts +24 -0
- package/lib/components/Tabs.svelte.d.ts +20 -0
- package/lib/components/Tooltip.svelte.d.ts +20 -0
- package/lib/components/VariableEditor.svelte.d.ts +21 -0
- package/lib/components/icons/DbIcon.svelte.d.ts +17 -0
- package/lib/components/icons/Mail.svelte.d.ts +17 -0
- package/lib/components/icons/Mysql.svelte.d.ts +17 -0
- package/lib/components/icons/PostgresIcon.svelte.d.ts +17 -0
- package/lib/components/icons/Slack.svelte.d.ts +17 -0
- package/package.json +110 -0
- package/stores.d.ts +19 -0
- 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>
|