[PULSE-47] Add uptime monitoring dashboard #15

Merged
uz1mani merged 6 commits from staging into main 2026-02-07 22:38:13 +00:00
uz1mani commented 2026-02-07 21:55:40 +00:00 (Migrated from github.com)

Work Item

PULSE-47

Summary

  • Add full uptime monitoring page with 90-day status bar visualization, response time charts, styled tooltips, and monitor CRUD
  • URL input uses protocol dropdown + domain prefix (like UTM builder), restricted to site's own domain
  • Overall status card shows "All Systems Operational" / "Partial Outage" / "Major Outage" text

Changes

  • lib/api/uptime.ts — TypeScript API client with types for monitors, checks, daily stats, and status response; functions for all uptime endpoints
  • app/sites/[id]/uptime/page.tsx — Full uptime page:
    • Overall status card with colored status dot and text label
    • Per-monitor cards with 90-day colored status bars (green/amber/red/gray)
    • Styled hover tooltips showing date, uptime %, check count, avg response time
    • Expandable details with response time area chart (Recharts) and recent checks list
    • Monitor CRUD modals with protocol dropdown (https:// / http://) + domain prefix URL input
    • Hidden number input spinners on Expected Status Code and Timeout fields
    • No-data days rendered as visible neutral gray bars
    • Auto-refresh every 30 seconds
  • app/sites/[id]/page.tsx — Added "Uptime" navigation button to dashboard header

Test Plan

  • Navigate to Uptime page — verify overall status card shows status text and uptime %
  • Hover over status bar days — verify styled tooltip with date, uptime %, checks, avg response time
  • Expand a monitor — verify response time area chart renders correctly
  • Click "Add Monitor" — verify URL field shows protocol dropdown + domain prefix + path input
  • Try adding a path like /api/health — verify full URL is constructed correctly
  • Verify no spinner arrows on Expected Status Code and Timeout inputs
  • Verify no-data days show as visible gray bars (not invisible)
  • Edit and delete a monitor — verify modals and data refresh work
  • Wait 30 seconds — verify auto-refresh updates data without page reload
## Work Item PULSE-47 ## Summary - Add full uptime monitoring page with 90-day status bar visualization, response time charts, styled tooltips, and monitor CRUD - URL input uses protocol dropdown + domain prefix (like UTM builder), restricted to site's own domain - Overall status card shows "All Systems Operational" / "Partial Outage" / "Major Outage" text ## Changes - **`lib/api/uptime.ts`** — TypeScript API client with types for monitors, checks, daily stats, and status response; functions for all uptime endpoints - **`app/sites/[id]/uptime/page.tsx`** — Full uptime page: - Overall status card with colored status dot and text label - Per-monitor cards with 90-day colored status bars (green/amber/red/gray) - Styled hover tooltips showing date, uptime %, check count, avg response time - Expandable details with response time area chart (Recharts) and recent checks list - Monitor CRUD modals with protocol dropdown (`https://` / `http://`) + domain prefix URL input - Hidden number input spinners on Expected Status Code and Timeout fields - No-data days rendered as visible neutral gray bars - Auto-refresh every 30 seconds - **`app/sites/[id]/page.tsx`** — Added "Uptime" navigation button to dashboard header ## Test Plan - [x] Navigate to Uptime page — verify overall status card shows status text and uptime % - [x] Hover over status bar days — verify styled tooltip with date, uptime %, checks, avg response time - [x] Expand a monitor — verify response time area chart renders correctly - [x] Click "Add Monitor" — verify URL field shows protocol dropdown + domain prefix + path input - [x] Try adding a path like `/api/health` — verify full URL is constructed correctly - [x] Verify no spinner arrows on Expected Status Code and Timeout inputs - [x] Verify no-data days show as visible gray bars (not invisible) - [x] Edit and delete a monitor — verify modals and data refresh work - [x] Wait 30 seconds — verify auto-refresh updates data without page reload
greptile-apps[bot] commented 2026-02-07 21:58:56 +00:00 (Migrated from github.com)

Greptile Overview

Greptile Summary

This PR implements a comprehensive uptime monitoring dashboard for PULSE-47, adding the ability to track endpoint availability and response times over a 90-day period.

Key Changes

  • API Client (lib/api/uptime.ts): Added TypeScript client with well-defined types for monitors, checks, and daily stats. All API functions follow existing patterns in the codebase.
  • Uptime Dashboard (app/sites/[id]/uptime/page.tsx): Implemented full-featured monitoring page with:
    • Overall status card showing "All Systems Operational" / "Partial Outage" / "Major Outage"
    • Per-monitor cards with 90-day colored status bars (green/amber/red/gray)
    • Interactive tooltips showing date, uptime %, check count, and avg response time
    • Expandable monitor details with Recharts area chart for response time visualization
    • Monitor CRUD modals with protocol dropdown + domain-prefixed URL input
    • 30-second auto-refresh for live updates
    • Hidden number input spinners for Expected Status Code and Timeout fields
  • Navigation (app/sites/[id]/page.tsx): Added "Uptime" button to site dashboard header for quick access

Code Quality

  • Follows existing codebase patterns (similar to stats API and dashboard components)
  • Proper TypeScript types throughout
  • Responsive design with dark mode support
  • Clean separation of concerns with reusable sub-components

Minor Issues Found

  • ESLint exhaustive-deps rule disabled in one useEffect (line 906) - should include all dependencies
  • Silent failure on auto-refresh could leave stale data without user awareness
  • Uses native confirm() dialog instead of custom modal for delete confirmation

Confidence Score: 4/5

  • This PR is safe to merge with minor style improvements recommended
  • Score of 4 reflects high-quality implementation following existing codebase patterns, with only minor style issues: disabled ESLint rule, silent auto-refresh failure, and native confirm dialog usage. No logic errors or security vulnerabilities found. The implementation is comprehensive, well-typed, and includes proper error handling.
  • app/sites/[id]/uptime/page.tsx - address ESLint warning and consider improving auto-refresh error visibility

Important Files Changed

Filename Overview
lib/api/uptime.ts Added comprehensive TypeScript API client for uptime monitoring with proper types and error handling
app/sites/[id]/uptime/page.tsx Implemented full uptime dashboard with visualization, charts, and CRUD operations; has dependency on exhaustive-deps and potential state initialization issue
app/sites/[id]/page.tsx Added Uptime navigation button to dashboard header

Sequence Diagram

sequenceDiagram
    participant User
    participant Browser
    participant UptimePage
    participant API
    participant Backend

    User->>Browser: Navigate to /sites/{id}/uptime
    Browser->>UptimePage: Load page component
    
    UptimePage->>API: getSite(siteId)
    UptimePage->>API: getUptimeStatus(siteId)
    API->>Backend: GET /api/v1/sites/{id}
    API->>Backend: GET /api/v1/sites/{id}/uptime/status
    Backend-->>API: Return site and uptime data
    API-->>UptimePage: Site + UptimeStatusResponse
    
    UptimePage->>Browser: Render overall status card
    UptimePage->>Browser: Render monitor cards with 90-day bars
    
    Note over UptimePage: Auto-refresh every 30s
    loop Every 30 seconds
        UptimePage->>API: getUptimeStatus(siteId)
        API->>Backend: GET /api/v1/sites/{id}/uptime/status
        Backend-->>API: Updated status
        API-->>UptimePage: Fresh data
        UptimePage->>Browser: Update UI
    end
    
    User->>UptimePage: Hover over status bar day
    UptimePage->>Browser: Show tooltip with stats
    
    User->>UptimePage: Click to expand monitor
    UptimePage->>API: getMonitorChecks(siteId, monitorId)
    API->>Backend: GET /api/v1/sites/{id}/uptime/monitors/{id}/checks
    Backend-->>API: Recent checks list
    API-->>UptimePage: UptimeCheck[]
    UptimePage->>Browser: Render response time chart
    
    User->>UptimePage: Click "Add Monitor"
    UptimePage->>Browser: Open modal with form
    User->>UptimePage: Fill form (protocol + domain + path)
    User->>UptimePage: Submit form
    UptimePage->>API: createUptimeMonitor(siteId, data)
    API->>Backend: POST /api/v1/sites/{id}/uptime/monitors
    Backend-->>API: New monitor created
    API-->>UptimePage: UptimeMonitor
    UptimePage->>API: getUptimeStatus(siteId)
    API->>Backend: GET /api/v1/sites/{id}/uptime/status
    Backend-->>API: Updated status
    API-->>UptimePage: Refresh data
    UptimePage->>Browser: Close modal, show success toast
    
    User->>UptimePage: Edit monitor
    UptimePage->>API: updateUptimeMonitor(siteId, monitorId, data)
    API->>Backend: PUT /api/v1/sites/{id}/uptime/monitors/{id}
    Backend-->>API: Updated monitor
    API-->>UptimePage: Updated data
    
    User->>UptimePage: Delete monitor
    UptimePage->>Browser: Show confirmation dialog
    User->>UptimePage: Confirm deletion
    UptimePage->>API: deleteUptimeMonitor(siteId, monitorId)
    API->>Backend: DELETE /api/v1/sites/{id}/uptime/monitors/{id}
    Backend-->>API: Deletion success
    API-->>UptimePage: Void
    UptimePage->>Browser: Show success toast, refresh list
<h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR implements a comprehensive uptime monitoring dashboard for PULSE-47, adding the ability to track endpoint availability and response times over a 90-day period. ## Key Changes - **API Client** (`lib/api/uptime.ts`): Added TypeScript client with well-defined types for monitors, checks, and daily stats. All API functions follow existing patterns in the codebase. - **Uptime Dashboard** (`app/sites/[id]/uptime/page.tsx`): Implemented full-featured monitoring page with: - Overall status card showing "All Systems Operational" / "Partial Outage" / "Major Outage" - Per-monitor cards with 90-day colored status bars (green/amber/red/gray) - Interactive tooltips showing date, uptime %, check count, and avg response time - Expandable monitor details with Recharts area chart for response time visualization - Monitor CRUD modals with protocol dropdown + domain-prefixed URL input - 30-second auto-refresh for live updates - Hidden number input spinners for Expected Status Code and Timeout fields - **Navigation** (`app/sites/[id]/page.tsx`): Added "Uptime" button to site dashboard header for quick access ## Code Quality - Follows existing codebase patterns (similar to stats API and dashboard components) - Proper TypeScript types throughout - Responsive design with dark mode support - Clean separation of concerns with reusable sub-components ## Minor Issues Found - ESLint exhaustive-deps rule disabled in one `useEffect` (line 906) - should include all dependencies - Silent failure on auto-refresh could leave stale data without user awareness - Uses native `confirm()` dialog instead of custom modal for delete confirmation <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with minor style improvements recommended - Score of 4 reflects high-quality implementation following existing codebase patterns, with only minor style issues: disabled ESLint rule, silent auto-refresh failure, and native confirm dialog usage. No logic errors or security vulnerabilities found. The implementation is comprehensive, well-typed, and includes proper error handling. - app/sites/[id]/uptime/page.tsx - address ESLint warning and consider improving auto-refresh error visibility <details><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | lib/api/uptime.ts | Added comprehensive TypeScript API client for uptime monitoring with proper types and error handling | | app/sites/[id]/uptime/page.tsx | Implemented full uptime dashboard with visualization, charts, and CRUD operations; has dependency on exhaustive-deps and potential state initialization issue | | app/sites/[id]/page.tsx | Added Uptime navigation button to dashboard header | </details> </details> <h3>Sequence Diagram</h3> ```mermaid sequenceDiagram participant User participant Browser participant UptimePage participant API participant Backend User->>Browser: Navigate to /sites/{id}/uptime Browser->>UptimePage: Load page component UptimePage->>API: getSite(siteId) UptimePage->>API: getUptimeStatus(siteId) API->>Backend: GET /api/v1/sites/{id} API->>Backend: GET /api/v1/sites/{id}/uptime/status Backend-->>API: Return site and uptime data API-->>UptimePage: Site + UptimeStatusResponse UptimePage->>Browser: Render overall status card UptimePage->>Browser: Render monitor cards with 90-day bars Note over UptimePage: Auto-refresh every 30s loop Every 30 seconds UptimePage->>API: getUptimeStatus(siteId) API->>Backend: GET /api/v1/sites/{id}/uptime/status Backend-->>API: Updated status API-->>UptimePage: Fresh data UptimePage->>Browser: Update UI end User->>UptimePage: Hover over status bar day UptimePage->>Browser: Show tooltip with stats User->>UptimePage: Click to expand monitor UptimePage->>API: getMonitorChecks(siteId, monitorId) API->>Backend: GET /api/v1/sites/{id}/uptime/monitors/{id}/checks Backend-->>API: Recent checks list API-->>UptimePage: UptimeCheck[] UptimePage->>Browser: Render response time chart User->>UptimePage: Click "Add Monitor" UptimePage->>Browser: Open modal with form User->>UptimePage: Fill form (protocol + domain + path) User->>UptimePage: Submit form UptimePage->>API: createUptimeMonitor(siteId, data) API->>Backend: POST /api/v1/sites/{id}/uptime/monitors Backend-->>API: New monitor created API-->>UptimePage: UptimeMonitor UptimePage->>API: getUptimeStatus(siteId) API->>Backend: GET /api/v1/sites/{id}/uptime/status Backend-->>API: Updated status API-->>UptimePage: Refresh data UptimePage->>Browser: Close modal, show success toast User->>UptimePage: Edit monitor UptimePage->>API: updateUptimeMonitor(siteId, monitorId, data) API->>Backend: PUT /api/v1/sites/{id}/uptime/monitors/{id} Backend-->>API: Updated monitor API-->>UptimePage: Updated data User->>UptimePage: Delete monitor UptimePage->>Browser: Show confirmation dialog User->>UptimePage: Confirm deletion UptimePage->>API: deleteUptimeMonitor(siteId, monitorId) API->>Backend: DELETE /api/v1/sites/{id}/uptime/monitors/{id} Backend-->>API: Deletion success API-->>UptimePage: Void UptimePage->>Browser: Show success toast, refresh list ```
greptile-apps[bot] (Migrated from github.com) reviewed 2026-02-07 21:59:06 +00:00
greptile-apps[bot] (Migrated from github.com) left a comment

3 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

<sub>3 files reviewed, 3 comments</sub> <sub>[Edit Code Review Agent Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews)</sub>
@@ -0,0 +1,1055 @@
'use client'
greptile-apps[bot] (Migrated from github.com) commented 2026-02-07 21:59:05 +00:00

use window.confirm instead of native confirm for better compatibility and clarity

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/sites/[id]/uptime/page.tsx
Line: 682:682

Comment:
use `window.confirm` instead of native `confirm` for better compatibility and clarity

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.
use `window.confirm` instead of native `confirm` for better compatibility and clarity <sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub> <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: app/sites/[id]/uptime/page.tsx Line: 682:682 Comment: use `window.confirm` instead of native `confirm` for better compatibility and clarity <sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub> How can I resolve this? If you propose a fix, please make it concise. ````` </details>
@@ -0,0 +637,4 @@
}
}, 30000)
return () => clearInterval(interval)
}, [siteId])
greptile-apps[bot] (Migrated from github.com) commented 2026-02-07 21:59:04 +00:00

auto-refresh will silently fail if user loses network connection or auth token expires, leaving stale data visible without indication to user. Consider adding visual feedback or error handling

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/sites/[id]/uptime/page.tsx
Line: 627:637

Comment:
auto-refresh will silently fail if user loses network connection or auth token expires, leaving stale data visible without indication to user. Consider adding visual feedback or error handling

How can I resolve this? If you propose a fix, please make it concise.
auto-refresh will silently fail if user loses network connection or auth token expires, leaving stale data visible without indication to user. Consider adding visual feedback or error handling <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: app/sites/[id]/uptime/page.tsx Line: 627:637 Comment: auto-refresh will silently fail if user loses network connection or auth token expires, leaving stale data visible without indication to user. Consider adding visual feedback or error handling How can I resolve this? If you propose a fix, please make it concise. ````` </details>
@@ -0,0 +907,4 @@
setFormData({ ...formData, url: `${protocol}${siteDomain}` })
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
greptile-apps[bot] (Migrated from github.com) commented 2026-02-07 21:59:03 +00:00

disabling exhaustive-deps can lead to stale closure bugs

  useEffect(() => {
    if (!formData.url) {
      setFormData({ ...formData, url: `${protocol}${siteDomain}` })
    }
  }, [formData, protocol, siteDomain, setFormData])
Prompt To Fix With AI
This is a comment left during a code review.
Path: app/sites/[id]/uptime/page.tsx
Line: 906:911

Comment:
disabling exhaustive-deps can lead to stale closure bugs

```suggestion
  useEffect(() => {
    if (!formData.url) {
      setFormData({ ...formData, url: `${protocol}${siteDomain}` })
    }
  }, [formData, protocol, siteDomain, setFormData])
```

How can I resolve this? If you propose a fix, please make it concise.
disabling exhaustive-deps can lead to stale closure bugs ```suggestion useEffect(() => { if (!formData.url) { setFormData({ ...formData, url: `${protocol}${siteDomain}` }) } }, [formData, protocol, siteDomain, setFormData]) ``` <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: app/sites/[id]/uptime/page.tsx Line: 906:911 Comment: disabling exhaustive-deps can lead to stale closure bugs ```suggestion useEffect(() => { if (!formData.url) { setFormData({ ...formData, url: `${protocol}${siteDomain}` }) } }, [formData, protocol, siteDomain, setFormData]) ``` How can I resolve this? If you propose a fix, please make it concise. ````` </details>
uz1mani (Migrated from github.com) reviewed 2026-02-07 22:02:48 +00:00
@@ -0,0 +907,4 @@
setFormData({ ...formData, url: `${protocol}${siteDomain}` })
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
uz1mani (Migrated from github.com) commented 2026-02-07 22:02:48 +00:00

Already fixed in the backend

Already fixed in the backend
greptile-apps[bot] commented 2026-02-07 22:03:05 +00:00 (Migrated from github.com)

Greptile Overview

Greptile Summary

This PR adds an uptime monitoring dashboard under /sites/:id/uptime, including an overall status card, per-monitor 90‑day status bars with hover tooltips, expandable response-time charts + recent checks, and monitor CRUD modals with a protocol dropdown + site-domain-prefixed URL builder. It also adds an "Uptime" navigation button to the main site dashboard header.

Main issues to address before merge are in the new uptime page: it assumes uptimeData.monitors is always an array, but the API client types it as nullable and the current ?? [] usage won’t prevent null from flowing into monitors.length/map, which can crash rendering. Separately, the status bar hover logic clears the wrong state on mouse leave, causing the tooltip to remain visible after hover ends.

Confidence Score: 3/5

  • This PR is close to mergeable but has a couple of user-visible runtime issues in the new uptime page that should be fixed first.
  • Most changes are additive and localized, but monitors: null can crash rendering and the tooltip hover state currently leaves tooltips stuck open; both are straightforward fixes but should be addressed before merging.
  • app/sites/[id]/uptime/page.tsx

Important Files Changed

Filename Overview
app/sites/[id]/page.tsx Adds an "Uptime" navigation button to the site dashboard header.
lib/api/uptime.ts Introduces uptime API client types and CRUD/status/check endpoints; note monitors is typed nullable which the UI must handle safely.
app/sites/[id]/uptime/page.tsx Adds full uptime monitoring page with status bar tooltips, charts, and monitor CRUD; has a render crash when API returns monitors: null and a tooltip hover-state bug that leaves tooltips stuck open.

Sequence Diagram

sequenceDiagram
  participant U as User
  participant P as UptimePage (app/sites/[id]/uptime/page.tsx)
  participant Sites as Sites API (getSite)
  participant Uptime as Uptime API (lib/api/uptime.ts)

  U->>P: Navigate /sites/:id/uptime
  activate P
  P->>Sites: getSite(siteId)
  P->>Uptime: getUptimeStatus(siteId)
  Sites-->>P: Site
  Uptime-->>P: UptimeStatusResponse
  P-->>U: Render status + monitor cards

  loop every 30s
    P->>Uptime: getUptimeStatus(siteId)
    Uptime-->>P: UptimeStatusResponse
    P-->>U: Update UI
  end

  alt Expand monitor
    U->>P: Click monitor header
    P->>Uptime: getMonitorChecks(siteId, monitorId, 50)
    Uptime-->>P: checks[]
    P-->>U: Render chart + recent checks
  end

  alt Create monitor
    U->>P: Submit Add Monitor modal
    P->>Uptime: createUptimeMonitor(siteId, data)
    Uptime-->>P: UptimeMonitor
    P->>Uptime: getUptimeStatus(siteId)
    Uptime-->>P: UptimeStatusResponse
    P-->>U: Updated list
  end

  alt Update monitor
    U->>P: Submit Edit Monitor modal
    P->>Uptime: updateUptimeMonitor(siteId, monitorId, data)
    Uptime-->>P: UptimeMonitor
    P->>Uptime: getUptimeStatus(siteId)
    Uptime-->>P: UptimeStatusResponse
    P-->>U: Updated list
  end

  alt Delete monitor
    U->>P: Confirm deletion
    P->>Uptime: deleteUptimeMonitor(siteId, monitorId)
    Uptime-->>P: 204/OK
    P->>Uptime: getUptimeStatus(siteId)
    Uptime-->>P: UptimeStatusResponse
    P-->>U: Updated list
  end

  deactivate P
<h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adds an uptime monitoring dashboard under `/sites/:id/uptime`, including an overall status card, per-monitor 90‑day status bars with hover tooltips, expandable response-time charts + recent checks, and monitor CRUD modals with a protocol dropdown + site-domain-prefixed URL builder. It also adds an "Uptime" navigation button to the main site dashboard header. Main issues to address before merge are in the new uptime page: it assumes `uptimeData.monitors` is always an array, but the API client types it as nullable and the current `?? []` usage won’t prevent `null` from flowing into `monitors.length`/`map`, which can crash rendering. Separately, the status bar hover logic clears the wrong state on mouse leave, causing the tooltip to remain visible after hover ends. <h3>Confidence Score: 3/5</h3> - This PR is close to mergeable but has a couple of user-visible runtime issues in the new uptime page that should be fixed first. - Most changes are additive and localized, but `monitors: null` can crash rendering and the tooltip hover state currently leaves tooltips stuck open; both are straightforward fixes but should be addressed before merging. - app/sites/[id]/uptime/page.tsx <details><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | app/sites/[id]/page.tsx | Adds an "Uptime" navigation button to the site dashboard header. | | lib/api/uptime.ts | Introduces uptime API client types and CRUD/status/check endpoints; note `monitors` is typed nullable which the UI must handle safely. | | app/sites/[id]/uptime/page.tsx | Adds full uptime monitoring page with status bar tooltips, charts, and monitor CRUD; has a render crash when API returns `monitors: null` and a tooltip hover-state bug that leaves tooltips stuck open. | </details> </details> <h3>Sequence Diagram</h3> ```mermaid sequenceDiagram participant U as User participant P as UptimePage (app/sites/[id]/uptime/page.tsx) participant Sites as Sites API (getSite) participant Uptime as Uptime API (lib/api/uptime.ts) U->>P: Navigate /sites/:id/uptime activate P P->>Sites: getSite(siteId) P->>Uptime: getUptimeStatus(siteId) Sites-->>P: Site Uptime-->>P: UptimeStatusResponse P-->>U: Render status + monitor cards loop every 30s P->>Uptime: getUptimeStatus(siteId) Uptime-->>P: UptimeStatusResponse P-->>U: Update UI end alt Expand monitor U->>P: Click monitor header P->>Uptime: getMonitorChecks(siteId, monitorId, 50) Uptime-->>P: checks[] P-->>U: Render chart + recent checks end alt Create monitor U->>P: Submit Add Monitor modal P->>Uptime: createUptimeMonitor(siteId, data) Uptime-->>P: UptimeMonitor P->>Uptime: getUptimeStatus(siteId) Uptime-->>P: UptimeStatusResponse P-->>U: Updated list end alt Update monitor U->>P: Submit Edit Monitor modal P->>Uptime: updateUptimeMonitor(siteId, monitorId, data) Uptime-->>P: UptimeMonitor P->>Uptime: getUptimeStatus(siteId) Uptime-->>P: UptimeStatusResponse P-->>U: Updated list end alt Delete monitor U->>P: Confirm deletion P->>Uptime: deleteUptimeMonitor(siteId, monitorId) Uptime-->>P: 204/OK P->>Uptime: getUptimeStatus(siteId) Uptime-->>P: UptimeStatusResponse P-->>U: Updated list end deactivate P ```
uz1mani (Migrated from github.com) reviewed 2026-02-07 22:03:07 +00:00
@@ -0,0 +637,4 @@
}
}, 30000)
return () => clearInterval(interval)
}, [siteId])
uz1mani (Migrated from github.com) commented 2026-02-07 22:03:07 +00:00

Issue: Auto-refresh could fail silently on network loss or auth expiry, leaving stale data with no indication.
Fix: On refresh failure we now call toast.error(...) so the user sees “Could not refresh uptime data. Check your connection or sign in again.”
Why: Users need feedback when background refresh fails so they know data may be stale and can reconnect or re-auth.

Issue: Auto-refresh could fail silently on network loss or auth expiry, leaving stale data with no indication. Fix: On refresh failure we now call toast.error(...) so the user sees “Could not refresh uptime data. Check your connection or sign in again.” Why: Users need feedback when background refresh fails so they know data may be stale and can reconnect or re-auth.
greptile-apps[bot] (Migrated from github.com) reviewed 2026-02-07 22:03:11 +00:00
greptile-apps[bot] (Migrated from github.com) left a comment

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

<sub>3 files reviewed, 2 comments</sub> <sub>[Edit Code Review Agent Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews)</sub>
@@ -0,0 +1,1055 @@
'use client'
greptile-apps[bot] (Migrated from github.com) commented 2026-02-07 22:03:09 +00:00

Null monitors breaks render

UptimeStatusResponse.monitors is typed as MonitorStatus[] | null (see lib/api/uptime.ts), but the page does const monitors = uptimeData?.monitors ?? [] and then calls monitors.length / monitors.map(...). If the API returns monitors: null, this becomes null (because ?? doesn’t coalesce inside the optional chain) and will throw at render.

Also appears at app/sites/[id]/uptime/page.tsx:749 (uses monitors.length > 0).

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/sites/[id]/uptime/page.tsx
Line: 707:709

Comment:
**Null monitors breaks render**

`UptimeStatusResponse.monitors` is typed as `MonitorStatus[] | null` (see `lib/api/uptime.ts`), but the page does `const monitors = uptimeData?.monitors ?? []` and then calls `monitors.length` / `monitors.map(...)`. If the API returns `monitors: null`, this becomes `null` (because `??` doesn’t coalesce inside the optional chain) and will throw at render.

Also appears at `app/sites/[id]/uptime/page.tsx:749` (uses `monitors.length > 0`).

How can I resolve this? If you propose a fix, please make it concise.
**Null monitors breaks render** `UptimeStatusResponse.monitors` is typed as `MonitorStatus[] | null` (see `lib/api/uptime.ts`), but the page does `const monitors = uptimeData?.monitors ?? []` and then calls `monitors.length` / `monitors.map(...)`. If the API returns `monitors: null`, this becomes `null` (because `??` doesn’t coalesce inside the optional chain) and will throw at render. Also appears at `app/sites/[id]/uptime/page.tsx:749` (uses `monitors.length > 0`). <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: app/sites/[id]/uptime/page.tsx Line: 707:709 Comment: **Null monitors breaks render** `UptimeStatusResponse.monitors` is typed as `MonitorStatus[] | null` (see `lib/api/uptime.ts`), but the page does `const monitors = uptimeData?.monitors ?? []` and then calls `monitors.length` / `monitors.map(...)`. If the API returns `monitors: null`, this becomes `null` (because `??` doesn’t coalesce inside the optional chain) and will throw at render. Also appears at `app/sites/[id]/uptime/page.tsx:749` (uses `monitors.length > 0`). How can I resolve this? If you propose a fix, please make it concise. ````` </details>
@@ -0,0 +248,4 @@
const handleMouseEnter = (e: React.MouseEvent, date: string, stat: UptimeDailyStat | undefined) => {
const rect = (e.target as HTMLElement).getBoundingClientRect()
setTooltipPos({ x: rect.left + rect.width / 2, y: rect.top })
setHoveredDay({ date, stat })
greptile-apps[bot] (Migrated from github.com) commented 2026-02-07 22:03:10 +00:00

Tooltip never clears

onMouseLeave only clears hoveredDay, but StatusBarTooltip uses visible={hoveredDay !== null} so the tooltip stays stuck open after hover ends. This will be reproducible whenever you move the mouse off a day bar.

Also appears at app/sites/[id]/uptime/page.tsx:266-276 (same hover state).

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/sites/[id]/uptime/page.tsx
Line: 245:251

Comment:
**Tooltip never clears**

`onMouseLeave` only clears `hoveredDay`, but `StatusBarTooltip` uses `visible={hoveredDay !== null}` so the tooltip stays stuck open after hover ends. This will be reproducible whenever you move the mouse off a day bar.

Also appears at `app/sites/[id]/uptime/page.tsx:266-276` (same hover state).

How can I resolve this? If you propose a fix, please make it concise.
**Tooltip never clears** `onMouseLeave` only clears `hoveredDay`, but `StatusBarTooltip` uses `visible={hoveredDay !== null}` so the tooltip stays stuck open after hover ends. This will be reproducible whenever you move the mouse off a day bar. Also appears at `app/sites/[id]/uptime/page.tsx:266-276` (same hover state). <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: app/sites/[id]/uptime/page.tsx Line: 245:251 Comment: **Tooltip never clears** `onMouseLeave` only clears `hoveredDay`, but `StatusBarTooltip` uses `visible={hoveredDay !== null}` so the tooltip stays stuck open after hover ends. This will be reproducible whenever you move the mouse off a day bar. Also appears at `app/sites/[id]/uptime/page.tsx:266-276` (same hover state). How can I resolve this? If you propose a fix, please make it concise. ````` </details>
uz1mani (Migrated from github.com) reviewed 2026-02-07 22:03:14 +00:00
@@ -0,0 +1,1055 @@
'use client'
uz1mani (Migrated from github.com) commented 2026-02-07 22:03:14 +00:00

Issue: Using bare confirm was flagged for compatibility/clarity.
Fix: Replaced with window.confirm(...) so the global is explicit.
Why: Explicit window.confirm is clearer and avoids any non-browser or strict global assumptions.

Issue: Using bare confirm was flagged for compatibility/clarity. Fix: Replaced with window.confirm(...) so the global is explicit. Why: Explicit window.confirm is clearer and avoids any non-browser or strict global assumptions.
uz1mani (Migrated from github.com) reviewed 2026-02-07 22:05:57 +00:00
@@ -0,0 +1,1055 @@
'use client'
uz1mani (Migrated from github.com) commented 2026-02-07 22:05:57 +00:00

Issue: monitors can be null; using ?? [] was flagged as potentially leaving a non-array.
Fix: Use Array.isArray(uptimeData?.monitors) ? uptimeData.monitors : [] so we always render with an array.
Why: Ensures .length and .map() are safe regardless of API response.

Issue: monitors can be null; using ?? [] was flagged as potentially leaving a non-array. Fix: Use Array.isArray(uptimeData?.monitors) ? uptimeData.monitors : [] so we always render with an array. Why: Ensures .length and .map() are safe regardless of API response.
uz1mani (Migrated from github.com) reviewed 2026-02-07 22:06:07 +00:00
@@ -0,0 +248,4 @@
const handleMouseEnter = (e: React.MouseEvent, date: string, stat: UptimeDailyStat | undefined) => {
const rect = (e.target as HTMLElement).getBoundingClientRect()
setTooltipPos({ x: rect.left + rect.width / 2, y: rect.top })
setHoveredDay({ date, stat })
uz1mani (Migrated from github.com) commented 2026-02-07 22:06:07 +00:00

Issue: Tooltip could stay visible after hover ended.
Fix: Added onMouseLeave on the status bar container to clear hoveredDay when the pointer leaves the whole block; bars still clear on their own onMouseLeave.
Why: Clearing at the container level guarantees the tooltip hides when the cursor leaves the component, including when moving over gaps or the fixed tooltip.

Issue: Tooltip could stay visible after hover ended. Fix: Added onMouseLeave on the status bar container to clear hoveredDay when the pointer leaves the whole block; bars still clear on their own onMouseLeave. Why: Clearing at the container level guarantees the tooltip hides when the cursor leaves the component, including when moving over gaps or the fixed tooltip.
greptile-apps[bot] commented 2026-02-07 22:07:34 +00:00 (Migrated from github.com)

Greptile Overview

Greptile Summary

This PR adds an uptime monitoring dashboard under app/sites/[id]/uptime/page.tsx, backed by a new uptime API client (lib/api/uptime.ts) and a new "Uptime" navigation button from the site dashboard (app/sites/[id]/page.tsx). The uptime page fetches site + uptime status, renders per-monitor 90‑day status bars with hover tooltips, expands monitors to show response-time charts and recent checks, and provides monitor CRUD via modals.

Key integration points:

  • Uses existing auth context (useAuth) for edit permissions.
  • Reuses the shared apiRequest client and existing getSite API.
  • UI components come from @ciphera-net/ui plus Recharts for charting.

There are a couple of merge-blocking runtime issues to address in the uptime page: handling monitors: null safely during render, and preventing the URL protocol dropdown state from getting out of sync when editing an existing monitor URL.

Confidence Score: 3/5

  • This PR is close to mergeable but has a couple of definite runtime issues in the new uptime page that should be fixed first.
  • Most changes are additive and use existing patterns (apiRequest, getSite, UI components). However, the uptime page still treats monitors as always an array even though it is typed as nullable, which can throw at render, and the monitor form’s protocol dropdown can become inconsistent with an edited monitor’s existing URL, causing silent URL rewrites during edits.
  • app/sites/[id]/uptime/page.tsx

Important Files Changed

Filename Overview
app/sites/[id]/page.tsx Adds an "Uptime" navigation Button that routes to /sites/:id/uptime; no functional issues found in the change.
app/sites/[id]/uptime/page.tsx Introduces full uptime dashboard page with status visualization and monitor CRUD; contains a few logic issues (null monitors handling still present here, URL form can desync protocol state from url, and time-series chart labels can collide).
lib/api/uptime.ts Adds uptime API client types and request helpers for status/monitors/checks endpoints; no definite issues found within this file alone.

Sequence Diagram

sequenceDiagram
  participant U as User
  participant Page as UptimePage (app/sites/[id]/uptime/page.tsx)
  participant SitesAPI as getSite (lib/api/sites)
  participant UptimeAPI as lib/api/uptime.ts
  participant ApiClient as apiRequest (lib/api/client)

  U->>Page: Navigate /sites/:id/uptime
  Page->>SitesAPI: getSite(siteId)
  Page->>UptimeAPI: getUptimeStatus(siteId)
  UptimeAPI->>ApiClient: GET /sites/:id/uptime/status
  SitesAPI->>ApiClient: GET /sites/:id
  ApiClient-->>Page: site + status payloads
  Page-->>U: Render overall card + MonitorCards

  loop Every 30s
    Page->>UptimeAPI: getUptimeStatus(siteId)
    UptimeAPI->>ApiClient: GET /sites/:id/uptime/status
    ApiClient-->>Page: status payload
    Page-->>U: Update status bars/UI
  end

  U->>Page: Expand a monitor
  Page->>UptimeAPI: getMonitorChecks(siteId, monitorId, 50)
  UptimeAPI->>ApiClient: GET /sites/:id/uptime/monitors/:monitorId/checks?limit=50
  ApiClient-->>Page: checks[]
  Page-->>U: Render chart + recent checks

  alt Create monitor
    U->>Page: Submit Add Monitor modal
    Page->>UptimeAPI: createUptimeMonitor(siteId, data)
    UptimeAPI->>ApiClient: POST /sites/:id/uptime/monitors
    ApiClient-->>Page: created monitor
    Page->>UptimeAPI: getUptimeStatus(siteId)
  else Update monitor
    U->>Page: Submit Edit Monitor modal
    Page->>UptimeAPI: updateUptimeMonitor(siteId, monitorId, data)
    UptimeAPI->>ApiClient: PUT /sites/:id/uptime/monitors/:monitorId
    ApiClient-->>Page: updated monitor
    Page->>UptimeAPI: getUptimeStatus(siteId)
  else Delete monitor
    U->>Page: Confirm delete
    Page->>UptimeAPI: deleteUptimeMonitor(siteId, monitorId)
    UptimeAPI->>ApiClient: DELETE /sites/:id/uptime/monitors/:monitorId
    ApiClient-->>Page: 204/ok
    Page->>UptimeAPI: getUptimeStatus(siteId)
  end

<h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adds an uptime monitoring dashboard under `app/sites/[id]/uptime/page.tsx`, backed by a new uptime API client (`lib/api/uptime.ts`) and a new "Uptime" navigation button from the site dashboard (`app/sites/[id]/page.tsx`). The uptime page fetches site + uptime status, renders per-monitor 90‑day status bars with hover tooltips, expands monitors to show response-time charts and recent checks, and provides monitor CRUD via modals. Key integration points: - Uses existing auth context (`useAuth`) for edit permissions. - Reuses the shared `apiRequest` client and existing `getSite` API. - UI components come from `@ciphera-net/ui` plus Recharts for charting. There are a couple of merge-blocking runtime issues to address in the uptime page: handling `monitors: null` safely during render, and preventing the URL protocol dropdown state from getting out of sync when editing an existing monitor URL. <h3>Confidence Score: 3/5</h3> - This PR is close to mergeable but has a couple of definite runtime issues in the new uptime page that should be fixed first. - Most changes are additive and use existing patterns (apiRequest, getSite, UI components). However, the uptime page still treats `monitors` as always an array even though it is typed as nullable, which can throw at render, and the monitor form’s protocol dropdown can become inconsistent with an edited monitor’s existing URL, causing silent URL rewrites during edits. - app/sites/[id]/uptime/page.tsx <details><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | app/sites/[id]/page.tsx | Adds an "Uptime" navigation Button that routes to `/sites/:id/uptime`; no functional issues found in the change. | | app/sites/[id]/uptime/page.tsx | Introduces full uptime dashboard page with status visualization and monitor CRUD; contains a few logic issues (null monitors handling still present here, URL form can desync protocol state from url, and time-series chart labels can collide). | | lib/api/uptime.ts | Adds uptime API client types and request helpers for status/monitors/checks endpoints; no definite issues found within this file alone. | </details> </details> <h3>Sequence Diagram</h3> ```mermaid sequenceDiagram participant U as User participant Page as UptimePage (app/sites/[id]/uptime/page.tsx) participant SitesAPI as getSite (lib/api/sites) participant UptimeAPI as lib/api/uptime.ts participant ApiClient as apiRequest (lib/api/client) U->>Page: Navigate /sites/:id/uptime Page->>SitesAPI: getSite(siteId) Page->>UptimeAPI: getUptimeStatus(siteId) UptimeAPI->>ApiClient: GET /sites/:id/uptime/status SitesAPI->>ApiClient: GET /sites/:id ApiClient-->>Page: site + status payloads Page-->>U: Render overall card + MonitorCards loop Every 30s Page->>UptimeAPI: getUptimeStatus(siteId) UptimeAPI->>ApiClient: GET /sites/:id/uptime/status ApiClient-->>Page: status payload Page-->>U: Update status bars/UI end U->>Page: Expand a monitor Page->>UptimeAPI: getMonitorChecks(siteId, monitorId, 50) UptimeAPI->>ApiClient: GET /sites/:id/uptime/monitors/:monitorId/checks?limit=50 ApiClient-->>Page: checks[] Page-->>U: Render chart + recent checks alt Create monitor U->>Page: Submit Add Monitor modal Page->>UptimeAPI: createUptimeMonitor(siteId, data) UptimeAPI->>ApiClient: POST /sites/:id/uptime/monitors ApiClient-->>Page: created monitor Page->>UptimeAPI: getUptimeStatus(siteId) else Update monitor U->>Page: Submit Edit Monitor modal Page->>UptimeAPI: updateUptimeMonitor(siteId, monitorId, data) UptimeAPI->>ApiClient: PUT /sites/:id/uptime/monitors/:monitorId ApiClient-->>Page: updated monitor Page->>UptimeAPI: getUptimeStatus(siteId) else Delete monitor U->>Page: Confirm delete Page->>UptimeAPI: deleteUptimeMonitor(siteId, monitorId) UptimeAPI->>ApiClient: DELETE /sites/:id/uptime/monitors/:monitorId ApiClient-->>Page: 204/ok Page->>UptimeAPI: getUptimeStatus(siteId) end ```
greptile-apps[bot] (Migrated from github.com) reviewed 2026-02-07 22:07:40 +00:00
greptile-apps[bot] (Migrated from github.com) left a comment

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

<sub>3 files reviewed, 2 comments</sub> <sub>[Edit Code Review Agent Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews)</sub>
@@ -0,0 +1,1055 @@
'use client'
greptile-apps[bot] (Migrated from github.com) commented 2026-02-07 22:07:39 +00:00

Protocol state can desync

protocol is initialized from formData.url once, but when opening the edit modal you set formData.url to an existing monitor URL without updating protocol. If the saved monitor URL is http://... and protocol remains https://, any path edit or protocol toggle rebuild will silently rewrite the URL with the wrong scheme. Derive protocol from formData.url (or sync it in an effect when formData.url changes) so editing preserves the monitor’s actual scheme.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/sites/[id]/uptime/page.tsx
Line: 868:903

Comment:
**Protocol state can desync**

`protocol` is initialized from `formData.url` once, but when opening the edit modal you set `formData.url` to an existing monitor URL without updating `protocol`. If the saved monitor URL is `http://...` and `protocol` remains `https://`, any path edit or protocol toggle rebuild will silently rewrite the URL with the wrong scheme. Derive `protocol` from `formData.url` (or sync it in an effect when `formData.url` changes) so editing preserves the monitor’s actual scheme.


How can I resolve this? If you propose a fix, please make it concise.
**Protocol state can desync** `protocol` is initialized from `formData.url` once, but when opening the edit modal you set `formData.url` to an existing monitor URL without updating `protocol`. If the saved monitor URL is `http://...` and `protocol` remains `https://`, any path edit or protocol toggle rebuild will silently rewrite the URL with the wrong scheme. Derive `protocol` from `formData.url` (or sync it in an effect when `formData.url` changes) so editing preserves the monitor’s actual scheme. <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: app/sites/[id]/uptime/page.tsx Line: 868:903 Comment: **Protocol state can desync** `protocol` is initialized from `formData.url` once, but when opening the edit modal you set `formData.url` to an existing monitor URL without updating `protocol`. If the saved monitor URL is `http://...` and `protocol` remains `https://`, any path edit or protocol toggle rebuild will silently rewrite the URL with the wrong scheme. Derive `protocol` from `formData.url` (or sync it in an effect when `formData.url` changes) so editing preserves the monitor’s actual scheme. How can I resolve this? If you propose a fix, please make it concise. ````` </details>
@@ -0,0 +706,4 @@
if (loading) return <LoadingOverlay logoSrc="/pulse_icon_no_margins.png" title="Uptime" />
if (!site) return <div className="p-8 text-neutral-500">Site not found</div>
greptile-apps[bot] (Migrated from github.com) commented 2026-02-07 22:07:38 +00:00

monitors can be null

UptimeStatusResponse.monitors is typed as MonitorStatus[] | null (lib/api/uptime.ts), but this page still does const monitors = uptimeData?.monitors ?? []. If the API returns monitors: null, this expression evaluates to null (because the optional chain returns null, which ?? does not replace), and the subsequent monitors.length / monitors.map(...) will throw during render. Use an explicit array guard (e.g., Array.isArray(uptimeData?.monitors) ? uptimeData.monitors : []) before reading .length / .map.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/sites/[id]/uptime/page.tsx
Line: 707:709

Comment:
**`monitors` can be `null`**

`UptimeStatusResponse.monitors` is typed as `MonitorStatus[] | null` (`lib/api/uptime.ts`), but this page still does `const monitors = uptimeData?.monitors ?? []`. If the API returns `monitors: null`, this expression evaluates to `null` (because the optional chain returns `null`, which `??` does not replace), and the subsequent `monitors.length` / `monitors.map(...)` will throw during render. Use an explicit array guard (e.g., `Array.isArray(uptimeData?.monitors) ? uptimeData.monitors : []`) before reading `.length` / `.map`.


How can I resolve this? If you propose a fix, please make it concise.
**`monitors` can be `null`** `UptimeStatusResponse.monitors` is typed as `MonitorStatus[] | null` (`lib/api/uptime.ts`), but this page still does `const monitors = uptimeData?.monitors ?? []`. If the API returns `monitors: null`, this expression evaluates to `null` (because the optional chain returns `null`, which `??` does not replace), and the subsequent `monitors.length` / `monitors.map(...)` will throw during render. Use an explicit array guard (e.g., `Array.isArray(uptimeData?.monitors) ? uptimeData.monitors : []`) before reading `.length` / `.map`. <details><summary>Prompt To Fix With AI</summary> `````markdown This is a comment left during a code review. Path: app/sites/[id]/uptime/page.tsx Line: 707:709 Comment: **`monitors` can be `null`** `UptimeStatusResponse.monitors` is typed as `MonitorStatus[] | null` (`lib/api/uptime.ts`), but this page still does `const monitors = uptimeData?.monitors ?? []`. If the API returns `monitors: null`, this expression evaluates to `null` (because the optional chain returns `null`, which `??` does not replace), and the subsequent `monitors.length` / `monitors.map(...)` will throw during render. Use an explicit array guard (e.g., `Array.isArray(uptimeData?.monitors) ? uptimeData.monitors : []`) before reading `.length` / `.map`. How can I resolve this? If you propose a fix, please make it concise. ````` </details>
uz1mani (Migrated from github.com) reviewed 2026-02-07 22:09:45 +00:00
@@ -0,0 +1,1055 @@
'use client'
uz1mani (Migrated from github.com) commented 2026-02-07 22:09:45 +00:00

Issue: protocol was initialized once from formData.url, so when opening edit with a monitor that had http://, protocol could still be https:// and path edits used the wrong scheme.
Fix: Protocol is now derived from formData.url at render time (formData.url.startsWith('http://') ? 'http://' : 'https://'); protocol state was removed and handleProtocolChange only updates formData.url.
Why: Editing must reflect the saved monitor’s scheme; deriving from formData.url keeps the dropdown and URL in sync whenever the parent sets formData (e.g. when opening edit).

Issue: protocol was initialized once from formData.url, so when opening edit with a monitor that had http://, protocol could still be https:// and path edits used the wrong scheme. Fix: Protocol is now derived from formData.url at render time (formData.url.startsWith('http://') ? 'http://' : 'https://'); protocol state was removed and handleProtocolChange only updates formData.url. Why: Editing must reflect the saved monitor’s scheme; deriving from formData.url keeps the dropdown and URL in sync whenever the parent sets formData (e.g. when opening edit).
uz1mani (Migrated from github.com) reviewed 2026-02-07 22:09:52 +00:00
@@ -0,0 +706,4 @@
if (loading) return <LoadingOverlay logoSrc="/pulse_icon_no_margins.png" title="Uptime" />
if (!site) return <div className="p-8 text-neutral-500">Site not found</div>
uz1mani (Migrated from github.com) commented 2026-02-07 22:09:52 +00:00

alreayd fixed

alreayd fixed
greptile-apps[bot] commented 2026-02-07 22:11:43 +00:00 (Migrated from github.com)

Greptile Overview

Greptile Summary

This PR adds a comprehensive uptime monitoring dashboard with 90-day status visualization, response time charts, and full CRUD operations for monitors. The implementation includes:

  • New API client (lib/api/uptime.ts) with properly typed interfaces for monitors, checks, daily stats, and status responses
  • Full-featured uptime page with overall status card, per-monitor cards with 90-day colored status bars, hover tooltips, expandable details with Recharts area charts, and recent checks list
  • Smart URL input with protocol dropdown and domain prefix, similar to UTM builder pattern
  • Auto-refresh every 30 seconds with error handling that shows toast notifications on failure
  • Navigation button added to main dashboard for easy access

Key strengths:

  • Previous review comments have been addressed (protocol state derivation, array guard for monitors, tooltip visibility, auto-refresh error handling)
  • Clean separation of concerns with reusable components
  • Consistent styling with existing dashboard theme
  • Proper error handling throughout with user-friendly toast messages
  • Type-safe API client with null-safe array handling

Confidence Score: 4/5

  • This PR is safe to merge with minor considerations around edge case handling
  • The implementation is solid and addresses all previously raised issues. The code follows established patterns in the codebase, includes proper error handling, and has good type safety. Score of 4 (not 5) due to the complexity of the feature and the typical need for real-world testing of auto-refresh behavior and edge cases in production
  • No files require special attention - all implementations follow best practices

Important Files Changed

Filename Overview
lib/api/uptime.ts New API client for uptime monitoring with comprehensive types and functions for CRUD operations on monitors and checks
app/sites/[id]/page.tsx Adds Uptime navigation button to dashboard header for accessing the new uptime monitoring page
app/sites/[id]/uptime/page.tsx Complete uptime monitoring dashboard with 90-day status visualization, response time charts, monitor CRUD, and auto-refresh. Protocol dropdown implementation correctly derives state from formData.url

Sequence Diagram

sequenceDiagram
    participant User
    participant UptimePage
    participant API
    participant Backend

    User->>UptimePage: Navigate to /sites/[id]/uptime
    UptimePage->>API: getSite(siteId)
    UptimePage->>API: getUptimeStatus(siteId)
    API->>Backend: GET /sites/{id}/uptime/status
    Backend-->>API: UptimeStatusResponse
    API-->>UptimePage: Site + UptimeStatusResponse
    UptimePage->>UptimePage: Render monitors with 90-day status bars
    
    loop Every 30 seconds
        UptimePage->>API: getUptimeStatus(siteId)
        API->>Backend: GET /sites/{id}/uptime/status
        Backend-->>API: UptimeStatusResponse
        API-->>UptimePage: Updated data
        UptimePage->>UptimePage: Update UI
    end

    User->>UptimePage: Click "Add Monitor"
    UptimePage->>UptimePage: Show MonitorForm modal
    User->>UptimePage: Select protocol + enter path
    UptimePage->>UptimePage: Derive URL from protocol + domain + path
    User->>UptimePage: Submit form
    UptimePage->>API: createUptimeMonitor(siteId, formData)
    API->>Backend: POST /sites/{id}/uptime/monitors
    Backend-->>API: UptimeMonitor
    API-->>UptimePage: Success
    UptimePage->>API: getUptimeStatus(siteId)
    UptimePage->>UptimePage: Refresh monitor list

    User->>UptimePage: Expand monitor
    UptimePage->>API: getMonitorChecks(siteId, monitorId, 50)
    API->>Backend: GET /sites/{id}/uptime/monitors/{monitorId}/checks
    Backend-->>API: UptimeCheck[]
    API-->>UptimePage: Recent checks
    UptimePage->>UptimePage: Render ResponseTimeChart + check list

    User->>UptimePage: Hover over status bar day
    UptimePage->>UptimePage: Show StatusBarTooltip with stats
    User->>UptimePage: Mouse leave
    UptimePage->>UptimePage: Hide tooltip
<h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR adds a comprehensive uptime monitoring dashboard with 90-day status visualization, response time charts, and full CRUD operations for monitors. The implementation includes: - **New API client** (`lib/api/uptime.ts`) with properly typed interfaces for monitors, checks, daily stats, and status responses - **Full-featured uptime page** with overall status card, per-monitor cards with 90-day colored status bars, hover tooltips, expandable details with Recharts area charts, and recent checks list - **Smart URL input** with protocol dropdown and domain prefix, similar to UTM builder pattern - **Auto-refresh** every 30 seconds with error handling that shows toast notifications on failure - **Navigation button** added to main dashboard for easy access Key strengths: - Previous review comments have been addressed (protocol state derivation, array guard for monitors, tooltip visibility, auto-refresh error handling) - Clean separation of concerns with reusable components - Consistent styling with existing dashboard theme - Proper error handling throughout with user-friendly toast messages - Type-safe API client with null-safe array handling <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with minor considerations around edge case handling - The implementation is solid and addresses all previously raised issues. The code follows established patterns in the codebase, includes proper error handling, and has good type safety. Score of 4 (not 5) due to the complexity of the feature and the typical need for real-world testing of auto-refresh behavior and edge cases in production - No files require special attention - all implementations follow best practices <details><summary><h3>Important Files Changed</h3></summary> | Filename | Overview | |----------|----------| | lib/api/uptime.ts | New API client for uptime monitoring with comprehensive types and functions for CRUD operations on monitors and checks | | app/sites/[id]/page.tsx | Adds Uptime navigation button to dashboard header for accessing the new uptime monitoring page | | app/sites/[id]/uptime/page.tsx | Complete uptime monitoring dashboard with 90-day status visualization, response time charts, monitor CRUD, and auto-refresh. Protocol dropdown implementation correctly derives state from formData.url | </details> </details> <h3>Sequence Diagram</h3> ```mermaid sequenceDiagram participant User participant UptimePage participant API participant Backend User->>UptimePage: Navigate to /sites/[id]/uptime UptimePage->>API: getSite(siteId) UptimePage->>API: getUptimeStatus(siteId) API->>Backend: GET /sites/{id}/uptime/status Backend-->>API: UptimeStatusResponse API-->>UptimePage: Site + UptimeStatusResponse UptimePage->>UptimePage: Render monitors with 90-day status bars loop Every 30 seconds UptimePage->>API: getUptimeStatus(siteId) API->>Backend: GET /sites/{id}/uptime/status Backend-->>API: UptimeStatusResponse API-->>UptimePage: Updated data UptimePage->>UptimePage: Update UI end User->>UptimePage: Click "Add Monitor" UptimePage->>UptimePage: Show MonitorForm modal User->>UptimePage: Select protocol + enter path UptimePage->>UptimePage: Derive URL from protocol + domain + path User->>UptimePage: Submit form UptimePage->>API: createUptimeMonitor(siteId, formData) API->>Backend: POST /sites/{id}/uptime/monitors Backend-->>API: UptimeMonitor API-->>UptimePage: Success UptimePage->>API: getUptimeStatus(siteId) UptimePage->>UptimePage: Refresh monitor list User->>UptimePage: Expand monitor UptimePage->>API: getMonitorChecks(siteId, monitorId, 50) API->>Backend: GET /sites/{id}/uptime/monitors/{monitorId}/checks Backend-->>API: UptimeCheck[] API-->>UptimePage: Recent checks UptimePage->>UptimePage: Render ResponseTimeChart + check list User->>UptimePage: Hover over status bar day UptimePage->>UptimePage: Show StatusBarTooltip with stats User->>UptimePage: Mouse leave UptimePage->>UptimePage: Hide tooltip ```
Sign in to join this conversation.
No description provided.