feat(dashboard): Enhanced chat, spec management, and Claude integration
Backend: - spec.py: New AtomizerSpec REST API endpoints - spec_manager.py: SpecManager service for unified config - interview_engine.py: Study creation interview logic - claude.py: Enhanced Claude API with context - optimization.py: Extended optimization endpoints - context_builder.py, session_manager.py: Improved services Frontend: - Chat components: Enhanced message rendering, tool call cards - Hooks: useClaudeCode, useSpecWebSocket, improved useChat - Pages: Updated Dashboard, Analysis, Insights, Setup, Home - Components: ParallelCoordinatesPlot, ParetoPlot improvements - App.tsx: Route updates for canvas/studio Infrastructure: - vite.config.ts: Build configuration updates - start/stop-dashboard.bat: Script improvements
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect, lazy, Suspense, useRef } from 'react';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Settings } from 'lucide-react';
|
||||
import { useOptimizationWebSocket } from '../hooks/useWebSocket';
|
||||
@@ -21,19 +21,6 @@ import { CurrentTrialPanel, OptimizerStatePanel } from '../components/tracker';
|
||||
import { NivoParallelCoordinates } from '../components/charts';
|
||||
import type { Trial } from '../types';
|
||||
|
||||
// Lazy load Plotly components for better initial load performance
|
||||
const PlotlyParallelCoordinates = lazy(() => import('../components/plotly/PlotlyParallelCoordinates').then(m => ({ default: m.PlotlyParallelCoordinates })));
|
||||
const PlotlyParetoPlot = lazy(() => import('../components/plotly/PlotlyParetoPlot').then(m => ({ default: m.PlotlyParetoPlot })));
|
||||
const PlotlyConvergencePlot = lazy(() => import('../components/plotly/PlotlyConvergencePlot').then(m => ({ default: m.PlotlyConvergencePlot })));
|
||||
const PlotlyParameterImportance = lazy(() => import('../components/plotly/PlotlyParameterImportance').then(m => ({ default: m.PlotlyParameterImportance })));
|
||||
|
||||
// Loading placeholder for lazy components
|
||||
const ChartLoading = () => (
|
||||
<div className="flex items-center justify-center h-64 text-dark-400">
|
||||
<div className="animate-pulse">Loading chart...</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function Dashboard() {
|
||||
const navigate = useNavigate();
|
||||
const { selectedStudy, refreshStudies, isInitialized } = useStudy();
|
||||
@@ -62,8 +49,8 @@ export default function Dashboard() {
|
||||
const [paretoFront, setParetoFront] = useState<any[]>([]);
|
||||
const [allTrialsRaw, setAllTrialsRaw] = useState<any[]>([]); // All trials for parallel coordinates
|
||||
|
||||
// Chart library toggle: 'nivo' (dark theme, default), 'plotly' (more interactive), or 'recharts' (simple)
|
||||
const [chartLibrary, setChartLibrary] = useState<'nivo' | 'plotly' | 'recharts'>('nivo');
|
||||
// Chart library toggle: 'nivo' (dark theme, default) or 'recharts' (simple)
|
||||
const [chartLibrary, setChartLibrary] = useState<'nivo' | 'recharts'>('nivo');
|
||||
|
||||
// Process status for tracker panels
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
@@ -464,18 +451,7 @@ export default function Dashboard() {
|
||||
}`}
|
||||
title="Modern Nivo charts with dark theme (recommended)"
|
||||
>
|
||||
Nivo
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setChartLibrary('plotly')}
|
||||
className={`px-3 py-1.5 text-sm transition-colors ${
|
||||
chartLibrary === 'plotly'
|
||||
? 'bg-primary-500 text-white'
|
||||
: 'bg-dark-600 text-dark-200 hover:bg-dark-500'
|
||||
}`}
|
||||
title="Interactive Plotly charts with zoom, pan, and export"
|
||||
>
|
||||
Plotly
|
||||
Advanced
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setChartLibrary('recharts')}
|
||||
@@ -570,22 +546,11 @@ export default function Dashboard() {
|
||||
title="Pareto Front"
|
||||
subtitle={`${paretoFront.length} Pareto-optimal solutions | ${studyMetadata.sampler || 'NSGA-II'} | ${studyMetadata.objectives?.length || 2} objectives`}
|
||||
>
|
||||
{chartLibrary === 'plotly' ? (
|
||||
<Suspense fallback={<ChartLoading />}>
|
||||
<PlotlyParetoPlot
|
||||
trials={allTrialsRaw}
|
||||
paretoFront={paretoFront}
|
||||
objectives={studyMetadata.objectives}
|
||||
height={300}
|
||||
/>
|
||||
</Suspense>
|
||||
) : (
|
||||
<ParetoPlot
|
||||
paretoData={paretoFront}
|
||||
objectives={studyMetadata.objectives}
|
||||
allTrials={allTrialsRaw}
|
||||
/>
|
||||
)}
|
||||
<ParetoPlot
|
||||
paretoData={paretoFront}
|
||||
objectives={studyMetadata.objectives}
|
||||
allTrials={allTrialsRaw}
|
||||
/>
|
||||
</ExpandableChart>
|
||||
</div>
|
||||
)}
|
||||
@@ -605,16 +570,6 @@ export default function Dashboard() {
|
||||
paretoFront={paretoFront}
|
||||
height={380}
|
||||
/>
|
||||
) : chartLibrary === 'plotly' ? (
|
||||
<Suspense fallback={<ChartLoading />}>
|
||||
<PlotlyParallelCoordinates
|
||||
trials={allTrialsRaw}
|
||||
objectives={studyMetadata.objectives}
|
||||
designVariables={studyMetadata.design_variables}
|
||||
paretoFront={paretoFront}
|
||||
height={350}
|
||||
/>
|
||||
</Suspense>
|
||||
) : (
|
||||
<ParallelCoordinatesPlot
|
||||
paretoData={allTrialsRaw}
|
||||
@@ -634,24 +589,12 @@ export default function Dashboard() {
|
||||
title="Convergence"
|
||||
subtitle={`Best ${studyMetadata?.objectives?.[0]?.name || 'Objective'} over ${allTrialsRaw.length} trials`}
|
||||
>
|
||||
{chartLibrary === 'plotly' ? (
|
||||
<Suspense fallback={<ChartLoading />}>
|
||||
<PlotlyConvergencePlot
|
||||
trials={allTrialsRaw}
|
||||
objectiveIndex={0}
|
||||
objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
|
||||
direction="minimize"
|
||||
height={280}
|
||||
/>
|
||||
</Suspense>
|
||||
) : (
|
||||
<ConvergencePlot
|
||||
trials={allTrialsRaw}
|
||||
objectiveIndex={0}
|
||||
objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
|
||||
direction="minimize"
|
||||
/>
|
||||
)}
|
||||
<ConvergencePlot
|
||||
trials={allTrialsRaw}
|
||||
objectiveIndex={0}
|
||||
objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
|
||||
direction="minimize"
|
||||
/>
|
||||
</ExpandableChart>
|
||||
</div>
|
||||
)}
|
||||
@@ -663,32 +606,16 @@ export default function Dashboard() {
|
||||
title="Parameter Importance"
|
||||
subtitle={`Correlation with ${studyMetadata?.objectives?.[0]?.name || 'Objective'}`}
|
||||
>
|
||||
{chartLibrary === 'plotly' ? (
|
||||
<Suspense fallback={<ChartLoading />}>
|
||||
<PlotlyParameterImportance
|
||||
trials={allTrialsRaw}
|
||||
designVariables={
|
||||
studyMetadata?.design_variables?.length > 0
|
||||
? studyMetadata.design_variables
|
||||
: Object.keys(allTrialsRaw[0]?.params || {}).map(name => ({ name }))
|
||||
}
|
||||
objectiveIndex={0}
|
||||
objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
|
||||
height={280}
|
||||
/>
|
||||
</Suspense>
|
||||
) : (
|
||||
<ParameterImportanceChart
|
||||
trials={allTrialsRaw}
|
||||
designVariables={
|
||||
studyMetadata?.design_variables?.length > 0
|
||||
? studyMetadata.design_variables
|
||||
: Object.keys(allTrialsRaw[0]?.params || {}).map(name => ({ name }))
|
||||
}
|
||||
objectiveIndex={0}
|
||||
objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
|
||||
/>
|
||||
)}
|
||||
<ParameterImportanceChart
|
||||
trials={allTrialsRaw}
|
||||
designVariables={
|
||||
studyMetadata?.design_variables?.length > 0
|
||||
? studyMetadata.design_variables
|
||||
: Object.keys(allTrialsRaw[0]?.params || {}).map(name => ({ name }))
|
||||
}
|
||||
objectiveIndex={0}
|
||||
objectiveName={studyMetadata?.objectives?.[0]?.name || 'Objective'}
|
||||
/>
|
||||
</ExpandableChart>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user