Files
windmill/frontend/src/lib/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte
T
Guilhem 87cda7a4d7 migrate popup to melt popover (3/4) (#5328)
* use melt menu in sidebar

* stop keyboard navigation for disabled items

* use melt menu for FavoriteMenu and WorkspaceMenu

* fix popover placement for menuButton

* use melt menu for operator menu

* fix notification

* fix operator menu

* Use melt menu in FlowJobsMenu

* use melt menu for AppMenu

* clean code

* clean code

* add use clickOutside option to Menu

* use pointerdown_outside

* use pointerdown_outside

# Conflicts:
#	frontend/src/lib/components/meltComponents/Menu.svelte

* use pointerdown in menus

* add max-h to app dropdown menu

* keep more open in operator menu

* add a MenuItem component

* clean

* nit

* nit

* clean code

* put conditionalMelt as utility function

* remove unused Portal

* Add debounce effect in operator menu

* fix component jumping due to z-index

* format pages

* migrate dropdown to melt

* migrate popup to melt popover

* feat: remove `pip` fallback option for python and ansible (#5186)

* refactor!: Remove `pip` fallback option for python and ansible

BREAKING CHANGE: pip was deprecated since 1.425.0 (2024-11-15)

* fix errors in main.rs

* fix tests

* remove nsjail for pip

* fix imports

* fix compilation error

* reinforce melt types

* fix racing condition issue in closing operator menu

* nit

* fix id conflix with melt element

* nit

* clean code

* use melt dropdown instead of menubar

* prevent modal from closing on click outside button in menu

* fix nit

* nit

* close dropdown when opening a new one

* replace MenuV2 with melt Menu (1/4) (#5214)

* use melt menu in sidebar

* stop keyboard navigation for disabled items

* use melt menu for FavoriteMenu and WorkspaceMenu

* fix popover placement for menuButton

* use melt menu for operator menu

* fix notification

* fix operator menu

* Use melt menu in FlowJobsMenu

* use melt menu for AppMenu

* clean code

* clean code

* add use clickOutside option to Menu

* use pointerdown_outside

* use pointerdown_outside

# Conflicts:
#	frontend/src/lib/components/meltComponents/Menu.svelte

* use pointerdown in menus

* add max-h to app dropdown menu

* keep more open in operator menu

* add a MenuItem component

* clean

* nit

* nit

* clean code

* put conditionalMelt as utility function

* remove unused Portal

* Add debounce effect in operator menu

* fix component jumping due to z-index

* feat: remove `pip` fallback option for python and ansible (#5186)

* refactor!: Remove `pip` fallback option for python and ansible

BREAKING CHANGE: pip was deprecated since 1.425.0 (2024-11-15)

* fix errors in main.rs

* fix tests

* remove nsjail for pip

* fix imports

* fix compilation error

* reinforce melt types

* fix racing condition issue in closing operator menu

* nit

* fix id conflix with melt element

* nit

* prevent modal from closing on click outside button in menu

---------

Co-authored-by: pyranota <92104930+pyranota@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
# Conflicts:
#	frontend/src/lib/components/meltComponents/MenuItem.svelte
#	frontend/src/lib/utils.ts

* clean

* fix z index and render

* fix initialize of dropdownmenu after melt migration

* feat: add support for | None and Optional in python (#5361)

* feat: add support for | None and Optional in python

* update python parser package

* add local rooting for MenuItem

* fix z index

* clean

* nit

* nit

* clean code

* nit

---------

Co-authored-by: pyranota <92104930+pyranota@users.noreply.github.com>
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
Co-authored-by: HugoCasa <hugo@casademont.ch>
2025-02-25 09:53:43 +01:00

243 lines
6.1 KiB
Svelte

<script lang="ts">
import { Button, Drawer, DrawerContent } from '$lib/components/common'
import { base } from '$lib/base'
import FlowModuleScript from '$lib/components/flows/content/FlowModuleScript.svelte'
import FlowPathViewer from '$lib/components/flows/content/FlowPathViewer.svelte'
import { emptySchema } from '$lib/utils'
import { getContext, tick } from 'svelte'
import type {
ConnectedAppInput,
RowAppInput,
RunnableByPath,
StaticAppInput,
UserAppInput
} from '../../inputType'
import type { AppViewerContext } from '../../types'
import { workspaceStore } from '$lib/stores'
import { createEventDispatcher } from 'svelte'
import { deepEqual } from 'fast-equals'
import { computeFields } from './utils'
import { inferArgs, loadSchema } from '$lib/infer'
import RunButton from './RunButton.svelte'
import { getScriptByPath } from '$lib/scripts'
import { sendUserToast } from '$lib/toast'
import { autoPlacement } from '@floating-ui/core'
import { ExternalLink, Eye, GitFork, Pen, RefreshCw, Trash } from 'lucide-svelte'
import Popover from '$lib/components/meltComponents/Popover.svelte'
export let runnable: RunnableByPath
export let fields: Record<string, StaticAppInput | ConnectedAppInput | RowAppInput | UserAppInput>
export let id: string
const { stateId } = getContext<AppViewerContext>('AppViewerContext')
let drawerFlowViewer: Drawer
let flowPath: string = ''
let notFound = false
const dispatch = createEventDispatcher()
async function refreshScript(x: RunnableByPath) {
try {
let { schema } = await getScriptByPath(x.path)
if (!deepEqual(x.schema, schema)) {
x.schema = schema
if (!x.schema.order) {
x.schema.order = Object.keys(x.schema.properties ?? {})
}
fields = computeFields(schema, false, fields)
}
} catch (e) {
notFound = true
console.error(e)
}
}
async function refreshFlow(x: RunnableByPath) {
try {
const { schema } = (await loadSchema($workspaceStore ?? '', x.path, 'flow')) ?? emptySchema()
if (!deepEqual(x.schema, schema)) {
x.schema = schema
if (!x.schema.order) {
x.schema.order = Object.keys(x.schema.properties ?? {})
}
fields = computeFields(schema, false, fields)
}
} catch (e) {
notFound = true
console.error(e)
}
}
async function fork(path: string) {
let { content, language, schema } = await getScriptByPath(path)
if (!schema || typeof schema == 'string' || Object.keys(schema).length == 0) {
schema = emptySchema()
await inferArgs(language, content, schema)
}
dispatch('fork', {
type: 'runnableByName',
name: path,
inlineScript: {
content,
language,
schema,
path
}
})
}
let lastRunnable: RunnableByPath | undefined = undefined
function refresh(runnable) {
if (deepEqual(runnable, lastRunnable)) {
return
}
notFound = false
if (runnable.runType == 'script') {
refreshScript(runnable)
} else if (runnable.runType == 'flow') {
refreshFlow(runnable)
}
lastRunnable = runnable
}
$: refresh(runnable)
</script>
<Drawer bind:this={drawerFlowViewer} size="1200px">
<DrawerContent title="Flow {flowPath}" on:close={drawerFlowViewer.closeDrawer}>
<FlowPathViewer path={flowPath ?? ''} />
</DrawerContent>
</Drawer>
<div class="p-2 h-full flex flex-col gap-2">
<div class="flex flex-row-reverse w-full gap-2">
<RunButton hideShortcut {id} />
<Button
variant="border"
size="xs"
color="light"
startIcon={{ icon: RefreshCw }}
on:click={async () => {
sendUserToast('Refreshing inputs')
refresh(runnable)
$stateId = $stateId + 1
await tick()
}}
/>
<Button
size="xs"
variant="border"
color="red"
startIcon={{ icon: Trash }}
on:click={() => {
dispatch('delete')
}}
>
Clear
</Button>
{#if runnable.runType == 'flow'}
<Button
variant="border"
size="xs"
color="light"
startIcon={{ icon: Eye }}
on:click={() => {
flowPath = runnable.path
drawerFlowViewer.openDrawer()
}}
>
Expand
</Button>
<Button
variant="border"
size="xs"
color="light"
startIcon={{ icon: Pen }}
endIcon={{ icon: ExternalLink }}
target="_blank"
href="{base}/flows/edit/{runnable.path}?nodraft=true">Edit</Button
>
<Button
variant="border"
size="xs"
color="light"
startIcon={{ icon: Eye }}
endIcon={{ icon: ExternalLink }}
target="_blank"
href="{base}/flows/get/{runnable.path}?workspace={$workspaceStore}"
>
Details
</Button>
{:else}
<Button
size="xs"
variant="border"
startIcon={{ icon: GitFork }}
on:click={() => {
fork(runnable.path)
}}
>
Fork
</Button>
{/if}
<Popover
floatingConfig={{
middleware: [
autoPlacement({
allowedPlacements: [
'bottom-start',
'bottom-end',
'top-start',
'top-end',
'top',
'bottom'
]
})
]
}}
closeButton
contentClasses="block text-primary text-xs p-4 w-[20vh]"
>
<svelte:fragment slot="trigger">
<Button
nonCaptureEvent={true}
btnClasses={'bg-surface text-primay hover:bg-hover'}
color="light"
variant="border"
size="xs">Cache</Button
>
</svelte:fragment>
<svelte:fragment slot="content">
Since this is a reference to a workspace {runnable.runType}, set the cache in the {runnable.runType}
settings directly by editing it. The cache will be shared by any app or flow that uses this
{runnable.runType}.
</svelte:fragment>
</Popover>
<input
on:keydown|stopPropagation
bind:value={runnable.name}
placeholder="Background runnable name"
class="!text-xs !rounded-xs"
/>
</div>
<div class="w-full grow overflow-y-auto">
{#key $stateId}
{#if notFound}
<div class="text-red-400"
>{runnable.runType} not found at {runnable.path} in workspace {$workspaceStore}</div
>
{:else if runnable.runType == 'script' || runnable.runType == 'hubscript'}
<div class="border">
<FlowModuleScript path={runnable.path} />
</div>
{:else if runnable.runType == 'flow'}
<FlowPathViewer path={runnable.path} />
{:else}
Unrecognized runType {runnable.runType}
{/if}
{/key}
</div>
</div>