diff --git a/backend/src/server.ts b/backend/src/server.ts
index 1293dbb..b9bb808 100644
--- a/backend/src/server.ts
+++ b/backend/src/server.ts
@@ -3,7 +3,7 @@ import { Healthcheck } from "./healthcheck";
import { printEndpoints, validateHash } from "./utils";
import { LogRequestMiddleware } from "./log";
import * as fs from "node:fs";
-import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
+import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, existsSync } from "node:fs";
import { entry } from "./entry";
import cors from "cors";
import archiver from "archiver";
@@ -362,6 +362,42 @@ v1.post("/remove", (req: Request, res: Response): void => {
res.status(201).json({ code: 201, message: `Deleted ${files.length} files.` });
});
+v1.post("/move", (req: Request, res: Response): void => {
+ // Get the array of paths and the root
+ const { oldPath, newPath } = req.body;
+
+ try {
+ // Get path of new path
+ const newDirectory = path.dirname(newPath);
+
+ // Ensure the directory exists
+ if (!existsSync(newDirectory)) {
+ mkdirSync(newDirectory, { recursive: true });
+ console.log(`Created directory: ${newDirectory}`);
+ }
+
+ // Move the file
+ renameSync(oldPath, newPath);
+ console.log(`File moved from ${oldPath} to ${newPath}`);
+
+ res.status(200).json({ code: 200 });
+ } catch (err: any) {
+ console.error("Error moving file:", err);
+ // You might want to send a more specific error message based on 'err.code'
+ if (err.code === 'EXDEV') {
+ // This specific error means moving across different file systems.
+ // Synchronous fallback would be more complex (read/write stream synchronously),
+ // which is why async is preferred here. For synchronous, you'd generally
+ // just fail or implement a blocking copy/delete.
+ res.status(500).json({ code: 500, error: "Error: Cannot move across different file systems synchronously. Try copying and deleting." });
+ } else if (err.code === 'ENOENT') {
+ res.status(404).json({ code: 404, error: "Error: Source file or destination path not found." });
+ } else {
+ res.status(500).json({ code: 500, error: `Failed to move file: ${err.message}` });
+ }
+ }
+});
+
/**
* Apply the routes to the server
*/
diff --git a/frontend/src/components/MoveDirectory.jsx b/frontend/src/components/MoveDirectory.jsx
new file mode 100644
index 0000000..f27592e
--- /dev/null
+++ b/frontend/src/components/MoveDirectory.jsx
@@ -0,0 +1,57 @@
+import { useState, useEffect } from "react";
+
+/**
+ * Move a file or directory.
+ * @constructor
+ */
+export default function MoveDirectory({ close, move, path }) {
+ const [dirName, setDirName] = useState("");
+
+ useEffect(() => {
+ setDirName("/" + path.join("/"));
+ }, [path]);
+
+ const moveDirectory = () => move(dirName);
+ const updateDirName = (e) => setDirName(e.target.value);
+
+ const closeWithoutSaving = () => {
+ setDirName("");
+ close();
+ }
+
+ return <>
+
+ {/* Blured backdrop */}
+
+
+
+
+ Move/Rename Directory
+
+
+ Move a file or directory from the current directory to a new location. This can be used to rename files
+ if the base directory remains the same.
+
+
+
+
+
+
+
+
+
+ >
+}
diff --git a/frontend/src/components/PathDisplay.jsx b/frontend/src/components/PathDisplay.jsx
index aeda4c7..ba6242c 100644
--- a/frontend/src/components/PathDisplay.jsx
+++ b/frontend/src/components/PathDisplay.jsx
@@ -6,7 +6,7 @@
* @returns {JSX.Element}
* @constructor
*/
-function HomeButton({onClick, enabled}) {
+function HomeButton({ onClick, enabled }) {
return <>
>
}
-function BackButton({onClick, enabled}) {
+function BackButton({ onClick, enabled }) {
return <>
>
}
-function CreateButton({onClick}) {
+function CreateButton({ onClick }) {
return <>
>
}
-function DeleteButton({onClick, enabled}) {
+function DeleteButton({ onClick, enabled }) {
return <>
>
}
+function MoveButton({ onClick, enabled }) {
+ return <>
+
+
+ >
+
+}
+
/**
*
* @param name {string}
@@ -74,7 +90,7 @@ function DeleteButton({onClick, enabled}) {
* @returns {JSX.Element}
* @constructor
*/
-function PathElement({name, index, onClick}) {
+function PathElement({ name, index, onClick }) {
const handleClick = () => onClick(index);
return <>