feat: node-specific error tab with selection-aware grouping and error overlay (#8956)

## Summary
Enhances the error panel with node-specific views: single-node selection
shows errors grouped by message in compact mode, container nodes
(subgraph/group) expose child errors via a badge and "See Error" button,
and a floating ErrorOverlay appears after execution failure with a
deduplicated summary and quick navigation to the errors tab.

## Changes
- **Consolidate error tab**: Remove `TabError.vue`; merge all error
display into `TabErrors.vue` and drop the separate `error` tab type from
`rightSidePanelStore`
- **Selection-aware grouping**: Single-node selection regroups errors by
message (not `class_type`) and renders `ErrorNodeCard` in compact mode
- **Container node support**: Detect child-node errors in subgraph/group
nodes via execution ID prefix matching; show error badge and "See Error"
button in `SectionWidgets`
- **ErrorOverlay**: New floating card shown after execution failure with
deduplicated error messages, "Dismiss" and "See Errors" actions;
`isErrorOverlayOpen` / `showErrorOverlay` / `dismissErrorOverlay` added
to `executionStore`
- **Refactor**: Centralize error ID collection in `executionStore`
(`allErrorExecutionIds`, `hasInternalErrorForNode`); split `errorGroups`
into `allErrorGroups` (unfiltered) and `tabErrorGroups`
(selection-filtered); move `ErrorOverlay` business logic into
`useErrorGroups`

## Review Focus
- `useErrorGroups.ts`: split into `allErrorGroups` / `tabErrorGroups`
and the new `filterBySelection` parameter flow
- `executionStore.ts`: `hasInternalErrorForNode` helper and
`allErrorExecutionIds` computed
- `ErrorOverlay.vue`: integration with `executionStore` overlay state
and `useErrorGroups`

## Screenshots
<img width="853" height="461" alt="image"
src="https://github.com/user-attachments/assets/a49ab620-4209-4ae7-b547-fba13da0c633"
/>
<img width="854" height="203" alt="image"
src="https://github.com/user-attachments/assets/c119da54-cd78-4e7a-8b7a-456cfd348f1d"
/>
<img width="497" height="361" alt="image"
src="https://github.com/user-attachments/assets/74b16161-cf45-454b-ae60-24922fe36931"
/>

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
jaeone94
2026-02-21 05:14:52 +09:00
committed by GitHub
parent c2452c5d20
commit 46c40c755e
25 changed files with 997 additions and 240 deletions

View File

@@ -1,10 +1,13 @@
<template>
<div class="overflow-hidden">
<!-- Card Header (Node ID & Actions) -->
<div v-if="card.nodeId" class="flex flex-wrap items-center gap-2 py-2">
<!-- Card Header -->
<div
v-if="card.nodeId && !compact"
class="flex flex-wrap items-center gap-2 py-2"
>
<span
v-if="showNodeIdBadge"
class="shrink-0 rounded-md bg-secondary-background-selected px-2 py-0.5 text-[10px] font-mono text-muted-foreground font-bold"
class="shrink-0 rounded-md bg-secondary-background-selected px-2 py-0.5 text-xs font-mono text-muted-foreground font-bold"
>
#{{ card.nodeId }}
</span>
@@ -19,7 +22,7 @@
variant="secondary"
size="sm"
class="rounded-lg text-sm shrink-0"
@click.stop="emit('enterSubgraph', card.nodeId ?? '')"
@click.stop="handleEnterSubgraph"
>
{{ t('rightSidePanel.enterSubgraph') }}
</Button>
@@ -27,7 +30,8 @@
variant="textonly"
size="icon-sm"
class="size-7 text-muted-foreground hover:text-base-foreground shrink-0"
@click.stop="emit('locateNode', card.nodeId ?? '')"
:aria-label="t('rightSidePanel.locateNode')"
@click.stop="handleLocateNode"
>
<i class="icon-[lucide--locate] size-3.5" />
</Button>
@@ -43,8 +47,8 @@
>
<!-- Error Message -->
<p
v-if="error.message"
class="m-0 text-sm break-words whitespace-pre-wrap leading-relaxed px-0.5"
v-if="error.message && !compact"
class="m-0 text-sm break-words whitespace-pre-wrap leading-relaxed px-0.5 max-h-[4lh] overflow-y-auto"
>
{{ error.message }}
</p>
@@ -69,7 +73,7 @@
<Button
variant="secondary"
size="sm"
class="w-full justify-center gap-2 h-8 text-[11px]"
class="w-full justify-center gap-2 h-8 text-xs"
@click="handleCopyError(error)"
>
<i class="icon-[lucide--copy] size-3.5" />
@@ -88,9 +92,15 @@ import { cn } from '@/utils/tailwindUtil'
import type { ErrorCardData, ErrorItem } from './types'
const { card, showNodeIdBadge = false } = defineProps<{
const {
card,
showNodeIdBadge = false,
compact = false
} = defineProps<{
card: ErrorCardData
showNodeIdBadge?: boolean
/** Hide card header and error message (used in single-node selection mode) */
compact?: boolean
}>()
const emit = defineEmits<{
@@ -101,6 +111,18 @@ const emit = defineEmits<{
const { t } = useI18n()
function handleLocateNode() {
if (card.nodeId) {
emit('locateNode', card.nodeId)
}
}
function handleEnterSubgraph() {
if (card.nodeId) {
emit('enterSubgraph', card.nodeId)
}
}
function handleCopyError(error: ErrorItem) {
emit(
'copyToClipboard',