Add 10 UX/feature improvements across dashboard, status page, and API

- Incident acknowledge: Ack button in dashboard rail and ResourceDetail incidents table
- Status page 90-day uptime history bars (teal ≥99%, amber ≥95%, red <95%, grey = no data)
- Theme setting applied: data-theme attribute wired to saved setting with CSS variables + light mode overrides
- Sparkline replaced with colored status bars (teal=up, red=down, grey=unknown) per check tick
- ResourceDetail chart time-range selector: 1h / 6h / 24h / 7d toggle fetches from checks endpoint
- Bulk actions: checkbox per row, select-all header, bulk delete and maintenance toggle bar
- CSV export adds 6 new fields (http_method, http_body, heartbeat_timeout, is_public, consecutive_failures_threshold, response_time_threshold)
- CSV import handles those 6 new fields on INSERT
- Check detail expansion: click expandable rows in Recent Checks to show full details JSON
- Browser push notifications: request permission opt-in, new Notification() on WS message when tab unfocused

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 4.6 committed 2026-07-31 11:01:24 -04:00
1 parent 5cfea703fb
commit b83a19e9cf
20 files changed
+580 -56

No files matched your search

+35
View File
@@ -125,6 +125,19 @@ function Status() {
return m.resource_id === resource.id && now >= start && now <= end;
});
const daily = resource.dailyUptime || [];
const last90Days = (() => {
const days = [];
for (let i = 89; i >= 0; i--) {
const d = new Date();
d.setDate(d.getDate() - i);
const key = d.toISOString().slice(0, 10);
const entry = daily.find(e => e.day === key);
days.push({ day: key, uptime: entry ? entry.uptime : null });
}
return days;
})();
return (
<div
key={resource.id}
@@ -145,6 +158,28 @@ function Status() {
</p>
)}
<div className="uptime-history" title="90-day uptime — hover for details">
{last90Days.map((d) => {
const color = d.uptime === null ? '#334155'
: d.uptime >= 99 ? '#14b8a6'
: d.uptime >= 95 ? '#f59e0b'
: '#ef4444';
return (
<div
key={d.day}
className="uptime-day-bar"
style={{ background: color }}
title={d.uptime !== null ? `${d.day}: ${d.uptime}%` : `${d.day}: no data`}
/>
);
})}
</div>
<div className="uptime-history-labels">
<span>90 days ago</span>
<span>{daily.length > 0 ? `${daily[daily.length - 1]?.uptime ?? '—'}% today` : ''}</span>
<span>Today</span>
</div>
{activeIncident && (
<div className="incident-info">
<p className="incident-title">Active Incident</p>