Skip to content

Commit

Permalink
Merge pull request #28 from Saifullah-dev/refactor/code-splitting
Browse files Browse the repository at this point in the history
Refactor: Providing props for File Manager
  • Loading branch information
Saifullah-dev authored Aug 20, 2024
2 parents 5123733 + 64122ca commit 903f9ad
Show file tree
Hide file tree
Showing 15 changed files with 318 additions and 278 deletions.
16 changes: 12 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"react": "^18.3.1",
"react-collapsible": "^2.10.0",
"react-dom": "^18.3.1",
"react-icons": "^5.2.1"
"react-icons": "^5.2.1",
"react-loading": "^2.0.3"
},
"devDependencies": {
"@types/react": "^18.3.3",
Expand Down
163 changes: 162 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,168 @@
import { useState } from "react";
import FileManager from "./File Manager/FileManager";

function App() {
return <FileManager />;
const [files, setFiles] = useState([
{
name: "DCIM",
isDirectory: true,
path: "",
},
{
name: "Camera",
isDirectory: true,
path: "/DCIM",
},
{
name: "Portraits",
isDirectory: true,
path: "/DCIM/Camera",
},
{
name: "Pic.png",
isDirectory: false,
path: "",
},
]);
const [isLoading, setIsLoading] = useState(false);

// Create Folder
const handleCreateFolder = (folderName, currentPath) => {
setFiles((prev) => {
return [
...prev,
{
name: folderName,
path: currentPath,
isDirectory: true,
},
];
});
};
//

// Rename File/Folder
const handleRename = (selectedFile, newName) => {
setFiles((prev) => {
return prev.map((file) => {
if (file.name === selectedFile?.name && file.path === selectedFile?.path) {
return {
// Rename the file itself
...file,
name: newName,
};
} else if (file.path.startsWith(selectedFile.path + "/" + selectedFile.name)) {
// Path update for all files in the folder
const basePath = selectedFile.path + "/" + selectedFile.name;
const newBasePath = basePath.split("/").slice(0, -1).join("/") + "/" + newName;
const newPath = newBasePath + file.path.slice(basePath.length);
return {
...file,
path: newPath,
};
} else {
return file;
}
});
});
};
//

// Delete File/Folder
const handleDelete = (file) => {
if (file.isDirectory) {
setFiles((prev) => {
return prev.filter((f) => {
const folderToDelete = f.path === file.path && f.name === file.name;
const folderChildren = f.path.startsWith(file.path + "/" + file.name);
return !folderToDelete && !folderChildren;
});
});
} else {
setFiles((prev) => {
return prev.filter((f) => !(f.name === file.name && f.path === file.path));
});
}
};
//

// Paste File/Folder
const getCopiedFiles = (file, pastePath) => {
const children = file.children ?? [];
return [
{ name: file.name, isDirectory: file.isDirectory, path: pastePath },
...children.flatMap((child) => getCopiedFiles(child, pastePath + "/" + file.name)),
];
};

const handleDuplicateFile = (file, pastePath, pastePathFiles) => {
if (file.path === pastePath || pastePathFiles.find((f) => f.name === file.name)) {
const fileExtension = file.isDirectory ? "" : "." + file.name.split(".").pop();
const fileName = file.isDirectory ? file.name : file.name.split(".").slice(0, -1).join(".");

// Generating new file name for duplicate file
let maxFileNum = 0;
// If there exists a file with name fileName (1), fileName (2), etc.
// Check if the number is greater than the maxFileNum, then set it to that greater number
const fileNameRegex = new RegExp(`${fileName} \\(\\d+\\)`);
pastePathFiles.forEach((f) => {
const fName = f.isDirectory ? f.name : f.name.split(".").slice(0, -1).join(".");
if (fileNameRegex.test(fName)) {
const fileNumStr = fName.split(`${fileName} (`).pop().slice(0, -1);
const fileNum = parseInt(fileNumStr);
if (!isNaN(fileNum) && fileNum > maxFileNum) {
maxFileNum = fileNum;
}
}
});
const appendNum = ` (${++maxFileNum})`;
const newFileName = fileName + appendNum + fileExtension;
//

return { ...file, name: newFileName };
} else {
return file;
}
};

const handlePaste = (pastePath, clipBoard, filesCopied) => {
setFiles((prevFiles) => {
if (clipBoard.isMoving) {
prevFiles = prevFiles.filter((f) => {
return !filesCopied.find((cf) => cf.name === f.name && cf.path === f.path);
});
}

return [
...prevFiles,
...clipBoard.files.flatMap((file) => {
const pastePathFiles = prevFiles.filter((f) => f.path === pastePath);
const nonDuplicateFile = handleDuplicateFile(file, pastePath, pastePathFiles);
return getCopiedFiles(nonDuplicateFile, pastePath);
}),
];
});
};
//

// Refresh Files
const handleRefresh = () => {
// Refresh Files API call here...
};
//

return (
<FileManager
files={files}
onCreateFolder={handleCreateFolder}
onRename={handleRename}
onDelete={handleDelete}
onPaste={handlePaste}
onRefresh={handleRefresh}
isLoading={isLoading}
allowedFileExtensions=".txt, .png, .jpg, .jpeg, .pdf, .doc, .docx"
/>
);
}

export default App;
12 changes: 9 additions & 3 deletions src/File Manager/Actions/Actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ const Actions = ({
currentPath,
currentPathFiles,
selectedFile,
setSelectedFile,
handleCreateFolder,
handleFileRename,
handleRename,
setIsItemSelection,
handleDelete,
allowedFileExtensions,
}) => {
const [activeAction, setActiveAction] = useState(null);

Expand All @@ -31,7 +34,7 @@ const Actions = ({
},
uploadFile: {
title: "Upload File",
component: <UploadFileAction />,
component: <UploadFileAction allowedFileExtensions={allowedFileExtensions} />,
width: "35%",
},
rename: {
Expand All @@ -41,7 +44,8 @@ const Actions = ({
selectedFile={selectedFile}
currentPathFiles={currentPathFiles}
triggerAction={triggerAction}
handleFileRename={handleFileRename}
handleRename={handleRename}
setSelectedFile={setSelectedFile}
/>
),
width: "25%",
Expand All @@ -53,6 +57,8 @@ const Actions = ({
selectedFile={selectedFile}
triggerAction={triggerAction}
handleDelete={handleDelete}
setIsItemSelection={setIsItemSelection}
setSelectedFile={setSelectedFile}
/>
),
width: "25%",
Expand Down
2 changes: 1 addition & 1 deletion src/File Manager/Actions/CreateFolder.action.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const CreateFolderAction = ({

if (!alreadyExists) {
// Current path doesn't have the same folder name
handleCreateFolder(newFolderName);
handleCreateFolder(newFolderName, currentPath);
triggerAction.close();
} else {
setFolderErrorMessage(`A folder with the name "${newFolderName}" already exits.`);
Expand Down
10 changes: 9 additions & 1 deletion src/File Manager/Actions/Delete.action.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import React from "react";
import Button from "../../components/Button/Button";

const DeleteAction = ({ selectedFile, triggerAction, handleDelete }) => {
const DeleteAction = ({
selectedFile,
triggerAction,
handleDelete,
setIsItemSelection,
setSelectedFile,
}) => {
const handleDeleting = (file) => {
handleDelete(file);
setIsItemSelection(false);
setSelectedFile(null);
triggerAction.close();
};

Expand Down
11 changes: 9 additions & 2 deletions src/File Manager/Actions/Rename.action.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import React, { useEffect, useRef, useState } from "react";
import Button from "../../components/Button/Button";
import { IoWarningOutline } from "react-icons/io5";

const RenameAction = ({ selectedFile, currentPathFiles, handleFileRename, triggerAction }) => {
const RenameAction = ({
selectedFile,
currentPathFiles,
handleRename,
triggerAction,
setSelectedFile,
}) => {
const [renameFile, setRenameFile] = useState(selectedFile?.name);
const renameFileRef = useRef(null);
const [renameFileWarning, setRenameFileWarning] = useState(false);
Expand Down Expand Up @@ -58,7 +64,8 @@ const RenameAction = ({ selectedFile, currentPathFiles, handleFileRename, trigge
return;
}
}
handleFileRename(selectedFile, renameFile);
handleRename(selectedFile, renameFile);
setSelectedFile((prev) => ({ ...prev, name: renameFile }));
triggerAction.close();
};

Expand Down
4 changes: 3 additions & 1 deletion src/File Manager/Actions/UploadFile.action.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { useFileIcons } from "../../hooks/useFileIcons";
import { FaRegFile } from "react-icons/fa6";
import Progress from "../../components/Progress/Progress";

const UploadFileAction = ({ onFilesSelected }) => {
const UploadFileAction = ({ onFilesSelected, allowedFileExtensions }) => {
const [files, setFiles] = useState([]);
const [isDragging, setIsDragging] = useState(false);
const fileIcons = useFileIcons(33);

// Todo: Also validate allowed file extensions on drop
const handleDrop = (e) => {
e.preventDefault();
setIsDragging(false);
Expand Down Expand Up @@ -51,6 +52,7 @@ const UploadFileAction = ({ onFilesSelected }) => {
className="choose-file-input"
onChange={handleChooseFile}
multiple
accept={allowedFileExtensions}
/>
</Button>
</div>
Expand Down
Loading

0 comments on commit 903f9ad

Please sign in to comment.