Skip to content

Commit 5d5fe15

Browse files
authored
Merge pull request #70 from Coding-Club-IITG/prajit
Add folder UI and recursive delete folder
2 parents 06c5c43 + 525ec7b commit 5d5fe15

File tree

8 files changed

+147
-106
lines changed

8 files changed

+147
-106
lines changed

client/src/api/Folder.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ export const createFolder = async ({ name, course, parentFolder,childType }) =>
2424
return data;
2525
};
2626

27-
export const deleteFolder = async ({ folderId, parentFolderId }) => {
27+
export const deleteFolder = async ({ folder, parentFolderId }) => {
2828
const { data } = await API.delete(`/folder/delete`, {
29-
params: { folderId, parentFolderId },
29+
params: { folder, parentFolderId },
3030
});
3131
return data;
3232
};

client/src/screens/browse/components/browsefolder/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { deleteFolder } from "../../../../api/Folder";
66
import { toast } from "react-toastify";
77
import { RefreshCurrentFolder } from "../../../../actions/filebrowser_actions";
88
import { ConfirmDialog } from "./confirmDialog";
9-
const BrowseFolder = ({ type = "file", color, path, name, subject, folderData }) => {
9+
const BrowseFolder = ({ type = "file", color, path, name, subject, folderData, parentFolder }) => {
1010
const dispatch = useDispatch();
1111
const [showConfirm, setShowConfirm] = useState(false);
1212
const onClick = (folderData) => {
@@ -16,7 +16,7 @@ const BrowseFolder = ({ type = "file", color, path, name, subject, folderData })
1616

1717
const handleDelete = async (e) => {
1818
try {
19-
await deleteFolder({ folderId: folderData._id, parentFolderId: folderData.parent });
19+
await deleteFolder({ folder: folderData, parentFolderId: parentFolder._id });
2020
toast.success("Folder deleted successfully!");
2121
dispatch(RefreshCurrentFolder());
2222
} catch (err) {

client/src/screens/browse/components/folder-info/confirmDialog.jsx

Lines changed: 82 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import React from "react";
2+
import { useState } from "react";
3+
import Wrapper from "../../../contributions/components/wrapper";
24

35
const styles = {
46
overlay: {
@@ -13,116 +15,104 @@ const styles = {
1315
justifyContent: "center",
1416
zIndex: 1000,
1517
},
16-
dialog: {
17-
backgroundColor: "#fff",
18-
padding: "25px 30px",
19-
borderRadius: "8px",
20-
maxWidth: "400px",
21-
width: "90%",
22-
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.2)",
23-
textAlign: "center",
24-
fontFamily: "sans-serif",
25-
},
26-
heading: {
27-
fontSize: "2em",
28-
marginBottom: "0.5em",
29-
},
30-
input: {
31-
padding: "10px",
32-
fontSize: "1em",
33-
width: "100%",
34-
marginBottom: "1.5em",
35-
border: "1px solid #ccc",
36-
borderRadius: "5px",
37-
},
38-
selectLabel: {
39-
textAlign: "left",
40-
fontWeight: "500",
41-
marginBottom: "0.3em",
42-
display: "block",
43-
},
44-
select: {
45-
width: "100%",
46-
padding: "10px",
47-
fontSize: "1em",
48-
marginBottom: "1.5em",
49-
border: "1px solid #ccc",
50-
borderRadius: "5px",
51-
},
52-
buttonGroup: {
53-
display: "flex",
54-
justifyContent: "center",
55-
gap: "1em",
56-
},
57-
confirmBtn: {
58-
backgroundColor: "#22c55e",
59-
color: "#fff",
60-
border: "none",
61-
padding: "10px 18px",
62-
borderRadius: "5px",
63-
cursor: "pointer",
64-
fontWeight: "bold",
65-
fontSize: "1em",
66-
},
67-
cancelBtn: {
68-
backgroundColor: "#9ca3af",
69-
color: "#fff",
70-
border: "none",
71-
padding: "10px 18px",
72-
borderRadius: "5px",
73-
cursor: "pointer",
74-
fontWeight: "bold",
75-
fontSize: "1em",
76-
},
7718
};
7819

7920
const ConfirmDialog = ({
8021
show,
8122
input = false,
8223
inputValue = "",
83-
onInputChange = () => {},
24+
onInputChange = () => { },
8425
childType = "",
85-
onChildTypeChange = () => {},
26+
onChildTypeChange = () => { },
8627
onCancel,
8728
onConfirm,
88-
confirmText = "Confirm",
89-
cancelText = "Cancel",
9029
}) => {
30+
const [submitEnabled, setSubmitEnabled] = useState(false);
9131
if (!show) return null;
9232

9333
return (
34+
// <div style={styles.overlay}>
35+
// <div style={styles.dialog}>
36+
// <h2 style={styles.heading}>Enter Folder Name</h2>
37+
// {input && (
38+
// <input
39+
// type="text"
40+
// placeholder="Folder name"
41+
// value={inputValue}
42+
// onChange={onInputChange}
43+
// style={styles.input}
44+
// />
45+
// )}
46+
// <select
47+
// value={childType}
48+
// onChange={(e) => onChildTypeChange(e.target.value)}
49+
// style={styles.select}
50+
// >
51+
// <option value="" disabled>
52+
// Select child type
53+
// </option>
54+
// <option value="File">File</option>
55+
// <option value="Folder">Folder</option>
56+
// </select>
57+
// <div style={styles.buttonGroup}>
58+
// <button style={styles.cancelBtn} onClick={onCancel}>
59+
// {cancelText}
60+
// </button>
61+
// <button style={styles.confirmBtn} onClick={onConfirm}>
62+
// {confirmText}
63+
// </button>
64+
// </div>
65+
// </div>
66+
// </div>
9467
<div style={styles.overlay}>
95-
<div style={styles.dialog}>
96-
<h2 style={styles.heading}>Enter Folder Name</h2>
97-
{input && (
68+
<Wrapper>
69+
<div className="head">📁 Add Folder</div>
70+
<div className="disclaimer">
71+
The new folder will be a subfolder of the current folder
72+
</div>
73+
<div className="course">
74+
<label className="label_course" htmlFor="folder">
75+
NAME :
76+
</label>
9877
<input
99-
type="text"
100-
placeholder="Folder name"
78+
placeholder="Name of Folder"
79+
name="folder"
80+
className="input_course"
10181
value={inputValue}
102-
onChange={onInputChange}
103-
style={styles.input}
82+
onChange={(e) => {
83+
if (e.target.value.length > 0) setSubmitEnabled(true);
84+
else setSubmitEnabled(false);
85+
onInputChange(e);
86+
}}
10487
/>
105-
)}
106-
<select
107-
value={childType}
108-
onChange={(e) => onChildTypeChange(e.target.value)}
109-
style={styles.select}
110-
>
111-
<option value="" disabled>
112-
Select child type
113-
</option>
114-
<option value="File">File</option>
115-
<option value="Folder">Folder</option>
116-
</select>
117-
<div style={styles.buttonGroup}>
118-
<button style={styles.cancelBtn} onClick={onCancel}>
119-
{cancelText}
120-
</button>
121-
<button style={styles.confirmBtn} onClick={onConfirm}>
122-
{confirmText}
123-
</button>
12488
</div>
125-
</div>
89+
<div className="section" id="bottommarginneeded">
90+
<label htmlFor="section" className="label_section">
91+
CHILD TYPE :
92+
</label>
93+
<select
94+
name="section"
95+
className="select_section"
96+
value={childType}
97+
onChange={(e) => onChildTypeChange(e.target.value)}
98+
>
99+
<option value="File">File</option>
100+
<option value="Folder">Folder</option>
101+
</select>
102+
</div>
103+
<div id="uploaded-container">
104+
<div>⚠️</div>
105+
<div>The Child Type of the folder indicates whether this new folder will have subfolders or files inside it</div>
106+
</div>
107+
<div className="addfolderbuttoncontainer">
108+
<div className="button cancelbutton addfolderbutton" onClick={onCancel}>
109+
CANCEL
110+
</div>
111+
<div className={`button ${submitEnabled} submitbutton addfolderbutton`} onClick={onConfirm}>
112+
CREATE
113+
</div>
114+
</div>
115+
</Wrapper>
126116
</div>
127117
);
128118
};

client/src/screens/browse/components/folder-info/index.jsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ const FolderInfo = ({
2424
const dispatch = useDispatch();
2525
const [showConfirm, setShowConfirm] = useState(false);
2626
const [newFolderName, setNewFolderName] = useState("");
27-
const [childType, setChildType] = useState("");
28-
27+
const [childType, setChildType] = useState("File");
2928

3029
const handleShare = () => {
3130
const sectionShare = document.getElementById("share");
@@ -34,7 +33,7 @@ const FolderInfo = ({
3433

3534
const handleCreateFolder = () => {
3635
setNewFolderName("");
37-
setChildType("");
36+
setChildType("File");
3837
setShowConfirm(true);
3938
};
4039

@@ -133,8 +132,6 @@ const FolderInfo = ({
133132
onChildTypeChange={setChildType}
134133
onConfirm={handleConfirmCreateFolder}
135134
onCancel={() => setShowConfirm(false)}
136-
confirmText="Create"
137-
cancelText="Cancel"
138135
/>
139136
</>
140137
);

client/src/screens/browse/components/folder-info/styles.scss

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,25 @@
8989
}
9090
}
9191
}
92+
}
93+
94+
.addfolderbuttoncontainer{
95+
display: flex;
96+
gap: 1rem;
97+
}
98+
99+
.addfolderbutton {
100+
flex: 1;
101+
}
102+
103+
.cancelbutton {
104+
background-color: #535353 !important;
105+
}
106+
107+
.submitbutton {
108+
background-color: #FECF6F !important;
109+
}
110+
111+
#bottommarginneeded {
112+
margin-bottom: 2rem;
92113
}

client/src/screens/browse/index.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ const BrowseScreen = () => {
238238
name={folder.name}
239239
subject={folder.course}
240240
folderData={folder}
241+
parentFolder={folderData}
241242
/>
242243
))
243244
)}

server/modules/file/file.controller.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ export const unverifyFile = async (req, res) => {
3434
}
3535
};
3636

37+
//Delete File function for folders
38+
export const deleteFile = async (file) => {
39+
console.log(file.fileId);
40+
await FileModel.findByIdAndDelete(file._id);
41+
await DeleteFile(file.fileId);
42+
}
43+
3744
export const getAllFiles = async (req, res) => {
3845
try {
3946
console.log(req.user);

server/modules/folder/folder.controller.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { FolderModel } from "../course/course.model.js";
2+
import { deleteFile } from "../file/file.controller.js";
23

34
async function createFolder(req, res) {
45
const { name, course, parentFolder, childType } = req.body;
6+
console.log(req.body);
57
const newFolder = await FolderModel.create({
68
name,
79
course,
@@ -18,22 +20,45 @@ async function createFolder(req, res) {
1820
return res.json(newFolder);
1921
}
2022
async function deleteFolder(req, res) {
21-
const { folderId, parentFolderId } = req.query;
23+
const { folder, parentFolderId } = req.query;
24+
const folderId = folder._id;
2225

2326
try {
2427
if (parentFolderId) {
2528
await FolderModel.findByIdAndUpdate(parentFolderId, {
2629
$pull: { children: folderId },
2730
});
2831
}
29-
const deleted = await FolderModel.findByIdAndDelete(folderId);
30-
if (!deleted) {
31-
return res.status(404).json({ message: "Folder not found" });
32-
}
32+
// const deleted = await FolderModel.findByIdAndDelete(folderId);
33+
// if (!deleted) {
34+
// return res.status(404).json({ message: "Folder not found" });
35+
// }
36+
recursiveDelete(folder);
3337

3438
return res.json({ success: true, folderId });
3539
} catch (err) {
3640
return res.status(500).json({ success: false, error: err.message });
3741
}
3842
}
43+
44+
async function recursiveDelete(folder){
45+
if(!folder.children) {
46+
await FolderModel.findByIdAndDelete(folder._id);
47+
return;
48+
}
49+
if (folder.childType === "Folder"){
50+
for(const subfolder of folder.children){
51+
await recursiveDelete(subfolder);
52+
}
53+
await FolderModel.findByIdAndDelete(folder._id);
54+
}
55+
else if(folder.childType === "File"){
56+
for(const file of folder.children){
57+
console.log(file);
58+
await deleteFile(file);
59+
}
60+
await FolderModel.findByIdAndDelete(folder._id);
61+
}
62+
}
63+
3964
export { createFolder, deleteFolder };

0 commit comments

Comments
 (0)