windmill-components 1.28.4 → 1.28.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/components/ArgInput.svelte +12 -7
- package/components/Editor.svelte +21 -17
- package/components/FlowBuilder.svelte +2 -2
- package/components/FlowPreview.svelte +12 -8
- package/components/FlowPreviewContent.svelte +6 -6
- package/components/FlowStatusViewer.svelte +3 -0
- package/components/InputTransformForm.svelte +2 -2
- package/components/InputTransformsViewer.svelte +1 -1
- package/components/ModuleStep.svelte +1 -1
- package/components/ObjectResourceInput.svelte +2 -2
- package/components/RadioButton.svelte +4 -2
- package/components/SchemaEditor.svelte +7 -3
- package/components/SchemaEditorProperty.svelte +9 -7
- package/components/SchemaViewer.svelte +5 -1
- package/components/ScriptEditor.svelte +7 -1
- package/components/flows/DynamicInputHelpBox.svelte +15 -10
- package/components/flows/DynamicInputHelpBox.svelte.d.ts +3 -1
- package/components/flows/FlowSettings.svelte +2 -1
- package/logout.d.ts +1 -1
- package/logout.js +11 -9
- package/package.json +1 -1
|
@@ -114,7 +114,7 @@ export let inputCat = 'string';
|
|
|
114
114
|
$: inputCat = computeInputCat(type, format, itemsType?.type, enum_, contentEncoding);
|
|
115
115
|
</script>
|
|
116
116
|
|
|
117
|
-
<div class="flex flex-col w-full">
|
|
117
|
+
<div class="flex flex-col w-full mb-2">
|
|
118
118
|
<div>
|
|
119
119
|
{#if displayHeader}
|
|
120
120
|
<FieldHeader {label} {required} {type} {contentEncoding} {format} {itemsType} />
|
|
@@ -158,13 +158,18 @@ $: inputCat = computeInputCat(type, format, itemsType?.type, enum_, contentEncod
|
|
|
158
158
|
{/if}
|
|
159
159
|
|
|
160
160
|
<div class="grid grid-cols-2">
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
{error === '' ? '
|
|
166
|
-
|
|
161
|
+
{#if description || error}
|
|
162
|
+
<div class="text-sm italic pb-1">
|
|
163
|
+
{description}
|
|
164
|
+
</div>
|
|
165
|
+
<div class="text-right text-xs {error === '' ? 'text-white' : 'font-bold text-red-600'}">
|
|
166
|
+
{error === '' ? '...' : error}
|
|
167
|
+
</div>
|
|
168
|
+
{:else}
|
|
169
|
+
<div class="mt-1" />
|
|
170
|
+
{/if}
|
|
167
171
|
</div>
|
|
172
|
+
|
|
168
173
|
<div class="flex space-x-1">
|
|
169
174
|
{#if inputCat == 'number'}
|
|
170
175
|
<input
|
package/components/Editor.svelte
CHANGED
|
@@ -179,13 +179,32 @@ export async function reloadWebsocket() {
|
|
|
179
179
|
async function connectToLanguageServer(url, name, options) {
|
|
180
180
|
try {
|
|
181
181
|
const webSocket = new WebSocket(url);
|
|
182
|
-
webSocket.onopen = () => {
|
|
182
|
+
webSocket.onopen = async () => {
|
|
183
183
|
const socket = toSocket(webSocket);
|
|
184
184
|
const reader = new WebSocketMessageReader(socket);
|
|
185
185
|
const writer = new WebSocketMessageWriter(socket);
|
|
186
186
|
const languageClient = createLanguageClient({ reader, writer }, name, options);
|
|
187
187
|
websockets.push([languageClient, webSocket]);
|
|
188
|
-
|
|
188
|
+
reader.onClose(async () => {
|
|
189
|
+
try {
|
|
190
|
+
console.log('CLOSE');
|
|
191
|
+
websocketAlive[name] = false;
|
|
192
|
+
await languageClient.stop();
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
console.error(err);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
socket.onClose((_code, _reason) => {
|
|
199
|
+
websocketAlive[name] = false;
|
|
200
|
+
});
|
|
201
|
+
try {
|
|
202
|
+
await languageClient.start();
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
console.error(err);
|
|
206
|
+
throw new Error(err);
|
|
207
|
+
}
|
|
189
208
|
lastWsAttempt = new Date();
|
|
190
209
|
nbWsAttempt = 0;
|
|
191
210
|
if (name == 'deno') {
|
|
@@ -200,18 +219,6 @@ export async function reloadWebsocket() {
|
|
|
200
219
|
}
|
|
201
220
|
});
|
|
202
221
|
}
|
|
203
|
-
reader.onClose(() => {
|
|
204
|
-
try {
|
|
205
|
-
console.log('CLOSE');
|
|
206
|
-
languageClient.stop();
|
|
207
|
-
}
|
|
208
|
-
catch (err) {
|
|
209
|
-
console.error(err);
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
socket.onClose((_code, _reason) => {
|
|
213
|
-
websocketAlive[name] = false;
|
|
214
|
-
});
|
|
215
222
|
websocketAlive[name] = true;
|
|
216
223
|
};
|
|
217
224
|
}
|
|
@@ -329,9 +336,6 @@ async function loadMonaco() {
|
|
|
329
336
|
minimap: {
|
|
330
337
|
enabled: false
|
|
331
338
|
},
|
|
332
|
-
scrollbar: {
|
|
333
|
-
alwaysConsumeMouseWheel: false
|
|
334
|
-
},
|
|
335
339
|
lightbulb: {
|
|
336
340
|
enabled: true
|
|
337
341
|
}
|
|
@@ -123,7 +123,7 @@ onDestroy(() => {
|
|
|
123
123
|
</script>
|
|
124
124
|
|
|
125
125
|
<div class="flex flex-row w-full h-full justify-between">
|
|
126
|
-
<div class={`flex flex-col mb-96 m-auto w-1/2`}>
|
|
126
|
+
<div class={`flex flex-col mb-96 m-auto w-full sm:w-3/4 lg:w-2/3 xl:w-1/2`}>
|
|
127
127
|
<!-- Nav between steps-->
|
|
128
128
|
<div class="justify-between flex flex-row w-full my-4">
|
|
129
129
|
<Breadcrumb>
|
|
@@ -205,7 +205,7 @@ onDestroy(() => {
|
|
|
205
205
|
<div class={`relative h-screen w-1/3 ${previewOpen ? '' : 'hidden'}`}>
|
|
206
206
|
<div class="absolute top-0 h-full">
|
|
207
207
|
{#if $flowStore && step === 1}
|
|
208
|
-
<div class="fixed border-l-2 right-0 h-screen w-1/3">
|
|
208
|
+
<div class="fixed border-l-2 right-0 h-screen w-1/2 sm:w-1/3">
|
|
209
209
|
<FlowPreviewContent
|
|
210
210
|
bind:args={scheduleArgs}
|
|
211
211
|
on:close={() => (previewOpen = !previewOpen)}
|
|
@@ -27,8 +27,7 @@ $: dispatch('change', jobs);
|
|
|
27
27
|
export async function runPreview(args) {
|
|
28
28
|
viewPreview = true;
|
|
29
29
|
intervalId && clearInterval(intervalId);
|
|
30
|
-
let newFlow =
|
|
31
|
-
newFlow = tab == 'upto' ? truncateFlow(newFlow) : extractStep(newFlow);
|
|
30
|
+
let newFlow = tab == 'upto' ? truncateFlow(flow) : setInputTransformFromArgs(extractStep(flow), args);
|
|
32
31
|
jobId = await runFlowPreview(args, newFlow);
|
|
33
32
|
jobs = [];
|
|
34
33
|
intervalId = setInterval(loadJob, 1000);
|
|
@@ -43,14 +42,19 @@ function extractStep(flow) {
|
|
|
43
42
|
const localFlow = JSON.parse(JSON.stringify(flow));
|
|
44
43
|
localFlow.value.modules = flow.value.modules.slice(i, i + 1);
|
|
45
44
|
localFlow.schema = schemas[i];
|
|
46
|
-
stepArgs = {};
|
|
47
|
-
Object.entries(flow.value.modules[i].input_transform).forEach((x) => {
|
|
48
|
-
if (x[1].type == 'static') {
|
|
49
|
-
stepArgs[x[0]] = x[1].value;
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
45
|
return localFlow;
|
|
53
46
|
}
|
|
47
|
+
function setInputTransformFromArgs(flow, args) {
|
|
48
|
+
let input_transform = {};
|
|
49
|
+
Object.entries(args).forEach(([key, value]) => {
|
|
50
|
+
input_transform[key] = {
|
|
51
|
+
type: 'static',
|
|
52
|
+
value: value
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
flow.value.modules[0].input_transform = input_transform;
|
|
56
|
+
return flow;
|
|
57
|
+
}
|
|
54
58
|
async function loadJob() {
|
|
55
59
|
try {
|
|
56
60
|
job = await JobService.getJob({ workspace: $workspaceStore, id: jobId });
|
|
@@ -41,8 +41,8 @@ onDestroy(() => {
|
|
|
41
41
|
});
|
|
42
42
|
</script>
|
|
43
43
|
|
|
44
|
-
<div class="flex flex-col space-y-4 h-screen bg-white
|
|
45
|
-
<div class="flex flex-col space-y-4 p-6 border-b-2">
|
|
44
|
+
<div class="flex flex-col space-y-4 h-screen bg-white">
|
|
45
|
+
<div class="flex flex-col space-y-4 p-6 border-b-2 overflow-y-auto grow">
|
|
46
46
|
<div class="flex justify-between">
|
|
47
47
|
<h3 class="text-lg leading-6 font-bold text-gray-900">Flow Preview</h3>
|
|
48
48
|
|
|
@@ -51,11 +51,11 @@ onDestroy(() => {
|
|
|
51
51
|
</Button>
|
|
52
52
|
</div>
|
|
53
53
|
<SchemaForm schema={$flowStore.schema} bind:isValid bind:args />
|
|
54
|
-
<Button disabled={!isValid} class="blue-button" on:click={() => runPreview(args)} size="md">
|
|
55
|
-
Preview
|
|
56
|
-
</Button>
|
|
57
54
|
</div>
|
|
58
|
-
<
|
|
55
|
+
<Button disabled={!isValid} class="blue-button mx-4" on:click={() => runPreview(args)} size="md">
|
|
56
|
+
Preview
|
|
57
|
+
</Button>
|
|
58
|
+
<div class="h-full overflow-y-auto mb-16 grow">
|
|
59
59
|
{#if job}
|
|
60
60
|
<div class="w-full">
|
|
61
61
|
<FlowStatusViewer {job} bind:jobs />
|
|
@@ -78,7 +78,7 @@ $: checked = propertyType == 'javascript';
|
|
|
78
78
|
</script>
|
|
79
79
|
|
|
80
80
|
{#if arg != undefined}
|
|
81
|
-
<div class="flex justify-between items-center">
|
|
81
|
+
<div class="flex justify-between items-center mb-2">
|
|
82
82
|
<div class="flex items-center">
|
|
83
83
|
<FieldHeader
|
|
84
84
|
label={argName}
|
|
@@ -199,7 +199,7 @@ $: checked = propertyType == 'javascript';
|
|
|
199
199
|
/>
|
|
200
200
|
</div>
|
|
201
201
|
</OverlayPropertyPicker>
|
|
202
|
-
<DynamicInputHelpBox />
|
|
202
|
+
<DynamicInputHelpBox {i} />
|
|
203
203
|
{/if}
|
|
204
204
|
{:else}
|
|
205
205
|
<p>Not recognized arg type {arg.type}</p>
|
|
@@ -10,7 +10,7 @@ export let inputTransforms;
|
|
|
10
10
|
<span class="font-black text-gray-700">{key}</span>: {#if val.type == 'static'}<ObjectViewer
|
|
11
11
|
json={val.value}
|
|
12
12
|
/>{:else}
|
|
13
|
-
<span class="inline-
|
|
13
|
+
<span class="inline-highlight">
|
|
14
14
|
<Highlight offsetTop={0} language={typescript} code={val.expr} />
|
|
15
15
|
</span>
|
|
16
16
|
{/if}
|
|
@@ -82,7 +82,7 @@ const isTrigger = mode === 'pull' && i === 0;
|
|
|
82
82
|
<div class="mb-2 overflow-hidden">
|
|
83
83
|
<EditorBar {editor} {websocketAlive} lang={mod.value.language ?? 'deno'} />
|
|
84
84
|
</div>
|
|
85
|
-
<div>
|
|
85
|
+
<div on:mouseleave={() => loadSchema(i)}>
|
|
86
86
|
<Editor
|
|
87
87
|
bind:websocketAlive
|
|
88
88
|
bind:this={editor}
|
|
@@ -42,8 +42,8 @@ function valueToPath() {
|
|
|
42
42
|
$: value && valueToPath();
|
|
43
43
|
</script>
|
|
44
44
|
|
|
45
|
-
<div class="flex flex-row w-full gap-2">
|
|
46
|
-
<div class="shrink
|
|
45
|
+
<div class="flex flex-row w-full flex-wrap gap-x-2">
|
|
46
|
+
<div class="shrink">
|
|
47
47
|
<RadioButton
|
|
48
48
|
options={[
|
|
49
49
|
[`Resource (${resourceTypeName})`, 'resource'],
|
|
@@ -12,7 +12,7 @@ const dispatch = createEventDispatcher();
|
|
|
12
12
|
{#each options as [label, val]}
|
|
13
13
|
<label
|
|
14
14
|
class:item-button-selected={val == value}
|
|
15
|
-
class="item-button text-center text-sm h-full p-2 grow"
|
|
15
|
+
class="item-button text-center text-sm h-full p-2 grow whitespace-nowrap"
|
|
16
16
|
>
|
|
17
17
|
<input
|
|
18
18
|
type="radio"
|
|
@@ -23,7 +23,9 @@ const dispatch = createEventDispatcher();
|
|
|
23
23
|
on:click={() => dispatch('change', val)}
|
|
24
24
|
/>
|
|
25
25
|
<p>
|
|
26
|
-
{#if typeof label !== 'string'}
|
|
26
|
+
{#if typeof label !== 'string'}
|
|
27
|
+
{label.title}
|
|
28
|
+
<Tooltip>{label.desc}</Tooltip>
|
|
27
29
|
{:else}{label}{/if}
|
|
28
30
|
</p>
|
|
29
31
|
</label>
|
|
@@ -126,7 +126,7 @@ function switchTab() {
|
|
|
126
126
|
</script>
|
|
127
127
|
|
|
128
128
|
<div class="flex flex-col">
|
|
129
|
-
<div class="flex justify-between">
|
|
129
|
+
<div class="flex justify-between gap-x-2">
|
|
130
130
|
<Button
|
|
131
131
|
on:click={() => {
|
|
132
132
|
modalProperty = Object.assign({}, DEFAULT_PROPERTY)
|
|
@@ -176,8 +176,12 @@ function switchTab() {
|
|
|
176
176
|
<SchemaEditorProperty {property} />
|
|
177
177
|
</td>
|
|
178
178
|
<td>{property.description}</td>
|
|
179
|
-
<td>{JSON.stringify(property.default)
|
|
180
|
-
<td
|
|
179
|
+
<td>{property.default ? JSON.stringify(property.default) : ''}</td>
|
|
180
|
+
<td
|
|
181
|
+
>{#if schema.required.includes(name)}
|
|
182
|
+
<span class="text-red-600 font-bold text-lg">*</span>
|
|
183
|
+
{/if}</td
|
|
184
|
+
>
|
|
181
185
|
<td class="justify-end flex">
|
|
182
186
|
<Button
|
|
183
187
|
color="red"
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
export let property;
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
|
-
<
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
{
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
{
|
|
5
|
+
<div class="flex flex-row flex-wrap gap-1">
|
|
6
|
+
<Badge color="blue">{property.type?.toUpperCase() ?? 'ANY'}</Badge>
|
|
7
|
+
{#if property.format}
|
|
8
|
+
<Badge color="green">{property.format?.toUpperCase()}</Badge>
|
|
9
|
+
{/if}
|
|
10
|
+
{#if property.contentEncoding}
|
|
11
|
+
<Badge color="indigo">{property.contentEncoding?.toUpperCase()}</Badge>
|
|
12
|
+
{/if}
|
|
13
|
+
</div>
|
|
@@ -58,7 +58,11 @@ let viewJsonSchema = false;
|
|
|
58
58
|
>{property.format ?? ''}
|
|
59
59
|
{property.contentEncoding ? `(encoding: ${property.contentEncoding})` : ''}</td
|
|
60
60
|
>
|
|
61
|
-
<td
|
|
61
|
+
<td
|
|
62
|
+
>{#if schema.required.includes(name)}
|
|
63
|
+
<span class="text-red-600 font-bold text-lg">*</span>
|
|
64
|
+
{/if}</td
|
|
65
|
+
>
|
|
62
66
|
</tr>
|
|
63
67
|
{/each}
|
|
64
68
|
</tbody>
|
|
@@ -206,7 +206,13 @@ onDestroy(() => {
|
|
|
206
206
|
<div class="header">
|
|
207
207
|
<EditorBar {editor} {lang} {websocketAlive} />
|
|
208
208
|
</div>
|
|
209
|
-
<div
|
|
209
|
+
<div
|
|
210
|
+
class="flex-1 overflow-hidden border p-2 rounded"
|
|
211
|
+
on:mouseleave={() => {
|
|
212
|
+
code = getEditor().getCode()
|
|
213
|
+
inferSchema()
|
|
214
|
+
}}
|
|
215
|
+
>
|
|
210
216
|
<Editor
|
|
211
217
|
{code}
|
|
212
218
|
bind:websocketAlive
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
|
|
2
2
|
import Icon from 'svelte-awesome';
|
|
3
3
|
import { slide } from 'svelte/transition';
|
|
4
|
+
export let i = 1;
|
|
4
5
|
$: opened = false;
|
|
5
6
|
</script>
|
|
6
7
|
|
|
@@ -25,29 +26,29 @@ $: opened = false;
|
|
|
25
26
|
>
|
|
26
27
|
<p class="font-bold">Dynamic arg help</p>
|
|
27
28
|
<p>
|
|
28
|
-
When a field is "
|
|
29
|
-
corresponding
|
|
29
|
+
When a field is using the "Raw Javascript Editor", its value is computed dynamically as the
|
|
30
|
+
evaluation of its corresponding javascript snippet.
|
|
30
31
|
</p>
|
|
31
|
-
That snippet can be single line:
|
|
32
|
+
That snippet can be a single line:
|
|
32
33
|
<pre><code>last_result.myarg</code></pre>
|
|
33
|
-
or multiline:
|
|
34
|
+
or a multiline:
|
|
34
35
|
<pre><code
|
|
35
36
|
>let x = 5;
|
|
36
37
|
x + 2</code
|
|
37
38
|
></pre>
|
|
38
39
|
<p>
|
|
39
|
-
If it is multiline, the
|
|
40
|
+
If it is multiline, the statement before the final expression <b
|
|
40
41
|
>MUST END WITH ; and a newline</b
|
|
41
42
|
>
|
|
42
43
|
</p>
|
|
43
44
|
The snippet can also be a string template:
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
<code
|
|
46
|
+
>`Hello ${params.name}, all your base ${previous_result.base_name} belong
|
|
47
|
+
to us`</code
|
|
48
|
+
>
|
|
48
49
|
However, the last line must always be the final expression.
|
|
49
50
|
<p>
|
|
50
|
-
The snippet can use any
|
|
51
|
+
The snippet can use any javascript primitives, and the following flow specific objects and
|
|
51
52
|
functions:
|
|
52
53
|
</p>
|
|
53
54
|
<ul class="ml-4">
|
|
@@ -68,5 +69,9 @@ belong to us`</code
|
|
|
68
69
|
<b>resource(path)</b>: the function returning the resource at a given path as an object
|
|
69
70
|
</li>
|
|
70
71
|
</ul>
|
|
72
|
+
<p>To re-enable editor assistance, import the helper functions types using:</p>
|
|
73
|
+
<code
|
|
74
|
+
>{`import { previous_result, flow_input, step, variable, resource, params } from 'windmill@${i}'`}</code
|
|
75
|
+
>
|
|
71
76
|
</div>
|
|
72
77
|
{/if}
|
|
@@ -161,12 +161,13 @@ let jsonValue = '';
|
|
|
161
161
|
right: 'enabled'
|
|
162
162
|
}}
|
|
163
163
|
/>
|
|
164
|
-
<div class="p-2
|
|
164
|
+
<div class="p-2 my-2 rounded" class:bg-gray-300={!scheduleEnabled}>
|
|
165
165
|
{#if !scheduleEnabled}
|
|
166
166
|
<span class="font-black">No next scheduled run when disabled</span>
|
|
167
167
|
{/if}
|
|
168
168
|
<CronInput bind:schedule={scheduleCron} />
|
|
169
169
|
</div>
|
|
170
|
+
|
|
170
171
|
<SchemaForm schema={$flowStore.schema} bind:args={scheduleArgs} />
|
|
171
172
|
</CollapseLink>
|
|
172
173
|
{/if}
|
package/logout.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare function logoutWithRedirect(rd?: string): void;
|
|
2
|
-
export declare function logout(
|
|
2
|
+
export declare function logout(): Promise<void>;
|
package/logout.js
CHANGED
|
@@ -6,22 +6,24 @@ function clearCookies() {
|
|
|
6
6
|
document.cookie.split(";").forEach(function (c) { document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/"); });
|
|
7
7
|
}
|
|
8
8
|
export function logoutWithRedirect(rd) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
if (rd?.split('?')[0] != '/user/login') {
|
|
10
|
+
const error = document.cookie.includes('token')
|
|
11
|
+
? `error=${encodeURIComponent('You have been logged out because your session has expired.')}&`
|
|
12
|
+
: '';
|
|
13
|
+
clearCookies();
|
|
14
|
+
goto(`/user/login?${error}${rd ? 'rd=' + encodeURIComponent(rd) : ''}`);
|
|
15
|
+
}
|
|
14
16
|
}
|
|
15
|
-
export async function logout(
|
|
17
|
+
export async function logout() {
|
|
16
18
|
try {
|
|
17
19
|
clearStores();
|
|
18
20
|
await UserService.logout();
|
|
19
21
|
clearCookies();
|
|
20
|
-
goto(`/user/login${logoutMessage ? '?error=' + encodeURIComponent(logoutMessage) : ''}`);
|
|
21
|
-
sendUserToast('you have been logged out');
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
|
-
goto('/user/login');
|
|
25
24
|
console.error(error);
|
|
25
|
+
clearCookies();
|
|
26
26
|
}
|
|
27
|
+
goto(`/user/login`);
|
|
28
|
+
sendUserToast('you have been logged out');
|
|
27
29
|
}
|