feat: edge edit mode + proxmox container mode toggle

- Double-click any link to open Edit Link modal (type, label, VLAN ID, delete)
- Add updateEdge / deleteEdge actions to canvasStore
- Add container_mode field to proxmox nodes (backend model, schemas, migration)
- NodeModal shows container toggle for proxmox type (defaults ON)
- ProxmoxGroupNode renders as regular BaseNode when container_mode is OFF
- setProxmoxContainerMode store action handles structural changes atomically
  (children parentId/extent, node dimensions)
- CanvasContainer filters edges between container proxmox and its children
- Canvas load respects container_mode when assigning parentId/extent
This commit is contained in:
Pouzor
2026-03-07 14:15:08 +01:00
parent 9eba62c5b5
commit 4fb9a8ee45
11 changed files with 190 additions and 30 deletions
+5
View File
@@ -1,3 +1,5 @@
from contextlib import suppress
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase
@@ -18,6 +20,9 @@ class Base(DeclarativeBase):
async def init_db() -> None:
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
# Add container_mode column if not present (existing databases)
with suppress(Exception):
await conn.exec_driver_sql("ALTER TABLE nodes ADD COLUMN container_mode BOOLEAN NOT NULL DEFAULT 0")
async def get_db():
+2 -1
View File
@@ -1,7 +1,7 @@
import uuid
from datetime import UTC, datetime
from sqlalchemy import JSON, DateTime, Float, ForeignKey, Integer, String, Text
from sqlalchemy import JSON, Boolean, DateTime, Float, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.db.database import Base
@@ -33,6 +33,7 @@ class Node(Base):
pos_x: Mapped[float] = mapped_column(Float, default=0)
pos_y: Mapped[float] = mapped_column(Float, default=0)
parent_id: Mapped[str | None] = mapped_column(String, ForeignKey("nodes.id"))
container_mode: Mapped[bool] = mapped_column(Boolean, default=False)
last_seen: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
response_time_ms: Mapped[int | None] = mapped_column(Integer)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now)