windmill-components 1.22.0 → 1.22.42
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/Editor.svelte +16 -3
- package/components/EditorBar.svelte +204 -0
- package/components/EditorBar.svelte.d.ts +23 -0
- package/components/FlowBuilder.svelte +2 -11
- package/components/FlowViewer.svelte +53 -17
- package/components/FlowViewer.svelte.d.ts +1 -1
- package/components/ModuleStep.svelte +8 -0
- package/components/Path.svelte +0 -1
- package/components/RunForm.svelte +2 -2
- package/components/SchemaViewer.svelte +1 -1
- package/components/ScriptEditor.svelte +11 -188
- package/components/ScriptPicker.svelte +4 -15
- package/components/flows/FlowModuleHeader.svelte +3 -2
- package/components/flows/utils.d.ts +0 -4
- package/components/flows/utils.js +2 -23
- package/gen/core/OpenAPI.js +1 -1
- package/gen/index.d.ts +1 -0
- package/gen/models/OpenFlow.d.ts +7 -0
- package/gen/models/OpenFlow.js +4 -0
- package/gen/services/FlowService.d.ts +13 -0
- package/gen/services/FlowService.js +11 -0
- package/gen/services/ScriptService.d.ts +11 -0
- package/gen/services/ScriptService.js +14 -0
- package/package.json +4 -1
- package/stores.d.ts +1 -0
- package/utils.d.ts +15 -2
- package/utils.js +42 -1
package/components/Editor.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>import { browser, dev } from '$app/env';
|
|
2
2
|
import { page } from '$app/stores';
|
|
3
|
-
import { buildExtraLib } from '../utils';
|
|
3
|
+
import { buildExtraLib, sendUserToast } from '../utils';
|
|
4
4
|
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
|
5
5
|
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
|
6
6
|
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
|
|
@@ -19,6 +19,7 @@ export let websocketAlive = { pyright: false, black: false, deno: false };
|
|
|
19
19
|
export let extraLib = lang == 'typescript' && !deno ? buildExtraLib() : '';
|
|
20
20
|
export let extraLibPath = 'file:///node_modules/@types/windmill/index.d.ts';
|
|
21
21
|
let websockets = [];
|
|
22
|
+
let websocketInterval;
|
|
22
23
|
let uri = '';
|
|
23
24
|
let disposeMethod;
|
|
24
25
|
const dispatch = createEventDispatcher();
|
|
@@ -129,8 +130,7 @@ export async function reloadWebsocket() {
|
|
|
129
130
|
const writer = new WebSocketMessageWriter(socket);
|
|
130
131
|
const languageClient = createLanguageClient({ reader, writer }, name, options);
|
|
131
132
|
languageClient.start();
|
|
132
|
-
|
|
133
|
-
websocketAlive[name] = false;
|
|
133
|
+
reader.onClose(() => {
|
|
134
134
|
try {
|
|
135
135
|
languageClient.stop();
|
|
136
136
|
}
|
|
@@ -138,6 +138,9 @@ export async function reloadWebsocket() {
|
|
|
138
138
|
console.error(err);
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
|
+
socket.onClose((_code, _reason) => {
|
|
142
|
+
websocketAlive[name] = false;
|
|
143
|
+
});
|
|
141
144
|
if (name == 'deno') {
|
|
142
145
|
vscode.commands.getCommands().then((v) => {
|
|
143
146
|
if (!v.includes('deno.cache')) {
|
|
@@ -212,6 +215,15 @@ export async function reloadWebsocket() {
|
|
|
212
215
|
}
|
|
213
216
|
});
|
|
214
217
|
}
|
|
218
|
+
websocketInterval && clearInterval(websocketInterval);
|
|
219
|
+
websocketInterval = setInterval(() => {
|
|
220
|
+
if (document.visibilityState == 'visible') {
|
|
221
|
+
if (!websocketAlive.black && !websocketAlive.deno && !websocketAlive.pyright) {
|
|
222
|
+
sendUserToast('Smart assistant got disconnected. Reconnecting to windmill language server for smart assistance');
|
|
223
|
+
reloadWebsocket();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}, 5000);
|
|
215
227
|
}
|
|
216
228
|
}
|
|
217
229
|
function closeWebsockets() {
|
|
@@ -224,6 +236,7 @@ function closeWebsockets() {
|
|
|
224
236
|
}
|
|
225
237
|
}
|
|
226
238
|
websockets = [];
|
|
239
|
+
websocketInterval && clearInterval(websocketInterval);
|
|
227
240
|
}
|
|
228
241
|
async function loadMonaco() {
|
|
229
242
|
const monaco = await import('monaco-editor');
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<script>import { ResourceService, ScriptService, VariableService } from '../gen';
|
|
2
|
+
import { getScriptByPath, loadHubScripts, sendUserToast } from '../utils';
|
|
3
|
+
import Icon from 'svelte-awesome';
|
|
4
|
+
import { faSearch } from '@fortawesome/free-solid-svg-icons';
|
|
5
|
+
import { workspaceStore, hubScripts } from '../stores';
|
|
6
|
+
import ItemPicker from './ItemPicker.svelte';
|
|
7
|
+
import VariableEditor from './VariableEditor.svelte';
|
|
8
|
+
import ResourceEditor from './ResourceEditor.svelte';
|
|
9
|
+
import { Highlight } from 'svelte-highlight';
|
|
10
|
+
import { python, typescript } from 'svelte-highlight/languages';
|
|
11
|
+
import github from 'svelte-highlight/styles/github';
|
|
12
|
+
import Modal from './Modal.svelte';
|
|
13
|
+
export let lang;
|
|
14
|
+
export let editor;
|
|
15
|
+
export let websocketAlive;
|
|
16
|
+
let variablePicker;
|
|
17
|
+
let resourcePicker;
|
|
18
|
+
let scriptPicker;
|
|
19
|
+
let variableEditor;
|
|
20
|
+
let resourceEditor;
|
|
21
|
+
let codeViewer;
|
|
22
|
+
let codeLang = 'deno';
|
|
23
|
+
let codeContent = '';
|
|
24
|
+
async function loadVariables() {
|
|
25
|
+
let r = [];
|
|
26
|
+
const variables = (await VariableService.listVariable({ workspace: $workspaceStore ?? 'NO_W' })).map((x) => {
|
|
27
|
+
return { name: x.path, ...x };
|
|
28
|
+
});
|
|
29
|
+
const rvariables = await VariableService.listContextualVariables({
|
|
30
|
+
workspace: $workspaceStore ?? 'NO_W'
|
|
31
|
+
});
|
|
32
|
+
r = r.concat(variables).concat(rvariables);
|
|
33
|
+
return r;
|
|
34
|
+
}
|
|
35
|
+
async function loadScripts() {
|
|
36
|
+
const workspaceScripts = await ScriptService.listScripts({
|
|
37
|
+
workspace: $workspaceStore ?? 'NO_W'
|
|
38
|
+
});
|
|
39
|
+
await loadHubScripts();
|
|
40
|
+
const hubScripts_ = $hubScripts ?? [];
|
|
41
|
+
return workspaceScripts.concat(hubScripts_);
|
|
42
|
+
}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<svelte:head>
|
|
46
|
+
{@html github}
|
|
47
|
+
</svelte:head>
|
|
48
|
+
|
|
49
|
+
<ItemPicker
|
|
50
|
+
bind:this={scriptPicker}
|
|
51
|
+
pickCallback={async (path, _) => {
|
|
52
|
+
const { language, content } = await getScriptByPath(path ?? '')
|
|
53
|
+
codeContent = content
|
|
54
|
+
codeLang = language
|
|
55
|
+
codeViewer.openModal()
|
|
56
|
+
}}
|
|
57
|
+
closeOnClick={false}
|
|
58
|
+
itemName="script"
|
|
59
|
+
extraField="summary"
|
|
60
|
+
loadItems={loadScripts}
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
<Modal bind:this={codeViewer}>
|
|
64
|
+
<div slot="title">Code</div>
|
|
65
|
+
<div slot="content">
|
|
66
|
+
{#if codeLang == 'python3'}
|
|
67
|
+
<Highlight language={python} code={codeContent} />
|
|
68
|
+
{:else if codeLang == 'deno'}
|
|
69
|
+
<Highlight language={typescript} code={codeContent} />
|
|
70
|
+
{/if}
|
|
71
|
+
</div></Modal
|
|
72
|
+
>
|
|
73
|
+
|
|
74
|
+
<ItemPicker
|
|
75
|
+
bind:this={variablePicker}
|
|
76
|
+
pickCallback={(path, name) => {
|
|
77
|
+
if (!path) {
|
|
78
|
+
if (lang == 'deno') {
|
|
79
|
+
editor.insertAtCursor(`Deno.env.get('${name}')`)
|
|
80
|
+
} else {
|
|
81
|
+
if (!editor.getCode().includes('import os')) {
|
|
82
|
+
editor.insertAtBeginning('import os\n')
|
|
83
|
+
}
|
|
84
|
+
editor.insertAtCursor(`os.environ.get("${name}")`)
|
|
85
|
+
}
|
|
86
|
+
sendUserToast(`${name} inserted at cursor`)
|
|
87
|
+
} else {
|
|
88
|
+
if (lang == 'deno') {
|
|
89
|
+
if (!editor.getCode().includes('import * as wmill from')) {
|
|
90
|
+
editor.insertAtBeginning(
|
|
91
|
+
`import * as wmill from 'https://deno.land/x/windmill@v${__pkg__.version}/index.ts'\n`
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
editor.insertAtCursor(`(await wmill.getVariable('${path}'))`)
|
|
95
|
+
} else {
|
|
96
|
+
if (!editor.getCode().includes('import wmill')) {
|
|
97
|
+
editor.insertAtBeginning('import wmill\n')
|
|
98
|
+
}
|
|
99
|
+
editor.insertAtCursor(`wmill.get_variable("${path}")`)
|
|
100
|
+
}
|
|
101
|
+
sendUserToast(`${name} inserted at cursor`)
|
|
102
|
+
}
|
|
103
|
+
}}
|
|
104
|
+
itemName="Variable"
|
|
105
|
+
extraField="name"
|
|
106
|
+
loadItems={loadVariables}
|
|
107
|
+
>
|
|
108
|
+
<div slot="submission" class="flex flex-row">
|
|
109
|
+
<div class="text-xs mr-2 align-middle">
|
|
110
|
+
The variable you were looking for does not exist yet?
|
|
111
|
+
</div>
|
|
112
|
+
<button
|
|
113
|
+
class="default-button-secondary"
|
|
114
|
+
type="button"
|
|
115
|
+
on:click={() => {
|
|
116
|
+
variableEditor.initNew()
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
Create a new variable
|
|
120
|
+
</button>
|
|
121
|
+
</div>
|
|
122
|
+
</ItemPicker>
|
|
123
|
+
|
|
124
|
+
<ItemPicker
|
|
125
|
+
bind:this={resourcePicker}
|
|
126
|
+
pickCallback={(path, _) => {
|
|
127
|
+
if (lang == 'deno') {
|
|
128
|
+
if (!editor.getCode().includes('import * as wmill from')) {
|
|
129
|
+
editor.insertAtBeginning(
|
|
130
|
+
`import * as wmill from 'https://deno.land/x/windmill@v${__pkg__.version}/index.ts'\n`
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
editor.insertAtCursor(`(await wmill.getResource('${path}'))`)
|
|
134
|
+
} else {
|
|
135
|
+
if (!editor.getCode().includes('import wmill')) {
|
|
136
|
+
editor.insertAtBeginning('import wmill\n')
|
|
137
|
+
}
|
|
138
|
+
editor.insertAtCursor(`wmill.get_resource("${path}")`)
|
|
139
|
+
}
|
|
140
|
+
sendUserToast(`${path} inserted at cursor`)
|
|
141
|
+
}}
|
|
142
|
+
itemName="Resource"
|
|
143
|
+
extraField="resource_type"
|
|
144
|
+
loadItems={async () =>
|
|
145
|
+
await ResourceService.listResource({ workspace: $workspaceStore ?? 'NO_W' })}
|
|
146
|
+
>
|
|
147
|
+
<div slot="submission" class="flex flex-row">
|
|
148
|
+
<div class="text-xs mr-2 align-middle">
|
|
149
|
+
The resource you were looking for does not exist yet?
|
|
150
|
+
</div>
|
|
151
|
+
<button
|
|
152
|
+
class="default-button-secondary"
|
|
153
|
+
type="button"
|
|
154
|
+
on:click={() => {
|
|
155
|
+
resourceEditor.initNew()
|
|
156
|
+
}}
|
|
157
|
+
>
|
|
158
|
+
Create a new resource
|
|
159
|
+
</button>
|
|
160
|
+
</div>
|
|
161
|
+
</ItemPicker>
|
|
162
|
+
|
|
163
|
+
<ResourceEditor bind:this={resourceEditor} on:refresh={resourcePicker.openModal} />
|
|
164
|
+
|
|
165
|
+
<VariableEditor bind:this={variableEditor} on:create={variablePicker.openModal} />
|
|
166
|
+
|
|
167
|
+
<div class="flex flex-row justify-around w-full">
|
|
168
|
+
<button
|
|
169
|
+
class="default-button-secondary font-semibold py-px mr-2 text-xs align-middle max-h-8"
|
|
170
|
+
on:click|stopPropagation={() => {
|
|
171
|
+
variablePicker.openModal()
|
|
172
|
+
}}
|
|
173
|
+
>Variable picker <Icon data={faSearch} scale={0.7} />
|
|
174
|
+
</button>
|
|
175
|
+
|
|
176
|
+
<button
|
|
177
|
+
class="default-button-secondary font-semibold py-px text-xs mr-2 align-middle max-h-8"
|
|
178
|
+
on:click|stopPropagation={() => {
|
|
179
|
+
resourcePicker.openModal()
|
|
180
|
+
}}
|
|
181
|
+
>Resource picker <Icon data={faSearch} scale={0.7} />
|
|
182
|
+
</button>
|
|
183
|
+
<button
|
|
184
|
+
class="default-button-secondary font-semibold py-px text-xs mr-2 align-middle max-h-8"
|
|
185
|
+
on:click|stopPropagation={() => {
|
|
186
|
+
scriptPicker.openModal()
|
|
187
|
+
}}
|
|
188
|
+
>Script explorer <Icon data={faSearch} scale={0.7} />
|
|
189
|
+
</button>
|
|
190
|
+
|
|
191
|
+
<button
|
|
192
|
+
class="default-button-secondary py-px max-h-8 text-xs"
|
|
193
|
+
on:click|stopPropagation={() => {
|
|
194
|
+
editor.reloadWebsocket()
|
|
195
|
+
}}
|
|
196
|
+
>
|
|
197
|
+
Reload assistants (status: {#if lang == 'deno'}<span
|
|
198
|
+
class={websocketAlive.deno ? 'text-green-600' : 'text-red-600'}>deno</span
|
|
199
|
+
>{:else if lang == 'python3'}<span
|
|
200
|
+
class={websocketAlive.pyright ? 'text-green-600' : 'text-red-600'}>pyright</span
|
|
201
|
+
>
|
|
202
|
+
<span class={websocketAlive.black ? 'text-green-600' : 'text-red-600'}> black</span>{/if})
|
|
203
|
+
</button>
|
|
204
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type Editor from './Editor.svelte';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
lang: 'python3' | 'deno';
|
|
6
|
+
editor: Editor;
|
|
7
|
+
websocketAlive: {
|
|
8
|
+
pyright: boolean;
|
|
9
|
+
black: boolean;
|
|
10
|
+
deno: boolean;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
};
|
|
16
|
+
slots: {};
|
|
17
|
+
};
|
|
18
|
+
export declare type EditorBarProps = typeof __propDef.props;
|
|
19
|
+
export declare type EditorBarEvents = typeof __propDef.events;
|
|
20
|
+
export declare type EditorBarSlots = typeof __propDef.slots;
|
|
21
|
+
export default class EditorBar extends SvelteComponentTyped<EditorBarProps, EditorBarEvents, EditorBarSlots> {
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { page } from '$app/stores';
|
|
3
3
|
import { FlowService, ScriptService } from '../gen';
|
|
4
4
|
import { clearPreviewResults, hubScripts, workspaceStore } from '../stores';
|
|
5
|
-
import { sendUserToast, setQueryWithoutLoad } from '../utils';
|
|
5
|
+
import { loadHubScripts, sendUserToast, setQueryWithoutLoad } from '../utils';
|
|
6
6
|
import { faFileExport, faFileImport } from '@fortawesome/free-solid-svg-icons';
|
|
7
7
|
import { onMount } from 'svelte';
|
|
8
8
|
import Icon from 'svelte-awesome';
|
|
@@ -14,15 +14,6 @@ export let initialPath = '';
|
|
|
14
14
|
let pathError = '';
|
|
15
15
|
let mode;
|
|
16
16
|
$: step = Number($page.url.searchParams.get('step')) || 1;
|
|
17
|
-
async function loadSearchData() {
|
|
18
|
-
const scripts = await ScriptService.listHubScripts();
|
|
19
|
-
$hubScripts = scripts.map((x) => ({
|
|
20
|
-
path: `hub/${x.id}/${x.summary.toLowerCase().replaceAll(/\s+/g, '_')}`,
|
|
21
|
-
summary: `${x.summary} (${x.app})`,
|
|
22
|
-
approved: x.approved,
|
|
23
|
-
is_trigger: x.is_trigger
|
|
24
|
-
}));
|
|
25
|
-
}
|
|
26
17
|
async function saveFlow() {
|
|
27
18
|
const newFlow = flowToMode($flowStore, mode);
|
|
28
19
|
if (initialPath === '') {
|
|
@@ -60,7 +51,7 @@ flowStore.subscribe((flow) => {
|
|
|
60
51
|
setQueryWithoutLoad($page.url, 'state', btoa(JSON.stringify(flowToMode(flow, mode))));
|
|
61
52
|
});
|
|
62
53
|
onMount(() => {
|
|
63
|
-
|
|
54
|
+
loadHubScripts();
|
|
64
55
|
clearPreviewResults();
|
|
65
56
|
});
|
|
66
57
|
</script>
|
|
@@ -7,6 +7,8 @@ import { FlowModuleValue } from '../gen';
|
|
|
7
7
|
import github from 'svelte-highlight/styles/github';
|
|
8
8
|
import { slide } from 'svelte/transition';
|
|
9
9
|
import Tabs from './Tabs.svelte';
|
|
10
|
+
import SchemaViewer from './SchemaViewer.svelte';
|
|
11
|
+
import FieldHeader from './FieldHeader.svelte';
|
|
10
12
|
export let flow;
|
|
11
13
|
let flowFiltered = {
|
|
12
14
|
summary: flow.summary,
|
|
@@ -27,22 +29,48 @@ let open = {};
|
|
|
27
29
|
<Tabs
|
|
28
30
|
tabs={[
|
|
29
31
|
['ui', 'Flow rendered'],
|
|
30
|
-
['json', 'JSON']
|
|
32
|
+
['json', 'JSON'],
|
|
33
|
+
['schema', 'Input schema of the flow']
|
|
31
34
|
]}
|
|
32
35
|
bind:tab
|
|
33
36
|
/>
|
|
34
37
|
{/if}
|
|
35
38
|
{#if tab == 'ui'}
|
|
36
39
|
<div class="flow-root w-full p-4">
|
|
37
|
-
<p class="font-black text-lg
|
|
38
|
-
<span>
|
|
40
|
+
<p class="font-black text-lg w-full ml-2">
|
|
41
|
+
<span>Inputs</span>
|
|
42
|
+
</p>
|
|
43
|
+
{#if flow.schema && flow.schema.properties && Object.keys(flow.schema.properties).length > 0 && flow.schema}
|
|
44
|
+
<ul class="my-4 ml-6">
|
|
45
|
+
{#each Object.entries(flow.schema.properties) as [inp, v]}
|
|
46
|
+
<li class="list-disc flex flex-row">
|
|
47
|
+
<FieldHeader
|
|
48
|
+
label={inp}
|
|
49
|
+
required={flow.schema.required?.includes(inp)}
|
|
50
|
+
type={v?.type}
|
|
51
|
+
contentEncoding={v?.contentEncoding}
|
|
52
|
+
format={v?.format}
|
|
53
|
+
itemsType={v?.itemsType}
|
|
54
|
+
/><span class="ml-4 mt-2 text-xs"
|
|
55
|
+
>{v.default != undefined ? 'default: ' + JSON.stringify(v.default) : ''}</span
|
|
56
|
+
>
|
|
57
|
+
</li>
|
|
58
|
+
{/each}
|
|
59
|
+
</ul>
|
|
60
|
+
{:else}
|
|
61
|
+
<div class="text-gray-700 text-xs italic mb-4">
|
|
62
|
+
This script has no argument or is ill-defined
|
|
63
|
+
</div>
|
|
64
|
+
{/if}
|
|
65
|
+
<p class="font-black text-lg my-6 w-full ml-2">
|
|
66
|
+
<span>{flow?.value?.modules?.length} Steps </span>
|
|
39
67
|
<span class="mt-4" />
|
|
40
68
|
</p>
|
|
41
69
|
<ul class="-mb-8 w-full">
|
|
42
|
-
{#each flow
|
|
70
|
+
{#each flow?.value?.modules ?? [] as mod, i}
|
|
43
71
|
<li class="w-full">
|
|
44
72
|
<div class="relative pb-8 w-full">
|
|
45
|
-
{#if i < (flow
|
|
73
|
+
{#if i < (flow?.value?.modules ?? []).length - 1}
|
|
46
74
|
<span
|
|
47
75
|
class="absolute top-4 left-4 -ml-px h-full w-0.5 bg-gray-200"
|
|
48
76
|
aria-hidden="true"
|
|
@@ -58,33 +86,33 @@ let open = {};
|
|
|
58
86
|
<div class="min-w-0 flex-1 pt-1.5 flex justify-between space-x-4 w-full">
|
|
59
87
|
<div class="w-full">
|
|
60
88
|
<p class="text-sm text-gray-500">
|
|
61
|
-
{#if mod
|
|
89
|
+
{#if mod?.value?.type == FlowModuleValue.type.SCRIPT}
|
|
62
90
|
Script at path <a
|
|
63
91
|
target="_blank"
|
|
64
|
-
href={scriptPathToHref(mod
|
|
65
|
-
class="font-medium text-gray-900">{mod
|
|
92
|
+
href={scriptPathToHref(mod?.value?.path ?? '')}
|
|
93
|
+
class="font-medium text-gray-900">{mod?.value?.path}</a
|
|
66
94
|
>
|
|
67
|
-
{:else if mod
|
|
95
|
+
{:else if mod?.value?.type == FlowModuleValue.type.RAWSCRIPT}
|
|
68
96
|
<button
|
|
69
97
|
on:click={() => (open[i] = !open[i])}
|
|
70
98
|
class="mb-2 underline text-black"
|
|
71
99
|
>
|
|
72
|
-
Raw {mod
|
|
100
|
+
Raw {mod?.value?.language} script {open[i] ? '(-)' : '(+)'}</button
|
|
73
101
|
>
|
|
74
102
|
|
|
75
103
|
{#if open[i]}
|
|
76
104
|
<div transition:slide class="border border-black p-2 bg-gray-50 w-full">
|
|
77
105
|
<Highlight
|
|
78
|
-
language={mod
|
|
79
|
-
code={mod
|
|
106
|
+
language={mod?.value?.language == 'deno' ? typescript : python}
|
|
107
|
+
code={mod?.value?.content}
|
|
80
108
|
/>
|
|
81
109
|
</div>
|
|
82
110
|
{/if}
|
|
83
|
-
{:else if mod
|
|
84
|
-
Flow at path {mod
|
|
85
|
-
{:else if mod
|
|
111
|
+
{:else if mod?.value?.type == FlowModuleValue.type.FLOW}
|
|
112
|
+
Flow at path {mod?.value?.path}
|
|
113
|
+
{:else if mod?.value?.type == FlowModuleValue.type.FORLOOPFLOW}
|
|
86
114
|
For loop over step {i}'s result':
|
|
87
|
-
<svelte:self flow={mod
|
|
115
|
+
<svelte:self flow={mod?.value} embedded={true} />
|
|
88
116
|
{/if}
|
|
89
117
|
</p>
|
|
90
118
|
</div>
|
|
@@ -95,6 +123,14 @@ let open = {};
|
|
|
95
123
|
{/each}
|
|
96
124
|
</ul>
|
|
97
125
|
</div>
|
|
98
|
-
{:else}
|
|
126
|
+
{:else if tab == 'json'}
|
|
127
|
+
<button
|
|
128
|
+
on:click={async () => {
|
|
129
|
+
await navigator.clipboard.writeText(JSON.stringify(flowFiltered, null, 4))
|
|
130
|
+
}}
|
|
131
|
+
class="default-primary-button-v2 float-right my-2 ml-4">copy content</button
|
|
132
|
+
>
|
|
99
133
|
<Highlight language={json} code={JSON.stringify(flowFiltered, null, 4)} />
|
|
134
|
+
{:else if tab == 'schema'}
|
|
135
|
+
<SchemaViewer schema={flow.schema} />
|
|
100
136
|
{/if}
|
|
@@ -4,6 +4,7 @@ import { buildExtraLib, objectToTsType, schemaToObject, schemaToTsType } from '.
|
|
|
4
4
|
import { faRobot } from '@fortawesome/free-solid-svg-icons';
|
|
5
5
|
import Icon from 'svelte-awesome';
|
|
6
6
|
import Editor from './Editor.svelte';
|
|
7
|
+
import EditorBar from './EditorBar.svelte';
|
|
7
8
|
import FlowPreview from './FlowPreview.svelte';
|
|
8
9
|
import FlowInputs from './flows/FlowInputs.svelte';
|
|
9
10
|
import FlowModuleHeader from './flows/FlowModuleHeader.svelte';
|
|
@@ -15,6 +16,8 @@ export let mode;
|
|
|
15
16
|
export let i;
|
|
16
17
|
export let mod;
|
|
17
18
|
export let args = {};
|
|
19
|
+
let editor;
|
|
20
|
+
let websocketAlive = { pyright: false, black: false, deno: false };
|
|
18
21
|
$: schema = $schemasStore[i];
|
|
19
22
|
$: shouldPick = mod.value.path === '' && mod.value.language === undefined;
|
|
20
23
|
$: previousSchema = i === 0 ? schemaToObject($flowStore?.schema) : $previewResults[i];
|
|
@@ -66,7 +69,12 @@ $: extraLib = buildExtraLib(i === 0 ? schemaToTsType($flowStore?.schema) : objec
|
|
|
66
69
|
/>
|
|
67
70
|
{/if}
|
|
68
71
|
{#if mod.value.type === FlowModuleValue.type.RAWSCRIPT}
|
|
72
|
+
<div class="p-1 overflow-hidden">
|
|
73
|
+
<EditorBar {editor} {websocketAlive} lang={mod.value.language ?? 'deno'} />
|
|
74
|
+
</div>
|
|
69
75
|
<Editor
|
|
76
|
+
bind:websocketAlive
|
|
77
|
+
bind:this={editor}
|
|
70
78
|
class="h-80 border p-2 rounded"
|
|
71
79
|
bind:code={mod.value.content}
|
|
72
80
|
deno={mod.value.language === FlowModuleValue.language.DENO}
|
package/components/Path.svelte
CHANGED
|
@@ -52,8 +52,8 @@ let scheduledForStr;
|
|
|
52
52
|
{#if runnable?.schema}
|
|
53
53
|
{#if detailed}
|
|
54
54
|
<h2>
|
|
55
|
-
Arguments<Tooltip
|
|
56
|
-
>
|
|
55
|
+
Arguments <Tooltip
|
|
56
|
+
>The optional fields, if left blank, will use the placeholder value as default.</Tooltip
|
|
57
57
|
>
|
|
58
58
|
</h2>
|
|
59
59
|
{/if}
|
|
@@ -67,7 +67,7 @@ let viewJsonSchema = false;
|
|
|
67
67
|
</TableCustom>
|
|
68
68
|
</div>
|
|
69
69
|
{:else}
|
|
70
|
-
<div class="text-gray-700 text-xs italic">This script has no
|
|
70
|
+
<div class="text-gray-700 text-xs italic">This script has no arguments</div>
|
|
71
71
|
{/if}
|
|
72
72
|
</div>
|
|
73
73
|
<div class={viewJsonSchema ? '' : 'hidden'}>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<script>import { JobService, Job, CompletedJob, VariableService,
|
|
2
|
-
import {
|
|
1
|
+
<script>import { JobService, Job, CompletedJob, VariableService, ScriptService } from '../gen';
|
|
2
|
+
import { emptySchema, displayDate } from '../utils';
|
|
3
3
|
import { fade } from 'svelte/transition';
|
|
4
4
|
import Icon from 'svelte-awesome';
|
|
5
|
-
import { faCheck, faChevronDown, faChevronUp, faExclamationTriangle, faMagic,
|
|
5
|
+
import { faCheck, faChevronDown, faChevronUp, faExclamationTriangle, faMagic, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons';
|
|
6
6
|
import Editor from './Editor.svelte';
|
|
7
7
|
import Tooltip from './Tooltip.svelte';
|
|
8
8
|
import { onDestroy, onMount } from 'svelte';
|
|
@@ -10,17 +10,14 @@ import { userStore, workspaceStore } from '../stores';
|
|
|
10
10
|
import TableCustom from './TableCustom.svelte';
|
|
11
11
|
import { check } from 'svelte-awesome/icons';
|
|
12
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
13
|
import { inferArgs } from '../infer';
|
|
20
14
|
// @ts-ignore
|
|
21
15
|
import { VSplitPane } from 'svelte-split-pane';
|
|
22
16
|
import SchemaForm from './SchemaForm.svelte';
|
|
23
17
|
import DisplayResult from './DisplayResult.svelte';
|
|
18
|
+
import EditorBar from './EditorBar.svelte';
|
|
19
|
+
import { Highlight } from 'svelte-highlight';
|
|
20
|
+
import { json, python, typescript } from 'svelte-highlight/languages';
|
|
24
21
|
// Exported
|
|
25
22
|
export let schema = emptySchema();
|
|
26
23
|
export let code;
|
|
@@ -30,6 +27,9 @@ export let lang;
|
|
|
30
27
|
export let viewPreview = true;
|
|
31
28
|
export let previewTab = 'logs';
|
|
32
29
|
let websocketAlive = { pyright: false, black: false, deno: false };
|
|
30
|
+
let modalViewerTitle = '';
|
|
31
|
+
let modalViewerContent;
|
|
32
|
+
let modalViewerMode = 'logs';
|
|
33
33
|
// Internal state
|
|
34
34
|
let editor;
|
|
35
35
|
// Preview args input
|
|
@@ -41,14 +41,6 @@ let previewIntervalId;
|
|
|
41
41
|
let previewJob;
|
|
42
42
|
let pastPreviews = [];
|
|
43
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
44
|
let syncIteration = 0;
|
|
53
45
|
let ITERATIONS_BEFORE_SLOW_REFRESH = 100;
|
|
54
46
|
let lastSave;
|
|
@@ -158,20 +150,6 @@ function syncer(id) {
|
|
|
158
150
|
loadPreviewJob(id);
|
|
159
151
|
}
|
|
160
152
|
}
|
|
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
153
|
let syncCode;
|
|
176
154
|
onMount(() => {
|
|
177
155
|
syncCode = setInterval(() => {
|
|
@@ -194,29 +172,6 @@ onDestroy(() => {
|
|
|
194
172
|
});
|
|
195
173
|
</script>
|
|
196
174
|
|
|
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
175
|
<Modal bind:this={modalViewer}>
|
|
221
176
|
<div slot="title">{modalViewerTitle}</div>
|
|
222
177
|
<div slot="content">
|
|
@@ -236,101 +191,7 @@ onDestroy(() => {
|
|
|
236
191
|
</div></Modal
|
|
237
192
|
>
|
|
238
193
|
|
|
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
194
|
<VSplitPane
|
|
333
|
-
class="h-full"
|
|
334
195
|
topPanelSize={viewPreview ? '75%' : '90%'}
|
|
335
196
|
downPanelSize={viewPreview ? '25%' : '10%'}
|
|
336
197
|
updateCallback={() => {
|
|
@@ -342,46 +203,7 @@ onDestroy(() => {
|
|
|
342
203
|
<top slot="top">
|
|
343
204
|
<div class="flex flex-col h-full">
|
|
344
205
|
<div class="header">
|
|
345
|
-
<
|
|
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>
|
|
206
|
+
<EditorBar {editor} {lang} {websocketAlive} />
|
|
385
207
|
</div>
|
|
386
208
|
<div class="flex-1 overflow-hidden">
|
|
387
209
|
<Editor
|
|
@@ -395,6 +217,7 @@ onDestroy(() => {
|
|
|
395
217
|
formatAction={() => {
|
|
396
218
|
code = getEditor().getCode()
|
|
397
219
|
localStorage.setItem(path ?? 'last_save', code)
|
|
220
|
+
lastSave = code
|
|
398
221
|
}}
|
|
399
222
|
class="h-full"
|
|
400
223
|
deno={lang == 'deno'}
|
|
@@ -9,6 +9,7 @@ import Modal from './Modal.svelte';
|
|
|
9
9
|
import { Highlight } from 'svelte-highlight';
|
|
10
10
|
import { python, typescript } from 'svelte-highlight/languages';
|
|
11
11
|
import github from 'svelte-highlight/styles/github';
|
|
12
|
+
import { getScript, getScriptByPath } from '../utils';
|
|
12
13
|
export let scriptPath = undefined;
|
|
13
14
|
export let allowFlow = false;
|
|
14
15
|
export let allowHub = false;
|
|
@@ -23,20 +24,6 @@ let options = [['Script', 'script']];
|
|
|
23
24
|
allowHub && options.unshift(['Hub', 'hub']);
|
|
24
25
|
allowFlow && options.push(['Flow', 'flow']);
|
|
25
26
|
const dispatch = createEventDispatcher();
|
|
26
|
-
async function getScript() {
|
|
27
|
-
if (itemKind == 'hub') {
|
|
28
|
-
code = await ScriptService.getHubScriptContentByPath({ path: scriptPath });
|
|
29
|
-
lang = Script.language.DENO;
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
const script = await ScriptService.getScriptByPath({
|
|
33
|
-
workspace: $workspaceStore,
|
|
34
|
-
path: scriptPath
|
|
35
|
-
});
|
|
36
|
-
code = script.content;
|
|
37
|
-
lang = script.language;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
27
|
async function loadItems() {
|
|
41
28
|
if (itemKind == 'flow') {
|
|
42
29
|
items = await FlowService.listFlows({ workspace: $workspaceStore });
|
|
@@ -86,7 +73,9 @@ $: {
|
|
|
86
73
|
<button
|
|
87
74
|
class="text-xs text-blue-500"
|
|
88
75
|
on:click={async () => {
|
|
89
|
-
await
|
|
76
|
+
const { language, content } = await getScriptByPath(scriptPath ?? '')
|
|
77
|
+
code = content
|
|
78
|
+
lang = language
|
|
90
79
|
modalViewer.openModal()
|
|
91
80
|
}}>show code</button
|
|
92
81
|
>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script>import { FlowModuleValue, Script } from '../../gen';
|
|
2
|
+
import { getScriptByPath } from '../../utils';
|
|
2
3
|
import { faCode, faCodeBranch, faSave, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
|
3
4
|
import Icon from 'svelte-awesome';
|
|
4
5
|
import { Highlight } from 'svelte-highlight';
|
|
@@ -6,14 +7,14 @@ import { python, typescript } from 'svelte-highlight/languages';
|
|
|
6
7
|
import github from 'svelte-highlight/styles/github';
|
|
7
8
|
import Modal from '../Modal.svelte';
|
|
8
9
|
import { createScriptFromInlineScript, fork, removeModule } from './flowStore';
|
|
9
|
-
import {
|
|
10
|
+
import { scrollIntoView } from './utils';
|
|
10
11
|
export let open;
|
|
11
12
|
export let i;
|
|
12
13
|
export let shouldPick = false;
|
|
13
14
|
export let mod;
|
|
14
15
|
let modalViewer;
|
|
15
16
|
let modalViewerContent = '';
|
|
16
|
-
let modalViewerLanguage =
|
|
17
|
+
let modalViewerLanguage = 'deno';
|
|
17
18
|
async function viewCode() {
|
|
18
19
|
const { content, language } = await getScriptByPath(mod.value.path);
|
|
19
20
|
modalViewerContent = content;
|
|
@@ -6,10 +6,6 @@ export declare function flattenForloopFlows(flow: Flow): Flow;
|
|
|
6
6
|
export declare function getTypeAsString(arg: any): string;
|
|
7
7
|
export declare function formatValue(arg: any): any;
|
|
8
8
|
export declare function getFirstStepSchema(flow: Flow): Promise<Schema>;
|
|
9
|
-
export declare function getScriptByPath(path: string): Promise<{
|
|
10
|
-
content: string;
|
|
11
|
-
language: FlowModuleValue.language;
|
|
12
|
-
}>;
|
|
13
9
|
export declare function createInlineScriptModuleFromPath(path: string): Promise<FlowModuleValue>;
|
|
14
10
|
export declare function scrollIntoView(el: any): void;
|
|
15
11
|
export declare function loadSchemaFromModule(module: FlowModule): Promise<{
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { FlowModuleValue, InputTransform, ScriptService } from '../../gen';
|
|
2
2
|
import { inferArgs } from '../../infer';
|
|
3
3
|
import { loadSchema } from '../../scripts';
|
|
4
|
-
import {
|
|
5
|
-
import { emptySchema } from '../../utils';
|
|
6
|
-
import { get } from 'svelte/store';
|
|
4
|
+
import { emptySchema, getScriptByPath } from '../../utils';
|
|
7
5
|
export function flowToMode(flow, mode) {
|
|
8
6
|
if (mode == 'pull') {
|
|
9
7
|
const newFlow = JSON.parse(JSON.stringify(flow));
|
|
@@ -66,25 +64,6 @@ export async function getFirstStepSchema(flow) {
|
|
|
66
64
|
}
|
|
67
65
|
return emptySchema();
|
|
68
66
|
}
|
|
69
|
-
export async function getScriptByPath(path) {
|
|
70
|
-
if (path.startsWith('hub/')) {
|
|
71
|
-
const content = await ScriptService.getHubScriptContentByPath({ path });
|
|
72
|
-
return {
|
|
73
|
-
content,
|
|
74
|
-
language: FlowModuleValue.language.DENO
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
const script = await ScriptService.getScriptByPath({
|
|
79
|
-
workspace: get(workspaceStore),
|
|
80
|
-
path: path ?? ''
|
|
81
|
-
});
|
|
82
|
-
return {
|
|
83
|
-
content: script.content,
|
|
84
|
-
language: script.language
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
67
|
export async function createInlineScriptModuleFromPath(path) {
|
|
89
68
|
const { content, language } = await getScriptByPath(path);
|
|
90
69
|
return {
|
|
@@ -121,7 +100,7 @@ export async function loadSchemaFromModule(module) {
|
|
|
121
100
|
input_transform = keys.reduce((accu, key) => {
|
|
122
101
|
accu[key] = {
|
|
123
102
|
type: 'static',
|
|
124
|
-
value:
|
|
103
|
+
value: undefined
|
|
125
104
|
};
|
|
126
105
|
return accu;
|
|
127
106
|
}, {});
|
package/gen/core/OpenAPI.js
CHANGED
package/gen/index.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export type { MainArgSignature } from './models/MainArgSignature';
|
|
|
30
30
|
export type { NewSchedule } from './models/NewSchedule';
|
|
31
31
|
export type { NewToken } from './models/NewToken';
|
|
32
32
|
export type { NewUser } from './models/NewUser';
|
|
33
|
+
export type { OpenFlow } from './models/OpenFlow';
|
|
33
34
|
export { Preview } from './models/Preview';
|
|
34
35
|
export { QueuedJob } from './models/QueuedJob';
|
|
35
36
|
export type { Resource } from './models/Resource';
|
|
@@ -2,6 +2,19 @@ import type { Flow } from '../models/Flow';
|
|
|
2
2
|
import type { FlowValue } from '../models/FlowValue';
|
|
3
3
|
import type { CancelablePromise } from '../core/CancelablePromise';
|
|
4
4
|
export declare class FlowService {
|
|
5
|
+
/**
|
|
6
|
+
* list all available hub flows
|
|
7
|
+
* @returns any hub flows list
|
|
8
|
+
* @throws ApiError
|
|
9
|
+
*/
|
|
10
|
+
static listHubFlows(): CancelablePromise<Array<{
|
|
11
|
+
id: number;
|
|
12
|
+
flow_id: number;
|
|
13
|
+
summary: string;
|
|
14
|
+
apps: Array<string>;
|
|
15
|
+
approved: boolean;
|
|
16
|
+
votes: number;
|
|
17
|
+
}>>;
|
|
5
18
|
/**
|
|
6
19
|
* list all available flows
|
|
7
20
|
* @returns Flow All available flow
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { OpenAPI } from '../core/OpenAPI';
|
|
2
2
|
import { request as __request } from '../core/request';
|
|
3
3
|
export class FlowService {
|
|
4
|
+
/**
|
|
5
|
+
* list all available hub flows
|
|
6
|
+
* @returns any hub flows list
|
|
7
|
+
* @throws ApiError
|
|
8
|
+
*/
|
|
9
|
+
static listHubFlows() {
|
|
10
|
+
return __request(OpenAPI, {
|
|
11
|
+
method: 'GET',
|
|
12
|
+
url: '/flows/hub/list',
|
|
13
|
+
});
|
|
14
|
+
}
|
|
4
15
|
/**
|
|
5
16
|
* list all available flows
|
|
6
17
|
* @returns Flow All available flow
|
|
@@ -9,11 +9,22 @@ export declare class ScriptService {
|
|
|
9
9
|
*/
|
|
10
10
|
static listHubScripts(): CancelablePromise<Array<{
|
|
11
11
|
id: number;
|
|
12
|
+
ask_id: number;
|
|
12
13
|
summary: string;
|
|
13
14
|
app: string;
|
|
14
15
|
approved: boolean;
|
|
15
16
|
is_trigger: boolean;
|
|
17
|
+
votes: number;
|
|
18
|
+
views: number;
|
|
16
19
|
}>>;
|
|
20
|
+
/**
|
|
21
|
+
* get hub flow by id
|
|
22
|
+
* @returns string flow
|
|
23
|
+
* @throws ApiError
|
|
24
|
+
*/
|
|
25
|
+
static getHubFlowById({ id, }: {
|
|
26
|
+
id: number;
|
|
27
|
+
}): CancelablePromise<string>;
|
|
17
28
|
/**
|
|
18
29
|
* get hub script content by path
|
|
19
30
|
* @returns string script details
|
|
@@ -12,6 +12,20 @@ export class ScriptService {
|
|
|
12
12
|
url: '/scripts/hub/list',
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* get hub flow by id
|
|
17
|
+
* @returns string flow
|
|
18
|
+
* @throws ApiError
|
|
19
|
+
*/
|
|
20
|
+
static getHubFlowById({ id, }) {
|
|
21
|
+
return __request(OpenAPI, {
|
|
22
|
+
method: 'GET',
|
|
23
|
+
url: '/flows/hub/get/{id}',
|
|
24
|
+
path: {
|
|
25
|
+
'id': id,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
}
|
|
15
29
|
/**
|
|
16
30
|
* get hub script content by path
|
|
17
31
|
* @returns string script details
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "windmill-components",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.42",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@playwright/test": "^1.23.4",
|
|
6
6
|
"@sveltejs/adapter-static": "^1.0.0-next.37",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"eslint-config-prettier": "^8.3.0",
|
|
18
18
|
"eslint-plugin-svelte3": "^4.0.0",
|
|
19
19
|
"openapi-typescript-codegen": "^0.23.0",
|
|
20
|
+
"path-browserify": "^1.0.1",
|
|
20
21
|
"postcss": "^8.4.5",
|
|
21
22
|
"postcss-load-config": "^4.0.1",
|
|
22
23
|
"prettier": "^2.7.1",
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
"./components/DisplayResult.svelte": "./components/DisplayResult.svelte",
|
|
65
66
|
"./components/Dropdown.svelte": "./components/Dropdown.svelte",
|
|
66
67
|
"./components/Editor.svelte": "./components/Editor.svelte",
|
|
68
|
+
"./components/EditorBar.svelte": "./components/EditorBar.svelte",
|
|
67
69
|
"./components/FieldHeader.svelte": "./components/FieldHeader.svelte",
|
|
68
70
|
"./components/FlowBuilder.svelte": "./components/FlowBuilder.svelte",
|
|
69
71
|
"./components/FlowEditor.svelte": "./components/FlowEditor.svelte",
|
|
@@ -164,6 +166,7 @@
|
|
|
164
166
|
"./gen/models/NewSchedule": "./gen/models/NewSchedule.js",
|
|
165
167
|
"./gen/models/NewToken": "./gen/models/NewToken.js",
|
|
166
168
|
"./gen/models/NewUser": "./gen/models/NewUser.js",
|
|
169
|
+
"./gen/models/OpenFlow": "./gen/models/OpenFlow.js",
|
|
167
170
|
"./gen/models/Preview": "./gen/models/Preview.js",
|
|
168
171
|
"./gen/models/QueuedJob": "./gen/models/QueuedJob.js",
|
|
169
172
|
"./gen/models/Resource": "./gen/models/Resource.js",
|
package/stores.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare const hubScripts: import("svelte/store").Writable<{
|
|
|
18
18
|
summary: string;
|
|
19
19
|
approved: boolean;
|
|
20
20
|
is_trigger: boolean;
|
|
21
|
+
app: string;
|
|
21
22
|
}[] | undefined>;
|
|
22
23
|
export declare function clearStores(): void;
|
|
23
24
|
export declare const previewResults: import("svelte/store").Writable<Record<number, Object>>;
|
package/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type User } from './gen';
|
|
2
2
|
import type { Schema } from './common';
|
|
3
|
-
import type
|
|
3
|
+
import { type UserExt } from './stores';
|
|
4
4
|
export declare function isToday(someDate: Date): boolean;
|
|
5
5
|
export declare function daysAgo(someDate: Date): number;
|
|
6
6
|
export declare function secondsAgo(date: Date): number;
|
|
@@ -65,3 +65,16 @@ export declare function objectToTsType(object: Object): string;
|
|
|
65
65
|
export declare type InputCat = "string" | "number" | "boolean" | "list" | "resource-object" | "enum" | "date" | "base64" | "resource-string" | "object";
|
|
66
66
|
export declare function setInputCat(type: string | undefined, format: string | undefined, itemsType: string | undefined, enum_: any, contentEncoding: string | undefined): InputCat;
|
|
67
67
|
export declare function scriptPathToHref(path: string): string;
|
|
68
|
+
export declare function getScriptByPath(path: string): Promise<{
|
|
69
|
+
content: string;
|
|
70
|
+
language: 'deno' | 'python3';
|
|
71
|
+
}>;
|
|
72
|
+
export declare function loadHubScripts(): Promise<void>;
|
|
73
|
+
export declare function loadHubFlows(): Promise<{
|
|
74
|
+
id: number;
|
|
75
|
+
flow_id: number;
|
|
76
|
+
summary: string;
|
|
77
|
+
apps: string[];
|
|
78
|
+
approved: boolean;
|
|
79
|
+
votes: number;
|
|
80
|
+
}[]>;
|
package/utils.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
2
2
|
import { goto } from '$app/navigation';
|
|
3
|
+
import { FlowService, Script, ScriptService } from './gen';
|
|
3
4
|
import { toast } from '@zerodevx/svelte-toast';
|
|
5
|
+
import { get } from 'svelte/store';
|
|
6
|
+
import { hubScripts, workspaceStore } from './stores';
|
|
4
7
|
export function isToday(someDate) {
|
|
5
8
|
const today = new Date();
|
|
6
9
|
return (someDate.getDate() == today.getDate() &&
|
|
@@ -351,9 +354,47 @@ export function setInputCat(type, format, itemsType, enum_, contentEncoding) {
|
|
|
351
354
|
}
|
|
352
355
|
export function scriptPathToHref(path) {
|
|
353
356
|
if (path.startsWith('hub/')) {
|
|
354
|
-
return 'https://hub.windmill.dev/
|
|
357
|
+
return 'https://hub.windmill.dev/from_version/' + path.substring(4);
|
|
355
358
|
}
|
|
356
359
|
else {
|
|
357
360
|
return `/scripts/get/${path}`;
|
|
358
361
|
}
|
|
359
362
|
}
|
|
363
|
+
export async function getScriptByPath(path) {
|
|
364
|
+
if (path.startsWith('hub/')) {
|
|
365
|
+
const content = await ScriptService.getHubScriptContentByPath({ path });
|
|
366
|
+
return {
|
|
367
|
+
content,
|
|
368
|
+
language: 'deno'
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
const script = await ScriptService.getScriptByPath({
|
|
373
|
+
workspace: get(workspaceStore),
|
|
374
|
+
path: path ?? ''
|
|
375
|
+
});
|
|
376
|
+
return {
|
|
377
|
+
content: script.content,
|
|
378
|
+
language: script.language
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
export async function loadHubScripts() {
|
|
383
|
+
const scripts = await ScriptService.listHubScripts();
|
|
384
|
+
const processed = scripts.map((x) => ({
|
|
385
|
+
path: `hub/${x.id}/${x.summary.toLowerCase().replaceAll(/\s+/g, '_')}`,
|
|
386
|
+
summary: `${x.summary} (${x.app}) ${x.views} uses`,
|
|
387
|
+
approved: x.approved,
|
|
388
|
+
is_trigger: x.is_trigger,
|
|
389
|
+
app: x.app,
|
|
390
|
+
views: x.views,
|
|
391
|
+
votes: x.votes,
|
|
392
|
+
ask_id: x.ask_id,
|
|
393
|
+
})).sort((a, b) => b.views - a.views);
|
|
394
|
+
hubScripts.set(processed);
|
|
395
|
+
}
|
|
396
|
+
export async function loadHubFlows() {
|
|
397
|
+
const flows = await FlowService.listHubFlows();
|
|
398
|
+
const processed = flows.sort((a, b) => b.votes - a.votes);
|
|
399
|
+
return processed;
|
|
400
|
+
}
|