Feat: Update API URL and refactor FileTable component for improved path handling

This commit is contained in:
Atharva Ombase
2025-04-19 20:04:57 +05:30
parent afccce0be3
commit 1f6cbf4310
3 changed files with 35 additions and 88 deletions
+1 -1
View File
@@ -1 +1 @@
VITE_API_URL=http://192.168.29.61:8080 VITE_API_URL=http://192.168.29.61:8081
+34 -53
View File
@@ -18,20 +18,24 @@ import {
ArrowLeft, ArrowLeft,
} from "lucide-react"; } from "lucide-react";
const username = localStorage.getItem("username");
// const authToken = localStorage.getItem("token");
const API_URL = import.meta.env.VITE_API_URL || "http://localhost:8080"; const API_URL = import.meta.env.VITE_API_URL || "http://localhost:8080";
// const token = localStorage.getItem("token");
const FileTable = ({ initialPath }) => { const FileTable = ({ initialPath }) => {
const [currentPath, setCurrentPathState] = useState(initialPath || "/"); // Read username dynamically to avoid stale null on first load
const username = localStorage.getItem("username") || "";
const userRoot = `/${username}`;
// Initialize currentPath only once with the correct userRoot
const [currentPath, setCurrentPathState] = useState(
() => initialPath || userRoot
);
const [files, setFiles] = useState([]); const [files, setFiles] = useState([]);
const dispatch = useDispatch(); const dispatch = useDispatch();
const isUploading = useSelector((state) => state.upload.isUploading); const isUploading = useSelector((state) => state.upload.isUploading);
const getType = (entry) => const getType = (entry) =>
entry.trim().startsWith("📁") ? "Folder" : "File"; entry.trim().startsWith("📁") ? "Folder" : "File";
const getName = (entry) => entry.trim().replace(/^📁\s*|^📄\s*/, ""); const getName = (entry) => entry.trim().replace(/^📁\s*|^📄\s*/, "");
const isFile = (entry) => getType(entry) === "File"; const isFile = (entry) => getType(entry) === "File";
const getIcon = (name, type) => { const getIcon = (name, type) => {
@@ -85,7 +89,6 @@ const FileTable = ({ initialPath }) => {
)}` )}`
); );
const data = await res.json(); const data = await res.json();
// filter out indented children, only top-level entries
const filtered = data.filter( const filtered = data.filter(
(entry) => entry.match(/^ */)[0].length === 0 (entry) => entry.match(/^ */)[0].length === 0
); );
@@ -99,18 +102,18 @@ const FileTable = ({ initialPath }) => {
const deleteFileOrFolder = async (name, type, e) => { const deleteFileOrFolder = async (name, type, e) => {
e.stopPropagation(); e.stopPropagation();
try { try {
const hdfsPath = const hdfsPath = `${currentPath}/${name}`;
currentPath === "/" ? `/${name}` : `${currentPath}/${name}`;
const encoded = encodeURIComponent(hdfsPath);
const endpoint = const endpoint =
type === "File" type === "File"
? `${API_URL}/api/hdfs/deleteFile?hdfsPath=${encoded}` ? `${API_URL}/api/hdfs/deleteFile?hdfsPath=${encodeURIComponent(
: `${API_URL}/api/hdfs/deleteFolder?hdfsPath=${encoded}`; hdfsPath
)}`
: `${API_URL}/api/hdfs/deleteFolder?hdfsPath=${encodeURIComponent(
hdfsPath
)}`;
const resp = await fetch(endpoint, { method: "DELETE" }); const resp = await fetch(endpoint, { method: "DELETE" });
if (!resp.ok) { if (!resp.ok) console.error("Deletion failed:", await resp.text());
console.error("Deletion failed:", await resp.text());
}
fetchFiles(); fetchFiles();
} catch (err) { } catch (err) {
console.error("Failed to delete:", err); console.error("Failed to delete:", err);
@@ -123,60 +126,40 @@ const FileTable = ({ initialPath }) => {
}, [currentPath, dispatch, isUploading]); }, [currentPath, dispatch, isUploading]);
const handleOpenFolder = (folderName) => { const handleOpenFolder = (folderName) => {
const newPath = setCurrentPathState((prev) => `${prev}/${folderName}`);
currentPath === "/" ? `/${folderName}` : `${currentPath}/${folderName}`;
setCurrentPathState(newPath);
}; };
const goBack = () => { const goBack = () => {
if (currentPath === "/") return; if (currentPath === userRoot) return;
const parts = currentPath.split("/").filter(Boolean); const parts = currentPath.split("/").filter(Boolean);
parts.pop(); parts.pop();
setCurrentPathState(parts.length === 0 ? "/" : `/${parts.join("/")}`); setCurrentPathState(parts.length === 0 ? userRoot : `/${parts.join("/")}`);
}; };
const handleFileDownload = async (hdfsPath, name, event) => { const handleFileDownload = async (hdfsPath, name, event) => {
event.stopPropagation(); // Prevent row click (if any) event.stopPropagation();
try { try {
const authToken = localStorage.getItem("token"); // Get JWT token from localStorage const authToken = localStorage.getItem("token");
const response = await fetch( const response = await fetch(
`${API_URL}/api/hdfs/downloadFile?hdfsEncPath=${hdfsPath}&localPath=${name}&username=${username}`, `${API_URL}/api/hdfs/downloadFile?hdfsEncPath=${encodeURIComponent(
hdfsPath
)}&localPath=${name}&username=${username}`,
{ {
method: "POST", method: "POST",
headers: { headers: { Authorization: `Bearer ${authToken}` },
Authorization: `Bearer ${authToken}`,
},
} }
); );
if (!response.ok) { if (!response.ok) throw new Error(await response.text());
const errorText = await response.text();
throw new Error(`Download failed: ${errorText}`);
}
// Extract filename from response headers or fallback to 'name'
const contentDisposition = response.headers.get("Content-Disposition");
let downloadedFileName = name;
if (contentDisposition && contentDisposition.includes("filename=")) {
const match = contentDisposition.match(
/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
);
if (match) downloadedFileName = match[1];
}
console.log(
`${API_URL}/api/hdfs/downloadFile?hdfsEncPath=${hdfsPath}&localPath=${name}&username=${username}`,
authToken
);
const blob = await response.blob(); const blob = await response.blob();
const blobUrl = window.URL.createObjectURL(blob); const url = window.URL.createObjectURL(blob);
const link = document.createElement("a"); const link = document.createElement("a");
link.href = blobUrl; link.href = url;
link.download = downloadedFileName; link.download = name;
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
link.remove(); link.remove();
window.URL.revokeObjectURL(blobUrl); window.URL.revokeObjectURL(url);
fetchFiles(); fetchFiles();
} catch (error) { } catch (error) {
console.error("Download failed:", error); console.error("Download failed:", error);
@@ -188,7 +171,7 @@ const FileTable = ({ initialPath }) => {
<div className="relative overflow-x-auto rounded-2xl shadow-lg border border-blue-200"> <div className="relative overflow-x-auto rounded-2xl shadow-lg border border-blue-200">
<div className="flex items-center justify-between px-6 py-4 bg-blue-100 text-black font-semibold text-sm"> <div className="flex items-center justify-between px-6 py-4 bg-blue-100 text-black font-semibold text-sm">
<span className="truncate max-w-[80%]">Path: {currentPath}</span> <span className="truncate max-w-[80%]">Path: {currentPath}</span>
{currentPath !== "/" && ( {currentPath !== userRoot && (
<button <button
onClick={goBack} onClick={goBack}
className="flex items-center gap-1 text-blue-600 hover:underline text-sm" className="flex items-center gap-1 text-blue-600 hover:underline text-sm"
@@ -206,7 +189,6 @@ const FileTable = ({ initialPath }) => {
<th className="px-6 py-3">Actions</th> <th className="px-6 py-3">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{files.length === 0 ? ( {files.length === 0 ? (
<tr> <tr>
@@ -218,8 +200,7 @@ const FileTable = ({ initialPath }) => {
files.map((entry, idx) => { files.map((entry, idx) => {
const name = getName(entry); const name = getName(entry);
const type = getType(entry); const type = getType(entry);
const hdfsPath = const hdfsPath = `${currentPath}/${name}`;
currentPath === "/" ? `/${name}` : `${currentPath}/${name}`;
return ( return (
<tr <tr
-34
View File
@@ -1,34 +0,0 @@
// utils/api.js
export const uploadFileToHDFS = async (
file,
hdfsPath,
uploadedFileName,
username
) => {
const formData = new FormData();
formData.append("file", file);
formData.append("hdfsPath", "/kalas");
formData.append("uploadedFileName", uploadedFileName);
formData.append("username", "kalas");
try {
const response = await fetch(
"http://192.168.29.61:8080/api/hdfs/uploadFile",
{
method: "POST",
body: formData,
}
);
if (response.ok) {
const data = await response.json(); // or response.json() if JSON is returned
console.log("Response:", data);
} else {
console.error("Upload failed with status:", response.status);
}
} catch (error) {
console.error("Error uploading file:", error);
alert("An error occurred while uploading the file.");
}
};