Bar chart single point#454
Conversation
🪼 branch checks and previews
|
🦄 change detectedThis Pull Request includes changes to the following packages.
|
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
qgallouedec
left a comment
There was a problem hiding this comment.
Looks good! I cannot really review the svelte code though 😅
There was a problem hiding this comment.
Pull request overview
Adds support for rendering metrics that only contain a single logged value per run as bar charts, improving readability vs. line plots for single-point series.
Changes:
- Add
isSinglePoint()detection in Metrics page and switch rendering toBarPlotfor those metrics. - Introduce new
BarPlot.svelteVega-Lite component with CSV/PNG export, fullscreen, and drag-reorder support. - Update Playwright UI test expectations and add a changeset for a minor release.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| trackio/frontend/src/pages/Metrics.svelte | Detects single-point metrics and conditionally renders BarPlot instead of LinePlot. |
| trackio/frontend/src/components/BarPlot.svelte | New bar chart component (Vega-Lite) for single-point metrics with toolbar + fullscreen support. |
| tests/ui/test_ui_display.py | Extends UI test to include a single-point metric and asserts bar plot presence. |
| .changeset/stupid-lions-speak.md | Declares a minor version bump for the new UI behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| {@const useBar = isSinglePoint(metric)} | ||
| {#if plotData.length > 0} |
There was a problem hiding this comment.
isSinglePoint(metric) scans masterData (filter + per-run counting) and is invoked for every metric render. With many metrics/rows this becomes an O(metrics × rows) hot path on each reactive update. Consider precomputing a Map<metric, boolean> (or counts per metric/run) when masterData changes (e.g., in processFromCache or a $derived.by), and only evaluating it when plotData.length > 0 to avoid extra full scans for empty plots.
| {@const useBar = isSinglePoint(metric)} | |
| {#if plotData.length > 0} | |
| {#if plotData.length > 0} | |
| {@const useBar = isSinglePoint(metric)} |
| function downloadCSV() { | ||
| const barData = getBarData(); | ||
| if (barData.length === 0) return; | ||
| const header = "run," + y; | ||
| const rows = barData.map((row) => { | ||
| const run = | ||
| typeof row.run === "string" && (row.run.includes(",") || row.run.includes('"')) | ||
| ? `"${row.run.replace(/"/g, '""')}"` | ||
| : row.run; | ||
| return `${run},${row.value}`; |
There was a problem hiding this comment.
CSV export builds the header as "run," + y without escaping/quoting y. If a metric name ever contains a comma or quote, the generated CSV will be malformed. Consider applying the same CSV escaping used for run names (and optionally values) to the header fields as well (or use fixed column names like run,value).
| function downloadCSV() { | |
| const barData = getBarData(); | |
| if (barData.length === 0) return; | |
| const header = "run," + y; | |
| const rows = barData.map((row) => { | |
| const run = | |
| typeof row.run === "string" && (row.run.includes(",") || row.run.includes('"')) | |
| ? `"${row.run.replace(/"/g, '""')}"` | |
| : row.run; | |
| return `${run},${row.value}`; | |
| function csvEscape(value) { | |
| if (value == null) return ""; | |
| const str = String(value); | |
| return /[",\n]/.test(str) ? `"${str.replace(/"/g, '""')}"` : str; | |
| } | |
| function downloadCSV() { | |
| const barData = getBarData(); | |
| if (barData.length === 0) return; | |
| const header = `${csvEscape("run")},${csvEscape(y)}`; | |
| const rows = barData.map((row) => { | |
| return `${csvEscape(row.run)},${csvEscape(row.value)}`; |
|
Thanks so much for reviewing @qgallouedec! The Svelte should be fine, as it's more or less vendored in from Gradio. Fixed the issues that @copilot found as well, will merge once CI is green. |
Renders single-value metrics as bar chart instead of line plots:
Screen.Recording.2026-03-25.at.7.21.30.PM.mov