mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-22 16:02:24 +00:00
235 lines
6.2 KiB
Svelte
235 lines
6.2 KiB
Svelte
<script lang="ts">
|
|
import { createBubbler, stopPropagation } from 'svelte/legacy'
|
|
|
|
const bubble = createBubbler()
|
|
import Button from '$lib/components/common/button/Button.svelte'
|
|
import type { Preview } from '$lib/gen'
|
|
import { createEventDispatcher, onMount } from 'svelte'
|
|
import { Maximize2, Trash2 } from 'lucide-svelte'
|
|
import { inferArgs } from '$lib/infer'
|
|
import type { Schema } from '$lib/common'
|
|
import Editor from '$lib/components/Editor.svelte'
|
|
import { emptySchema } from '$lib/utils'
|
|
|
|
import { scriptLangToEditorLang } from '$lib/scripts'
|
|
import ScriptGen from '$lib/components/copilot/ScriptGen.svelte'
|
|
import DiffEditor from '$lib/components/DiffEditor.svelte'
|
|
import EditorSettings from '$lib/components/EditorSettings.svelte'
|
|
import InlineScriptEditorDrawer from '../apps/editor/inlineScriptsPanel/InlineScriptEditorDrawer.svelte'
|
|
import type { InlineScript } from '../apps/types'
|
|
import type { AppInput } from '../apps/inputType'
|
|
import CacheTtlPopup from '../apps/editor/inlineScriptsPanel/CacheTtlPopup.svelte'
|
|
import RunButton from '$lib/components/RunButton.svelte'
|
|
import { computeFields } from '../apps/editor/inlineScriptsPanel/utils'
|
|
|
|
let inlineScriptEditorDrawer = $state() as InlineScriptEditorDrawer | undefined
|
|
|
|
interface Props {
|
|
inlineScript: InlineScript | undefined
|
|
name?: string | undefined
|
|
id: string
|
|
fields?: Record<string, AppInput>
|
|
path: string
|
|
isLoading?: boolean
|
|
onRun: () => Promise<void>
|
|
onCancel: () => Promise<void>
|
|
editor?: Editor | undefined
|
|
}
|
|
|
|
let {
|
|
inlineScript = $bindable(),
|
|
name = $bindable(undefined),
|
|
id,
|
|
fields = $bindable({}),
|
|
path,
|
|
isLoading = false,
|
|
onRun,
|
|
onCancel,
|
|
editor = $bindable(undefined)
|
|
}: Props = $props()
|
|
let diffEditor = $state() as DiffEditor | undefined
|
|
let validCode = $state(true)
|
|
|
|
async function inferInlineScriptSchema(
|
|
language: Preview['language'],
|
|
content: string,
|
|
schema: Schema
|
|
): Promise<Schema> {
|
|
try {
|
|
await inferArgs(language, content, schema)
|
|
validCode = true
|
|
} catch (e) {
|
|
console.error("Couldn't infer args", e)
|
|
validCode = false
|
|
}
|
|
|
|
return schema
|
|
}
|
|
|
|
onMount(async () => {
|
|
if (inlineScript && !inlineScript.schema) {
|
|
if (inlineScript.language != 'frontend') {
|
|
inlineScript.schema = await inferInlineScriptSchema(
|
|
inlineScript?.language,
|
|
inlineScript?.content,
|
|
emptySchema()
|
|
)
|
|
}
|
|
}
|
|
syncFields()
|
|
})
|
|
|
|
async function syncFields() {
|
|
if (inlineScript) {
|
|
const newSchema = inlineScript.schema ?? emptySchema()
|
|
fields = computeFields(newSchema, true, fields)
|
|
}
|
|
}
|
|
|
|
const dispatch = createEventDispatcher()
|
|
|
|
let drawerIsOpen: boolean | undefined = $state(undefined)
|
|
</script>
|
|
|
|
{#if inlineScript}
|
|
{#if inlineScript.language != 'frontend'}
|
|
<InlineScriptEditorDrawer
|
|
{id}
|
|
appPath={path}
|
|
bind:isOpen={drawerIsOpen}
|
|
{editor}
|
|
bind:this={inlineScriptEditorDrawer}
|
|
bind:inlineScript
|
|
on:createScriptFromInlineScript={() => {
|
|
dispatch('createScriptFromInlineScript')
|
|
drawerIsOpen = false
|
|
}}
|
|
/>
|
|
{/if}
|
|
<div class="h-full flex flex-col gap-1">
|
|
<div class="flex justify-between w-full gap-2 px-2 pt-1 flex-row items-center">
|
|
{#if name !== undefined}
|
|
<div class="flex flex-row gap-2 w-full items-center">
|
|
<input
|
|
onkeydown={stopPropagation(bubble('keydown'))}
|
|
bind:value={name}
|
|
placeholder="Inline script name"
|
|
class="!text-xs !rounded-sm !shadow-none"
|
|
onkeyup={() => {
|
|
// $app = $app
|
|
// if (stateId) {
|
|
// $stateId++
|
|
// }
|
|
}}
|
|
/>
|
|
<div
|
|
title={validCode ? 'Main function parsable' : 'Main function not parsable'}
|
|
class="rounded-full !w-2 !h-2 {validCode ? 'bg-green-300' : 'bg-red-300'}"
|
|
></div>
|
|
</div>
|
|
{/if}
|
|
<div class="flex w-full flex-row gap-1 items-center justify-end">
|
|
{#if inlineScript}
|
|
<CacheTtlPopup bind:cache_ttl={inlineScript.cache_ttl} />
|
|
{/if}
|
|
<ScriptGen
|
|
lang={inlineScript?.language}
|
|
{editor}
|
|
{diffEditor}
|
|
inlineScript
|
|
args={Object.entries(fields ?? {}).reduce((acc, [key, obj]) => {
|
|
acc[key] = obj.type === 'static' ? obj.value : undefined
|
|
return acc
|
|
}, {})}
|
|
/>
|
|
<EditorSettings />
|
|
|
|
<Button
|
|
title="Delete"
|
|
size="xs2"
|
|
color="light"
|
|
variant="contained"
|
|
aria-label="Delete"
|
|
on:click={() => dispatch('delete')}
|
|
endIcon={{ icon: Trash2 }}
|
|
iconOnly
|
|
/>
|
|
{#if inlineScript.language != 'frontend'}
|
|
<Button
|
|
size="xs2"
|
|
color="light"
|
|
title="Full Editor"
|
|
variant="contained"
|
|
on:click={() => {
|
|
inlineScriptEditorDrawer?.openDrawer()
|
|
}}
|
|
endIcon={{ icon: Maximize2 }}
|
|
iconOnly
|
|
/>
|
|
{/if}
|
|
|
|
<Button
|
|
variant="default"
|
|
size="xs2"
|
|
on:click={async () => {
|
|
editor?.format()
|
|
}}
|
|
shortCut={{
|
|
key: 'S'
|
|
}}
|
|
>
|
|
Format
|
|
</Button>
|
|
<RunButton {isLoading} {onRun} {onCancel} />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- {inlineScript.content} -->
|
|
|
|
<div class="border-y h-full w-full">
|
|
{#if !drawerIsOpen && inlineScript.language != 'frontend'}
|
|
<Editor
|
|
path={path + '/' + id}
|
|
bind:this={editor}
|
|
small
|
|
class="flex flex-1 grow h-full"
|
|
scriptLang={inlineScript.language}
|
|
bind:code={inlineScript.content}
|
|
fixedOverflowWidgets={true}
|
|
cmdEnterAction={() => onRun()}
|
|
on:change={async (e) => {
|
|
if (inlineScript && inlineScript.language != 'frontend') {
|
|
if (inlineScript.lock != undefined) {
|
|
inlineScript.lock = undefined
|
|
}
|
|
const oldSchema = JSON.stringify(inlineScript.schema)
|
|
if (inlineScript.schema == undefined) {
|
|
inlineScript.schema = emptySchema()
|
|
}
|
|
await inferInlineScriptSchema(inlineScript?.language, e.detail, inlineScript.schema)
|
|
if (JSON.stringify(inlineScript.schema) != oldSchema) {
|
|
inlineScript = inlineScript
|
|
syncFields()
|
|
}
|
|
}
|
|
// $app = $app
|
|
}}
|
|
args={Object.entries(fields ?? {}).reduce((acc, [key, obj]) => {
|
|
acc[key] = obj.type === 'static' ? obj.value : undefined
|
|
return acc
|
|
}, {})}
|
|
/>
|
|
|
|
<DiffEditor
|
|
open={false}
|
|
bind:this={diffEditor}
|
|
className="h-full"
|
|
automaticLayout
|
|
fixedOverflowWidgets
|
|
defaultLang={scriptLangToEditorLang(inlineScript?.language)}
|
|
/>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
{/if}
|