mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-12 00:20:15 +00:00
feat(error-groups): sort execution error cards by node execution ID (#9334)
## Summary Sort execution error cards within each error group by their node execution ID in ascending numeric order, ensuring consistent and predictable display order. ## Changes - **What**: Added `compareExecutionId` utility to `src/types/nodeIdentification.ts` that splits node IDs on `:` and compares segments numerically left-to-right; applied it as a sort comparator when building `ErrorGroup.cards` in `useErrorGroups.ts` ## Review Focus - The comparison treats missing segments as `0`, so `"1"` sorts before `"1:20"` (subgraph nodes follow their parent); confirm this ordering matches user expectations - All comparisons are purely numeric — non-numeric segment values would sort as `NaN` (treated as `0`) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9334-feat-error-groups-sort-execution-error-cards-by-node-execution-ID-3176d73d365081e1b3e4e4fa8831fe16) by [Unito](https://www.unito.io)
This commit is contained in:
@@ -323,6 +323,90 @@ describe('useErrorGroups', () => {
|
||||
)
|
||||
expect(promptGroup).toBeDefined()
|
||||
})
|
||||
|
||||
it('sorts cards within an execution group by nodeId numerically', async () => {
|
||||
const { store, groups } = createErrorGroups()
|
||||
store.lastNodeErrors = {
|
||||
'10': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
},
|
||||
'2': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
},
|
||||
'1': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
}
|
||||
}
|
||||
await nextTick()
|
||||
|
||||
const execGroup = groups.allErrorGroups.value.find(
|
||||
(g) => g.type === 'execution'
|
||||
)
|
||||
const nodeIds = execGroup?.cards.map((c) => c.nodeId)
|
||||
expect(nodeIds).toEqual(['1', '2', '10'])
|
||||
})
|
||||
|
||||
it('sorts cards with subpath nodeIds before higher root IDs', async () => {
|
||||
const { store, groups } = createErrorGroups()
|
||||
store.lastNodeErrors = {
|
||||
'2': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
},
|
||||
'1:20': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
},
|
||||
'1': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
}
|
||||
}
|
||||
await nextTick()
|
||||
|
||||
const execGroup = groups.allErrorGroups.value.find(
|
||||
(g) => g.type === 'execution'
|
||||
)
|
||||
const nodeIds = execGroup?.cards.map((c) => c.nodeId)
|
||||
expect(nodeIds).toEqual(['1', '1:20', '2'])
|
||||
})
|
||||
|
||||
it('sorts deeply nested nodeIds by each segment numerically', async () => {
|
||||
const { store, groups } = createErrorGroups()
|
||||
store.lastNodeErrors = {
|
||||
'10:11:99': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
},
|
||||
'10:11:12': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
},
|
||||
'10:2': {
|
||||
class_type: 'KSampler',
|
||||
dependent_outputs: [],
|
||||
errors: [{ type: 'err', message: 'Error', details: '' }]
|
||||
}
|
||||
}
|
||||
await nextTick()
|
||||
|
||||
const execGroup = groups.allErrorGroups.value.find(
|
||||
(g) => g.type === 'execution'
|
||||
)
|
||||
const nodeIds = execGroup?.cards.map((c) => c.nodeId)
|
||||
expect(nodeIds).toEqual(['10:2', '10:11:12', '10:11:99'])
|
||||
})
|
||||
})
|
||||
|
||||
describe('filteredGroups', () => {
|
||||
|
||||
@@ -23,7 +23,10 @@ import { st } from '@/i18n'
|
||||
import type { MissingNodeType } from '@/types/comfy'
|
||||
import type { ErrorCardData, ErrorGroup, ErrorItem } from './types'
|
||||
import type { NodeExecutionId } from '@/types/nodeIdentification'
|
||||
import { isNodeExecutionId } from '@/types/nodeIdentification'
|
||||
import {
|
||||
isNodeExecutionId,
|
||||
compareExecutionId
|
||||
} from '@/types/nodeIdentification'
|
||||
|
||||
const PROMPT_CARD_ID = '__prompt__'
|
||||
const SINGLE_GROUP_KEY = '__single__'
|
||||
@@ -151,12 +154,16 @@ function addCardErrorToGroup(
|
||||
group.get(card.id)?.errors.push(error)
|
||||
}
|
||||
|
||||
function compareNodeId(a: ErrorCardData, b: ErrorCardData): number {
|
||||
return compareExecutionId(a.nodeId, b.nodeId)
|
||||
}
|
||||
|
||||
function toSortedGroups(groupsMap: Map<string, GroupEntry>): ErrorGroup[] {
|
||||
return Array.from(groupsMap.entries())
|
||||
.map(([title, groupData]) => ({
|
||||
type: 'execution' as const,
|
||||
title,
|
||||
cards: Array.from(groupData.cards.values()),
|
||||
cards: Array.from(groupData.cards.values()).sort(compareNodeId),
|
||||
priority: groupData.priority
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
|
||||
Reference in New Issue
Block a user