import React, { useEffect, useState } from 'react'; import type { NodeDetails } from '../types'; import { formatType, formatSchema, formatSchemaType } from '../utils/formatting'; interface DetailPanelProps { selectedNodeData: any | null; onNodeSelect: (nodeId: string) => void; onTestFunction: (functionName: string) => void; } export const DetailPanel: React.FC = ({ selectedNodeData, onNodeSelect, onTestFunction, }) => { const [details, setDetails] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { if (!selectedNodeData) { setDetails(null); return; } const fetchDetails = async () => { setLoading(true); try { const [type, id] = selectedNodeData.id.split(':'); const response = await fetch(`/api/node/${type}/${id}`); const data = await response.json(); setDetails(data); } catch (error) { console.error('Failed to fetch node details:', error); } finally { setLoading(false); } }; fetchDetails(); }, [selectedNodeData]); if (!selectedNodeData) { return ( ); } const data = selectedNodeData; const changeStatus = data.changeStatus || 'unchanged'; const changeBadge = changeStatus !== 'unchanged' ? ( {changeStatus === 'added' ? 'New' : changeStatus === 'removed' ? 'Removed' : 'Modified'} ) : null; const userContextBadge = data.metadata?.usesUserContext ? ( User Context ) : null; const orgContextBadge = data.metadata?.usesOrganizationContext ? ( Org Context ) : null; const readOnlyBadge = data.type === 'function' && data.isReadOnly !== undefined ? ( {data.isReadOnly ? 'Query' : 'Mutation'} ) : null; return ( ); }; const ChangeSection: React.FC<{ changeStatus: string; changeDetails: any }> = ({ changeStatus, changeDetails, }) => { const items = []; if (changeDetails.oldAccess && changeDetails.newAccess) { const oldList = changeDetails.oldAccess.join(', '); const newList = changeDetails.newAccess.join(', '); items.push(
Access: {oldList} {newList}
); } if (changeDetails.oldEntities && changeDetails.newEntities) { const oldList = changeDetails.oldEntities.join(', ') || '(none)'; const newList = changeDetails.newEntities.join(', ') || '(none)'; items.push(
Entities: {oldList} {newList}
); } if (changeDetails.oldDescription && changeDetails.newDescription) { items.push(
Description:
{changeDetails.oldDescription}
{changeDetails.newDescription}
); } if (changeDetails.inputsChanged) { items.push(
Input schema changed
); } if (changeDetails.outputsChanged) { items.push(
Output schema changed
); } if (items.length === 0) { items.push(
Details modified
); } return (
Changes
{items}
); }; const FunctionDetails: React.FC<{ details: NodeDetails; data: any; changeStatus: string; onNodeSelect: (nodeId: string) => void; onTestFunction: (functionName: string) => void; }> = ({ details, data, changeStatus, onNodeSelect, onTestFunction }) => { return ( <> {details.connections.accessGroups.length > 0 && (
Access Groups
{details.connections.accessGroups.map((g) => ( onNodeSelect(`accessGroup:${g}`)} > {g} ))}
)} {details.connections.entities.length > 0 && (
Entities
{details.connections.entities.map((e) => ( onNodeSelect(`entity:${e}`)} > {e} ))}
)} {details.connections.dependsOn.length > 0 && (
Dependencies (fieldFrom)
{details.connections.dependsOn.map((d, i) => (
onNodeSelect(`function:${d.functionName}`)} > {d.functionName} {d.path}
))}
)} {details.connections.dependedOnBy.length > 0 && (
Used By
    {details.connections.dependedOnBy.map((f) => (
  • onNodeSelect(`function:${f}`)} > {f}
  • ))}
)} {data.metadata?.inputs && (
Input Schema
{formatSchema(data.metadata.inputs)}
)} {data.metadata?.outputs && (
Returns
{formatSchemaType(data.metadata.outputs)}
{formatSchema(data.metadata.outputs)}
)} {changeStatus !== 'removed' && (
)} ); }; const EntityAccessDetails: React.FC<{ details: NodeDetails; data: any; onNodeSelect: (nodeId: string) => void; }> = ({ details, data, onNodeSelect }) => { if (details.connections.functions.length > 0) { return (
Functions ({details.connections.functions.length})
{details.connections.functions.map((f) => (
onNodeSelect(`function:${f.name}`)} >
{f.name}
{f.description}
{f.outputs && (
Returns: {formatSchemaType(f.outputs)}
)}
))}
); } return (
Functions

No functions{' '} {data.type === 'accessGroup' ? 'require this access' : 'operate on this entity'}

); };