Skip to content

Commit

Permalink
wip: FE usability enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobiClark committed Jan 15, 2025
1 parent d273ec9 commit c75a99c
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 9 deletions.
4 changes: 3 additions & 1 deletion src/renderer/src/components/shared/DataImporter/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ const DataImporter = () => {
// Opens the dataset dialog on click
const handleClick = async (event) => {
event.preventDefault();
window.electron.ipcRenderer.send("open-folders-organize-datasets-dialog");
window.electron.ipcRenderer.send("open-folders-organize-datasets-dialog", {
importRelativePath: "primary/",
});
};

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { Menu } from "@mantine/core";
import { Menu, Group, Text, Divider } from "@mantine/core";
import { useEffect, useCallback } from "react";
import useGlobalStore from "../../../stores/globalStore";
import { closeContextMenu, setFolderMoveMode } from "../../../stores/slices/datasetTreeViewSlice";
import {
deleteFilesByRelativePath,
deleteFoldersByRelativePath,
} from "../../../stores/utils/folderAndFileActions";
import { IconFolder, IconFolderOpen } from "@tabler/icons-react";

const ICON_SETTINGS = {
folderColor: "#ADD8E6",
folderSize: 16,
fileSize: 14,
};

const ContextMenu = () => {
const {
Expand Down Expand Up @@ -57,7 +68,17 @@ const ContextMenu = () => {
<div id="context-menu" style={menuStyles}>
<Menu opened position="top" offset={5} styles={{ dropdown: menuStyles }}>
<Menu.Dropdown>
asdf
<Group position="apart" spacing="sm">
{contextMenuItemType === "folder" ? (
<IconFolder size={ICON_SETTINGS.folderSize} color={ICON_SETTINGS.folderColor} />
) : (
<IconFolderOpen size={ICON_SETTINGS.folderSize} color={ICON_SETTINGS.folderColor} />
)}
<Text fw={500} size="md">
{contextMenuItemName}
</Text>
</Group>
<Divider my={3} />
<Menu.Item
onClick={() => {
setFolderMoveMode(true);
Expand All @@ -69,19 +90,18 @@ const ContextMenu = () => {
<Menu.Item
onClick={() => {
if (contextMenuItemType === "file") {
window.deleteFilesByRelativePath([contextMenuItemData.relativePath]);
deleteFilesByRelativePath([contextMenuItemData.relativePath]);
}
if (contextMenuItemType === "folder") {
window.deleteFoldersByRelativePath([contextMenuItemData.relativePath]);
deleteFoldersByRelativePath([contextMenuItemData.relativePath]);
}
closeContextMenu();
}}
>
Delete
</Menu.Item>
<Menu.Item>qwer</Menu.Item>
{contextMenuItemType === "folder" && (
<Menu.Item onClick={() => console.log("Delete")}>
<Menu.Item onClick={() => console.log("Import data")}>
Import data into {contextMenuItemName}
</Menu.Item>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
setFolderMoveMode,
moveFolderToNewLocation,
} from "../../../stores/slices/datasetTreeViewSlice";
import { moveFoldersToTargetLocation } from "../../../stores/utils/folderAndFileActions";
import { naturalSort } from "../utils/util-functions";

const ICON_SETTINGS = {
Expand Down Expand Up @@ -82,7 +83,7 @@ const FolderItem = ({
isFileSelected,
allowStructureEditing,
}) => {
const { folderMoveModeIsActive } = useGlobalStore();
const { folderMoveModeIsActive, contextMenuItemType, contextMenuItemData } = useGlobalStore();
const [isOpen, setIsOpen] = useState(false);
const { hovered, ref } = useHover();

Expand Down Expand Up @@ -110,6 +111,13 @@ const FolderItem = ({
!content ||
(Object.keys(content.folders).length === 0 && Object.keys(content.files).length === 0);

console.log("content", content);

const folderIsPassThrough = content.folderIsPassThrough === true;
if (folderIsPassThrough) {
console.log("Folder is pass through", name);
}

return (
<Stack gap={1} ml="xs">
<Group ref={ref} gap={3} justify="flex-start" onContextMenu={handleFileContextMenuOpen}>
Expand Down Expand Up @@ -140,8 +148,13 @@ const FolderItem = ({
<Tooltip label="Move data to this folder" zIndex={2999}>
<Checkbox
readOnly
disabled={content.relativePath.includes(contextMenuItemData.relativePath)}
onClick={() => {
moveFolderToNewLocation(content.relativePath);
moveFoldersToTargetLocation(
[contextMenuItemData.relativePath],
content.relativePath
);
setFolderMoveMode(false);
}}
/>
</Tooltip>
Expand Down
12 changes: 12 additions & 0 deletions src/renderer/src/stores/slices/datasetTreeViewSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,25 @@ const filterStructure = (structure, searchFilter) => {
searchFilter
);

// If the folder does not match and is not a pass-through, return null (exclude it)
if (!matchesDirectly && !matchesFilesDirectly && !passThrough) return null;

// If the folder is pass-through, it should still be included in the structure
return produce(folderObj, (draft) => {
// If it's a pass-through, we include it even if it doesn't match directly
if (passThrough) {
console.log("Pass-through folder:", draft.relativePath); // Debug log
draft.folderIsPassThrough = true; // Mark it as pass-through in the JSON
}

// Recursively prune subfolders that don't match
for (const subFolder in draft.folders || {}) {
if (!pruneStructure(draft.folders[subFolder], searchFilter)) {
delete draft.folders[subFolder];
}
}

// Remove files that don't match the filter
for (const fileName in draft.files || {}) {
if (!draft.files[fileName].relativePath.toLowerCase().includes(searchFilter)) {
delete draft.files[fileName];
Expand All @@ -76,6 +87,7 @@ const filterStructure = (structure, searchFilter) => {
});
};

// Start the filtering process
return pruneStructure(structure, searchFilter.toLowerCase());
};

Expand Down
97 changes: 97 additions & 0 deletions src/renderer/src/stores/utils/folderAndFileActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import useGlobalStore from "../globalStore";
import { setTreeViewDatasetStructure } from "../slices/datasetTreeViewSlice";
import { setFolderMoveMode } from "../slices/datasetTreeViewSlice";

const getNestedObjectAtPathArray = (pathArray) => {
// Traverse the dataset structure to find the object at the given path.
let currentPath = window.datasetStructureJSONObj;
for (const folder of pathArray) {
currentPath = currentPath["folders"][folder];
}
return currentPath;
};

const getItemAtPath = (relativePath, itemType) => {
// Split the relative path into segments and isolate the item name.
const pathSegments = relativePath.split("/").filter((segment) => segment !== "");
const itemName = pathSegments.pop();

// Get the parent folder by traversing the path segments.
const parentFolder = getNestedObjectAtPathArray(pathSegments);

// Retrieve the target item from the parent folder based on its type.
const itemObject =
itemType === "folder" ? parentFolder["folders"][itemName] : parentFolder["files"][itemName];

return { parentFolder, itemName, itemObject };
};

export const deleteFoldersByRelativePath = (arrayOfRelativePaths) => {
for (const relativePathToDelete of arrayOfRelativePaths) {
const { parentFolder, itemName, itemObject } = getItemAtPath(relativePathToDelete, "folder");

if (itemObject?.["type"] === "bf") {
// Mark folders from Pennsieve for deletion instead of directly deleting them.
parentFolder["folders"][itemName]["action"].push("deleted");
} else {
// Directly delete folders not originating from Pennsieve.
delete parentFolder["folders"][itemName];
}
}

// Update the tree view structure to reflect the changes.
setTreeViewDatasetStructure(window.datasetStructureJSONObj);
};

export const deleteFilesByRelativePath = (arrayOfRelativePaths) => {
for (const relativePathToDelete of arrayOfRelativePaths) {
const { parentFolder, itemName, itemObject } = getItemAtPath(relativePathToDelete, "file");

if (itemObject?.["type"] === "bf") {
// Mark files from Pennsieve for deletion instead of directly deleting them.
parentFolder["files"][itemName]["action"].push("deleted");
} else {
// Directly delete files not originating from Pennsieve.
delete parentFolder["files"][itemName];
}
}

// Update the tree view structure to reflect the changes.
setTreeViewDatasetStructure(window.datasetStructureJSONObj);
};

export const moveFoldersToTargetLocation = (
arrayOfRelativePathsToMove,
destionationRelativePath
) => {
console.log("moveFoldersByRelativePath called");
console.log("arrayOfRelativePathsToMove", arrayOfRelativePathsToMove);
console.log("destionationRelativePath", destionationRelativePath);

const {
parentFolder: destinationParentFolder,
itemName: destinationItemName,
itemObject: destinationItemObject,
} = getItemAtPath(destionationRelativePath, "folder");
console.log("destinationParentFolder", destinationParentFolder);
console.log("destinationItemName", destinationItemName);

for (const relativePathToMove of arrayOfRelativePathsToMove) {
const { parentFolder, itemName, itemObject } = getItemAtPath(relativePathToMove, "folder");
console.log("parentFolder", parentFolder);
console.log("itemName", itemName);
console.log("itemObject", itemObject);
// Move the folder to the destination folder.
console.log("destinationItemObject before move", destinationItemObject);
console.log("number of folders", Object.keys(destinationItemObject["folders"]).length);
destinationItemObject["folders"][itemName] = itemObject;
console.log("itemObject after move", destinationItemObject);
console.log("number of folders", Object.keys(destinationItemObject["folders"]).length);

// Remove the folder from its original location.
delete parentFolder["folders"][itemName];
}

// Update the tree view structure to reflect the changes.
setTreeViewDatasetStructure(window.datasetStructureJSONObj);
};

0 comments on commit c75a99c

Please sign in to comment.