windmill-components 1.138.7 → 1.139.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package/components/DeployWorkspace.svelte +0 -1
- package/package/components/DisplayResult.svelte +3 -1
- package/package/components/EditorBar.svelte +0 -1
- package/package/components/GroupEditor.svelte +6 -1
- package/package/components/ResultJobLoader.svelte +9 -1
- package/package/components/ResultJobLoader.svelte.d.ts +1 -1
- package/package/components/ScheduleEditor.svelte +0 -1
- package/package/components/SchemaEditor.svelte +0 -1
- package/package/components/SupabaseConnect.svelte +2 -1
- package/package/components/apps/components/display/AppCarouselList.svelte +161 -0
- package/package/components/apps/components/display/AppCarouselList.svelte.d.ts +24 -0
- package/package/components/apps/components/display/AppMarkdown.svelte +66 -0
- package/package/components/apps/components/display/AppMarkdown.svelte.d.ts +23 -0
- package/package/components/apps/components/display/index.d.ts +1 -0
- package/package/components/apps/components/display/index.js +1 -0
- package/package/components/apps/components/helpers/RunnableComponent.svelte +77 -53
- package/package/components/apps/components/helpers/eval.js +0 -1
- package/package/components/apps/components/icon.js +7 -1
- package/package/components/apps/components/inputs/AppFileInput.svelte +8 -0
- package/package/components/apps/components/inputs/AppSelect.svelte +54 -28
- package/package/components/apps/editor/AppEditorHeader.svelte +23 -0
- package/package/components/apps/editor/component/Component.svelte +20 -1
- package/package/components/apps/editor/component/components.d.ts +73 -2
- package/package/components/apps/editor/component/components.js +70 -2
- package/package/components/apps/editor/component/sets.js +3 -1
- package/package/components/apps/editor/componentsPanel/quickStyleProperties.js +6 -0
- package/package/components/apps/editor/settingsPanel/GridTab.svelte +1 -1
- package/package/components/apps/editor/settingsPanel/script/shared/ScriptSettingHeader.svelte +1 -1
- package/package/components/apps/types.d.ts +4 -0
- package/package/components/apps/utils.js +0 -1
- package/package/components/codeGen/ScriptGen.svelte +84 -80
- package/package/components/common/button/Button.svelte +6 -2
- package/package/components/common/button/ButtonDropdown.svelte +1 -1
- package/package/components/flows/content/FlowModuleMock.svelte +0 -1
- package/package/components/graph/svelvet/edges/views/Edges/BaseEdge.svelte +0 -1
- package/package/logout.js +0 -1
- package/package.json +11 -1
- package/package/components/flows/content/FlowModuleConcurrencyLimit.svelte +0 -51
- package/package/components/flows/content/FlowModuleConcurrencyLimit.svelte.d.ts +0 -17
|
@@ -113,7 +113,6 @@ async function getDependencies(kind, path) {
|
|
|
113
113
|
let processed = [];
|
|
114
114
|
while (toProcess.length > 0) {
|
|
115
115
|
const { kind, path } = toProcess.pop();
|
|
116
|
-
console.log('BAR', kind, path);
|
|
117
116
|
toProcess.push(...(await rec(kind, path)));
|
|
118
117
|
processed.push({ kind, path });
|
|
119
118
|
}
|
|
@@ -197,7 +197,9 @@ $: jsonStr = JSON.stringify(result, null, 4);
|
|
|
197
197
|
href="data:application/octet-stream;base64,{result.file}">Download</a
|
|
198
198
|
>
|
|
199
199
|
</div>
|
|
200
|
-
{:else if !forceJson && resultKind == 'error'}<div
|
|
200
|
+
{:else if !forceJson && resultKind == 'error' && result?.error}<div
|
|
201
|
+
class="flex flex-col items-start"
|
|
202
|
+
>
|
|
201
203
|
<span class="text-red-500 font-semibold text-sm whitespace-pre-wrap"
|
|
202
204
|
>{#if result.error.name || result.error.message}{result.error.name}: {result.error
|
|
203
205
|
.message}{:else}{JSON.stringify(result.error, null, 4)}{/if}</span
|
|
@@ -361,7 +361,6 @@ let historyBrowserDrawerOpen = false;
|
|
|
361
361
|
}
|
|
362
362
|
} else {
|
|
363
363
|
const tsSchema = compile(resourceType.schema)
|
|
364
|
-
console.log(tsSchema)
|
|
365
364
|
editor.insertAtCursor(`type ${toCamel(capitalize(name))} = ${tsSchema}\n`)
|
|
366
365
|
}
|
|
367
366
|
sendUserToast(`${name} inserted at cursor`)
|
|
@@ -37,7 +37,12 @@ async function addToGroup() {
|
|
|
37
37
|
loadGroup();
|
|
38
38
|
}
|
|
39
39
|
async function loadInstanceGroup() {
|
|
40
|
-
|
|
40
|
+
try {
|
|
41
|
+
instance_group = await GroupService.getInstanceGroup({ name });
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
instance_group = undefined;
|
|
45
|
+
}
|
|
41
46
|
}
|
|
42
47
|
async function loadGroup() {
|
|
43
48
|
try {
|
|
@@ -118,7 +118,15 @@ async function loadTestJob(id) {
|
|
|
118
118
|
if (currentId === id) {
|
|
119
119
|
job = { ...maybe_job, id };
|
|
120
120
|
await tick();
|
|
121
|
-
|
|
121
|
+
if ('error' in job ?? {}) {
|
|
122
|
+
dispatch('doneError', {
|
|
123
|
+
id,
|
|
124
|
+
error: job.result.error
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
dispatch('done', job);
|
|
129
|
+
}
|
|
122
130
|
currentId = undefined;
|
|
123
131
|
}
|
|
124
132
|
}
|
|
@@ -89,7 +89,6 @@ async function loadSchedule() {
|
|
|
89
89
|
script_path = s.script_path ?? '';
|
|
90
90
|
is_flow = s.is_flow;
|
|
91
91
|
if (s.on_failure) {
|
|
92
|
-
console.log(s.on_failure);
|
|
93
92
|
let splitted = s.on_failure.split('/');
|
|
94
93
|
errorHandleritemKind = splitted[0];
|
|
95
94
|
errorHandlerPath = splitted.slice(1)?.join('/');
|
|
@@ -101,7 +101,6 @@ function startEditArgument(argName) {
|
|
|
101
101
|
if (Object.keys(schema.properties).includes(argName)) {
|
|
102
102
|
editing = true;
|
|
103
103
|
const modalProperty = schemaToModal(schema.properties[argName], argName, schema.required.includes(argName));
|
|
104
|
-
console.log(modalProperty.format);
|
|
105
104
|
oldArgName = argName;
|
|
106
105
|
schemaModal.openDrawer(modalProperty);
|
|
107
106
|
}
|
|
@@ -126,7 +126,8 @@ async function save() {
|
|
|
126
126
|
bind:error={pathError}
|
|
127
127
|
bind:path
|
|
128
128
|
initialPath=""
|
|
129
|
-
fullNamePlaceholder={'supabase_' +
|
|
129
|
+
fullNamePlaceholder={'supabase_' +
|
|
130
|
+
selectedDatabase?.name?.replace(/\s+/g, '').replace(/[^\w\s]/gi, '')}
|
|
130
131
|
kind="resource"
|
|
131
132
|
/>
|
|
132
133
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { initConfig, initOutput } from '../../editor/appUtils';
|
|
3
|
+
import SubGridEditor from '../../editor/SubGridEditor.svelte';
|
|
4
|
+
import { concatCustomCss } from '../../utils';
|
|
5
|
+
import InitializeComponent from '../helpers/InitializeComponent.svelte';
|
|
6
|
+
import ResolveConfig from '../helpers/ResolveConfig.svelte';
|
|
7
|
+
import { components } from '../../editor/component';
|
|
8
|
+
import RunnableWrapper from '../helpers/RunnableWrapper.svelte';
|
|
9
|
+
import ListWrapper from '../layout/ListWrapper.svelte';
|
|
10
|
+
import Carousel from 'svelte-carousel';
|
|
11
|
+
import { ArrowLeftCircle, ArrowRightCircle } from 'lucide-svelte';
|
|
12
|
+
import { Button } from '../../../common';
|
|
13
|
+
export let id;
|
|
14
|
+
export let componentInput;
|
|
15
|
+
export let configuration;
|
|
16
|
+
export let customCss = undefined;
|
|
17
|
+
export let render;
|
|
18
|
+
export let initializing;
|
|
19
|
+
export let componentContainerHeight;
|
|
20
|
+
const { app, focusedGrid, selectedComponent, worldStore, connectingInput } = getContext('AppViewerContext');
|
|
21
|
+
const outputs = initOutput($worldStore, id, {
|
|
22
|
+
result: undefined,
|
|
23
|
+
loading: false,
|
|
24
|
+
inputs: {}
|
|
25
|
+
});
|
|
26
|
+
const resolvedConfig = initConfig(components['carousellistcomponent'].initialData.configuration, configuration);
|
|
27
|
+
function onFocus() {
|
|
28
|
+
$focusedGrid = {
|
|
29
|
+
parentComponentId: id,
|
|
30
|
+
subGridIndex: 0
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
$: css = concatCustomCss($app.css?.containercomponent, customCss);
|
|
34
|
+
let result = undefined;
|
|
35
|
+
let inputs = {};
|
|
36
|
+
let carousel;
|
|
37
|
+
$: $selectedComponent?.includes(id) &&
|
|
38
|
+
$focusedGrid === undefined &&
|
|
39
|
+
($focusedGrid = {
|
|
40
|
+
parentComponentId: id,
|
|
41
|
+
subGridIndex: 0
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
{#each Object.keys(components['carousellistcomponent'].initialData.configuration) as key (key)}
|
|
46
|
+
<ResolveConfig
|
|
47
|
+
{id}
|
|
48
|
+
{key}
|
|
49
|
+
bind:resolvedConfig={resolvedConfig[key]}
|
|
50
|
+
configuration={configuration[key]}
|
|
51
|
+
/>
|
|
52
|
+
{/each}
|
|
53
|
+
|
|
54
|
+
<InitializeComponent {id} />
|
|
55
|
+
|
|
56
|
+
<RunnableWrapper
|
|
57
|
+
render={true}
|
|
58
|
+
{outputs}
|
|
59
|
+
autoRefresh
|
|
60
|
+
{componentInput}
|
|
61
|
+
{id}
|
|
62
|
+
bind:initializing
|
|
63
|
+
bind:result
|
|
64
|
+
>
|
|
65
|
+
<div class="w-full flex flex-wrap overflow-auto divide-y max-h-full">
|
|
66
|
+
{#if $app.subgrids?.[`${id}-0`]}
|
|
67
|
+
{#if Array.isArray(result) && result.length > 0}
|
|
68
|
+
{#key result}
|
|
69
|
+
<Carousel
|
|
70
|
+
particlesToShow={1}
|
|
71
|
+
particlesToScroll={1}
|
|
72
|
+
autoplay={false}
|
|
73
|
+
autoplayProgressVisible={false}
|
|
74
|
+
timingFunction={resolvedConfig.timingFunction}
|
|
75
|
+
dots={true}
|
|
76
|
+
arrows={true}
|
|
77
|
+
swiping={false}
|
|
78
|
+
bind:this={carousel}
|
|
79
|
+
let:currentPageIndex
|
|
80
|
+
on:pageChange={(event) => {
|
|
81
|
+
$focusedGrid = {
|
|
82
|
+
parentComponentId: id,
|
|
83
|
+
subGridIndex: event.detail
|
|
84
|
+
}
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
<div slot="prev" class="h-full flex justify-center flex-col p-2">
|
|
88
|
+
<div>
|
|
89
|
+
<Button
|
|
90
|
+
color="light"
|
|
91
|
+
on:click={() => {
|
|
92
|
+
const pagesCount = result?.length ?? 0
|
|
93
|
+
|
|
94
|
+
if (currentPageIndex > 0) {
|
|
95
|
+
carousel.goTo(currentPageIndex - 1)
|
|
96
|
+
} else {
|
|
97
|
+
carousel.goTo(pagesCount - 1)
|
|
98
|
+
}
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
<ArrowLeftCircle size={16} />
|
|
102
|
+
</Button>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div slot="next" class="h-full flex justify-center flex-col p-2">
|
|
106
|
+
<div>
|
|
107
|
+
<Button
|
|
108
|
+
color="light"
|
|
109
|
+
on:click={() => {
|
|
110
|
+
const pagesCount = result?.length ?? 0
|
|
111
|
+
if (currentPageIndex < pagesCount - 1) {
|
|
112
|
+
carousel.goTo(currentPageIndex + 1)
|
|
113
|
+
} else {
|
|
114
|
+
carousel.goTo(0)
|
|
115
|
+
}
|
|
116
|
+
}}
|
|
117
|
+
>
|
|
118
|
+
<ArrowRightCircle size={16} />
|
|
119
|
+
</Button>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
{#each result ?? [] as value, index}
|
|
123
|
+
<div class="overflow-auto w-full">
|
|
124
|
+
<ListWrapper
|
|
125
|
+
on:inputsChange={() => {
|
|
126
|
+
outputs?.inputs.set(inputs, true)
|
|
127
|
+
}}
|
|
128
|
+
bind:inputs
|
|
129
|
+
{value}
|
|
130
|
+
{index}
|
|
131
|
+
>
|
|
132
|
+
<SubGridEditor
|
|
133
|
+
{id}
|
|
134
|
+
visible={render}
|
|
135
|
+
class={css?.container?.class}
|
|
136
|
+
style={css?.container?.style}
|
|
137
|
+
subGridId={`${id}-0`}
|
|
138
|
+
containerHeight={componentContainerHeight - 40}
|
|
139
|
+
on:focus={() => {
|
|
140
|
+
if (!$connectingInput.opened) {
|
|
141
|
+
$selectedComponent = [id]
|
|
142
|
+
}
|
|
143
|
+
onFocus()
|
|
144
|
+
}}
|
|
145
|
+
/>
|
|
146
|
+
</ListWrapper>
|
|
147
|
+
</div>
|
|
148
|
+
{/each}
|
|
149
|
+
</Carousel>
|
|
150
|
+
{/key}
|
|
151
|
+
{:else}
|
|
152
|
+
<ListWrapper disabled value={undefined} index={0}>
|
|
153
|
+
<SubGridEditor visible={false} {id} subGridId={`${id}-0`} />
|
|
154
|
+
</ListWrapper>
|
|
155
|
+
{#if !Array.isArray(result)}
|
|
156
|
+
<div class="text-center text-tertiary">Input data is not an array</div>
|
|
157
|
+
{/if}
|
|
158
|
+
{/if}
|
|
159
|
+
{/if}
|
|
160
|
+
</div>
|
|
161
|
+
</RunnableWrapper>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { ComponentCustomCSS, RichConfigurations } from '../../types';
|
|
3
|
+
import type { AppInput } from '../../inputType';
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
id: string;
|
|
7
|
+
componentInput: AppInput | undefined;
|
|
8
|
+
configuration: RichConfigurations;
|
|
9
|
+
customCss?: ComponentCustomCSS<'containercomponent'> | undefined;
|
|
10
|
+
render: boolean;
|
|
11
|
+
initializing: boolean | undefined;
|
|
12
|
+
componentContainerHeight: number;
|
|
13
|
+
};
|
|
14
|
+
events: {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
};
|
|
17
|
+
slots: {};
|
|
18
|
+
};
|
|
19
|
+
export type AppCarouselListProps = typeof __propDef.props;
|
|
20
|
+
export type AppCarouselListEvents = typeof __propDef.events;
|
|
21
|
+
export type AppCarouselListSlots = typeof __propDef.slots;
|
|
22
|
+
export default class AppCarouselList extends SvelteComponentTyped<AppCarouselListProps, AppCarouselListEvents, AppCarouselListSlots> {
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script>import { getContext } from 'svelte';
|
|
2
|
+
import { initConfig, initOutput } from '../../editor/appUtils';
|
|
3
|
+
import { concatCustomCss } from '../../utils';
|
|
4
|
+
import RunnableWrapper from '../helpers/RunnableWrapper.svelte';
|
|
5
|
+
import Markdown from 'svelte-exmarkdown';
|
|
6
|
+
import { classNames } from '../../../../utils';
|
|
7
|
+
import { components } from '../../editor/component';
|
|
8
|
+
import ResolveConfig from '../helpers/ResolveConfig.svelte';
|
|
9
|
+
export let id;
|
|
10
|
+
export let componentInput;
|
|
11
|
+
export let initializing = undefined;
|
|
12
|
+
export let customCss = undefined;
|
|
13
|
+
export let render;
|
|
14
|
+
export let configuration;
|
|
15
|
+
const { app, worldStore } = getContext('AppViewerContext');
|
|
16
|
+
const resolvedConfig = initConfig(components['mardowncomponent'].initialData.configuration, configuration);
|
|
17
|
+
const outputs = initOutput($worldStore, id, {
|
|
18
|
+
result: undefined,
|
|
19
|
+
loading: false
|
|
20
|
+
});
|
|
21
|
+
let result = undefined;
|
|
22
|
+
$: css = concatCustomCss($app.css?.mardowncomponent, customCss);
|
|
23
|
+
const proseMapping = {
|
|
24
|
+
sm: 'prose-sm',
|
|
25
|
+
Default: 'prose-base',
|
|
26
|
+
lg: 'prose-lg',
|
|
27
|
+
xl: 'prose-xl',
|
|
28
|
+
'2xl': 'prose-2xl'
|
|
29
|
+
};
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
{#each Object.keys(components['mardowncomponent'].initialData.configuration) as key (key)}
|
|
33
|
+
<ResolveConfig
|
|
34
|
+
{id}
|
|
35
|
+
{key}
|
|
36
|
+
bind:resolvedConfig={resolvedConfig[key]}
|
|
37
|
+
configuration={configuration[key]}
|
|
38
|
+
/>
|
|
39
|
+
{/each}
|
|
40
|
+
|
|
41
|
+
<div
|
|
42
|
+
on:pointerdown={(e) => {
|
|
43
|
+
e?.preventDefault()
|
|
44
|
+
}}
|
|
45
|
+
class={classNames(
|
|
46
|
+
'h-full w-full overflow-y-auto prose',
|
|
47
|
+
resolvedConfig?.size ? proseMapping[resolvedConfig.size] : '',
|
|
48
|
+
css?.container?.class
|
|
49
|
+
)}
|
|
50
|
+
>
|
|
51
|
+
<RunnableWrapper
|
|
52
|
+
{outputs}
|
|
53
|
+
{render}
|
|
54
|
+
autoRefresh
|
|
55
|
+
{componentInput}
|
|
56
|
+
{id}
|
|
57
|
+
bind:initializing
|
|
58
|
+
bind:result
|
|
59
|
+
>
|
|
60
|
+
{#if result}
|
|
61
|
+
{#key result}
|
|
62
|
+
<Markdown md={result} />
|
|
63
|
+
{/key}
|
|
64
|
+
{/if}
|
|
65
|
+
</RunnableWrapper>
|
|
66
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { AppInput } from '../../inputType';
|
|
3
|
+
import type { ComponentCustomCSS, RichConfigurations } from '../../types';
|
|
4
|
+
declare const __propDef: {
|
|
5
|
+
props: {
|
|
6
|
+
id: string;
|
|
7
|
+
componentInput: AppInput | undefined;
|
|
8
|
+
initializing?: boolean | undefined;
|
|
9
|
+
customCss?: ComponentCustomCSS<'mardowncomponent'> | undefined;
|
|
10
|
+
render: boolean;
|
|
11
|
+
configuration: RichConfigurations;
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
};
|
|
16
|
+
slots: {};
|
|
17
|
+
};
|
|
18
|
+
export type AppMarkdownProps = typeof __propDef.props;
|
|
19
|
+
export type AppMarkdownEvents = typeof __propDef.events;
|
|
20
|
+
export type AppMarkdownSlots = typeof __propDef.slots;
|
|
21
|
+
export default class AppMarkdown extends SvelteComponentTyped<AppMarkdownProps, AppMarkdownEvents, AppMarkdownSlots> {
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -13,3 +13,4 @@ export { default as AppText } from './AppText.svelte';
|
|
|
13
13
|
export { default as AppTimeseries } from './AppTimeseries.svelte';
|
|
14
14
|
export { default as PlotlyHtml } from './PlotlyHtml.svelte';
|
|
15
15
|
export { default as VegaLiteHtml } from './VegaLiteHtml.svelte';
|
|
16
|
+
export { default as AppMarkdown } from './AppMarkdown.svelte';
|
|
@@ -13,3 +13,4 @@ export { default as AppText } from './AppText.svelte';
|
|
|
13
13
|
export { default as AppTimeseries } from './AppTimeseries.svelte';
|
|
14
14
|
export { default as PlotlyHtml } from './PlotlyHtml.svelte';
|
|
15
15
|
export { default as VegaLiteHtml } from './VegaLiteHtml.svelte';
|
|
16
|
+
export { default as AppMarkdown } from './AppMarkdown.svelte';
|
|
@@ -125,22 +125,14 @@ async function executeComponent(noToast = false, inlineScriptOverride) {
|
|
|
125
125
|
iter: iterContext ? $iterContext : undefined,
|
|
126
126
|
row: rowContext ? $rowContext : undefined
|
|
127
127
|
}), false, $state, $mode == 'dnd', $componentControl, $worldStore, $runnableComponents);
|
|
128
|
-
await setResult(r, undefined);
|
|
129
|
-
$state = $state;
|
|
130
128
|
const job = generateNextFrontendJobId();
|
|
131
|
-
|
|
132
|
-
$
|
|
129
|
+
await setResult(r, job);
|
|
130
|
+
$state = $state;
|
|
133
131
|
}
|
|
134
132
|
catch (e) {
|
|
135
133
|
sendUserToast(`Error running frontend script ${id}: ` + e.message, true);
|
|
136
|
-
// Manually add a fake job to the job list to show the error
|
|
137
134
|
const job = generateNextFrontendJobId();
|
|
138
|
-
|
|
139
|
-
$errorByComponent[job] = {
|
|
140
|
-
error,
|
|
141
|
-
componentId: id
|
|
142
|
-
};
|
|
143
|
-
$jobs = [{ job, component: id, error }, ...$jobs];
|
|
135
|
+
await setResult({ error: { message: e.body ?? e.message } }, job);
|
|
144
136
|
}
|
|
145
137
|
loading = false;
|
|
146
138
|
donePromise?.();
|
|
@@ -161,7 +153,7 @@ async function executeComponent(noToast = false, inlineScriptOverride) {
|
|
|
161
153
|
return;
|
|
162
154
|
}
|
|
163
155
|
try {
|
|
164
|
-
|
|
156
|
+
await resultJobLoader?.abstractRun(async () => {
|
|
165
157
|
const nonStaticRunnableInputs = {};
|
|
166
158
|
const staticRunnableInputs = {};
|
|
167
159
|
for (const k of Object.keys(fields ?? {})) {
|
|
@@ -206,13 +198,9 @@ async function executeComponent(noToast = false, inlineScriptOverride) {
|
|
|
206
198
|
requestBody
|
|
207
199
|
});
|
|
208
200
|
});
|
|
209
|
-
if (njob) {
|
|
210
|
-
const njobs = [{ job: njob, component: id }, ...$jobs];
|
|
211
|
-
$jobs = $jobs?.length > 100 ? njobs.slice(0, 100) : njobs;
|
|
212
|
-
}
|
|
213
201
|
}
|
|
214
202
|
catch (e) {
|
|
215
|
-
|
|
203
|
+
updateResult({ error: e.body ?? e.message });
|
|
216
204
|
loading = false;
|
|
217
205
|
}
|
|
218
206
|
}
|
|
@@ -226,7 +214,7 @@ export async function runComponent() {
|
|
|
226
214
|
}
|
|
227
215
|
}
|
|
228
216
|
catch (e) {
|
|
229
|
-
|
|
217
|
+
updateResult({ error: e.body ?? e.message });
|
|
230
218
|
}
|
|
231
219
|
}
|
|
232
220
|
function recordError(error, jobId) {
|
|
@@ -238,21 +226,49 @@ function recordError(error, jobId) {
|
|
|
238
226
|
async function setJobId(jobId) {
|
|
239
227
|
outputs.jobId?.set(jobId);
|
|
240
228
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
229
|
+
function recordJob(jobId, result, error, transformer) {
|
|
230
|
+
const job = {
|
|
231
|
+
...(result ? { result } : {}),
|
|
232
|
+
...(error ? { error } : {}),
|
|
233
|
+
...(transformer ? { transformer } : {}),
|
|
234
|
+
job: jobId,
|
|
235
|
+
component: id
|
|
236
|
+
};
|
|
237
|
+
if (error) {
|
|
238
|
+
recordError(error, jobId);
|
|
239
|
+
}
|
|
240
|
+
else if (job?.transformer?.error) {
|
|
241
|
+
recordError(job.transformer.error, jobId);
|
|
242
|
+
}
|
|
243
|
+
const njobs = [job, ...$jobs];
|
|
244
|
+
// Only keep the last 100 jobs
|
|
245
|
+
$jobs = $jobs?.length > 100 ? njobs.slice(0, 100) : njobs;
|
|
246
|
+
}
|
|
247
|
+
function getResultErrors(result) {
|
|
248
|
+
const errorAsArray = Array.isArray(result) ? result.flat() : [result];
|
|
249
|
+
const hasErrors = errorAsArray.some((r) => r?.error);
|
|
250
|
+
if (!hasErrors) {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
return errorAsArray
|
|
254
|
+
.map((r) => r?.error?.message)
|
|
255
|
+
.filter(Boolean)
|
|
256
|
+
.join('\n');
|
|
257
|
+
}
|
|
258
|
+
async function runTransformer(res) {
|
|
244
259
|
if (transformer) {
|
|
245
260
|
try {
|
|
246
261
|
let raw = $worldStore.newOutput(id, 'raw', res);
|
|
247
|
-
|
|
262
|
+
const transformerResult = await eval_like(transformer.content, computeGlobalContext($worldStore, {
|
|
248
263
|
iter: iterContext ? $iterContext : undefined,
|
|
249
264
|
row: rowContext ? $rowContext : undefined,
|
|
250
265
|
result: res
|
|
251
266
|
}), false, $state, $mode == 'dnd', $componentControl, $worldStore, $runnableComponents);
|
|
252
|
-
raw.set(
|
|
267
|
+
raw.set(transformerResult);
|
|
268
|
+
return transformerResult;
|
|
253
269
|
}
|
|
254
270
|
catch (err) {
|
|
255
|
-
|
|
271
|
+
return {
|
|
256
272
|
error: {
|
|
257
273
|
name: 'TransformerError',
|
|
258
274
|
message: 'An error occured in the transformer',
|
|
@@ -260,39 +276,40 @@ async function setResult(res, jobId) {
|
|
|
260
276
|
}
|
|
261
277
|
};
|
|
262
278
|
}
|
|
263
|
-
if (hasRes && res === undefined) {
|
|
264
|
-
res = {
|
|
265
|
-
error: {
|
|
266
|
-
name: 'TransformerError',
|
|
267
|
-
message: 'An error occured in the transformer',
|
|
268
|
-
stack: 'Transformer returned undefined'
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
279
|
}
|
|
273
|
-
|
|
280
|
+
}
|
|
281
|
+
function updateResult(res) {
|
|
274
282
|
outputs.result?.set(res);
|
|
275
283
|
result = res;
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
if (
|
|
281
|
-
|
|
282
|
-
.map((r) => r?.error?.message)
|
|
283
|
-
.filter(Boolean)
|
|
284
|
-
.join('\n');
|
|
285
|
-
jobId && recordError(errorMessages, jobId);
|
|
286
|
-
dispatch('handleError', errorMessages);
|
|
284
|
+
}
|
|
285
|
+
async function setResult(res, jobId) {
|
|
286
|
+
dispatch('done');
|
|
287
|
+
const hasRes = res !== undefined && res !== null;
|
|
288
|
+
if (!jobId && !hasRes) {
|
|
289
|
+
return;
|
|
287
290
|
}
|
|
288
|
-
|
|
289
|
-
|
|
291
|
+
const errors = getResultErrors(res);
|
|
292
|
+
console.log('errors', errors);
|
|
293
|
+
if (errors) {
|
|
294
|
+
const transformerResult = transformer
|
|
295
|
+
? { error: 'Transformer could not be run because of previous errors' }
|
|
296
|
+
: undefined;
|
|
297
|
+
recordJob(jobId, undefined, errors, transformerResult);
|
|
298
|
+
updateResult(res);
|
|
299
|
+
dispatch('handleError', errors);
|
|
300
|
+
return;
|
|
290
301
|
}
|
|
291
|
-
const
|
|
292
|
-
if (
|
|
293
|
-
|
|
294
|
-
|
|
302
|
+
const transformerResult = await runTransformer(res);
|
|
303
|
+
if (transformerResult?.error) {
|
|
304
|
+
recordJob(jobId, res, undefined, transformerResult);
|
|
305
|
+
updateResult(transformerResult);
|
|
306
|
+
dispatch('handleError', transformerResult.error);
|
|
307
|
+
return;
|
|
295
308
|
}
|
|
309
|
+
updateResult(transformerResult ?? res);
|
|
310
|
+
recordJob(jobId, result, undefined, transformerResult);
|
|
311
|
+
$errorByComponent = clearErrorByComponentId(id, $errorByComponent);
|
|
312
|
+
dispatch('success');
|
|
296
313
|
donePromise?.();
|
|
297
314
|
}
|
|
298
315
|
function handleInputClick(e) {
|
|
@@ -377,7 +394,7 @@ let inputValues = {};
|
|
|
377
394
|
loading = false
|
|
378
395
|
}}
|
|
379
396
|
on:doneError={(e) => {
|
|
380
|
-
setResult({ error: e.detail }, e.detail.id)
|
|
397
|
+
setResult({ error: e.detail.error }, e.detail.id)
|
|
381
398
|
loading = false
|
|
382
399
|
}}
|
|
383
400
|
bind:this={resultJobLoader}
|
|
@@ -414,10 +431,17 @@ let inputValues = {};
|
|
|
414
431
|
<Alert type="error" title="Error during execution">
|
|
415
432
|
<div class="flex flex-col gap-2">
|
|
416
433
|
An error occured, please contact the app author.
|
|
434
|
+
|
|
435
|
+
{#if lastJobId && $errorByComponent[lastJobId]?.error}
|
|
436
|
+
<div class="font-bold">{$errorByComponent[lastJobId]?.error}</div>
|
|
437
|
+
{/if}
|
|
417
438
|
<a
|
|
418
439
|
href={`/run/${lastJobId}?workspace=${workspace}`}
|
|
419
|
-
class="font-semibold text-red-800 underline"
|
|
440
|
+
class="font-semibold text-red-800 underline"
|
|
441
|
+
target="_blank"
|
|
420
442
|
>
|
|
443
|
+
Job id: {lastJobId}
|
|
444
|
+
</a>
|
|
421
445
|
</div>
|
|
422
446
|
</Alert>
|
|
423
447
|
</div>
|
|
@@ -26,7 +26,6 @@ ${noReturn ? `return ${eval_string}` : eval_string}
|
|
|
26
26
|
}
|
|
27
27
|
function make_context_evaluator(eval_string, context, noReturn) {
|
|
28
28
|
let template = create_context_function_template(eval_string, context, noReturn);
|
|
29
|
-
console.debug(template);
|
|
30
29
|
let functor = Function(template);
|
|
31
30
|
return functor();
|
|
32
31
|
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
function toKebabCase(str) {
|
|
2
|
+
return str
|
|
3
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2') // Convert camel case to kebab case
|
|
4
|
+
.replace(/([A-Z0-9])([A-Z])/g, '$1-$2') // Separate consecutive uppercase letters
|
|
5
|
+
.replace(/([a-z])([0-9])/g, '$1-$2') // Separate letters from digits
|
|
6
|
+
.toLowerCase();
|
|
7
|
+
}
|
|
2
8
|
export async function loadIcon(name) {
|
|
3
9
|
let iconComponent;
|
|
4
10
|
try {
|
|
@@ -13,11 +13,18 @@ const { app, worldStore } = getContext('AppViewerContext');
|
|
|
13
13
|
let acceptedFileTypes = undefined;
|
|
14
14
|
let allowMultiple = undefined;
|
|
15
15
|
let text = undefined;
|
|
16
|
+
let includeMimeType = undefined;
|
|
16
17
|
let outputs = initOutput($worldStore, id, {
|
|
17
18
|
result: []
|
|
18
19
|
});
|
|
19
20
|
// Receives Base64 encoded strings from the input component
|
|
20
21
|
async function handleChange(files) {
|
|
22
|
+
if (includeMimeType === false) {
|
|
23
|
+
files = files?.map((file) => {
|
|
24
|
+
const [_, data] = file.data.split('base64,');
|
|
25
|
+
return { name: file.name, data };
|
|
26
|
+
});
|
|
27
|
+
}
|
|
21
28
|
outputs?.result.set(files);
|
|
22
29
|
}
|
|
23
30
|
$: css = concatCustomCss($app.css?.fileinputcomponent, customCss);
|
|
@@ -26,6 +33,7 @@ $: css = concatCustomCss($app.css?.fileinputcomponent, customCss);
|
|
|
26
33
|
<InputValue {id} input={configuration.acceptedFileTypes} bind:value={acceptedFileTypes} />
|
|
27
34
|
<InputValue {id} input={configuration.allowMultiple} bind:value={allowMultiple} />
|
|
28
35
|
<InputValue {id} input={configuration.text} bind:value={text} />
|
|
36
|
+
<InputValue {id} input={configuration.includeMimeType} bind:value={includeMimeType} />
|
|
29
37
|
|
|
30
38
|
<InitializeComponent {id} />
|
|
31
39
|
|