mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 08:02:18 +00:00
100 lines
2.5 KiB
Svelte
100 lines
2.5 KiB
Svelte
<script lang="ts">
|
|
import { setContext } from 'svelte'
|
|
import { writable } from 'svelte/store'
|
|
import {
|
|
type ProgressStep,
|
|
type ProgressState,
|
|
type LoopState,
|
|
isLoopStep,
|
|
isLoopState,
|
|
getTween,
|
|
type ProgressStateStoreValue
|
|
} from './model'
|
|
import ProgressBarGeneralPart from './ProgressBarGeneralPart.svelte'
|
|
import ProgressBarLoopPart from './ProgressBarLoopPart.svelte'
|
|
|
|
export let steps: ProgressStep[]
|
|
export let error = false
|
|
export let duration = 100
|
|
let percent = getTween(0, duration)
|
|
let finished = false
|
|
let state: ProgressState[] = []
|
|
|
|
const stateStore = writable<ProgressStateStoreValue>({
|
|
length: state.length,
|
|
index: 0,
|
|
finished,
|
|
error
|
|
})
|
|
setContext('state', stateStore)
|
|
|
|
$: state = steps.map((step, i) => {
|
|
if (isLoopStep(step)) {
|
|
return {
|
|
type: step.type,
|
|
isDone: error ? false : step.isDone,
|
|
isDoneChanged: !state[i]?.isDone && step.isDone,
|
|
length: step.length,
|
|
index: step.index,
|
|
indexChanged: (state[i] as LoopState)?.index !== step.index
|
|
}
|
|
} else {
|
|
return {
|
|
type: step.type,
|
|
isDone: step.isDone,
|
|
isDoneChanged: !state[i]?.isDone && step.isDone
|
|
}
|
|
}
|
|
})
|
|
$: stateStore.update(({ index }) => ({ length: state.length, index, finished, error }))
|
|
$: stepIndex = state.findIndex(({ isDone }) => !isDone)
|
|
$: lastStep = state.at(-1)
|
|
$: if (typeof lastStep?.isDone === 'boolean') {
|
|
finished = lastStep.isDone
|
|
if ($percent >= 100 && !lastStep.isDone) {
|
|
percent = getTween(0, duration)
|
|
}
|
|
}
|
|
$: subStepIndex = lastStep ? lastStep['index'] : undefined
|
|
$: length = 100 / (state.length || 1)
|
|
$: if (finished) {
|
|
percent.set(100)
|
|
} else {
|
|
const product = length * stepIndex
|
|
percent.set(product < 0 ? 0 : product)
|
|
}
|
|
</script>
|
|
|
|
<div class={$$props.class}>
|
|
<div
|
|
class="flex justify-between items-end font-medium mb-1 {error
|
|
? 'text-red-700'
|
|
: 'text-blue-700'}"
|
|
>
|
|
<span class="text-base">
|
|
{error
|
|
? 'Error occured'
|
|
: finished
|
|
? 'Done'
|
|
: `Step ${stepIndex + 1}${subStepIndex !== undefined ? `.${subStepIndex + 1}` : ''}`}
|
|
</span>
|
|
<span class="text-sm">
|
|
{state.length ? $percent.toFixed(0) : 0}%
|
|
</span>
|
|
</div>
|
|
<div class="flex w-full bg-gray-200 rounded-full h-4 overflow-hidden">
|
|
{#each state as step, index}
|
|
<div
|
|
class="h-full relative border-white {index === 0 ? '' : 'border-l'}"
|
|
style="width: {length}%;"
|
|
>
|
|
{#if isLoopState(step)}
|
|
<ProgressBarLoopPart {step} {index} {duration} />
|
|
{:else}
|
|
<ProgressBarGeneralPart {step} {index} {duration} />
|
|
{/if}
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
</div>
|