mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 08:02:18 +00:00
Merge branch 'main' into fr/xyflow
This commit is contained in:
@@ -3,9 +3,10 @@
|
||||
import type { Writable } from 'svelte/store'
|
||||
import type { GroupContext } from '../types'
|
||||
|
||||
export let groupContext: Writable<Record<string, any>>
|
||||
export let context: Writable<Record<string, any>>
|
||||
export let id: string
|
||||
|
||||
setContext<GroupContext>('GroupContext', groupContext)
|
||||
setContext<GroupContext>('GroupContext', { id, context })
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
|
||||
@@ -43,10 +43,12 @@
|
||||
|
||||
let previousConnectedValues: Record<string, any> = {}
|
||||
|
||||
let groupStore = groupContext?.context
|
||||
|
||||
$: fullContext = {
|
||||
iter: iterContext ? $iterContext : undefined,
|
||||
row: rowContext ? $rowContext : undefined,
|
||||
group: groupContext ? $groupContext : undefined
|
||||
group: groupStore ? $groupStore : undefined
|
||||
}
|
||||
|
||||
$: lastInput?.type == 'evalv2' &&
|
||||
@@ -272,7 +274,8 @@
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
false
|
||||
false,
|
||||
groupContext?.id
|
||||
)
|
||||
error = ''
|
||||
return r
|
||||
@@ -297,7 +300,8 @@
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
false
|
||||
false,
|
||||
groupContext?.id
|
||||
)
|
||||
error = ''
|
||||
return r
|
||||
|
||||
@@ -279,14 +279,15 @@
|
||||
computeGlobalContext($worldStore, {
|
||||
iter: iterContext ? $iterContext : undefined,
|
||||
row: rowContext ? $rowContext : undefined,
|
||||
group: groupContext ? $groupContext : undefined
|
||||
group: groupContext ? get(groupContext.context) : undefined
|
||||
}),
|
||||
$state,
|
||||
isEditor,
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
true
|
||||
true,
|
||||
groupContext?.id
|
||||
)
|
||||
|
||||
await setResult(r, job)
|
||||
@@ -504,6 +505,7 @@
|
||||
computeGlobalContext($worldStore, {
|
||||
iter: iterContext ? $iterContext : undefined,
|
||||
row: rowContext ? $rowContext : undefined,
|
||||
group: groupContext ? get(groupContext.context) : undefined,
|
||||
result: res
|
||||
}),
|
||||
$state,
|
||||
@@ -511,7 +513,8 @@
|
||||
$componentControl,
|
||||
$worldStore,
|
||||
$runnableComponents,
|
||||
true
|
||||
true,
|
||||
groupContext?.id
|
||||
)
|
||||
return transformerResult
|
||||
} catch (err) {
|
||||
|
||||
@@ -25,11 +25,11 @@ function create_context_function_template(
|
||||
) {
|
||||
let hasReturnAsLastLine = noReturn || eval_string.split('\n').some((x) => x.startsWith('return '))
|
||||
return `
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close, validate, invalidate, validateAll, clearFiles, showToast, waitJob, askNewResource) {
|
||||
return async function (context, state, createProxy, goto, setTab, recompute, getAgGrid, setValue, setSelectedIndex, openModal, closeModal, open, close, validate, invalidate, validateAll, clearFiles, showToast, waitJob, askNewResource) {
|
||||
"use strict";
|
||||
${
|
||||
contextKeys && contextKeys.length > 0
|
||||
? `let ${contextKeys.map((key) => ` ${key} = context['${key}']`)};`
|
||||
? `let ${contextKeys.map((key) => ` ${key} = createProxy('${key}', context['${key}'] ?? {})`)};`
|
||||
: ``
|
||||
}
|
||||
${
|
||||
@@ -46,6 +46,7 @@ return ${eval_string.startsWith('return ') ? eval_string.substring(7) : eval_str
|
||||
type WmFunctor = (
|
||||
context,
|
||||
state,
|
||||
createProxy,
|
||||
goto,
|
||||
setTab,
|
||||
recompute,
|
||||
@@ -113,30 +114,67 @@ export async function eval_like(
|
||||
showToast?: (message: string, error?: boolean) => void
|
||||
waitJob?: (jobId: string) => void
|
||||
askNewResource?: () => void
|
||||
setGroupValue?: (key: string, value: any) => void
|
||||
}
|
||||
>,
|
||||
worldStore: World | undefined,
|
||||
runnableComponents: Record<string, { cb?: (() => void)[] }>,
|
||||
noReturn: boolean
|
||||
noReturn: boolean,
|
||||
groupContextId: string | undefined
|
||||
) {
|
||||
const proxiedState = new Proxy(state, {
|
||||
set(target, key, value) {
|
||||
if (typeof key !== 'string') {
|
||||
throw new Error('Invalid key')
|
||||
}
|
||||
target[key] = value
|
||||
let o = worldStore?.newOutput('state', key, value)
|
||||
o?.set(value, true)
|
||||
|
||||
return true
|
||||
const createProxy = (name: string, obj: any) => {
|
||||
if (name == 'group' && groupContextId) {
|
||||
return createGroupProxy(groupContextId, obj)
|
||||
}
|
||||
})
|
||||
return new Proxy(obj, {
|
||||
set(target, key, value) {
|
||||
if (name != 'state') {
|
||||
throw new Error(
|
||||
'Cannot set value on objects that are neither the global state or a container group field'
|
||||
)
|
||||
}
|
||||
if (typeof key !== 'string') {
|
||||
throw new Error('Invalid key')
|
||||
}
|
||||
target[key] = value
|
||||
let o = worldStore?.newOutput(name, key, value)
|
||||
o?.set(value, true)
|
||||
|
||||
return true
|
||||
},
|
||||
get(obj, prop) {
|
||||
if (name != 'state' && prop == 'group') {
|
||||
return createGroupProxy(name, obj[prop])
|
||||
} else {
|
||||
return obj[prop]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const createGroupProxy = (name: string, obj: any) => {
|
||||
return new Proxy(obj, {
|
||||
set(target, key, value) {
|
||||
target[key] = value
|
||||
let o = worldStore?.newOutput(name, 'group', target)
|
||||
o?.set(target, true)
|
||||
if (typeof key !== 'string') {
|
||||
throw new Error('Invalid key')
|
||||
}
|
||||
controlComponents[name]?.setGroupValue?.(key, value)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const proxiedState = createProxy('state', state)
|
||||
|
||||
let evaluator = make_context_evaluator(text, Object.keys(context ?? {}), noReturn)
|
||||
// console.log(i, j)
|
||||
return await evaluator(
|
||||
context,
|
||||
proxiedState,
|
||||
createProxy,
|
||||
async (x, newTab) => {
|
||||
if (newTab || editor) {
|
||||
if (!newTab) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import { initOutput } from '../../editor/appUtils'
|
||||
import SubGridEditor from '../../editor/SubGridEditor.svelte'
|
||||
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
|
||||
@@ -18,7 +18,7 @@
|
||||
export let render: boolean
|
||||
export let groupFields: RichConfigurations | undefined = undefined
|
||||
|
||||
const { app, focusedGrid, selectedComponent, worldStore, connectingInput } =
|
||||
const { app, focusedGrid, selectedComponent, worldStore, connectingInput, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let groupContext = writable({})
|
||||
@@ -34,6 +34,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
$componentControl[id] = {
|
||||
setGroupValue: (field: string, value: any) => {
|
||||
groupContext.update((group) => {
|
||||
group[field] = value
|
||||
return group
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let css = initCss($app.css?.containercomponent, customCss)
|
||||
</script>
|
||||
|
||||
@@ -57,7 +68,7 @@
|
||||
|
||||
<div class="w-full h-full">
|
||||
{#if $app.subgrids?.[`${id}-0`]}
|
||||
<GroupWrapper {groupContext}>
|
||||
<GroupWrapper {id} context={groupContext}>
|
||||
<SubGridEditor
|
||||
visible={render}
|
||||
{id}
|
||||
|
||||
+5
-1
@@ -23,6 +23,7 @@
|
||||
}
|
||||
|
||||
function applyConnection(connection: InputConnection) {
|
||||
console.log(connection)
|
||||
const expr = `${connection.componentId}.${connection.path}`
|
||||
//@ts-ignore
|
||||
componentInput = {
|
||||
@@ -30,7 +31,10 @@
|
||||
type: 'evalv2',
|
||||
expr: expr,
|
||||
connections: [
|
||||
{ componentId: connection.componentId, id: connection.path.split('.')[0].split('[')[0] }
|
||||
{
|
||||
componentId: connection.componentId,
|
||||
id: connection?.path?.split('.')?.[0]?.split('[')?.[0]
|
||||
}
|
||||
]
|
||||
}
|
||||
evalV2editor?.setCode(expr)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import InputsSpecsEditor from './InputsSpecsEditor.svelte'
|
||||
import GroupManagementDrawer from '../componentsPanel/GroupManagementDrawer.svelte'
|
||||
import { Plus } from 'lucide-svelte'
|
||||
import { Alert } from '$lib/components/common'
|
||||
|
||||
export let groupFields: RichConfigurations | undefined
|
||||
export let item: GridItem
|
||||
@@ -44,7 +45,10 @@
|
||||
right: 'container is a component group',
|
||||
rightTooltip: `Group fields allow inner components to depend on the group fields which make the container a
|
||||
group of component that is encapsulated. Inside the group, it is possible to retrieve the values
|
||||
using \`group.<x />\` where x is the group field name`
|
||||
using \`group.x\` where x is the group field name.
|
||||
|
||||
Group fields are mutable by frontend scripts, so \`group.x = 42\` can be used to set the value inside the group and
|
||||
\`a.group.x = 42\` outside of it.`
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -111,6 +115,14 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2" />
|
||||
<Alert size="xs" title="Group fields are mutable" type="info">
|
||||
You may set the value of a group field in a frontend script within the group using: <code
|
||||
>group.x = 42</code
|
||||
>
|
||||
and externally using <code>{item.id}.group.x = 42</code>
|
||||
</Alert>
|
||||
</PanelSection>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ export type ListInputs = {
|
||||
remove: (id: string) => void
|
||||
}
|
||||
|
||||
export type GroupContext = Writable<Record<string, any>>
|
||||
export type GroupContext = { id: string; context: Writable<Record<string, any>> }
|
||||
|
||||
export type AppViewerContext = {
|
||||
worldStore: Writable<World>
|
||||
@@ -263,6 +263,7 @@ export type AppViewerContext = {
|
||||
showToast?: (message: string, error?: boolean) => void
|
||||
recompute?: () => void
|
||||
askNewResource?: () => void
|
||||
setGroupValue?: (key: string, value: any) => void
|
||||
}
|
||||
>
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user