windmill-components 1.60.1 → 1.60.3
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/AppConnect.svelte +4 -0
- package/components/ArgInput.svelte +0 -1
- package/components/ArgInput.svelte.d.ts +0 -2
- package/components/DisplayResult.svelte +9 -6
- package/components/FlowMetadata.svelte +19 -3
- package/components/FlowPreviewContent.svelte +15 -9
- package/components/InputTransformForm.svelte +1 -2
- package/components/JobArgs.svelte +1 -1
- package/components/ModulePreview.svelte +2 -1
- package/components/Popover.model.d.ts +4 -0
- package/components/Popover.model.js +3 -0
- package/components/Popover.svelte +0 -2
- package/components/Popover.svelte.d.ts +2 -1
- package/components/ResourceEditor.svelte +11 -1
- package/components/ResourcePicker.svelte +10 -1
- package/components/RunForm.svelte +41 -37
- package/components/RunForm.svelte.d.ts +1 -0
- package/components/ScriptBuilder.svelte +3 -1
- package/components/ScriptEditor.svelte +1 -0
- package/components/TemplateEditor.svelte +14 -1
- package/components/TestJobLoader.svelte +1 -1
- package/components/Tooltip.svelte +8 -3
- package/components/Tooltip.svelte.d.ts +5 -0
- package/components/apps/components/buttons/AppButton.svelte +16 -0
- package/components/apps/components/dataDisplay/AppHtml.svelte +24 -12
- package/components/apps/components/dataDisplay/VegaLiteHtml.svelte +28 -0
- package/components/apps/components/dataDisplay/VegaLiteHtml.svelte.d.ts +23 -0
- package/components/apps/components/helpers/InputValue.svelte +24 -5
- package/components/apps/components/helpers/InputValue.svelte.d.ts +1 -0
- package/components/apps/components/helpers/RunnableComponent.svelte +5 -2
- package/components/apps/components/selectInputs/AppSelect.svelte +11 -3
- package/components/apps/components/table/AppTable.svelte +6 -12
- package/components/apps/editor/AppEditor.svelte +7 -2
- package/components/apps/editor/AppPreview.svelte +1 -1
- package/components/apps/editor/componentsPanel/data.js +5 -0
- package/components/apps/editor/contextPanel/ContextPanel.svelte +3 -2
- package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +4 -1
- package/components/apps/editor/inlineScriptsPanel/InlineScriptsPanelList.svelte +8 -56
- package/components/apps/editor/inlineScriptsPanel/utils.d.ts +15 -0
- package/components/apps/editor/inlineScriptsPanel/utils.js +28 -0
- package/components/apps/editor/settingsPanel/ComponentPanel.svelte +9 -14
- package/components/apps/editor/settingsPanel/ComponentPanel.svelte.d.ts +0 -3
- package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte +6 -2
- package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte.d.ts +4 -2
- package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte +8 -7
- package/components/apps/editor/settingsPanel/InputsSpecsEditor.svelte.d.ts +1 -1
- package/components/apps/editor/settingsPanel/Recompute.svelte +1 -1
- package/components/apps/editor/settingsPanel/TableActions.svelte +7 -2
- package/components/apps/editor/settingsPanel/common/PanelSection.svelte +10 -1
- package/components/apps/editor/settingsPanel/common/PanelSection.svelte.d.ts +1 -0
- package/components/apps/editor/settingsPanel/inputEditor/EvalInputEditor.svelte +25 -0
- package/components/apps/editor/settingsPanel/inputEditor/EvalInputEditor.svelte.d.ts +19 -0
- package/components/apps/inputType.d.ts +8 -1
- package/components/apps/types.d.ts +3 -2
- package/components/apps/utils.d.ts +2 -0
- package/components/apps/utils.js +11 -0
- package/components/common/button/Button.svelte +1 -1
- package/components/common/kbd/Kbd.svelte +6 -6
- package/components/common/table/Row.svelte +1 -1
- package/components/flows/content/CapturePayload.svelte +1 -1
- package/components/flows/content/FlowModuleComponent.svelte +4 -2
- package/components/flows/utils.js +1 -1
- package/components/icons/SurrealdbIcon.svelte +13 -0
- package/components/icons/SurrealdbIcon.svelte.d.ts +17 -0
- package/components/icons/index.d.ts +3 -1
- package/components/icons/index.js +3 -1
- package/components/propertyPicker/PropPicker.svelte +7 -1
- package/package.json +8 -3
- package/script_helpers.d.ts +3 -3
- package/script_helpers.js +18 -19
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { AppInput } from '../../inputType';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
id: string;
|
|
6
|
+
componentInput: AppInput | undefined;
|
|
7
|
+
horizontalAlignment?: 'left' | 'center' | 'right' | undefined;
|
|
8
|
+
verticalAlignment?: 'top' | 'center' | 'bottom' | undefined;
|
|
9
|
+
configuration: Record<string, AppInput>;
|
|
10
|
+
staticOutputs?: string[] | undefined;
|
|
11
|
+
};
|
|
12
|
+
events: {
|
|
13
|
+
[evt: string]: CustomEvent<any>;
|
|
14
|
+
};
|
|
15
|
+
slots: {};
|
|
16
|
+
};
|
|
17
|
+
export type VegaLiteHtmlProps = typeof __propDef.props;
|
|
18
|
+
export type VegaLiteHtmlEvents = typeof __propDef.events;
|
|
19
|
+
export type VegaLiteHtmlSlots = typeof __propDef.slots;
|
|
20
|
+
export default class VegaLiteHtml extends SvelteComponentTyped<VegaLiteHtmlProps, VegaLiteHtmlEvents, VegaLiteHtmlSlots> {
|
|
21
|
+
get staticOutputs(): string[];
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -1,28 +1,44 @@
|
|
|
1
1
|
<script>import { isCodeInjection } from '../../../flows/utils';
|
|
2
|
-
import {
|
|
2
|
+
import { getContext } from 'svelte';
|
|
3
3
|
import { accessPropertyByPath } from '../../utils';
|
|
4
4
|
export let input;
|
|
5
5
|
export let value;
|
|
6
6
|
export let id = undefined;
|
|
7
7
|
export let row = {};
|
|
8
|
+
export let error = '';
|
|
8
9
|
const { worldStore } = getContext('AppEditorContext');
|
|
9
10
|
$: state = $worldStore?.state;
|
|
10
11
|
$: input && $worldStore && row && handleConnection();
|
|
11
|
-
$: input &&
|
|
12
|
+
$: input && input.type == 'template' && $state && (value = getValue(input));
|
|
13
|
+
$: input && input.type == 'eval' && $state && (value = evalExpr(input));
|
|
12
14
|
function handleConnection() {
|
|
13
15
|
if (input.type === 'connected') {
|
|
14
16
|
$worldStore?.connect(input, onValueChange);
|
|
15
17
|
}
|
|
16
18
|
else if (input.type === 'row') {
|
|
17
|
-
setTimeout(() => (value = row[input['column']]), 0);
|
|
19
|
+
setTimeout(() => (value = row?.[input['column']]), 0);
|
|
18
20
|
}
|
|
19
21
|
else if (input.type === 'static' || input.type == 'template') {
|
|
20
22
|
setTimeout(() => (value = getValue(input)), 0);
|
|
21
23
|
}
|
|
24
|
+
else if (input.type == 'eval') {
|
|
25
|
+
setTimeout(() => ((value = evalExpr(input)), 0));
|
|
26
|
+
}
|
|
22
27
|
else {
|
|
23
28
|
setTimeout(() => (value = undefined), 0);
|
|
24
29
|
}
|
|
25
30
|
}
|
|
31
|
+
function evalExpr(input) {
|
|
32
|
+
try {
|
|
33
|
+
const r = eval_like(input.expr, computeGlobalContext());
|
|
34
|
+
error = '';
|
|
35
|
+
return r;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
error = e.message;
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
26
42
|
function computeGlobalContext() {
|
|
27
43
|
return Object.fromEntries(Object.entries($worldStore?.outputsById ?? {})
|
|
28
44
|
.filter(([k, _]) => k != id)
|
|
@@ -31,12 +47,15 @@ function computeGlobalContext() {
|
|
|
31
47
|
key,
|
|
32
48
|
Object.fromEntries(Object.entries(value ?? {}).map((x) => [x[0], x[1].peak()]))
|
|
33
49
|
];
|
|
34
|
-
})
|
|
50
|
+
})
|
|
51
|
+
.concat(row ? [['row', row]] : []));
|
|
35
52
|
}
|
|
36
53
|
export function getValue(input) {
|
|
37
54
|
if (input.type === 'template' && isCodeInjection(input.eval)) {
|
|
38
55
|
try {
|
|
39
|
-
|
|
56
|
+
const r = eval_like('`' + input.eval + '`', computeGlobalContext());
|
|
57
|
+
error = '';
|
|
58
|
+
return r;
|
|
40
59
|
}
|
|
41
60
|
catch (e) {
|
|
42
61
|
return e.message;
|
|
@@ -6,6 +6,7 @@ declare const __propDef: {
|
|
|
6
6
|
value: string | number | boolean | Record<string | number, any> | undefined;
|
|
7
7
|
id?: string | undefined;
|
|
8
8
|
row?: Record<string, any> | undefined;
|
|
9
|
+
error?: string | undefined;
|
|
9
10
|
getValue?: ((input: AppInput) => any) | undefined;
|
|
10
11
|
};
|
|
11
12
|
events: {
|
|
@@ -257,12 +257,15 @@ let lastStartedAt = Date.now();
|
|
|
257
257
|
<div class="p-2">
|
|
258
258
|
<Alert type="error" title="Error during execution">
|
|
259
259
|
See "Debug Runs" on the top right for more details
|
|
260
|
-
<pre
|
|
260
|
+
<pre
|
|
261
|
+
title={JSON.stringify(result.error, null, 4)}
|
|
262
|
+
class=" mt-2 text-2xs whitespace-pre-wrap">{JSON.stringify(result.error, null, 4)}</pre
|
|
263
|
+
>
|
|
261
264
|
</Alert>
|
|
262
265
|
<slot />
|
|
263
266
|
</div>
|
|
264
267
|
{:else}
|
|
265
|
-
<div class="
|
|
268
|
+
<div class="block w-full h-full">
|
|
266
269
|
<slot />
|
|
267
270
|
</div>
|
|
268
271
|
{/if}
|
|
@@ -12,10 +12,13 @@ let label;
|
|
|
12
12
|
let items;
|
|
13
13
|
let itemKey;
|
|
14
14
|
$: outputs = $worldStore?.outputsById[id];
|
|
15
|
-
function onChange(
|
|
16
|
-
|
|
15
|
+
function onChange(e) {
|
|
16
|
+
e?.stopPropagation();
|
|
17
|
+
window.dispatchEvent(new Event('pointerup'));
|
|
18
|
+
outputs?.result.set(e.detail?.[itemKey] || undefined);
|
|
17
19
|
}
|
|
18
|
-
|
|
20
|
+
let value = undefined;
|
|
21
|
+
$: items?.[0]?.['value'] != value && (value = items?.[0]?.['value']);
|
|
19
22
|
</script>
|
|
20
23
|
|
|
21
24
|
<InputValue {id} input={configuration.label} bind:value={label} />
|
|
@@ -28,7 +31,12 @@ const dispatch = createEventDispatcher();
|
|
|
28
31
|
class="select"
|
|
29
32
|
on:clear={onChange}
|
|
30
33
|
on:change={onChange}
|
|
34
|
+
on:focus={(e) => {
|
|
35
|
+
e?.stopPropagation()
|
|
36
|
+
window.dispatchEvent(new Event('pointerup'))
|
|
37
|
+
}}
|
|
31
38
|
{items}
|
|
39
|
+
{value}
|
|
32
40
|
placeholder="Select an item"
|
|
33
41
|
on:click={() => {
|
|
34
42
|
if (!$connectingInput.opened) {
|
|
@@ -29,13 +29,9 @@ const options = writable({
|
|
|
29
29
|
});
|
|
30
30
|
let table = createSvelteTable(options);
|
|
31
31
|
const { worldStore, staticOutputs: staticOutputsStore } = getContext('AppEditorContext');
|
|
32
|
-
let selectedRowIndex =
|
|
32
|
+
let selectedRowIndex = 0;
|
|
33
33
|
function toggleRow(row, rowIndex) {
|
|
34
|
-
if (selectedRowIndex
|
|
35
|
-
selectedRowIndex = -1;
|
|
36
|
-
outputs.selectedRow.set(null);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
34
|
+
if (selectedRowIndex !== rowIndex) {
|
|
39
35
|
selectedRowIndex = rowIndex;
|
|
40
36
|
outputs?.selectedRow.set(row.original);
|
|
41
37
|
}
|
|
@@ -101,7 +97,7 @@ $: result && rerender();
|
|
|
101
97
|
|
|
102
98
|
<div class="overflow-x-auto flex-1 w-full">
|
|
103
99
|
<table class="relative w-full border-b border-b-gray-200">
|
|
104
|
-
<thead class="sticky top-0 bg-gray-50 text-left">
|
|
100
|
+
<thead class="sticky top-0 z-40 bg-gray-50 text-left">
|
|
105
101
|
{#each $table.getHeaderGroups() as headerGroup}
|
|
106
102
|
<tr class="divide-x">
|
|
107
103
|
{#each headerGroup.headers as header}
|
|
@@ -121,9 +117,7 @@ $: result && rerender();
|
|
|
121
117
|
{/each}
|
|
122
118
|
{#if actionButtons.length > 0}
|
|
123
119
|
<th class="!p-0">
|
|
124
|
-
<span class="block px-4 py-4 text-sm font-semibold border-b">
|
|
125
|
-
Actions
|
|
126
|
-
</span>
|
|
120
|
+
<span class="block px-4 py-4 text-sm font-semibold border-b"> Actions </span>
|
|
127
121
|
</th>
|
|
128
122
|
{/if}
|
|
129
123
|
</tr>
|
|
@@ -133,11 +127,11 @@ $: result && rerender();
|
|
|
133
127
|
{#each $table.getRowModel().rows as row, rowIndex (row.id)}
|
|
134
128
|
<tr
|
|
135
129
|
class={classNames(
|
|
130
|
+
'last-of-type:!border-b-0',
|
|
136
131
|
selectedRowIndex === rowIndex
|
|
137
132
|
? 'bg-blue-100 hover:bg-blue-200'
|
|
138
133
|
: 'hover:bg-blue-50',
|
|
139
|
-
'divide-x',
|
|
140
|
-
'border-b w-full',
|
|
134
|
+
'divide-x w-full',
|
|
141
135
|
selectedRowIndex === rowIndex
|
|
142
136
|
? 'divide-blue-200 hover:divide-blue-300'
|
|
143
137
|
: 'divide-gray-200'
|
|
@@ -19,6 +19,7 @@ import InlineScriptsPanel from './inlineScriptsPanel/InlineScriptsPanel.svelte';
|
|
|
19
19
|
import SettingsPanel from './SettingsPanel.svelte';
|
|
20
20
|
import { fly } from 'svelte/transition';
|
|
21
21
|
import UnsavedConfirmationModal from '../../common/confirmationModal/UnsavedConfirmationModal.svelte';
|
|
22
|
+
import { page } from '$app/stores';
|
|
22
23
|
export let app;
|
|
23
24
|
export let path;
|
|
24
25
|
export let initialMode = 'dnd';
|
|
@@ -73,7 +74,11 @@ let mounted = false;
|
|
|
73
74
|
onMount(() => {
|
|
74
75
|
mounted = true;
|
|
75
76
|
});
|
|
76
|
-
$: context = {
|
|
77
|
+
$: context = {
|
|
78
|
+
email: $userStore?.email,
|
|
79
|
+
username: $userStore?.username,
|
|
80
|
+
query: Object.fromEntries($page.url.searchParams.entries())
|
|
81
|
+
};
|
|
77
82
|
$: mounted && ($worldStore = buildWorld($staticOutputs, $worldStore, context));
|
|
78
83
|
$: previewing = $mode === 'preview';
|
|
79
84
|
$: width = $breakpoint === 'sm' ? 'min-w-[400px] max-w-[656px]' : 'min-w-[710px] w-full';
|
|
@@ -170,7 +175,7 @@ else {
|
|
|
170
175
|
{#if $connectingInput.opened}
|
|
171
176
|
<div
|
|
172
177
|
class="fixed top-32 p-2 z-50 flex justify-center items-center"
|
|
173
|
-
transition:fly={{ duration: 100, y: -100 }}
|
|
178
|
+
transition:fly|local={{ duration: 100, y: -100 }}
|
|
174
179
|
>
|
|
175
180
|
<Alert title="Connecting" type="info">
|
|
176
181
|
<div class="flex gap-2 flex-col">
|
|
@@ -50,7 +50,7 @@ $: mounted && ($worldStore = buildWorld($staticOutputs, undefined, context));
|
|
|
50
50
|
$: width = $breakpoint === 'sm' ? 'max-w-[640px]' : 'w-full ';
|
|
51
51
|
</script>
|
|
52
52
|
|
|
53
|
-
<div class="h-full w-full {app.fullscreen ? '' : 'max-w-6xl'} mx-auto">
|
|
53
|
+
<div class="h-full max-h-[calc(100%-41px)] overflow-auto w-full {app.fullscreen ? '' : 'max-w-6xl'} mx-auto">
|
|
54
54
|
{#if $appStore.grid}
|
|
55
55
|
<div class={classNames('mx-auto pb-4', width)}>
|
|
56
56
|
<GridEditor {policy} />
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { page } from '$app/stores';
|
|
2
|
+
import { classNames } from '../../../../utils';
|
|
2
3
|
import { getContext } from 'svelte';
|
|
3
4
|
import { key } from 'svelte-awesome/icons';
|
|
4
5
|
import { displayData } from '../../utils';
|
|
@@ -32,7 +33,7 @@ function getComponentNameById(componentId) {
|
|
|
32
33
|
return 'Table action';
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
|
-
$: panels = [['ctx', ['email', 'username']]].concat(Object.entries($staticOutputs));
|
|
36
|
+
$: panels = [['ctx', ['email', 'username', 'query']]].concat(Object.entries($staticOutputs));
|
|
36
37
|
</script>
|
|
37
38
|
|
|
38
39
|
<PanelSection noPadding titlePadding="px-4 pt-2" title="Outputs">
|
|
@@ -38,7 +38,7 @@ let runLoading = false;
|
|
|
38
38
|
|
|
39
39
|
<InlineScriptEditorDrawer {editor} bind:this={inlineScriptEditorDrawer} bind:inlineScript />
|
|
40
40
|
|
|
41
|
-
<div class="h-full flex flex-col gap-1" transition:fly={{ duration: 50 }}>
|
|
41
|
+
<div class="h-full flex flex-col gap-1" transition:fly|local={{ duration: 50 }}>
|
|
42
42
|
<div class="flex justify-between w-full gap-1 px-2 pt-1 flex-row items-center">
|
|
43
43
|
{#if name !== undefined}
|
|
44
44
|
<input bind:value={name} placeholder="Inline script name" />
|
|
@@ -119,6 +119,9 @@ let runLoading = false;
|
|
|
119
119
|
on:change={async (e) => {
|
|
120
120
|
if (inlineScript) {
|
|
121
121
|
const oldSchema = JSON.stringify(inlineScript.schema)
|
|
122
|
+
if (inlineScript.schema == undefined) {
|
|
123
|
+
inlineScript.schema = emptySchema()
|
|
124
|
+
}
|
|
122
125
|
await inferInlineScriptSchema(inlineScript?.language, e.detail, inlineScript.schema)
|
|
123
126
|
if (JSON.stringify(inlineScript.schema) != oldSchema) {
|
|
124
127
|
inlineScript = inlineScript
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { classNames } from '../../../../utils';
|
|
3
3
|
import { getContext } from 'svelte';
|
|
4
4
|
import PanelSection from '../settingsPanel/common/PanelSection.svelte';
|
|
5
|
+
import { getAppScripts } from './utils';
|
|
5
6
|
export let selectedScriptComponentId = undefined;
|
|
6
7
|
const { app, selectedComponent, lazyGrid } = getContext('AppEditorContext');
|
|
7
8
|
function selectInlineScript(id) {
|
|
@@ -10,56 +11,7 @@ function selectInlineScript(id) {
|
|
|
10
11
|
$selectedComponent = selectedScriptComponentId;
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
|
-
$:
|
|
14
|
-
const component = gridComponent.data;
|
|
15
|
-
if (component.type === 'tablecomponent') {
|
|
16
|
-
component.actionButtons.forEach((actionButton) => {
|
|
17
|
-
if (actionButton.componentInput?.type === 'runnable') {
|
|
18
|
-
if (actionButton.componentInput.runnable?.type === 'runnableByName') {
|
|
19
|
-
acc.push({
|
|
20
|
-
name: actionButton.componentInput.runnable.name,
|
|
21
|
-
id: actionButton.id
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
const componentInput = component.componentInput;
|
|
28
|
-
if (componentInput?.type === 'runnable') {
|
|
29
|
-
if (componentInput.runnable?.type === 'runnableByName') {
|
|
30
|
-
acc.push({
|
|
31
|
-
name: componentInput.runnable.name,
|
|
32
|
-
id: gridComponent.id
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return acc;
|
|
37
|
-
}, []);
|
|
38
|
-
$: runnablesByPath = $lazyGrid.reduce((acc, gridComponent) => {
|
|
39
|
-
const component = gridComponent.data;
|
|
40
|
-
if (component.type === 'tablecomponent') {
|
|
41
|
-
component.actionButtons.forEach((actionButton) => {
|
|
42
|
-
if (actionButton.componentInput?.type === 'runnable') {
|
|
43
|
-
if (actionButton.componentInput.runnable?.type === 'runnableByPath') {
|
|
44
|
-
acc.push({
|
|
45
|
-
name: actionButton.componentInput.runnable.path,
|
|
46
|
-
id: actionButton.id
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
const componentInput = component.componentInput;
|
|
53
|
-
if (componentInput?.type === 'runnable') {
|
|
54
|
-
if (componentInput.runnable?.type === 'runnableByPath') {
|
|
55
|
-
acc.push({
|
|
56
|
-
name: componentInput.runnable.path,
|
|
57
|
-
id: gridComponent.id
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return acc;
|
|
62
|
-
}, []);
|
|
14
|
+
$: runnables = getAppScripts($lazyGrid);
|
|
63
15
|
// When seleced component changes, update selectedScriptComponentId
|
|
64
16
|
$: {
|
|
65
17
|
if (selectedComponent) {
|
|
@@ -71,9 +23,9 @@ $: {
|
|
|
71
23
|
<div class="min-h-full flex flex-col gap-4">
|
|
72
24
|
<PanelSection title="Inline scripts" smallPadding>
|
|
73
25
|
<div class="flex flex-col gap-2 w-full">
|
|
74
|
-
{#if
|
|
26
|
+
{#if runnables.inline.length > 0}
|
|
75
27
|
<div class="flex gap-2 flex-col ">
|
|
76
|
-
{#each
|
|
28
|
+
{#each runnables.inline as { name, id }, index (index)}
|
|
77
29
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
78
30
|
<div
|
|
79
31
|
class="{classNames(
|
|
@@ -109,17 +61,17 @@ $: {
|
|
|
109
61
|
</div>
|
|
110
62
|
{/if}
|
|
111
63
|
|
|
112
|
-
{#if
|
|
64
|
+
{#if runnables.inline.length == 0 && $app.unusedInlineScripts?.length == 0}
|
|
113
65
|
<div class="text-sm text-gray-500">No inline scripts</div>
|
|
114
66
|
{/if}
|
|
115
67
|
</div>
|
|
116
68
|
</PanelSection>
|
|
117
69
|
|
|
118
|
-
<PanelSection title="
|
|
70
|
+
<PanelSection title="Imported scripts" smallPadding>
|
|
119
71
|
<div class="flex flex-col gap-2 w-full">
|
|
120
|
-
{#if
|
|
72
|
+
{#if runnables.imported.length > 0}
|
|
121
73
|
<div class="flex gap-2 flex-col ">
|
|
122
|
-
{#each
|
|
74
|
+
{#each runnables.imported as { name, id }, index (index)}
|
|
123
75
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
124
76
|
<div
|
|
125
77
|
class="{classNames(
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AppComponent, GridItem } from "../../types";
|
|
2
|
+
export interface AppScriptsList {
|
|
3
|
+
inline: {
|
|
4
|
+
name: string;
|
|
5
|
+
id: string;
|
|
6
|
+
}[];
|
|
7
|
+
imported: {
|
|
8
|
+
name: string;
|
|
9
|
+
id: string;
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
export declare function getAppScripts(grid: GridItem[]): FilledItem<{
|
|
13
|
+
data: AppComponent;
|
|
14
|
+
id: string;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function getAppScripts(grid) {
|
|
2
|
+
return grid.reduce((acc, gridComponent) => {
|
|
3
|
+
const component = gridComponent.data;
|
|
4
|
+
const componentInput = component.componentInput;
|
|
5
|
+
if (component.type === 'tablecomponent') {
|
|
6
|
+
component.actionButtons.forEach((actionButton) => {
|
|
7
|
+
if (actionButton.componentInput?.type !== 'runnable') {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
processRunnable(actionButton.componentInput.runnable, actionButton.id, acc);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
if (componentInput?.type === 'runnable') {
|
|
14
|
+
processRunnable(componentInput.runnable, gridComponent.id, acc);
|
|
15
|
+
}
|
|
16
|
+
return acc;
|
|
17
|
+
}, { inline: [], imported: [] });
|
|
18
|
+
}
|
|
19
|
+
function processRunnable(runnable, id, list) {
|
|
20
|
+
if (runnable?.type === undefined) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const type = runnable.type === 'runnableByPath' ? 'imported' : 'inline';
|
|
24
|
+
list[type].push({
|
|
25
|
+
name: runnable[runnable.type === 'runnableByPath' ? 'path' : 'name'],
|
|
26
|
+
id
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -8,7 +8,7 @@ import StaticInputEditor from './inputEditor/StaticInputEditor.svelte';
|
|
|
8
8
|
import ConnectedInputEditor from './inputEditor/ConnectedInputEditor.svelte';
|
|
9
9
|
import Badge from '../../../common/badge/Badge.svelte';
|
|
10
10
|
import { capitalize, classNames } from '../../../../utils';
|
|
11
|
-
import { fieldTypeToTsType } from '../../utils';
|
|
11
|
+
import { buildExtraLib, fieldTypeToTsType } from '../../utils';
|
|
12
12
|
import Recompute from './Recompute.svelte';
|
|
13
13
|
import Tooltip from '../../../Tooltip.svelte';
|
|
14
14
|
import ComponentInputTypeEditor from './ComponentInputTypeEditor.svelte';
|
|
@@ -54,20 +54,9 @@ function removeGridElement() {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
export function buildExtraLib(components) {
|
|
58
|
-
return Object.entries(components)
|
|
59
|
-
.filter(([k, v]) => k != component?.id)
|
|
60
|
-
.map(([k, v]) => [k, Object.fromEntries(Object.entries(v).map(([k, v]) => [k, v.peak()]))])
|
|
61
|
-
.map(([k, v]) => `
|
|
62
|
-
|
|
63
|
-
declare const ${k} = ${JSON.stringify(v)};
|
|
64
|
-
|
|
65
|
-
`)
|
|
66
|
-
.join('\n');
|
|
67
|
-
}
|
|
68
57
|
$: extraLib =
|
|
69
58
|
component?.componentInput?.type === 'template' && $worldStore
|
|
70
|
-
? buildExtraLib($worldStore?.outputsById ?? {})
|
|
59
|
+
? buildExtraLib($worldStore?.outputsById ?? {}, component?.id, false)
|
|
71
60
|
: undefined;
|
|
72
61
|
</script>
|
|
73
62
|
|
|
@@ -131,6 +120,7 @@ $: extraLib =
|
|
|
131
120
|
</svelte:fragment>
|
|
132
121
|
|
|
133
122
|
<InputsSpecsEditor
|
|
123
|
+
id={component.id}
|
|
134
124
|
shouldCapitalize={false}
|
|
135
125
|
bind:inputSpecs={component.componentInput.fields}
|
|
136
126
|
userInputEnabled={component.type !== 'buttoncomponent'}
|
|
@@ -144,7 +134,12 @@ $: extraLib =
|
|
|
144
134
|
|
|
145
135
|
{#if Object.values(component.configuration).length > 0}
|
|
146
136
|
<PanelSection title={`Configuration (${Object.values(component.configuration).length})`}>
|
|
147
|
-
<InputsSpecsEditor
|
|
137
|
+
<InputsSpecsEditor
|
|
138
|
+
{rowColumns}
|
|
139
|
+
id={component.id}
|
|
140
|
+
bind:inputSpecs={component.configuration}
|
|
141
|
+
userInputEnabled={false}
|
|
142
|
+
/>
|
|
148
143
|
</PanelSection>
|
|
149
144
|
{/if}
|
|
150
145
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
2
|
import type { AppComponent } from '../../types';
|
|
3
|
-
import type { Output } from '../../rx';
|
|
4
3
|
declare const __propDef: {
|
|
5
4
|
props: {
|
|
6
5
|
component: AppComponent | undefined;
|
|
7
6
|
onDelete?: (() => void) | undefined;
|
|
8
7
|
rowColumns?: boolean | undefined;
|
|
9
|
-
buildExtraLib?: ((components: Record<string, Record<string, Output<any>>>) => string) | undefined;
|
|
10
8
|
};
|
|
11
9
|
events: {
|
|
12
10
|
[evt: string]: CustomEvent<any>;
|
|
@@ -17,6 +15,5 @@ export type ComponentPanelProps = typeof __propDef.props;
|
|
|
17
15
|
export type ComponentPanelEvents = typeof __propDef.events;
|
|
18
16
|
export type ComponentPanelSlots = typeof __propDef.slots;
|
|
19
17
|
export default class ComponentPanel extends SvelteComponentTyped<ComponentPanelProps, ComponentPanelEvents, ComponentPanelSlots> {
|
|
20
|
-
get buildExtraLib(): (components: Record<string, Record<string, Output<any>>>) => string;
|
|
21
18
|
}
|
|
22
19
|
export {};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
<script>import
|
|
2
|
-
import
|
|
1
|
+
<script>import ConnectedInputEditor from './inputEditor/ConnectedInputEditor.svelte';
|
|
2
|
+
import EvalInputEditor from './inputEditor/EvalInputEditor.svelte';
|
|
3
3
|
import RowInputEditor from './inputEditor/RowInputEditor.svelte';
|
|
4
4
|
import StaticInputEditor from './inputEditor/StaticInputEditor.svelte';
|
|
5
|
+
export let id;
|
|
5
6
|
export let componentInput;
|
|
7
|
+
export let hasRows = false;
|
|
6
8
|
</script>
|
|
7
9
|
|
|
8
10
|
{#if componentInput.type === 'connected'}
|
|
@@ -11,6 +13,8 @@ export let componentInput;
|
|
|
11
13
|
<RowInputEditor bind:componentInput />
|
|
12
14
|
{:else if componentInput.type === 'static'}
|
|
13
15
|
<StaticInputEditor bind:componentInput />
|
|
16
|
+
{:else if componentInput.type === 'eval'}
|
|
17
|
+
<EvalInputEditor {hasRows} {id} bind:componentInput />
|
|
14
18
|
{:else if componentInput.type === 'user'}
|
|
15
19
|
<span class="text-2xs italic text-gray-6f00">Field's value is set by the user</span>
|
|
16
20
|
{/if}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import type { ConnectedAppInput, RowAppInput, StaticAppInput, UserAppInput } from '../../inputType';
|
|
2
|
+
import type { ConnectedAppInput, EvalAppInput, RowAppInput, StaticAppInput, UserAppInput } from '../../inputType';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
-
|
|
5
|
+
id: string;
|
|
6
|
+
componentInput: StaticAppInput | ConnectedAppInput | UserAppInput | RowAppInput | EvalAppInput;
|
|
7
|
+
hasRows?: boolean | undefined;
|
|
6
8
|
};
|
|
7
9
|
events: {
|
|
8
10
|
[evt: string]: CustomEvent<any>;
|
|
@@ -6,9 +6,9 @@ import InputsSpecEditor from './InputsSpecEditor.svelte';
|
|
|
6
6
|
import { getContext } from 'svelte';
|
|
7
7
|
import Tooltip from '../../../Tooltip.svelte';
|
|
8
8
|
import Popover from '../../../Popover.svelte';
|
|
9
|
+
export let id;
|
|
9
10
|
export let inputSpecs;
|
|
10
11
|
export let userInputEnabled = true;
|
|
11
|
-
export let staticOnly = false;
|
|
12
12
|
export let shouldCapitalize = true;
|
|
13
13
|
export let rowColumns = false;
|
|
14
14
|
const { connectingInput } = getContext('AppEditorContext');
|
|
@@ -38,7 +38,7 @@ const { connectingInput } = getContext('AppEditorContext');
|
|
|
38
38
|
: capitalize(fieldTypeToTsType(input.fieldType))}
|
|
39
39
|
</Badge>
|
|
40
40
|
|
|
41
|
-
{#if !inputSpecs[inputSpecKey].onlyStatic}
|
|
41
|
+
{#if !inputSpecs[inputSpecKey].onlyStatic && inputSpecs[inputSpecKey].type != 'eval'}
|
|
42
42
|
<ToggleButtonGroup
|
|
43
43
|
bind:selected={inputSpecs[inputSpecKey].type}
|
|
44
44
|
on:selected={(e) => {
|
|
@@ -68,9 +68,8 @@ const { connectingInput } = getContext('AppEditorContext');
|
|
|
68
68
|
value="row"
|
|
69
69
|
startIcon={{ icon: faTableCells }}
|
|
70
70
|
size="xs"
|
|
71
|
-
disabled={staticOnly}
|
|
72
71
|
>
|
|
73
|
-
<Tooltip>
|
|
72
|
+
<Tooltip scale={0.6} placement="top-end" wrapperClass="center-center">
|
|
74
73
|
Use the column name to have the value of the cell be passed to the action
|
|
75
74
|
</Tooltip>
|
|
76
75
|
</ToggleButton>
|
|
@@ -85,7 +84,6 @@ const { connectingInput } = getContext('AppEditorContext');
|
|
|
85
84
|
startIcon={{ icon: faUser }}
|
|
86
85
|
size="xs"
|
|
87
86
|
iconOnly
|
|
88
|
-
disabled={staticOnly}
|
|
89
87
|
/>
|
|
90
88
|
<svelte:fragment slot="text">User Input</svelte:fragment>
|
|
91
89
|
</Popover>
|
|
@@ -97,7 +95,6 @@ const { connectingInput } = getContext('AppEditorContext');
|
|
|
97
95
|
startIcon={{ icon: faArrowRight }}
|
|
98
96
|
size="xs"
|
|
99
97
|
iconOnly
|
|
100
|
-
disabled={staticOnly}
|
|
101
98
|
/>
|
|
102
99
|
<svelte:fragment slot="text">Connect</svelte:fragment>
|
|
103
100
|
</Popover>
|
|
@@ -106,7 +103,11 @@ const { connectingInput } = getContext('AppEditorContext');
|
|
|
106
103
|
</div>
|
|
107
104
|
</div>
|
|
108
105
|
|
|
109
|
-
<InputsSpecEditor
|
|
106
|
+
<InputsSpecEditor
|
|
107
|
+
hasRows={rowColumns}
|
|
108
|
+
{id}
|
|
109
|
+
bind:componentInput={inputSpecs[inputSpecKey]}
|
|
110
|
+
/>
|
|
110
111
|
</div>
|
|
111
112
|
{/each}
|
|
112
113
|
</div>
|
|
@@ -2,9 +2,9 @@ import { SvelteComponentTyped } from "svelte";
|
|
|
2
2
|
import type { BaseAppComponent } from '../../types';
|
|
3
3
|
declare const __propDef: {
|
|
4
4
|
props: {
|
|
5
|
+
id: string;
|
|
5
6
|
inputSpecs: BaseAppComponent['configuration'];
|
|
6
7
|
userInputEnabled?: boolean | undefined;
|
|
7
|
-
staticOnly?: boolean | undefined;
|
|
8
8
|
shouldCapitalize?: boolean | undefined;
|
|
9
9
|
rowColumns?: boolean | undefined;
|
|
10
10
|
};
|
|
@@ -14,7 +14,7 @@ function onChange(event, id) {
|
|
|
14
14
|
}
|
|
15
15
|
</script>
|
|
16
16
|
|
|
17
|
-
<PanelSection title="Recompute after this
|
|
17
|
+
<PanelSection title="Recompute others" tooltip="Select components to recompute after running this script">
|
|
18
18
|
{#if Object.keys($runnableComponents ?? {}).filter((id) => id !== ownId).length > 0}
|
|
19
19
|
<table class="divide-y divide-gray-300 border w-full">
|
|
20
20
|
<thead class="bg-gray-50">
|
|
@@ -11,7 +11,7 @@ export let components;
|
|
|
11
11
|
export let id;
|
|
12
12
|
const { selectedComponent, staticOutputs } = getContext('AppEditorContext');
|
|
13
13
|
function addComponent() {
|
|
14
|
-
const actionId = getNextId(components.map((x) => x.id.split('
|
|
14
|
+
const actionId = getNextId(components.map((x) => x.id.split('_')[1]));
|
|
15
15
|
const newComponent = {
|
|
16
16
|
id: `${id}_${actionId}`,
|
|
17
17
|
type: 'buttoncomponent',
|
|
@@ -32,6 +32,11 @@ function addComponent() {
|
|
|
32
32
|
type: 'static',
|
|
33
33
|
value: 'xs',
|
|
34
34
|
optionValuesKey: 'buttonSizeOptions'
|
|
35
|
+
},
|
|
36
|
+
disabled: {
|
|
37
|
+
fieldType: 'boolean',
|
|
38
|
+
type: 'eval',
|
|
39
|
+
expr: 'false'
|
|
35
40
|
}
|
|
36
41
|
},
|
|
37
42
|
componentInput: {
|
|
@@ -72,7 +77,7 @@ function deleteComponent(cid) {
|
|
|
72
77
|
{#each components as component}
|
|
73
78
|
<div
|
|
74
79
|
class={classNames(
|
|
75
|
-
'w-full text-xs font-bold gap-1 py-1.5 px-2 cursor-pointer transition-all justify-between flex items-center border border-gray-3 rounded-md',
|
|
80
|
+
'w-full text-xs font-bold gap-1 truncate py-1.5 px-2 cursor-pointer transition-all justify-between flex items-center border border-gray-3 rounded-md',
|
|
76
81
|
'bg-white border-gray-300 hover:bg-gray-100 focus:bg-gray-100 text-gray-700',
|
|
77
82
|
$selectedComponent === component.id ? 'outline outline-blue-500 bg-red-400' : ''
|
|
78
83
|
)}
|