feat: arrowhead endpoints for edges + fix parallel edges not rendering
Add optional filled-triangle arrowheads at either end of an edge, independently toggleable per edge (EdgeModal) and as per-edge-type defaults (CustomStyleModal). Arrowheads are custom inline <marker> defs filled with the live stroke colour so they recolour reactively with custom_color / vlan / selected state. Persisted frontend (serializer) and backend (edge columns + schemas + runtime migration). Also fix two dedupe layers that silently dropped legitimate parallel links between the same two devices: - store: React Flow addEdge() connectionExists dropped a second edge with matching source+target when handles were null/equal. Build the edge with a unique id and append directly. - render: rewireEdgesForCollapse deduped ALL edges by src->tgt key even when nothing was collapsed, filtering real parallel edges out of the visible set. Restrict the anti-mesh dedupe to rewired collapse stubs. Tests: marker render, per-edge/per-type UI, store apply, serializer round-trip, backend edge/canvas persistence, parallel-edge regressions. ha-relevant: yes
This commit is contained in:
@@ -91,6 +91,31 @@ async def test_update_edge_custom_color_and_path_style(client: AsyncClient, head
|
||||
assert res.json()["path_style"] == "smooth"
|
||||
|
||||
|
||||
async def test_create_edge_with_arrow_markers(client: AsyncClient, headers: dict, two_nodes):
|
||||
src, tgt = two_nodes
|
||||
res = await client.post("/api/v1/edges", json={"source": src, "target": tgt, "type": "ethernet", "marker_start": True, "marker_end": True}, headers=headers)
|
||||
assert res.status_code == 201
|
||||
assert res.json()["marker_start"] is True
|
||||
assert res.json()["marker_end"] is True
|
||||
|
||||
|
||||
async def test_create_edge_defaults_arrow_markers_off(client: AsyncClient, headers: dict, two_nodes):
|
||||
src, tgt = two_nodes
|
||||
res = await client.post("/api/v1/edges", json={"source": src, "target": tgt, "type": "ethernet"}, headers=headers)
|
||||
assert res.status_code == 201
|
||||
assert res.json()["marker_start"] is False
|
||||
assert res.json()["marker_end"] is False
|
||||
|
||||
|
||||
async def test_update_edge_arrow_markers(client: AsyncClient, headers: dict, two_nodes):
|
||||
src, tgt = two_nodes
|
||||
edge_id = (await client.post("/api/v1/edges", json={"source": src, "target": tgt, "type": "ethernet"}, headers=headers)).json()["id"]
|
||||
res = await client.patch(f"/api/v1/edges/{edge_id}", json={"marker_end": True}, headers=headers)
|
||||
assert res.status_code == 200
|
||||
assert res.json()["marker_end"] is True
|
||||
assert res.json()["marker_start"] is False
|
||||
|
||||
|
||||
async def test_create_edge_requires_auth(client: AsyncClient, two_nodes):
|
||||
src, tgt = two_nodes
|
||||
res = await client.post("/api/v1/edges", json={"source": src, "target": tgt, "type": "ethernet"})
|
||||
|
||||
Reference in New Issue
Block a user