wu981526092's picture
🧹 Clean up and optimize HF Spaces deployment
697eb00
import React, { useEffect, useCallback } from "react";
import { useAgentGraph } from "@/context/AgentGraphContext";
import { useNavigation } from "@/context/NavigationContext";
import { Breadcrumb } from "./Breadcrumb";
import { DashboardView } from "../features/workspace/DashboardView";
import { TraceKnowledgeGraphView } from "../features/traces/TraceKnowledgeGraphView";
import { TracesView } from "../features/traces/TracesView";
import { KnowledgeGraphVisualizer } from "../features/traces/KnowledgeGraphVisualizer";
import { AdvancedProcessingView } from "../features/processing/AdvancedProcessingView";
import { TraceEditor } from "../features/traces/TraceEditor";
import { TemporalGraphVisualizer } from "../features/traces/TemporalGraphVisualizer";
import { GraphComparisonView } from "../features/comparison/GraphComparisonView";
import { FloatingActionWidget } from "../shared/FloatingActionWidget";
import ExampleTraceBrowserView from "@/components/features/traces/ExampleTraceBrowserView";
import { ConnectionsView } from "../features/connections/ConnectionsView";
import { UploadView } from "../features/upload/UploadView";
import { Button } from "@/components/ui/button";
import { ArrowLeft } from "lucide-react";
interface MainWorkspaceProps {
isSidebarCollapsed: boolean;
onToggleSidebar?: () => void;
}
export function MainWorkspace({
isSidebarCollapsed: _isSidebarCollapsed,
onToggleSidebar: _onToggleSidebar,
}: MainWorkspaceProps) {
const { state, actions } = useAgentGraph();
const navigation = useNavigation();
const { activeView } = state;
// FloatingActionWidget now handles its own contextual actions
// Function to handle back navigation using breadcrumbs
const handleBackNavigation = useCallback(() => {
const breadcrumbs = navigation.state.breadcrumbs;
if (breadcrumbs.length > 1) {
// Navigate to the second-to-last breadcrumb item
const previousBreadcrumb = breadcrumbs[breadcrumbs.length - 2];
if (previousBreadcrumb?.path) {
switch (previousBreadcrumb.path) {
case "welcome":
actions.setActiveView("welcome");
break;
case "traces":
actions.setActiveView("traces");
break;
case "trace-kg":
actions.setActiveView("trace-kg");
break;
case "kg-visualizer":
actions.setActiveView("kg-visualizer");
break;
case "advanced-processing":
actions.setActiveView("advanced-processing");
break;
case "trace-editor":
actions.setActiveView("trace-editor");
break;
case "temporal-visualizer":
actions.setActiveView("temporal-visualizer");
break;
case "connections":
actions.setActiveView("connections");
break;
case "upload":
actions.setActiveView("upload");
break;
case "graph-comparison":
actions.setActiveView("graph-comparison");
break;
case "example-traces":
actions.setActiveView("example-traces");
break;
default:
actions.setActiveView("welcome");
}
} else {
actions.setActiveView("welcome");
}
} else {
// If no previous breadcrumb, go to dashboard
actions.setActiveView("welcome");
}
}, [navigation.state.breadcrumbs, actions]);
// Generate breadcrumbs based on current state
const generateBreadcrumbs = useCallback(() => {
const breadcrumbs: Array<{ label: string; path: string; active: boolean }> =
[];
// Always show Dashboard breadcrumb
if (activeView === "welcome") {
breadcrumbs.push({
label: "Dashboard",
path: "welcome",
active: true,
});
} else {
breadcrumbs.push({
label: "Dashboard",
path: "welcome",
active: false,
});
}
if (activeView === "traces") {
breadcrumbs.push({
label: "My Traces",
path: "traces",
active: true,
});
}
if (activeView === "trace-kg" && state.selectedTrace) {
breadcrumbs.push({
label: "My Traces",
path: "traces",
active: false,
});
breadcrumbs.push({
label: state.selectedTrace.filename,
path: "trace-kg",
active: true,
});
}
if (
activeView === "kg-visualizer" &&
state.selectedTrace &&
state.selectedKnowledgeGraph
) {
breadcrumbs.push({
label: "My Traces",
path: "traces",
active: false,
});
breadcrumbs.push({
label: state.selectedTrace.filename,
path: "trace-kg",
active: false,
});
breadcrumbs.push({
label: "Agent Graph Visualization",
path: "kg-visualizer",
active: true,
});
}
if (
activeView === "advanced-processing" &&
state.selectedTrace &&
state.selectedKnowledgeGraph
) {
breadcrumbs.push({
label: "My Traces",
path: "traces",
active: false,
});
breadcrumbs.push({
label: state.selectedTrace.filename,
path: "trace-kg",
active: false,
});
breadcrumbs.push({
label: "Agent Graph Visualization",
path: "kg-visualizer",
active: false,
});
breadcrumbs.push({
label: "Advanced Processing",
path: "advanced-processing",
active: true,
});
}
if (activeView === "trace-editor" && state.selectedTrace) {
breadcrumbs.push({
label: "My Traces",
path: "traces",
active: false,
});
breadcrumbs.push({
label: state.selectedTrace.filename,
path: "trace-kg",
active: false,
});
breadcrumbs.push({
label: "Edit Trace",
path: "trace-editor",
active: true,
});
}
if (activeView === "temporal-visualizer" && state.selectedTemporalData) {
breadcrumbs.push({
label: "My Traces",
path: "traces",
active: false,
});
breadcrumbs.push({
label: state.selectedTemporalData.trace_title,
path: "trace-kg",
active: false,
});
breadcrumbs.push({
label: "Temporal Visualization",
path: "temporal-visualizer",
active: true,
});
}
if (activeView === "graph-comparison") {
breadcrumbs.push({
label: "Graph Comparison",
path: "graph-comparison",
active: true,
});
}
if (activeView === "example-traces") {
breadcrumbs.push({
label: "Gallery",
path: "example-traces",
active: true,
});
}
if (activeView === "connections") {
breadcrumbs.push({
label: "Connections",
path: "connections",
active: true,
});
}
if (activeView === "upload") {
breadcrumbs.push({
label: "Upload Trace",
path: "upload",
active: true,
});
}
return breadcrumbs;
}, [
activeView,
state.selectedTrace,
state.selectedKnowledgeGraph,
state.selectedTemporalData,
]);
// Update navigation context when state changes
useEffect(() => {
const breadcrumbs = generateBreadcrumbs();
navigation.actions.setBreadcrumbs(breadcrumbs);
}, [generateBreadcrumbs, navigation.actions]);
const renderView = () => {
switch (activeView) {
case "welcome":
return <DashboardView />;
case "traces":
return <TracesView />;
case "trace-kg":
return state.selectedTrace ? (
<TraceKnowledgeGraphView
trace={state.selectedTrace}
knowledgeGraphs={state.knowledgeGraphs.filter(
(kg) => kg.filename === state.selectedTrace?.filename
)}
/>
) : (
<DashboardView />
);
case "kg-visualizer":
return state.selectedKnowledgeGraph ? (
<KnowledgeGraphVisualizer
knowledgeGraph={state.selectedKnowledgeGraph}
/>
) : (
<DashboardView />
);
case "advanced-processing":
return state.selectedKnowledgeGraph ? (
<AdvancedProcessingView
knowledgeGraph={state.selectedKnowledgeGraph}
onBack={() => actions.setActiveView("trace-kg")}
/>
) : (
<DashboardView />
);
case "trace-editor":
return state.selectedTrace ? (
<TraceEditor
trace={state.selectedTrace}
onBack={() => actions.setActiveView("trace-kg")}
/>
) : (
<DashboardView />
);
case "temporal-visualizer":
return state.selectedTemporalData ? (
<TemporalGraphVisualizer
temporalData={state.selectedTemporalData}
onBack={() => actions.setActiveView("trace-kg")}
/>
) : (
<DashboardView />
);
case "graph-comparison":
return <GraphComparisonView />;
case "example-traces":
return <ExampleTraceBrowserView />;
case "connections":
return <ConnectionsView />;
case "upload":
return <UploadView />;
default:
return <DashboardView />;
}
};
// Special layout for temporal visualizer - full screen with sidebar
if (activeView === "temporal-visualizer") {
return (
<div className="fixed inset-0 bg-background z-50 flex flex-col">
{/* Global Floating Action Widget for temporal view */}
<FloatingActionWidget />
{/* Breadcrumb Navigation */}
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="flex items-center justify-between px-6 py-3">
<div className="flex items-center gap-3">
{navigation.state.breadcrumbs.length > 1 && (
<Button
variant="ghost"
size="sm"
onClick={handleBackNavigation}
className="h-8 w-8 p-0 hover:bg-muted/50 rounded-md"
title="Go back"
>
<ArrowLeft className="h-4 w-4" />
</Button>
)}
<Breadcrumb />
</div>
</div>
</div>
{/* Main content with sidebar */}
<div className="flex w-full flex-1 min-h-0">
<div className="flex-1 overflow-hidden">{renderView()}</div>
</div>
</div>
);
}
return (
<div className="flex-1 flex flex-col min-h-0">
{/* Global Floating Action Widget */}
<FloatingActionWidget />
{/* Breadcrumb Navigation - Only show when needed */}
{navigation.state.breadcrumbs.length > 0 ? (
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 flex-shrink-0">
<div className="flex items-center justify-between px-6 py-2">
<div className="flex items-center gap-3">
{navigation.state.breadcrumbs.length > 1 && (
<Button
variant="ghost"
size="sm"
onClick={handleBackNavigation}
className="h-8 w-8 p-0 hover:bg-muted/50 rounded-md"
title="Go back"
>
<ArrowLeft className="h-4 w-4" />
</Button>
)}
<Breadcrumb />
</div>
</div>
</div>
) : (
<div className="border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 flex-shrink-0">
<div className="flex items-center px-6 py-2">
{/* Empty div to maintain layout when no breadcrumbs */}
</div>
</div>
)}
{/* Main Content */}
<div className="flex-1 flex flex-col min-h-0">{renderView()}</div>
</div>
);
}