import { Logout as LogoutIcon, Refresh as RefreshIcon, UploadFile as UploadFileIcon, Warning as WarningIcon, } from "@mui/icons-material"; import { Alert, AppBar, Box, Button, CircularProgress, Collapse, Divider, Stack, Toolbar, Tooltip, Typography, } from "@mui/material"; import React, { useCallback, useEffect, useState } from "react"; import { FormData } from "../types"; import { ModelProviderSelector } from "./ModelProviderSelector"; import { McpConfigurationWarningDialog } from "./dialogs"; import { ServerLoadingIndicator } from "./ServerLoadingIndicator"; interface DemoViewProps { iframeUrl: string; iframeLoading: boolean; healthCheckProgress?: { attempt: number; maxAttempts: number; } | null; formData: FormData; defaultMcpFile: File | null; onIframeLoad: () => void; onRestart: () => void; onFormChange: (formData: FormData) => void; onSettingsRestart: () => void; } export const DemoView: React.FC = ({ iframeUrl, iframeLoading, healthCheckProgress, formData, onIframeLoad, onRestart, onFormChange, onSettingsRestart, }) => { const [showWarning, setShowWarning] = useState(false); const [originalFormData, setOriginalFormData] = useState(formData); const [dialogOpen, setDialogOpen] = useState(false); const [pendingFile, setPendingFile] = useState(null); const [isMcpTooltipOpen, setMcpTooltipOpen] = useState(false); // Form validation const isFormValid = Boolean( formData.model.trim() && formData.provider.trim(), ); // Update original form data when component first loads or when iframe URL changes (successful restart) useEffect(() => { setOriginalFormData(formData); }, [iframeUrl]); // Update when iframe URL changes, indicating successful restart const handleModelChange = useCallback( (value: string) => { onFormChange({ ...formData, model: value }); setShowWarning(true); }, [formData, onFormChange], ); const handleProviderChange = useCallback( (value: string) => { // When provider changes, clear the model as well to avoid stale selections onFormChange({ ...formData, provider: value, model: "" }); setShowWarning(true); }, [formData, onFormChange], ); const handleFileChange = useCallback( (event: React.ChangeEvent) => { const file = event.target.files?.[0] || null; if (file) { setPendingFile(file); setDialogOpen(true); } else { onFormChange({ ...formData, mcpFile: null }); setShowWarning(true); } }, [formData, onFormChange], ); const handleDialogClose = useCallback(() => { setDialogOpen(false); setPendingFile(null); // Clear the file input element to reset the UI const fileInput = document.querySelector( 'input[type="file"]', ) as HTMLInputElement; if (fileInput) { fileInput.value = ""; } }, []); const handleDialogConfirm = useCallback(() => { if (pendingFile) { onFormChange({ ...formData, mcpFile: pendingFile }); setShowWarning(true); } setDialogOpen(false); setPendingFile(null); }, [formData, onFormChange, pendingFile]); const handleSettingsRestartClick = () => { setShowWarning(false); // Update the original form data to the current form data after restart setOriginalFormData(formData); onSettingsRestart(); }; const handleWarningDismiss = () => { setShowWarning(false); // Reset form data back to original values onFormChange(originalFormData); }; return ( {/* Top Bar with Settings and Restart Button */} Meta Agents Research Environments {/* Spacer to push form to the right */} {/* Settings Form */} {/* Model and Provider Selection */} {/* MCP File Input with Tooltip */} setMcpTooltipOpen(true)} onMouseLeave={() => setMcpTooltipOpen(false)} onClick={() => setMcpTooltipOpen(false)} > {/* Restart Button */} {/* Warning Alert */} } action={ } sx={{ borderTopLeftRadius: 0, borderTopRightRadius: 0, pl: 3, pr: 4 }} > You've made changes to the configuration. Click "Restart demo with changes" to apply them. {/* Iframe Content */} {iframeLoading ? ( ) : (