feat: Add Analysis page, run comparison, notifications, and config editor
Dashboard enhancements:
- Add Analysis page with tabs: Overview, Parameters, Pareto, Correlations, Constraints, Surrogate, Runs
- Add PlotlyCorrelationHeatmap for parameter-objective correlation analysis
- Add PlotlyFeasibilityChart for constraint satisfaction visualization
- Add PlotlySurrogateQuality for FEA vs NN prediction comparison
- Add PlotlyRunComparison for comparing optimization runs within a study
Real-time improvements:
- Replace watchdog file-watching with SQLite database polling for better Windows reliability
- Add DatabasePoller class with 2-second polling interval
- Enhanced WebSocket messages: trial_completed, new_best, pareto_update, progress
Desktop notifications:
- Add useNotifications hook using Web Notifications API
- Add NotificationSettings toggle component
- Notify users when new best solutions are found
Config editor:
- Add PUT /studies/{study_id}/config endpoint with auto-backup
- Add ConfigEditor modal with tabs: General, Variables, Objectives, Settings, JSON
- Prevents editing while optimization is running
Enhanced Pareto visualization:
- Add dark mode styling with transparent backgrounds
- Add stats bar showing Pareto, FEA, NN, and infeasible counts
- Add Pareto front connecting line for 2D view
- Add table showing top 10 Pareto-optimal solutions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,20 +1,25 @@
|
||||
import { NavLink, useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
Home,
|
||||
Settings,
|
||||
Activity,
|
||||
FileText,
|
||||
BarChart3,
|
||||
TrendingUp,
|
||||
ChevronLeft,
|
||||
Play,
|
||||
Pause,
|
||||
CheckCircle,
|
||||
Clock,
|
||||
Zap
|
||||
Zap,
|
||||
Terminal
|
||||
} from 'lucide-react';
|
||||
import clsx from 'clsx';
|
||||
import { useStudy } from '../../context/StudyContext';
|
||||
import { useClaudeTerminal } from '../../context/ClaudeTerminalContext';
|
||||
|
||||
export const Sidebar = () => {
|
||||
const { selectedStudy, clearStudy } = useStudy();
|
||||
const { isConnected: claudeConnected, setIsOpen: setClaudeTerminalOpen } = useClaudeTerminal();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleBackToHome = () => {
|
||||
@@ -26,8 +31,12 @@ export const Sidebar = () => {
|
||||
switch (status) {
|
||||
case 'running':
|
||||
return <Play className="w-3 h-3 text-green-400" />;
|
||||
case 'paused':
|
||||
return <Pause className="w-3 h-3 text-orange-400" />;
|
||||
case 'completed':
|
||||
return <CheckCircle className="w-3 h-3 text-blue-400" />;
|
||||
case 'not_started':
|
||||
return <Clock className="w-3 h-3 text-dark-400" />;
|
||||
default:
|
||||
return <Clock className="w-3 h-3 text-dark-400" />;
|
||||
}
|
||||
@@ -37,8 +46,12 @@ export const Sidebar = () => {
|
||||
switch (status) {
|
||||
case 'running':
|
||||
return 'text-green-400';
|
||||
case 'paused':
|
||||
return 'text-orange-400';
|
||||
case 'completed':
|
||||
return 'text-blue-400';
|
||||
case 'not_started':
|
||||
return 'text-dark-400';
|
||||
default:
|
||||
return 'text-dark-400';
|
||||
}
|
||||
@@ -47,9 +60,10 @@ export const Sidebar = () => {
|
||||
// Navigation items depend on whether a study is selected
|
||||
const navItems = selectedStudy
|
||||
? [
|
||||
{ to: '/setup', icon: Settings, label: 'Setup' },
|
||||
{ to: '/dashboard', icon: Activity, label: 'Live Tracker' },
|
||||
{ to: '/results', icon: FileText, label: 'Reports' },
|
||||
{ to: '/analytics', icon: BarChart3, label: 'Analytics' },
|
||||
{ to: '/analysis', icon: TrendingUp, label: 'Analysis' },
|
||||
{ to: '/results', icon: FileText, label: 'Results' },
|
||||
]
|
||||
: [
|
||||
{ to: '/', icon: Home, label: 'Select Study' },
|
||||
@@ -133,6 +147,23 @@ export const Sidebar = () => {
|
||||
Optimization Running
|
||||
</div>
|
||||
)}
|
||||
{selectedStudy && selectedStudy.status === 'paused' && (
|
||||
<div className="flex items-center gap-2 text-sm text-orange-400 mt-1">
|
||||
<div className="w-2 h-2 bg-orange-500 rounded-full" />
|
||||
Optimization Paused
|
||||
</div>
|
||||
)}
|
||||
{/* Claude Terminal Status */}
|
||||
<button
|
||||
onClick={() => setClaudeTerminalOpen(true)}
|
||||
className={clsx(
|
||||
'flex items-center gap-2 text-sm mt-1 w-full text-left hover:opacity-80 transition-opacity',
|
||||
claudeConnected ? 'text-green-400' : 'text-dark-400'
|
||||
)}
|
||||
>
|
||||
<Terminal className="w-3 h-3" />
|
||||
{claudeConnected ? 'Claude Connected' : 'Claude Disconnected'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
Reference in New Issue
Block a user