feat(dashboard): polish charts, add time ranges, and visual refinements#17
Open
feat(dashboard): polish charts, add time ranges, and visual refinements#17
Conversation
…affic charts Errors and warnings were invisible when info/debug counts were 10-50x larger because all levels shared one y-axis. This splits the chart into two vertically stacked panels with independent y-axes: - Top panel "Errors & Warnings" (h-40): red + yellow datasets, x-axis labels hidden to avoid duplication - Bottom panel "Traffic Volume" (h-48): blue info + gray debug datasets, with x-axis labels visible Both panels share the same date labels for visual time-correlation. The new splitDailyStatsChartConfigs() helper in charts.ts returns two separate Chart.js config JSON strings; the existing dailyStatsChartConfig() is preserved. Co-Authored-By: Claude <noreply@anthropic.com>
Adds three toggle buttons above the split Chart.js charts that let users switch the stats window without a page reload. Clicking a button calls loadStats() which fetches /dashboard/api/stats/:app_id?days=N and updates both chart instances in-place (data.labels + data.datasets + chart.update()). Stats cards and chart section title now reflect the active range dynamically via Alpine.js x-text bindings. statsTotals state recalculates from the API response on each range change so the four summary cards stay in sync. Module-level ewChart/trafficChart vars are assigned in DOMContentLoaded and closed over by the Alpine loadStats() method so no DOM query is needed on each fetch. No backend changes required — the DO already supports ?days=N. Co-Authored-By: Claude <noreply@anthropic.com>
…ge toggle Extends the overview page with a grouped bar chart showing per-app errors and warnings over the selected time range (7d/14d/30d). The chart updates in-place when the range changes, reusing the same Alpine.js + Chart.js in-place update pattern from the app-detail page. - Add overviewBarChartConfig() to charts.ts for grouped bar chart config - Add AppChartData/OverviewChartResponse types to dashboard/types.ts - Add getOverviewChart() to api/overview.ts for multi-day per-day stats - Add /dashboard/api/overview/chart?days=N endpoint to index.ts - Update overview page with chart section, range buttons, and chart init Co-Authored-By: Claude <noreply@anthropic.com>
Add sparkline trend visualizations to all stats cards on both overview
and app-detail pages, pulling from existing sparkline() utility that was
previously unused. Error cards now also display an error rate percentage
("X% of all logs") to give context alongside raw counts.
- Extend statsCard() to accept optional sparklineHtml and subtext params
- Overview: 2-point sparklines (yesterday→today) for errors/warnings/info
- App-detail: full multi-day sparklines from stats[] history per level
- App-detail stats cards now use card-glow class for consistency
- Error rate shown on error card when >0%
Co-Authored-By: Claude <noreply@anthropic.com>
…ansitions Final visual polish sweep to make the dashboard presentation-ready: - Add branded footer() to layout.ts, rendered in every page via htmlDocument() showing brand name, service name, and "Powered by Cloudflare Workers & Durable Objects" - Improve emptyState() helper to accept an optional hint text below the message - Overview: use emptyState() with SVG icons for "no apps" and "no recent errors" states - App-detail: upgrade "no logs found" state with clipboard icon, message, and filter hint - Add log-row CSS class with 0.1s ease background transition for smooth table hovers - Apply log-row class to all data rows in overview tables - Tune app-detail stats cards: use var(--text-muted) for labels and add card-glow class Co-Authored-By: Claude <noreply@anthropic.com>
Extract shared chart helpers (lineDataset, barDataset, CHART_SCALES, CHART_BASE_OPTIONS), consolidate repeated sparkline options, remove dead code in overview refresh, and add addStats helper. Net -91 lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
worker-logs-production | 6c9b110 | Mar 13 2026, 04:15 AM |
There was a problem hiding this comment.
Pull request overview
This PR enhances the dashboard with visual improvements including split charts, time-range toggles, sparklines, and better empty states. It refactors chart configuration into shared helpers and adds a new overview bar chart endpoint.
Changes:
- Split the single line chart into stacked Errors/Warnings + Traffic Volume charts with independent y-axes, added time-range toggle (7d/14d/30d) on both overview and app-detail pages
- Added a new
/dashboard/api/overview/chartendpoint and grouped bar chart to the overview page showing per-app errors/warnings over time - Added sparklines to stats cards, error rate percentages, branded footer, improved empty states with icons/hints, and table hover transitions
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/dashboard/types.ts | New AppChartData and OverviewChartResponse types for the overview bar chart |
| src/dashboard/styles.ts | Added CSS transition for table row hover |
| src/dashboard/components/layout.ts | Extended statsCard with sparkline/subtext, added hint to emptyState, new footer component |
| src/dashboard/components/charts.ts | Extracted shared chart helpers (lineDataset, barDataset, CHART_SCALES, CHART_BASE_OPTIONS), added splitDailyStatsChartConfigs and overviewBarChartConfig |
| src/dashboard/api/overview.ts | New getOverviewChart function, addStats helper to reduce duplication |
| src/dashboard/index.ts | New /api/overview/chart route |
| src/dashboard/pages/overview.ts | Overview page updated with sparklines, error rates, bar chart, time-range toggle, improved empty states |
| src/dashboard/pages/app-detail.ts | App-detail page updated with split charts, time-range toggle, sparklines, inline stats cards |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Comment on lines
+74
to
+94
| <div class="brand-card card-glow rounded-lg p-4"> | ||
| <div class="text-xs mb-1" style="color: var(--text-muted);">Debug (<span x-text="statsRange + 'd'">7d</span>)</div> | ||
| <div class="text-2xl font-bold text-gray-400" x-text="statsTotals.debug">${totals.debug}</div> | ||
| <div class="mt-2 h-5 w-full opacity-70">${debugSparkline}</div> | ||
| </div> | ||
| <div class="brand-card card-glow rounded-lg p-4"> | ||
| <div class="text-xs mb-1" style="color: var(--text-muted);">Info (<span x-text="statsRange + 'd'">7d</span>)</div> | ||
| <div class="text-2xl font-bold text-blue-400" x-text="statsTotals.info">${totals.info}</div> | ||
| <div class="mt-2 h-5 w-full opacity-70">${infoSparkline}</div> | ||
| </div> | ||
| <div class="brand-card card-glow rounded-lg p-4"> | ||
| <div class="text-xs mb-1" style="color: var(--text-muted);">Warn (<span x-text="statsRange + 'd'">7d</span>)</div> | ||
| <div class="text-2xl font-bold text-yellow-400" x-text="statsTotals.warn">${totals.warn}</div> | ||
| <div class="mt-2 h-5 w-full opacity-70">${warnSparkline}</div> | ||
| </div> | ||
| <div class="brand-card card-glow rounded-lg p-4"> | ||
| <div class="text-xs mb-1" style="color: var(--text-muted);">Error (<span x-text="statsRange + 'd'">7d</span>)</div> | ||
| <div class="text-2xl font-bold text-red-400" x-text="statsTotals.error">${totals.error}</div> | ||
| ${errorRate > 0 ? `<div class="text-xs mt-1" style="color: var(--text-muted);">${errorRate}% of all logs</div>` : ''} | ||
| <div class="mt-2 h-5 w-full opacity-70">${errorSparkline}</div> | ||
| </div> |
| import { dailyStatsChartConfig, formatHealthStatus, determineHealthStatus } from '../components/charts' | ||
| import { htmlDocument, header } from '../components/layout' | ||
| import { splitDailyStatsChartConfigs, formatHealthStatus, determineHealthStatus, sparkline } from '../components/charts' | ||
| import { escapeHtml, styles } from '../styles' |
| return c.json({ ok: false, error: 'Unauthorized' }, 401) | ||
| } | ||
|
|
||
| const days = Math.min(Math.max(parseInt(c.req.query('days') || '7', 10), 1), 90) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
?days=NAPITest plan
npm testpasses (all 35 tests)/dashboardoverview — grouped bar chart renders with time-range toggle/dashboard/app/:id— two stacked charts render, time-range toggle works🤖 Generated with Claude Code