Add comprehensive column visibility controls to HTTP requests table

- Create ColumnSettings component with collapsible panel and organized column groups
- Implement localStorage persistence for column visibility preferences across sessions
- Add default visible columns: expand, url, start time, total response time, data rate, content-length
- Group columns by category: Basic, Connection, Timing, Performance, Advanced
- Provide bulk actions: Show All, Hide All, Reset to Defaults
- Add conditional rendering for all table headers and cells based on visibility state
- Update RequestRowDetails to dynamically calculate colSpan based on visible columns
- Create responsive grid layout for column settings with hover effects
- Use CSS modules with App.css variables for consistent theming
- Implement type-safe column management with proper TypeScript interfaces

Features:
- 🎛️ Gear icon toggle button for easy access to column settings
- 📁 Logical grouping of related columns for better organization
- 💾 Automatic persistence of user preferences in localStorage
- 🎯 Clean default view showing only essential columns
- 🔧 Flexible customization allowing users to show exactly what they need
- 📱 Responsive design that adapts to different screen sizes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Michael Mainguy 2025-08-12 09:46:14 -05:00
parent 33cafe695c
commit f9abfbc8ff
6 changed files with 651 additions and 201 deletions

View File

@ -0,0 +1,125 @@
/* Column Settings component styles using CSS variables from App.module.css */
.columnSettings {
margin-bottom: var(--spacing-md);
}
.toggleButton {
background: var(--color-bg-secondary);
border: 1px solid var(--color-border);
color: var(--color-text);
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius-md);
cursor: pointer;
font-size: var(--font-size-base);
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: var(--spacing-xs);
}
.toggleButton:hover {
background: var(--color-bg-hover);
border-color: var(--color-primary);
color: var(--color-primary);
}
.panel {
background: var(--color-bg-secondary);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
padding: var(--spacing-lg);
margin-top: var(--spacing-sm);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.panelHeader {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--spacing-lg);
padding-bottom: var(--spacing-md);
border-bottom: 1px solid var(--color-border);
}
.panelHeader h3 {
margin: 0;
color: var(--color-text-highlight);
font-size: var(--font-size-lg);
font-weight: bold;
}
.bulkActions {
display: flex;
gap: var(--spacing-xs);
}
.bulkButton {
background: var(--color-bg-light);
border: 1px solid var(--color-border);
color: var(--color-text);
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: var(--radius-sm);
cursor: pointer;
font-size: var(--font-size-sm);
transition: all 0.2s ease;
}
.bulkButton:hover {
background: var(--color-primary);
color: white;
border-color: var(--color-primary);
}
.columnGroups {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--spacing-lg);
}
.columnGroup {
background: var(--color-bg-light);
border-radius: var(--radius-md);
padding: var(--spacing-md);
}
.groupTitle {
margin: 0 0 var(--spacing-md) 0;
color: var(--color-text-highlight);
font-size: var(--font-size-md);
font-weight: bold;
border-bottom: 1px solid var(--color-border);
padding-bottom: var(--spacing-xs);
}
.columnList {
display: flex;
flex-direction: column;
gap: var(--spacing-xs);
}
.columnItem {
display: flex;
align-items: center;
gap: var(--spacing-xs);
cursor: pointer;
padding: var(--spacing-xs);
border-radius: var(--radius-sm);
transition: background-color 0.2s ease;
}
.columnItem:hover {
background-color: var(--color-bg-hover);
}
.checkbox {
accent-color: var(--color-primary);
cursor: pointer;
}
.columnLabel {
font-size: var(--font-size-base);
color: var(--color-text);
cursor: pointer;
user-select: none;
}

View File

@ -0,0 +1,122 @@
import React from 'react'
import styles from './ColumnSettings.module.css'
interface ColumnConfig {
key: string
label: string
group: string
}
const COLUMN_CONFIGS: ColumnConfig[] = [
// Basic Info
{ key: 'expand', label: 'Expand', group: 'Basic' },
{ key: 'method', label: 'Method', group: 'Basic' },
{ key: 'status', label: 'Status', group: 'Basic' },
{ key: 'type', label: 'Type', group: 'Basic' },
{ key: 'priority', label: 'Priority', group: 'Basic' },
{ key: 'url', label: 'URL', group: 'Basic' },
// Connection Info
{ key: 'connectionNumber', label: 'Connection #', group: 'Connection' },
{ key: 'requestNumber', label: 'Request #', group: 'Connection' },
// Timing
{ key: 'startTime', label: 'Start Time', group: 'Timing' },
{ key: 'queueTime', label: 'Queue Time', group: 'Timing' },
{ key: 'dns', label: 'DNS', group: 'Timing' },
{ key: 'connection', label: 'Connection', group: 'Timing' },
{ key: 'serverLatency', label: 'Server Latency', group: 'Timing' },
{ key: 'duration', label: 'Duration', group: 'Timing' },
{ key: 'totalResponseTime', label: 'Total Response Time', group: 'Timing' },
// Size & Performance
{ key: 'dataRate', label: 'Data Rate', group: 'Performance' },
{ key: 'size', label: 'Size', group: 'Performance' },
{ key: 'contentLength', label: 'Content-Length', group: 'Performance' },
// Advanced
{ key: 'protocol', label: 'Protocol', group: 'Advanced' },
{ key: 'cdn', label: 'CDN', group: 'Advanced' },
{ key: 'cache', label: 'Cache', group: 'Advanced' }
]
interface ColumnSettingsProps {
visibleColumns: Record<string, boolean>
onColumnToggle: (column: string) => void
isOpen: boolean
onToggle: () => void
onShowAll: () => void
onHideAll: () => void
onResetDefaults: () => void
}
const ColumnSettings: React.FC<ColumnSettingsProps> = ({
visibleColumns,
onColumnToggle,
isOpen,
onToggle,
onShowAll,
onHideAll,
onResetDefaults
}) => {
const groups = [...new Set(COLUMN_CONFIGS.map(col => col.group))]
return (
<div className={styles.columnSettings}>
<button
className={styles.toggleButton}
onClick={onToggle}
title="Column Settings"
>
Columns {isOpen ? '▼' : '▶'}
</button>
{isOpen && (
<div className={styles.panel}>
<div className={styles.panelHeader}>
<h3>Column Visibility</h3>
<div className={styles.bulkActions}>
<button onClick={onShowAll} className={styles.bulkButton}>
Show All
</button>
<button onClick={onHideAll} className={styles.bulkButton}>
Hide All
</button>
<button onClick={onResetDefaults} className={styles.bulkButton}>
Reset Defaults
</button>
</div>
</div>
<div className={styles.columnGroups}>
{groups.map(group => (
<div key={group} className={styles.columnGroup}>
<h4 className={styles.groupTitle}>{group}</h4>
<div className={styles.columnList}>
{COLUMN_CONFIGS
.filter(col => col.group === group)
.map(column => (
<label key={column.key} className={styles.columnItem}>
<input
type="checkbox"
checked={visibleColumns[column.key] || false}
onChange={() => onColumnToggle(column.key)}
className={styles.checkbox}
/>
<span className={styles.columnLabel}>
{column.label}
</span>
</label>
))
}
</div>
</div>
))}
</div>
</div>
)}
</div>
)
}
export default ColumnSettings

View File

@ -3,6 +3,7 @@ import { useDatabaseTraceData } from '../../hooks/useDatabaseTraceData'
import { getUrlParams, updateUrlWithTraceId } from '../../App' import { getUrlParams, updateUrlWithTraceId } from '../../App'
import RequestFilters from './RequestFilters' import RequestFilters from './RequestFilters'
import RequestsTable from './RequestsTable' import RequestsTable from './RequestsTable'
import ColumnSettings from './ColumnSettings'
import styles from './HTTPRequestViewer.module.css' import styles from './HTTPRequestViewer.module.css'
// Lazy load 3D viewers to reduce main bundle size // Lazy load 3D viewers to reduce main bundle size
@ -77,6 +78,43 @@ export default function HTTPRequestViewer({ traceId }: HTTPRequestViewerProps) {
const [show3DViewer, setShow3DViewer] = useState(false) const [show3DViewer, setShow3DViewer] = useState(false)
const [showTimelineViewer, setShowTimelineViewer] = useState(false) const [showTimelineViewer, setShowTimelineViewer] = useState(false)
// Column visibility state - default visible columns as requested
const [visibleColumns, setVisibleColumns] = useState(() => {
const saved = localStorage.getItem('httpRequestTableColumns')
if (saved) {
try {
return JSON.parse(saved)
} catch (e) {
console.warn('Failed to parse saved column settings, using defaults')
}
}
// Default visible columns
return {
expand: true,
method: false,
status: false,
type: false,
priority: false,
url: true,
connectionNumber: false,
requestNumber: false,
startTime: true,
queueTime: false,
dns: false,
connection: false,
serverLatency: false,
duration: false,
totalResponseTime: true,
dataRate: true,
size: false,
contentLength: true,
protocol: false,
cdn: false,
cache: false
}
})
const [columnSettingsOpen, setColumnSettingsOpen] = useState(false)
// Initialize 3D view state from URL on component mount and handle URL changes // Initialize 3D view state from URL on component mount and handle URL changes
useEffect(() => { useEffect(() => {
const updateFrom3DUrl = () => { const updateFrom3DUrl = () => {
@ -117,6 +155,62 @@ export default function HTTPRequestViewer({ traceId }: HTTPRequestViewerProps) {
setSsimThreshold(pendingSSIMThreshold) setSsimThreshold(pendingSSIMThreshold)
} }
// Column visibility handlers
const handleColumnToggle = (column: string) => {
const newVisibleColumns = {
...visibleColumns,
[column]: !visibleColumns[column]
}
setVisibleColumns(newVisibleColumns)
localStorage.setItem('httpRequestTableColumns', JSON.stringify(newVisibleColumns))
}
const handleShowAllColumns = () => {
const allVisible = Object.keys(visibleColumns).reduce((acc, key) => {
acc[key] = true
return acc
}, {} as Record<string, boolean>)
setVisibleColumns(allVisible)
localStorage.setItem('httpRequestTableColumns', JSON.stringify(allVisible))
}
const handleHideAllColumns = () => {
const allHidden = Object.keys(visibleColumns).reduce((acc, key) => {
acc[key] = key === 'expand' // Always keep expand column visible
return acc
}, {} as Record<string, boolean>)
setVisibleColumns(allHidden)
localStorage.setItem('httpRequestTableColumns', JSON.stringify(allHidden))
}
const handleResetDefaults = () => {
const defaultColumns = {
expand: true,
method: false,
status: false,
type: false,
priority: false,
url: true,
connectionNumber: false,
requestNumber: false,
startTime: true,
queueTime: false,
dns: false,
connection: false,
serverLatency: false,
duration: false,
totalResponseTime: true,
dataRate: true,
size: false,
contentLength: true,
protocol: false,
cdn: false,
cache: false
}
setVisibleColumns(defaultColumns)
localStorage.setItem('httpRequestTableColumns', JSON.stringify(defaultColumns))
}
const httpRequests = useMemo(() => { const httpRequests = useMemo(() => {
if (!traceData) return [] if (!traceData) return []
const httpRequests = processHTTPRequests(traceData.traceEvents) const httpRequests = processHTTPRequests(traceData.traceEvents)
@ -429,6 +523,17 @@ export default function HTTPRequestViewer({ traceId }: HTTPRequestViewerProps) {
</div> </div>
)} )}
{/* Column Settings */}
<ColumnSettings
visibleColumns={visibleColumns}
onColumnToggle={handleColumnToggle}
isOpen={columnSettingsOpen}
onToggle={() => setColumnSettingsOpen(!columnSettingsOpen)}
onShowAll={handleShowAllColumns}
onHideAll={handleHideAllColumns}
onResetDefaults={handleResetDefaults}
/>
{/* Requests Table */} {/* Requests Table */}
<RequestsTable <RequestsTable
httpRequests={httpRequests} httpRequests={httpRequests}
@ -438,6 +543,7 @@ export default function HTTPRequestViewer({ traceId }: HTTPRequestViewerProps) {
showQueueAnalysis={showQueueAnalysis} showQueueAnalysis={showQueueAnalysis}
expandedRows={expandedRows} expandedRows={expandedRows}
onToggleRowExpansion={toggleRowExpansion} onToggleRowExpansion={toggleRowExpansion}
visibleColumns={visibleColumns}
/> />
</div> </div>
) )

View File

@ -14,12 +14,15 @@ import {
interface RequestRowDetailsProps { interface RequestRowDetailsProps {
request: HTTPRequest request: HTTPRequest
visibleColumns: Record<string, boolean>
} }
const RequestRowDetails: React.FC<RequestRowDetailsProps> = ({ request }) => { const RequestRowDetails: React.FC<RequestRowDetailsProps> = ({ request, visibleColumns }) => {
// Calculate the number of visible columns for colSpan
const visibleColumnCount = Object.values(visibleColumns).filter(Boolean).length
return ( return (
<tr key={`${request.requestId}-expanded`} className={styles.expandedRow}> <tr key={`${request.requestId}-expanded`} className={styles.expandedRow}>
<td colSpan={20}> <td colSpan={visibleColumnCount}>
<div className={styles.expandedContent}> <div className={styles.expandedContent}>
{/* Request Details */} {/* Request Details */}

View File

@ -25,51 +25,72 @@ interface RequestRowSummaryProps {
showQueueAnalysis: boolean showQueueAnalysis: boolean
isExpanded: boolean isExpanded: boolean
onToggleRowExpansion: (requestId: string) => void onToggleRowExpansion: (requestId: string) => void
visibleColumns: Record<string, boolean>
} }
const RequestRowSummary: React.FC<RequestRowSummaryProps> = ({ const RequestRowSummary: React.FC<RequestRowSummaryProps> = ({
request, request,
showQueueAnalysis, showQueueAnalysis,
isExpanded, isExpanded,
onToggleRowExpansion onToggleRowExpansion,
visibleColumns
}) => { }) => {
return ( return (
<> <>
<tr className={styles.default} key={request.requestId} <tr className={styles.default} key={request.requestId}
onClick={() => onToggleRowExpansion(request.requestId)} onClick={() => onToggleRowExpansion(request.requestId)}
> >
{visibleColumns.expand && (
<td> <td>
{isExpanded ? '' : '+'} {isExpanded ? '' : '+'}
</td> </td>
)}
{visibleColumns.method && (
<td> <td>
{request.method} {request.method}
</td> </td>
)}
{visibleColumns.status && (
<td> <td>
{request.statusCode || '-'} {request.statusCode || '-'}
</td> </td>
)}
{visibleColumns.type && (
<td> <td>
{request.resourceType} {request.resourceType}
</td> </td>
)}
{visibleColumns.priority && (
<td className={styles.priorityCell}> <td className={styles.priorityCell}>
<span> <span>
{getPriorityIcon(request.priority)} {getPriorityIcon(request.priority)}
{request.priority || '-'} {request.priority || '-'}
</span> </span>
</td> </td>
)}
{visibleColumns.url && (
<td> <td>
<a href={request.url} target="_blank" rel="noopener noreferrer"> <a href={request.url} target="_blank" rel="noopener noreferrer">
{truncateUrl(request.url)} {truncateUrl(request.url)}
</a> </a>
</td> </td>
)}
{visibleColumns.connectionNumber && (
<td> <td>
{request.connectionNumber || '-'} {request.connectionNumber || '-'}
</td> </td>
)}
{visibleColumns.requestNumber && (
<td> <td>
{request.requestNumberOnConnection || '-'} {request.requestNumberOnConnection || '-'}
</td> </td>
)}
{visibleColumns.startTime && (
<td> <td>
{formatDuration(request.timing.startOffset)} {formatDuration(request.timing.startOffset)}
</td> </td>
)}
{visibleColumns.queueTime && (
<td className={getConnectionClass(request?.timing?.queueTime ||0)}> <td className={getConnectionClass(request?.timing?.queueTime ||0)}>
<div> <div>
{formatDuration(request.timing.queueTime)} {formatDuration(request.timing.queueTime)}
@ -82,16 +103,20 @@ const RequestRowSummary: React.FC<RequestRowSummaryProps> = ({
)} )}
</div> </div>
</td> </td>
)}
{/* DNS Time */} {/* DNS Time */}
{visibleColumns.dns && (
<td > <td >
{request.timing.dnsStart !== undefined && request.timing.dnsEnd !== undefined && request.timing.dnsStart >= 0 && request.timing.dnsEnd >= 0 {request.timing.dnsStart !== undefined && request.timing.dnsEnd !== undefined && request.timing.dnsStart >= 0 && request.timing.dnsEnd >= 0
? formatDuration((request.timing.dnsEnd || 0) - (request.timing.dnsStart || 0)) ? formatDuration((request.timing.dnsEnd || 0) - (request.timing.dnsStart || 0))
: <span>cached</span> : <span>cached</span>
} }
</td> </td>
)}
{/* Connection Time */} {/* Connection Time */}
{visibleColumns.connection && (
<td className={getConnectionClass((request.timing.connectEnd || 0) - (request.timing.connectStart || 0))}> <td className={getConnectionClass((request.timing.connectEnd || 0) - (request.timing.connectStart || 0))}>
{request.timing.connectStart !== undefined && request.timing.connectEnd !== undefined {request.timing.connectStart !== undefined && request.timing.connectEnd !== undefined
&& request.timing.connectStart >= 0 && request.timing.connectEnd >= 0 && request.timing.connectStart >= 0 && request.timing.connectEnd >= 0
@ -103,33 +128,53 @@ const RequestRowSummary: React.FC<RequestRowSummaryProps> = ({
</span> </span>
} }
</td> </td>
)}
{visibleColumns.serverLatency && (
<td className={`${getServerLatencyClass(request.timing.serverLatency)}`}> <td className={`${getServerLatencyClass(request.timing.serverLatency)}`}>
{formatDuration(request.timing.serverLatency)} {formatDuration(request.timing.serverLatency)}
</td> </td>
)}
{visibleColumns.duration && (
<td className={getDurationClass(request.timing.duration)}> <td className={getDurationClass(request.timing.duration)}>
{formatDuration(request.timing.duration)} {formatDuration(request.timing.duration)}
</td> </td>
)}
{/* Total Response Time */} {/* Total Response Time */}
{visibleColumns.totalResponseTime && (
<td className={`${getTotalResponseTimeClass(request.timing.totalResponseTime)}`}> <td className={`${getTotalResponseTimeClass(request.timing.totalResponseTime)}`}>
{formatDuration(request.timing.totalResponseTime)} {formatDuration(request.timing.totalResponseTime)}
</td> </td>
)}
{/* Data Rate */} {/* Data Rate */}
{visibleColumns.dataRate && (
<td className={`${getDataRateClass(request.encodedDataLength, request.contentLength, request.timing.duration)}`}> <td className={`${getDataRateClass(request.encodedDataLength, request.contentLength, request.timing.duration)}`}>
{formatDataRate(request.encodedDataLength, request.contentLength, request.timing.duration)} {formatDataRate(request.encodedDataLength, request.contentLength, request.timing.duration)}
</td> </td>
)}
{visibleColumns.size && (
<td className={`${getSizeClass(request.encodedDataLength)}`}> <td className={`${getSizeClass(request.encodedDataLength)}`}>
{formatSize(request.encodedDataLength)} {formatSize(request.encodedDataLength)}
</td> </td>
)}
{visibleColumns.contentLength && (
<td className={`${getSizeClass(request.contentLength)}`}> <td className={`${getSizeClass(request.contentLength)}`}>
{request.contentLength ? formatSize(request.contentLength) : '-'} {request.contentLength ? formatSize(request.contentLength) : '-'}
</td> </td>
)}
{visibleColumns.protocol && (
<td className={getProtocolClass(request.protocol)}> <td className={getProtocolClass(request.protocol)}>
{request.protocol || '-'} {request.protocol || '-'}
</td> </td>
)}
{visibleColumns.cdn && (
<td <td
title={request.cdnAnalysis ? title={request.cdnAnalysis ?
`${getCDNDisplayName(request.cdnAnalysis.provider)} ${request.cdnAnalysis.isEdge ? '(Edge)' : '(Origin)'} - ${request.cdnAnalysis.detectionMethod}` : `${getCDNDisplayName(request.cdnAnalysis.provider)} ${request.cdnAnalysis.isEdge ? '(Edge)' : '(Origin)'} - ${request.cdnAnalysis.detectionMethod}` :
@ -137,13 +182,17 @@ const RequestRowSummary: React.FC<RequestRowSummaryProps> = ({
> >
{request.cdnAnalysis ? getCDNIcon(request.cdnAnalysis) : '-'} {request.cdnAnalysis ? getCDNIcon(request.cdnAnalysis) : '-'}
</td> </td>
)}
{visibleColumns.cache && (
<td> <td>
{request.fromCache ? '💾' : request.connectionReused ? '🔄' : '🌐'} {request.fromCache ? '💾' : request.connectionReused ? '🔄' : '🌐'}
</td> </td>
)}
</tr> </tr>
{/* Expanded Row Details */} {/* Expanded Row Details */}
{isExpanded && <RequestRowDetails request={request} />} {isExpanded && <RequestRowDetails request={request} visibleColumns={visibleColumns} />}
</> </>
) )
} }

View File

@ -19,6 +19,7 @@ interface RequestsTableProps {
// Display options // Display options
showQueueAnalysis: boolean showQueueAnalysis: boolean
visibleColumns: Record<string, boolean>
// Row expansion state // Row expansion state
expandedRows: Set<string> expandedRows: Set<string>
@ -31,6 +32,7 @@ const RequestsTable: React.FC<RequestsTableProps> = ({
paginatedTimelineEntries, paginatedTimelineEntries,
paginatedRequests, paginatedRequests,
showQueueAnalysis, showQueueAnalysis,
visibleColumns,
expandedRows, expandedRows,
onToggleRowExpansion onToggleRowExpansion
}) => { }) => {
@ -41,111 +43,153 @@ const RequestsTable: React.FC<RequestsTableProps> = ({
<table className={styles.table}> <table className={styles.table}>
<thead className={styles.tableHeader}> <thead className={styles.tableHeader}>
<tr> <tr>
{visibleColumns.expand && (
<th className={`${styles.tableHeaderCell} ${styles.center} ${styles.expandColumn}`}> <th className={`${styles.tableHeaderCell} ${styles.center} ${styles.expandColumn}`}>
<Tooltip type={TooltipType.EXPAND_ROW}> <Tooltip type={TooltipType.EXPAND_ROW}>
Expand Expand
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.method && (
<th className={`${styles.tableHeaderCell} ${styles.left}`}> <th className={`${styles.tableHeaderCell} ${styles.left}`}>
<Tooltip type={TooltipType.HTTP_METHOD}> <Tooltip type={TooltipType.HTTP_METHOD}>
Method Method
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.status && (
<th className={`${styles.tableHeaderCell} ${styles.center}`}> <th className={`${styles.tableHeaderCell} ${styles.center}`}>
<Tooltip type={TooltipType.HTTP_STATUS}> <Tooltip type={TooltipType.HTTP_STATUS}>
Status Status
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.type && (
<th className={`${styles.tableHeaderCell} ${styles.left}`}> <th className={`${styles.tableHeaderCell} ${styles.left}`}>
<Tooltip type={TooltipType.RESOURCE_TYPE}> <Tooltip type={TooltipType.RESOURCE_TYPE}>
Type Type
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.priority && (
<th className={`${styles.tableHeaderCell} ${styles.center}`}> <th className={`${styles.tableHeaderCell} ${styles.center}`}>
<Tooltip type={TooltipType.REQUEST_PRIORITY}> <Tooltip type={TooltipType.REQUEST_PRIORITY}>
Priority Priority
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.url && (
<th className={`${styles.tableHeaderCell} ${styles.left}`}> <th className={`${styles.tableHeaderCell} ${styles.left}`}>
<Tooltip type={TooltipType.REQUEST_URL}> <Tooltip type={TooltipType.REQUEST_URL}>
URL URL
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.connectionNumber && (
<th className={`${styles.tableHeaderCell} ${styles.center}`}> <th className={`${styles.tableHeaderCell} ${styles.center}`}>
<Tooltip type={TooltipType.CONNECTION_NUMBER}> <Tooltip type={TooltipType.CONNECTION_NUMBER}>
Connection # Connection #
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.requestNumber && (
<th className={`${styles.tableHeaderCell} ${styles.center}`}> <th className={`${styles.tableHeaderCell} ${styles.center}`}>
<Tooltip type={TooltipType.REQUEST_NUMBER}> <Tooltip type={TooltipType.REQUEST_NUMBER}>
Request # Request #
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.startTime && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.START_TIME}> <Tooltip type={TooltipType.START_TIME}>
Start Time Start Time
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.queueTime && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.QUEUE_TIME}> <Tooltip type={TooltipType.QUEUE_TIME}>
Queue Time Queue Time
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.dns && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.DNS_TIME}> <Tooltip type={TooltipType.DNS_TIME}>
DNS DNS
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.connection && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.CONNECTION_TIME}> <Tooltip type={TooltipType.CONNECTION_TIME}>
Connection Connection
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.serverLatency && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.SERVER_LATENCY}> <Tooltip type={TooltipType.SERVER_LATENCY}>
Server Latency Server Latency
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.duration && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.REQUEST_DURATION}> <Tooltip type={TooltipType.REQUEST_DURATION}>
Duration Duration
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.totalResponseTime && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.TOTAL_RESPONSE_TIME}> <Tooltip type={TooltipType.TOTAL_RESPONSE_TIME}>
Total Response Time Total Response Time
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.dataRate && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.DATA_RATE}> <Tooltip type={TooltipType.DATA_RATE}>
Data Rate Data Rate
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.size && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.TRANSFER_SIZE}> <Tooltip type={TooltipType.TRANSFER_SIZE}>
Size Size
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.contentLength && (
<th className={`${styles.tableHeaderCell} ${styles.right}`}> <th className={`${styles.tableHeaderCell} ${styles.right}`}>
<Tooltip type={TooltipType.CONTENT_LENGTH}> <Tooltip type={TooltipType.CONTENT_LENGTH}>
Content-Length Content-Length
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.protocol && (
<th className={`${styles.tableHeaderCell} ${styles.center}`}> <th className={`${styles.tableHeaderCell} ${styles.center}`}>
<Tooltip type={TooltipType.HTTP_PROTOCOL}> <Tooltip type={TooltipType.HTTP_PROTOCOL}>
Protocol Protocol
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.cdn && (
<th className={`${styles.tableHeaderCell} ${styles.center}`}> <th className={`${styles.tableHeaderCell} ${styles.center}`}>
<Tooltip type={TooltipType.CDN_DETECTION}> <Tooltip type={TooltipType.CDN_DETECTION}>
CDN CDN
</Tooltip> </Tooltip>
</th> </th>
)}
{visibleColumns.cache && (
<th className={`${styles.tableHeaderCell} ${styles.center}`}> <th className={`${styles.tableHeaderCell} ${styles.center}`}>
<Tooltip type={TooltipType.CACHE_STATUS}> <Tooltip type={TooltipType.CACHE_STATUS}>
Cache Cache
</Tooltip> </Tooltip>
</th> </th>
)}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -173,6 +217,7 @@ const RequestsTable: React.FC<RequestsTableProps> = ({
showQueueAnalysis={showQueueAnalysis} showQueueAnalysis={showQueueAnalysis}
isExpanded={isExpanded} isExpanded={isExpanded}
onToggleRowExpansion={onToggleRowExpansion} onToggleRowExpansion={onToggleRowExpansion}
visibleColumns={visibleColumns}
/> />
) )
})} })}