feat(dashboard): add Grad-CAM heatmap overlay visualizer#106
Conversation
|
@Deepak06-v is attempting to deploy a commit to the karan3431's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Warning Review limit reached
More reviews will be available in 39 minutes and 15 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the 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 credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. 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, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
Warning
|
| Layer / File(s) | Summary |
|---|---|
State declarations and icon imports src/pages/AnalysisDashboard.tsx |
Adds lucide-react icons for the overlay UI and declares component state for Grad-CAM image, loading/error status, blend opacity, retry trigger, and derived photo_url. |
Grad-CAM fetch effect and retry handler src/pages/AnalysisDashboard.tsx |
Introduces a useEffect that downloads the scan image as a blob, calls api.getGradcam, stores gradcam_image, and manages loading/error state with an isMounted cleanup guard; adds handleRetry to re-trigger the effect. |
Grad-CAM overlay layout and controls src/pages/AnalysisDashboard.tsx |
Reworks the main render path to display a stacked visualization card (original image + conditional heatmap overlay) with toggle buttons, blend opacity slider and range input, a legend overlay, and dedicated loading/error/retry UI when photo_url is present; retains a fallback to the prior stats-only card layout when no photo_url is available. |
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45 minutes
Poem
🐇 Hippity-hop, what do I see?
A heatmap glowing, warm as tea!
The fish's freshness, pixel-bright,
Blended layers, just right.
Retry with a click, the colors flow—
GradCAM's magic puts on a show! 🐠
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title accurately and concisely describes the main feature addition: a Grad-CAM heatmap overlay visualizer for the dashboard. |
| Linked Issues check | ✅ Passed | The implementation fully addresses issue #46 requirements: retrieves base64 heatmap from /api/v1/gradcam endpoint, builds an overlay component, and provides toggle controls between original and heatmap views. |
| Out of Scope Changes check | ✅ Passed | The PR focuses exclusively on Grad-CAM visualization in AnalysisDashboard with necessary icon imports; no unrelated changes detected. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
|
Give the issue no. |
46 |
|
This is an incredible implementation! The slider and the mix-blend-multiply CSS overlay are exactly what we wanted. However, because main moved fast this week, your branch is out of date and currently reverts our recent bug fixes for the Offline Mode in AnalysisDashboard.tsx. Please git pull origin main to sync your branch and restore the offlineScanResult fallback block in the load() function. Once that's synced, we will merge this immediately |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/pages/AnalysisDashboard.tsx (2)
80-125: ⚡ Quick winConsider adding AbortController for request cancellation.
The effect uses
isMountedto prevent state updates after unmount, but in-flight requests are not cancelled. If the user navigates away or clicks retry rapidly, previous requests continue unnecessarily. Adding an AbortController improves resource efficiency and prevents potential race conditions with rapid retries.♻️ Proposed refactor with AbortController
useEffect(() => { if (!photo_url) return; const url = photo_url; let isMounted = true; + const controller = new AbortController(); async function loadGradcam() { setGradcamLoading(true); setGradcamError(null); try { - const res = await fetch(url); + const res = await fetch(url, { signal: controller.signal }); if (!res.ok) { throw new Error(`Failed to download scan image (${res.status})`); } const blob = await res.blob(); const gradcamRes = await api.getGradcam(blob); if (isMounted) { setGradcamImage(gradcamRes.gradcam_image); } } catch (err) { + if (err instanceof DOMException && err.name === 'AbortError') { + return; // Request was cancelled, no error handling needed + } console.error("Grad-CAM generation error:", err); if (isMounted) { setGradcamError( err instanceof Error ? err.message : "Heatmap generation failed." ); } } finally { if (isMounted) { setGradcamLoading(false); } } } loadGradcam(); return () => { isMounted = false; + controller.abort(); }; }, [photo_url, retryTrigger]);🤖 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/pages/AnalysisDashboard.tsx` around lines 80 - 125, The useEffect hook in the loadGradcam function uses isMounted flag to prevent state updates after unmount, but in-flight network requests (the fetch call and the api.getGradcam call) are not being cancelled, wasting resources on unnecessary requests if the user navigates away or retries rapidly. Add an AbortController instance at the beginning of the loadGradcam function, pass its signal to both the fetch call and the api.getGradcam call, and then call the abort method on the controller in the cleanup function (where isMounted is currently set to false) to ensure all pending requests are properly cancelled when the effect is cleaned up.
319-364: ⚖️ Poor tradeoffConsider extracting duplicated score card and species panel into reusable components.
The score card (lines 319-364 vs 411-456) and species panel (lines 367-405 vs 459-497) are nearly identical across both layout branches. Extracting these into
<ScoreCard>and<SpeciesPanel>components would reduce duplication and simplify future maintenance.Also applies to: 411-456
🤖 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/pages/AnalysisDashboard.tsx` around lines 319 - 364, The GlassCard component displaying the score information with grade, freshness_index, classification, and confidence fields is duplicated across multiple layout branches in the file. Create two new reusable components: extract the GlassCard structure (starting with className "p-8 relative overflow-hidden") into a ScoreCard component that accepts props for grade, freshness_index, classification, and confidence, and similarly extract the species panel structure into a SpeciesPanel component. Then replace all duplicated instances of these card layouts with calls to the new components, passing the appropriate data as props to eliminate the duplication across the different layout branches.
🤖 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/pages/AnalysisDashboard.tsx`:
- Around line 221-228: The className on the div element wrapping the color
legend map contains an invalid Tailwind z-index utility class `z-25`, which is
not part of the standard Tailwind scale (z-0, z-10, z-20, z-30, z-40, z-50).
Replace `z-25` with `z-30` to ensure the legend layers correctly above overlays
and properly apply z-index styling.
---
Nitpick comments:
In `@src/pages/AnalysisDashboard.tsx`:
- Around line 80-125: The useEffect hook in the loadGradcam function uses
isMounted flag to prevent state updates after unmount, but in-flight network
requests (the fetch call and the api.getGradcam call) are not being cancelled,
wasting resources on unnecessary requests if the user navigates away or retries
rapidly. Add an AbortController instance at the beginning of the loadGradcam
function, pass its signal to both the fetch call and the api.getGradcam call,
and then call the abort method on the controller in the cleanup function (where
isMounted is currently set to false) to ensure all pending requests are properly
cancelled when the effect is cleaned up.
- Around line 319-364: The GlassCard component displaying the score information
with grade, freshness_index, classification, and confidence fields is duplicated
across multiple layout branches in the file. Create two new reusable components:
extract the GlassCard structure (starting with className "p-8 relative
overflow-hidden") into a ScoreCard component that accepts props for grade,
freshness_index, classification, and confidence, and similarly extract the
species panel structure into a SpeciesPanel component. Then replace all
duplicated instances of these card layouts with calls to the new components,
passing the appropriate data as props to eliminate the duplication across the
different layout branches.
🪄 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 Plus
Run ID: d451b1ec-31ac-4f88-8d58-25713e4c88a6
📒 Files selected for processing (1)
src/pages/AnalysisDashboard.tsx
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Description
Closes #46
This PR resolves the issue by integrating the Grad-CAM activation map overlay visualization on the scan analysis page (
AnalysisDashboard.tsx).Key changes:
photo_urlfrom the scan result and fetches the image in the frontend, sending it to the backend/api/v1/gradcamendpoint to generate the Grad-CAM base64 JPEG heatmap.LOW → HIGHcolor gradient bar when the heatmap is visible.Checklist
npm run lintpasses with no errorsnpm run buildcompiles without TypeScript errorspython -m pytestpasses (including new tests I added).envfiles, API keys, secrets, model weights, or__pycache__in this diffmain, not mergedSummary by CodeRabbit