windmill-components 1.377.7 → 1.379.2
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/ata/apis.d.ts +1 -0
- package/package/ata/apis.js +5 -3
- package/package/ata/index.d.ts +1 -1
- package/package/ata/index.js +2 -1
- package/package/components/DateInput.svelte +30 -3
- package/package/components/DisplayResult.svelte +19 -10
- package/package/components/DisplayResult.svelte.d.ts +1 -0
- package/package/components/FlowStatusViewer.svelte +2 -0
- package/package/components/FlowStatusViewer.svelte.d.ts +1 -0
- package/package/components/FlowStatusViewerInner.svelte +13 -10
- package/package/components/FlowStatusViewerInner.svelte.d.ts +1 -0
- package/package/components/FlowViewer.svelte.d.ts +1 -1
- package/package/components/InstanceSettings.svelte +1 -0
- package/package/components/LightweightArgInput.svelte +13 -6
- package/package/components/LightweightSchemaForm.svelte +4 -1
- package/package/components/LightweightSchemaForm.svelte.d.ts +1 -0
- package/package/components/LogViewer.svelte +0 -3
- package/package/components/Login.svelte +66 -73
- package/package/components/Login.svelte.d.ts +0 -2
- package/package/components/ModulePreview.svelte +1 -1
- package/package/components/ObjectStoreConfigSettings.svelte +2 -2
- package/package/components/Password.svelte +1 -1
- package/package/components/Portal.svelte +2 -2
- package/package/components/apps/components/GroupWrapper.svelte +3 -2
- package/package/components/apps/components/GroupWrapper.svelte.d.ts +2 -1
- package/package/components/apps/components/buttons/AppSchemaForm.svelte +16 -13
- package/package/components/apps/components/display/AppJobIdLogComponent.svelte +1 -1
- package/package/components/apps/components/display/AppRecomputeAll.svelte +2 -2
- package/package/components/apps/components/display/table/AppCell.svelte +5 -1
- package/package/components/apps/components/display/table/AppTableFooter.svelte +4 -1
- package/package/components/apps/components/helpers/InputValue.svelte +4 -3
- package/package/components/apps/components/helpers/RunnableComponent.svelte +4 -3
- package/package/components/apps/components/helpers/eval.d.ts +2 -1
- package/package/components/apps/components/helpers/eval.js +45 -14
- package/package/components/apps/components/inputs/AppTextInput.svelte +1 -0
- package/package/components/apps/components/layout/AppContainer.svelte +13 -3
- package/package/components/apps/editor/AppEditor.svelte +4 -7
- package/package/components/apps/editor/AppEditorHeader.svelte +22 -16
- package/package/components/apps/editor/AppPreview.svelte +8 -20
- package/package/components/apps/editor/AppPreview.svelte.d.ts +3 -1
- package/package/components/apps/editor/DeploymentHistory.svelte +1 -1
- package/package/components/apps/editor/RunnableJobPanel.svelte +8 -8
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +2 -2
- package/package/components/apps/editor/settingsPanel/ComponentInputTypeEditor.svelte +5 -1
- package/package/components/apps/editor/settingsPanel/GridGroup.svelte +13 -1
- package/package/components/apps/types.d.ts +7 -2
- package/package/components/apps/utils.js +30 -3
- package/package/components/common/drawer/Drawer.svelte +1 -1
- package/package/components/flows/previousResults.js +1 -0
- package/package/components/jobs/JobPreview.svelte +1 -1
- package/package/components/propertyPicker/PropPicker.svelte +2 -1
- package/package/components/runs/JobLoader.svelte +19 -7
- package/package/components/runs/JobLoader.svelte.d.ts +2 -1
- package/package/components/runs/JobPreview.svelte +2 -2
- package/package/components/runs/QueuePopover.svelte +1 -1
- package/package/components/runs/RunRow.svelte +14 -7
- package/package/components/runs/RunRow.svelte.d.ts +1 -0
- package/package/components/runs/RunsFilter.svelte +78 -15
- package/package/components/runs/RunsFilter.svelte.d.ts +3 -2
- package/package/components/runs/RunsQueue.svelte +23 -11
- package/package/components/runs/RunsQueue.svelte.d.ts +5 -1
- package/package/components/runs/RunsTable.svelte +65 -63
- package/package/components/runs/RunsTable.svelte.d.ts +1 -0
- package/package/components/scriptEditor/LogPanel.svelte +1 -1
- package/package/gen/core/OpenAPI.js +1 -1
- package/package/gen/services.gen.d.ts +8 -3
- package/package/gen/services.gen.js +16 -4
- package/package/gen/types.gen.d.ts +22 -0
- package/package.json +2 -9
- package/package/components/AppEmbed.svelte +0 -155
- package/package/components/AppEmbed.svelte.d.ts +0 -21
|
@@ -94,20 +94,23 @@ function onDefaultChange() {
|
|
|
94
94
|
<div
|
|
95
95
|
class={twMerge('p-2 overflow-auto h-full', css?.container?.class, 'wm-schema-form')}
|
|
96
96
|
style={css?.container?.style}
|
|
97
|
-
on:pointerdown|stopPropagation={(e) =>
|
|
98
|
-
!$connectingInput.opened && selectId(e, id, selectedComponent, $app)}
|
|
99
97
|
>
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
98
|
+
<div
|
|
99
|
+
on:pointerdown|stopPropagation={(e) =>
|
|
100
|
+
!$connectingInput.opened && selectId(e, id, selectedComponent, $app)}
|
|
101
|
+
>
|
|
102
|
+
<LightweightSchemaForm
|
|
103
|
+
defaultValues={resolvedConfig.defaultValues}
|
|
104
|
+
dynamicEnums={resolvedConfig.dynamicEnums}
|
|
105
|
+
schema={result}
|
|
106
|
+
bind:isValid={valid}
|
|
107
|
+
bind:args
|
|
108
|
+
bind:this={schemaForm}
|
|
109
|
+
displayType={Boolean(resolvedConfig.displayType)}
|
|
110
|
+
largeGap={Boolean(resolvedConfig.largeGap)}
|
|
111
|
+
{css}
|
|
112
|
+
/>
|
|
113
|
+
</div>
|
|
111
114
|
</div>
|
|
112
115
|
{:else}
|
|
113
116
|
<p class="m-2 italic">Empty form (no property)</p>
|
|
@@ -14,7 +14,7 @@ export let customCss = undefined;
|
|
|
14
14
|
export let configuration;
|
|
15
15
|
export let render;
|
|
16
16
|
export let horizontalAlignment = undefined;
|
|
17
|
-
const { app, worldStore } = getContext('AppViewerContext');
|
|
17
|
+
const { app, worldStore, policy } = getContext('AppViewerContext');
|
|
18
18
|
let resolvedConfig = initConfig(components['recomputeallcomponent'].initialData.configuration, configuration);
|
|
19
19
|
initOutput($worldStore, id, {
|
|
20
20
|
loading: undefined
|
|
@@ -45,7 +45,7 @@ let css = initCss($app.css?.recomputeallcomponent, customCss);
|
|
|
45
45
|
<InitializeComponent {id} />
|
|
46
46
|
|
|
47
47
|
<AlignWrapper {horizontalAlignment}>
|
|
48
|
-
{#if render}
|
|
48
|
+
{#if render && policy}
|
|
49
49
|
<RecomputeAllWrapper
|
|
50
50
|
containerClass={css?.container?.class}
|
|
51
51
|
containerStyle={css?.container?.style}
|
|
@@ -69,7 +69,11 @@ function saveEdit() {
|
|
|
69
69
|
{:else}
|
|
70
70
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
71
71
|
<div on:dblclick={toggleEdit}>
|
|
72
|
-
{value}
|
|
72
|
+
{#if typeof value == 'object'}
|
|
73
|
+
{JSON.stringify(value)}
|
|
74
|
+
{:else}
|
|
75
|
+
{value}
|
|
76
|
+
{/if}
|
|
73
77
|
</div>
|
|
74
78
|
{/if}
|
|
75
79
|
</td>
|
|
@@ -18,8 +18,11 @@ function convertJSONToCSV(objArray) {
|
|
|
18
18
|
for (let i = 0; i < objArray.length; i++) {
|
|
19
19
|
let line = '';
|
|
20
20
|
for (let j = 0; j < headers.length; j++) {
|
|
21
|
-
|
|
21
|
+
let value = objArray[i][headers[j]];
|
|
22
22
|
line += j ? ',' : '';
|
|
23
|
+
if (typeof value != 'string') {
|
|
24
|
+
value = JSON.stringify(value);
|
|
25
|
+
}
|
|
23
26
|
line += /[\",\n]/.test(value) ? '"' + value.replace(/"/g, '""') + '"' : value;
|
|
24
27
|
}
|
|
25
28
|
str += line + '\r\n';
|
|
@@ -20,10 +20,11 @@ const rowContext = getContext('RowWrapperContext');
|
|
|
20
20
|
const groupContext = getContext('GroupContext');
|
|
21
21
|
let previousConnectedValue = undefined;
|
|
22
22
|
let previousConnectedValues = {};
|
|
23
|
+
let groupStore = groupContext?.context;
|
|
23
24
|
$: fullContext = {
|
|
24
25
|
iter: iterContext ? $iterContext : undefined,
|
|
25
26
|
row: rowContext ? $rowContext : undefined,
|
|
26
|
-
group:
|
|
27
|
+
group: groupStore ? $groupStore : undefined
|
|
27
28
|
};
|
|
28
29
|
$: lastInput?.type == 'evalv2' &&
|
|
29
30
|
!onDemandOnly &&
|
|
@@ -190,7 +191,7 @@ async function evalExpr(input, args) {
|
|
|
190
191
|
return;
|
|
191
192
|
try {
|
|
192
193
|
const context = computeGlobalContext($worldStore, deepMergeWithPriority(fullContext, args ?? {}));
|
|
193
|
-
const r = await eval_like(input.expr, context, $state, $mode == 'dnd', $componentControl, $worldStore, $runnableComponents, false);
|
|
194
|
+
const r = await eval_like(input.expr, context, $state, $mode == 'dnd', $componentControl, $worldStore, $runnableComponents, false, groupContext?.id);
|
|
194
195
|
error = '';
|
|
195
196
|
return r;
|
|
196
197
|
}
|
|
@@ -207,7 +208,7 @@ async function getValue(input) {
|
|
|
207
208
|
return;
|
|
208
209
|
if ((input.type === 'template' || input.type == 'templatev2') && isCodeInjection(input.eval)) {
|
|
209
210
|
try {
|
|
210
|
-
const r = await eval_like('`' + input.eval + '`', computeGlobalContext($worldStore, fullContext), $state, $mode == 'dnd', $componentControl, $worldStore, $runnableComponents, false);
|
|
211
|
+
const r = await eval_like('`' + input.eval + '`', computeGlobalContext($worldStore, fullContext), $state, $mode == 'dnd', $componentControl, $worldStore, $runnableComponents, false, groupContext?.id);
|
|
211
212
|
error = '';
|
|
212
213
|
return r;
|
|
213
214
|
}
|
|
@@ -196,8 +196,8 @@ async function executeComponent(noToast = false, inlineScriptOverride, setRunnab
|
|
|
196
196
|
r = await eval_like(runnable.inlineScript?.content, computeGlobalContext($worldStore, {
|
|
197
197
|
iter: iterContext ? $iterContext : undefined,
|
|
198
198
|
row: rowContext ? $rowContext : undefined,
|
|
199
|
-
group: groupContext ?
|
|
200
|
-
}), $state, isEditor, $componentControl, $worldStore, $runnableComponents, true);
|
|
199
|
+
group: groupContext ? get(groupContext.context) : undefined
|
|
200
|
+
}), $state, isEditor, $componentControl, $worldStore, $runnableComponents, true, groupContext?.id);
|
|
201
201
|
await setResult(r, job);
|
|
202
202
|
$state = $state;
|
|
203
203
|
}
|
|
@@ -385,8 +385,9 @@ async function runTransformer(res) {
|
|
|
385
385
|
const transformerResult = await eval_like(transformer.content, computeGlobalContext($worldStore, {
|
|
386
386
|
iter: iterContext ? $iterContext : undefined,
|
|
387
387
|
row: rowContext ? $rowContext : undefined,
|
|
388
|
+
group: groupContext ? get(groupContext.context) : undefined,
|
|
388
389
|
result: res
|
|
389
|
-
}), $state, isEditor, $componentControl, $worldStore, $runnableComponents, true);
|
|
390
|
+
}), $state, isEditor, $componentControl, $worldStore, $runnableComponents, true, groupContext?.id);
|
|
390
391
|
return transformerResult;
|
|
391
392
|
}
|
|
392
393
|
catch (err) {
|
|
@@ -19,6 +19,7 @@ export declare function eval_like(text: string, context: {} | undefined, state:
|
|
|
19
19
|
showToast?: (message: string, error?: boolean) => void;
|
|
20
20
|
waitJob?: (jobId: string) => void;
|
|
21
21
|
askNewResource?: () => void;
|
|
22
|
+
setGroupValue?: (key: string, value: any) => void;
|
|
22
23
|
}>, worldStore: World | undefined, runnableComponents: Record<string, {
|
|
23
24
|
cb?: (() => void)[];
|
|
24
|
-
}>, noReturn: boolean): Promise<any>;
|
|
25
|
+
}>, noReturn: boolean, groupContextId: string | undefined): Promise<any>;
|
|
@@ -16,10 +16,10 @@ export function computeGlobalContext(world, extraContext = {}) {
|
|
|
16
16
|
function create_context_function_template(eval_string, contextKeys, noReturn) {
|
|
17
17
|
let hasReturnAsLastLine = noReturn || eval_string.split('\n').some((x) => x.startsWith('return '));
|
|
18
18
|
return `
|
|
19
|
-
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close, validate, invalidate, validateAll, clearFiles, showToast, waitJob, askNewResource) {
|
|
19
|
+
return async function (context, state, createProxy, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close, validate, invalidate, validateAll, clearFiles, showToast, waitJob, askNewResource) {
|
|
20
20
|
"use strict";
|
|
21
21
|
${contextKeys && contextKeys.length > 0
|
|
22
|
-
? `let ${contextKeys.map((key) => ` ${key} = context['${key}']`)};`
|
|
22
|
+
? `let ${contextKeys.map((key) => ` ${key} = createProxy('${key}', context['${key}'] ?? {})`)};`
|
|
23
23
|
: ``}
|
|
24
24
|
${hasReturnAsLastLine
|
|
25
25
|
? eval_string
|
|
@@ -52,21 +52,52 @@ function hashCode(s) {
|
|
|
52
52
|
}
|
|
53
53
|
return hash;
|
|
54
54
|
}
|
|
55
|
-
export async function eval_like(text, context = {}, state, editor, controlComponents, worldStore, runnableComponents, noReturn) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw new Error('Invalid key');
|
|
60
|
-
}
|
|
61
|
-
target[key] = value;
|
|
62
|
-
let o = worldStore?.newOutput('state', key, value);
|
|
63
|
-
o?.set(value, true);
|
|
64
|
-
return true;
|
|
55
|
+
export async function eval_like(text, context = {}, state, editor, controlComponents, worldStore, runnableComponents, noReturn, groupContextId) {
|
|
56
|
+
const createProxy = (name, obj) => {
|
|
57
|
+
if (name == 'group' && groupContextId) {
|
|
58
|
+
return createGroupProxy(groupContextId, obj);
|
|
65
59
|
}
|
|
66
|
-
|
|
60
|
+
return new Proxy(obj, {
|
|
61
|
+
set(target, key, value) {
|
|
62
|
+
if (name != 'state') {
|
|
63
|
+
throw new Error('Cannot set value on objects that are neither the global state or a container group field');
|
|
64
|
+
}
|
|
65
|
+
if (typeof key !== 'string') {
|
|
66
|
+
throw new Error('Invalid key');
|
|
67
|
+
}
|
|
68
|
+
target[key] = value;
|
|
69
|
+
let o = worldStore?.newOutput(name, key, value);
|
|
70
|
+
o?.set(value, true);
|
|
71
|
+
return true;
|
|
72
|
+
},
|
|
73
|
+
get(obj, prop) {
|
|
74
|
+
if (name != 'state' && prop == 'group') {
|
|
75
|
+
return createGroupProxy(name, obj[prop]);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return obj[prop];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const createGroupProxy = (name, obj) => {
|
|
84
|
+
return new Proxy(obj, {
|
|
85
|
+
set(target, key, value) {
|
|
86
|
+
target[key] = value;
|
|
87
|
+
let o = worldStore?.newOutput(name, 'group', target);
|
|
88
|
+
o?.set(target, true);
|
|
89
|
+
if (typeof key !== 'string') {
|
|
90
|
+
throw new Error('Invalid key');
|
|
91
|
+
}
|
|
92
|
+
controlComponents[name]?.setGroupValue?.(key, value);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
const proxiedState = createProxy('state', state);
|
|
67
98
|
let evaluator = make_context_evaluator(text, Object.keys(context ?? {}), noReturn);
|
|
68
99
|
// console.log(i, j)
|
|
69
|
-
return await evaluator(context, proxiedState, async (x, newTab) => {
|
|
100
|
+
return await evaluator(context, proxiedState, createProxy, async (x, newTab) => {
|
|
70
101
|
if (newTab || editor) {
|
|
71
102
|
if (!newTab) {
|
|
72
103
|
sendUserToast('In editor mode, `goto` opens a new tab to prevent losing your work. To test the redirection , use the preview mode.');
|
|
@@ -122,6 +122,7 @@ async function handleAfterIcon() {
|
|
|
122
122
|
!$connectingInput.opened && selectId(e, id, selectedComponent, $app)}
|
|
123
123
|
on:keydown|stopPropagation
|
|
124
124
|
type="password"
|
|
125
|
+
autocomplete="new-password"
|
|
125
126
|
bind:value
|
|
126
127
|
placeholder={resolvedConfig.placeholder}
|
|
127
128
|
disabled={resolvedConfig.disabled}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>import { getContext } from 'svelte';
|
|
1
|
+
<script>import { getContext, onMount } from 'svelte';
|
|
2
2
|
import { initOutput } from '../../editor/appUtils';
|
|
3
3
|
import SubGridEditor from '../../editor/SubGridEditor.svelte';
|
|
4
4
|
import { initCss } from '../../utils';
|
|
@@ -14,7 +14,7 @@ export let componentContainerHeight;
|
|
|
14
14
|
export let customCss = undefined;
|
|
15
15
|
export let render;
|
|
16
16
|
export let groupFields = undefined;
|
|
17
|
-
const { app, focusedGrid, selectedComponent, worldStore, connectingInput } = getContext('AppViewerContext');
|
|
17
|
+
const { app, focusedGrid, selectedComponent, worldStore, connectingInput, componentControl } = getContext('AppViewerContext');
|
|
18
18
|
let groupContext = writable({});
|
|
19
19
|
let outputs = initOutput($worldStore, id, { group: $groupContext });
|
|
20
20
|
$: outputs.group.set($groupContext, true);
|
|
@@ -24,6 +24,16 @@ function onFocus() {
|
|
|
24
24
|
subGridIndex: 0
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
onMount(() => {
|
|
28
|
+
$componentControl[id] = {
|
|
29
|
+
setGroupValue: (field, value) => {
|
|
30
|
+
groupContext.update((group) => {
|
|
31
|
+
group[field] = value;
|
|
32
|
+
return group;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
});
|
|
27
37
|
let css = initCss($app.css?.containercomponent, customCss);
|
|
28
38
|
</script>
|
|
29
39
|
|
|
@@ -47,7 +57,7 @@ let css = initCss($app.css?.containercomponent, customCss);
|
|
|
47
57
|
|
|
48
58
|
<div class="w-full h-full">
|
|
49
59
|
{#if $app.subgrids?.[`${id}-0`]}
|
|
50
|
-
<GroupWrapper {groupContext}>
|
|
60
|
+
<GroupWrapper {id} context={groupContext}>
|
|
51
61
|
<SubGridEditor
|
|
52
62
|
visible={render}
|
|
53
63
|
{id}
|
|
@@ -68,8 +68,8 @@ let context = {
|
|
|
68
68
|
email: $userStore?.email,
|
|
69
69
|
groups: $userStore?.groups,
|
|
70
70
|
username: $userStore?.username,
|
|
71
|
-
query: Object.fromEntries(
|
|
72
|
-
hash:
|
|
71
|
+
query: Object.fromEntries($page.url.searchParams.entries()),
|
|
72
|
+
hash: $page.url.hash,
|
|
73
73
|
workspace: $workspaceStore,
|
|
74
74
|
mode: 'editor',
|
|
75
75
|
summary: $summaryStore,
|
|
@@ -114,6 +114,7 @@ setContext('AppViewerContext', {
|
|
|
114
114
|
previewTheme,
|
|
115
115
|
debuggingComponents: writable({}),
|
|
116
116
|
replaceStateFn: (path) => replaceState(path, $page.state),
|
|
117
|
+
policy: policy,
|
|
117
118
|
recomputeAllContext: writable({
|
|
118
119
|
loading: false,
|
|
119
120
|
componentNumber: 0,
|
|
@@ -156,10 +157,6 @@ function saveFrontendDraft() {
|
|
|
156
157
|
function hashchange(e) {
|
|
157
158
|
context.hash = e.newURL.split('#')[1];
|
|
158
159
|
context = context;
|
|
159
|
-
worldStore.update((x) => {
|
|
160
|
-
x.outputsById?.['ctx']?.['hash'].set(context.hash, true);
|
|
161
|
-
return x;
|
|
162
|
-
});
|
|
163
160
|
}
|
|
164
161
|
$: context.mode = $mode == 'dnd' ? 'editor' : 'viewer';
|
|
165
162
|
$: width = $breakpoint === 'sm' ? 'min-w-[400px] max-w-[656px]' : 'min-w-[710px] w-full';
|
|
@@ -440,7 +437,7 @@ let stillInJobEnter = false;
|
|
|
440
437
|
app={$appStore}
|
|
441
438
|
appPath={path}
|
|
442
439
|
{breakpoint}
|
|
443
|
-
|
|
440
|
+
{policy}
|
|
444
441
|
isEditor
|
|
445
442
|
{context}
|
|
446
443
|
noBackend={false}
|
|
@@ -811,17 +811,19 @@ export function openTroubleshootPanel() {
|
|
|
811
811
|
<h2>Public URL</h2>
|
|
812
812
|
<div class="mt-4" />
|
|
813
813
|
|
|
814
|
-
<
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
814
|
+
<div class="flex gap-2 items-center">
|
|
815
|
+
<Toggle
|
|
816
|
+
options={{
|
|
817
|
+
left: `Require login and read-access`,
|
|
818
|
+
right: `No login required`
|
|
819
|
+
}}
|
|
820
|
+
checked={policy.execution_mode == 'anonymous'}
|
|
821
|
+
on:change={(e) => {
|
|
822
|
+
policy.execution_mode = e.detail ? 'anonymous' : 'publisher'
|
|
823
|
+
setPublishState()
|
|
824
|
+
}}
|
|
825
|
+
/>
|
|
826
|
+
</div>
|
|
825
827
|
|
|
826
828
|
<div class="my-6 box">
|
|
827
829
|
Public url:
|
|
@@ -848,10 +850,14 @@ export function openTroubleshootPanel() {
|
|
|
848
850
|
of embedding app must be the same as the one of Windmill)</div
|
|
849
851
|
>
|
|
850
852
|
</div>
|
|
851
|
-
|
|
852
853
|
<Alert type="info" title="Only latest deployed app is publicly available">
|
|
853
854
|
You will still need to deploy the app to make visible the latest changes
|
|
854
855
|
</Alert>
|
|
856
|
+
|
|
857
|
+
<a
|
|
858
|
+
href="https://www.windmill.dev/docs/advanced/external_auth_with_jwt#embed-public-apps-using-your-own-authentification"
|
|
859
|
+
class="mt-4 text-2xs">Embed this app in your own product to be used by your own users</a
|
|
860
|
+
>
|
|
855
861
|
{/if}
|
|
856
862
|
</DrawerContent>
|
|
857
863
|
</Drawer>
|
|
@@ -1020,14 +1026,14 @@ export function openTroubleshootPanel() {
|
|
|
1020
1026
|
duration={job?.['duration_ms']}
|
|
1021
1027
|
jobId={job?.id}
|
|
1022
1028
|
content={job?.logs}
|
|
1023
|
-
isLoading={testIsLoading}
|
|
1029
|
+
isLoading={testIsLoading && job?.['running'] == false}
|
|
1024
1030
|
tag={job?.tag}
|
|
1025
1031
|
/>
|
|
1026
1032
|
</Pane>
|
|
1027
1033
|
<Pane size={50} minSize={10} class="text-sm text-secondary">
|
|
1028
|
-
{#if job != undefined && 'result' in job && job.result != undefined}
|
|
1029
|
-
|
|
1030
|
-
|
|
1034
|
+
{#if job != undefined && 'result' in job && job.result != undefined}<div
|
|
1035
|
+
class="relative h-full px-2"
|
|
1036
|
+
><DisplayResult
|
|
1031
1037
|
workspaceId={$workspaceStore}
|
|
1032
1038
|
jobId={selectedJobId}
|
|
1033
1039
|
result={job.result}
|
|
@@ -10,7 +10,7 @@ import { columnConfiguration } from '../gridUtils';
|
|
|
10
10
|
import { deepEqual } from 'fast-equals';
|
|
11
11
|
import { dfs, maxHeight } from './appUtils';
|
|
12
12
|
import { BG_PREFIX, migrateApp } from '../utils';
|
|
13
|
-
import { workspaceStore, enterpriseLicense
|
|
13
|
+
import { workspaceStore, enterpriseLicense } from '../../../stores';
|
|
14
14
|
import DarkModeObserver from '../../DarkModeObserver.svelte';
|
|
15
15
|
import { getTheme } from './componentsPanel/themeUtils';
|
|
16
16
|
import HiddenComponent from '../components/helpers/HiddenComponent.svelte';
|
|
@@ -18,19 +18,17 @@ import RecomputeAllComponents from './RecomputeAllComponents.svelte';
|
|
|
18
18
|
export let app;
|
|
19
19
|
export let appPath = '';
|
|
20
20
|
export let breakpoint = writable('lg');
|
|
21
|
-
export let
|
|
21
|
+
export let policy = {};
|
|
22
22
|
export let summary = '';
|
|
23
23
|
export let workspace = $workspaceStore;
|
|
24
24
|
export let isEditor = false;
|
|
25
|
+
export let context;
|
|
25
26
|
export let noBackend = false;
|
|
26
27
|
export let isLocked = false;
|
|
27
28
|
export let hideRefreshBar = false;
|
|
28
29
|
export let replaceStateFn = (path) => window.history.replaceState(null, '', path);
|
|
29
30
|
export let gotoFn = (path, opt) => window.history.pushState(null, '', path);
|
|
30
31
|
migrateApp(app);
|
|
31
|
-
let email = $userStore?.email ?? 'anonymous';
|
|
32
|
-
let groups = $userStore?.groups ?? [];
|
|
33
|
-
let username = $userStore?.username ?? 'anonymous';
|
|
34
32
|
const appStore = writable(app);
|
|
35
33
|
const selectedComponent = writable(undefined);
|
|
36
34
|
const mode = writable('preview');
|
|
@@ -41,15 +39,11 @@ const connectingInput = writable({
|
|
|
41
39
|
});
|
|
42
40
|
const allIdsInPath = writable([]);
|
|
43
41
|
let ncontext = {
|
|
44
|
-
|
|
45
|
-
groups,
|
|
46
|
-
username,
|
|
47
|
-
query: Object.fromEntries(new URLSearchParams(window.location.search).entries()),
|
|
48
|
-
hash: window.location.hash,
|
|
42
|
+
...context,
|
|
49
43
|
workspace,
|
|
50
44
|
mode: 'viewer',
|
|
51
45
|
summary: summary,
|
|
52
|
-
author
|
|
46
|
+
author: policy.on_behalf_of_email
|
|
53
47
|
};
|
|
54
48
|
function resizeWindow() {
|
|
55
49
|
!isEditor && ($breakpoint = window.innerWidth < 769 ? 'sm' : 'lg');
|
|
@@ -60,14 +54,7 @@ const darkMode = writable(document.documentElement.classList.contains('dark'));
|
|
|
60
54
|
const state = writable({});
|
|
61
55
|
let parentContext = getContext('AppViewerContext');
|
|
62
56
|
let worldStore = buildWorld(ncontext);
|
|
63
|
-
$: onContextChange(
|
|
64
|
-
email,
|
|
65
|
-
groups,
|
|
66
|
-
username,
|
|
67
|
-
workspace,
|
|
68
|
-
summary: summary,
|
|
69
|
-
author
|
|
70
|
-
});
|
|
57
|
+
$: onContextChange(context);
|
|
71
58
|
function onContextChange(context) {
|
|
72
59
|
Object.assign(ncontext, context);
|
|
73
60
|
ncontext = ncontext;
|
|
@@ -120,6 +107,7 @@ setContext('AppViewerContext', {
|
|
|
120
107
|
debuggingComponents: writable({}),
|
|
121
108
|
replaceStateFn,
|
|
122
109
|
gotoFn,
|
|
110
|
+
policy,
|
|
123
111
|
recomputeAllContext: writable({
|
|
124
112
|
loading: false,
|
|
125
113
|
componentNumber: 0,
|
|
@@ -215,7 +203,7 @@ $: maxRow = maxHeight($appStore.grid, appHeight, $breakpoint);
|
|
|
215
203
|
<h2 class="truncate">{summary}</h2>
|
|
216
204
|
<RecomputeAllComponents />
|
|
217
205
|
<div class="text-2xs text-secondary">
|
|
218
|
-
{
|
|
206
|
+
{policy.on_behalf_of ? `on behalf of ${policy.on_behalf_of_email}` : ''}
|
|
219
207
|
</div>
|
|
220
208
|
</div>
|
|
221
209
|
</div>
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import { type Writable } from 'svelte/store';
|
|
3
3
|
import type { App, EditorBreakpoint } from '../types';
|
|
4
|
+
import type { Policy } from '../../../gen';
|
|
4
5
|
declare const __propDef: {
|
|
5
6
|
props: {
|
|
6
7
|
[x: string]: any;
|
|
7
8
|
app: App;
|
|
8
9
|
appPath?: string | undefined;
|
|
9
10
|
breakpoint?: Writable<EditorBreakpoint> | undefined;
|
|
10
|
-
|
|
11
|
+
policy?: Policy | undefined;
|
|
11
12
|
summary?: string | undefined;
|
|
12
13
|
workspace?: string | undefined;
|
|
13
14
|
isEditor?: boolean | undefined;
|
|
15
|
+
context: Record<string, any>;
|
|
14
16
|
noBackend?: boolean | undefined;
|
|
15
17
|
isLocked?: boolean | undefined;
|
|
16
18
|
hideRefreshBar?: boolean | undefined;
|
|
@@ -61,27 +61,27 @@ let resultDrawerOpen = false;
|
|
|
61
61
|
duration={testJob?.['duration_ms']}
|
|
62
62
|
mem={testJob?.['mem_peak']}
|
|
63
63
|
content={testJob?.logs}
|
|
64
|
-
isLoading={testIsLoading}
|
|
64
|
+
isLoading={testIsLoading && testJob?.['running'] == false}
|
|
65
65
|
tag={testJob?.tag}
|
|
66
66
|
/>
|
|
67
67
|
{/if}
|
|
68
68
|
</Pane>
|
|
69
69
|
<Pane size={frontendJob ? 70 : 50} minSize={10} class="text-sm text-tertiary">
|
|
70
70
|
{#if frontendJob}
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
>
|
|
71
|
+
<div class="break-words relative h-full px-1">
|
|
72
|
+
<DisplayResult bind:drawerOpen={resultDrawerOpen} result={frontendJob} />
|
|
73
|
+
</div>
|
|
74
74
|
{:else if testJob != undefined && 'result' in testJob && testJob.result != undefined}
|
|
75
|
-
<
|
|
76
|
-
|
|
75
|
+
<div class="break-words relative h-full px-1">
|
|
76
|
+
<DisplayResult
|
|
77
77
|
bind:drawerOpen={resultDrawerOpen}
|
|
78
78
|
workspaceId={testJob?.workspace_id}
|
|
79
79
|
jobId={testJob?.id}
|
|
80
80
|
result={testJob.result}
|
|
81
|
-
/></
|
|
81
|
+
/></div
|
|
82
82
|
>
|
|
83
83
|
{:else}
|
|
84
|
-
<div class="
|
|
84
|
+
<div class="px-1 pt-1">
|
|
85
85
|
{#if testIsLoading}
|
|
86
86
|
<Loader2 class="animate-spin" />
|
|
87
87
|
{:else}
|
|
@@ -255,7 +255,7 @@ async function inferSuggestions(code) {
|
|
|
255
255
|
|
|
256
256
|
<!-- {inlineScript.content} -->
|
|
257
257
|
|
|
258
|
-
<div class="border-y h-full">
|
|
258
|
+
<div class="border-y h-full w-full">
|
|
259
259
|
{#if !drawerIsOpen}
|
|
260
260
|
{#if inlineScript.language != 'frontend'}
|
|
261
261
|
<Editor
|
|
@@ -304,7 +304,7 @@ async function inferSuggestions(code) {
|
|
|
304
304
|
{:else}
|
|
305
305
|
<SimpleEditor
|
|
306
306
|
bind:this={simpleEditor}
|
|
307
|
-
class="h-full"
|
|
307
|
+
class="h-full max-w-full"
|
|
308
308
|
small
|
|
309
309
|
{extraLib}
|
|
310
310
|
bind:code={inlineScript.content}
|
|
@@ -14,6 +14,7 @@ $: if (componentInput.fieldType == 'template' && componentInput.type == 'static'
|
|
|
14
14
|
componentInput['connections'] = [{ componentId: 'ctx', id: 'email' }];
|
|
15
15
|
}
|
|
16
16
|
function applyConnection(connection) {
|
|
17
|
+
console.log(connection);
|
|
17
18
|
const expr = `${connection.componentId}.${connection.path}`;
|
|
18
19
|
//@ts-ignore
|
|
19
20
|
componentInput = {
|
|
@@ -21,7 +22,10 @@ function applyConnection(connection) {
|
|
|
21
22
|
type: 'evalv2',
|
|
22
23
|
expr: expr,
|
|
23
24
|
connections: [
|
|
24
|
-
{
|
|
25
|
+
{
|
|
26
|
+
componentId: connection.componentId,
|
|
27
|
+
id: connection?.path?.split('.')?.[0]?.split('[')?.[0]
|
|
28
|
+
}
|
|
25
29
|
]
|
|
26
30
|
};
|
|
27
31
|
evalV2editor?.setCode(expr);
|
|
@@ -4,6 +4,7 @@ import Toggle from '../../../Toggle.svelte';
|
|
|
4
4
|
import InputsSpecsEditor from './InputsSpecsEditor.svelte';
|
|
5
5
|
import GroupManagementDrawer from '../componentsPanel/GroupManagementDrawer.svelte';
|
|
6
6
|
import { Plus } from 'lucide-svelte';
|
|
7
|
+
import { Alert } from '../../../common';
|
|
7
8
|
export let groupFields;
|
|
8
9
|
export let item;
|
|
9
10
|
let groupManagementDrawer = undefined;
|
|
@@ -39,7 +40,10 @@ function addField(name) {
|
|
|
39
40
|
right: 'container is a component group',
|
|
40
41
|
rightTooltip: `Group fields allow inner components to depend on the group fields which make the container a
|
|
41
42
|
group of component that is encapsulated. Inside the group, it is possible to retrieve the values
|
|
42
|
-
using \`group
|
|
43
|
+
using \`group.x\` where x is the group field name.
|
|
44
|
+
|
|
45
|
+
Group fields are mutable by frontend scripts, so \`group.x = 42\` can be used to set the value inside the group and
|
|
46
|
+
\`a.group.x = 42\` outside of it.`
|
|
43
47
|
}}
|
|
44
48
|
/>
|
|
45
49
|
</div>
|
|
@@ -106,6 +110,14 @@ function addField(name) {
|
|
|
106
110
|
/>
|
|
107
111
|
</div>
|
|
108
112
|
</div>
|
|
113
|
+
|
|
114
|
+
<div class="mt-2" />
|
|
115
|
+
<Alert size="xs" title="Group fields are mutable" type="info">
|
|
116
|
+
You may set the value of a group field in a frontend script within the group using: <code
|
|
117
|
+
>group.x = 42</code
|
|
118
|
+
>
|
|
119
|
+
and externally using <code>{item.id}.group.x = 42</code>
|
|
120
|
+
</Alert>
|
|
109
121
|
</PanelSection>
|
|
110
122
|
{/if}
|
|
111
123
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="svelte" />
|
|
2
2
|
import type { Schema } from '../../common';
|
|
3
|
-
import type { Preview } from '../../gen';
|
|
3
|
+
import type { Policy, Preview } from '../../gen';
|
|
4
4
|
import type { History } from '../../history';
|
|
5
5
|
import type { Writable } from 'svelte/store';
|
|
6
6
|
import type { AppComponent, PresetComponentConfig, RecomputeOthersSource, components } from './editor/component/components';
|
|
@@ -127,7 +127,10 @@ export type ListInputs = {
|
|
|
127
127
|
set: (id: string, value: any) => void;
|
|
128
128
|
remove: (id: string) => void;
|
|
129
129
|
};
|
|
130
|
-
export type GroupContext =
|
|
130
|
+
export type GroupContext = {
|
|
131
|
+
id: string;
|
|
132
|
+
context: Writable<Record<string, any>>;
|
|
133
|
+
};
|
|
131
134
|
export type AppViewerContext = {
|
|
132
135
|
worldStore: Writable<World>;
|
|
133
136
|
app: Writable<App>;
|
|
@@ -198,6 +201,7 @@ export type AppViewerContext = {
|
|
|
198
201
|
showToast?: (message: string, error?: boolean) => void;
|
|
199
202
|
recompute?: () => void;
|
|
200
203
|
askNewResource?: () => void;
|
|
204
|
+
setGroupValue?: (key: string, value: any) => void;
|
|
201
205
|
}>>;
|
|
202
206
|
hoverStore: Writable<string | undefined>;
|
|
203
207
|
allIdsInPath: Writable<string[]>;
|
|
@@ -207,6 +211,7 @@ export type AppViewerContext = {
|
|
|
207
211
|
debuggingComponents: Writable<Record<string, number>>;
|
|
208
212
|
replaceStateFn?: ((url: string) => void) | undefined;
|
|
209
213
|
gotoFn?: ((url: string, opt?: Record<string, any> | undefined) => void) | undefined;
|
|
214
|
+
policy: Policy;
|
|
210
215
|
recomputeAllContext: Writable<{
|
|
211
216
|
onClick?: () => void;
|
|
212
217
|
componentNumber?: number | undefined;
|