Skip to content

Commit

Permalink
fix(select-all): disable select all for empty folder
Browse files Browse the repository at this point in the history
  • Loading branch information
Saifullah-dev committed Dec 29, 2024
1 parent 8450ee0 commit 8cc9ce0
Show file tree
Hide file tree
Showing 9 changed files with 36 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ type File = {
| `fileUploadConfig` | { url: string; headers?: { [key: string]: string } } | Configuration object for file uploads. It includes the upload URL (`url`) and an optional `headers` object for setting custom HTTP headers in the upload request. The `headers` object can accept any standard or custom headers required by the server. Example: `{ url: "https://example.com/fileupload", headers: { Authorization: "Bearer" + TOKEN, "X-Custom-Header": "value" } }` |
| `files` | Array<[File](#-file-structure)> | An array of file and folder objects representing the current directory structure. Each object includes `name`, `isDirectory`, and `path` properties. |
| `height` | string \| number | The height of the component `default: 600px`. Can be a string (e.g., `'100%'`, `'10rem'`) or a number (in pixels). |
| `initialPath` | string | The path of the directory to be loaded initially.This path should be a path of a folder which is included in `files` array. |
| `initialPath` | string | The path of the directory to be loaded initially e.g. `/Documents`. This should be the path of a folder which is included in `files` array. Default value is `""` |
| `isLoading` | boolean | A boolean state indicating whether the application is currently performing an operation, such as creating, renaming, or deleting a file/folder. Displays a loading state if set `true`. |
| `layout` | "list" \| "grid" | Specifies the default layout style for the file manager. Can be either "list" or "grid". Default value is "grid". |
| `maxFileSize` | number | For limiting the maximum upload file size in bytes. |
Expand Down
2 changes: 2 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VITE_API_BASE_URL=http://localhost:3000/api/file-system
VITE_API_FILES_BASE_URL=http://localhost:3000
1 change: 1 addition & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ type File = {
| `fileUploadConfig` | { url: string; headers?: { [key: string]: string } } | Configuration object for file uploads. It includes the upload URL (`url`) and an optional `headers` object for setting custom HTTP headers in the upload request. The `headers` object can accept any standard or custom headers required by the server. Example: `{ url: "https://example.com/fileupload", headers: { Authorization: "Bearer" + TOKEN, "X-Custom-Header": "value" } }` |
| `files` | Array<[File](#-file-structure)> | An array of file and folder objects representing the current directory structure. Each object includes `name`, `isDirectory`, and `path` properties. |
| `height` | string \| number | The height of the component `default: 600px`. Can be a string (e.g., `'100%'`, `'10rem'`) or a number (in pixels). |
| `initialPath` | string | The path of the directory to be loaded initially e.g. `/Documents`. This should be the path of a folder which is included in `files` array. Default value is `""` |
| `isLoading` | boolean | A boolean state indicating whether the application is currently performing an operation, such as creating, renaming, or deleting a file/folder. Displays a loading state if set `true`. |
| `layout` | "list" \| "grid" | Specifies the default layout style for the file manager. Can be either "list" or "grid". Default value is "grid". |
| `maxFileSize` | number | For limiting the maximum upload file size in bytes. |
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/FileManager/FileList/FilesHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const FilesHeader = ({ unselectFiles }) => {
const { currentPathFiles } = useFileNavigation();

const allFilesSelected = useMemo(() => {
return selectedFiles.length === currentPathFiles.length;
return currentPathFiles.length > 0 && selectedFiles.length === currentPathFiles.length;
}, [selectedFiles, currentPathFiles]);

const handleSelectAll = (e) => {
Expand All @@ -30,7 +30,7 @@ const FilesHeader = ({ unselectFiles }) => {
>
<div className="file-select-all">
{(showSelectAll || allFilesSelected) && (
<Checkbox checked={allFilesSelected} onChange={handleSelectAll} title="Select all" />
<Checkbox checked={allFilesSelected} onChange={handleSelectAll} title="Select all" disabled={currentPathFiles.length === 0} />
)}
</div>
<div className="file-name">Name</div>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/Checkbox/Checkbox.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "./Checkbox.scss";

const Checkbox = ({ name, id, checked, onClick, onChange, className = "", title }) => {
const Checkbox = ({ name, id, checked, onClick, onChange, className = "", title, disabled = false }) => {
return (
<input
className={`fm-checkbox ${className}`}
Expand All @@ -11,6 +11,7 @@ const Checkbox = ({ name, id, checked, onClick, onChange, className = "", title
onClick={onClick}
onChange={onChange}
title={title}
disabled={disabled}
/>
);
};
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/Checkbox/Checkbox.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
.fm-checkbox {
accent-color: white;

&:disabled {
cursor: default !important;
}

&:hover {
cursor: pointer;
}
Expand Down
17 changes: 14 additions & 3 deletions frontend/src/components/ContextMenu/ContextMenu.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { FaChevronRight } from "react-icons/fa6";
import SubMenu from "./SubMenu";
import "./ContextMenu.scss";
Expand All @@ -7,6 +7,9 @@ const ContextMenu = ({ filesViewRef, contextMenuRef, menuItems, visible, clickPo
const [left, setLeft] = useState(0);
const [top, setTop] = useState(0);
const [activeSubMenuIndex, setActiveSubMenuIndex] = useState(null);
const [subMenuPosition, setSubMenuPosition] = useState("right");

const subMenuRef = useRef(null);

const contextMenuPosition = () => {
const { clickX, clickY } = clickPosition;
Expand All @@ -31,9 +34,11 @@ const ContextMenu = ({ filesViewRef, contextMenuRef, menuItems, visible, clickPo

if (right) {
setLeft(`${leftToCursor}px`);
setSubMenuPosition("right");
} else if (left) {
// Location: -width of the context menu from cursor's position i.e. left side
setLeft(`${leftToCursor - menuWidth}px`);
setSubMenuPosition("left");
}

if (top) {
Expand Down Expand Up @@ -80,7 +85,7 @@ const ContextMenu = ({ filesViewRef, contextMenuRef, menuItems, visible, clickPo
.filter((item) => !item.hidden)
.map((item, index) => {
const hasChildren = item.hasOwnProperty("children");
const activeSubMenu = activeSubMenuIndex === index;
const activeSubMenu = activeSubMenuIndex === index && hasChildren;
return (
<div key={item.title}>
<li
Expand All @@ -93,7 +98,13 @@ const ContextMenu = ({ filesViewRef, contextMenuRef, menuItems, visible, clickPo
{hasChildren && (
<>
<FaChevronRight size={14} className="list-expand-icon" />
{activeSubMenu && <SubMenu list={item.children} />}
{activeSubMenu && (
<SubMenu
subMenuRef={subMenuRef}
list={item.children}
position={subMenuPosition}
/>
)}
</>
)}
</li>
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/components/ContextMenu/ContextMenu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@

.sub-menu {
position: absolute;
left: calc(100% - 2px);
top: 0;
background-color: white;
border: 1px solid #c6c6c6;
Expand All @@ -80,6 +79,14 @@
}
}
}

.sub-menu.right {
left: calc(100% - 2px);
}

.sub-menu.left {
left: calc(-83%);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ContextMenu/SubMenu.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { FaCheck } from "react-icons/fa6";

const SubMenu = ({ list }) => {
const SubMenu = ({ subMenuRef, list, position = "right" }) => {
return (
<ul className="sub-menu">
<ul ref={subMenuRef} className={`sub-menu ${position}`}>
{list?.map((item) => (
<li key={item.title} onClick={item.onClick}>
<span className="item-selected">{item.selected && <FaCheck size={13} />}</span>
Expand Down

0 comments on commit 8cc9ce0

Please sign in to comment.