Commit Graph

16 Commits

Author SHA1 Message Date
95d26ec805 Fix module drag + move delete button into edit modal
Module drag broken:
  listeners were on a 12px grip strip only; dragging anywhere else on
  the block had no effect. Moved {...listeners} {...attributes} to the
  outer container so the whole module face is the drag source.
  Port buttons now stop pointerdown propagation so clicking a port does
  not accidentally start a drag. Resize handle also stops pointerdown
  propagation before forwarding to its own handler.
  Removed the now-redundant GripVertical strip.

Delete button covering ports 23-24:
  Removed the absolute-positioned Trash2 button from ModuleBlock face.
  Delete is now inside ModuleEditPanel with an inline confirm flow:
    - 'Delete module' link in the modal footer (left side)
    - Clicking shows 'Remove this module? [Delete] [Cancel]' inline
    - On confirm: calls API, removeModuleLocal, closes modal
  ConfirmDialog import and related state also removed from ModuleBlock.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 23:10:12 -05:00
3d72f429bc Redesign rack module face: ports-first layout, wider column, taller U-slots
Problems fixed:
- Name label + type badge were eating all horizontal space in 1U modules,
  pushing 24 port dots into a cramped overflow that was barely visible
- U_HEIGHT_PX=28 was too tight to show a full port row at all
- Column width (192px) was too narrow to fit 24x10px dots + gaps (286px needed)

Changes:
- U_HEIGHT_PX: 28 -> 44px  (enough room for ports + resize handle)
- RackColumn: w-48 (192px) -> w-80 (320px), min-w-[200px] -> min-w-[320px]
- PORTS_PER_ROW = 24 constant added to constants.ts
- ModuleBlock face redesigned:
    * Removed name <span> and type <Badge> from the visible face
    * Module name + IP now shown as a native title tooltip on hover
    * Port dots are the primary face content (24 per row, gap-[3px])
    * Multiple rows rendered for multi-U modules (up to available height)
    * Hidden port overflow shown as "+N more" below the rows
    * Drag handle slimmed to 12px; delete/resize handles unchanged
    * Type still communicated via background color

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 23:03:10 -05:00
128b43e43d Fix database not initializing in Docker (no db file created)
Root cause: DATABASE_URL used a relative path (file:./data/rackmapper.db).
Prisma CLI (migrate deploy) resolves relative SQLite paths from the
prisma/ schema directory -> /app/prisma/data/rackmapper.db, while the
Prisma Client at runtime resolves from CWD -> /app/data/rackmapper.db.
The migration ran against a different path than the bind mount, so no
database file ever appeared in /app/data (the mounted volume).

Fixes:
- Change DATABASE_URL to absolute path: file:/app/data/rackmapper.db
  everywhere (docker-compose, .env.example, UNRAID.md)
- Replace inline CMD with docker-entrypoint.sh:
    mkdir -p /app/data before migrating (safety net)
    npx prisma migrate deploy with set -e so failures are visible
    exec node dist/server/index.js
  This surfaces migration errors in docker logs instead of silently
  exiting, and ensures the data dir always exists before SQLite opens it
- Update .env.example to reflect plain ADMIN_PASSWORD and COOKIE_SECURE

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:52:16 -05:00
b5df2e6721 Fix palette drag-and-drop not triggering AddModuleModal
DevicePalette's useDraggable was missing dragType: 'palette' in its data
object. RackPlanner's handleDragStart and handleDragEnd both guard on
dragType === 'palette' — without it the drag overlay never showed and the
drop onto a slot was silently ignored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:44:50 -05:00
69b7262535 Fix 401 Unauthorized on all API calls after login (HTTP installs)
Root cause: cookie was set with Secure=true whenever NODE_ENV=production.
Browsers refuse to send Secure cookies over plain HTTP, so the session
cookie was dropped on every request after login — causing every protected
endpoint to return 401.

Fix: replace the NODE_ENV check with an explicit COOKIE_SECURE env var
(default false). Set COOKIE_SECURE=true only when running behind an HTTPS
reverse proxy. Direct HTTP installs (standard Unraid setup) work as-is.

Also updated UNRAID.md to document COOKIE_SECURE with a warning explaining
why it must stay false for plain-HTTP access.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:40:08 -05:00
2c95d01e7a Fix Prisma OpenSSL error on Alpine Linux (Docker)
- Add openssl + openssl-dev to Dockerfile apk install; Alpine does not
  ship OpenSSL by default but Prisma's query engine binary requires it
- Add binaryTargets to schema.prisma generator:
    native                    → used during docker build (npx prisma generate)
    linux-musl-openssl-3.0.x  → correct engine binary for Alpine at runtime
  Without the explicit target Prisma defaults to openssl-1.1.x, which
  does not exist on Alpine 3.18+, producing the "Could not parse schema
  engine response" error at migrate/startup time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:32:25 -05:00
7ea358e66a Add UNRAID.md with GUI and CLI installation instructions
- GUI method: Docker tab field-by-field walkthrough (name, port, volume, env vars)
- CLI method: docker run one-liner with all required flags
- Building the image: local build on Unraid terminal + push-to-registry option
- JWT_SECRET generation tip using /proc/sys/kernel/random/uuid
- Updating, password change, backup, and troubleshooting sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:09:30 -05:00
84cd94a0f5 Update documentation to reflect current build state
RREADME.md: rewrite from TBD to full user-facing README with features,
quick-start, environment variable table, and tech stack.

AGENTS.md:
- Auth: ADMIN_PASSWORD_HASH → ADMIN_PASSWORD (plain text); remove bcryptjs
- Schema: replace enum blocks with String fields + SQLite/Prisma enum warning
- Repo structure: add vlans/, ContextMenu.tsx, NodeEditModal.tsx, /vlans route
- API routes: add POST /modules/:id/move
- Service Mapper canvas features: update to reflect implemented context menus,
  NodeEditModal, and edge type/animation toggle
- Commands: remove hashPassword.ts entry
- Docker env block: update to ADMIN_PASSWORD
- Key Decision #3: updated to plain-text password rationale

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:07:58 -05:00
bcb8a95fae Switch auth to plain-text password env var (remove bcrypt)
- Replace ADMIN_PASSWORD_HASH with ADMIN_PASSWORD in auth route and docker-compose
- Remove bcryptjs / @types/bcryptjs dependencies
- Delete scripts/hashPassword.ts (no longer needed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:05:42 -05:00
7ef0509f2b Add module resize handle to ModuleBlock
- Drag handle at bottom edge of each module (GripHorizontal icon)
- Pointer capture tracks vertical drag delta → U-size delta
- Clamped to: minimum 1U, rack bounds, first module below
- Shows current U-size label during active resize
- On release: PUT /modules/:id with new uSize (server validates collision)
- Optimistic store update via updateModuleLocal on success

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:03:42 -05:00
f4e139972e Add VLAN management page at /vlans
- Full CRUD: create, inline-edit, delete with confirm dialog
- Table shows VLAN ID, name, description, color swatch
- Add-VLAN form at top; hover shows edit/delete actions per row
- Route registered in App.tsx under ProtectedRoute
- VLANs nav button added to RackToolbar and MapToolbar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:02:16 -05:00
0b4e9ea1e5 Add Service Mapper context menus, node edit modal, and edge type toggle
- Right-click on canvas → add any node type at cursor position
- Right-click on node → edit, duplicate, or delete
- Right-click on edge → toggle animation, set edge type (bezier/smooth/step/straight), delete
- Double-click a node → NodeEditModal (label, accent color, rack module link)
- ContextMenu component: viewport-clamped, closes on outside click or Escape
- All actions persist to API; React Flow state updated optimistically

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 22:00:27 -05:00
231de3d005 Initial scaffold: full-stack RackMapper application
Complete project scaffold with working auth, REST API, Prisma/SQLite
schema, Docker config, and React frontend for both Rack Planner and
Service Mapper modules. Both server and client pass TypeScript strict
mode with zero errors. Initial migration applied.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 21:48:56 -05:00
61a4d37d94 Update AGENTS.md 2026-03-21 20:57:16 -05:00
247188354a Upload files to "/" 2026-03-21 20:50:34 -05:00
f0464f3e63 Add RREADME.md 2026-03-21 20:22:57 -05:00