Skip to content

Build Reachability Frontend #72

Draft
Hubtrick-Git wants to merge 7 commits intomainfrom
build-reachability-analysis-frontend
Draft

Build Reachability Frontend #72
Hubtrick-Git wants to merge 7 commits intomainfrom
build-reachability-analysis-frontend

Conversation

@Hubtrick-Git
Copy link
Collaborator

@Hubtrick-Git Hubtrick-Git commented Jan 29, 2026

Minimal requirements:

  • Creating the new page
  • A working search for the hero section
    • Api request to vex-server is mocked
    • Results are logged to the console

Functional Requirements:

  • Display the response in a table
  • Add a good description to the page
  • Make each vuln clickable?

Stylistic Requirements:

  • Overhaul the visuals
  • Unify looks with other similar pages

Finalized status

  • The functionality of the frontend page is provided.
  • Since the api endpoint does not exist yet I do not know the format of the data received so I cannot yet display it visually organized.
  • The same is true for the detail-page of a specific analysis.
  • Therefor the UI looks kinda ugly and is just a placeholder to have some guiding lines when finalizing the page later on in the process of merging different docu frontend pages.

@seb-kw
Copy link
Member

seb-kw commented Feb 2, 2026

Looks nice 😊 - like that small micro animation when typing away.....

Copy link
Member

@timbastin timbastin left a comment

Choose a reason for hiding this comment

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

Overall, this looks really great! I love the splitting in table and hero. I think we can improve this further by extracting the whole logic into a container component which just renders some presentational components while providing state and mutation functions.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new reachability analysis feature to the frontend, adding search functionality and visualization for vulnerability reachability data. The feature includes a main search page, detail pages for individual packages, and supporting UI components. The implementation uses placeholder API endpoints since the backend is not yet finalized, as noted in the PR description.

Changes:

  • Added new reachability analysis pages with search and display functionality
  • Integrated new dependencies (SWR for data fetching, TanStack Table for data tables, Recharts for future visualizations)
  • Created reusable UI components (table, skeleton, input) following shadcn/ui patterns

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 26 comments.

Show a summary per file
File Description
src/pages/reachability-analysis.mdx Main entry point for reachability analysis page
src/pages/reachability-analysis/[purl].mdx Dynamic route for package-specific details with custom styling
src/pages/_meta.ts Navigation configuration for new reachability page
src/lib/fetcher.js Simple fetcher utility for SWR data fetching
src/components/ui/table.tsx Reusable table component following shadcn/ui patterns
src/components/ui/skeleton.tsx Loading skeleton component for better UX
src/components/ui/input.tsx Form input component with consistent styling
src/components/reachabilityAnalysis/reachability-types.tsx TypeScript type definitions for API responses
src/components/reachabilityAnalysis/reachability-analysis-results-table.tsx Table component displaying search results with pagination
src/components/reachabilityAnalysis/reachability-analysis-page.tsx Main page component managing search state and API calls
src/components/reachabilityAnalysis/reachability-analysis-package-details.tsx Detail view for individual packages with collapsible sections
src/components/reachabilityAnalysis/reachability-analysis-hero.tsx Hero section with search input
src/components/reachabilityAnalysis/columns.tsx Column definitions for data table
package.json Added dependencies for SWR, TanStack Table, Recharts, and date-fns
package-lock.json Lockfile updates for new dependencies
.gitignore Minor cleanup and reorganization

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

import { fetcher } from 'src/lib/fetcher'
import useSWR from 'swr'

const apiBaseURL = 'http://localhost:8080/api/v1/vulndb/reachability/'
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The unused constant 'apiBaseURL' is declared but never used. Consider removing it or using it instead of the hardcoded URL on line 26.

Copilot uses AI. Check for mistakes.



export default function CVEDetailComponent({ purl }: { purl?: string }) {
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The function is named 'CVEDetailComponent' but it displays package details for reachability analysis, not CVE details. The name should be updated to 'PackageDetailComponent' or 'ReachabilityAnalysisPackageDetails' to accurately reflect its purpose.

Suggested change
export default function CVEDetailComponent({ purl }: { purl?: string }) {
export default function ReachabilityAnalysisPackageDetails({ purl }: { purl?: string }) {

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +57
<Skeleton className="h-6 w-48"
/>
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

There's a missing closing tag for the Skeleton component. The line should end with '/>' instead of just '/>'. This will cause a syntax error.

Suggested change
<Skeleton className="h-6 w-48"
/>
<Skeleton className="h-6 w-48" />

Copilot uses AI. Check for mistakes.
Comment on lines +151 to +159
<div>
{data.vulnerabilities.map((vuln) => (
<div className='flex'>
<p className='px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50'>{vuln.id}</p>
<p className='px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50'>{vuln['bom-ref']}</p>
</div>
))}
</div>
</div>
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Missing key prop in the map function. Each element in the list should have a unique 'key' prop for React to efficiently update the list. Add a unique key based on vulnerability data.

Suggested change
<div>
{data.vulnerabilities.map((vuln) => (
<div className='flex'>
<p className='px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50'>{vuln.id}</p>
<p className='px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50'>{vuln['bom-ref']}</p>
</div>
))}
</div>
</div>
<div>
{data.vulnerabilities.map((vuln) => (
<div className="flex" key={vuln.id}>
<p className="px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50">{vuln.id}</p>
<p className="px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50">{vuln['bom-ref']}</p>
</div>
))}
</div>
</div>

Copilot uses AI. Check for mistakes.
Comment on lines +127 to +148
<button
onClick={() => setIsVulnerabilitiesOpen(!isVulnerabilitiesOpen)}
className="flex w-full items-center justify-between p-6 text-left transition-colors hover:bg-gray-50 dark:hover:bg-gray-700/50"
>
<h2 className="text-lg font-medium text-gray-950 dark:text-white">
Vulnerabilities (
{data.vulnerabilities.length})
</h2>
<svg
className={`h-5 w-5 transition-transform ${isVulnerabilitiesOpen ? 'rotate-180' : ''}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</svg>
</button>
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Similar to the Components section, this collapsible Vulnerabilities button lacks proper ARIA attributes. Add aria-expanded={isVulnerabilitiesOpen} to indicate its state to screen reader users.

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +31
const description = row.getValue('type') as string
return <div className="w-108">{description}</div>
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The variable 'description' is misleading since it's actually holding the 'type' value, not a description. Rename to 'type' or 'packageType' for clarity.

Suggested change
const description = row.getValue('type') as string
return <div className="w-108">{description}</div>
const packageType = row.getValue('type') as string
return <div className="w-108">{packageType}</div>

Copilot uses AI. Check for mistakes.
import { useState } from 'react'
import { Container } from '../top-level-pages/container'
import { ReachabilityAnalysisResponse } from 'src/components/reachabilityAnalysis/reachability-types'
import { Label, Pie, PieChart } from 'recharts'
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The imports 'Label', 'Pie', and 'PieChart' from 'recharts' are unused and should be removed.

Suggested change
import { Label, Pie, PieChart } from 'recharts'

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +117
{data.components.map((comp) => (
<div className='flex'>
<p className='px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50'>{comp.name}</p>
<p className='px-4 mx-8 my-4 py-4 rounded-lg border border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50'>{comp.type}</p>
</div>
))}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

Missing key prop in the map function. Each element in the list should have a unique 'key' prop for React to efficiently update the list. Add a unique key based on component data.

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +63
export interface ReachabilityAnalysisResponse{
bomFormat : string
specVersion : string
serialNumber : string
version : number
metadata : Metadata
components : Component[]
vulnerabilities : Vulnerability[]
}

interface Metadata{
timestamp : string
tools : Tool[]
}

interface Tool{
vendor : string
name : string
version : string
}

interface Component {
type : string
name : string
purl : string
"bom-ref" : string
}

interface Vulnerability{
"bom-ref" : string
id : string
description : string
affects : Affect[]
analysis : Analysis
}

interface Affect{
ref : string
}

interface Analysis {
state : string
detail : string
evidence : Evidence[]
}

interface Evidence {
path : PathElement[]
}


interface PathElement{
id: number;
cve_id: string;
signature: string;
filename: string;
start_line: number;
end_line: number;
evidence: string;
purl: string;
calls_id: number | null;
} No newline at end of file
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The interface properties are using inline type definitions with spaces around the colon (e.g., 'bomFormat : string'). TypeScript convention is to have no space before the colon and one space after (e.g., 'bomFormat: string') for consistency with the rest of the codebase.

Copilot uses AI. Check for mistakes.

if (!isLoading && data.length == 0) {
return (
<div className='my-40'>
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

When there's no data and not loading, an empty div is returned with no user feedback. Consider displaying a message like "No packages found. Try searching for a package." to improve user experience.

Suggested change
<div className='my-40'>
<div className="my-40 flex items-center justify-center text-sm text-muted-foreground">
No packages found. Try searching for a package.

Copilot uses AI. Check for mistakes.
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.

3 participants