Commit graph

57 commits

Author SHA1 Message Date
rcourtman
0ddc30c1e1 Redesign Ceph, Replication, and Mail Gateway pages for UI consistency
- Ceph: Complete rework with summary cards (storage, clusters, services, pools),
  search with type-to-search, proper loading/disconnected/empty states, cluster
  overview table, pools table with filtering, health badges with tooltips

- Replication: Add summary cards (total/healthy/issues/next sync), status filter
  buttons (All/Healthy/Warning/Error), search with type-to-search, countdown timers
  for next sync with overdue/imminent highlighting, row highlighting for problem jobs,
  error tooltips, loading state

- Mail Gateway: Add aggregate summary cards across all instances (mail/spam/virus/
  quarantine/queue), visual threat rate progress bars, status badges with health
  indicators, queue depth tooltips with breakdown, streamlined stats grid with
  color-coded threat categories, improved cluster nodes table

All three pages now follow the same design patterns as Dashboard, Hosts, Docker,
and Storage using Card, EmptyState, and consistent styling.
2025-12-13 00:08:29 +00:00
rcourtman
bf43d448cf fix: Robust OCI container detection with state persistence
Backend:
- Seed OCI classification from previous state so containers never
  'downgrade' to LXC if config fetching intermittently fails
- Prevent type regression in recordGuestSnapshot when OCI was previously detected
- Move metrics zeroing before snapshot recording for cleaner flow

Frontend:
- Add isOCIContainer() memo that checks both type and isOci flag
- Use isOCI helper in Dashboard.tsx for AI context building
- Include oci-container type in useResources container conversion
- Preserve isOci and osTemplate fields through legacy conversion

This ensures OCI containers retain their classification even when
Proxmox API permissions or transient errors prevent config reads.
2025-12-12 20:06:39 +00:00
rcourtman
e82cf7eaaf feat: Enhance OCI container display and AI context
- Frontend: Add ociImage memo to extract clean image name from osTemplate
- Frontend: Show OCI image name in type badge tooltip
- Frontend: Display OCI image in OS column when no guest agent info available
- Frontend: Include ociImage in AI context data for selected OCI containers
- Backend: Differentiate OCI containers as 'oci_container' type in AI context
- Backend: Add Metadata field to ResourceContext for extensibility
- Backend: Include oci_image in container metadata for AI analysis
- Backend: Update section heading to 'LXC/OCI Containers' in AI context

This follows Docker container patterns to avoid duplicating work.
2025-12-12 18:00:09 +00:00
rcourtman
dfb5d50f73 feat: Add Proxmox 9.1+ OCI container support
- Backend: Add IsOCI and OSTemplate fields to Container model
- Backend: Add extractContainerOSTemplate() and isOCITemplate() detection functions
- Backend: Detect OCI containers via ostemplate config and set type to 'oci'
- Frontend: Add isOci and osTemplate to Container interface
- Frontend: Add 'oci-container' to ResourceType with distinct purple badge
- Frontend: Update Dashboard filters to include OCI containers with LXC
- Tests: Add comprehensive unit tests for OCI detection logic

OCI containers are detected by checking the ostemplate for patterns like:
- oci: prefix (e.g., oci:docker.io/library/alpine:latest)
- docker: prefix (e.g., docker:nginx:latest)
- Known registry URLs (docker.io, ghcr.io, gcr.io, quay.io, etc.)
- Local templates with oci- or oci_ filename patterns
2025-12-12 17:51:43 +00:00
rcourtman
f57e45ed5f feat: Docker agent retry, UI column improvements, and IP tooltip enhancements
- Add exponential backoff retry for Docker agent startup (main.go)
- Fix Docker resource/image column widths with proper truncation
- Unify IP tooltip styling across hosts and guests with detailed network info
- Improve column visibility defaults and sticky column handling
- Various component refinements for Dashboard, Storage, and Backups views
2025-12-12 08:26:36 +00:00
rcourtman
d2330cf405 refactor(ai): Remove over-engineered URL discovery service
Keep only the simple AI-powered approach:
- set_resource_url tool lets AI save discovered URLs
- Users ask AI directly: 'Find URLs for my containers'
- AI uses its intelligence to discover and set URLs

Removed:
- URLDiscoveryService (rigid port scanning)
- Bulk discovery API endpoints
- Frontend discovery button

The AI itself is smart enough to iterate through resources
and discover URLs when asked.
2025-12-10 08:35:24 +00:00
rcourtman
721f973271 AI features checkpoint: Host selection, memory sparklines, UI refinements
- Extended AI context selection to host rows in HostsOverview
- Added resourceId prop to StackedMemoryBar for sparkline support
- Relocated guest URL editing from GuestRow name click
- Added GuestNotes component with URL field in AI sidebar
- Refined host routing in AI service backend
- Minor animation and styling improvements
2025-12-07 12:25:26 +00:00
rcourtman
6988eb746a Frontend updates 2025-12-07 00:49:32 +00:00
rcourtman
c0da4768bb Metric bar and CPU bar improvements 2025-12-07 00:27:47 +00:00
rcourtman
fc8d88a7c7 Dashboard and sparkline improvements 2025-12-07 00:08:52 +00:00
rcourtman
90c45968e7 AI Problem Solver implementation and various fixes
- Implement 'Show Problems Only' toggle combining degraded status, high CPU/memory alerts, and needs backup filters
- Add 'Investigate with AI' button to filter bar for problematic guests
- Fix dashboard column sizing inconsistencies between bars and sparklines view modes
- Fix PBS backups display and polling
- Refine AI prompt for general-purpose usage
- Fix frontend flickering and reload loops during initial load
- Integrate persistent SQLite metrics store with Monitor
- Fortify AI command routing with improved validation and logging
- Fix CSRF token handling for note deletion
- Debug and fix AI command execution issues
- Various AI reliability improvements and command safety enhancements
2025-12-06 23:46:08 +00:00
rcourtman
469307d607 refactor: Use text labels for OS column instead of icons
Simplified OS display to plain "Windows" and "Linux" text labels.
Previous icon attempts were rejected as too complex or unclear.
Text labels are cleaner and more universally recognizable.
2025-12-05 12:58:18 +00:00
rcourtman
c9915ead8b feat: Add OS type display for LXC containers
- Extract ostype from LXC container config (debian, ubuntu, alpine, etc.)
- Map ostype values to human-readable names (e.g., "debian" -> "Debian")
- Add OSName field to Container model and ContainerFrontend
- Add icons for NixOS, openSUSE, and Gentoo in frontend
- LXC containers now show OS icons alongside VMs in the dashboard

Supported LXC OS types: alpine, archlinux, centos, debian, devuan,
fedora, gentoo, nixos, opensuse, ubuntu, unmanaged
2025-12-05 12:43:32 +00:00
rcourtman
41acb4f2ce feat: Replace OS column text with icons and rich tooltips
- Add OSInfoCell component with OS-specific icons (Windows, Ubuntu,
  Debian, Alpine, CentOS/RHEL, Fedora, Arch, FreeBSD, generic Linux)
- Each OS type has a distinct color for quick visual identification
- Portal tooltip shows full OS name, version, and guest agent version
- Much more compact than text strings like "Microsoft Windows Server 2022"
2025-12-05 12:34:52 +00:00
rcourtman
c169ead4d2 fix: Correct column render order (Tags before OS) 2025-12-05 12:23:24 +00:00
rcourtman
871a714a3e fix: Move OS column to detailed tier (xl+ screens)
OS info requires guest agent to be installed and configured, so most
guests won't have this data. Move to detailed tier so it only shows
on extra-wide screens or when explicitly enabled by user.
2025-12-05 12:21:43 +00:00
rcourtman
3b38578bce feat: Add icons to backup status column with rich tooltip
- Add checkmark icon for fresh backups
- Add warning triangle for stale backups
- Add X icon for critical/never backups
- Use consistent Portal-based tooltip matching other columns
- Show formatted date, time, and relative age in tooltip
2025-12-05 12:16:43 +00:00
rcourtman
a15dc6b899 feat: Toggleable table columns with rich tooltips for Proxmox dashboard
Replace drawer-based info display with inline columns that can be toggled:
- Add IP, Uptime, Node, Backup, OS, Tags columns (user-toggleable)
- Add ColumnPicker dropdown to show/hide columns with localStorage persistence
- Columns auto-show based on screen width using priority system
- Remove GuestDrawer - all info now visible inline or via tooltips

Rich hover tooltips:
- Disk bar: Shows all mount points with usage %, color-coded by severity
- Memory bar: Shows used/free/balloon/swap breakdown
- IP column: Shows network icon + count, hover for interfaces, MACs, IPs, traffic

Also:
- Create useColumnVisibility hook for responsive column management
- Create ColumnPicker component for column toggle UI
- Update drawer layouts in Hosts/Docker tabs for consistency
2025-12-05 12:12:56 +00:00
rcourtman
f32d22dc41 Convert data tables from CSS Grid to HTML tables
- Replace CSS Grid with native <table> elements across all data tables
- HTML tables naturally align columns based on widest content in each column
- Add min-width on CPU/Memory/Disk columns for proper progress bar display
- Remove responsive column header abbreviations (show full labels always)
- Remove icon components from NodeSummaryTable headers
- Simplify TemperatureGauge to text-only display (no progress bar)

Tables converted: Dashboard guest table, NodeSummaryTable, HostsOverview,
DockerUnifiedTable, DockerHostSummaryTable
2025-11-29 21:20:02 +00:00
courtmanr@gmail.com
ae3a349124 Refine memory visualization with StackedMemoryBar component
- Add StackedMemoryBar component to visualize Active/Balloon/Swap memory
- Integrate StackedMemoryBar into NodeSummaryTable, GuestRow, HostsOverview, and DockerUnifiedTable
- Add TemperatureGauge component for temperature visualization
- Standardize replication job status indicators with StatusDot
- Fix mock data generator to use realistic balloon memory values (0 by default, small % when active)
- Add StackedContainerBar for Docker container status visualization
- Add ZFSHealthMap component for storage pool health visualization
2025-11-29 13:48:30 +00:00
rcourtman
71580181d0 Add stacked bar visualization for multiple disks
Show individual disk usage segments as a stacked bar in the dashboard
table. Each segment represents one disk's used space proportional to
total capacity. Multi-disk systems display a count badge [N] and
hovering shows a tooltip with per-disk breakdown (name, used/total, %).

Single-disk and aggregate fallback still work as before.

Related to #489
2025-11-28 10:36:23 +00:00
courtmanr@gmail.com
b0ff539fcc Remove unwanted table animations on data updates
- Remove animate-enter class from all table row components
- Prevents animations on routine WebSocket data updates
- Animations now only occur on initial load/new items
- Fix test expectation for Docker monitoring checkbox default state

Components updated:
- DockerUnifiedTable (container/service rows)
- DockerHostSummaryTable
- NodeSummaryTable
- GuestRow
- ConfiguredNodeTables (PVE/PBS/PMG)
- Storage and DiskList
- APITokenManager
- UnifiedAgents

All tests passing.
2025-11-27 18:52:43 +00:00
rcourtman
244431b6c2 refactor(ui): improve table column sizing and progress bar constraints
- Cap progress bars at 140px max-width for better readability
- Constrain shell layout to 1400px max-width, centered
- Fix metric columns (CPU, Memory, Disk) at 156px
- Give name/resource columns extra space via flex
- Remove Docker Disk column (data rarely available from API)
- Remove fixed percentage widths from backups table for auto-sizing
- Improve text contrast in progress bar labels
2025-11-27 12:09:12 +00:00
courtmanr@gmail.com
185476750d feat(ui): apply glassmorphism and staggered animations to tables 2025-11-27 10:44:36 +00:00
rcourtman
91c72a274c feat: add backup status indicator to guest table
Shows shield icon next to guest name when backup is stale or missing:
- Yellow shield: backup 24-72 hours old
- Red shield: backup older than 72 hours
- Gray shield: no backup found

Fresh backups (<24h) show no indicator to keep the UI clean.
Templates are excluded from backup status display.
2025-11-26 21:30:41 +00:00
rcourtman
17c99377f6 fix: restore I/O column styling to match v4.32.5 release
- Restore green/yellow/red color thresholds for disk and network I/O
- Use consistent text-xs font size across all columns
- Expand column widths to fit full header text at larger breakpoints
- Show full header names (Disk Read, VMID, Uptime, Memory) at xl+ screens
- Use shared GUEST_COLUMNS config for header/row grid alignment
- Add whitespace-nowrap to prevent header text wrapping
2025-11-26 09:32:58 +00:00
rcourtman
5dce402d62 fix: make I/O metrics reactive to WebSocket updates
The I/O columns were not updating in real-time because they accessed
props.guest directly instead of through reactive memos. This wraps
diskRead, diskWrite, networkIn, networkOut in createMemo() to properly
track changes from WebSocket data updates.
2025-11-25 21:36:27 +00:00
rcourtman
bc3bb7a7ac fix: restore intensity-based coloring for I/O columns
The I/O columns (Disk Read, Disk Write, Net In, Net Out) were showing
static gray text regardless of throughput values. This restores the
visual intensity scaling that was lost during the responsive table
refactor, where higher throughput values appear bolder/brighter to
draw attention to active I/O.

Thresholds:
- < 1 MB/s: dim gray
- 1-10 MB/s: normal gray
- 10-50 MB/s: medium weight, slightly brighter
- > 50 MB/s: semibold, white/black
2025-11-25 21:29:06 +00:00
rcourtman
98b0721461 feat: improve responsive table layout with tighter columns
- Add 4 separate I/O columns (D Read, D Write, N In, N Out) to guest table
- Tighten column widths: fixed-width I/O columns, flexible progress bar columns
- Remove sticky columns from NodeSummaryTable (not needed)
- Shorten "Containers" to "CTs" in node summary for consistency
- Always show full VM/LXC labels (no mobile abbreviation)
- Increase name column minWidth to 100px for mobile readability
- Add formatSpeed utility function for I/O display
- Add responsive infrastructure: useBreakpoint hook, useGridTemplate hook
2025-11-25 20:37:28 +00:00
courtmanr@gmail.com
ebcafa1dac feat: adaptive node table layout, guest row fixes, and legacy agent detection
- Implemented adaptive layout for NodeSummaryTable with responsive columns and sticky name column.
- Fixed GuestRow background display issues.
- Added IsLegacy field to Host and DockerHost models to flag legacy agents (version < 1.0.0).
- Updated monitor to populate IsLegacy based on agent version.
2025-11-25 17:19:36 +00:00
courtmanr@gmail.com
ac747ddf11 Enhance UI responsiveness for tables: apply percentage-based widths and selective column hiding 2025-11-25 10:57:33 +00:00
rcourtman
65fbd72b15 feat: add shared status indicators
Related to #677
2025-11-14 12:42:08 +00:00
rcourtman
3fa7356ff3 Improve auth timeout handling (related to #705) 2025-11-12 21:50:53 +00:00
rcourtman
a82a345cd6 Improve table column widths and sparkline visibility 2025-11-09 23:36:52 +00:00
rcourtman
886368ec44 feat: add sparklines view mode for metrics visualization
Add comprehensive sparkline chart support as an alternative to progress bars
for CPU, Memory, and Disk metrics across all tables.

Features:
- Toggle between bars/trends view modes (persisted to localStorage)
- 30-second sampling with 2-hour retention window using ring buffer
- Canvas-based rendering with shared requestAnimationFrame for efficiency
- Hover tooltips showing exact values and timestamps
- Threshold reference lines (warning/critical) for context
- localStorage persistence survives page refreshes (12-hour max age)
- Dynamic width adaptation to column size
- Namespaced resource IDs prevent collisions
- Lifecycle cleanup prevents memory leaks

Performance optimizations:
- Decoupled sampling from WebSocket handler (6x reduction in recording)
- O(1) ring buffer insertions (no array cloning)
- Batched canvas rendering (single rAF for all sparklines)
- Debounced localStorage writes
- Automatic pruning of removed resources

UI improvements:
- Consistent radio toggle styling matching other filters
- Fixed column widths prevent layout shift during toggle
- Fixed row heights prevent vertical size changes
- Sparklines fill available column width proportionally
2025-11-09 22:31:35 +00:00
rcourtman
4f9ba7a285 Allow layout to expand on wide displays (related to #643)
Changed .pulse-shell from fixed 95rem cap to fluid clamp(95rem, 92vw, 120rem)
to match standard monitoring dashboard behavior (Proxmox, Grafana, Portainer).

On laptops/small screens: unchanged (capped at 1520px)
On 1080p displays: expands to ~1766px usable width
On 4K/ultrawide: expands up to 1920px max for readability

Added back 2xl column widths (totaling ~1720px) that properly fit within
the expanded shell, giving wide-display users more breathing room while
maintaining proportional scaling across all breakpoints.

Changed files:
- index.css: Update .pulse-shell max-width to use clamp()
- Dashboard.tsx: Add 2xl column widths calculated for expanded shell
- GuestRow.tsx: Add matching 2xl column widths
2025-11-06 21:51:17 +00:00
rcourtman
68caf5592b Fix Proxmox dashboard table overflow on wide displays (related to #643)
Removed 2xl: width overrides that caused the table to exceed container width.
At ≥1536px viewport, the 2xl breakpoint expanded table columns to ~1528px
total width while .pulse-shell container provides only ~1416px usable space,
forcing Net In/Net Out columns off-screen and requiring horizontal scroll.

Table now caps at xl: breakpoint widths (~1266px) which fit comfortably within
the container at all viewport sizes. Net In/Net Out columns are now visible
without scrolling on 1080p, 4K, and all wide displays.

Changed files:
- Dashboard.tsx: Remove 2xl: width classes from all table header columns
- GuestRow.tsx: Remove 2xl: width classes from all table cell columns
2025-11-06 21:36:30 +00:00
rcourtman
a8fa834d24 Fix critical truncation bug preventing data readability on touch devices (related to #643)
Removed CSS truncate from key identifier columns (container names, service names,
guest names, host names, image names) that were making data inaccessible on mobile/
touch devices where title tooltips don't work.

Users can now read full identifiers via horizontal scroll (already implemented via
ScrollableTable component). Data should always be readable without requiring additional
UI affordances.

Changed files:
- DockerUnifiedTable: Remove truncate from container/service names and images
- GuestRow: Remove truncate from guest names
- HostsOverview: Remove truncate from host display names and hostnames

Column resizing remains on backlog as optional enhancement; users should not need
a drag handle just to read the contents.
2025-11-06 15:00:36 +00:00
rcourtman
20854256c3 Fix VM migration issue where custom alert thresholds are lost
Resolves #641

## Problem
When a VM migrates between Proxmox nodes, Pulse was treating it as a new
resource and discarding custom alert threshold overrides. This occurred
because guest IDs included the node name (e.g., `instance-node-VMID`),
causing the ID to change when the VM moved to a different node.

Users reported that after migrating a VM, previously disabled alerts
(e.g., memory threshold set to 0) would resume firing.

## Root Cause
Guest IDs were constructed as:
- Standalone: `node-VMID`
- Cluster: `instance-node-VMID`

When a VM migrated from node1 to node2, the ID changed from
`instance-node1-100` to `instance-node2-100`, causing:
- Alert threshold overrides to be orphaned (keyed by old ID)
- Guest metadata (custom URLs, descriptions) to be orphaned
- Active alerts to reference the wrong resource ID

## Solution
Changed guest ID format to be stable across node migrations:
- New format: `instance-VMID` (for both standalone and cluster)
- Retains uniqueness across instances while being node-independent
- Allows VMs to migrate freely without losing configuration

## Implementation

### Backend Changes
1. **Guest ID Construction** (`monitor_polling.go`):
   - Simplified to always use `instance-VMID` format
   - Removed node from the ID construction logic

2. **Alert Override Migration** (`alerts.go`):
   - Added lazy migration in `getGuestThresholds()`
   - Detects legacy ID formats and migrates to new format
   - Preserves user configurations automatically

3. **Guest Metadata Migration** (`guest_metadata.go`):
   - Added `GetWithLegacyMigration()` helper method
   - Called during VM/container polling to migrate metadata
   - Preserves custom URLs and descriptions

4. **Active Alerts Migration** (`alerts.go`):
   - Added migration logic in `LoadActiveAlerts()`
   - Translates legacy alert resource IDs to new format
   - Preserves alert acknowledgments across restarts

### Frontend Changes
5. **ID Construction Updates**:
   - `ThresholdsTable.tsx`: Updated fallback from `instance-node-vmid` to `instance-vmid`
   - `Dashboard.tsx`: Simplified guest ID construction
   - `GuestRow.tsx`: Updated `buildGuestId()` helper

## Migration Strategy
- **Lazy Migration**: Configs are migrated as guests are discovered
- **Backwards Compatible**: Old IDs are detected and automatically converted
- **Zero Downtime**: No manual intervention required
- **Persisted**: Migrated configs are saved on next config write cycle

## Testing Recommendations
After deployment:
1. Verify existing alert overrides still apply
2. Test VM migration - confirm thresholds persist
3. Check guest metadata (custom URLs) survive migration
4. Verify active alerts maintain acknowledgment state

## Related
- Addresses similar issues with guest metadata and active alert tracking
- Lays groundwork for any future guest-specific configuration features
- Aligns with project philosophy: correctness and UX over implementation complexity
2025-11-06 10:27:15 +00:00
rcourtman
5a328637af Improve drawer layout and UX for Docker and Proxmox pages
- Add flex-1 to all drawer cards for consistent space filling
- Implement single-drawer-open behavior (accordion-style)
- Add text truncation to labels and IP badges to prevent overflow
- Replace Map-based state with reactive signals for better performance
2025-11-05 14:46:13 +00:00
rcourtman
6eb1a10d9b Refactor: Code cleanup and localStorage consolidation
This commit includes comprehensive codebase cleanup and refactoring:

## Code Cleanup
- Remove dead TypeScript code (types/monitoring.ts - 194 lines duplicate)
- Remove unused Go functions (GetClusterNodes, MigratePassword, GetClusterHealthInfo)
- Clean up commented-out code blocks across multiple files
- Remove unused TypeScript exports (helpTextClass, private tag color helpers)
- Delete obsolete test files and components

## localStorage Consolidation
- Centralize all storage keys into STORAGE_KEYS constant
- Update 5 files to use centralized keys:
  * utils/apiClient.ts (AUTH, LEGACY_TOKEN)
  * components/Dashboard/Dashboard.tsx (GUEST_METADATA)
  * components/Docker/DockerHosts.tsx (DOCKER_METADATA)
  * App.tsx (PLATFORMS_SEEN)
  * stores/updates.ts (UPDATES)
- Benefits: Single source of truth, prevents typos, better maintainability

## Previous Work Committed
- Docker monitoring improvements and disk metrics
- Security enhancements and setup fixes
- API refactoring and cleanup
- Documentation updates
- Build system improvements

## Testing
- All frontend tests pass (29 tests)
- All Go tests pass (15 packages)
- Production build successful
- Zero breaking changes

Total: 186 files changed, 5825 insertions(+), 11602 deletions(-)
2025-11-04 21:50:46 +00:00
rcourtman
93faaacbd1 Simplify metric bar labels 2025-10-29 10:37:18 +00:00
rcourtman
7ee417a629 Refine grouped guest indentation 2025-10-29 08:43:02 +00:00
rcourtman
b3285c05c8 Consolidate pending changes
- Add Docker metadata test comment
- Update alerts configuration and thresholds
- Enhance config file watcher
- Update documentation
- Refine settings UI
2025-10-28 23:20:44 +00:00
rcourtman
52b0c65977 ui: align tables and docker styling 2025-10-28 18:51:52 +00:00
rcourtman
7733d4b870 Adjust header layout and widen guest name column 2025-10-27 20:55:28 +00:00
rcourtman
1ae4f5bfd8 fix: prevent guest link icon from re-animating on WebSocket updates
The external guest link icon was fading in/out on every WebSocket update,
creating a distracting visual effect. Now the fade-in animation only plays
when the URL first becomes available (initial load or when saving a new URL),
rather than re-triggering on every state update.

- Add fadeIn keyframe animation to Tailwind config
- Track animation state with shouldAnimateIcon signal
- Only animate on transition from no URL to having a URL
- Clear animation flag after 200ms to prevent re-triggering
2025-10-24 09:27:06 +00:00
rcourtman
30b78784e0 Refine inline URL editor event handling
- Add double-checks in global click handlers to prevent race conditions
- Add isCurrentlyMounted flag to prevent cleanup during re-renders
- Remove onBlur handler that was causing premature editor closure
- Simplify conditional logic in click handlers

These changes improve the robustness of the inline editor when
websocket updates occur during editing sessions.
2025-10-23 17:56:58 +00:00
rcourtman
32cd925e1f Fix inline editor persistence during websocket updates
Critical fixes to prevent the inline URL editor from closing during API updates:

1. Implement stable guest store with reconcile:
   - Use createStore with reconcile() to maintain stable object references
   - Key function ensures each guest keeps same proxy instance across updates
   - Prevents <For> loop from remounting rows during websocket updates

2. Allow switching between guest editors:
   - Mark guest name spans with data-guest-name-editable attribute
   - Click handler allows clicking another guest name to switch editors
   - Prevents click consumption when opening a different guest's editor

This ensures the inline editor stays open and preserves user input even when
websocket updates arrive, while still allowing seamless switching between
editing different guests.
2025-10-23 17:45:54 +00:00
rcourtman
15252c95ce Add inline URL editing for guest rows with click-away protection
Redesigned guest URL management from a bulky settings table to streamlined
inline editing directly on the dashboard:

Features:
- Single-click guest name to edit custom URL
- Text cursor indicates editability
- Inline editor with save (✓) and delete (✕) buttons
- Auto-focus and text selection on edit start
- Tag badges hidden during editing to maximize input space
- Click-away closes editor without activating underlying elements

Technical improvements:
- Global editing state prevents multiple simultaneous edits
- Smart click capture intercepts mousedown/click events when editor is open
- Prevents accidental row expansion or other actions during editing
- Delete button (✕) removes URL and icon entirely
- Escape key closes without saving
- Enter key saves and closes
2025-10-23 17:42:40 +00:00