Commit graph

321 commits

Author SHA1 Message Date
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
fcb258ac2d wip: AI provider improvements and chat store enhancements
- Improve Anthropic provider error handling
- Add AI service enhancements
- Update AI chat store with additional state management
2025-12-05 12:14:00 +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
309302a793 fix: StatusDot not updating reactively when VM status changes
The StatusDot component was computing variant, size, and className once
at mount time, not reactively. When a VM transitioned from stopped to
running, the tooltip updated (it accessed props.title directly) but the
dot color stayed red because className was stale.

Fix: Convert plain variable assignments to getter functions that access
props reactively, and call them in the JSX template.
2025-12-05 10:40:03 +00:00
rcourtman
cc3c0187a0 feat: AI features, agent improvements, and host monitoring enhancements
AI Chat Integration:
- Multi-provider support (Anthropic, OpenAI, Ollama)
- Streaming responses with markdown rendering
- Agent command execution for remote troubleshooting
- Context-aware conversations with host/container metadata

Agent Updates:
- Add --enable-proxmox flag for automatic PVE/PBS token setup
- Improve auto-update with semver comparison (prevents downgrades)
- Add updatedFrom tracking to report previous version after update
- Reduce initial update check delay from 30s to 5s
- Add agent version column to Hosts page table

Host Metrics:
- Add DiskIO stats collection (read/write bytes, ops, time)
- Improve disk filtering to exclude Docker overlay mounts
- Add RAID array monitoring via mdadm
- Enhanced temperature sensor parsing

Frontend:
- New Agent Version column on Hosts overview table
- Improved node modal with agent-first installation flow
- Add DiskIO display in host drawer
- Better responsive handling for metric bars
2025-12-05 10:37:02 +00:00
rcourtman
3f08bfe8d0 wip: AI chat integration with multi-provider support
- Add AI service with Anthropic, OpenAI, and Ollama providers
- Add AI chat UI component with streaming responses
- Add AI settings page for configuration
- Add agent exec framework for command execution
- Add API endpoints for AI chat and configuration
2025-12-04 20:16:53 +00:00
rcourtman
d195c8357e fix: Use specific checkbox selector in UnifiedAgents test
The test was using getByRole('checkbox') which now matches multiple
elements after adding the "Skip certificate verification" checkbox.
Use name matcher to select the specific Docker monitoring checkbox.
2025-12-03 14:32:05 +00:00
rcourtman
4585db8a9d feat: Add "Skip certificate verification" option for agent install commands
Adds a checkbox in Settings → Host Agents that enables insecure mode for
users running Pulse behind self-signed HTTPS certificates.

When enabled:
- Adds -k flag to curl commands for downloading the install script
- Adds --insecure flag to the agent for connecting back to Pulse

Related to #806
2025-12-03 14:15:17 +00:00
rcourtman
d3f22f06bf fix: Truncate very long container names in Docker table
Add max-width constraint to the resource column in the Docker table to
ensure very long container names (like Kubernetes UUID-based names) are
properly truncated instead of extending the table width.

Related to #789
2025-12-03 14:09:16 +00:00
rcourtman
93223d8283 Add refresh-cluster button to detect new Proxmox cluster members
When new nodes are added to a Proxmox cluster after Pulse was
initially configured, they weren't showing up in Settings. The
existing "Refresh" button only triggered network discovery, not
cluster membership re-detection.

Changes:
- Add POST /api/config/nodes/{id}/refresh-cluster endpoint
- Add "Refresh" button in cluster node panel in Settings
- Re-detect cluster membership and update stored endpoints

Related to #799
2025-12-02 22:01:00 +00:00
rcourtman
fdf7de29f0 fix: Resolve TypeScript errors in StackedMemoryBar and Settings
StackedMemoryBar.tsx:
- Fixed 'props.balloon' possibly undefined error by adding fallback
  to second comparison in Show condition

Settings.tsx:
- Fixed 'systemSettings' scope error by using updateChannel() signal
  instead of referencing out-of-scope variable from previous try block

Both files now pass strict TypeScript checks.
2025-12-02 20:37:44 +00:00
rcourtman
282a323c10 fix: Update Mail Gateway disconnect state for consistency
Changed from warning (amber) to danger (red) tone and added:
- Dynamic description based on reconnecting status
- Manual "Reconnect now" button when not auto-reconnecting
- Consistent "Connection lost" title

All 7 major pages now have unified connection lost UX:
Dashboard, Storage, Backups, Replication, Hosts, Docker, Mail Gateway
2025-12-02 20:34:32 +00:00
rcourtman
6505ff5edf fix: Add connection lost indicator to Docker page
Docker/Containers page now shows a clear error state when WebSocket
connection is lost, with a manual "Reconnect now" button. This
matches the pattern established across all other major pages.

Connection lost UX is now consistent across: Dashboard, Storage,
Backups, Replication, Hosts, and Docker.
2025-12-02 20:31:59 +00:00
rcourtman
779e4e8a86 fix: Add connection lost indicator to Hosts page
Hosts page now shows a clear error state when WebSocket connection
is lost, with a manual "Reconnect now" button. Also improved loading
state logic to differentiate between initial loading and connection
loss after having received data.

This completes the connection lost UX consistency across all major
pages: Dashboard, Storage, Backups, Replication, and now Hosts.
2025-12-02 20:29:15 +00:00
rcourtman
3a5f0d1c19 fix: Add reconnect button to Backups and Replication pages
Both pages now show a consistent disconnect state with:
- Dynamic description based on reconnecting status
- Manual "Reconnect now" button when not auto-reconnecting

This matches the Dashboard and Storage page behavior, providing a
consistent UX across all main pages when connection is lost.
2025-12-02 20:24:34 +00:00
rcourtman
2cec2215f1 fix: Add connection lost indicator to Storage page
Storage page now shows a clear error state when WebSocket connection
is lost, matching the Dashboard's behavior. Users see the issue and
can manually reconnect instead of wondering why data isn't updating.
2025-12-02 20:20:39 +00:00
rcourtman
1d188db11f fix: Correct lastBackup TypeScript type from string to number
The backend sends lastBackup as Unix milliseconds (int64), not as an
ISO string. Update VM and Container interfaces to match the actual
JSON payload.

The getBackupInfo() function already handles both string and number
types, so this is a type-safety fix that aligns types with reality.
2025-12-02 20:15:35 +00:00
rcourtman
1a9d15b1c1 chore: Remove unused usePersistentSignal import
Cleanup from Settings sidebar change - the import was left behind
when switching from usePersistentSignal to createSignal.
2025-12-02 20:09:54 +00:00
rcourtman
42766be8cc fix: Settings sidebar always starts expanded for discoverability
The sidebar no longer persists its collapsed state to localStorage.
Each visit to Settings starts with the sidebar expanded, showing
all menu labels for better discoverability by new users.

Users can still collapse the sidebar during their session if they
want more space, but it will reset to expanded on page reload.

Related to #764
2025-12-02 20:03:54 +00:00
rcourtman
b70a4eba9d feat: Add 'Needs Backup' filter to Dashboard
Add a new filter button that shows only guests with stale, critical,
or missing backups. This makes it easy to identify which VMs and
containers need attention for backup scheduling.

- Adds backupMode state with 'all' and 'needs-backup' options
- Filters out templates (they don't need backups)
- Uses existing getBackupInfo() thresholds (>24h stale, >72h critical)
- Integrates with Reset button and Escape key handling
- Persists filter state in localStorage

Related to #762
2025-12-02 20:00:33 +00:00
rcourtman
6c76823754 fix: Constrain Docker drawer width to force card wrapping
The previous fix (2078421d) added overflow-hidden but didn't address
the root cause: the drawer div inside overflow-x-auto context had no
width constraint, so flex-wrap saw infinite space and didn't wrap.

Adding w-0 min-w-full forces the div to take exactly 100% of parent
width, which properly constrains flex-wrap to wrap cards within the
visible viewport.

Related to #789
2025-12-02 18:02:28 +00:00
rcourtman
53a2c2a587 fix: Prevent agent type badge flapping in UnifiedAgents view
Track previously seen host types and preserve them when one data source
temporarily has no entry for a hostname. This prevents the "Host" or
"Docker" type badge from disappearing and reappearing when websocket
updates cause momentary state inconsistencies.

The fix only preserves types if the corresponding source array has any
data at all, ensuring that intentional host removal (both arrays empty
for that host) still works correctly.

Related to #773
2025-12-02 11:29:03 +00:00
rcourtman
99a6debd3a fix: Update Channel setting not persisting after save
The Update Channel dropdown reverted to "stable" after saving because the
frontend was overwriting the user's saved preference with the running
version's channel. Now the saved setting takes priority over the detected
channel.

Related to #738
2025-12-02 03:03:51 +00:00
rcourtman
aec63b7abd Fix memory bar width showing 100% instead of actual percentage
The StackedMemoryBar component was incorrectly calculating segments when
Proxmox balloon was set to maxmem (no actual ballooning). In this case:
- balloon = total (e.g., 32GB)
- used = actual memory (e.g., 20GB)
- active = used - balloon = 20GB - 32GB = 0 (clamped)
- balloonPercent = 32GB/32GB * 100 = 100%

This caused the bar to always show 100% yellow (balloon) even when the
actual memory usage was much lower.

Fixed by only showing balloon segment when actual ballooning is in effect
(balloon > 0 && balloon < total). When there's no ballooning, the bar
now correctly shows used memory as green with the actual percentage.

Related to #788
2025-12-02 00:08:05 +00:00
rcourtman
2078421da4 Fix Docker expanded drawer cards being cut off
The expanded container/service drawer cards were overflowing
horizontally instead of wrapping when the table had overflow-x-auto.
Adding overflow-hidden to the drawer's outer container forces the
flex-wrap to work correctly.

Related to #789
2025-12-01 15:06:49 +00:00
rcourtman
32ffc1046c Fix memory bar width not scaling correctly
The StackedMemoryBar component was using flex layout for segments,
but flex children grow by default regardless of percentage width.
Changed to absolute positioning (like MetricBar uses) so the width
percentages actually work as expected.

Related to #788
2025-11-30 23:46:56 +00:00
rcourtman
6c1a0815ea Fix host agent type badge flapping in UI
Add transient empty payload protection for hosts data, matching the
existing protection for dockerHosts. When a websocket message contains
an empty hosts array (transient state), the UI now waits for 3
consecutive empty payloads before applying the change.

This prevents the "Host" type badge from disappearing intermittently
in Settings → Agents → Managed Agents when the unified agent is
reporting both host and docker data.

Related to #773
2025-11-30 22:07:40 +00:00
rcourtman
6ae7ed4ae0 Add pagination to backup list for large backup counts
- Add pagination (100 items per page) to prevent UI lockup with 2500+ backups
- Show year in date labels for non-current year backups
- Reset to page 1 when filters change
- Add First/Previous/Next/Last navigation controls

Fixes #541
2025-11-30 09:55:01 +00:00
rcourtman
949d54905c Remove CPU capacity marker and highlight high container restarts
- Remove load average marker from CPU progress bar (confusing, not useful)
- Keep load average in tooltip only
- Highlight container restart count in red when >5 (indicates instability)
2025-11-29 22:37:17 +00:00
rcourtman
e2cdcb7b3e Match original sublabel style for CPU core count display 2025-11-29 21:49:00 +00:00
rcourtman
46f90e1585 Show CPU core count on EnhancedCPUBar progress bar 2025-11-29 21:47:22 +00:00
rcourtman
02d8d8a9f9 Use left-aligned headers consistently in Docker table 2025-11-29 21:31:44 +00:00
rcourtman
f2983634e5 Center CPU and Memory cells in Docker container/service rows 2025-11-29 21:27:25 +00:00
rcourtman
c7184a1327 Center CPU and Memory column headers in Docker table 2025-11-29 21:25:08 +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
rcourtman
fbabace023 Fix SolidJS proxy error in batched WebSocket updates
Using reconcile() inside produce() is invalid - reconcile returns a
function that creates a new proxy, but produce expects direct mutations.
Use batch() from solid-js instead to atomically batch the two setState
calls without proxy conflicts.
2025-11-29 18:54:22 +00:00
rcourtman
8bc8a98bb8 Remove unused usagePercent variable in Storage.tsx 2025-11-29 18:46:14 +00:00
rcourtman
67519304f9 Fix agent type flapping in Settings/Agents page
When a unified agent reports both host and docker data, the WebSocket
handler was calling setState separately for dockerHosts and hosts.
This caused the UnifiedAgents component's allHosts memo to recalculate
twice - first seeing only the updated dockerHosts (showing "Docker"),
then seeing both (showing "Host & Docker").

Batch both updates into a single setState call using produce() when
both are present in the same message, ensuring the component always
sees consistent data.

Related to #778
2025-11-29 18:06:41 +00:00
courtmanr@gmail.com
a8911b0f32 Add EnhancedStorageBar component with ZFS status visualization
- Create EnhancedStorageBar component to show storage usage with ZFS integration
- Animated overlay for active scrubbing/resilvering operations
- Red pulse border indicator for pools with errors
- Detailed tooltip showing ZFS state, scan status, and error counts
- Replace static progress bar in Storage.tsx with EnhancedStorageBar
- Remove unused getProgressBarColor function
2025-11-29 17:32:54 +00:00
courtmanr@gmail.com
3ed190e8bc Add EnhancedCPUBar component with Load Average visualization
- Create EnhancedCPUBar component to show CPU usage with Load Average overlay
- Add vertical marker indicating 1-minute Load Average relative to core count
- Purple glow indicator when Load > Cores (system overload)
- Detailed tooltip showing Usage, Load, and Capacity metrics
- Full sparkline mode support for historical view
- Integrate into NodeSummaryTable for Proxmox nodes
- Integrate into DockerHostSummaryTable for Docker hosts
- Integrate into HostsOverview for standalone hosts
2025-11-29 15:15:38 +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
courtmanr@gmail.com
6852004ffb feat: add stacked disk bar to hosts overview and fix tooltip positioning
- Replace standard disk metric bar with StackedDiskBar in HostsOverview
    - Show detailed per-disk usage breakdown on hover
    - Use Portal for tooltips to ensure correct positioning and z-index
    - Add class prop support to MetricBar
2025-11-28 22:10:15 +00:00
rcourtman
4de209b8a1 Fix TypeScript errors in Login.tsx and UnifiedAgents.tsx 2025-11-28 20:16:31 +00:00
rcourtman
d93e17e898 Fix settings sidebar width causing status icons to wrap
Revert expanded width from w-64 (256px) to w-72 (288px) and min/max
from 16rem to 18rem. The reduction in commit 6333a445 caused PVE node
status icons to wrap to two lines.

Related to #764
2025-11-28 15:07:42 +00:00
rcourtman
f9bd09a2b4 Add UI for removed Docker hosts re-enrollment
Adds a "Removed Docker Hosts" section to Settings -> Agents that displays
hosts blocked from re-enrolling and provides an "Allow re-enroll" button.
The backend API already existed; this adds the missing frontend component.

Related to #773
2025-11-28 12:07:28 +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
rcourtman
8afc4d0c6c Fix hideLocalLogin toggle persistence and login page UI
- Add hideLocalLogin handler in HandleUpdateSystemSettings() so the
  toggle setting is saved to system.json
- Conditionally hide "or" divider and admin credentials message when
  local login is hidden

Related to #750
2025-11-28 09:05:41 +00:00