Skip to content

Commit 4831366

Browse files
aksOpsclaude
andcommitted
fix(ui): satisfy SonarCloud on the dagre map
- S2871 (reliability bug): give the shape-hash edge-key sort an explicit localeCompare comparator (a bare .sort() is an unreliable UTF-16 sort). - S7755: use Array.prototype.at(-1)/at(-2) instead of [length - n]. - S3735: drop the `void` operator on the fitView calls (block-body arrows). No behaviour change. tsc 0, eslint 0, 9 map tests, build + budgets green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LDQVJrixs2nJoea67a8pEG
1 parent d3ff48f commit 4831366

1 file changed

Lines changed: 5 additions & 5 deletions

File tree

ui/src/components/map/FlowMap.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ function routedPath(pts: { x: number; y: number }[], radius = 7): string {
168168
const u2 = unit(p2.x - p1.x, p2.y - p1.y)
169169
d += ` L${p1.x - u1.x * r},${p1.y - u1.y * r} Q${p1.x},${p1.y} ${p1.x + u2.x * r},${p1.y + u2.y * r}`
170170
}
171-
const last = pts[pts.length - 1]
171+
const last = pts.at(-1)!
172172
d += ` L${last.x},${last.y}`
173173
return d
174174
}
@@ -213,7 +213,7 @@ function RoutedEdge({ source, target, data, style }: EdgeProps) {
213213
// the chip edge (not its centre) and still follow a dragged node.
214214
if (!compact && pts.length >= 2) {
215215
const a = borderToward(s, pts[1] ?? nodeCenter(t))
216-
const b = borderToward(t, pts[pts.length - 2] ?? nodeCenter(s))
216+
const b = borderToward(t, pts.at(-2) ?? nodeCenter(s))
217217
return <BaseEdge path={routedPath([a, ...pts.slice(1, -1), b])} style={style} />
218218
}
219219
// LOD dot zoom, or the fallback layout with no waypoints: plain centre line.
@@ -251,7 +251,7 @@ function FlowMapInner({
251251
Pick<FlowMapProps, 'nodes' | 'edges' | 'selectedId' | 'impact' | 'dim' | 'onSelect' | 'onClearSelection' | 'ref'>
252252
>) {
253253
const { fitView } = useReactFlow()
254-
useImperativeHandle(ref, () => ({ fit: () => void fitView(FIT_OPTIONS) }), [fitView])
254+
useImperativeHandle(ref, () => ({ fit: () => { fitView(FIT_OPTIONS) } }), [fitView])
255255

256256
const edgeRefs: GraphEdgeRef[] = useMemo(
257257
() => edges.map((e) => ({ source: e.source, target: e.target })),
@@ -262,7 +262,7 @@ function FlowMapInner({
262262
// dagre). Carries both node positions and edge routing waypoints.
263263
const shapeKey = useMemo(() => {
264264
const ids = nodes.map((n) => n.id).sort(compareIds)
265-
const es = edgeRefs.map((e) => `${e.source}->${e.target}`).sort()
265+
const es = edgeRefs.map((e) => `${e.source}->${e.target}`).sort((a, b) => a.localeCompare(b))
266266
return JSON.stringify({ ids, es })
267267
}, [nodes, edgeRefs])
268268
// dagre layout, computed synchronously. It's deterministic and instant at
@@ -327,7 +327,7 @@ function FlowMapInner({
327327
// polls (layout ref unchanged), so it doesn't fight the user's zoom. rAF lets
328328
// the nodes settle into the new positions before fitting.
329329
useEffect(() => {
330-
const raf = requestAnimationFrame(() => void fitView(FIT_OPTIONS))
330+
const raf = requestAnimationFrame(() => { fitView(FIT_OPTIONS) })
331331
return () => cancelAnimationFrame(raf)
332332
}, [layout, fitView])
333333

0 commit comments

Comments
 (0)