mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
feat(frontend): Display error as an icon in order to avoid clutter wh… (#1143)
* feat(frontend): Display error as an icon in order to avoid clutter when an error occures * feat(frontend): Fix build * feat(frontend): Fix error icon position
This commit is contained in:
@@ -54,7 +54,6 @@
|
||||
|
||||
<RunnableWrapper
|
||||
defaultUserInput
|
||||
noMinH
|
||||
bind:runnableComponent
|
||||
bind:componentInput
|
||||
{id}
|
||||
|
||||
@@ -89,7 +89,6 @@
|
||||
>
|
||||
<RunnableWrapper
|
||||
defaultUserInput
|
||||
noMinH
|
||||
bind:runnableComponent
|
||||
bind:componentInput
|
||||
{id}
|
||||
|
||||
@@ -21,13 +21,20 @@
|
||||
export let autoRefresh: boolean = true
|
||||
export let result: any = undefined
|
||||
export let forceSchemaDisplay: boolean = false
|
||||
export let noMinH = false
|
||||
export let defaultUserInput = false
|
||||
export let flexWrap = false
|
||||
export let wrapperClass = ''
|
||||
|
||||
const { worldStore, runnableComponents, workspace, appPath, isEditor, jobs, noBackend } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
const {
|
||||
worldStore,
|
||||
runnableComponents,
|
||||
workspace,
|
||||
appPath,
|
||||
isEditor,
|
||||
jobs,
|
||||
noBackend,
|
||||
errorByComponent
|
||||
} = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
onMount(() => {
|
||||
if (autoRefresh) {
|
||||
@@ -245,7 +252,14 @@
|
||||
export async function runComponent() {
|
||||
await executeComponent()
|
||||
}
|
||||
|
||||
let lastStartedAt: number = Date.now()
|
||||
|
||||
function recordError(error: string) {
|
||||
$errorByComponent[id] = error
|
||||
}
|
||||
|
||||
$: result?.error && recordError(result.error)
|
||||
</script>
|
||||
|
||||
{#each Object.entries(fields ?? {}) as [key, v]}
|
||||
@@ -268,6 +282,11 @@
|
||||
lastStartedAt = startedAt
|
||||
outputs.result?.set(testJob?.result)
|
||||
result = testJob.result
|
||||
|
||||
if ($errorByComponent[id] && !result?.error) {
|
||||
delete $errorByComponent[id]
|
||||
$errorByComponent = $errorByComponent
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -299,17 +318,6 @@
|
||||
<Alert type="warning" size="xs" class="mt-2 px-1" title="Missing runnable">
|
||||
Please select a runnable
|
||||
</Alert>
|
||||
{:else if result?.error}
|
||||
<div class="p-2">
|
||||
<Alert type="error" title="Error during execution">
|
||||
See "Debug Runs" on the top right for more details
|
||||
<pre
|
||||
title={JSON.stringify(result.error, null, 4)}
|
||||
class=" mt-2 text-2xs whitespace-pre-wrap">{JSON.stringify(result.error, null, 4)}</pre
|
||||
>
|
||||
</Alert>
|
||||
<slot />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="block w-full h-full">
|
||||
<slot />
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
export let componentInput: AppInput | undefined
|
||||
export let id: string
|
||||
export let result: any = undefined
|
||||
export let noMinH = false
|
||||
|
||||
export let extraQueryParams: Record<string, any> = {}
|
||||
export let autoRefresh: boolean = true
|
||||
@@ -47,7 +46,6 @@
|
||||
{id}
|
||||
{extraQueryParams}
|
||||
{forceSchemaDisplay}
|
||||
{noMinH}
|
||||
wrapperClass={runnableClass}
|
||||
>
|
||||
<slot />
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
})
|
||||
|
||||
const runnableComponents = writable<Record<string, () => Promise<void>>>({})
|
||||
const errorByComponent = writable<Record<string, string>>({})
|
||||
|
||||
setContext<AppEditorContext>('AppEditorContext', {
|
||||
worldStore,
|
||||
@@ -72,7 +73,8 @@
|
||||
isEditor: true,
|
||||
jobs: writable([]),
|
||||
staticExporter: writable({}),
|
||||
noBackend: false
|
||||
noBackend: false,
|
||||
errorByComponent
|
||||
})
|
||||
|
||||
let timeout: NodeJS.Timeout | undefined = undefined
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
export let policy: Policy
|
||||
|
||||
const { app, summary, mode, breakpoint, appPath, jobs, staticExporter } =
|
||||
const { app, summary, mode, breakpoint, appPath, jobs, staticExporter, errorByComponent } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
const loading = {
|
||||
publish: false,
|
||||
@@ -183,6 +183,7 @@
|
||||
let testIsLoading = false
|
||||
|
||||
$: selectedJobId && testJobLoader?.watchJob(selectedJobId)
|
||||
$: hasErrors = Object.keys($errorByComponent).length > 0
|
||||
</script>
|
||||
|
||||
<TestJobLoader bind:this={testJobLoader} bind:isLoading={testIsLoading} bind:job />
|
||||
@@ -243,12 +244,14 @@
|
||||
{:else}
|
||||
<div class="flex flex-col h-full w-full gap-4 mb-4">
|
||||
{#if job?.['running']}
|
||||
<div class="flex flex-row-reverse w-full"
|
||||
><Button
|
||||
<div class="flex flex-row-reverse w-full">
|
||||
<Button
|
||||
color="red"
|
||||
variant="border"
|
||||
on:click={() => testJobLoader?.cancelJob()}>Cancel</Button
|
||||
on:click={() => testJobLoader?.cancelJob()}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="p-2">
|
||||
@@ -436,7 +439,7 @@
|
||||
<span class="hidden md:inline">
|
||||
<Button
|
||||
on:click={() => (jobsDrawerOpen = true)}
|
||||
color="light"
|
||||
color={hasErrors ? 'red' : 'light'}
|
||||
size="xs"
|
||||
variant="border"
|
||||
startIcon={{ icon: faBug }}
|
||||
|
||||
@@ -59,7 +59,8 @@
|
||||
isEditor,
|
||||
jobs: writable([]),
|
||||
staticExporter: writable({}),
|
||||
noBackend
|
||||
noBackend,
|
||||
errorByComponent: writable({})
|
||||
})
|
||||
|
||||
let mounted = false
|
||||
@@ -74,8 +75,10 @@
|
||||
</script>
|
||||
|
||||
<div class="relative">
|
||||
<div class="{$$props.class} {lockedClasses} h-full max-h-[calc(100%-41px)] overflow-auto
|
||||
w-full {app.fullscreen ? '' : 'max-w-6xl'} mx-auto">
|
||||
<div
|
||||
class="{$$props.class} {lockedClasses} h-full max-h-[calc(100%-41px)] overflow-auto
|
||||
w-full {app.fullscreen ? '' : 'max-w-6xl'} mx-auto"
|
||||
>
|
||||
{#if $appStore.grid}
|
||||
<div class={classNames('mx-auto pb-4', width)}>
|
||||
<GridEditor {policy} />
|
||||
@@ -86,10 +89,10 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
transition:fade|local={{ duration: 200, easing: cubicOut }}
|
||||
on:click={() => isLocked = false}
|
||||
on:click={() => (isLocked = false)}
|
||||
class="absolute inset-0 center-center bg-black/20 z-50 backdrop-blur-[1px] cursor-pointer"
|
||||
>
|
||||
<Button on:click={() => isLocked = false}>
|
||||
<Button on:click={() => (isLocked = false)}>
|
||||
Unlock preview
|
||||
<Unlock size={18} class="ml-1" strokeWidth={2.5} />
|
||||
</Button>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { classNames } from '$lib/utils'
|
||||
import type { AppComponent } from '../types'
|
||||
import { Anchor, Move } from 'lucide-svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import type { AppComponent, AppEditorContext } from '../types'
|
||||
import { Anchor, Bug, Move } from 'lucide-svelte'
|
||||
import { createEventDispatcher, getContext } from 'svelte'
|
||||
import Popover from '$lib/components/Popover.svelte'
|
||||
import { Alert, Button } from '$lib/components/common'
|
||||
|
||||
export let component: AppComponent
|
||||
export let selected: boolean
|
||||
@@ -11,6 +13,10 @@
|
||||
export let hover: boolean = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const { errorByComponent } = getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
$: error = $errorByComponent[component.id]
|
||||
</script>
|
||||
|
||||
<span
|
||||
@@ -56,3 +62,26 @@
|
||||
<Move size={14} />
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if error}
|
||||
<span
|
||||
title="Error"
|
||||
class={classNames(
|
||||
'text-red-500 px-1 text-2xs py-0.5 font-bold w-fit absolute border border-red-500 -bottom-1 shadow left-1/2 transform -translate-x-1/2 z-50 cursor-pointer',
|
||||
'bg-red-100/80'
|
||||
)}
|
||||
>
|
||||
<Popover notClickable placement="bottom" popupClass="!bg-white border w-96">
|
||||
<Bug size={14} />
|
||||
<span slot="text">
|
||||
<div class="bg-white">
|
||||
<Alert type="error" title="Error during execution">
|
||||
<div class="flex flex-col">
|
||||
<span> See "Debug Runs" on the top right for more details </span>
|
||||
</div>
|
||||
</Alert>
|
||||
</div>
|
||||
</span>
|
||||
</Popover>
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
@@ -172,6 +172,7 @@ export type AppEditorContext = {
|
||||
isEditor: boolean
|
||||
jobs: Writable<{ job: string; component: string }[]>
|
||||
noBackend: boolean
|
||||
errorByComponent: Writable<Record<string, string>>
|
||||
}
|
||||
|
||||
export type EditorMode = 'dnd' | 'preview'
|
||||
|
||||
Reference in New Issue
Block a user