Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/components/nodes-table/NodeDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,12 @@ export default {
groups.Configuration = []
}

for (const key in groups) {
if (groups[key][0]?.commandClass === 99) {
groups[key].sort((a, b) => (a.propertyKey ?? 0) - (b.propertyKey ?? 0))
}
}

Comment on lines +573 to +578

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on the ordering, but this comparator has two issues worth fixing before merge:

  1. NaN on string propertyKey. propertyKey is string | number | null (see api/lib/utils.ts:151-152, ZwaveClient.ts:442). CCs like Color Switch (red/green/blue), Notification/Alarm and Indicator use string keys, so (a.propertyKey ?? 0) - (b.propertyKey ?? 0) evaluates to NaN and leaves those groups in an undefined order — potentially scrambling CCs that were previously fine.
  2. Sorting by propertyKey alone ignores property and endpoint. A group can contain multiple properties and endpoints. For Configuration, partial (bitmask) params carry a propertyKey while base params don't, so a partial param gets pulled away from its base param.

Suggested type-safe comparator (endpoint → property → propertyKey, with natural-numeric string ordering so "slot 2" < "slot 10"):

Suggested change
for (const key in groups) {
groups[key].sort((a, b) => (a.propertyKey ?? 0) - (b.propertyKey ?? 0))
}
// sort each group by endpoint → property → propertyKey so keyed
// CCs (e.g. User Code slots) display in a stable, natural order.
// Uses a type-safe comparator because propertyKey may be a string
// (Color Switch, Notification, …) — numeric subtraction would NaN.
const cmp = (a, b) => {
if (typeof a === 'number' && typeof b === 'number') {
return a - b
}
return String(a ?? '').localeCompare(String(b ?? ''), undefined, {
numeric: true,
})
}
for (const key in groups) {
groups[key].sort(
(x, y) =>
cmp(x.endpoint ?? 0, y.endpoint ?? 0) ||
cmp(x.property, y.property) ||
cmp(x.propertyKey, y.propertyKey),
)
}

Note this now reorders all CC groups (rather than relying on insertion order), but the comparator is total and stable so it's safe.

return groups
} else {
return {}
Expand Down