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:
@@ -8,6 +8,7 @@ interface StudyContextType {
|
||||
studies: Study[];
|
||||
refreshStudies: () => Promise<void>;
|
||||
isLoading: boolean;
|
||||
isInitialized: boolean; // True once initial load + localStorage restoration is complete
|
||||
clearStudy: () => void;
|
||||
}
|
||||
|
||||
@@ -17,6 +18,7 @@ export const StudyProvider: React.FC<{ children: ReactNode }> = ({ children }) =
|
||||
const [selectedStudy, setSelectedStudyState] = useState<Study | null>(null);
|
||||
const [studies, setStudies] = useState<Study[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isInitialized, setIsInitialized] = useState(false);
|
||||
|
||||
const refreshStudies = async () => {
|
||||
try {
|
||||
@@ -55,16 +57,23 @@ export const StudyProvider: React.FC<{ children: ReactNode }> = ({ children }) =
|
||||
// Initial load
|
||||
useEffect(() => {
|
||||
const init = async () => {
|
||||
await refreshStudies();
|
||||
|
||||
// Restore last selected study
|
||||
const lastStudyId = localStorage.getItem('selectedStudyId');
|
||||
if (lastStudyId) {
|
||||
try {
|
||||
const response = await apiClient.getStudies();
|
||||
const study = response.studies.find(s => s.id === lastStudyId);
|
||||
if (study) {
|
||||
setSelectedStudyState(study);
|
||||
setStudies(response.studies);
|
||||
|
||||
// Restore last selected study from localStorage
|
||||
const lastStudyId = localStorage.getItem('selectedStudyId');
|
||||
if (lastStudyId) {
|
||||
const study = response.studies.find(s => s.id === lastStudyId);
|
||||
if (study) {
|
||||
setSelectedStudyState(study);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize studies:', error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
setIsInitialized(true); // Mark as initialized AFTER localStorage restoration
|
||||
}
|
||||
};
|
||||
init();
|
||||
@@ -77,6 +86,7 @@ export const StudyProvider: React.FC<{ children: ReactNode }> = ({ children }) =
|
||||
studies,
|
||||
refreshStudies,
|
||||
isLoading,
|
||||
isInitialized,
|
||||
clearStudy
|
||||
}}>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user