mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 06:20:11 +00:00
refactor: consolidate error logic and split errorGroups by scope
- Add allErrorExecutionIds computed to executionStore to centralize error ID collection from lastNodeErrors and lastExecutionError - Add hasInternalErrorForNode helper to executionStore to encapsulate prefix-based container error detection - Replace duplicated error ID collection and prefix checks in RightSidePanel and SectionWidgets with store computed/helper - Split errorGroups into allErrorGroups (unfiltered) and tabErrorGroups (selection-filtered) in useErrorGroups - Add filterBySelection param (default: false) to addNodeErrorToGroup, processNodeErrors, processExecutionError - Add groupedErrorMessages computed derived from allErrorGroups for deduped message list used by ErrorOverlay - Migrate ErrorOverlay business logic to useErrorGroups composable, removing inline groupedErrors computed and redundant totalErrorCount wrapper
This commit is contained in:
@@ -30,14 +30,14 @@
|
||||
<div class="px-4 pb-3">
|
||||
<ul class="m-0 flex list-none flex-col gap-1.5 p-0">
|
||||
<li
|
||||
v-for="(entry, idx) in groupedErrors"
|
||||
v-for="(message, idx) in groupedErrorMessages"
|
||||
:key="idx"
|
||||
class="flex items-baseline gap-2 text-sm leading-snug text-muted-foreground"
|
||||
>
|
||||
<span
|
||||
class="mt-1.5 size-1 shrink-0 rounded-full bg-muted-foreground"
|
||||
/>
|
||||
<span>{{ entry.message }}</span>
|
||||
<span>{{ message }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -57,51 +57,24 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import type { NodeError } from '@/schemas/apiSchema'
|
||||
import { useExecutionStore } from '@/stores/executionStore'
|
||||
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useErrorGroups } from '@/components/rightSidePanel/errors/useErrorGroups'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
interface ErrorEntry {
|
||||
message: string
|
||||
}
|
||||
|
||||
const { t } = useI18n()
|
||||
const executionStore = useExecutionStore()
|
||||
const rightSidePanelStore = useRightSidePanelStore()
|
||||
const canvasStore = useCanvasStore()
|
||||
|
||||
const groupedErrors = computed<ErrorEntry[]>(() => {
|
||||
const messages = new Set<string>()
|
||||
|
||||
if (executionStore.lastPromptError) {
|
||||
messages.add(executionStore.lastPromptError.message)
|
||||
}
|
||||
|
||||
if (executionStore.lastNodeErrors) {
|
||||
for (const nodeError of Object.values(
|
||||
executionStore.lastNodeErrors
|
||||
) as NodeError[]) {
|
||||
for (const err of nodeError.errors) {
|
||||
messages.add(err.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (executionStore.lastExecutionError) {
|
||||
const e = executionStore.lastExecutionError
|
||||
messages.add(`${e.exception_type}: ${e.exception_message}`)
|
||||
}
|
||||
|
||||
return Array.from(messages).map((message) => ({ message }))
|
||||
})
|
||||
|
||||
const totalErrorCount = computed(() => executionStore.totalErrorCount)
|
||||
const { totalErrorCount, isErrorOverlayOpen } = storeToRefs(executionStore)
|
||||
const { groupedErrorMessages } = useErrorGroups(ref(''), t)
|
||||
|
||||
const errorCountLabel = computed(() =>
|
||||
t(
|
||||
@@ -112,7 +85,7 @@ const errorCountLabel = computed(() =>
|
||||
)
|
||||
|
||||
const isVisible = computed(
|
||||
() => executionStore.isErrorOverlayOpen && totalErrorCount.value > 0
|
||||
() => isErrorOverlayOpen.value && totalErrorCount.value > 0
|
||||
)
|
||||
|
||||
function dismiss() {
|
||||
|
||||
@@ -41,7 +41,7 @@ const rightSidePanelStore = useRightSidePanelStore()
|
||||
const settingStore = useSettingStore()
|
||||
const { t } = useI18n()
|
||||
|
||||
const { hasAnyError } = storeToRefs(executionStore)
|
||||
const { hasAnyError, allErrorExecutionIds } = storeToRefs(executionStore)
|
||||
|
||||
const { findParentGroup } = useGraphHierarchy()
|
||||
|
||||
@@ -96,17 +96,6 @@ type RightSidePanelTabList = Array<{
|
||||
icon?: string
|
||||
}>
|
||||
|
||||
const allErrorIds = computed<string[]>(() => {
|
||||
const ids: string[] = []
|
||||
if (executionStore.lastNodeErrors) {
|
||||
ids.push(...Object.keys(executionStore.lastNodeErrors))
|
||||
}
|
||||
if (executionStore.lastExecutionError) {
|
||||
ids.push(String(executionStore.lastExecutionError.node_id))
|
||||
}
|
||||
return ids
|
||||
})
|
||||
|
||||
const hasDirectNodeError = computed(() =>
|
||||
selectedNodes.value.some((node) =>
|
||||
executionStore.activeGraphErrorNodeIds.has(String(node.id))
|
||||
@@ -114,11 +103,10 @@ const hasDirectNodeError = computed(() =>
|
||||
)
|
||||
|
||||
const hasContainerInternalError = computed(() => {
|
||||
if (allErrorIds.value.length === 0) return false
|
||||
if (allErrorExecutionIds.value.length === 0) return false
|
||||
return selectedNodes.value.some((node) => {
|
||||
if (!(node instanceof SubgraphNode || isGroupNode(node))) return false
|
||||
const prefix = `${node.id}:`
|
||||
return allErrorIds.value.some((execId) => execId.startsWith(prefix))
|
||||
return executionStore.hasInternalErrorForNode(node.id)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -223,13 +223,7 @@ export function useErrorGroups(
|
||||
|
||||
const errorNodeCache = computed(() => {
|
||||
const map = new Map<string, LGraphNode>()
|
||||
const allExecutionIds = [
|
||||
...Object.keys(executionStore.lastNodeErrors ?? {}),
|
||||
...(executionStore.lastExecutionError
|
||||
? [String(executionStore.lastExecutionError.node_id)]
|
||||
: [])
|
||||
]
|
||||
for (const execId of allExecutionIds) {
|
||||
for (const execId of executionStore.allErrorExecutionIds) {
|
||||
const node = getNodeByExecutionId(app.rootGraph, execId)
|
||||
if (node) map.set(execId, node)
|
||||
}
|
||||
@@ -255,9 +249,10 @@ export function useErrorGroups(
|
||||
nodeId: string,
|
||||
classType: string,
|
||||
idPrefix: string,
|
||||
errors: ErrorItem[]
|
||||
errors: ErrorItem[],
|
||||
filterBySelection = false
|
||||
) {
|
||||
if (!isErrorInSelection(nodeId)) return
|
||||
if (filterBySelection && !isErrorInSelection(nodeId)) return
|
||||
const groupKey = isSingleNodeSelected.value ? SINGLE_GROUP_KEY : classType
|
||||
const cards = getOrCreateGroup(groupsMap, groupKey, 1)
|
||||
if (!cards.has(nodeId)) {
|
||||
@@ -289,7 +284,10 @@ export function useErrorGroups(
|
||||
})
|
||||
}
|
||||
|
||||
function processNodeErrors(groupsMap: Map<string, GroupEntry>) {
|
||||
function processNodeErrors(
|
||||
groupsMap: Map<string, GroupEntry>,
|
||||
filterBySelection = false
|
||||
) {
|
||||
if (!executionStore.lastNodeErrors) return
|
||||
|
||||
for (const [nodeId, nodeError] of Object.entries(
|
||||
@@ -303,31 +301,52 @@ export function useErrorGroups(
|
||||
nodeError.errors.map((e) => ({
|
||||
message: e.message,
|
||||
details: e.details ?? undefined
|
||||
}))
|
||||
})),
|
||||
filterBySelection
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function processExecutionError(groupsMap: Map<string, GroupEntry>) {
|
||||
function processExecutionError(
|
||||
groupsMap: Map<string, GroupEntry>,
|
||||
filterBySelection = false
|
||||
) {
|
||||
if (!executionStore.lastExecutionError) return
|
||||
|
||||
const e = executionStore.lastExecutionError
|
||||
addNodeErrorToGroup(groupsMap, String(e.node_id), e.node_type, 'exec', [
|
||||
{
|
||||
message: `${e.exception_type}: ${e.exception_message}`,
|
||||
details: e.traceback.join('\n'),
|
||||
isRuntimeError: true
|
||||
}
|
||||
])
|
||||
addNodeErrorToGroup(
|
||||
groupsMap,
|
||||
String(e.node_id),
|
||||
e.node_type,
|
||||
'exec',
|
||||
[
|
||||
{
|
||||
message: `${e.exception_type}: ${e.exception_message}`,
|
||||
details: e.traceback.join('\n'),
|
||||
isRuntimeError: true
|
||||
}
|
||||
],
|
||||
filterBySelection
|
||||
)
|
||||
}
|
||||
|
||||
const errorGroups = computed<ErrorGroup[]>(() => {
|
||||
const allErrorGroups = computed<ErrorGroup[]>(() => {
|
||||
const groupsMap = new Map<string, GroupEntry>()
|
||||
|
||||
processPromptError(groupsMap)
|
||||
processNodeErrors(groupsMap)
|
||||
processExecutionError(groupsMap)
|
||||
|
||||
return toSortedGroups(groupsMap)
|
||||
})
|
||||
|
||||
const tabErrorGroups = computed<ErrorGroup[]>(() => {
|
||||
const groupsMap = new Map<string, GroupEntry>()
|
||||
|
||||
processPromptError(groupsMap)
|
||||
processNodeErrors(groupsMap, true)
|
||||
processExecutionError(groupsMap, true)
|
||||
|
||||
return isSingleNodeSelected.value
|
||||
? toSortedGroups(regroupByErrorMessage(groupsMap))
|
||||
: toSortedGroups(groupsMap)
|
||||
@@ -335,7 +354,19 @@ export function useErrorGroups(
|
||||
|
||||
const filteredGroups = computed<ErrorGroup[]>(() => {
|
||||
const query = searchQuery.value.trim()
|
||||
return searchErrorGroups(errorGroups.value, query)
|
||||
return searchErrorGroups(tabErrorGroups.value, query)
|
||||
})
|
||||
|
||||
const groupedErrorMessages = computed<string[]>(() => {
|
||||
const messages = new Set<string>()
|
||||
for (const group of allErrorGroups.value) {
|
||||
for (const card of group.cards) {
|
||||
for (const err of card.errors) {
|
||||
messages.add(err.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(messages)
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -363,10 +394,12 @@ export function useErrorGroups(
|
||||
})
|
||||
|
||||
return {
|
||||
errorGroups,
|
||||
allErrorGroups,
|
||||
tabErrorGroups,
|
||||
filteredGroups,
|
||||
collapseState,
|
||||
isSingleNodeSelected,
|
||||
errorNodeCache
|
||||
errorNodeCache,
|
||||
groupedErrorMessages
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,16 +119,7 @@ const hasContainerInternalError = computed(() => {
|
||||
targetNode.value instanceof SubgraphNode || isGroupNode(targetNode.value)
|
||||
if (!isContainer) return false
|
||||
|
||||
const errorIds: string[] = []
|
||||
if (executionStore.lastNodeErrors) {
|
||||
errorIds.push(...Object.keys(executionStore.lastNodeErrors))
|
||||
}
|
||||
if (executionStore.lastExecutionError) {
|
||||
errorIds.push(String(executionStore.lastExecutionError.node_id))
|
||||
}
|
||||
|
||||
const prefix = `${targetNode.value.id}:`
|
||||
return errorIds.some((execId) => execId.startsWith(prefix))
|
||||
return executionStore.hasInternalErrorForNode(targetNode.value.id)
|
||||
})
|
||||
|
||||
const nodeHasError = computed(() => {
|
||||
|
||||
@@ -740,6 +740,17 @@ export const useExecutionStore = defineStore('execution', () => {
|
||||
() => hasExecutionError.value || hasPromptError.value || hasNodeError.value
|
||||
)
|
||||
|
||||
const allErrorExecutionIds = computed<string[]>(() => {
|
||||
const ids: string[] = []
|
||||
if (lastNodeErrors.value) {
|
||||
ids.push(...Object.keys(lastNodeErrors.value))
|
||||
}
|
||||
if (lastExecutionError.value) {
|
||||
ids.push(String(lastExecutionError.value.node_id))
|
||||
}
|
||||
return ids
|
||||
})
|
||||
|
||||
/** Total count of all individual errors */
|
||||
const totalErrorCount = computed(() => {
|
||||
let count = 0
|
||||
@@ -785,6 +796,12 @@ export const useExecutionStore = defineStore('execution', () => {
|
||||
return ids
|
||||
})
|
||||
|
||||
|
||||
function hasInternalErrorForNode(nodeId: string | number): boolean {
|
||||
const prefix = `${nodeId}:`
|
||||
return allErrorExecutionIds.value.some((id) => id.startsWith(prefix))
|
||||
}
|
||||
|
||||
const isErrorOverlayOpen = ref(false)
|
||||
|
||||
function showErrorOverlay() {
|
||||
@@ -804,6 +821,7 @@ export const useExecutionStore = defineStore('execution', () => {
|
||||
lastExecutionError,
|
||||
lastPromptError,
|
||||
hasAnyError,
|
||||
allErrorExecutionIds,
|
||||
totalErrorCount,
|
||||
lastExecutionErrorNodeId,
|
||||
executingNodeId,
|
||||
@@ -837,6 +855,7 @@ export const useExecutionStore = defineStore('execution', () => {
|
||||
// Node error lookup helpers
|
||||
getNodeErrors,
|
||||
slotHasError,
|
||||
hasInternalErrorForNode,
|
||||
activeGraphErrorNodeIds,
|
||||
isErrorOverlayOpen,
|
||||
showErrorOverlay,
|
||||
|
||||
Reference in New Issue
Block a user