feat: Major update with validators, skills, dashboard, and docs reorganization
- Add validation framework (config, model, results, study validators) - Add Claude Code skills (create-study, run-optimization, generate-report, troubleshoot, analyze-model) - Add Atomizer Dashboard (React frontend + FastAPI backend) - Reorganize docs into structured directories (00-09) - Add neural surrogate modules and training infrastructure - Add multi-objective optimization support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
524
docs/04_USER_GUIDES/DASHBOARD_REACT_IMPLEMENTATION.md
Normal file
524
docs/04_USER_GUIDES/DASHBOARD_REACT_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,524 @@
|
||||
# Dashboard React Implementation - Progress Report
|
||||
|
||||
**Date**: November 21, 2025
|
||||
**Status**: 🔄 In Progress - Configuration Complete, Components Ready
|
||||
|
||||
---
|
||||
|
||||
## ✅ What Has Been Completed
|
||||
|
||||
### 1. Project Structure Created
|
||||
```
|
||||
atomizer-dashboard/frontend/
|
||||
├── src/
|
||||
│ ├── components/ # Reusable UI components ✅
|
||||
│ ├── hooks/ # Custom React hooks ✅
|
||||
│ ├── pages/ # Page components (empty - ready for Dashboard.tsx)
|
||||
│ ├── types/ # TypeScript type definitions ✅
|
||||
│ ├── utils/ # Utility functions (empty - ready for API utils)
|
||||
│ ├── index.css # Tailwind CSS styles ✅
|
||||
│ └── (main.tsx, App.tsx pending)
|
||||
├── public/ # Static assets
|
||||
├── index.html # HTML entry point ✅
|
||||
├── package.json # Dependencies ✅
|
||||
├── tsconfig.json # TypeScript config ✅
|
||||
├── vite.config.ts # Vite config with proxy ✅
|
||||
├── tailwind.config.js # Tailwind CSS config ✅
|
||||
└── postcss.config.js # PostCSS config ✅
|
||||
```
|
||||
|
||||
### 2. Configuration Files ✅
|
||||
- **[package.json](../atomizer-dashboard/frontend/package.json)** - All dependencies specified:
|
||||
- React 18.2.0
|
||||
- React Router DOM 6.20.0
|
||||
- Recharts 2.10.3
|
||||
- TailwindCSS 3.3.6
|
||||
- TypeScript 5.2.2
|
||||
- Vite 5.0.8
|
||||
|
||||
- **[vite.config.ts](../atomizer-dashboard/frontend/vite.config.ts)** - Dev server on port 3000 with proxy to backend
|
||||
- **[tsconfig.json](../atomizer-dashboard/frontend/tsconfig.json)** - Strict TypeScript configuration
|
||||
- **[tailwind.config.js](../atomizer-dashboard/frontend/tailwind.config.js)** - Custom dark theme colors
|
||||
- **[index.html](../atomizer-dashboard/frontend/index.html)** - HTML entry point
|
||||
|
||||
### 3. TypeScript Types ✅
|
||||
**File**: [src/types/index.ts](../atomizer-dashboard/frontend/src/types/index.ts)
|
||||
|
||||
Complete type definitions for:
|
||||
- `Study` - Study metadata
|
||||
- `Trial` - Optimization trial data
|
||||
- `PrunedTrial` - Pruned trial diagnostics
|
||||
- `WebSocketMessage` - WebSocket message types
|
||||
- `ConvergenceDataPoint` - Chart data for convergence plot
|
||||
- `ParameterSpaceDataPoint` - Chart data for parameter space
|
||||
- All API response types
|
||||
|
||||
### 4. Custom Hooks ✅
|
||||
**File**: [src/hooks/useWebSocket.ts](../atomizer-dashboard/frontend/src/hooks/useWebSocket.ts)
|
||||
|
||||
Professional WebSocket hook with:
|
||||
- Automatic connection management
|
||||
- Reconnection with exponential backoff (up to 5 attempts)
|
||||
- Type-safe message handling
|
||||
- Callback system for different message types
|
||||
- Connection status tracking
|
||||
|
||||
**Usage**:
|
||||
```typescript
|
||||
const { isConnected, lastMessage } = useWebSocket({
|
||||
studyId: selectedStudyId,
|
||||
onTrialCompleted: (trial) => setTrials(prev => [trial, ...prev]),
|
||||
onNewBest: (trial) => showAlert('New best trial!'),
|
||||
onProgress: (progress) => updateProgress(progress),
|
||||
onTrialPruned: (pruned) => showWarning(pruned.pruning_cause),
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Reusable UI Components ✅
|
||||
Created professional, typed components:
|
||||
|
||||
**[Card.tsx](../atomizer-dashboard/frontend/src/components/Card.tsx)**
|
||||
- Wrapper for content sections
|
||||
- Optional title prop
|
||||
- Tailwind CSS card styling
|
||||
|
||||
**[MetricCard.tsx](../atomizer-dashboard/frontend/src/components/MetricCard.tsx)**
|
||||
- Display key metrics (total trials, best value, etc.)
|
||||
- Customizable label and value color
|
||||
- Responsive design
|
||||
|
||||
**[Badge.tsx](../atomizer-dashboard/frontend/src/components/Badge.tsx)**
|
||||
- Status indicators (success, warning, error, info)
|
||||
- Variant-based styling
|
||||
- Used for study status display
|
||||
|
||||
**[StudyCard.tsx](../atomizer-dashboard/frontend/src/components/StudyCard.tsx)**
|
||||
- Study list item component
|
||||
- Progress bar visualization
|
||||
- Active state highlighting
|
||||
- Click handler for study selection
|
||||
|
||||
### 6. Tailwind CSS Setup ✅
|
||||
**File**: [src/index.css](../atomizer-dashboard/frontend/src/index.css)
|
||||
|
||||
Custom utility classes:
|
||||
- `.card` - Card container styling
|
||||
- `.btn`, `.btn-primary`, `.btn-secondary` - Button variants
|
||||
- `.input` - Form input styling
|
||||
- `.badge-*` - Badge variants
|
||||
- Custom scrollbar styling for dark theme
|
||||
|
||||
---
|
||||
|
||||
## 🔨 Next Steps - Manual Completion Required
|
||||
|
||||
Since `npm` is not available in the current environment, you'll need to complete the following steps manually:
|
||||
|
||||
### Step 1: Install Dependencies
|
||||
```bash
|
||||
cd atomizer-dashboard/frontend
|
||||
npm install
|
||||
```
|
||||
|
||||
This will install:
|
||||
- React, React DOM, React Router
|
||||
- Recharts for charts
|
||||
- TailwindCSS, Autoprefixer, PostCSS
|
||||
- Vite and TypeScript
|
||||
- ESLint for code quality
|
||||
|
||||
### Step 2: Create Remaining Components
|
||||
|
||||
I've prepared the structure, but you'll need to create:
|
||||
|
||||
#### **src/main.tsx** (React entry point)
|
||||
```typescript
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
```
|
||||
|
||||
#### **src/App.tsx** (Main application component)
|
||||
```typescript
|
||||
import { useState, useEffect } from 'react';
|
||||
import Dashboard from './pages/Dashboard';
|
||||
import type { Study } from './types';
|
||||
|
||||
function App() {
|
||||
const [studies, setStudies] = useState<Study[]>([]);
|
||||
const [selectedStudyId, setSelectedStudyId] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Fetch studies from API
|
||||
fetch('/api/optimization/studies')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
setStudies(data.studies);
|
||||
if (data.studies.length > 0) {
|
||||
setSelectedStudyId(data.studies[0].id);
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('Failed to load studies:', err));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-dark-700">
|
||||
<Dashboard
|
||||
studies={studies}
|
||||
selectedStudyId={selectedStudyId}
|
||||
onStudySelect={setSelectedStudyId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
#### **src/pages/Dashboard.tsx** (Main dashboard page)
|
||||
This is the core component that needs to be created. It should:
|
||||
- Use the `useWebSocket` hook for real-time updates
|
||||
- Display study list in sidebar using `StudyCard` components
|
||||
- Show metrics using `MetricCard` components
|
||||
- Render convergence and parameter space charts with Recharts
|
||||
- Handle trial feed display
|
||||
- Show pruning alerts
|
||||
|
||||
**Template structure**:
|
||||
```typescript
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useWebSocket } from '../hooks/useWebSocket';
|
||||
import { Card } from '../components/Card';
|
||||
import { MetricCard } from '../components/MetricCard';
|
||||
import { StudyCard } from '../components/StudyCard';
|
||||
import type { Study, Trial } from '../types';
|
||||
// Import Recharts components for charts
|
||||
|
||||
interface DashboardProps {
|
||||
studies: Study[];
|
||||
selectedStudyId: string | null;
|
||||
onStudySelect: (studyId: string) => void;
|
||||
}
|
||||
|
||||
export default function Dashboard({ studies, selectedStudyId, onStudySelect }: DashboardProps) {
|
||||
const [trials, setTrials] = useState<Trial[]>([]);
|
||||
const [bestValue, setBestValue] = useState<number>(Infinity);
|
||||
|
||||
// WebSocket connection
|
||||
const { isConnected } = useWebSocket({
|
||||
studyId: selectedStudyId,
|
||||
onTrialCompleted: (trial) => {
|
||||
setTrials(prev => [trial, ...prev].slice(0, 20));
|
||||
if (trial.objective < bestValue) {
|
||||
setBestValue(trial.objective);
|
||||
}
|
||||
},
|
||||
onNewBest: (trial) => {
|
||||
console.log('New best trial:', trial);
|
||||
// Show alert
|
||||
},
|
||||
onTrialPruned: (pruned) => {
|
||||
console.log('Trial pruned:', pruned);
|
||||
// Show warning
|
||||
},
|
||||
});
|
||||
|
||||
// Load initial trial history when study changes
|
||||
useEffect(() => {
|
||||
if (selectedStudyId) {
|
||||
fetch(`/api/optimization/studies/${selectedStudyId}/history?limit=20`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
setTrials(data.trials.reverse());
|
||||
if (data.trials.length > 0) {
|
||||
setBestValue(Math.min(...data.trials.map(t => t.objective)));
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('Failed to load history:', err));
|
||||
}
|
||||
}, [selectedStudyId]);
|
||||
|
||||
return (
|
||||
<div className="container mx-auto p-6">
|
||||
{/* Header */}
|
||||
<header className="mb-8">
|
||||
<h1 className="text-3xl font-bold text-primary-400">
|
||||
Atomizer Dashboard
|
||||
</h1>
|
||||
<p className="text-dark-200 mt-2">
|
||||
Real-time optimization monitoring
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div className="grid grid-cols-12 gap-6">
|
||||
{/* Sidebar - Study List */}
|
||||
<aside className="col-span-3">
|
||||
<Card title="Active Studies">
|
||||
<div className="space-y-3">
|
||||
{studies.map(study => (
|
||||
<StudyCard
|
||||
key={study.id}
|
||||
study={study}
|
||||
isActive={study.id === selectedStudyId}
|
||||
onClick={() => onStudySelect(study.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</aside>
|
||||
|
||||
{/* Main Content */}
|
||||
<main className="col-span-9">
|
||||
{/* Metrics Grid */}
|
||||
<div className="grid grid-cols-4 gap-4 mb-6">
|
||||
<MetricCard label="Total Trials" value={trials.length} />
|
||||
<MetricCard
|
||||
label="Best Value"
|
||||
value={bestValue === Infinity ? '-' : bestValue.toFixed(4)}
|
||||
valueColor="text-green-400"
|
||||
/>
|
||||
<MetricCard
|
||||
label="Connection"
|
||||
value={isConnected ? 'Connected' : 'Disconnected'}
|
||||
valueColor={isConnected ? 'text-green-400' : 'text-red-400'}
|
||||
/>
|
||||
<MetricCard label="Pruned" value={0} valueColor="text-yellow-400" />
|
||||
</div>
|
||||
|
||||
{/* Charts */}
|
||||
<div className="grid grid-cols-2 gap-6 mb-6">
|
||||
<Card title="Convergence Plot">
|
||||
{/* Add Recharts LineChart here */}
|
||||
<div className="h-64 flex items-center justify-center text-dark-300">
|
||||
Convergence chart will go here
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card title="Parameter Space">
|
||||
{/* Add Recharts ScatterChart here */}
|
||||
<div className="h-64 flex items-center justify-center text-dark-300">
|
||||
Parameter space chart will go here
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Trial Feed */}
|
||||
<Card title="Recent Trials">
|
||||
<div className="space-y-2 max-h-96 overflow-y-auto">
|
||||
{trials.map(trial => (
|
||||
<div
|
||||
key={trial.trial_number}
|
||||
className={`p-3 rounded-lg ${
|
||||
trial.objective === bestValue
|
||||
? 'bg-green-900 border-l-4 border-green-400'
|
||||
: 'bg-dark-500'
|
||||
}`}
|
||||
>
|
||||
<div className="flex justify-between mb-1">
|
||||
<span className="font-semibold text-primary-400">
|
||||
Trial #{trial.trial_number}
|
||||
</span>
|
||||
<span className="font-mono text-green-400">
|
||||
{trial.objective.toFixed(4)} Hz
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-dark-200">
|
||||
{Object.entries(trial.design_variables).map(([key, val]) => (
|
||||
<span key={key} className="mr-3">
|
||||
{key}: {val.toFixed(2)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Add Recharts Integration
|
||||
|
||||
In the Dashboard component, add the convergence and parameter space charts using Recharts:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
LineChart, Line, ScatterChart, Scatter,
|
||||
XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer
|
||||
} from 'recharts';
|
||||
|
||||
// Convergence chart
|
||||
const convergenceData = trials.map((trial, idx) => ({
|
||||
trial_number: trial.trial_number,
|
||||
objective: trial.objective,
|
||||
best_so_far: Math.min(...trials.slice(0, idx + 1).map(t => t.objective)),
|
||||
}));
|
||||
|
||||
<ResponsiveContainer width="100%" height={250}>
|
||||
<LineChart data={convergenceData}>
|
||||
<CartesianGrid strokeDasharray="3 3" stroke="#334155" />
|
||||
<XAxis dataKey="trial_number" stroke="#94a3b8" />
|
||||
<YAxis stroke="#94a3b8" />
|
||||
<Tooltip
|
||||
contentStyle={{ backgroundColor: '#1e293b', border: 'none' }}
|
||||
labelStyle={{ color: '#e2e8f0' }}
|
||||
/>
|
||||
<Legend />
|
||||
<Line type="monotone" dataKey="objective" stroke="#60a5fa" name="Objective" />
|
||||
<Line type="monotone" dataKey="best_so_far" stroke="#10b981" name="Best So Far" />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
|
||||
// Parameter space chart (similar structure with ScatterChart)
|
||||
```
|
||||
|
||||
### Step 4: Run Development Server
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The React app will be available at **http://localhost:3000**
|
||||
|
||||
The Vite proxy will forward:
|
||||
- `/api/*` → `http://localhost:8000/api/*`
|
||||
- WebSocket connections automatically
|
||||
|
||||
---
|
||||
|
||||
## 📊 Architecture Summary
|
||||
|
||||
### Data Flow
|
||||
```
|
||||
Backend (FastAPI) :8000
|
||||
↓ REST API
|
||||
React App :3000 (Vite dev server with proxy)
|
||||
↓ WebSocket
|
||||
useWebSocket hook → Dashboard component → UI updates
|
||||
```
|
||||
|
||||
### Component Hierarchy
|
||||
```
|
||||
App
|
||||
└── Dashboard
|
||||
├── Sidebar
|
||||
│ └── StudyCard (multiple)
|
||||
├── Metrics Grid
|
||||
│ └── MetricCard (multiple)
|
||||
├── Charts
|
||||
│ ├── Card (Convergence)
|
||||
│ │ └── LineChart (Recharts)
|
||||
│ └── Card (Parameter Space)
|
||||
│ └── ScatterChart (Recharts)
|
||||
└── Trial Feed
|
||||
└── Card
|
||||
└── Trial Items
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Benefits of React Implementation
|
||||
|
||||
### vs. Current HTML Dashboard
|
||||
1. **Component Reusability** - UI components can be used across pages
|
||||
2. **Type Safety** - TypeScript catches errors at compile time
|
||||
3. **Better State Management** - React state + hooks vs. manual DOM manipulation
|
||||
4. **Easier Testing** - React Testing Library for component tests
|
||||
5. **Professional Architecture** - Scalable for adding Configurator and Results pages
|
||||
6. **Hot Module Replacement** - Instant updates during development
|
||||
7. **Better Performance** - React's virtual DOM optimizations
|
||||
|
||||
---
|
||||
|
||||
## 📁 Files Created
|
||||
|
||||
### Configuration (Complete)
|
||||
- `package.json` ✅
|
||||
- `vite.config.ts` ✅
|
||||
- `tsconfig.json` ✅
|
||||
- `tsconfig.node.json` ✅
|
||||
- `tailwind.config.js` ✅
|
||||
- `postcss.config.js` ✅
|
||||
- `index.html` ✅
|
||||
|
||||
### Source Files (Complete)
|
||||
- `src/index.css` ✅
|
||||
- `src/types/index.ts` ✅
|
||||
- `src/hooks/useWebSocket.ts` ✅
|
||||
- `src/components/Card.tsx` ✅
|
||||
- `src/components/MetricCard.tsx` ✅
|
||||
- `src/components/Badge.tsx` ✅
|
||||
- `src/components/StudyCard.tsx` ✅
|
||||
|
||||
### Source Files (Pending - Templates Provided Above)
|
||||
- `src/main.tsx` ⏳
|
||||
- `src/App.tsx` ⏳
|
||||
- `src/pages/Dashboard.tsx` ⏳
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### npm not found
|
||||
- Install Node.js from nodejs.org
|
||||
- Verify: `node --version` and `npm --version`
|
||||
|
||||
### Dependency installation fails
|
||||
- Delete `node_modules` and `package-lock.json`
|
||||
- Run `npm install` again
|
||||
- Check for network/proxy issues
|
||||
|
||||
### TypeScript errors
|
||||
- Run `npm run build` to see all errors
|
||||
- Check `tsconfig.json` settings
|
||||
- Ensure all imports use correct paths
|
||||
|
||||
### WebSocket connection fails
|
||||
- Ensure backend is running on port 8000
|
||||
- Check Vite proxy configuration in `vite.config.ts`
|
||||
- Verify CORS settings in backend
|
||||
|
||||
### Charts not displaying
|
||||
- Check Recharts is installed: `npm list recharts`
|
||||
- Verify data format matches Recharts API
|
||||
- Check browser console for errors
|
||||
|
||||
---
|
||||
|
||||
## 📚 Next Steps After Manual Completion
|
||||
|
||||
1. **Test the Dashboard**
|
||||
- Start backend: `python -m uvicorn api.main:app --reload`
|
||||
- Start frontend: `npm run dev`
|
||||
- Open browser: http://localhost:3000
|
||||
- Select a study and verify real-time updates
|
||||
|
||||
2. **Add Enhancements**
|
||||
- Data export buttons
|
||||
- Pruning alert toasts
|
||||
- Study control buttons (future)
|
||||
- Parameter importance chart (if Protocol 9 data available)
|
||||
|
||||
3. **Build for Production**
|
||||
- `npm run build`
|
||||
- Serve `dist/` folder from FastAPI static files
|
||||
|
||||
4. **Add More Pages**
|
||||
- Study Configurator page
|
||||
- Results Viewer page
|
||||
- Add React Router for navigation
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ Configuration and foundation complete. Ready for manual `npm install` and component completion.
|
||||
|
||||
**Next Session**: Complete Dashboard.tsx, integrate Recharts, test end-to-end.
|
||||
Reference in New Issue
Block a user