mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 02:00:46 +08:00
Make neighbor projection save-deferred and Visio-style connect.
Project-neighbors supports dry_run for local dirty canvas; Save flushes adds. Connect mode uses drag-from side anchors with smoothstep elbows instead of click-click. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
a746a84d01
commit
b4f0e468cb
11 changed files with 229 additions and 76 deletions
|
|
@ -244,10 +244,14 @@ class ViewProjectNeighborsRequest(BaseModel):
|
|||
When seed ids are omitted, expand from every node already on the canvas.
|
||||
When provided, expand only from those seeds (resolved to fabric nodes that
|
||||
are already placed on the view).
|
||||
|
||||
dry_run=True: return the would-be graph without writing placements (canvas
|
||||
can apply locally and persist on Save).
|
||||
"""
|
||||
|
||||
seed_fabric_node_ids: list[str] = Field(default_factory=list)
|
||||
managed_ne_ids: list[str] = Field(default_factory=list)
|
||||
dry_run: bool = False
|
||||
|
||||
|
||||
class ViewNodeIn(BaseModel):
|
||||
|
|
|
|||
|
|
@ -967,10 +967,14 @@ def project_fabric_neighbors_to_view(
|
|||
|
||||
Optional seeds limit expansion to neighbors of those fabric nodes (must
|
||||
already be on the view). Empty seeds → expand from every canvas node.
|
||||
|
||||
dry_run=True returns the projected graph without persisting placements.
|
||||
"""
|
||||
merge_duplicate_fabric_nodes(db)
|
||||
view = _get_view_or_404(db, view_id)
|
||||
mem = _membership_for_view(view)
|
||||
req = body or ViewProjectNeighborsRequest()
|
||||
dry_run = bool(req.dry_run)
|
||||
if bool(mem.get("frozen")):
|
||||
g = get_view_graph(db, view.id)
|
||||
g.truncated = True
|
||||
|
|
@ -981,7 +985,6 @@ def project_fabric_neighbors_to_view(
|
|||
hops = int(mem.get("expand_hops") or 1)
|
||||
filt = dict(view.filter or {})
|
||||
layer = str(filt.get("layer") or "physical").strip() or "physical"
|
||||
req = body or ViewProjectNeighborsRequest()
|
||||
|
||||
vnodes = db.query(TopoViewNode).filter(TopoViewNode.view_id == view.id).all()
|
||||
fids_on_view = [vn.fabric_node_id for vn in vnodes]
|
||||
|
|
@ -995,7 +998,7 @@ def project_fabric_neighbors_to_view(
|
|||
)
|
||||
# Drop placements pointing at missing fabric rows only (keep LLDP placeholders).
|
||||
orphan_vns = [vn for vn in vnodes if vn.fabric_node_id not in fabric_on_view]
|
||||
if orphan_vns:
|
||||
if orphan_vns and not dry_run:
|
||||
for vn in orphan_vns:
|
||||
db.delete(vn)
|
||||
view.updated_at = _utcnow()
|
||||
|
|
@ -1064,6 +1067,25 @@ def project_fabric_neighbors_to_view(
|
|||
room = max(0, max_nodes - len(existing))
|
||||
to_add = eligible[:room]
|
||||
truncated = len(eligible) > len(to_add)
|
||||
|
||||
if dry_run:
|
||||
if to_add:
|
||||
nested = db.begin_nested()
|
||||
try:
|
||||
_place_fabric_ids_on_view(
|
||||
db, view, to_add, existing=set(existing), near_fabric_ids=seed_ids
|
||||
)
|
||||
db.flush()
|
||||
g = get_view_graph(db, view.id)
|
||||
finally:
|
||||
nested.rollback()
|
||||
else:
|
||||
g = get_view_graph(db, view.id)
|
||||
if truncated:
|
||||
g.truncated = True
|
||||
g.truncate_reason = g.truncate_reason or "membership_cap"
|
||||
return g
|
||||
|
||||
if to_add:
|
||||
_place_fabric_ids_on_view(
|
||||
db, view, to_add, existing=existing, near_fabric_ids=seed_ids
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue