Skip to content

Add charts to the homepage#2

Merged
willy1989cv merged 7 commits into
mainfrom
feat/resource-chart
Jul 8, 2026
Merged

Add charts to the homepage#2
willy1989cv merged 7 commits into
mainfrom
feat/resource-chart

Conversation

@willy1989cv

@willy1989cv willy1989cv commented Jul 8, 2026

Copy link
Copy Markdown
Member

Issue: datopian/portaljs#1618

Summary by CodeRabbit

  • New Features

    • Added a featured data-signal carousel on the home page, with automatic rotation and direct links to related datasets.
    • Introduced richer chart displays for dataset resources, including line and bar visualizations with clearer labels and tooltips.
    • Improved CSV-backed search and viewing flows so data can be searched, reset, and displayed more smoothly.
  • Bug Fixes

    • Updated the site disclaimer text to be shorter and clearer.
    • Improved handling of chart and data loading failures so pages can continue rendering gracefully.

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
portaljs-research Ready Ready Preview, Comment Jul 8, 2026 1:23pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@willy1989cv, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3f432912-09ec-4ec7-b121-4ecf2ba3c45e

📥 Commits

Reviewing files that changed from the base of the PR and between 9ffbe17 and 2ae632f.

📒 Files selected for processing (5)
  • src/components/csv-explorer/DataProvider.tsx
  • src/components/home/HomeDataSignalCarousel.tsx
  • src/components/home/HomeDataSignalCarouselClient.tsx
  • src/components/resource-chart/transform.ts
  • src/lib/csv.ts
📝 Walkthrough

Walkthrough

This PR adds a home page carousel showcasing data signals, backed by a new resource-chart component library (types, data transform, Plot-based rendering) and CKAN/DMS resource-fetching helpers. It also migrates CSV parsing across the codebase to shared parseCsvRows/unparseCsvRows utilities, and updates a description string.

Changes

Data Signal Carousel and Chart Infrastructure

Layer / File(s) Summary
Shared CSV parse/unparse utility and adoption
src/lib/csv.ts, src/lib/parseCsv.ts, src/components/csv-explorer/DataProvider.tsx, src/components/csv-explorer/SearchDataForm.tsx
Adds parseCsvRows/unparseCsvRows wrappers around papaparse and migrates parseCsv, DataProvider, and SearchDataForm to use them instead of Papa directly.
DMS URL helpers and CKAN resource fetching
src/lib/dms.ts, src/lib/ckan/resource.ts, src/lib/ckan/api.ts
Adds getDmsBaseUrl/getDmsActionUrl and searchResources/getResourceByName/getResourceMetadata, and refactors CKAN.getResourceMetadata to delegate to the new helper.
Resource chart types and data transform
src/components/resource-chart/types.ts, src/components/resource-chart/transform.ts
Defines chart row/config/state types and buildResourceChartState, which filters, buckets, aggregates, sorts, and limits rows into chart-ready data.
CKAN row fetcher and ResourceChart entry point
src/components/resource-chart/fetchers.ts, src/components/resource-chart/ResourceChart.tsx, src/components/resource-chart/index.ts, src/components/resource-chart/client.ts
Adds createCkanResourceFetcher/fetchCkanResourceRows and the async ResourceChart component that fetches rows, builds chart state, and renders ResourceChartClient or an empty fallback; barrels the public exports.
Plot-based chart rendering
src/lib/charts/format.ts, src/lib/charts/usePlot.ts, src/components/resource-chart/ResourceChartClient.tsx
Adds formatCompactNumber, a resize-driven usePlot hook, and ResourceChartClient with LineChart/BarChart implementations using Observable Plot.
Home data signal carousel and page wiring
src/components/home/HomeDataSignalCarousel.tsx, src/components/home/HomeDataSignalCarouselClient.tsx, src/app/[locale]/page.tsx, messages/en.json
Resolves slides to CKAN resources/dataset details, renders charts inside a paginated/auto-advancing carousel, wires it into the home page, and updates the site description text.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Page as Home Page
  participant Carousel as HomeDataSignalCarousel
  participant CKAN as CKAN Resource API
  participant Chart as ResourceChart
  participant Client as HomeDataSignalCarouselClient

  Page->>Carousel: render()
  Carousel->>CKAN: getResourceByName(slide.name)
  CKAN-->>Carousel: resource or null
  Carousel->>CKAN: getDatasetDetails(resource.package_id)
  CKAN-->>Carousel: dataset details or null
  Carousel->>Chart: render(resourceId, config)
  Chart->>CKAN: fetchCkanResourceRows(resourceId)
  CKAN-->>Chart: CSV rows
  Chart-->>Carousel: chart element
  Carousel->>Client: render(slides, charts)
  Client-->>Page: carousel UI
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately highlights the main visible change: adding charts to the homepage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/resource-chart

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
src/components/resource-chart/ResourceChart.tsx (1)

25-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider simplifying the IIFE to a straightforward try/catch.

The await (async () => { ... })() pattern works but adds cognitive overhead. A plain try/catch with a let binding is more idiomatic.

♻️ Proposed refactor
-  const state = await (async () => {
-    try {
-      const rows = await fetchRows(resourceId);
-      return buildResourceChartState(rows, config);
-    } catch (error) {
-      console.error(`Failed to render resource chart for ${resourceId}:`, error);
-      return { status: "empty" as const, message: "This chart could not be loaded." };
-    }
-  })();
+  let state: ResourceChartState;
+  try {
+    const rows = await fetchRows(resourceId);
+    state = buildResourceChartState(rows, config);
+  } catch (error) {
+    console.error(`Failed to render resource chart for ${resourceId}:`, error);
+    state = { status: "empty", message: "This chart could not be loaded." };
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/resource-chart/ResourceChart.tsx` around lines 25 - 33, The
async IIFE used to assign state in ResourceChart is unnecessarily complex;
replace it with a direct try/catch around the fetchRows/resource chart state
creation logic. Use a simple let binding for state in ResourceChart and keep the
existing error handling and fallback state behavior unchanged.
src/components/resource-chart/transform.ts (1)

16-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Regex character class has a redundant comma.

The , appears twice in /[$,%\s,]/g. It's functionally harmless but slightly confusing — a reader might wonder if the second comma was meant to be a different character.

🧹 Proposed cleanup
-  const normalized = value.replace(/[$,%\s,]/g, "");
+  const normalized = value.replace(/[$,%\s]/g, "");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/resource-chart/transform.ts` around lines 16 - 23, The
toNumber helper in transform.ts has a redundant comma in the cleanup regex,
which is confusing to read. Update the regex used in toNumber to remove the
duplicate comma character while preserving the existing normalization behavior
for values handled by toNumber.
src/app/[locale]/page.tsx (1)

196-197: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Wrap HomeDataSignalCarousel in Suspense to avoid blocking page render.

HomeDataSignalCarousel is an async server component that fetches CKAN resources and dataset details. Without a Suspense boundary, the entire page waits for this data before sending any HTML. Wrapping it allows the hero section and stats to render immediately while the carousel streams in.

⚡ Proposed fix
+import { Suspense, type CSSProperties } from "react";
           </div>
+
+          <Suspense fallback={<div className="min-h-[380px]" />}>
+            <HomeDataSignalCarousel />
+          </Suspense>
         </Container>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`[locale]/page.tsx around lines 196 - 197, Wrap
HomeDataSignalCarousel in a Suspense boundary so the page can render the
hero/stats immediately while the async server component streams in. Update the
page component in the locale page to render HomeDataSignalCarousel with Suspense
and provide a lightweight fallback, keeping the existing HomeDataSignalCarousel
usage intact.
src/lib/charts/usePlot.ts (1)

22-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider re-rendering the plot when the builder closure changes.

The main effect depends only on [ref], so the ResizeObserver is set up once. builderRef.current is updated via the ref-update effect, but the plot only rebuilds on container resize. If the underlying data changes (e.g., props update causing a new builder closure), the plot shows stale content until the next resize event. This is fine for the current carousel (static data), but could cause confusion if the hook is reused with dynamic data.

A simple fix: extract the render logic into a helper and also call it from the ref-update effect, or add a deps parameter to the hook's main effect.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/charts/usePlot.ts` around lines 22 - 40, The plot rendering in
usePlot only updates on ResizeObserver events, so a new builder closure can
leave stale content visible until resize. Update usePlot so the render path is
also triggered when builderRef.current changes, either by extracting the plot
निर्माण logic into a shared helper and calling it from the ref-update effect or
by adding a deps parameter to the main effect. Keep the ResizeObserver setup in
usePlot, but ensure the latest builder closure rebuilds the plot immediately
after props/data changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/resource-chart/ResourceChartClient.tsx`:
- Around line 89-156: The horizontal bar chart in BarChart can be taller than
the carousel slide height, causing the plot content to be clipped by the outer
h-full overflow-hidden container. Update the bar-h slide configuration in the
carousel (where config.height is set) so it is at least 330, or lower the bar
chart limit so BarChart’s minHeight stays within the available height; use the
BarChart component and the fossil-co2-emitters slide config as the key locations
to adjust.

In `@src/components/resource-chart/transform.ts`:
- Around line 63-72: The aggregate helper currently returns 0 for empty buckets,
which makes empty min/max buckets look like real zero-valued points. Update
aggregate in transform.ts so the min/max branches do not hit the generic
empty-values fallback; instead return null or NaN when acc.values is empty, and
widen the return type accordingly. Keep count and avg behavior intact, and
ensure the downstream Number.isFinite filter in the resource chart transform
continues to drop these empty min/max results.
- Around line 97-104: `limitPoints` has a division-by-zero edge case when
`limit` is 1 and `preserveRange` is true, causing the sampled result to become
empty instead of returning one point. Update the `limitPoints` logic to handle
the `limit === 1` case explicitly before computing `step`, and return a single
preserved point (for example the first or only sampled point) when used by the
line-chart path. Keep the fix localized in `limitPoints` and ensure the existing
`preserveRange` sampling behavior still works for `limit > 1`.

---

Nitpick comments:
In `@src/app/`[locale]/page.tsx:
- Around line 196-197: Wrap HomeDataSignalCarousel in a Suspense boundary so the
page can render the hero/stats immediately while the async server component
streams in. Update the page component in the locale page to render
HomeDataSignalCarousel with Suspense and provide a lightweight fallback, keeping
the existing HomeDataSignalCarousel usage intact.

In `@src/components/resource-chart/ResourceChart.tsx`:
- Around line 25-33: The async IIFE used to assign state in ResourceChart is
unnecessarily complex; replace it with a direct try/catch around the
fetchRows/resource chart state creation logic. Use a simple let binding for
state in ResourceChart and keep the existing error handling and fallback state
behavior unchanged.

In `@src/components/resource-chart/transform.ts`:
- Around line 16-23: The toNumber helper in transform.ts has a redundant comma
in the cleanup regex, which is confusing to read. Update the regex used in
toNumber to remove the duplicate comma character while preserving the existing
normalization behavior for values handled by toNumber.

In `@src/lib/charts/usePlot.ts`:
- Around line 22-40: The plot rendering in usePlot only updates on
ResizeObserver events, so a new builder closure can leave stale content visible
until resize. Update usePlot so the render path is also triggered when
builderRef.current changes, either by extracting the plot निर्माण logic into a
shared helper and calling it from the ref-update effect or by adding a deps
parameter to the main effect. Keep the ResizeObserver setup in usePlot, but
ensure the latest builder closure rebuilds the plot immediately after props/data
changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2bae728e-eeca-4f0e-a759-0e94ce62efb7

📥 Commits

Reviewing files that changed from the base of the PR and between feebd1a and 9ffbe17.

📒 Files selected for processing (20)
  • messages/en.json
  • src/app/[locale]/page.tsx
  • src/components/csv-explorer/DataProvider.tsx
  • src/components/csv-explorer/SearchDataForm.tsx
  • src/components/home/HomeDataSignalCarousel.tsx
  • src/components/home/HomeDataSignalCarouselClient.tsx
  • src/components/resource-chart/ResourceChart.tsx
  • src/components/resource-chart/ResourceChartClient.tsx
  • src/components/resource-chart/client.ts
  • src/components/resource-chart/fetchers.ts
  • src/components/resource-chart/index.ts
  • src/components/resource-chart/transform.ts
  • src/components/resource-chart/types.ts
  • src/lib/charts/format.ts
  • src/lib/charts/usePlot.ts
  • src/lib/ckan/api.ts
  • src/lib/ckan/resource.ts
  • src/lib/csv.ts
  • src/lib/dms.ts
  • src/lib/parseCsv.ts

Comment thread src/components/resource-chart/ResourceChartClient.tsx
Comment thread src/components/resource-chart/transform.ts Outdated
Comment thread src/components/resource-chart/transform.ts
@willy1989cv willy1989cv merged commit 79e792f into main Jul 8, 2026
4 checks passed
@willy1989cv willy1989cv deleted the feat/resource-chart branch July 8, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant