mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 16:00:38 +00:00
fix(frontend): Update app scripts pane (#1146)
* fix(frontend): Update app scripts pane * fix wrapping content * import capitalize util Co-authored-by: Faton Ramadani <faton.ramadani14@gmail.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
import { Script, type Preview } from '$lib/gen'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import { initialCode } from '$lib/script_helpers'
|
||||
import { emptySchema } from '$lib/utils'
|
||||
import { capitalize, emptySchema } from '$lib/utils'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import { fly } from 'svelte/transition'
|
||||
import { defaultCode } from '../../editorUtils'
|
||||
@@ -61,7 +61,7 @@
|
||||
<div class="flex gap-2 flex-row flex-wrap">
|
||||
{#each langs as lang}
|
||||
<FlowScriptPicker
|
||||
label={lang}
|
||||
label={capitalize(lang)}
|
||||
{lang}
|
||||
on:click={() => {
|
||||
createInlineScriptByLanguage(lang, name)
|
||||
|
||||
+37
-29
@@ -4,7 +4,7 @@
|
||||
import { faTrash } from '@fortawesome/free-solid-svg-icons'
|
||||
import { createEventDispatcher, getContext, onMount } from 'svelte'
|
||||
import type { AppEditorContext, InlineScript } from '../../types'
|
||||
import { CheckCircle, Code2, X } from 'lucide-svelte'
|
||||
import { CheckCircle, Code2, Maximize2, Trash2, X } from 'lucide-svelte'
|
||||
import InlineScriptEditorDrawer from './InlineScriptEditorDrawer.svelte'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import type { Schema } from '$lib/common'
|
||||
@@ -13,6 +13,7 @@
|
||||
import Editor from '$lib/components/Editor.svelte'
|
||||
import { emptySchema, scriptLangToEditorLang } from '$lib/utils'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import Popover from '../../../Popover.svelte'
|
||||
|
||||
let inlineScriptEditorDrawer: InlineScriptEditorDrawer
|
||||
|
||||
@@ -57,21 +58,51 @@
|
||||
<InlineScriptEditorDrawer {editor} bind:this={inlineScriptEditorDrawer} bind:inlineScript />
|
||||
|
||||
<div class="h-full flex flex-col gap-1" transition:fly|local={{ duration: 50 }}>
|
||||
<div class="flex justify-between w-full gap-1 px-2 pt-1 flex-row items-center">
|
||||
<div class="flex justify-between w-full gap-2 px-2 pt-1 flex-row items-center">
|
||||
{#if name !== undefined}
|
||||
<input bind:value={name} placeholder="Inline script name" />
|
||||
{/if}
|
||||
<div class="flex w-full flex-row gap-2 items-center justify-end">
|
||||
{#if validCode}
|
||||
<Badge color="green">
|
||||
<Badge color="green" baseClass="!p-0 !h-[30px] aspect-square center-center">
|
||||
<CheckCircle size={16} />
|
||||
</Badge>
|
||||
{:else}
|
||||
<Badge color="red">
|
||||
<Badge color="red" baseClass="!p-0 !h-[30px] aspect-square center-center">
|
||||
<X size={16} />
|
||||
</Badge>
|
||||
{/if}
|
||||
|
||||
{#if id.startsWith('unused-') || id.startsWith('bg_')}
|
||||
<Popover notClickable placement="bottom">
|
||||
<Button
|
||||
size="xs"
|
||||
color="red"
|
||||
variant="border"
|
||||
btnClasses="!px-1.5"
|
||||
aria-label="Delete"
|
||||
on:click={() => dispatch('delete')}
|
||||
>
|
||||
<Trash2 size={16} />
|
||||
</Button>
|
||||
<svelte:fragment slot="text">Delete</svelte:fragment>
|
||||
</Popover>
|
||||
{/if}
|
||||
<Popover notClickable placement="bottom">
|
||||
<Button
|
||||
size="xs"
|
||||
color="blue"
|
||||
variant="border"
|
||||
btnClasses="!px-1.5"
|
||||
aria-label="Open full editor"
|
||||
on:click={() => {
|
||||
inlineScriptEditorDrawer?.openDrawer()
|
||||
}}
|
||||
>
|
||||
<Maximize2 size={16} />
|
||||
</Button>
|
||||
<svelte:fragment slot="text">Open full editor</svelte:fragment>
|
||||
</Popover>
|
||||
<Button
|
||||
variant="border"
|
||||
size="xs"
|
||||
@@ -80,18 +111,8 @@
|
||||
editor.format()
|
||||
}}
|
||||
>
|
||||
Format <Tooltip>Ctrl+S</Tooltip>
|
||||
Format <Tooltip placement="bottom">Ctrl+S</Tooltip>
|
||||
</Button>
|
||||
{#if id.startsWith('unused-') || id.startsWith('bg_')}
|
||||
<Button
|
||||
size="xs"
|
||||
color="light"
|
||||
variant="border"
|
||||
iconOnly
|
||||
startIcon={{ icon: faTrash }}
|
||||
on:click={() => dispatch('delete')}
|
||||
/>
|
||||
{/if}
|
||||
{#if $runnableComponents[id] != undefined}
|
||||
<Button
|
||||
loading={runLoading}
|
||||
@@ -104,22 +125,9 @@
|
||||
}}
|
||||
>
|
||||
Run
|
||||
<Tooltip light>Ctrl+Enter</Tooltip>
|
||||
<Tooltip light placement="bottom">Ctrl+Enter</Tooltip>
|
||||
</Button>
|
||||
{/if}
|
||||
|
||||
<Button
|
||||
size="xs"
|
||||
color="blue"
|
||||
on:click={() => {
|
||||
inlineScriptEditorDrawer?.openDrawer()
|
||||
}}
|
||||
>
|
||||
<div class="flex gap-1 items-center">
|
||||
<Code2 size={16} />
|
||||
Open full editor
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+47
-43
@@ -1,7 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Badge, Button } from '$lib/components/common'
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
@@ -9,8 +7,11 @@
|
||||
import PanelSection from '../settingsPanel/common/PanelSection.svelte'
|
||||
import { getAppScripts } from './utils'
|
||||
|
||||
const PREFIX = 'script-selector-' as const
|
||||
|
||||
export let selectedScriptComponentId: string | undefined = undefined
|
||||
const { app, selectedComponent, lazyGrid } = getContext<AppEditorContext>('AppEditorContext')
|
||||
let list: HTMLElement
|
||||
|
||||
function selectInlineScript(id: string) {
|
||||
selectedScriptComponentId = id
|
||||
@@ -21,13 +22,20 @@
|
||||
|
||||
$: runnables = getAppScripts($lazyGrid)
|
||||
|
||||
// When seleced component changes, update selectedScriptComponentId
|
||||
$: {
|
||||
if (selectedComponent) {
|
||||
selectedScriptComponentId = $selectedComponent
|
||||
}
|
||||
// When selected component changes, update selectedScriptComponentId
|
||||
$: if (selectedComponent) {
|
||||
selectedScriptComponentId = $selectedComponent
|
||||
}
|
||||
|
||||
// Doesn't work for some reason
|
||||
// $: if (selectedScriptComponentId) {
|
||||
// const selected = document.getElementById(PREFIX + selectedScriptComponentId)
|
||||
// if(selected) {
|
||||
// const top = selected.getBoundingClientRect().top - list.getBoundingClientRect().top + list.scrollTop
|
||||
// list.scrollTo({ top, behavior: 'smooth' })
|
||||
// }
|
||||
// }
|
||||
|
||||
function createBackgroundScript() {
|
||||
let index = 0
|
||||
let newScriptPath = `Background Script ${index}`
|
||||
@@ -49,28 +57,27 @@
|
||||
fields: {}
|
||||
})
|
||||
$app.hiddenInlineScripts = $app.hiddenInlineScripts
|
||||
selectInlineScript(`bg_${$app.hiddenInlineScripts.length - 1}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="min-h-full flex flex-col gap-4">
|
||||
<div bind:this={list} class="min-h-full 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 ">
|
||||
{#each runnables.inline as { name, id }, index (index)}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="{classNames(
|
||||
'border flex gap-1 truncate justify-between flex-row w-full items-center p-2 rounded-sm cursor-pointer hover:bg-blue-50 hover:text-blue-400',
|
||||
selectedScriptComponentId === id ? 'border-blue-500 border' : ''
|
||||
)},"
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center p-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>
|
||||
<div>
|
||||
<Badge color="dark-indigo">{id}</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -78,17 +85,16 @@
|
||||
{#if $app.unusedInlineScripts?.length > 0}
|
||||
<div class="flex gap-2 flex-col ">
|
||||
{#each $app.unusedInlineScripts as unusedInlineScript, index (index)}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="{classNames(
|
||||
'border flex gap-1 truncate justify-between flex-row w-full items-center p-2 rounded-md cursor-pointer hover:bg-blue-50 hover:text-blue-400',
|
||||
selectedScriptComponentId === `unused-${index}` ? 'bg-blue-100 text-blue-600' : ''
|
||||
)},"
|
||||
on:click={() => selectInlineScript(`unused-${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
|
||||
{selectedScriptComponentId === id ? 'border-blue-500 bg-blue-100' : 'hover:bg-blue-50'}"
|
||||
on:click={() => selectInlineScript(id)}
|
||||
>
|
||||
<span class="text-xs truncate">{unusedInlineScript.name}</span>
|
||||
<Badge color="red">Detached</Badge>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -104,17 +110,15 @@
|
||||
{#if runnables.imported.length > 0}
|
||||
<div class="flex gap-2 flex-col ">
|
||||
{#each runnables.imported as { name, id }, index (index)}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="{classNames(
|
||||
'border flex gap-1 truncate justify-between flex-row w-full items-center p-2 rounded-md cursor-pointer hover:bg-blue-50 hover:text-blue-400',
|
||||
selectedScriptComponentId === id ? 'bg-blue-100 text-blue-600' : ''
|
||||
)},"
|
||||
<button
|
||||
id={PREFIX + id}
|
||||
class="border flex gap-1 truncate font-normal justify-between w-full items-center p-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>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
@@ -123,31 +127,31 @@
|
||||
</div>
|
||||
</PanelSection>
|
||||
|
||||
<PanelSection title="Background scripts" smallPadding>
|
||||
<PanelSection
|
||||
title="Background scripts"
|
||||
tooltip="Background scripts are triggered upon global refresh or when their input changes. The result
|
||||
of a background script can be shared among many components."
|
||||
smallPadding
|
||||
>
|
||||
<svelte:fragment slot="action">
|
||||
<Button size="xs" color="dark" startIcon={{ icon: faPlus }} on:click={createBackgroundScript}>
|
||||
Add
|
||||
</Button>
|
||||
<Tooltip>
|
||||
Background scripts are triggered upon global refresh or when their input changes. The result
|
||||
of a background script can be shared among many components.
|
||||
</Tooltip>
|
||||
</svelte:fragment>
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
{#if $app.hiddenInlineScripts?.length > 0}
|
||||
<div class="flex gap-2 flex-col ">
|
||||
{#each $app.hiddenInlineScripts as { name }, index (index)}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="{classNames(
|
||||
'border flex gap-1 truncate justify-between flex-row w-full items-center p-2 rounded-md cursor-pointer hover:bg-blue-50 hover:text-blue-400',
|
||||
selectedScriptComponentId === `bg_${index}` ? 'bg-blue-100 text-blue-600' : ''
|
||||
)},"
|
||||
on:click={() => selectInlineScript(`bg_${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
|
||||
{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>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
colorVariants?.[color]?.[variant],
|
||||
variant === 'border' ? 'border' : '',
|
||||
ButtonType.FontSizeClasses[size],
|
||||
ButtonType.SpacingClasses[spacingSize],
|
||||
ButtonType.SpacingClasses[spacingSize][variant],
|
||||
'focus:ring-2 font-semibold',
|
||||
'duration-200 rounded-md',
|
||||
'justify-center items-center text-center whitespace-nowrap inline-flex',
|
||||
@@ -79,7 +79,8 @@
|
||||
target,
|
||||
tabindex: disabled ? -1 : 0,
|
||||
type: buttonType,
|
||||
title
|
||||
title,
|
||||
...$$restProps
|
||||
}
|
||||
|
||||
async function onClick(event: MouseEvent) {
|
||||
|
||||
@@ -20,12 +20,27 @@ export namespace ButtonType {
|
||||
xl: 'text-xl'
|
||||
} as const
|
||||
|
||||
export const SpacingClasses: Record<ButtonType.Size, string> = {
|
||||
xs: 'px-3 py-1.5',
|
||||
sm: 'px-3 py-1.5',
|
||||
md: 'px-3 py-1.5',
|
||||
lg: 'px-4 py-2',
|
||||
xl: 'px-4 py-2'
|
||||
export const SpacingClasses: Record<ButtonType.Size, Record<ButtonType.Variant, string>> = {
|
||||
xs: {
|
||||
border: 'px-3 py-[6px]',
|
||||
contained: 'px-3 py-[7px]'
|
||||
},
|
||||
sm: {
|
||||
border: 'px-3 py-[6px]',
|
||||
contained: 'px-3 py-[7px]'
|
||||
},
|
||||
md: {
|
||||
border: 'px-3 py-[6px]',
|
||||
contained: 'px-3 py-[7px]'
|
||||
},
|
||||
lg: {
|
||||
border: 'px-4 py-[8px]',
|
||||
contained: 'px-4 py-[9px]'
|
||||
},
|
||||
xl: {
|
||||
border: 'px-4 py-[8px]',
|
||||
contained: 'px-4 py-[9px]'
|
||||
},
|
||||
} as const
|
||||
|
||||
export const IconScale: Record<ButtonType.Size, number> = {
|
||||
|
||||
Reference in New Issue
Block a user