mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-01-27 07:43:41 +00:00
refactor: consolidate duplicate panel headers into reusable component
Consolidates three duplicate header implementations in RightPanel into a single reusable PanelHeader component, following DRY principles. Changes: - Created PanelHeader component in RightPanel.tsx with consistent props - Refactored Actor Properties to use PanelHeader - Refactored Relation Properties to use PanelHeader - Refactored Graph Analysis to use PanelHeader (removed internal header) - All panel headers now have consistent appearance and behavior - Supports optional close button and required collapse functionality Benefits: - Eliminates code duplication across panel views - Ensures consistent UX across all panel states - Easier to maintain and update header behavior in one place - Reduces bundle size by removing redundant JSX 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3db4898902
commit
5020ce0ed7
2 changed files with 35 additions and 52 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { IconButton, Tooltip } from '@mui/material';
|
import { Tooltip } from '@mui/material';
|
||||||
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import InfoIcon from '@mui/icons-material/Info';
|
import InfoIcon from '@mui/icons-material/Info';
|
||||||
import BarChartIcon from '@mui/icons-material/BarChart';
|
import BarChartIcon from '@mui/icons-material/BarChart';
|
||||||
|
|
@ -11,7 +10,6 @@ interface GraphMetricsProps {
|
||||||
nodes: Actor[];
|
nodes: Actor[];
|
||||||
edges: Relation[];
|
edges: Relation[];
|
||||||
onActorClick?: (actorId: string) => void;
|
onActorClick?: (actorId: string) => void;
|
||||||
onCollapse?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,7 +18,7 @@ interface GraphMetricsProps {
|
||||||
* Shows when no node or edge is selected in the right panel.
|
* Shows when no node or edge is selected in the right panel.
|
||||||
* Provides insights into graph structure, connectivity, and key actors.
|
* Provides insights into graph structure, connectivity, and key actors.
|
||||||
*/
|
*/
|
||||||
const GraphMetrics = ({ nodes, edges, onActorClick, onCollapse }: GraphMetricsProps) => {
|
const GraphMetrics = ({ nodes, edges, onActorClick }: GraphMetricsProps) => {
|
||||||
// Calculate all metrics (memoized for performance - auto-updates when nodes/edges change)
|
// Calculate all metrics (memoized for performance - auto-updates when nodes/edges change)
|
||||||
const metrics = useMemo(() => {
|
const metrics = useMemo(() => {
|
||||||
return calculateGraphMetrics(nodes, edges);
|
return calculateGraphMetrics(nodes, edges);
|
||||||
|
|
@ -36,21 +34,6 @@ const GraphMetrics = ({ nodes, edges, onActorClick, onCollapse }: GraphMetricsPr
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex flex-col">
|
<div className="h-full flex flex-col">
|
||||||
{/* Header */}
|
|
||||||
<div className="flex items-center justify-between px-3 py-2 border-b border-gray-200 bg-gray-50">
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<BarChartIcon className="text-blue-600" fontSize="small" />
|
|
||||||
<h2 className="text-sm font-semibold text-gray-700">Graph Analysis</h2>
|
|
||||||
</div>
|
|
||||||
{onCollapse && (
|
|
||||||
<Tooltip title="Collapse Panel (Ctrl+I)">
|
|
||||||
<IconButton size="small" onClick={onCollapse}>
|
|
||||||
<ChevronRightIcon fontSize="small" />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Scrollable Content */}
|
{/* Scrollable Content */}
|
||||||
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
||||||
{/* Overview Section */}
|
{/* Overview Section */}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,35 @@ interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PanelHeader - Reusable header component for right panel views
|
||||||
|
*/
|
||||||
|
interface PanelHeaderProps {
|
||||||
|
title: string;
|
||||||
|
onClose?: () => void;
|
||||||
|
onCollapse: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PanelHeader = ({ title, onClose, onCollapse }: PanelHeaderProps) => (
|
||||||
|
<div className="flex items-center justify-between px-3 py-2 border-b border-gray-200 bg-gray-50">
|
||||||
|
<h2 className="text-sm font-semibold text-gray-700">{title}</h2>
|
||||||
|
<div className="flex items-center space-x-1">
|
||||||
|
{onClose && (
|
||||||
|
<Tooltip title="Close (Esc)">
|
||||||
|
<IconButton size="small" onClick={onClose}>
|
||||||
|
✕
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
<Tooltip title="Collapse Panel (Ctrl+I)">
|
||||||
|
<IconButton size="small" onClick={onCollapse}>
|
||||||
|
<ChevronRightIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
@ -181,7 +210,8 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
className="h-full bg-white border-l border-gray-200 flex flex-col"
|
className="h-full bg-white border-l border-gray-200 flex flex-col"
|
||||||
style={{ width: `${rightPanelWidth}px` }}
|
style={{ width: `${rightPanelWidth}px` }}
|
||||||
>
|
>
|
||||||
<GraphMetrics nodes={nodes} edges={edges} onCollapse={collapseRightPanel} />
|
<PanelHeader title="Graph Analysis" onCollapse={collapseRightPanel} />
|
||||||
|
<GraphMetrics nodes={nodes} edges={edges} />
|
||||||
{ConfirmDialogComponent}
|
{ConfirmDialogComponent}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -196,22 +226,7 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
className="h-full bg-white border-l border-gray-200 flex flex-col"
|
className="h-full bg-white border-l border-gray-200 flex flex-col"
|
||||||
style={{ width: `${rightPanelWidth}px` }}
|
style={{ width: `${rightPanelWidth}px` }}
|
||||||
>
|
>
|
||||||
{/* Header */}
|
<PanelHeader title="Actor Properties" onClose={onClose} onCollapse={collapseRightPanel} />
|
||||||
<div className="flex items-center justify-between px-3 py-2 border-b border-gray-200 bg-gray-50">
|
|
||||||
<h2 className="text-sm font-semibold text-gray-700">Actor Properties</h2>
|
|
||||||
<div className="flex items-center space-x-1">
|
|
||||||
<Tooltip title="Close (Esc)">
|
|
||||||
<IconButton size="small" onClick={onClose}>
|
|
||||||
✕
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip title="Collapse Panel (Ctrl+I)">
|
|
||||||
<IconButton size="small" onClick={collapseRightPanel}>
|
|
||||||
<ChevronRightIcon fontSize="small" />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Scrollable content */}
|
{/* Scrollable content */}
|
||||||
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
||||||
|
|
@ -377,22 +392,7 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
className="h-full bg-white border-l border-gray-200 flex flex-col"
|
className="h-full bg-white border-l border-gray-200 flex flex-col"
|
||||||
style={{ width: `${rightPanelWidth}px` }}
|
style={{ width: `${rightPanelWidth}px` }}
|
||||||
>
|
>
|
||||||
{/* Header */}
|
<PanelHeader title="Relation Properties" onClose={onClose} onCollapse={collapseRightPanel} />
|
||||||
<div className="flex items-center justify-between px-3 py-2 border-b border-gray-200 bg-gray-50">
|
|
||||||
<h2 className="text-sm font-semibold text-gray-700">Relation Properties</h2>
|
|
||||||
<div className="flex items-center space-x-1">
|
|
||||||
<Tooltip title="Close (Esc)">
|
|
||||||
<IconButton size="small" onClick={onClose}>
|
|
||||||
✕
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip title="Collapse Panel (Ctrl+I)">
|
|
||||||
<IconButton size="small" onClick={collapseRightPanel}>
|
|
||||||
<ChevronRightIcon fontSize="small" />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Scrollable content */}
|
{/* Scrollable content */}
|
||||||
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue