mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 08:02:26 +00:00
feat(apps): add setValue to frontend script's SDK
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
||||
|
||||
import libStdContent from '$lib/es5.d.ts.txt?raw'
|
||||
import { buildWorkerDefinition } from 'monaco-editor-workers'
|
||||
import { buildWorkerDefinition } from './build_workers'
|
||||
|
||||
meditor.defineTheme('myTheme', {
|
||||
base: 'vs',
|
||||
|
||||
@@ -390,6 +390,7 @@
|
||||
|
||||
if ($selectedComponent) {
|
||||
$componentControl[$selectedComponent[0]] = {
|
||||
...$componentControl[$selectedComponent[0]],
|
||||
setCode: (value: string) => {
|
||||
code = value
|
||||
setCode(value)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
export let configuration: RichConfigurations
|
||||
export let customCss: ComponentCustomCSS<'schemaformcomponent'> | undefined = undefined
|
||||
|
||||
const { worldStore, connectingInput, app, selectedComponent } =
|
||||
const { worldStore, connectingInput, app, selectedComponent, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
@@ -43,6 +43,12 @@
|
||||
outputs.values.set(newArgs, true)
|
||||
}
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: any) {
|
||||
args = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
$: args && handleArgsChange()
|
||||
|
||||
$: outputs.valid.set(valid)
|
||||
|
||||
@@ -19,9 +19,15 @@
|
||||
export let render: boolean
|
||||
|
||||
const requireHtmlApproval = getContext<boolean | undefined>(IS_APP_PUBLIC_CONTEXT_KEY)
|
||||
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
let result: any = undefined
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(value: string) {
|
||||
result = value
|
||||
}
|
||||
}
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
result: undefined,
|
||||
loading: false
|
||||
|
||||
@@ -48,6 +48,13 @@
|
||||
initializing = false
|
||||
}
|
||||
|
||||
$componentControl[id] = {
|
||||
...$componentControl[id],
|
||||
setValue(value: string) {
|
||||
result = value
|
||||
}
|
||||
}
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
result,
|
||||
loading: initializing
|
||||
@@ -119,7 +126,7 @@
|
||||
$: resolvedConfig.style && (component = getComponent())
|
||||
$: resolvedConfig.style && (classes = getClasses())
|
||||
$: initialValue = componentInput?.type == 'template' ? componentInput.eval : ''
|
||||
$: editableValue = initialValue ? JSON.parse(JSON.stringify(initialValue)) : ''
|
||||
$: editableValue = initialValue ?? ''
|
||||
|
||||
let rows = 1
|
||||
|
||||
@@ -128,7 +135,6 @@
|
||||
|
||||
if (target.value) {
|
||||
$componentControl[id]?.setCode?.(target.value)
|
||||
editableValue
|
||||
autosize()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,28 +72,29 @@
|
||||
|
||||
$: lastInput && $worldStore && debounce(handleConnection)
|
||||
|
||||
$: lastInput &&
|
||||
lastInput.type == 'template' &&
|
||||
$stateId &&
|
||||
$state &&
|
||||
debounce(async () => {
|
||||
let nvalue = await getValue(lastInput)
|
||||
if (!deepEqual(nvalue, value)) {
|
||||
value = nvalue
|
||||
}
|
||||
dispatch('done')
|
||||
})
|
||||
const debounceTemplate = async () => {
|
||||
console.log('template')
|
||||
let nvalue = await getValue(lastInput)
|
||||
if (!deepEqual(nvalue, value)) {
|
||||
value = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
$: lastInput &&
|
||||
lastInput.type == 'eval' &&
|
||||
lastInput.type == 'template' &&
|
||||
isCodeInjection(lastInput.eval) &&
|
||||
$stateId &&
|
||||
$state &&
|
||||
debounce2(async () => {
|
||||
let nvalue = await evalExpr(lastInput)
|
||||
if (!deepEqual(nvalue, value)) {
|
||||
value = nvalue
|
||||
}
|
||||
})
|
||||
debounce(debounceTemplate)
|
||||
|
||||
const debounceEval = async () => {
|
||||
let nvalue = await evalExpr(lastInput)
|
||||
if (!deepEqual(nvalue, value)) {
|
||||
value = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
$: lastInput && lastInput.type == 'eval' && $stateId && $state && debounce2(debounceEval)
|
||||
|
||||
async function handleConnection() {
|
||||
if (lastInput?.type === 'connected') {
|
||||
|
||||
@@ -20,7 +20,7 @@ export function computeGlobalContext(world: World | undefined, extraContext: any
|
||||
|
||||
function create_context_function_template(eval_string, context, noReturn: boolean) {
|
||||
return `
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid) {
|
||||
return async function (context, state, goto, setTab, recompute, getAgGrid, setValue) {
|
||||
"use strict";
|
||||
${
|
||||
Object.keys(context).length > 0
|
||||
@@ -36,7 +36,7 @@ function make_context_evaluator(
|
||||
eval_string,
|
||||
context,
|
||||
noReturn: boolean
|
||||
): (context, state, goto, setTab, recompute, getAgGrid) => Promise<any> {
|
||||
): (context, state, goto, setTab, recompute, getAgGrid, setValue) => Promise<any> {
|
||||
let template = create_context_function_template(eval_string, context, noReturn)
|
||||
let functor = Function(template)
|
||||
return functor()
|
||||
@@ -82,7 +82,11 @@ export async function eval_like(
|
||||
editor: boolean,
|
||||
controlComponents: Record<
|
||||
string,
|
||||
{ setTab?: (index: number) => void; agGrid?: { api: any; columnApi: any } }
|
||||
{
|
||||
setTab?: (index: number) => void
|
||||
agGrid?: { api: any; columnApi: any }
|
||||
setValue?: (value: any) => void
|
||||
}
|
||||
>,
|
||||
worldStore: World | undefined,
|
||||
runnableComponents: Record<string, { cb?: () => void }>
|
||||
@@ -126,6 +130,9 @@ export async function eval_like(
|
||||
},
|
||||
(id) => {
|
||||
return controlComponents[id]?.agGrid
|
||||
},
|
||||
(id, value) => {
|
||||
controlComponents[id]?.setValue?.(value)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -30,8 +30,16 @@
|
||||
configuration
|
||||
)
|
||||
|
||||
let value: boolean = (resolvedConfig.defaultValue as boolean | undefined) ?? false
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: boolean) {
|
||||
value = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
if (controls) {
|
||||
$componentControl[id] = controls
|
||||
$componentControl[id] = { ...$componentControl[id], ...controls }
|
||||
}
|
||||
|
||||
// As the checkbox is a special case and has no input
|
||||
@@ -41,7 +49,21 @@
|
||||
result: false
|
||||
})
|
||||
|
||||
$: resolvedConfig.defaultValue != undefined && outputs?.result.set(resolvedConfig.defaultValue)
|
||||
function handleInput() {
|
||||
outputs.result.set(value)
|
||||
if (recomputeIds) {
|
||||
recomputeIds.forEach((id) => $runnableComponents?.[id]?.cb())
|
||||
}
|
||||
}
|
||||
|
||||
function handleDefault() {
|
||||
value = resolvedConfig.defaultValue ?? false
|
||||
handleInput()
|
||||
}
|
||||
|
||||
$: value != undefined && handleInput()
|
||||
|
||||
$: resolvedConfig.defaultValue != undefined && handleDefault()
|
||||
|
||||
$: css = concatCustomCss($app.css?.checkboxcomponent, customCss)
|
||||
</script>
|
||||
@@ -60,16 +82,13 @@
|
||||
<AlignWrapper {render} {horizontalAlignment} {verticalAlignment}>
|
||||
<Toggle
|
||||
size="sm"
|
||||
bind:checked={resolvedConfig.defaultValue}
|
||||
bind:checked={value}
|
||||
options={{ right: resolvedConfig.label }}
|
||||
textClass={css?.text?.class ?? ''}
|
||||
textStyle={css?.text?.style ?? ''}
|
||||
on:change={(e) => {
|
||||
preclickAction?.()
|
||||
outputs.result.set(e.detail)
|
||||
if (recomputeIds) {
|
||||
recomputeIds.forEach((id) => $runnableComponents?.[id]?.cb())
|
||||
}
|
||||
value = e.detail
|
||||
}}
|
||||
/>
|
||||
</AlignWrapper>
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
export let customCss: ComponentCustomCSS<'dateinputcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, selectedComponent, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
let labelValue: string = 'Title'
|
||||
let minValue: string = ''
|
||||
let maxValue: string = ''
|
||||
@@ -23,6 +24,12 @@
|
||||
|
||||
let value: string | undefined = undefined
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
value = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
let outputs = initOutput($worldStore, id, {
|
||||
result: undefined as string | undefined
|
||||
})
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
export let customCss: ComponentCustomCSS<'multiselectcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, selectedComponent, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
let items: string[]
|
||||
|
||||
const resolvedConfig = initConfig(
|
||||
@@ -30,6 +31,13 @@
|
||||
|
||||
let value: string[] | undefined = outputs?.result.peak()
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string[]) {
|
||||
value = nvalue
|
||||
outputs?.result.set([...(value ?? [])])
|
||||
}
|
||||
}
|
||||
|
||||
$: resolvedConfig.items && handleItems()
|
||||
|
||||
function handleItems() {
|
||||
|
||||
@@ -14,12 +14,19 @@
|
||||
export let customCss: ComponentCustomCSS<'numberinputcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, selectedComponent, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let defaultValue: number | undefined = undefined
|
||||
let placeholder: string | undefined = undefined
|
||||
let value: number | undefined = undefined
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: number) {
|
||||
value = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
let min: number | undefined = undefined
|
||||
let max: number | undefined = undefined
|
||||
let step = 1
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
export let customCss: ComponentCustomCSS<'rangecomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
let min = 0
|
||||
let max = 42
|
||||
let step = 1
|
||||
@@ -27,6 +27,12 @@
|
||||
result: null as [number, number] | null
|
||||
})
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: [number, number]) {
|
||||
values = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
$: outputs?.result.set(values)
|
||||
|
||||
$: css = concatCustomCss($app.css?.rangecomponent, customCss)
|
||||
|
||||
@@ -31,8 +31,14 @@
|
||||
componentControl
|
||||
} = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
setValue(JSON.stringify(nvalue))
|
||||
}
|
||||
}
|
||||
|
||||
if (controls) {
|
||||
$componentControl[id] = controls
|
||||
$componentControl[id] = { ...$componentControl[id], ...controls }
|
||||
}
|
||||
|
||||
let resolvedConfig = initConfig(
|
||||
@@ -80,13 +86,16 @@
|
||||
return i
|
||||
})
|
||||
}
|
||||
|
||||
preclickAction?.()
|
||||
setValue(e.detail?.['value'])
|
||||
}
|
||||
|
||||
function setValue(nvalue: any) {
|
||||
let result: any = undefined
|
||||
try {
|
||||
result = JSON.parse(e.detail?.['value'])
|
||||
result = JSON.parse(nvalue)
|
||||
} catch (_) {}
|
||||
value = e.detail?.['value']
|
||||
value = nvalue
|
||||
outputs?.result.set(result)
|
||||
if (recomputeIds) {
|
||||
recomputeIds.forEach((id) => $runnableComponents?.[id]?.cb())
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const resolvedConfig = initConfig(
|
||||
components['selectstepcomponent'].initialData.configuration,
|
||||
@@ -26,13 +26,31 @@
|
||||
})
|
||||
|
||||
let selected: string = ''
|
||||
$: selected === '' && resolvedConfig && setDefaultValue()
|
||||
let selectedIndex: number = 0
|
||||
|
||||
$: resolvedConfig.defaultValue != undefined && setDefaultValue()
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
selected = nvalue
|
||||
selectedIndex = resolvedConfig.items.findIndex((item) => item.value === nvalue)
|
||||
},
|
||||
setTab(index) {
|
||||
selected = resolvedConfig.items?.[index]?.value
|
||||
selectedIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
function setDefaultValue() {
|
||||
if (resolvedConfig.defaultValue === undefined) {
|
||||
if (resolvedConfig.defaultValue != undefined) {
|
||||
selectedIndex = resolvedConfig.items.findIndex(
|
||||
(item) => item.value === resolvedConfig.defaultValue
|
||||
)
|
||||
}
|
||||
if (selectedIndex === -1 || resolvedConfig.defaultValue == undefined) {
|
||||
selected = resolvedConfig.items[0].value
|
||||
} else if (resolvedConfig.defaultValue?.value) {
|
||||
selected = resolvedConfig.defaultValue?.value
|
||||
} else if (resolvedConfig.defaultValue) {
|
||||
selected = resolvedConfig.items[selectedIndex].value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +69,6 @@
|
||||
}
|
||||
|
||||
$: selected && handleSelection(selected)
|
||||
|
||||
let selectedIndex: number = 0
|
||||
</script>
|
||||
|
||||
{#each Object.keys(components['selectstepcomponent'].initialData.configuration) as key (key)}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
export let customCss: ComponentCustomCSS<'selecttabcomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, componentControl } = getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const resolvedConfig = initConfig(
|
||||
components['selecttabcomponent'].initialData.configuration,
|
||||
@@ -30,6 +30,15 @@
|
||||
let selected: string = ''
|
||||
$: selected === '' && resolvedConfig && setDefaultValue()
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
selected = nvalue
|
||||
},
|
||||
setTab(index) {
|
||||
selected = resolvedConfig.items?.[index]?.value
|
||||
}
|
||||
}
|
||||
|
||||
function setDefaultValue() {
|
||||
if (resolvedConfig.defaultValue === undefined) {
|
||||
selected = resolvedConfig.items[0].value
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
export let customCss: ComponentCustomCSS<'slidercomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, selectedComponent, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
let min = 0
|
||||
let max = 42
|
||||
let step = 1
|
||||
@@ -28,6 +29,12 @@
|
||||
|
||||
let values: [number] = [outputs?.result.peak() ?? 0]
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: number) {
|
||||
values[0] = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
$: values && handleValues()
|
||||
|
||||
function handleValues() {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
| 'textareainputcomponent' = 'textinputcomponent'
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore, selectedComponent, connectingInput } =
|
||||
const { app, worldStore, selectedComponent, connectingInput, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
let placeholder: string | undefined = undefined
|
||||
@@ -31,6 +31,12 @@
|
||||
result: ''
|
||||
})
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: string) {
|
||||
value = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
$: handleDefault(defaultValue)
|
||||
|
||||
$: outputs?.result.set(value ?? '')
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
export let customCss: ComponentCustomCSS<'currencycomponent'> | undefined = undefined
|
||||
export let render: boolean
|
||||
|
||||
const { app, worldStore, selectedComponent } = getContext<AppViewerContext>('AppViewerContext')
|
||||
const { app, worldStore, selectedComponent, componentControl } =
|
||||
getContext<AppViewerContext>('AppViewerContext')
|
||||
|
||||
const outputs = initOutput($worldStore, id, {
|
||||
result: null as number | null
|
||||
@@ -28,6 +29,12 @@
|
||||
let locale: string | undefined = undefined
|
||||
let value: number | undefined = undefined
|
||||
|
||||
$componentControl[id] = {
|
||||
setValue(nvalue: number) {
|
||||
value = nvalue
|
||||
}
|
||||
}
|
||||
|
||||
function handleInput() {
|
||||
outputs?.result.set(value ?? null)
|
||||
}
|
||||
|
||||
@@ -237,6 +237,7 @@ state.foo += 1
|
||||
// you may also just reassign as next statement 'state.foo = state.foo'
|
||||
|
||||
// you can also navigate (goto), recompute a script (recompute), or set a tab (setTab)
|
||||
// Inputs and display components support settings their value directly (setValue)
|
||||
|
||||
return state.foo`,
|
||||
language: 'frontend',
|
||||
|
||||
+2
-2
@@ -161,8 +161,8 @@
|
||||
class="mb-0.5"
|
||||
documentationLink="https://docs.windmill.dev/docs/apps/app-runnable#background-runnable"
|
||||
>
|
||||
Background runnables are triggered upon global refresh or when their input changes. The
|
||||
result of a background runnable can be shared among many components.
|
||||
Background runnables can be triggered on app refresh or when their input changes. The
|
||||
result can be shared among many components.
|
||||
</Tooltip>
|
||||
</div>
|
||||
<Button
|
||||
|
||||
@@ -195,6 +195,7 @@ export type AppViewerContext = {
|
||||
agGrid?: { api: any; columnApi: any }
|
||||
setCode?: (value: string) => void
|
||||
onDelete?: () => void
|
||||
setValue?: (value: any) => void
|
||||
}
|
||||
>
|
||||
>
|
||||
|
||||
@@ -216,6 +216,7 @@ ${
|
||||
declare function setTab(id: string, index: string): void;
|
||||
declare function recompute(id: string): void;
|
||||
declare function getAgGrid(id: string): {api: any, columnApi: any} | undefined;
|
||||
declare function setValue(id: string, value: any): void;
|
||||
`
|
||||
: ''
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user