.. _frontend-pages:
=====
Pages
=====
This page documents the page components in ``frontend/src/pages/``. Each page
corresponds to a route in the application.
----
RunListPage
===========
:Location: ``src/pages/RunListPage.tsx``
:Route: ``/`` or ``/runs``
The main dashboard showing all simulation runs.
Features
--------
- Lists all runs with status indicators
- Automatic refresh (polls every 5 seconds)
- Filter by status (completed, running, failed)
- Click to navigate to run details
- "New Run" button to create a simulation
Implementation
--------------
.. code-block:: text
function RunListPage() {
const navigate = useNavigate()
const { data, isLoading } = useQuery({
queryKey: ['runs'],
queryFn: () => runsApi.list(),
refetchInterval: 5000,
})
return (
Simulation Runs
navigate('/runs/new')}>New Run
{isLoading ? (
) : (
{data?.runs.map((run) => (
navigate(`/runs/${run.id}`)}
/>
))}
)}
)
}
----
NewRunPage
==========
:Location: ``src/pages/NewRunPage.tsx``
:Route: ``/runs/new``
Form for creating a new simulation run.
Features
--------
- Run ID input (auto-generated if empty)
- Optional display name
- Template selection dropdown
- Configuration editor (Monaco) for customization
- Validation before submission
Implementation
--------------
.. code-block:: text
function NewRunPage() {
const navigate = useNavigate()
const [runId, setRunId] = useState('')
const [template, setTemplate] = useState('minimal.ini')
const [configContent, setConfigContent] = useState('')
const { data: templates } = useQuery({
queryKey: ['templates'],
queryFn: configsApi.listTemplates,
})
const createMutation = useMutation({
mutationFn: runsApi.create,
onSuccess: (run) => navigate(`/runs/${run.id}`),
})
const handleSubmit = () => {
createMutation.mutate({
run_id: runId || undefined,
template,
config_content: configContent,
})
}
return (
New Simulation Run
)
}
----
RunDetailPage
=============
:Location: ``src/pages/RunDetailPage.tsx``
:Route: ``/runs/:runId``
Detailed view of a single run with tabs for different information.
Features
--------
- Run metadata (status, timestamps, template)
- Progress indicator for running simulations
- Logs tab with real-time streaming
- Artifacts tab with file browser
- Cancel button for running simulations
Tabs
----
**Logs Tab**
- Displays simulation output in a scrollable terminal-like view
- Uses Server-Sent Events for real-time updates
- Auto-scrolls to bottom for new content
- Preserves scroll position when manually scrolled up
**Artifacts Tab**
- File browser for simulation output files
- Navigate folders (breadcrumb navigation)
- Click files to download
- Preview JSON files inline
Implementation (Logs)
---------------------
.. code-block:: text
function LogsPanel({ runId }: { runId: string }) {
const [logs, setLogs] = useState([])
const logsEndRef = useRef(null)
useEffect(() => {
const eventSource = new EventSource(runsApi.getLogsUrl(runId))
eventSource.addEventListener('log', (e) => {
const data = JSON.parse(e.data)
setLogs((prev) => [...prev, data.line])
})
eventSource.addEventListener('done', () => {
eventSource.close()
})
return () => eventSource.close()
}, [runId])
// Auto-scroll effect
useEffect(() => {
logsEndRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [logs])
return (
{logs.map((line, i) => (
{line}
))}
)
}
----
TopologyPage
============
:Location: ``src/pages/TopologyPage.tsx``
:Route: ``/topology``
Interactive network topology visualization.
Features
--------
- Dropdown to select topology (NSFNet, USNet, etc.)
- Force-directed graph visualization
- Click nodes to see details
- Zoom and pan controls
- Node degree information on selection
Implementation
--------------
.. code-block:: text
function TopologyPage() {
const [selectedTopology, setSelectedTopology] = useState('NSFNet')
const [selectedNode, setSelectedNode] = useState(null)
const { data: topologies } = useQuery({
queryKey: ['topologies'],
queryFn: topologyApi.list,
})
const { data: topology } = useQuery({
queryKey: ['topology', selectedTopology],
queryFn: () => topologyApi.get(selectedTopology),
enabled: !!selectedTopology,
})
return (
{selectedNode !== null && (
)}
{topology && (
)}
)
}
----
ConfigEditorPage
================
:Location: ``src/pages/ConfigEditorPage.tsx``
:Route: ``/config``
INI configuration file editor.
Features
--------
- Template selection dropdown
- Monaco editor with INI syntax highlighting
- Dark/light theme support
- Copy to clipboard
- Use with new run (navigates to NewRunPage with config)
Implementation
--------------
.. code-block:: text
function ConfigEditorPage() {
const [template, setTemplate] = useState(null)
const [content, setContent] = useState('')
const { theme } = useTheme()
const { data: templates } = useQuery({
queryKey: ['templates'],
queryFn: configsApi.listTemplates,
})
const { data: templateData } = useQuery({
queryKey: ['template', template],
queryFn: () => configsApi.getTemplate(template!),
enabled: !!template,
})
useEffect(() => {
if (templateData) {
setContent(templateData.content)
}
}, [templateData])
return (
t.name) ?? []}
/>
setContent(value ?? '')}
language="ini"
theme={theme === 'dark' ? 'vs-dark' : 'light'}
/>
)
}
----
CodebaseExplorerPage
====================
:Location: ``src/pages/CodebaseExplorerPage.tsx``
:Route: ``/codebase``
Browse and explore the FUSION codebase.
Features
--------
- Architecture view with module cards
- Guided tour for newcomers
- File tree navigation
- Code viewer with syntax highlighting
- File search
Views
-----
**Architecture View**
Grid of cards showing high-level modules (core, modules, configs, etc.).
Each card shows the module name, description, and key files.
**Code View**
Split panel with file tree on left and code viewer on right.
Supports syntax highlighting for Python, INI, TypeScript, etc.
**Tour Mode**
Step-by-step walkthrough of the codebase structure with
highlighted sections and explanatory text.
Implementation
--------------
.. code-block:: text
function CodebaseExplorerPage() {
const [view, setView] = useState<'architecture' | 'code'>('architecture')
const [selectedFile, setSelectedFile] = useState(null)
const [tourActive, setTourActive] = useState(false)
const { data: tree } = useQuery({
queryKey: ['codebase-tree'],
queryFn: codebaseApi.getTree,
})
const { data: fileContent } = useQuery({
queryKey: ['codebase-file', selectedFile],
queryFn: () => codebaseApi.getFile(selectedFile!),
enabled: !!selectedFile,
})
if (view === 'architecture') {
return
}
return (
)
}
----
SettingsPage
============
:Location: ``src/pages/SettingsPage.tsx``
:Route: ``/settings``
User preferences and settings.
Features
--------
- Theme selection (light, dark, system)
- Settings persisted to localStorage
Implementation
--------------
.. code-block:: text
function SettingsPage() {
const { theme, setTheme } = useTheme()
return (
Settings
Appearance
Theme
{['light', 'dark', 'system'].map((t) => (
setTheme(t)}
>
{t.charAt(0).toUpperCase() + t.slice(1)}
))}
)
}