You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
4.3 KiB

'use client';
import { useState, useEffect } from 'react';
import { useNotification } from '@/app/context/NotificationContext';
import GrantSudoLink from "@/app/components/GrantSudoLink";
export default function TFTPPage() {
const [files, setFiles] = useState([]);
const [selectedFile, setSelectedFile] = useState(null);
const { showNotification } = useNotification();
const fetchFiles = async () => {
try {
const response = await fetch('/api/tftp/files');
const data = await response.json();
if (response.ok) {
setFiles(data.files);
showNotification('File list refreshed successfully.', 'success');
} else {
showNotification(data.error, 'error');
}
} catch (error) {
showNotification('Failed to fetch files.', 'error');
}
};
const handleDownload = (filename) => {
window.location.href = `/api/tftp/files/${filename}`;
};
const handleDelete = async (filename) => {
if (confirm(`Are you sure you want to delete ${filename}?`)) {
try {
const response = await fetch(`/api/tftp/files/${filename}`, {
method: 'DELETE',
});
const data = await response.json();
if (response.ok) {
showNotification('File deleted successfully.', 'success');
fetchFiles();
} else {
showNotification(data.error, 'error');
}
} catch (error) {
showNotification('Failed to delete file.', 'error');
}
}
};
const handleUpload = async (event) => {
event.preventDefault();
if (!selectedFile) return;
const formData = new FormData();
formData.append('file', selectedFile);
try {
const response = await fetch('/api/tftp/files/upload', {
method: 'POST',
body: formData,
});
const data = await response.json();
if (response.ok) {
showNotification('File uploaded successfully.', 'success');
fetchFiles();
} else {
showNotification(data.error, 'error');
}
} catch (error) {
showNotification('Failed to upload file.', 'error');
}
};
useEffect(() => {
fetchFiles();
}, []);
return (
<div className="container mt-5">
<h1 className="mb-4">TFTP Server Files</h1>
<div className="mb-3">
<input
type="file"
className="form-control"
id="fileUpload"
onChange={(e) => setSelectedFile(e.target.files[0])}
/>
<button className="btn btn-primary mt-2" onClick={handleUpload}>
Upload File
</button>
<button className="btn btn-secondary mt-2 ml-2" onClick={fetchFiles}>
Refresh
</button>
</div>
<div className="mb-3">
<div>
If upload fails: <GrantSudoLink text="Grant Sudo Rights"/>
</div>
</div>
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Filename</th>
<th scope="col">Size (bytes)</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{files.map((file) => (
<tr key={file.name}>
<td>{file.name}</td>
<td>{file.size}</td>
<td>
<button className="btn btn-success btn-sm mr-2" onClick={() => handleDownload(file.name)}>
Download
</button>
<button className="btn btn-danger btn-sm" onClick={() => handleDelete(file.name)}>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}

Powered by TurnKey Linux.