feat(frontend): add Phase 3 UI components for observability
Components created: - ValidationWarningsAlert: Display validation warnings with collapsible list - StructuredErrorDisplay: Parse and display HTTP 502 errors as bullet points - AutoFixBadge: Show automatically applied fixes - ReasoningChainViewer: Collapsible panel for LLM thinking process - MetadataDebugPanel: Collapsible debug info (model, duration, token metrics) CSS changes: - Add .editorial-alert--warning and .editorial-alert--info variants Integration: - Update routines/suggest page to show warnings, auto-fixes, reasoning, and metadata - Update products/suggest page with same observability components - Replace plain error divs with StructuredErrorDisplay for better UX All components follow design system and pass svelte-check with 0 errors
This commit is contained in:
parent
3c3248c2ea
commit
5d3f876bec
8 changed files with 310 additions and 3 deletions
48
frontend/src/lib/components/StructuredErrorDisplay.svelte
Normal file
48
frontend/src/lib/components/StructuredErrorDisplay.svelte
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<script lang="ts">
|
||||
import { XCircle } from 'lucide-svelte';
|
||||
|
||||
interface Props {
|
||||
error: string;
|
||||
}
|
||||
|
||||
let { error }: Props = $props();
|
||||
|
||||
// Parse semicolon-separated errors from backend validation failures
|
||||
const errors = $derived(
|
||||
error.includes(';')
|
||||
? error
|
||||
.split(';')
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => e.length > 0)
|
||||
: [error]
|
||||
);
|
||||
|
||||
// Extract prefix if present (e.g., "Generated routine failed safety validation: ")
|
||||
const hasPrefix = $derived(errors.length === 1 && errors[0].includes(': '));
|
||||
const prefix = $derived(
|
||||
hasPrefix ? errors[0].substring(0, errors[0].indexOf(': ') + 1) : ''
|
||||
);
|
||||
const cleanedErrors = $derived(
|
||||
hasPrefix && prefix ? [errors[0].substring(prefix.length)] : errors
|
||||
);
|
||||
</script>
|
||||
|
||||
<div class="editorial-alert editorial-alert--error">
|
||||
<div class="flex items-start gap-2">
|
||||
<XCircle class="size-5 shrink-0 mt-0.5" />
|
||||
<div class="flex-1">
|
||||
{#if prefix}
|
||||
<p class="font-medium mb-2">{prefix.replace(':', '')}</p>
|
||||
{/if}
|
||||
{#if cleanedErrors.length === 1}
|
||||
<p>{cleanedErrors[0]}</p>
|
||||
{:else}
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
{#each cleanedErrors as err}
|
||||
<li>{err}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue