mirror of
https://github.com/hansjone/netx.git
synced 2026-10-17 04:43:20 +08:00
Optimize topology canvas per the 2026-10-12 plan.
Save path: one atomic POST /views/{id}/commit (edges, ports, styles, node
add/remove, positions) replaces the multi-request save. Edge styles and
manual-edge port edits now go through dirty/undo/save instead of writing
immediately; non-manual edge ports are read-only.
Data safety: UI saves no longer clear MCP node locks or freeze the device
name into the placement label (label_override + omit-means-keep semantics,
also applied to the MCP positions tool). Adding NEs/neighbors with unsaved
edits now saves first instead of silently dropping them. Positions no longer
bypass membership caps, except persisting synthesized child-region icons.
Fixes found in acceptance: nodes added in the same commit kept (40,40)
under autoflush=False; edits on edges deleted in the same save 404'd the
whole save; box-selection drags and arrow-key moves were not marked dirty;
large canvases far from the origin opened blank and locate did nothing
because fitView waits for measurement that onlyRenderVisibleElements never
does (now fitBounds from known geometry).
Also: batch N+1 lookups in graph/positions, deterministic truncation,
outside-peer scan excludes internal edges, split TopologyPage into hooks,
fix flaky UME/LLDP port test, add scripts/topology_clear_frozen_labels.py.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
60a0ea6021
commit
f301544b99
40 changed files with 5587 additions and 1916 deletions
|
|
@ -121,6 +121,39 @@ def place_child_region_on_parent_canvas(
|
|||
return row
|
||||
|
||||
|
||||
def add_missing_region_placement(
|
||||
db: Session, view: TopoView, fabric_node_id: str, *, x: float, y: float
|
||||
) -> TopoViewNode | None:
|
||||
"""Persist a child-region icon that was only synthesized (no placement row yet).
|
||||
|
||||
Returns None unless ``fabric_node_id`` is a manual child region of the view's folder.
|
||||
"""
|
||||
if not is_region_canvas_node_id(fabric_node_id) or _is_world_flat(view):
|
||||
return None
|
||||
folder = db.get(TopoFolder, region_folder_id_from_node(fabric_node_id))
|
||||
if (
|
||||
folder is None
|
||||
or str(folder.kind or "") != "region"
|
||||
or str(folder.parent_id or "") != str(view.folder_id or "")
|
||||
or _is_ume_managed_folder(folder)
|
||||
):
|
||||
return None
|
||||
now = _utcnow()
|
||||
row = TopoViewNode(
|
||||
id=uuid4().hex,
|
||||
view_id=view.id,
|
||||
fabric_node_id=fabric_node_id,
|
||||
x=float(x),
|
||||
y=float(y),
|
||||
label="",
|
||||
locked=False,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
)
|
||||
db.add(row)
|
||||
return row
|
||||
|
||||
|
||||
def remove_region_canvas_placements(db: Session, folder_id: str) -> int:
|
||||
"""Drop this folder's icon from any parent canvas."""
|
||||
nid = region_canvas_node_id(folder_id)
|
||||
|
|
@ -139,6 +172,7 @@ def region_node_out(
|
|||
y: float,
|
||||
locked: bool = False,
|
||||
label: str = "",
|
||||
label_override: str | None = None,
|
||||
) -> ViewNodeOut:
|
||||
child_view = _child_primary_view(db, folder.id)
|
||||
kids = (
|
||||
|
|
@ -154,12 +188,14 @@ def region_node_out(
|
|||
.filter(TopoViewNode.view_id == child_view.id)
|
||||
.count()
|
||||
)
|
||||
display = (label or folder.name or folder.id)[:256]
|
||||
raw = str(label_override if label_override is not None else label or "")
|
||||
display = (raw or folder.name or folder.id)[:256]
|
||||
return ViewNodeOut(
|
||||
fabric_node_id=region_canvas_node_id(folder.id),
|
||||
managed_ne_id="",
|
||||
ume_ne_id="",
|
||||
label=display,
|
||||
label_override=raw[:256],
|
||||
x=float(x),
|
||||
y=float(y),
|
||||
locked=bool(locked),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue