mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 00:02:19 +00:00
frontend misc
This commit is contained in:
+103
-3
@@ -1,18 +1,28 @@
|
||||
<script lang="ts">
|
||||
import type { Schema } from '$lib/common'
|
||||
import { Button, Drawer, DrawerContent, Tab, Tabs } from '$lib/components/common'
|
||||
import FlowScriptPicker from '$lib/components/flows/pickers/FlowScriptPicker.svelte'
|
||||
import PickHubScript from '$lib/components/flows/pickers/PickHubScript.svelte'
|
||||
import { Script, type Preview } from '$lib/gen'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { initialCode } from '$lib/script_helpers'
|
||||
import { capitalize, emptySchema } from '$lib/utils'
|
||||
import { capitalize, emptySchema, getScriptByPath } from '$lib/utils'
|
||||
import { faCodeBranch } from '@fortawesome/free-solid-svg-icons'
|
||||
import { Building, Globe2 } from 'lucide-svelte'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import { fly } from 'svelte/transition'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import { defaultCode } from '../Component.svelte'
|
||||
import InlineScriptList from '../settingsPanel/mainInput/InlineScriptList.svelte'
|
||||
import WorkspaceScriptList from '../settingsPanel/mainInput/WorkspaceScriptList.svelte'
|
||||
|
||||
export let name: string
|
||||
export let id: string
|
||||
|
||||
let tab = 'inlinescripts'
|
||||
let filter: string = ''
|
||||
let picker: Drawer
|
||||
|
||||
const { appPath, app } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -37,11 +47,16 @@
|
||||
) {
|
||||
const componentType = $app.grid.find((c) => c.data.id === id)?.data?.type
|
||||
|
||||
const fullPath = `${appPath}/inline-script/${path}`
|
||||
const content =
|
||||
defaultCode(componentType, language) ??
|
||||
initialCode(language, Script.kind.SCRIPT, subkind ?? 'flow')
|
||||
|
||||
return newInlineScript(content, language, path)
|
||||
}
|
||||
|
||||
async function newInlineScript(content: string, language: Preview.language, path: string) {
|
||||
const fullPath = `${appPath}/inline-script/${path}`
|
||||
|
||||
let schema: Schema = emptySchema()
|
||||
|
||||
schema = await inferInlineScriptSchema(language, content, schema)
|
||||
@@ -53,11 +68,84 @@
|
||||
}
|
||||
dispatch('new', newInlineScript)
|
||||
}
|
||||
|
||||
async function pickScript(path: string) {
|
||||
const script = await getScriptByPath(path)
|
||||
newInlineScript(script.content, script.language, path)
|
||||
}
|
||||
|
||||
async function pickHubScript(path: string) {
|
||||
const script = await getScriptByPath(path)
|
||||
newInlineScript(script.content, script.language, path)
|
||||
}
|
||||
|
||||
function pickInlineScript(name: string) {
|
||||
const unusedInlineScriptIndex = $app.unusedInlineScripts?.findIndex(
|
||||
(script) => script.name === name
|
||||
)
|
||||
const unusedInlineScript = $app.unusedInlineScripts?.[unusedInlineScriptIndex]
|
||||
|
||||
$app.unusedInlineScripts.splice(unusedInlineScriptIndex, 1)
|
||||
$app = $app
|
||||
dispatch('new', unusedInlineScript.inlineScript)
|
||||
}
|
||||
|
||||
const langs = ['deno', 'python3', 'go', 'bash'] as Script.language[]
|
||||
|
||||
function loadSchemaFromTriggerable(path: string, arg1: string) {
|
||||
throw new Error('Function not implemented.')
|
||||
}
|
||||
</script>
|
||||
|
||||
<Drawer bind:this={picker} size="1000px">
|
||||
<DrawerContent title="Script/Flow Picker" on:close={picker.closeDrawer}>
|
||||
<div>
|
||||
<div class="max-w-6xl">
|
||||
<Tabs bind:selected={tab}>
|
||||
<Tab size="sm" value="inlinescripts">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
<Building size={18} />
|
||||
Detached Inline Scripts
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab size="sm" value="workspacescripts">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
<Building size={18} />
|
||||
Workspace Scripts
|
||||
</div>
|
||||
</Tab>
|
||||
|
||||
<Tab size="sm" value="hubscripts">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
<Globe2 size={18} />
|
||||
Hub Scripts
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div class="my-2" />
|
||||
<div class="flex flex-col gap-y-16">
|
||||
<div class="flex flex-col">
|
||||
{#if tab == 'inlinescripts'}
|
||||
<InlineScriptList
|
||||
on:pick={(e) => pickInlineScript(e.detail)}
|
||||
inlineScripts={$app.unusedInlineScripts
|
||||
? $app.unusedInlineScripts.map((uis) => uis.name)
|
||||
: []}
|
||||
/>
|
||||
{:else if tab == 'workspacescripts'}
|
||||
<WorkspaceScriptList on:pick={(e) => pickScript(e.detail)} />
|
||||
{:else if tab == 'hubscripts'}
|
||||
<PickHubScript bind:filter on:pick={(e) => pickHubScript(e.detail.path)} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<div class="flex flex-col px-4 py-2 gap-2 text-sm" in:fly={{ duration: 50 }}>
|
||||
Please choose a language:
|
||||
<div>Choose a language:</div>
|
||||
<div class="flex gap-2 flex-row flex-wrap">
|
||||
{#each langs as lang}
|
||||
<FlowScriptPicker
|
||||
@@ -84,4 +172,16 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<Button
|
||||
on:click={() => picker?.openDrawer()}
|
||||
size="sm"
|
||||
color="blue"
|
||||
startIcon={{ icon: faCodeBranch }}
|
||||
btnClasses="truncate"
|
||||
>
|
||||
or fork a detached/Workspace/Hub script
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+3
-1
@@ -8,7 +8,8 @@
|
||||
import InlineScriptEditor from './InlineScriptEditor.svelte'
|
||||
import EmptyInlineScript from './EmptyInlineScript.svelte'
|
||||
|
||||
const { lazyGrid, app, staticOutputs } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const { lazyGrid, app, staticOutputs, runnableComponents } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
let selectedScriptComponentId: string | undefined = undefined
|
||||
</script>
|
||||
@@ -68,6 +69,7 @@
|
||||
$app.hiddenInlineScripts = [...$app.hiddenInlineScripts]
|
||||
|
||||
delete $staticOutputs[`bg_${index}`]
|
||||
delete $runnableComponents[`bg_${index}`]
|
||||
$staticOutputs = $staticOutputs
|
||||
}}
|
||||
/>
|
||||
|
||||
+30
-34
@@ -63,19 +63,19 @@
|
||||
</script>
|
||||
|
||||
<div class="mb-0 pb-0 pl-2 sticky top-0 bg-white border-b text-xs font-semibold">Runnables</div>
|
||||
<div bind:this={list} class="min-h-full flex flex-col gap-4">
|
||||
<div bind:this={list} class="grow flex flex-col gap-4">
|
||||
<PanelSection title="Inline scripts" smallPadding>
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
{#if runnables.inline.length > 0}
|
||||
<div class="flex gap-2 flex-col ">
|
||||
<div class="flex gap-1 flex-col ">
|
||||
{#each runnables.inline as { name, id }, index (index)}
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center p-2 rounded-sm duration-200
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center py-1 px-2 rounded-sm duration-200
|
||||
{selectedScriptComponentId === id ? 'border-blue-500 bg-blue-100' : 'hover:bg-blue-50'}"
|
||||
on:click={() => selectInlineScript(id)}
|
||||
>
|
||||
<span class="text-xs truncate">{name}</span>
|
||||
<span class="text-2xs truncate">{name}</span>
|
||||
<div>
|
||||
<Badge color="dark-indigo">{id}</Badge>
|
||||
</div>
|
||||
@@ -85,16 +85,16 @@
|
||||
{/if}
|
||||
|
||||
{#if $app.unusedInlineScripts?.length > 0}
|
||||
<div class="flex gap-2 flex-col ">
|
||||
<div class="flex gap-1 flex-col ">
|
||||
{#each $app.unusedInlineScripts as unusedInlineScript, index (index)}
|
||||
{@const id = `unused-${index}`}
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center p-2 rounded-sm duration-200
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center py-1 px-2 rounded-sm duration-200
|
||||
{selectedScriptComponentId === id ? 'border-blue-500 bg-blue-100' : 'hover:bg-blue-50'}"
|
||||
on:click={() => selectInlineScript(id)}
|
||||
>
|
||||
<span class="text-xs truncate">{unusedInlineScript.name}</span>
|
||||
<span class="text-2xs truncate">{unusedInlineScript.name}</span>
|
||||
<Badge color="red">Detached</Badge>
|
||||
</button>
|
||||
{/each}
|
||||
@@ -108,21 +108,19 @@
|
||||
</PanelSection>
|
||||
|
||||
<PanelSection title="Workspace/Hub" smallPadding>
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
<div class="flex flex-col gap-1 w-full">
|
||||
{#if runnables.imported.length > 0}
|
||||
<div class="flex gap-2 flex-col ">
|
||||
{#each runnables.imported as { name, id }, index (index)}
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center p-2 rounded-sm duration-200
|
||||
{#each runnables.imported as { name, id }, index (index)}
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center py-1 px-2 rounded-sm duration-200
|
||||
{selectedScriptComponentId === id ? 'border-blue-500 bg-blue-100' : 'hover:bg-blue-50'}"
|
||||
on:click={() => selectInlineScript(id)}
|
||||
>
|
||||
<span class="text-xs truncate">{name}</span>
|
||||
<Badge color="dark-indigo">{id}</Badge>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
on:click={() => selectInlineScript(id)}
|
||||
>
|
||||
<span class="text-2xs truncate">{name}</span>
|
||||
<Badge color="dark-indigo">{id}</Badge>
|
||||
</button>
|
||||
{/each}
|
||||
{:else}
|
||||
<div class="text-sm text-gray-500">No imported scripts/flows</div>
|
||||
{/if}
|
||||
@@ -140,22 +138,20 @@
|
||||
><Plus size={14} />
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
<div class="flex flex-col gap-1 w-full">
|
||||
{#if $app.hiddenInlineScripts?.length > 0}
|
||||
<div class="flex gap-2 flex-col ">
|
||||
{#each $app.hiddenInlineScripts as { name }, index (index)}
|
||||
{@const id = `bg_${index}`}
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center p-2 rounded-sm duration-200
|
||||
{#each $app.hiddenInlineScripts as { name }, index (index)}
|
||||
{@const id = `bg_${index}`}
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center py-1 px-2 rounded-sm duration-200
|
||||
{selectedScriptComponentId === id ? 'border-blue-500 bg-blue-100' : 'hover:bg-blue-50'}"
|
||||
on:click={() => selectInlineScript(id)}
|
||||
>
|
||||
<span class="text-xs truncate">{name}</span>
|
||||
<Badge color="yellow">Background</Badge>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
on:click={() => selectInlineScript(id)}
|
||||
>
|
||||
<span class="text-2xs truncate">{name}</span>
|
||||
<Badge color="dark-indigo">{id}</Badge>
|
||||
</button>
|
||||
{/each}
|
||||
{:else}
|
||||
<div class="text-sm text-gray-500">No items</div>
|
||||
{/if}
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<PanelSection title="Recompute others" tooltip="Select components to recompute after running this script">
|
||||
<PanelSection
|
||||
title="Recompute others"
|
||||
tooltip="Select components to recompute after running this script"
|
||||
>
|
||||
{#if Object.keys($runnableComponents ?? {}).filter((id) => id !== ownId).length > 0}
|
||||
<table class="divide-y divide-gray-300 border w-full">
|
||||
<thead class="bg-gray-50">
|
||||
|
||||
@@ -95,12 +95,12 @@
|
||||
|
||||
{#if adminsInstance}
|
||||
<Button
|
||||
btnClasses="w-full mt-2 mb-4"
|
||||
btnClasses="w-full mt-2 mb-4 truncate"
|
||||
color="light"
|
||||
size="sm"
|
||||
href="/user/switch_to_admins{rd ? `?rd=${encodeURIComponent(rd)}` : ''}"
|
||||
variant="border"
|
||||
>Manage Windmill on the workspace for superadmins
|
||||
>Manage Windmill on the superadmins workspace
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="flex justify-between items-center mt-10 flex-wrap">
|
||||
<div class="flex justify-between items-center mt-10 flex-wrap gap-2">
|
||||
{#if $superadmin}
|
||||
<Button variant="border" size="sm" on:click={superadminSettings.openDrawer}>
|
||||
<Icon data={faCrown} class="mr-1" scale={1} />
|
||||
|
||||
Reference in New Issue
Block a user