Skip to content

Conversation

@adityathebe
Copy link
Member

@adityathebe adityathebe commented Dec 9, 2025

Summary by CodeRabbit

  • New Features

    • Added a Playbooks panel to audit reports with integrated Run action that loads playbook details and opens a submit form.
    • Smart scroll indicators in long panel lists for clearer navigation.
  • Refactor

    • Standardized panel layout via a shared panel wrapper for consistent headers, descriptions, and styling across report panels.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 9, 2025

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

Project Deployment Preview Updated (UTC)
aws-preview Ready Ready Preview Dec 11, 2025 0:03am
flanksource-ui Ready Ready Preview Dec 11, 2025 0:03am

@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Walkthrough

Adds a new PlaybooksPanel and PanelWrapper, refactors multiple existing panels to use PanelWrapper, updates View to render "playbooks" panels, extends panel types with "playbooks", and adds a cross-browser hoverScrollbar CSS class.

Changes

Cohort / File(s) Change Summary
New PlaybooksPanel
src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx
New default-export panel that lists playbook rows, supports "Run" which fetches playbook specs via hook and opens SubmitPlaybookRunForm modal; manages selection, loading, scroll indicator, and empty state.
New PanelWrapper
src/pages/audit-report/components/View/panels/PanelWrapper.tsx
New reusable wrapper component providing standardized title, optional description, container styling, and children slot.
Panels refactored to use PanelWrapper
src/pages/audit-report/components/View/panels/{BarGaugePanel,DurationPanel,NumberPanel,PieChartPanel,TablePanel,TextPanel}.tsx
Replaced inline header/description and outer wrappers with PanelWrapper usage; internal rendering logic preserved.
Panels barrel export updated
src/pages/audit-report/components/View/panels/index.ts
Exports PlaybooksPanel from the panels index.
View updated
src/pages/audit-report/components/View/View.tsx
Imports panels export and adds a render branch for panel.type === "playbooks" to render PlaybooksPanel.
Type update
src/pages/audit-report/types/index.ts
Extended PanelResult.type union to include the "playbooks" value.
CSS utility added
src/utils/mixins.module.css
Added hoverScrollbar class to enable overflow-y scrolling while hiding scrollbars across browsers.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant PlaybooksPanel
    participant API as useGetPlaybookSpecsDetails
    participant Modal as SubmitPlaybookRunForm

    User->>PlaybooksPanel: View playbook rows
    User->>PlaybooksPanel: Click "Run" on a row
    PlaybooksPanel->>PlaybooksPanel: set selectedRow, set loading
    PlaybooksPanel->>API: fetch playbook specs (component_id, config_id, check_id)
    API-->>PlaybooksPanel: return specs
    PlaybooksPanel->>Modal: open with prefilled ids and params
    User->>Modal: submit or close
    Modal-->>PlaybooksPanel: close
    PlaybooksPanel->>PlaybooksPanel: clear selectedRow, clear loading
Loading

Possibly related PRs

Suggested reviewers

  • moshloop

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat/playbooks panel' directly corresponds to the main change: introducing a new PlaybooksPanel component and integrating it into the audit report view system.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/playbooks-panel

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/utils/mixins.module.css (1)

22-32: Class name may be misleading.

The class hoverScrollbar always hides the scrollbar rather than showing it on hover. If the intent was to reveal the scrollbar on hover, add a :hover pseudo-class rule. If permanent hiding is intentional, consider renaming to hiddenScrollbar for clarity.

If hover-reveal behavior is desired:

 .hoverScrollbar {
   overflow-y: auto;
   scrollbar-width: none; /* Firefox */
   -ms-overflow-style: none; /* IE/Edge */
 }

 .hoverScrollbar::-webkit-scrollbar {
   display: none; /* Safari/Chrome */
   width: 0;
   height: 0;
 }
+
+.hoverScrollbar:hover {
+  scrollbar-width: thin; /* Firefox */
+  -ms-overflow-style: auto; /* IE/Edge */
+}
+
+.hoverScrollbar:hover::-webkit-scrollbar {
+  display: block;
+  width: 8px;
+}
+
+.hoverScrollbar:hover::-webkit-scrollbar-thumb {
+  background: rgba(160, 160, 160, 0.7);
+  border-radius: 4px;
+}
src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (1)

66-74: Missing dependency in useEffect.

checkScrollPosition is referenced inside useEffect but not included in the dependency array. While this works because the function only uses the stable ref, ESLint's exhaustive-deps rule would flag this. Consider using useCallback or inlining the logic.

+import { useMemo, useState, useRef, useEffect, useCallback } from "react";
+
-  // Check scroll position to show/hide indicator
-  const checkScrollPosition = () => {
+  // Check scroll position to show/hide indicator
+  const checkScrollPosition = useCallback(() => {
     const container = scrollContainerRef.current;
     if (!container) return;

     const { scrollTop, scrollHeight, clientHeight } = container;
     const isScrollable = scrollHeight > clientHeight;
     const isAtBottom = scrollHeight - scrollTop - clientHeight < 10;

     setShowScrollIndicator(isScrollable && !isAtBottom);
-  };
+  }, []);

   // Set up scroll listener and check initial state
   useEffect(() => {
     const container = scrollContainerRef.current;
     if (!container) return;

     checkScrollPosition();

     container.addEventListener("scroll", checkScrollPosition);
     return () => container.removeEventListener("scroll", checkScrollPosition);
-  }, [rows]);
+  }, [rows, checkScrollPosition]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ae198b and 15863d3.

📒 Files selected for processing (12)
  • src/pages/audit-report/components/View/View.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/BarGaugePanel.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/DurationPanel.tsx (2 hunks)
  • src/pages/audit-report/components/View/panels/NumberPanel.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/PanelWrapper.tsx (1 hunks)
  • src/pages/audit-report/components/View/panels/PieChartPanel.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (1 hunks)
  • src/pages/audit-report/components/View/panels/TablePanel.tsx (2 hunks)
  • src/pages/audit-report/components/View/panels/TextPanel.tsx (2 hunks)
  • src/pages/audit-report/components/View/panels/index.ts (1 hunks)
  • src/pages/audit-report/types/index.ts (1 hunks)
  • src/utils/mixins.module.css (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/pages/audit-report/components/View/panels/TablePanel.tsx (1)
src/pages/audit-report/types/index.ts (1)
  • PanelResult (478-496)
src/pages/audit-report/components/View/View.tsx (1)
src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (1)
  • PlaybooksPanel (33-172)
🔇 Additional comments (12)
src/pages/audit-report/components/View/panels/PanelWrapper.tsx (1)

3-36: PanelWrapper abstraction looks consistent and reusable

Props cover current usage (title/description plus overrideable class names), and the container styling provides a sensible, uniform panel shell for the other components.

src/pages/audit-report/components/View/panels/TextPanel.tsx (1)

3-25: TextPanel correctly delegates header/description to PanelWrapper

Each row is now wrapped in PanelWrapper with consistent title/description handling, while the value rendering and keys remain unchanged, so behavior should be preserved.

src/pages/audit-report/components/View/panels/TablePanel.tsx (1)

11-35: TablePanel now uses PanelWrapper without affecting table rendering

Wrapping the table body with PanelWrapper centralizes the header/description styling while leaving row iteration and cell content unchanged.

src/pages/audit-report/components/View/panels/NumberPanel.tsx (1)

4-41: NumberPanel’s PanelWrapper usage preserves existing value behavior

Per-row PanelWrapper titles correctly use label || summary.name, and the numeric formatting path is unchanged, so this is a safe structural improvement.

src/pages/audit-report/components/View/panels/BarGaugePanel.tsx (1)

4-126: BarGaugePanel wrapping with PanelWrapper is purely structural

The gauge configuration and rendering logic are untouched; using PanelWrapper standardizes the header/description styling around the existing bar gauge UI.

src/pages/audit-report/components/View/panels/DurationPanel.tsx (1)

4-38: DurationPanel cleanly migrated to per-row PanelWrapper

Each duration row now lives inside a PanelWrapper with appropriate title/description, while the nanoseconds → milliseconds conversion and formatDuration call remain as before.

src/pages/audit-report/components/View/panels/PieChartPanel.tsx (1)

12-130: PieChartPanel’s adoption of PanelWrapper keeps chart logic intact

Only the outer container is swapped for PanelWrapper with a min-height; the pie data generation and Recharts setup are unchanged, so functionality should be preserved with more consistent panel styling.

src/pages/audit-report/types/index.ts (1)

478-495: PanelResult type extension to include "properties" and "playbooks" looks correct

Extending the type union ensures the compiler is aware of these panel variants while keeping the rest of the shape unchanged.

src/pages/audit-report/components/View/panels/index.ts (1)

9-9: LGTM!

The export follows the established pattern for panel barrel exports.

src/pages/audit-report/components/View/View.tsx (2)

28-30: LGTM!

The import addition follows the existing pattern for panel imports.


431-432: LGTM!

The new case follows the established pattern for rendering panel types.

src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (1)

76-157: LGTM on the UI implementation.

The component structure is well-organized with proper empty state handling, accessible button states during loading, and a thoughtful scroll indicator UX pattern.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (1)

49-54: Consider adding error handling for failed playbook fetches.

The useGetPlaybookSpecsDetails hook can return an error state, but it's not currently destructured or handled. If the fetch fails, the button simply returns to the "Run" state with no user feedback, which could be confusing.

Consider destructuring the error and showing feedback:

-  const { data: playbookSpec, isLoading } = useGetPlaybookSpecsDetails(
+  const { data: playbookSpec, isLoading, error } = useGetPlaybookSpecsDetails(
     selected?.id ?? "",
     {
       enabled: !!selected?.id
     }
   );

Then display an error state or toast notification when error is truthy, so users understand why the modal didn't open.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15863d3 and 11104fd.

📒 Files selected for processing (12)
  • src/pages/audit-report/components/View/View.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/BarGaugePanel.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/DurationPanel.tsx (2 hunks)
  • src/pages/audit-report/components/View/panels/NumberPanel.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/PanelWrapper.tsx (1 hunks)
  • src/pages/audit-report/components/View/panels/PieChartPanel.tsx (3 hunks)
  • src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (1 hunks)
  • src/pages/audit-report/components/View/panels/TablePanel.tsx (2 hunks)
  • src/pages/audit-report/components/View/panels/TextPanel.tsx (2 hunks)
  • src/pages/audit-report/components/View/panels/index.ts (1 hunks)
  • src/pages/audit-report/types/index.ts (1 hunks)
  • src/utils/mixins.module.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/pages/audit-report/components/View/panels/BarGaugePanel.tsx
  • src/utils/mixins.module.css
  • src/pages/audit-report/components/View/panels/TextPanel.tsx
  • src/pages/audit-report/types/index.ts
  • src/pages/audit-report/components/View/panels/NumberPanel.tsx
  • src/pages/audit-report/components/View/panels/PanelWrapper.tsx
🧰 Additional context used
🧬 Code graph analysis (3)
src/pages/audit-report/components/View/panels/TablePanel.tsx (1)
src/pages/audit-report/types/index.ts (1)
  • PanelResult (478-496)
src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (3)
src/components/Playbooks/Runs/Submit/SubmitPlaybookRunForm.tsx (2)
  • SubmitPlaybookRunFormValues (25-32)
  • SubmitPlaybookRunForm (45-161)
src/pages/audit-report/types/index.ts (1)
  • PanelResult (478-496)
src/api/query-hooks/playbooks.tsx (1)
  • useGetPlaybookSpecsDetails (96-111)
src/pages/audit-report/components/View/View.tsx (1)
src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (1)
  • PlaybooksPanel (33-179)
🔇 Additional comments (7)
src/pages/audit-report/components/View/panels/TablePanel.tsx (1)

3-3: LGTM! Clean refactor to PanelWrapper.

The refactoring to use PanelWrapper standardizes the panel layout and is consistent with other panels in the PR.

Also applies to: 11-15, 34-34

src/pages/audit-report/components/View/panels/DurationPanel.tsx (1)

4-4: LGTM! Consistent with the PanelWrapper refactor pattern.

The refactor aligns with the broader PR changes to standardize panel layout using PanelWrapper.

Also applies to: 26-31, 37-37

src/pages/audit-report/components/View/panels/index.ts (1)

9-9: LGTM! Export completes the public API surface.

The export makes PlaybooksPanel available for use in the view rendering flow.

src/pages/audit-report/components/View/panels/PieChartPanel.tsx (1)

12-12: LGTM! PanelWrapper refactor with appropriate styling.

The addition of min-h-[300px] ensures the chart has adequate display space. Refactor is consistent with other panels.

Also applies to: 102-106, 130-130

src/pages/audit-report/components/View/View.tsx (1)

28-29: LGTM! PlaybooksPanel integration is correct.

The import and rendering case for PlaybooksPanel properly integrates the new panel type into the view rendering flow.

Also applies to: 431-432

src/pages/audit-report/components/View/panels/PlaybooksPanel.tsx (2)

34-44: Excellent fix! Runtime validation now properly guards against invalid data.

The type guard correctly validates that each row is an object with a non-empty id string before treating it as a PlaybookRunRow. This addresses the previous concern about unsafe casting.


166-166: Good fix for the stale data race condition.

The added check playbookSpec.id === selected.id ensures the modal only renders when the fetched spec matches the currently selected row, preventing mismatched data from appearing if the user rapidly switches selections.

@netlify
Copy link

netlify bot commented Dec 19, 2025

Deploy Preview for clerk-saas-ui failed. Why did it fail? →

Name Link
🔨 Latest commit 11104fd
🔍 Latest deploy log https://app.netlify.com/projects/clerk-saas-ui/deploys/693ab19fb39eb3000849d514

@netlify
Copy link

netlify bot commented Dec 19, 2025

Deploy Preview for flanksource-demo-stable failed. Why did it fail? →

Name Link
🔨 Latest commit 11104fd
🔍 Latest deploy log https://app.netlify.com/projects/flanksource-demo-stable/deploys/693ab19fb39eb3000849d512

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.

2 participants