Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CourseHub
Submodule CourseHub added at d7ccac
5 changes: 5 additions & 0 deletions client/src/actions/filebrowser_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ export const RemoveFileFromFolder = (fileId) => ({
type: "REMOVE_FILE_FROM_FOLDER",
payload: fileId,
});

export const RefreshCurrentFolder = () => ({
type: "REFRESH_CURRENT_FOLDER",
payload: Date.now(),
});
33 changes: 33 additions & 0 deletions client/src/api/Folder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import axios from "axios";
import serverRoot from "./server";

// Create axios instance with baseURL and withCredentials
const API = axios.create({
baseURL: `${serverRoot}/api`,
withCredentials: true,
});

// Attach token to every request if available (from localStorage)
API.interceptors.request.use((req) => {
const user = JSON.parse(localStorage.getItem("profile"));
if (user) req.headers.Authorization = `Bearer ${user.token}`;
return req;
});

export const createFolder = async ({ name, course, parentFolder,childType }) => {
const { data } = await API.post("/folder/create", {
name,
course,
parentFolder,
childType
});
return data;
};

export const deleteFolder = async ({ folderId, parentFolderId }) => {
const { data } = await API.delete(`/folder/delete`, {
params: { folderId, parentFolderId },
});
return data;
};

6 changes: 6 additions & 0 deletions client/src/reducers/filebrowser_reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ const FileBrowserReducer = (
},
};

case "REFRESH_CURRENT_FOLDER":
return {
...state,
refreshKey: action.payload,
};

default:
return state;
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from "react";
import cross from "./cross.svg";

const styles = {
overlay: {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "rgba(0, 0, 0, 0.4)",
display: "flex",
alignItems: "center",
justifyContent: "center",
zIndex: 1000,
},
dialog: {
backgroundColor: "#fff",
padding: "25px 30px",
borderRadius: "8px",
maxWidth: "400px",
width: "90%",
boxShadow: "0 4px 20px rgba(0, 0, 0, 0.2)",
textAlign: "center",
fontFamily: "sans-serif",
},

iconImage: {
width: "80px",
height: "80px",
margin: "1em",

},
heading: {
fontSize: "2em",
},
message: {
fontSize: "1em",
color: "#374151",
margin: "1em",
},
buttonGroup: {
display: "flex",
justifyContent: "center",
gap: "1em",
},
deleteBtn: {
display: "flex",
alignItems: "center",
backgroundColor: "#ef4444",
color: "#fff",
border: "none",
padding: "10px 18px",
borderRadius: "5px",
cursor: "pointer",
fontWeight: "bold",
fontSize: "1em",
},
cancelBtn: {
backgroundColor: "#9ca3af",
color: "#fff",
border: "none",
padding: "10px 18px",
borderRadius: "5px",
cursor: "pointer",
fontWeight: "bold",
fontSize: "1em",
},
};


const ConfirmDialog = ({ isOpen, onConfirm, onCancel }) => {
if (!isOpen) return null;

return (
<div style={styles.overlay}>
<div style={styles.dialog}>
<img src={cross} alt="Delete" style={styles.iconImage} />
<h3 style={styles.heading}>Are you sure?</h3>
<p style={styles.message}>
Do you want to permanently delete this folder? This action cannot be undone.
</p>
<div style={styles.buttonGroup}>
<button style={styles.cancelBtn} onClick={onCancel}>
Cancel
</button>
<button style={styles.deleteBtn} onClick={onConfirm}>
Delete
</button>
</div>
</div>
</div>
);
};

export { ConfirmDialog };
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 51 additions & 10 deletions client/src/screens/browse/components/browsefolder/index.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
import "./styles.scss";
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { ChangeFolder } from "../../../../actions/filebrowser_actions";
import { deleteFolder } from "../../../../api/Folder";
import { toast } from "react-toastify";
import { RefreshCurrentFolder } from "../../../../actions/filebrowser_actions";
import { ConfirmDialog } from "./confirmDialog";
const BrowseFolder = ({ type = "file", color, path, name, subject, folderData }) => {
const dispatch = useDispatch();
const [showConfirm, setShowConfirm] = useState(false);
const onClick = (folderData) => {
// return;
dispatch(ChangeFolder(folderData));
};

const handleDelete = async (e) => {
try {
await deleteFolder({ folderId: folderData._id, parentFolderId: folderData.parent });
toast.success("Folder deleted successfully!");
dispatch(RefreshCurrentFolder());
} catch (err) {
console.log(err);
toast.error("Failed to delete folder.");
}
setShowConfirm(false);
};

const cancelDelete = () => {
setShowConfirm(false);
};

return (
<div className="browse-folder" onClick={() => onClick(folderData)}>
{/* {type === "folder" ? (
<>
<div className="browse-folder" onClick={() => onClick(folderData)}>
{/* {type === "folder" ? (
<svg
width="200"
height="175"
Expand Down Expand Up @@ -86,16 +110,33 @@ const BrowseFolder = ({ type = "file", color, path, name, subject, folderData })
/>
</svg>
)} */}
<div className="content">
<div className="top">
<p className="path">{""}</p>
<p className="name">{name ? name : "Name"}</p>
</div>
<div className="bottom">
<p className="subject">{subject ? subject.toUpperCase() : "Subject Here"}</p>
<div className="content">
<div className="top">
<p className="path">{""}</p>
<p className="name">{name ? name : "Name"}</p>
<span
className="delete"
onClick={(e) => {
e.stopPropagation();
setShowConfirm(true);
}}
title="Delete folder"
></span>
</div>
<div className="bottom">
<p className="subject">
{subject ? subject.toUpperCase() : "Subject Here"}
</p>
</div>
</div>
</div>
</div>
<ConfirmDialog
isOpen={showConfirm}
type="delete"
onConfirm={handleDelete}
onCancel={cancelDelete}
/>
</>
);
};

Expand Down
47 changes: 32 additions & 15 deletions client/src/screens/browse/components/browsefolder/styles.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.browse-folder{
.browse-folder {
width: 200px;
height: 175px;
margin: 10px;
Expand All @@ -8,45 +8,62 @@
background: url(./folder.svg), none;
background-position: center;
background-repeat: no-repeat;
&:hover{
&:hover {
transform: translateY(-2px);
}

svg{
svg {
position: absolute;
z-index: -1;
}
.content{
.content {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
.top{
.path{
.top {
position: relative;
.delete {
background: url(./Delete.svg), none;
position: absolute;
top: 5px;
right: 5px;
width: 20px;
height: 20px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
opacity: 0;
transition: opacity 0.2s ease-in-out;
z-index: 3;
}
.path {
padding: 30px 50px 0px 15px;
font-size: 0.9rem;
}
.name{
font-family: 'Bold';
.name {
font-family: "Bold";
font-size: 1.2rem;
padding: 0px 50px 0px 15px;
}

}
.bottom{
.top:hover .delete {
opacity: 1;
}
.bottom {
width: 100%;
text-align: right;
display: flex;
justify-content: right;
.subject{
.subject {
width: 85%;
text-align: right;
padding: 0px 15px 20px 0px;
font-family: 'Bold';
font-family: "Bold";
font-size: 1.2rem;
color: rgba(80, 80, 80, 0.5)
color: rgba(80, 80, 80, 0.5);
}
}
}

}
}
Loading
Loading