Commit Graph

48 Commits

Author SHA1 Message Date
Pouzor bfe520cd49 fix: use absolute positioning for status dot to prevent IP truncation 2026-04-23 02:35:23 +02:00
Pouzor 29c97ae501 fix: align status dot to top and restore gap in ProxmoxGroupNode header 2026-04-23 02:35:23 +02:00
findthelorax 4ecd241bf4 enlarged node resizer border for easier resizing 2026-04-23 02:35:23 +02:00
findthelorax 96786f155b aligned all status icon styling 2026-04-23 02:35:23 +02:00
Pouzor ebc1d41d5c feat: add docker_container node type and fix container mode for non-proxmox types
- Add docker_container node type (Package icon, sky-blue accent) as child of docker_host
- Parent selector for docker_container filters to docker_host only via nodeType field
- Virtual edge drag-connect syncs parent_id for docker_container <-> docker_host
- Fix setProxmoxContainerMode: remove proxmox-only guard so width/height are properly
  set/cleared for all container-capable types (docker_host, vm, lxc)
- Fix handleAddNode: only give group size when container_mode=true, making create
  and reload behavior consistent (was giving size unconditionally for CONTAINER_MODE_TYPES)
- Add regression tests for docker_host container mode toggle and docker_container nesting
2026-04-22 22:41:01 +02:00
findthelorax 78b47384da fixed the container mode toggle styling for backward compatability and proper padding to remain centered in it's parent element 2026-04-22 22:41:01 +02:00
findthelorax 585df726e7 feature: added a Container Mode toggle to the Virtualization group of node types 2026-04-22 22:41:01 +02:00
Pouzor a0f18dd237 fix: use custom icon in proxmox container mode header 2026-04-20 14:57:45 +02:00
Pouzor 00edc32aeb fix: show visible properties on proxmox container mode node header 2026-04-20 14:45:37 +02:00
Pouzor a816faa0b9 fix: prevent node width expansion when content overflows after resize
Proxmox nodes with container_mode=false fell through both width conditions
in deserializeApiNode and got no explicit width on reload, causing RF to
auto-size to content width and ignoring the user's manual resize.

- canvasSerializer: unified width restore logic — saved width applies to all
  node types; proxmox container_mode defaults (300x200) only kick in when
  no saved width exists
- BaseNode: add overflow-hidden + min-w-0 to properties row so truncate
  actually clips long values instead of expanding the node
2026-04-19 23:43:15 +02:00
Pouzor fbfacec6dc fix: prevent node from expanding beyond resized width on reload 2026-04-19 22:58:10 +02:00
Pouzor 5ad5eba58c feat: add connection handles to zone nodes (closes #58)
- GroupRectNode now renders source+target handles on all four sides
  (top, right, bottom, left) using IDs zone-{side} / zone-{side}-t
- Handles are hover-only: opacity 0 by default, fade in on mouse enter
- Handle color matches the zone border color (respects custom_colors)
- Zone↔zone and zone↔node connections both allowed; edge type picker
  (EdgeModal) opens on connect so user chooses ethernet/wifi/vlan/etc.
- Add GroupRectNode.test.tsx: verifies 8 handles rendered (4 source + 4 target)
- Fix @xyflow/react mocks in LiveView and CanvasContainer tests to include Position
2026-04-19 22:13:40 +02:00
Pouzor ef96cafcc8 feat: IPv6 support and multi-IP per node (closes #60)
- maskIp handles IPv6 addresses (masks second and last group)
- maskIp handles comma-separated IP strings (masks each address)
- Add splitIps() helper to parse comma-separated IP field
- Add primaryIp() helper used by status checker (first IP wins)
- BaseNode renders each IP on its own line when comma-separated
- NodeModal placeholder shows comma-separated example
- Backend status_checker uses only first IP for connectivity checks
- Expand maskIp test suite: IPv6, comma-separated, splitIps, primaryIp
2026-04-19 22:13:40 +02:00
Brett Ferrante eb235cb101 Merge branch 'Pouzor:main' into bug/drag-from-title 2026-04-18 22:14:00 -04:00
Pouzor 70311e6331 fix: propertyIcons mock, key stability, isValidConnection memoized
- Add resolvePropertyIcon mock to BaseNode tests
- Reset mockZoom in top-level beforeEach to prevent test bleed
- Use prop.key instead of index as list key in BaseNode properties
- Extract isValidConnection into useCallback in CanvasContainer
2026-04-18 23:03:21 +02:00
Pouzor 35c3d00f17 fix: memoize borderWidth and sync boxShadow glow ring with zoom
- Wrap borderWidth in useMemo to avoid re-computing on unrelated renders
- Replace hardcoded 1px in boxShadow with borderWidth so glow ring
  matches border thickness at all zoom levels
- Add useViewport mock + 4 zoom-scaling tests to BaseNode.test.tsx
2026-04-18 23:01:27 +02:00
findthelorax 3a5cb0de21 feature: extend zoom out and border width math 2026-04-18 23:01:27 +02:00
findthelorax b0a67744f5 bug: fixed to allow draging from the titlebar 2026-04-17 22:34:17 -04:00
Pouzor 3d89ba3b6f feat: replace static hardware fields with dynamic node properties
Replaces the 4 fixed hardware columns (cpu_count, cpu_model, ram_gb,
disk_gb) with a flexible properties system. Each property has a key,
value, icon (from a curated Lucide picker), and a visibility toggle
that controls whether it appears on the canvas node card.

- Backend: add `properties` JSON column to Node model; data migration
  converts existing hardware rows to properties with correct icons
  (idempotent, old columns kept for safety)
- Backend: add `properties` to NodeBase, NodeUpdate, NodeSave schemas
  and canvasSerializer so values survive canvas save/load
- Frontend: add NodeProperty type; new propertyIcons.ts registry (20
  icons); BaseNode renders visible properties with legacy hardware
  fallback for unmigrated nodes
- Frontend: DetailPanel gains interactive properties section (add /
  edit / remove / toggle visibility / icon picker) replacing the
  read-only hardware block; hardware section removed from NodeModal
- Tests: 6 migration tests, 7 API tests, 8 DetailPanel property tests,
  6 BaseNode render/fallback tests, 9 propertyIcons util tests
2026-04-09 13:47:36 +02:00
Pouzor b0df8f389a fix: align dot grid to snap grid and fix node selection layout shift 2026-04-08 13:58:27 +02:00
Pouzor 38c5bcb606 feat: configurable bottom handles, scanner rewrite, UI polish
## New features
- Configurable bottom connection points per node (1–4 handles)
- Fit view on load
- LiveView improvements
- Node modal: inline Type/Icon picker, default icon in trigger
- Remove redundant Save button from ScanConfigModal

## Scanner fixes
- Phase 1: replace nmap ARP sweep with concurrent asyncio ping sweep
  (50 parallel pings, 1s timeout). Zero false positives, works in any
  Docker network mode. Supplements with /proc/net/arp for ICMP-blocked devices.
- Phase 2: explicit -sS (root) / -sT (non-root) scan type; bump
  host-timeout to 60s; gather(return_exceptions=True) so one failing
  host doesn't abort the batch
- Fix 404 on missing device in hide/ignore
- Validate CIDR ranges to prevent nmap injection
- Thread-safe cancel set, pre-fetch canvas/hidden IPs (no N+1 queries)
- Logging: attach StreamHandler to root logger so app.* logs are visible

## Tests
- 21 backend scanner tests (ping sweep, ARP cache, Phase 2 tolerance)
- Full NodeModal coverage (53 tests)
- LiveView, store, edge label tests
2026-04-04 23:15:47 +02:00
Pouzor 0b89244317 feat: lasso selection, multi-select panel, and named groups
- Add lasso/box selection via selectionOnDrag (Space to pan, lasso by default)
- Add lasso/pan toggle button in canvas controls (bottom-left)
- Multi-select panel in right panel when 2+ nodes selected (including zones)
- Create named Group node from selected nodes with bounding box math
- Group node: resizable, inline rename, show/hide border toggle, status summary
- GroupDetailPanel: lists members, online/offline count, ungroup action
- Fix group persistence after save/reload (extend proxmox container map to include group nodes)
- Fix groupRect serialization to preserve parent_id
- Remove background color from group and proxmox container node wrappers
- Add tests for all new store actions, GroupNode, MultiSelectPanel, GroupDetailPanel
2026-04-01 23:15:52 +02:00
Pouzor 4ccdbed711 feat: add label position (inside/outside) and text size to Zone modal
- Label position toggle: inside (default) or outside the border
- Outside mode renders the label above/below the zone based on text_position
- Text size selector: 10/12/14/16/18/20px (default 12)
- Both fields persisted in custom_colors (no backend schema change needed)
- 8 new frontend tests, 1 new backend test
2026-03-29 03:04:29 +02:00
Pouzor 38a06682e5 feat: rename Rectangle to Zone, add border width selector
- Rename "Rectangle" → "Zone" in sidebar, add modal and edit modal
- Add border width selector (1–5px, default 2px) to the Zone modal
- Border width persisted in custom_colors.border_width and applied in GroupRectNode
2026-03-29 01:47:04 +01:00
Pouzor 2a9cbc5932 feat: resizable nodes with width/height persistence
Add NodeResizer to BaseNode so users can drag corners to resize any node.
Persist width/height through the full stack: DB model, schemas, canvas
save/load route, and migration for existing databases.

Add tests covering save, update, clear, and load of node dimensions.
2026-03-28 11:57:09 +01:00
Pouzor 06ec18a137 feat: add hardware specs to nodes (CPU, RAM, Disk) with canvas display
- Add cpu_count, cpu_model, ram_gb, disk_gb, show_hardware fields to NodeData
- NodeModal: collapsible Hardware section with toggle to show specs on canvas
- BaseNode: 2-line hardware section with Cpu/MemoryStick/HardDrive icons, only renders set fields
- DetailPanel: Hardware section with GB/TB formatting
- Backend: schema, model, DB migration, canvas save/load support
- Tests: frontend (NodeModal, DetailPanel) + backend (canvas persist/load)
2026-03-21 00:01:15 +01:00
Pouzor adb4474687 feat: add Docker node type, group rect border style, and categorized node type selector
- Fix DockerNode default icon: use Anchor instead of Package
- Add border_style option to Group Rectangle (solid/dashed/dotted/double/none)
- Group node type selector by category (Hardware, Virtualization, IoT, Generic)
- Add tests for border style feature
2026-03-20 21:09:58 +01:00
Pouzor 271bbf2d01 feat: add hide IP toggle in sidebar
- Add hideIp / toggleHideIp to canvasStore (UI-only, not persisted)
- Add maskIp util: 192.168.1.115 → 192.168.XX.XX (non-IPv4 passthrough)
- BaseNode reads hideIp from store and masks last two octets when active
- Sidebar shows Eye/EyeOff toggle below Scan Network, highlights when active
2026-03-11 16:15:22 +01:00
Pouzor 92d505f78c feat: add logo, favicon, and theme system
- Add custom SVG favicon and Logo component (house + network nodes motif)
- Update page title to Homelable with meta description
- Show Logo in sidebar header and toolbar
- Add theme store and ThemeModal for canvas style switching
- Refactor node colors and edge styles for theme support
2026-03-11 14:29:15 +01:00
Pouzor 1e72366d03 feat: add Group Rectangle — resizable decorative zones on canvas
- New GroupRectNode: rounded rect with NodeResizer (8 handles), no
  connection handles, always behind network nodes via negative zIndex
- GroupRectModal: label, font preset (Inter/Mono/Serif), 3×3 text
  position grid, text/border/background color pickers, z-order 1–9
- Sidebar: "Add Rectangle" button (below Add Node), group rects
  excluded from node count stats
- Save/load: size persisted in custom_colors.width/height, no backend
  schema changes required
- elevateNodesOnSelect=false on ReactFlow so selected rects never
  pop above network nodes
- Tests: 3 new store tests + 9 GroupRectModal tests (66 total, all pass)
2026-03-10 16:59:40 +01:00
Pouzor 220d831cf1 feat: add CPL / Powerline node type with PlugZap icon 2026-03-08 20:42:00 +01:00
Pouzor 3312742f4c feat: add printer and computer node types with icons 2026-03-08 17:48:53 +01:00
Pouzor d829a4821e fix: use explicit source+hidden-target handles for reliable bidirectional snapping
source handles: visible, can initiate drag from top or bottom
target handles: invisible (opacity:0, 12x12px), overlap the source at same
position — React Flow detects them for snapping and shows visual feedback
without the user seeing a second dot. Ensures bottom→top connections work.
2026-03-08 13:10:25 +01:00
Pouzor be18bcc6d9 fix: add source+target handles at top and bottom so all snatch points work
connectionMode=loose alone does not reliably make source handles act as
drop targets. Each position now has both a source handle (to initiate
drag) and a target handle (to receive drops). They overlap visually as
one dot but support full bidirectional connections.
2026-03-08 12:26:21 +01:00
Pouzor 3e1edd9458 fix: make top handles type=source so connections can be dragged from them
React Flow only allows initiating a drag from type=source handles.
Top handles were type=target so users could never start a connection
from the top of any node. With connectionMode=loose, source-to-source
connections are already allowed, so all handles can now be source.
2026-03-08 12:16:21 +01:00
Pouzor 4511763bac fix: persist custom_icon on canvas save + add CCTV icon
- NodeSave schema was missing custom_icon field — icon reset to default on reload
- handleSave was not including custom_icon in the payload
- CameraNode now uses Cctv icon (clearer than Camera)
- Added 'cctv' entry to ICON_REGISTRY for the icon picker
2026-03-08 12:00:11 +01:00
Pouzor 88634aeb1d feat: add Camera node type + flag RTSP/camera ports during scan
- New 'camera' node type with Camera icon (frontend + types)
- Scanner fingerprint: camera ports (554, 8554, 37777, 34567, 2020) now suggest 'camera' instead of 'iot'
- service_signatures.json: all camera/NVR entries updated to suggested_node_type=camera
- 'camera' added to priority list in suggest_node_type (above iot)
2026-03-08 11:55:26 +01:00
Pouzor a63e248427 fix: cluster handles are bidirectional — connectionMode loose, both type source 2026-03-08 11:24:18 +01:00
Pouzor 2fcc9eba80 fix: reduce cluster handles to one per side, normal size 2026-03-08 01:41:36 +01:00
Pouzor b2a6651db7 fix: show cluster handles in both container and simple mode on Proxmox node 2026-03-08 01:05:13 +01:00
Pouzor 1364b30eb4 feat: add left/right cluster handles on Proxmox group node 2026-03-08 00:44:22 +01:00
Pouzor d98bfba506 feat: add custom icon picker to node create/edit modal
- Add 65+ icons across 7 categories (Infrastructure, Media, Monitoring,
  Storage, Security, Automation, Dev & Containers, Communications) covering
  popular self-hosted apps: Home Assistant, Jellyfin, Plex, Grafana, Portainer,
  Pi-hole, Vaultwarden, Gitea, Nextcloud, Node-RED, Frigate, etc.
- New nodeIcons.ts utility with ICON_REGISTRY, ICON_MAP and resolveNodeIcon()
- Inline icon picker in NodeModal: collapsible panel with search + grid grouped
  by category; click to select, click again or Reset to revert to type default
- BaseNode uses resolveNodeIcon() so custom icon renders live on canvas
- Add custom_icon field to NodeData type, NodeBase/NodeUpdate schemas, Node ORM
  model, and database.py idempotent ALTER TABLE migration
2026-03-07 23:01:30 +01:00
Pouzor 7dd500feee fix: always show node border color, widen to 2px on selection 2026-03-07 14:37:46 +01:00
Pouzor 37c963cf96 feat: per-node custom color styling (border, background, icon)
- Add resolveNodeColors() utility merging type defaults with per-node overrides
- Default colors per node type (cyan=isp/router/lxc/ap, green=switch/nas,
  purple=server/vm, orange=proxmox, amber=iot, gray=generic)
- Remove glowColor prop from BaseNode — colors now come from node data
- ProxmoxGroupNode uses resolveNodeColors for group border/header/icon
- NodeModal: Appearance section with 3 color swatches (border, background, icon)
  — click swatch to open native color picker; Reset to defaults button
- custom_colors persisted as JSON in DB (backend model + schemas + migration)
- 7 new unit tests for resolveNodeColors covering all node types + partial overrides
2026-03-07 14:31:05 +01:00
Pouzor 4fb9a8ee45 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
2026-03-07 14:15:08 +01:00
Pouzor a3e6a97404 feat: Proxmox nested nodes — VM/LXC rendered inside resizable group container
- ProxmoxGroupNode: resizable bordered container with orange accent, header
  bar (icon, label, IP, status dot), NodeResizer on selection
- nodeTypes: proxmox now uses ProxmoxGroupNode instead of BaseNode
- NodeData: added parent_id field
- canvasStore: addNode and loadCanvas wire parentId + extent='parent'
  for child nodes; loadCanvas sorts parents before children (RF requirement)
- NodeModal: Parent Proxmox dropdown appears when type is VM or LXC,
  lists all Proxmox nodes on the canvas
- App.tsx: passes proxmoxNodes to modals; child nodes positioned relative
  to parent (x:20, y:50); Proxmox nodes get width:300/height:200 on load
- layout.ts: Dagre skips child nodes (parentId set); uses actual group
  dimensions for Proxmox nodes in rank calculation
2026-03-07 00:50:50 +01:00
Pouzor 44a448e26d fix: all lint errors, test + lint pre-commit passing
Frontend:
- Split nodeTypes/edgeTypes into separate .ts files (react-refresh)
- Remove setState-in-effect in NodeModal (key prop reset)
- Fix handleSave accessed before declaration (useRef pattern)
- Exclude src/components/ui/** from eslint (shadcn generated)
- Use defineConfig from vitest/config for test type support

Backend:
- ruff --fix: sort imports, datetime.UTC alias
- Raise line-length to 120, ignore E501 in tests
- Break long update_node/update_edge signatures
- pyproject.toml: per-file-ignores for tests
2026-03-06 23:58:10 +01:00
Pouzor 9bb34c99cc feat: add frontend source (fix submodule), compact node design
- Remove nested .git from Vite scaffold
- Horizontal node layout: icon left, label+IP right, reduced height
2026-03-06 23:31:15 +01:00