Files
windmill/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptsPanel.svelte
2024-12-21 00:53:55 +01:00

162 lines
5.3 KiB
Svelte

<script lang="ts">
import { getContext } from 'svelte'
import type { AppEditorContext, AppViewerContext, HiddenRunnable } from '../../types'
import { Pane, Splitpanes } from 'svelte-splitpanes'
import InlineScriptsPanelList from './InlineScriptsPanelList.svelte'
import InlineScriptEditor from './InlineScriptEditor.svelte'
import InlineScriptsPanelWithTable from './InlineScriptsPanelWithTable.svelte'
import { findGridItem } from '../appUtils'
import InlineScriptHiddenRunnable from './InlineScriptHiddenRunnable.svelte'
import { BG_PREFIX } from '../../utils'
import { sendUserToast } from '$lib/toast'
import type { RunnableByName } from '../../inputType'
import { ScriptService } from '$lib/gen'
import { workspaceStore } from '$lib/stores'
import { findNextAvailablePath } from '$lib/path'
import { twMerge } from 'tailwind-merge'
const { app, runnableComponents } = getContext<AppViewerContext>('AppViewerContext')
const { selectedComponentInEditor } = getContext<AppEditorContext>('AppEditorContext')
function deleteBackgroundScript(index: number) {
// remove the script from the array at the index
if ($app.hiddenInlineScripts.length - 1 == index) {
$app.hiddenInlineScripts.splice(index, 1)
$app.hiddenInlineScripts = [...$app.hiddenInlineScripts]
} else {
$app.hiddenInlineScripts[index] = {
hidden: true,
inlineScript: undefined,
name: `Background Runnable ${index}`,
fields: {},
type: 'runnableByName',
recomputeIds: undefined
}
$app.hiddenInlineScripts = $app.hiddenInlineScripts
}
$selectedComponentInEditor = undefined
delete $runnableComponents[BG_PREFIX + index]
$runnableComponents = $runnableComponents
}
$: gridItem =
$selectedComponentInEditor && !$selectedComponentInEditor.startsWith(BG_PREFIX)
? findGridItem($app, $selectedComponentInEditor?.split('_')?.[0])
: undefined
$: hiddenInlineScript = $app?.hiddenInlineScripts?.findIndex((k_, index) => {
const [prefix, id] = $selectedComponentInEditor?.split('_') || []
if (prefix !== 'bg') return false
return Number(id) === index
})
$: unusedInlineScript = $app?.unusedInlineScripts?.findIndex(
(k_, index) => `unused-${index}` === $selectedComponentInEditor
)
async function createScriptFromInlineScript(
id: string,
runnable: HiddenRunnable | RunnableByName
) {
if (runnable.type != 'runnableByName') {
sendUserToast('Only inline scripts can be saved to workspace', true)
return
}
if (!runnable.inlineScript) {
sendUserToast('No inline script found', true)
return
}
let path = `${runnable.inlineScript.path}/inline_${id}`
path = await findNextAvailablePath(path)
let language = runnable.inlineScript.language
if (language == 'frontend') {
sendUserToast('Frontend scripts can not be saved to workspace', true)
return
}
await ScriptService.createScript({
workspace: $workspaceStore!,
requestBody: {
path: path,
summary: runnable.name ?? '',
description: '',
content: runnable.inlineScript.content,
parent_hash: undefined,
schema: runnable.inlineScript.schema,
is_template: false,
language: language!
}
})
Object.assign(runnable, {
type: 'runnableByPath',
schema: runnable.inlineScript.schema,
runType: 'script',
recomputeIds: undefined,
path
})
$app = $app
}
export let width: number | undefined = undefined
</script>
<Splitpanes
class={twMerge('!overflow-visible')}
style={width !== undefined ? `width:${width}px;` : 'width: 100%;'}
>
<Pane size={25}>
<InlineScriptsPanelList on:hidePanel />
</Pane>
<Pane size={75}>
{#if !$selectedComponentInEditor}
<div class="text-sm text-secondary text-center py-8 px-2">
Select a script on the left panel
</div>
{:else if gridItem}
{#key gridItem?.id}
<InlineScriptsPanelWithTable
on:createScriptFromInlineScript={(e) => {
createScriptFromInlineScript(gridItem?.id ?? 'unknown', e.detail)
}}
bind:gridItem
/>
{/key}
{:else if unusedInlineScript > -1 && $app.unusedInlineScripts?.[unusedInlineScript]}
{#key unusedInlineScript}
<InlineScriptEditor
on:createScriptFromInlineScript={() =>
sendUserToast('Cannot save to workspace unused scripts', true)}
id={`unused-${unusedInlineScript}`}
bind:name={$app.unusedInlineScripts[unusedInlineScript].name}
bind:inlineScript={$app.unusedInlineScripts[unusedInlineScript].inlineScript}
on:delete={() => {
// remove the script from the array at the index
$app.unusedInlineScripts.splice(unusedInlineScript, 1)
$app.unusedInlineScripts = [...$app.unusedInlineScripts]
}}
/>
{/key}
{:else if hiddenInlineScript > -1}
{#key hiddenInlineScript}
{#if $app.hiddenInlineScripts?.[hiddenInlineScript]}
<InlineScriptHiddenRunnable
on:createScriptFromInlineScript={(e) => {
createScriptFromInlineScript(BG_PREFIX + hiddenInlineScript, e.detail)
}}
transformer={$selectedComponentInEditor?.endsWith('_transformer')}
on:delete={() => deleteBackgroundScript(hiddenInlineScript)}
id={BG_PREFIX + hiddenInlineScript}
bind:runnable={$app.hiddenInlineScripts[hiddenInlineScript]}
/>{/if}{/key}
{:else}
<div class="text-sm text-tertiary text-center py-8 px-2">
No script found at id {$selectedComponentInEditor}
</div>
{/if}
</Pane>
</Splitpanes>