Skip to content

Commit 2332ff7

Browse files
committed
fix(dashboard): unblock release packaging
1 parent f1a2963 commit 2332ff7

File tree

2 files changed

+34
-23
lines changed

2 files changed

+34
-23
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to Viaduct should be documented in this file.
44

55
This changelog tracks published releases and the major implementation milestones that shaped the current repository state.
66

7+
## [1.4.1] - 2026-04-08
8+
9+
### Release Reliability
10+
- fixed the dashboard dependency graph typing so `make release-gate` can complete the web build and package the release bundle
11+
- superseded the `v1.4.0` candidate tag before publishing a downloadable GitHub release
12+
713
## [1.4.0] - 2026-04-08
814

915
### Dashboard Product Workflow

web/src/components/DependencyGraph.tsx

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { getGraph } from "../api";
55
import { StatusBadge } from "./primitives/StatusBadge";
66
import type { DependencyGraph as DependencyGraphModel, GraphEdge, GraphNode } from "../types";
77

8+
type GraphSimulationNode = GraphNode & d3.SimulationNodeDatum;
9+
type GraphSimulationLink = GraphEdge & d3.SimulationLinkDatum<GraphSimulationNode>;
10+
811
interface GraphFilterState {
912
nodeTypes: Record<GraphNode["type"], boolean>;
1013
platform: string;
@@ -136,6 +139,8 @@ export function DependencyGraph() {
136139

137140
const root = svg.attr("viewBox", `0 0 ${width} ${height}`);
138141
const canvas = root.append("g");
142+
const simulationNodes: GraphSimulationNode[] = visibleGraph.nodes.map((node) => ({ ...node }));
143+
const simulationLinks: GraphSimulationLink[] = visibleGraph.edges.map((edge) => ({ ...edge }));
139144

140145
root.call(
141146
d3.zoom<SVGSVGElement, unknown>().scaleExtent([0.5, 2]).on("zoom", (event: d3.D3ZoomEvent<SVGSVGElement, unknown>) => {
@@ -144,80 +149,80 @@ export function DependencyGraph() {
144149
);
145150

146151
const simulation = d3
147-
.forceSimulation(visibleGraph.nodes as d3.SimulationNodeDatum[])
152+
.forceSimulation<GraphSimulationNode>(simulationNodes)
148153
.force(
149154
"link",
150155
d3
151-
.forceLink(visibleGraph.edges as d3.SimulationLinkDatum<d3.SimulationNodeDatum>[])
152-
.id((node: { id: string }) => node.id)
153-
.distance((edge: any) => (edge.type === "backup" ? 150 : 120)),
156+
.forceLink<GraphSimulationNode, GraphSimulationLink>(simulationLinks)
157+
.id((node) => node.id)
158+
.distance((edge) => (edge.type === "backup" ? 150 : 120)),
154159
)
155160
.force("charge", d3.forceManyBody().strength(-280))
156161
.force("center", d3.forceCenter(width / 2, height / 2));
157162

158163
const edges = canvas
159164
.append("g")
160165
.selectAll("line")
161-
.data(visibleGraph.edges)
166+
.data(simulationLinks)
162167
.join("line")
163-
.attr("stroke", (edge: GraphEdge) => edgeColor(edge))
168+
.attr("stroke", (edge: GraphSimulationLink) => edgeColor(edge))
164169
.attr("stroke-width", 1.75)
165170
.attr("stroke-opacity", 0.65);
166171

167172
const nodes = canvas
168173
.append("g")
169-
.selectAll<SVGCircleElement, GraphNode>("circle")
170-
.data(visibleGraph.nodes)
174+
.selectAll<SVGCircleElement, GraphSimulationNode>("circle")
175+
.data(simulationNodes)
171176
.join("circle")
172177
.attr("r", (node) => (node.id === selectedNodeId ? 18 : node.type === "vm" ? 14 : 12))
173-
.attr("fill", (node: GraphNode) => nodeColor(node))
178+
.attr("fill", (node: GraphSimulationNode) => nodeColor(node))
174179
.attr("stroke", (node) => (node.id === selectedNodeId ? "#0f172a" : "#ffffff"))
175180
.attr("stroke-width", (node) => (node.id === selectedNodeId ? 3 : 2))
176181
.style("cursor", "pointer")
177182
.call(
178183
d3
179-
.drag<SVGCircleElement, GraphNode>()
180-
.on("start", (event: d3.D3DragEvent<SVGCircleElement, GraphNode, GraphNode>, node: any) => {
184+
.drag<SVGCircleElement, GraphSimulationNode>()
185+
.on("start", (event: d3.D3DragEvent<SVGCircleElement, GraphSimulationNode, GraphSimulationNode>, node) => {
181186
if (!event.active) {
182187
simulation.alphaTarget(0.3).restart();
183188
}
184189
node.fx = node.x;
185190
node.fy = node.y;
186191
})
187-
.on("drag", (event: d3.D3DragEvent<SVGCircleElement, GraphNode, GraphNode>, node: any) => {
192+
.on("drag", (event: d3.D3DragEvent<SVGCircleElement, GraphSimulationNode, GraphSimulationNode>, node) => {
188193
node.fx = event.x;
189194
node.fy = event.y;
190195
})
191-
.on("end", (event: d3.D3DragEvent<SVGCircleElement, GraphNode, GraphNode>, node: any) => {
196+
.on("end", (event: d3.D3DragEvent<SVGCircleElement, GraphSimulationNode, GraphSimulationNode>, node) => {
192197
if (!event.active) {
193198
simulation.alphaTarget(0);
194199
}
195200
node.fx = null;
196201
node.fy = null;
197202
}),
198203
)
199-
.on("click", (_event: MouseEvent, node: GraphNode) => setSelectedNodeId(node.id));
204+
.on("click", (_event: MouseEvent, node: GraphSimulationNode) => setSelectedNodeId(node.id));
200205

201-
nodes.append("title").text((node: GraphNode) => node.label);
206+
nodes.append("title").text((node: GraphSimulationNode) => node.label);
202207

203208
const labels = canvas
204209
.append("g")
205210
.selectAll("text")
206-
.data(visibleGraph.nodes)
211+
.data(simulationNodes)
207212
.join("text")
208213
.attr("font-size", 12)
209214
.attr("fill", "#0f172a")
210-
.text((node: GraphNode) => node.label);
215+
.text((node: GraphSimulationNode) => node.label);
211216

212217
simulation.on("tick", () => {
213218
edges
214-
.attr("x1", (edge: any) => edge.source.x)
215-
.attr("y1", (edge: any) => edge.source.y)
216-
.attr("x2", (edge: any) => edge.target.x)
217-
.attr("y2", (edge: any) => edge.target.y);
219+
.attr("x1", (edge) => (typeof edge.source === "object" ? edge.source.x ?? 0 : 0))
220+
.attr("y1", (edge) => (typeof edge.source === "object" ? edge.source.y ?? 0 : 0))
221+
.attr("x2", (edge) => (typeof edge.target === "object" ? edge.target.x ?? 0 : 0))
222+
.attr("y2", (edge) => (typeof edge.target === "object" ? edge.target.y ?? 0 : 0));
218223

219-
nodes.attr("cx", (node: any) => node.x).attr("cy", (node: any) => node.y);
220-
labels.attr("x", (node: any) => node.x + 18).attr("y", (node: any) => node.y + 4);
224+
nodes.attr("cx", (node) => node.x ?? 0).attr("cy", (node) => node.y ?? 0);
225+
labels.attr("x", (node) => (node.x ?? 0) + 18).attr("y", (node) => (node.y ?? 0) + 4);
221226
});
222227

223228
return () => {

0 commit comments

Comments
 (0)