Files
windmill/frontend/src/lib/components/flows/map/FlowGraphPreviewButton.svelte
T

128 lines
3.3 KiB
Svelte

<script lang="ts">
import { Button } from '$lib/components/common'
import { fade } from 'svelte/transition'
import { Loader2, Play, X } from 'lucide-svelte'
import { twMerge } from 'tailwind-merge'
import Popover from '$lib/components/Popover.svelte'
import type { Job } from '$lib/gen'
import { NODE } from '$lib/components/graph'
interface Props {
isRunning?: boolean
hover?: boolean
selected?: boolean
individualStepTests?: boolean
showJobStatus?: boolean
job?: Job
flowHasChanged?: boolean
onTestFlow?: () => void
onCancelTestFlow?: () => void
onOpenPreview?: () => void
onHideJobStatus?: () => void
}
let {
isRunning,
hover,
selected,
individualStepTests,
job,
showJobStatus,
flowHasChanged,
onTestFlow,
onCancelTestFlow,
onOpenPreview,
onHideJobStatus
}: Props = $props()
const flowPreviewJob = $derived(showJobStatus ? job : undefined)
const wide = $derived(hover || selected || flowPreviewJob || individualStepTests)
</script>
{#if !isRunning}
<Button
size="sm"
variant="accent-secondary"
btnClasses={twMerge(
'relative p-1.5 transition-all duration-200 drop-shadow-base',
wide ? 'w-[120px]' : 'w-[44.5px]',
'max-[1760px]:mt-[1.5px]' // Magic number comes from app.css (when :root fontSize becomes bigger)
)}
style="height: {NODE.height}px;"
on:click={() => {
onTestFlow?.()
}}
>
{#if isRunning}
<Loader2 size={16} class="animate-spin" />
{:else}
<Play size={16} />
{/if}
{#if wide}
<span transition:fade={{ duration: 100 }} class="text-xs">Test flow</span>
{/if}
</Button>
{#if wide && flowPreviewJob}
<div
class="flex flex-row items-center shadow-sm rounded-md mt-1"
in:fade={{ duration: 100, delay: 200 }}
style={`width: ${wide ? '120px' : '44.5px'}`}
>
<Popover class="grow min-w-0">
<button
class={twMerge(
'text-xs rounded-md rounded-r-none px-1.5 h-[24px] w-full bg-surface flex flex-row items-center gap-2 justify-center transition-all duration-200 ',
'hover:bg-surface-hover text-gray-400 hover:text-primary'
)}
onclick={onOpenPreview}
>
{#if flowPreviewJob && !flowHasChanged}
<div
class={twMerge(
'rounded-full h-2 w-2',
'success' in flowPreviewJob && flowPreviewJob.success
? 'bg-green-400'
: 'bg-red-400'
)}
title={'success' in flowPreviewJob && flowPreviewJob.success ? 'Success' : 'Failed'}
>
</div>
{/if}
<span class={twMerge('text-xs truncate', flowHasChanged && 'text-orange-600')} dir="rtl">
{!individualStepTests && !flowHasChanged && flowPreviewJob
? flowPreviewJob.id.slice(-5)
: '~'}
</span>
</button>
{#snippet text()}
{#if !individualStepTests && !flowHasChanged}
See run details
{:else}
Open preview
{/if}
{/snippet}
</Popover>
<button
class="h-[24px] px-1.5 bg-surface rounded-md rounded-l-none text-gray-400 hover:bg-red-500 hover:text-white"
title="Hide jobs status"
onclick={onHideJobStatus}
>
<X size={14} />
</button>
</div>
{/if}
{:else}
<Button
size="xs"
color="red"
variant="contained"
btnClasses="h-[34px] w-[120px] p-1.5"
on:click={async () => {
onCancelTestFlow?.()
}}
>
<Loader2 size={16} class="animate-spin" />
<span transition:fade={{ duration: 100 }} class="text-xs">Cancel</span>
</Button>
{/if}