import React, { useState } from 'react';
import axios from 'axios';
import { Container, Navbar, Card, ProgressBar, Alert, Button } from 'react-bootstrap';
// This will be our main component for handling uploads and progress
const UploadComponent = () => {
const [file, setFile] = useState(null);
const [progress, setProgress] = useState(0);
const [statusMessage, setStatusMessage] = useState('Upload a file to begin.');
const [downloadUrl, setDownloadUrl] = useState(null);
const [error, setError] = useState(null);
const handleFileChange = (event) => {
setFile(event.target.files[0]);
setStatusMessage(event.target.files[0] ? event.target.files[0].name : 'Upload a file to begin.');
setProgress(0);
setDownloadUrl(null);
setError(null);
};
const handleUpload = async () => {
if (!file) return;
setProgress(0);
setDownloadUrl(null);
setError(null);
setStatusMessage('Uploading file...');
const formData = new FormData();
formData.append('file', file);
try {
// Step 1: Upload the file to the backend (will be proxied by the dev server)
const uploadResponse = await axios.post('/upload/', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
const { file_id, filename } = uploadResponse.data;
setStatusMessage('File uploaded. Initializing processing...');
// Step 2: Establish a WebSocket connection (proxied by the dev server)
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsHost = window.location.hostname;
const wsPort = window.location.port ? `:${window.location.port}` : '';
const ws = new WebSocket(`${wsProtocol}//${wsHost}${wsPort}/ws/${file_id}/${filename}`);
ws.onopen = () => {
setStatusMessage('Connection established. Starting processing...');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.status === 'processing') {
setProgress(data.progress);
setStatusMessage(data.message);
} else if (data.status === 'complete') {
setProgress(data.progress);
setStatusMessage(data.message);
setDownloadUrl(data.download_url); // This will be a relative URL like /download/xyz.dxf
ws.close();
} else if (data.status === 'error') {
setError(data.message);
setProgress(0);
ws.close();
}
};
ws.onerror = (event) => {
console.error("WebSocket error observed:", event);
setError('A connection error occurred. Could not get progress updates.');
};
ws.onclose = () => {
console.log('WebSocket connection closed.');
// If the process isn't complete, show a message
if (!downloadUrl && !error) {
setStatusMessage('Connection closed.');
}
};
} catch (err) {
console.error(err);
setError(err.response?.data?.detail || 'File upload failed. Please try again.');
}
};
return (
<Card>
<Card.Body>
<Card.Title>Mesh Simplifier</Card.Title>
<Card.Text>
Select a <code>.obj</code>, <code>.stl</code>, or <code>.3mf</code> file to process. The tool will generate a DXF file containing the layered profiles of your model.
</Card.Text>
<div className="input-group mb-3">
<input type="file" className="form-control" id="inputGroupFile02" onChange={handleFileChange} accept=".obj,.stl,.3mf" />
</div>
{file && (
<Button variant="primary" onClick={handleUpload} className="mb-3">
Start Processing
</Button>
)}
<hr />
<h6>Processing Status</h6>
<p className="text-muted">{statusMessage}</p>
<ProgressBar now={progress} label={`${progress}%`} animated />
{error && (
<Alert variant="danger" className="mt-3">
{error}
</Alert>
)}
{downloadUrl && (
<div className="mt-4 text-center">
<Button variant="success" href={downloadUrl}>
Download DXF File
</Button>
</div>
)}
</Card.Body>
</Card>
);
};
function App() {
return (
<div>
<Navbar bg="dark" variant="dark">
<Container>
<Navbar.Brand href="#home">DXF Curve Generator</Navbar.Brand>
</Container>
</Navbar>
<Container className="mt-5">
<UploadComponent />
</Container>
</div>
);
}
export default App;