Files
windmill/frontend/src/lib/components/FlowLogRow.svelte
Guilhem 8569675612 fix(frontend): add timeline to the flow log viewer (#6577)
* Fix flow time display

* Make compute timeline a separate component

* Add timeline to log viewer

* Add timeline for subflows

* remove debug log

* fix progresion display while running

* Handle loop iteration

* nit

* Display all iteration for loops

* Show total execution time for loop steps

* Show subflow timeline

* Do not hightlight selected iteration

* Add subflow duration and starting time

* Allow zoom on subflow timeline

* Show execution time

* Improve timeline layout

* nit

* hover effect

* add show timeline toggle

* reset log viewer state when job id changes

* Display history loader in flow preview

* handle branch one

* reset timeline on jobId change

* nit

* fix branch chosen default

* improve time display

* improve look v1

* improve look v2

* Allow loading of more iterations when limit is reached

* fix display

* Add tooltip

* Use popover to display durations

* allow select iteration from timeline

* remove debug log

* fix iteration to index for long loops

* select iteration based on id

* Use localModuleState to get current display job ids

* clean subflow job creation

* improve subflow fetching

* fix load more position

* improve parallele display

* clean

* Add color status

* remove unwanted change

* prevent toggle expand on click timeline

* fix expand running module

* make timeline optional

* prevent running flow be marked as error

* Fix width jump during execution

* fix typo

* nit

* Use a class for timeline computation

* nit
2025-09-15 17:24:12 +00:00

93 lines
2.0 KiB
Svelte

<script lang="ts">
import { twMerge } from 'tailwind-merge'
import { ChevronDown, ChevronRight } from 'lucide-svelte'
interface Props {
id: string
isCollapsible: boolean
isRunning?: boolean
isCurrent: (id: string) => boolean
isExpanded: (id: string, isRunning?: boolean) => boolean
toggleExpanded: (id: string) => void
children: import('svelte').Snippet
label: import('svelte').Snippet
class?: string
select: (id: string) => void
}
let {
id,
isCollapsible,
isRunning,
isCurrent,
isExpanded,
toggleExpanded,
children,
label,
class: className = '',
select
}: Props = $props()
function handleClick() {
if (isCollapsible) {
toggleExpanded(id)
}
select(id)
}
</script>
<li
class={twMerge(
'border-b flex flex-col',
isCurrent(id) ? 'border-l-2 !border-l-gray-400 -ml-[2px]' : ''
)}
>
<button
class={twMerge(
'py-1 leading-tight w-full flex items-center justify-left text-xs text-tertiary hover:text-primary hover:bg-surface-hover ',
isCurrent(id) ? 'bg-surface-hover text-primary' : '',
className
)}
tabindex="-1"
onclick={handleClick}
data-nav-id={id}
>
<div class="px-1">
{#if isCollapsible}
{#if isExpanded(id, isRunning) || id === 'root-flow'}
<ChevronDown size={8} strokeWidth={isCurrent(id) ? 4 : 2} />
{:else}
<ChevronRight size={8} strokeWidth={isCurrent(id) ? 4 : 2} />
{/if}
{:else}
<!-- Empty subflow - no collapse button, just spacing -->
<div class="w-2"></div>
{/if}
</div>
<div class="w-full leading-tight">
<div class={twMerge('w-full pr-2 cursor-pointer', isCurrent(id) ? 'bg-surface-hover' : '')}>
{@render label()}
</div>
</div>
</button>
{#if isExpanded(id, isRunning) || !isCollapsible}
<div class="my-1 transition-all duration-200 ease-in-out">
<div class="pl-4">
{@render children()}
</div>
</div>
{/if}
</li>
<style>
.transition-all {
transition: all 0.2s ease-in-out;
}
[data-nav-id]:focus-visible {
outline: none;
outline-offset: 0;
}
</style>