Skip to content

Commit bd0bb1b

Browse files
authored
Merge branch 'main' into issues/2051-calm-server
2 parents e82ecb1 + 8eb1fa7 commit bd0bb1b

32 files changed

+595
-401
lines changed

calm-hub-ui/src/visualizer/components/drawer/Drawer.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,12 @@ import {
44
CalmNodeSchema,
55
CalmRelationshipSchema,
66
} from '../../../../../calm-models/src/types/core-types.js';
7-
import { Data } from '../../../model/calm.js';
87
import { useDropzone } from 'react-dropzone';
98
import { ReactFlowVisualizer } from '../reactflow/ReactFlowVisualizer.js';
109
import { Sidebar } from '../sidebar/Sidebar.js';
1110
import { MetadataPanel } from '../reactflow/MetadataPanel.js';
1211
import { NodeData, EdgeData } from '../../contracts/contracts.js';
13-
import type { Flow } from '../reactflow/FlowsPanel.js';
14-
import type { Control } from '../reactflow/ControlsPanel.js';
15-
16-
interface DrawerProps {
17-
data?: Data; // Optional data prop passed in from CALM Hub if user navigates from there
18-
}
19-
20-
// Selected item can be either node or edge data from the graph
21-
type SelectedItem = {
22-
data: NodeData | EdgeData;
23-
} | null;
12+
import type { DrawerProps, SelectedItem, Flow, Control } from '../../contracts/contracts.js';
2413

2514
/**
2615
* Extract the unique-id from a CALM node or relationship

calm-hub-ui/src/visualizer/components/reactflow/ArchitectureGraph.tsx

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,13 @@ import ReactFlow, {
1010
NodeChange,
1111
} from 'reactflow';
1212
import 'reactflow/dist/style.css';
13-
import { FloatingEdge } from './FloatingEdge';
14-
import { CustomNode } from './CustomNode';
15-
import { SystemGroupNode } from './SystemGroupNode';
16-
import { THEME } from './theme';
17-
import { parseCALMData } from './utils/calmTransformer';
18-
import { GRAPH_LAYOUT } from './utils/constants';
19-
import {
20-
CalmArchitectureSchema,
21-
CalmNodeSchema,
22-
CalmRelationshipSchema,
23-
} from '../../../../../calm-models/src/types/core-types.js';
24-
25-
interface ArchitectureGraphProps {
26-
jsonData: CalmArchitectureSchema;
27-
onNodeClick?: (node: CalmNodeSchema) => void;
28-
onEdgeClick?: (edge: CalmRelationshipSchema) => void;
29-
}
13+
import { FloatingEdge } from './FloatingEdge.js';
14+
import { CustomNode } from './CustomNode.js';
15+
import { SystemGroupNode } from './SystemGroupNode.js';
16+
import { THEME } from './theme.js';
17+
import { parseCALMData } from './utils/calmTransformer.js';
18+
import { GRAPH_LAYOUT } from './utils/constants.js';
19+
import type { ArchitectureGraphProps } from '../../contracts/contracts.js';
3020

3121
/**
3222
* Calculate the minimum bounds for a group node based on its children

calm-hub-ui/src/visualizer/components/reactflow/ControlsPanel.tsx

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,6 @@
1-
import { THEME } from './theme';
2-
import { ControlsPanelHeader, ControlCard } from './controls-panel';
3-
4-
// Types for CALM control data
5-
export interface ControlRequirementConfig {
6-
appliesTo?: {
7-
nodes?: string[];
8-
relationships?: string[];
9-
};
10-
[key: string]: unknown;
11-
}
12-
13-
export interface ControlRequirement {
14-
'requirement-url'?: string;
15-
'config-url'?: string;
16-
config?: ControlRequirementConfig;
17-
}
18-
19-
export interface Control {
20-
description?: string;
21-
requirements?: ControlRequirement[];
22-
'aigf-mitigations'?: string[];
23-
'aigf-risks'?: string[];
24-
// Extended properties added during extraction
25-
appliesTo?: string;
26-
nodeName?: string;
27-
relationshipDescription?: string;
28-
appliesToType?: 'node' | 'relationship';
29-
}
30-
31-
interface ControlsPanelProps {
32-
controls: Record<string, Control>;
33-
onNodeClick?: (nodeId: string) => void;
34-
onControlClick?: (controlId: string) => void;
35-
}
1+
import { THEME } from './theme.js';
2+
import { ControlsPanelHeader, ControlCard } from './controls-panel/index.js';
3+
import type { ControlsPanelProps } from '../../contracts/contracts.js';
364

375
export function ControlsPanel({ controls, onNodeClick, onControlClick }: ControlsPanelProps) {
386
if (!controls || Object.keys(controls).length === 0) return null;

calm-hub-ui/src/visualizer/components/reactflow/CustomNode.tsx

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,9 @@ import {
1616
ZoomIn,
1717
Info,
1818
} from 'lucide-react';
19-
import { extractId, extractNodeType } from './utils/calmHelpers';
20-
import { THEME, getNodeTypeColor, getRiskLevelColor } from './theme';
21-
22-
/**
23-
* AIGF risk item - all fields optional as CALM data may have partial info
24-
*/
25-
interface RiskItem {
26-
id?: string;
27-
name?: string;
28-
description?: string;
29-
}
30-
31-
/**
32-
* AIGF mitigation item - all fields optional as CALM data may have partial info
33-
*/
34-
interface MitigationItem {
35-
id?: string;
36-
name?: string;
37-
description?: string;
38-
}
39-
40-
/**
41-
* Control item - flexible structure to accommodate various control types
42-
*/
43-
interface ControlItem {
44-
description?: string;
45-
[key: string]: unknown;
46-
}
19+
import { extractId, extractNodeType } from './utils/calmHelpers.js';
20+
import { THEME, getNodeTypeColor, getRiskLevelColor } from './theme.js';
21+
import type { RiskItem, MitigationItem, ControlItem } from '../../contracts/contracts.js';
4722

4823
export function CustomNode({ data }: NodeProps) {
4924
const [isHovered, setIsHovered] = useState(false);

calm-hub-ui/src/visualizer/components/reactflow/FloatingEdge.tsx

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,8 @@
11
import { useState, useCallback } from 'react';
22
import { EdgeProps, getBezierPath, EdgeLabelRenderer, useStore } from 'reactflow';
3-
import { getEdgeParams } from './utils/floatingEdges';
4-
import { EdgeBadge, EdgeTooltip, getBadgeStyle } from './edge-components';
5-
import type { FlowTransition, EdgeControl, Mitigation, Risk } from './edge-components';
6-
7-
/**
8-
* Edge data from CALM relationships - all fields optional as different
9-
* relationship types have different data (connects, interacts, etc.)
10-
*/
11-
interface EdgeData {
12-
description?: string;
13-
protocol?: string;
14-
direction?: 'forward' | 'backward';
15-
flowTransitions?: FlowTransition[];
16-
controls?: Record<string, EdgeControl>;
17-
metadata?: {
18-
aigf?: {
19-
'controls-applied'?: string[];
20-
mitigations?: (string | Mitigation)[];
21-
risks?: (string | Risk)[];
22-
};
23-
};
24-
}
3+
import { getEdgeParams } from './utils/floatingEdges.js';
4+
import { EdgeBadge, EdgeTooltip, getBadgeStyle } from './edge-components/index.js';
5+
import type { EdgeData } from '../../contracts/contracts.js';
256

267
export function FloatingEdge({
278
id,

calm-hub-ui/src/visualizer/components/reactflow/FlowsPanel.tsx

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,6 @@
1-
import { THEME } from './theme';
2-
import { FlowsPanelHeader, FlowCard } from './flows-panel';
3-
4-
// Types for CALM flow data
5-
export interface FlowTransition {
6-
'sequence-number': number;
7-
'relationship-unique-id': string;
8-
description?: string;
9-
direction?: string;
10-
}
11-
12-
export interface AIGFGovernance {
13-
'mitigations-applied'?: string[];
14-
'risks-addressed'?: string[];
15-
'trust-boundaries-crossed'?: string[];
16-
}
17-
18-
export interface Flow {
19-
'unique-id': string;
20-
name: string;
21-
description?: string;
22-
transitions?: FlowTransition[];
23-
'aigf-governance'?: AIGFGovernance;
24-
}
25-
26-
interface FlowsPanelProps {
27-
flows: Flow[];
28-
onTransitionClick?: (relationshipId: string) => void;
29-
}
1+
import { THEME } from './theme.js';
2+
import { FlowsPanelHeader, FlowCard } from './flows-panel/index.js';
3+
import type { FlowsPanelProps } from '../../contracts/contracts.js';
304

315
export function FlowsPanel({ flows, onTransitionClick }: FlowsPanelProps) {
326
if (!flows || flows.length === 0) return null;

calm-hub-ui/src/visualizer/components/reactflow/MetadataPanel.tsx

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,9 @@
11
import { useState, useRef, useCallback } from 'react';
2-
import { THEME } from './theme';
3-
import { FlowsPanel, Flow } from './FlowsPanel';
4-
import { ControlsPanel, Control } from './ControlsPanel';
2+
import { THEME } from './theme.js';
3+
import { FlowsPanel } from './FlowsPanel.js';
4+
import { ControlsPanel } from './ControlsPanel.js';
55
import { FiChevronDown, FiChevronUp } from 'react-icons/fi';
6-
7-
interface MetadataPanelProps {
8-
flows: Flow[];
9-
controls: Record<string, Control>;
10-
onTransitionClick?: (relationshipId: string) => void;
11-
onNodeClick?: (nodeId: string) => void;
12-
onControlClick?: (controlId: string) => void;
13-
isCollapsed: boolean;
14-
onToggleCollapse: () => void;
15-
height: number;
16-
onHeightChange: (height: number) => void;
17-
}
18-
19-
type TabType = 'flows' | 'controls';
6+
import type { MetadataPanelProps, MetadataPanelTabType } from '../../contracts/contracts.js';
207

218
export function MetadataPanel({
229
flows,
@@ -31,7 +18,7 @@ export function MetadataPanel({
3118
}: MetadataPanelProps) {
3219
const hasFlows = flows.length > 0;
3320
const hasControls = Object.keys(controls).length > 0;
34-
const [activeTab, setActiveTab] = useState<TabType>(hasFlows ? 'flows' : 'controls');
21+
const [activeTab, setActiveTab] = useState<MetadataPanelTabType>(hasFlows ? 'flows' : 'controls');
3522
const [isDragging, setIsDragging] = useState(false);
3623
const dragStartY = useRef<number>(0);
3724
const dragStartHeight = useRef<number>(0);

calm-hub-ui/src/visualizer/components/reactflow/ReactFlowVisualizer.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
1-
import { ArchitectureGraph } from './ArchitectureGraph';
2-
import {
3-
CalmArchitectureSchema,
4-
CalmNodeSchema,
5-
CalmRelationshipSchema,
6-
} from '../../../../../calm-models/src/types/core-types.js';
7-
8-
export interface ReactFlowVisualizerProps {
9-
calmData: CalmArchitectureSchema;
10-
onNodeClick?: (nodeData: CalmNodeSchema) => void;
11-
onEdgeClick?: (edgeData: CalmRelationshipSchema) => void;
12-
onBackgroundClick?: () => void;
13-
}
1+
import { ArchitectureGraph } from './ArchitectureGraph.js';
2+
import type { ReactFlowVisualizerProps } from '../../contracts/visualizer-contracts.js';
143

154
/**
165
* ReactFlow-based visualizer component

calm-hub-ui/src/visualizer/components/reactflow/controls-panel/AIGFMappingSection.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import { FiShield, FiAlertCircle } from 'react-icons/fi';
2-
import { THEME } from '../theme';
3-
4-
interface AIGFMappingSectionProps {
5-
mitigations?: string[];
6-
risks?: string[];
7-
}
2+
import { THEME } from '../theme.js';
3+
import type { AIGFMappingSectionProps } from '../../../contracts/contracts.js';
84

95
export function AIGFMappingSection({ mitigations, risks }: AIGFMappingSectionProps) {
106
if (!mitigations?.length && !risks?.length) return null;

calm-hub-ui/src/visualizer/components/reactflow/controls-panel/ControlCard.tsx

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
import { FiShield } from 'react-icons/fi';
2-
import { THEME } from '../theme';
3-
import { ControlRequirementItem } from './ControlRequirementItem';
4-
import { AIGFMappingSection } from './AIGFMappingSection';
5-
import type { Control } from '../ControlsPanel';
6-
7-
interface ControlCardProps {
8-
controlId: string;
9-
control: Control;
10-
onNodeClick?: (nodeId: string) => void;
11-
onControlClick?: (controlId: string) => void;
12-
}
2+
import { THEME } from '../theme.js';
3+
import { ControlRequirementItem } from './ControlRequirementItem.js';
4+
import { AIGFMappingSection } from './AIGFMappingSection.js';
5+
import type { ControlCardProps, ControlCardHeaderProps, NodeBadgeProps, RequirementsSectionProps } from '../../../contracts/contracts.js';
136

147
export function ControlCard({ controlId, control, onNodeClick, onControlClick }: ControlCardProps) {
158
return (
@@ -52,12 +45,6 @@ export function ControlCard({ controlId, control, onNodeClick, onControlClick }:
5245
);
5346
}
5447

55-
interface ControlCardHeaderProps {
56-
controlId: string;
57-
control: Control;
58-
onNodeClick?: (nodeId: string) => void;
59-
}
60-
6148
function ControlCardHeader({ controlId, control, onNodeClick }: ControlCardHeaderProps) {
6249
return (
6350
<div
@@ -101,12 +88,6 @@ function ControlCardHeader({ controlId, control, onNodeClick }: ControlCardHeade
10188
);
10289
}
10390

104-
interface NodeBadgeProps {
105-
nodeName: string;
106-
nodeId?: string;
107-
onClick?: (nodeId: string) => void;
108-
}
109-
11091
function NodeBadge({ nodeName, nodeId, onClick }: NodeBadgeProps) {
11192
return (
11293
<div style={{ marginTop: '6px', marginBottom: '8px' }}>
@@ -158,11 +139,6 @@ function RelationshipBadge({ description }: { description: string }) {
158139
);
159140
}
160141

161-
interface RequirementsSectionProps {
162-
requirements: NonNullable<Control['requirements']>;
163-
onNodeClick?: (nodeId: string) => void;
164-
}
165-
166142
function RequirementsSection({ requirements, onNodeClick }: RequirementsSectionProps) {
167143
return (
168144
<div style={{ padding: '12px' }}>

0 commit comments

Comments
 (0)