mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
feat(frontend): allow running eval in every field
This commit is contained in:
@@ -160,7 +160,9 @@
|
||||
editor.onDidBlurEditorText(() => {
|
||||
code = getCode()
|
||||
})
|
||||
}
|
||||
|
||||
function loadExtraLib() {
|
||||
if (lang == 'javascript') {
|
||||
const stdLib = { content: libStdContent, filePath: 'es5.d.ts' }
|
||||
if (extraLib != '') {
|
||||
@@ -177,12 +179,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
let mounted = false
|
||||
onMount(async () => {
|
||||
if (browser) {
|
||||
loadMonaco()
|
||||
mounted = true
|
||||
await loadMonaco()
|
||||
}
|
||||
})
|
||||
|
||||
$: mounted && extraLib && loadExtraLib()
|
||||
|
||||
onDestroy(() => {
|
||||
try {
|
||||
model && model.dispose()
|
||||
|
||||
@@ -459,19 +459,6 @@
|
||||
editor.addCommand(KeyMod.CtrlCmd | KeyCode.KeyS, function () {})
|
||||
})
|
||||
|
||||
const stdLib = { content: libStdContent, filePath: 'es5.d.ts' }
|
||||
if (extraLib != '') {
|
||||
languages.typescript.javascriptDefaults.setExtraLibs([
|
||||
{
|
||||
content: extraLib,
|
||||
filePath: 'windmill.d.ts'
|
||||
},
|
||||
stdLib
|
||||
])
|
||||
} else {
|
||||
languages.typescript.javascriptDefaults.setExtraLibs([stdLib])
|
||||
}
|
||||
|
||||
extraModel = meditor.createModel('`' + model.getValue() + '`', 'javascript')
|
||||
const worker = await languages.typescript.getJavaScriptWorker()
|
||||
const client = await worker(extraModel.uri)
|
||||
@@ -589,12 +576,31 @@
|
||||
editor?.focus()
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
let mounted = false
|
||||
onMount(async () => {
|
||||
if (browser) {
|
||||
loadMonaco()
|
||||
await loadMonaco()
|
||||
mounted = true
|
||||
}
|
||||
})
|
||||
|
||||
$: mounted && extraLib && loadExtraLib()
|
||||
|
||||
function loadExtraLib() {
|
||||
const stdLib = { content: libStdContent, filePath: 'es5.d.ts' }
|
||||
if (extraLib != '') {
|
||||
languages.typescript.javascriptDefaults.setExtraLibs([
|
||||
{
|
||||
content: extraLib,
|
||||
filePath: 'windmill.d.ts'
|
||||
},
|
||||
stdLib
|
||||
])
|
||||
} else {
|
||||
languages.typescript.javascriptDefaults.setExtraLibs([stdLib])
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
try {
|
||||
model && model.dispose()
|
||||
|
||||
@@ -56,6 +56,18 @@
|
||||
timeout = setTimeout(cb, debounce_ms)
|
||||
}
|
||||
|
||||
function debounce2(cb: () => Promise<void>) {
|
||||
if (firstDebounce) {
|
||||
firstDebounce = false
|
||||
cb()
|
||||
return
|
||||
}
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
timeout = setTimeout(cb, 1000)
|
||||
}
|
||||
|
||||
$: lastInput && $worldStore && debounce(handleConnection)
|
||||
|
||||
$: lastInput &&
|
||||
@@ -63,7 +75,10 @@
|
||||
$stateId &&
|
||||
$state &&
|
||||
debounce(async () => {
|
||||
value = await getValue(lastInput)
|
||||
let nvalue = await getValue(lastInput)
|
||||
if (!deepEqual(nvalue, value)) {
|
||||
value = nvalue
|
||||
}
|
||||
dispatch('done')
|
||||
})
|
||||
|
||||
@@ -71,7 +86,12 @@
|
||||
lastInput.type == 'eval' &&
|
||||
$stateId &&
|
||||
$state &&
|
||||
debounce(async () => (value = await evalExpr(lastInput)))
|
||||
debounce2(async () => {
|
||||
let nvalue = await evalExpr(lastInput)
|
||||
if (!deepEqual(nvalue, value)) {
|
||||
value = nvalue
|
||||
}
|
||||
})
|
||||
|
||||
async function handleConnection() {
|
||||
if (lastInput?.type === 'connected') {
|
||||
@@ -88,7 +108,7 @@
|
||||
dispatch('done')
|
||||
}
|
||||
|
||||
async function evalExpr(input: EvalAppInput) {
|
||||
async function evalExpr(input: EvalAppInput): Promise<any> {
|
||||
try {
|
||||
const r = await eval_like(
|
||||
input.expr,
|
||||
|
||||
@@ -135,11 +135,7 @@
|
||||
Object.keys(inputs ?? {}).forEach((key: string) => {
|
||||
const input = inputs[key]
|
||||
|
||||
if (input.type === 'static' && schemaStripped !== undefined) {
|
||||
delete schemaStripped.properties[key]
|
||||
}
|
||||
|
||||
if (input.type === 'connected' && schemaStripped !== undefined) {
|
||||
if (['static', 'eval', 'connected'].includes(input.type) && schemaStripped !== undefined) {
|
||||
delete schemaStripped.properties[key]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
</Splitpanes>
|
||||
</SplitPanesWrapper>
|
||||
</Pane>
|
||||
<Pane size={22} minSize={5} maxSize={33}>
|
||||
<Pane size={22} minSize={15} maxSize={33}>
|
||||
<div class="relative flex flex-col h-full">
|
||||
<Tabs bind:selected={selectedTab} wrapperClass="!min-h-[42px]" class="!h-full">
|
||||
<Popover disappearTimeout={0} notClickable placement="bottom">
|
||||
|
||||
@@ -55,15 +55,7 @@ export function selectId(
|
||||
selectedComponent: Writable<string[] | undefined>,
|
||||
app: App
|
||||
) {
|
||||
// this ensure handleClickOutside are triggered
|
||||
let event = new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
relatedTarget: e.target
|
||||
})
|
||||
window.dispatchEvent(event)
|
||||
|
||||
;(document?.activeElement as HTMLElement)?.blur()
|
||||
if (e.shiftKey) {
|
||||
selectedComponent.update((old) => {
|
||||
if (old && old?.[0]) {
|
||||
|
||||
@@ -410,8 +410,8 @@ export const components = {
|
||||
},
|
||||
disabled: {
|
||||
fieldType: 'boolean',
|
||||
type: 'eval',
|
||||
expr: 'false'
|
||||
type: 'static',
|
||||
value: false
|
||||
},
|
||||
beforeIcon: {
|
||||
type: 'static',
|
||||
@@ -517,8 +517,8 @@ export const components = {
|
||||
onSuccess: onSuccessClick,
|
||||
disabled: {
|
||||
fieldType: 'boolean',
|
||||
type: 'eval',
|
||||
expr: 'false'
|
||||
type: 'static',
|
||||
value: false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1536,8 +1536,8 @@ Hello \${ctx.username}
|
||||
},
|
||||
disabled: {
|
||||
fieldType: 'boolean',
|
||||
type: 'eval',
|
||||
expr: 'false'
|
||||
type: 'static',
|
||||
value: false
|
||||
}
|
||||
},
|
||||
componentInput: undefined,
|
||||
|
||||
@@ -97,9 +97,9 @@ export async function main(db: Resource<"postgresql"> = "$res:f/examples/demodb"
|
||||
}`
|
||||
},
|
||||
displaycomponent: {
|
||||
deno: `export async function main() {
|
||||
deno: `export async function main(x = 42) {
|
||||
return {
|
||||
"foo": 42
|
||||
foo: x
|
||||
}
|
||||
}`,
|
||||
python3: `def main():
|
||||
|
||||
+10
-14
@@ -132,20 +132,16 @@
|
||||
</Popover>
|
||||
{/if}
|
||||
{#if inlineScript.language != 'frontend'}
|
||||
<Popover notClickable placement="bottom">
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
btnClasses="!px-2 !bg-gray-100 hover:!bg-gray-200"
|
||||
aria-label="Open full editor"
|
||||
on:click={() => {
|
||||
inlineScriptEditorDrawer?.openDrawer()
|
||||
}}
|
||||
>
|
||||
Full Editor <Maximize2 size={14} />
|
||||
</Button>
|
||||
<svelte:fragment slot="text">Open full editor</svelte:fragment>
|
||||
</Popover>
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
btnClasses="!px-2 !bg-gray-100 hover:!bg-gray-200"
|
||||
on:click={() => {
|
||||
inlineScriptEditorDrawer?.openDrawer()
|
||||
}}
|
||||
>
|
||||
Full Editor <Maximize2 size={14} />
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
<Button
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import type { InputConnection, InputType, UploadAppInput } from '../../inputType'
|
||||
import ToggleButtonGroup from '$lib/components/common/toggleButton-v2/ToggleButtonGroup.svelte'
|
||||
import ToggleButton from '$lib/components/common/toggleButton-v2/ToggleButton.svelte'
|
||||
import { Pen, Plug2, Upload, User } from 'lucide-svelte'
|
||||
import { FunctionSquare, Pen, Plug2, Upload, User } from 'lucide-svelte'
|
||||
import { fieldTypeToTsType } from '../../utils'
|
||||
|
||||
export let id: string
|
||||
@@ -82,7 +82,7 @@
|
||||
</div>
|
||||
|
||||
<div class={classNames('flex gap-x-2 gap-y-1 flex-wrap justify-end items-center')}>
|
||||
{#if !onlyStatic && componentInput?.type && componentInput.type != 'eval'}
|
||||
{#if !onlyStatic && componentInput?.type}
|
||||
<ToggleButtonGroup
|
||||
class="h-7"
|
||||
bind:selected={componentInput.type}
|
||||
@@ -94,6 +94,12 @@
|
||||
hoveredComponent: undefined,
|
||||
onConnect: applyConnection
|
||||
}
|
||||
} else if (
|
||||
e.detail == 'eval' &&
|
||||
componentInput['value'] != undefined &&
|
||||
(componentInput['expr'] == '' || componentInput['expr'] == undefined)
|
||||
) {
|
||||
componentInput['expr'] = JSON.stringify(componentInput['value'])
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -105,6 +111,7 @@
|
||||
<ToggleButton value="upload" icon={Upload} iconOnly tooltip="Upload" />
|
||||
{/if}
|
||||
<ToggleButton value="connected" icon={Plug2} iconOnly tooltip="Connect" />
|
||||
<ToggleButton value="eval" icon={FunctionSquare} iconOnly tooltip="Eval" />
|
||||
</ToggleButtonGroup>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -115,7 +122,7 @@
|
||||
{:else if componentInput?.type === 'row'}
|
||||
<RowInputEditor bind:componentInput />
|
||||
{:else if componentInput?.type === 'static'}
|
||||
<div class={onlyStatic ? 'w-2/3 flex justify-end' : 'w-full'}>
|
||||
<div class={onlyStatic ? 'w-2/3 flex justify-end' : 'w-full flex flex-row-reverse'}>
|
||||
<StaticInputEditor
|
||||
{fieldType}
|
||||
{subFieldType}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
</script>
|
||||
|
||||
{#if componentInput?.type === 'eval'}
|
||||
<div class="border border-gray-300 ">
|
||||
<div class="border border-gray-300">
|
||||
<SimpleEditor
|
||||
lang="javascript"
|
||||
bind:code={componentInput.expr}
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@
|
||||
import TabSelectInput from './TabSelectInput.svelte'
|
||||
import { DollarSign } from 'lucide-svelte'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
import Toggle from '$lib/components/Toggle.svelte'
|
||||
|
||||
export let componentInput: StaticInput<any> | undefined
|
||||
export let fieldType: InputType | undefined = undefined
|
||||
@@ -34,7 +35,7 @@
|
||||
{:else if fieldType === 'date'}
|
||||
<input on:keydown|stopPropagation type="date" bind:value={componentInput.value} />
|
||||
{:else if fieldType === 'boolean'}
|
||||
<input type="checkbox" class="!w-4 !h-4 !rounded-sm" bind:checked={componentInput.value} />
|
||||
<Toggle bind:checked={componentInput.value} size="xs" />
|
||||
{:else if fieldType === 'select' && selectOptions}
|
||||
<select on:keydown|stopPropagation on:keydown|stopPropagation bind:value={componentInput.value}>
|
||||
{#each selectOptions ?? [] as option}
|
||||
|
||||
Reference in New Issue
Block a user