feat(app): mesh bands — kind-columns, draggable, shared headers
Remote machines' deployments now sit in the same kind-columns as local (so a cross-node edge runs straight down its column), are draggable with persisted positions, and the lane headers lift above the topmost band so they head every machine's columns.
This commit is contained in:
@@ -93,7 +93,6 @@ const PROTO_COLOR: Record<string, string> = {
|
|||||||
system: "#6e7681",
|
system: "#6e7681",
|
||||||
}
|
}
|
||||||
const EXTERNAL_X = 1450 // external resources (references) — beyond Internet
|
const EXTERNAL_X = 1450 // external resources (references) — beyond Internet
|
||||||
const MESH_Y = -150 // band above the local lanes for other machines' deployments
|
|
||||||
|
|
||||||
const HANDLE = { opacity: 0, width: 8, height: 8 } as const
|
const HANDLE = { opacity: 0, width: 8, height: 8 } as const
|
||||||
|
|
||||||
@@ -491,33 +490,35 @@ export function SystemMapPage() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Other machines (mesh-discovered) — a read-only band above the local lanes,
|
// Other machines (mesh-discovered). Each is a band above the local lanes, with
|
||||||
// one row per node, its deployments laid out horizontally.
|
// its deployments in the SAME kind-columns as local, draggable, and the shared
|
||||||
|
// lane headers lifted above the topmost band so they head every machine.
|
||||||
const byMachine = new Map<string, MeshDeployment[]>()
|
const byMachine = new Map<string, MeshDeployment[]>()
|
||||||
for (const md of meshResp?.deployments ?? []) {
|
for (const md of meshResp?.deployments ?? []) {
|
||||||
const arr = byMachine.get(md.node) ?? []
|
const arr = byMachine.get(md.node) ?? []
|
||||||
arr.push(md)
|
arr.push(md)
|
||||||
byMachine.set(md.node, arr)
|
byMachine.set(md.node, arr)
|
||||||
}
|
}
|
||||||
let mrow = 0
|
let bandBaseline = TOP - 70 // first band sits just above local; bands stack upward
|
||||||
|
let headersY = TOP - 40 // rises above the bands when machines are present
|
||||||
for (const [machine, deps] of byMachine) {
|
for (const [machine, deps] of byMachine) {
|
||||||
const y = MESH_Y - mrow * (ROW_H + 8)
|
const perLaneM: Record<string, number> = {}
|
||||||
nodes.push({
|
const laid = deps
|
||||||
id: `__machine_${machine}__`,
|
.filter((md) => LANES[md.kind])
|
||||||
type: "lane",
|
.map((md) => {
|
||||||
position: { x: PROG_X, y: y - 4 },
|
const lane = LANES[md.kind]
|
||||||
selectable: false,
|
const row = (perLaneM[md.kind] = (perLaneM[md.kind] ?? 0) + 1) - 1
|
||||||
draggable: false,
|
return { md, x: lane.x, row }
|
||||||
deletable: false,
|
})
|
||||||
data: { label: `⬡ ${machine}` },
|
const rows = Math.max(1, ...Object.values(perLaneM))
|
||||||
})
|
const bandTop = bandBaseline - (rows - 1) * ROW_H
|
||||||
deps.forEach((md, i) => {
|
for (const { md, x, row } of laid) {
|
||||||
nodes.push({
|
nodes.push({
|
||||||
id: `__remote_${machine}_${md.name}__`,
|
id: `__remote_${machine}_${md.name}__`,
|
||||||
type: "remote",
|
type: "remote",
|
||||||
position: { x: i * 150, y },
|
position: { x, y: bandTop + row * ROW_H },
|
||||||
selectable: false,
|
selectable: true,
|
||||||
draggable: false,
|
draggable: true,
|
||||||
deletable: false,
|
deletable: false,
|
||||||
data: {
|
data: {
|
||||||
label: md.name,
|
label: md.name,
|
||||||
@@ -525,8 +526,18 @@ export function SystemMapPage() {
|
|||||||
sub: md.endpoints[0] ? `:${md.endpoints[0].port}` : undefined,
|
sub: md.endpoints[0] ? `:${md.endpoints[0].port}` : undefined,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
nodes.push({
|
||||||
|
id: `__machine_${machine}__`,
|
||||||
|
type: "lane",
|
||||||
|
position: { x: PROG_X, y: bandTop },
|
||||||
|
selectable: false,
|
||||||
|
draggable: false,
|
||||||
|
deletable: false,
|
||||||
|
data: { label: `⬡ ${machine}` },
|
||||||
})
|
})
|
||||||
mrow++
|
headersY = Math.min(headersY, bandTop - 44)
|
||||||
|
bandBaseline = bandTop - (ROW_H + 44) // gap before the next machine (upward)
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxRows = Math.max(1, ...Object.values(perLane))
|
const maxRows = Math.max(1, ...Object.values(perLane))
|
||||||
@@ -557,7 +568,7 @@ export function SystemMapPage() {
|
|||||||
nodes.push({
|
nodes.push({
|
||||||
id: `__lane_${title}__`,
|
id: `__lane_${title}__`,
|
||||||
type: "lane",
|
type: "lane",
|
||||||
position: { x, y: TOP - 40 },
|
position: { x, y: headersY },
|
||||||
data: { label: title },
|
data: { label: title },
|
||||||
selectable: false,
|
selectable: false,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
|
|||||||
Reference in New Issue
Block a user