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:
@@ -52,6 +52,22 @@ export interface ProcessStatus {
|
||||
nn_count?: number;
|
||||
}
|
||||
|
||||
export interface ModelFile {
|
||||
name: string;
|
||||
path: string;
|
||||
extension: string;
|
||||
size_bytes: number;
|
||||
size_display: string;
|
||||
modified: string;
|
||||
}
|
||||
|
||||
export interface ModelFilesResponse {
|
||||
study_id: string;
|
||||
model_dir: string;
|
||||
files: ModelFile[];
|
||||
count: number;
|
||||
}
|
||||
|
||||
class ApiClient {
|
||||
async getStudies(): Promise<StudyListResponse> {
|
||||
const response = await fetch(`${API_BASE}/optimization/studies`);
|
||||
@@ -193,6 +209,64 @@ class ApiClient {
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Model files
|
||||
async getModelFiles(studyId: string): Promise<ModelFilesResponse> {
|
||||
const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/model-files`);
|
||||
if (!response.ok) throw new Error('Failed to fetch model files');
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async openFolder(studyId: string, folderType: 'model' | 'results' | 'setup' = 'model'): Promise<{ success: boolean; message: string; path: string }> {
|
||||
const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/open-folder?folder_type=${folderType}`, {
|
||||
method: 'POST',
|
||||
});
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.detail || 'Failed to open folder');
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async getBestSolution(studyId: string): Promise<{
|
||||
study_id: string;
|
||||
best_trial: {
|
||||
trial_number: number;
|
||||
objective: number;
|
||||
design_variables: Record<string, number>;
|
||||
user_attrs?: Record<string, any>;
|
||||
timestamp?: string;
|
||||
} | null;
|
||||
first_trial: {
|
||||
trial_number: number;
|
||||
objective: number;
|
||||
design_variables: Record<string, number>;
|
||||
} | null;
|
||||
improvements: Record<string, {
|
||||
initial: number;
|
||||
final: number;
|
||||
improvement_pct: number;
|
||||
absolute_change: number;
|
||||
}>;
|
||||
total_trials: number;
|
||||
}> {
|
||||
const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/best-solution`);
|
||||
if (!response.ok) throw new Error('Failed to fetch best solution');
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async exportData(studyId: string, format: 'csv' | 'json' | 'config'): Promise<{
|
||||
filename?: string;
|
||||
content: string;
|
||||
content_type?: string;
|
||||
study_id?: string;
|
||||
total_trials?: number;
|
||||
trials?: any[];
|
||||
}> {
|
||||
const response = await fetch(`${API_BASE}/optimization/studies/${studyId}/export/${format}`);
|
||||
if (!response.ok) throw new Error(`Failed to export ${format}`);
|
||||
return response.json();
|
||||
}
|
||||
}
|
||||
|
||||
export const apiClient = new ApiClient();
|
||||
|
||||
Reference in New Issue
Block a user