@basic-genomics/hivdb-report
v2.0.5
Published
React component library for displaying HIV drug resistance analysis results
Maintainers
Readme
@basic-genomics/hivdb-report
React component library for displaying HIV drug resistance analysis results from the Stanford HIVDB.
Table of Contents
- Features
- Installation
- Quick Start
- Usage Modes
- Props
- Advanced Examples
- Configuration
- Data Structure
- API Integration
- Styling
- Browser Support
- TypeScript Support
- Development
- Troubleshooting
- Performance Considerations
- License
Features
- 📊 Complete Report Display - Sequence summary, drug resistance interpretation, mutation analysis
- 🎨 Customizable Theme - Configure primary colors to match your brand
- 📱 Responsive Design - Works on desktop and mobile devices
- 📤 Multiple Export Formats - HTML, CSV, JSON export support
- 🔄 Flexible Data Input - Direct data props or API-based sequence input
- 🔌 API Integration - Built-in support for custom API endpoints
- 📜 Custom Scroll Container - Support for non-window scroll scenarios with anchor navigation
- ⚡ Production Ready - Enterprise-grade code quality, used in production environments
Installation
npm install @basic-genomics/hivdb-report
# or
yarn add @basic-genomics/hivdb-report
# or
pnpm add @basic-genomics/hivdb-reportQuick Start
import { HIVDBReport } from '@basic-genomics/hivdb-report';
function App() {
// Data from HIVDB GraphQL API
const reportData = {
currentVersion: { text: 'HIVDB_9.8', publishDate: '2025-01-05' },
currentProgramVersion: { text: '3.5.3', publishDate: '2025-01-05' },
sequenceAnalysis: [
{
inputSequence: { header: 'Sample1' },
strain: { name: 'HIV1', display: 'HIV-1' },
bestMatchingSubtype: { display: 'B (2.26%)' },
// ... analysis results
}
]
};
return <HIVDBReport reportData={reportData} />;
}Usage Modes
The component supports two mutually exclusive modes:
Mode 1: Direct Data Mode (Default)
Provide analysis data directly via props. Best for pre-fetched data or GraphQL integration.
<HIVDBReport reportData={analysisData} />Mode 2: Sequence Input Mode
Enable user sequence input with API integration. Best for interactive applications.
Request Function Injection
Use callback functions for full control over the request flow. This allows you to:
- Use your own HTTP client (axios, fetch, etc.)
- Integrate with your app's authentication system
- Apply unified error handling
- Use your existing API proxy configuration
import { HIVDBReport } from '@basic-genomics/hivdb-report';
function SequenceAnalyzer() {
// Host controls the entire request flow
const handleFetchReport = async (sequenceText) => {
const response = await myApiClient.post('/api/hivdb/analyze', {
sequences: parseSequences(sequenceText),
includeGenes: ['PR', 'RT', 'IN']
});
return response.data;
};
const handleFetchExport = async (sequenceText) => {
const response = await myApiClient.post('/api/hivdb/analyze-full', {
sequences: parseSequences(sequenceText),
includeGenes: ['PR', 'RT', 'IN']
});
return response.data;
};
return (
<HIVDBReport
enableSequenceInput={true}
onFetchReport={handleFetchReport}
onFetchExport={handleFetchExport}
/>
);
}Props
HIVDBReport
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| Data Props (Mode 1) |
| reportData | object | Conditional* | Analysis data for HTML report display |
| exportData | object | No | Analysis data for CSV/JSON export (includes additional fields) |
| analysisData | object | Conditional* | Legacy: single data source for both report and export |
| Sequence Input Props (Mode 2) |
| enableSequenceInput | boolean | No | Enable sequence input mode (default: false) |
| sequenceInputPlaceholder | string | No | Placeholder text for sequence input |
| Request Function Injection |
| onFetchReport | (sequenceText: string) => Promise<AnalysisData> | Conditional** | Host-provided function for report requests |
| onFetchExport | (sequenceText: string) => Promise<AnalysisData> | Conditional** | Host-provided function for export requests |
| onSequenceChange | (sequenceText: string) => void | No | Callback when sequence input changes |
| General Props |
| config | object | No | Configuration overrides (see Configuration section) |
| scrollContainer | HTMLElement \| null | No | Custom scroll container for non-window scroll scenarios |
*In Mode 1: Either
reportDataoranalysisDatais required.
**In Mode 2:onFetchReportis required for HTML reports;onFetchExportis required for CSV/JSON exports.
Data Source Options (Mode 1)
Option 1: Separate data sources (Recommended)
Use separate queries optimized for display vs export:
<HIVDBReport
reportData={reportQueryResult} // Lighter query for display
exportData={exportQueryResult} // Full query for export
/>Option 2: Single data source (Legacy)
Use one complete data object for both:
<HIVDBReport analysisData={fullQueryResult} />Advanced Examples
Sequence Input Mode Example
Best for enterprise applications with existing HTTP clients and error handling:
import { HIVDBReport } from '@basic-genomics/hivdb-report';
import { apiClient } from './api'; // Your axios instance with interceptors
function SequenceAnalyzer() {
// Full control over request flow
const handleFetchReport = async (sequenceText) => {
const response = await apiClient.post('/hivdb/analyze', {
sequences: parseSequences(sequenceText),
includeGenes: ['PR', 'RT', 'IN']
});
// Handle GraphQL errors
if (response.data.errors) {
throw new Error(response.data.errors[0]?.message);
}
return response.data.data;
};
const handleFetchExport = async (sequenceText) => {
const response = await apiClient.post('/hivdb/analyze-full', {
sequences: parseSequences(sequenceText),
includeGenes: ['PR', 'RT', 'IN']
});
if (response.data.errors) {
throw new Error(response.data.errors[0]?.message);
}
return response.data.data;
};
return (
<HIVDBReport
enableSequenceInput={true}
onFetchReport={handleFetchReport}
onFetchExport={handleFetchExport}
/>
);
}Note: The component displays a simulated progress bar during API requests.
Custom Scroll Container Example
When embedding the component in a layout with a custom scrollable container (not window), pass the container element:
import { useRef } from 'react';
import { HIVDBReport } from '@basic-genomics/hivdb-report';
function EmbeddedReport() {
const scrollContainerRef = useRef(null);
return (
<div
ref={scrollContainerRef}
style={{ height: '100vh', overflow: 'auto' }}
>
<HIVDBReport
enableSequenceInput={true}
onFetchReport={handleFetchReport}
scrollContainer={scrollContainerRef.current}
/>
</div>
);
}Note: The scroll container must have
overflow: autooroverflow: scrollto be scrollable. The component will automatically detect the actual scrollable ancestor if needed.
GraphQL Integration Example
import { useQuery } from '@apollo/client';
import { HIVDBReport } from '@basic-genomics/hivdb-report';
import { ANALYZE_SEQUENCES } from './queries';
function GraphQLReport({ sequences }) {
const { data, loading, error } = useQuery(ANALYZE_SEQUENCES, {
variables: { sequences }
});
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<HIVDBReport
reportData={data.viewer.sequenceAnalysis}
exportData={data.viewer.sequenceAnalysisWithGenes}
/>
);
}Configuration
Theme Colors
Customize the primary theme color to match your brand:
<HIVDBReport
reportData={data}
config={{
themeColors: {
main: '#1565c0', // Primary color (default: #8c1515 red)
mainLighter: '#1e88e5' // Hover/lighter variant (default: #d32424)
}
}}
/>Preset Theme Examples:
| Theme | main | mainLighter |
|-------|------|-------------|
| Red (default) | #8c1515 | #d32424 |
| Blue | #1565c0 | #1e88e5 |
| Green | #2e7d32 | #43a047 |
| Purple | #6a1b9a | #8e24aa |
| Teal | #00796b | #00897b |
| Orange | #e65100 | #f57c00 |
Full Configuration Example
import { HIVDBReport, defaultConfig } from '@basic-genomics/hivdb-report';
<HIVDBReport
reportData={data}
config={{
// Theme customization
themeColors: {
main: '#1565c0',
mainLighter: '#1e88e5'
},
// Gene display settings
allGenes: ['PR', 'RT', 'IN'],
highlightGenes: ['PR', 'RT', 'IN'],
// Display options
displayMutationScores: ['PR', 'RT', 'IN'],
displaySDRMs: ['PR', 'RT', 'IN'],
// Form settings
formEnableTabs: ['patterns', 'sequences', 'reads'],
// ... see defaultConfig for all options
}}
/>Data Structure
reportData / analysisData
The data should match the HIVDB GraphQL API response structure:
interface AnalysisData {
currentVersion?: {
text: string;
publishDate: string;
};
currentProgramVersion?: {
text: string;
publishDate: string;
};
sequenceAnalysis: Array<{
inputSequence: {
header: string;
};
strain: {
name: string;
display: string;
};
availableGenes: Array<{ name: string }>;
bestMatchingSubtype: {
display: string;
referenceAccession: string;
};
subtypes: Array<{
displayWithoutDistance: string;
distancePcnt: string;
referenceAccession: string;
referenceCountry: string;
referenceYear: number;
}>;
validationResults: Array<{
level: string;
message: string;
}>;
alignedGeneSequences: Array<{
gene: { name: string };
firstAA: number;
lastAA: number;
mutations: Array<{
text: string;
position: number;
primaryType: string;
}>;
}>;
drugResistance: Array<{
gene: { name: string };
drugScores: Array<{
drug: { name: string; displayAbbr: string };
score: number;
level: number;
text: string;
partialScores: Array<{
mutations: Array<{ text: string }>;
score: number;
}>;
}>;
}>;
}>;
mutationPrevalenceSubtypes?: Array<{
name: string;
stats: object;
}>;
}Exports
import {
HIVDBReport, // Main report component
defaultConfig // Default configuration object
} from '@basic-genomics/hivdb-report';API Integration
Request/Response Flow
When using enableSequenceInput={true}:
- User enters sequence(s) in FASTA format
- User selects output format (HTML Report / CSV/JSON)
- Component calls
onFetchReportoronFetchExportwith sequence text - A simulated progress bar is displayed during the request
- API response is validated for required fields
- Results are displayed or downloaded
Error Handling
The component provides built-in error handling:
- Input validation: Empty sequences are rejected
- API errors: Network failures and HTTP errors are caught
- Data validation: API responses are validated for required fields
- User feedback: Clear error messages are displayed
Security Best Practices
When implementing API integration with onFetchReport/onFetchExport:
// ✅ Good: Use environment variables for sensitive data
const handleFetchReport = async (sequenceText) => {
const response = await fetch(process.env.REACT_APP_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.REACT_APP_API_TOKEN}`
},
body: JSON.stringify({ sequences: sequenceText })
});
return response.json();
};
// ❌ Bad: Never hardcode tokens
const handleFetchReport = async (sequenceText) => {
const response = await fetch('https://api.example.com', {
headers: {
'Authorization': 'Bearer hardcoded-token-123' // Don't do this!
},
// ...
});
};Styling
The component includes all necessary styles automatically. No additional style imports are needed.
Note: If you encounter style issues, ensure your build system supports SCSS. The component uses SCSS for styling internally.
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
TypeScript Support
While the component is written in JavaScript, TypeScript definitions are provided for better IDE support:
import { HIVDBReport, AnalysisData } from '@basic-genomics/hivdb-report';
// Sequence Input Mode
const MyComponent: React.FC = () => {
const handleFetchReport = async (sequenceText: string): Promise<AnalysisData> => {
const result = await api.analyze(parseSequences(sequenceText));
return result;
};
return (
<HIVDBReport
enableSequenceInput={true}
onFetchReport={handleFetchReport}
/>
);
};
// Direct Data Mode
const DirectDataComponent: React.FC<{ data: AnalysisData }> = ({ data }) => {
return <HIVDBReport reportData={data} />;
};Development
# Install dependencies
yarn install
# Start development server (runs on port 3009)
yarn start
# Build for production
yarn build
# Run tests
yarn testTroubleshooting
Common Issues
Q: Styles are not loading correctly
A: Ensure your build system supports SCSS. If using Create React App, this is supported by default. For custom webpack configs, install sass-loader and node-sass.
Q: API requests are failing with CORS errors
A: Configure CORS on your API server to allow requests from your application's origin. Add appropriate CORS headers:
Access-Control-Allow-Origin: https://your-app.com
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, AuthorizationQ: Component shows "No valid sequence analysis data returned from API"
A: Ensure your onFetchReport/onFetchExport function returns data with a sequenceAnalysis array containing at least one element.
Q: Export (CSV/JSON) option is disabled
A: In Direct Data Mode, provide exportData or ensure analysisData.allGenes exists. In Sequence Input Mode, provide onFetchExport function.
Performance Considerations
- Data optimization: Use separate
reportDataandexportDatato minimize initial load - API caching: Implement caching on your API server to improve response times
- Lazy loading: Consider code-splitting if the component is not needed on initial page load
- Large datasets: For sequences with many mutations, rendering may take a few seconds
License
MIT © Basic Genomics
Related
- Stanford HIVDB - HIV Drug Resistance Database
- HIVDB GraphQL API - Data source API
- React - JavaScript library for building user interfaces
Made with ❤️ by Basic Genomics
