Skip to content

Commit

Permalink
wip: Make Dataset entity selector more modulare
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobiClark committed Dec 12, 2024
1 parent 34bb587 commit 0871146
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
import { useHover } from "@mantine/hooks";
import {
IconFolder,
IconFolderFilled,
IconFolderOpen,
IconFile,
IconFileTypeCsv,
Expand Down Expand Up @@ -69,27 +68,12 @@ const getFileTypeIcon = (fileName) => {
return FILE_ICON_MAP[extension] || <IconFile size={ICON_SETTINGS.fileSize} />;
};

const FileItem = ({ name, content, onFileClick, getEntityForRelativePath }) => {
const datasetEntityObj = useGlobalStore((state) => state.datasetEntityObj);
console.log("datasetEntityObj", datasetEntityObj);
const entityType = useGlobalStore((state) => state.entityType);
const activeEntity = useGlobalStore((state) => state.activeEntity);

const filesEntity = getEntityForRelativePath
? getEntityForRelativePath(datasetEntityObj, entityType, content.relativePath)
: null;

const FileItem = ({ name, content, onFileClick, isFileSelected }) => {
return (
<Group
gap="sm"
justify="flex-start"
bg={
!filesEntity
? "transparent"
: filesEntity === activeEntity
? "rgb(227, 242, 253)"
: "lightgray"
}
bg={isFileSelected(content) ? "#e3f2fd" : "transparent"}
onClick={() => onFileClick && onFileClick(name, content)}
onContextMenu={(e) => {
e.preventDefault();
Expand All @@ -108,15 +92,10 @@ const FolderItem = ({
content,
onFolderClick,
onFileClick,
getEntityForRelativePath,
datasetStructureSearchFilter,
isFolderSelected,
isFileSelected,
}) => {
const { datasetEntityObj, entityType, activeEntity } = useGlobalStore.getState();

const foldersEntity = getEntityForRelativePath
? getEntityForRelativePath(datasetEntityObj, entityType, content.relativePath)
: null;

const [isOpen, setIsOpen] = useState(false);
const { hovered, ref } = useHover();

Expand All @@ -138,7 +117,7 @@ const FolderItem = ({

const folderHasFiles = Object.keys(content.files || {}).length > 0;

const isViewOnly = !onFileClick || !onFolderClick || !getEntityForRelativePath;
const isViewOnly = !onFileClick || !onFolderClick;

return (
<Stack gap={1} ml="xs">
Expand All @@ -160,27 +139,38 @@ const FolderItem = ({
<Tooltip label="Select this folder and ALL contents" zIndex={2999}>
<Checkbox
readOnly
onClick={() => onFolderClick(name, content, "folder-recursive-select")}
checked={foldersEntity}
color={foldersEntity === activeEntity ? "blue" : "gray"}
checked={isFolderSelected(name, content)}
onClick={() => onFolderClick(name, content, isFolderSelected(name, content))}
/>
</Tooltip>
)}
<Text size="md" px={5} onClick={toggleFolder}>
{name}
</Text>
<Space w="lg" />
{!isViewOnly && (
<>
{folderHasFiles && (
<Tooltip label="Select all files in this folder" zIndex={2999}>
<IconFileDownload
size={20}
onClick={() => onFolderClick(name, content, "folder-files-select")}
/>
</Tooltip>
)}
</>
{!isViewOnly && folderHasFiles && (
<Tooltip label="Select all files in this folder" zIndex={2999}>
<IconFileDownload
size={20}
onClick={() => {
// Trigger the `onFileClick` callback for all files in the folder
const allFilesAreSelected = Object.keys(content.files).every((fileName) =>
isFileSelected(content.files[fileName])
);
if (allFilesAreSelected) {
Object.keys(content.files).forEach((fileName) =>
onFileClick(fileName, content.files[fileName])
);
} else {
Object.keys(content.files).forEach(
(fileName) =>
!isFileSelected(content.files[fileName]) &&
onFileClick(fileName, content.files[fileName])
);
}
}}
/>
</Tooltip>
)}
</Group>
<Collapse in={isOpen}>
Expand All @@ -192,7 +182,7 @@ const FolderItem = ({
name={fileName}
content={content.files[fileName]}
onFileClick={onFileClick}
getEntityForRelativePath={getEntityForRelativePath}
isFileSelected={isFileSelected}
/>
))}
{naturalSort(Object.keys(content?.folders || {})).map((folderName) => (
Expand All @@ -202,8 +192,9 @@ const FolderItem = ({
content={content.folders[folderName]}
onFolderClick={onFolderClick}
onFileClick={onFileClick}
getEntityForRelativePath={getEntityForRelativePath}
datasetStructureSearchFilter={datasetStructureSearchFilter}
isFolderSelected={isFolderSelected}
isFileSelected={isFileSelected}
/>
))}
</>
Expand All @@ -213,7 +204,7 @@ const FolderItem = ({
);
};

const DatasetTreeViewRenderer = ({ onFolderClick, onFileClick, getEntityForRelativePath }) => {
const DatasetTreeViewRenderer = ({ folderActions, fileActions }) => {
const { renderDatasetStructureJSONObj, datasetStructureSearchFilter } = useGlobalStore(
(state) => ({
renderDatasetStructureJSONObj: state.renderDatasetStructureJSONObj,
Expand Down Expand Up @@ -259,8 +250,8 @@ const DatasetTreeViewRenderer = ({ onFolderClick, onFileClick, getEntityForRelat
key={fileName}
name={fileName}
content={renderDatasetStructureJSONObj.files[fileName]}
onFileClick={onFileClick}
getEntityForRelativePath={getEntityForRelativePath}
onFileClick={fileActions?.["on-file-click"]}
isFileSelected={fileActions?.["is-file-selected"]}
/>
)
)}
Expand All @@ -270,10 +261,11 @@ const DatasetTreeViewRenderer = ({ onFolderClick, onFileClick, getEntityForRelat
key={folderName}
name={folderName}
content={renderDatasetStructureJSONObj.folders[folderName]}
onFolderClick={onFolderClick}
onFileClick={onFileClick}
getEntityForRelativePath={getEntityForRelativePath}
onFolderClick={folderActions?.["on-folder-click"]}
onFileClick={fileActions?.["on-file-click"]}
datasetStructureSearchFilter={datasetStructureSearchFilter}
isFolderSelected={folderActions?.["is-folder-selected"]}
isFileSelected={fileActions?.["is-file-selected"]}
/>
)
)}
Expand Down
129 changes: 54 additions & 75 deletions src/renderer/src/components/shared/manifest/DatasetEntitySelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,7 @@ import {
} from "../../../stores/slices/datasetEntitySelectorSlice";
import { setDatasetStructureSearchFilter } from "../../../stores/slices/datasetTreeViewSlice";

const useDatasetEntityStore = () => {
return useGlobalStore((state) => ({
entityList: state.entityList,
activeEntity: state.activeEntity,
entityType: state.entityType,
datasetEntityObj: state.datasetEntityObj,
}));
};
const ENTITY_PREFIXES = ["sub-", "sam-", "perf-"];

const handleEntityClick = (entity) => setActiveEntity(entity);

Expand All @@ -30,13 +23,15 @@ const handleFileClick = (entityType, activeEntity, datasetEntityObj, fileContent
);
};

const recursiveFolderAction = (
folderContents,
const handleFolderClick = (
entityType,
activeEntity,
datasetEntityObj,
action
folderContents,
folderWasSelectedBeforeClick
) => {
const action = folderWasSelectedBeforeClick ? "remove" : "add";

modifyDatasetEntityForRelativeFilePath(
entityType,
activeEntity,
Expand All @@ -49,67 +44,28 @@ const recursiveFolderAction = (
});

Object.values(folderContents.folders).forEach((subFolder) => {
recursiveFolderAction(subFolder, entityType, activeEntity, datasetEntityObj, action);
});
};

const handleFolderClick = (
entityType,
activeEntity,
datasetEntityObj,
folderContents,
folderClickAction
) => {
if (folderClickAction === "folder-files-select") {
const fileEntities = Object.keys(folderContents.files)
.map((file) => folderContents.files[file].relativePath)
.filter((fileEntity) => {
const entity = getEntityForRelativePath(datasetEntityObj, entityType, fileEntity);
return !entity || entity === activeEntity;
});

const allFilesClaimed = fileEntities.every((fileEntity) => {
const entity = getEntityForRelativePath(datasetEntityObj, entityType, fileEntity);
return entity === activeEntity;
});

fileEntities.forEach((fileEntity) => {
modifyDatasetEntityForRelativeFilePath(
entityType,
activeEntity,
fileEntity,
allFilesClaimed ? "remove" : "add"
);
});
}

if (folderClickAction === "folder-recursive-select") {
const clickedFoldersEntity = getEntityForRelativePath(
datasetEntityObj,
entityType,
folderContents.relativePath
);
recursiveFolderAction(
folderContents,
handleFolderClick(
entityType,
activeEntity,
datasetEntityObj,
clickedFoldersEntity === activeEntity ? "remove" : "add"
subFolder,
folderWasSelectedBeforeClick
);
}
});
};

const renderEntityList = (entityType, activeEntity, datasetEntityObj) => {
if (!datasetEntityObj?.[entityType]) {
return null;
}
if (!datasetEntityObj?.[entityType]) return null;

return Object.keys(datasetEntityObj[entityType]).map((entity) => {
const entityItemsCount = datasetEntityObj[entityType][entity].length || 0;
console.log("entity", entity);
console.log("activeEntity", activeEntity);
const isActive = entity === activeEntity;
console.log("isActive", isActive);

// Show the search icon for sub-, sam-, and perf- entities
const showSearchIcon = ["sub-", "sam-", "perf-"].some((prefix) => entity.startsWith(prefix));
// Check if search icon should be shown for specific entities
const showSearchIcon = ENTITY_PREFIXES.some((prefix) => entity.startsWith(prefix));

return (
<Box
Expand Down Expand Up @@ -156,7 +112,12 @@ const renderEntityList = (entityType, activeEntity, datasetEntityObj) => {
};

const DatasetEntitySelector = () => {
const { entityType, activeEntity, datasetEntityObj } = useDatasetEntityStore();
const { entityList, activeEntity, entityType, datasetEntityObj } = useGlobalStore((state) => ({
entityList: state.entityList,
activeEntity: state.activeEntity,
entityType: state.entityType,
datasetEntityObj: state.datasetEntityObj,
}));

return (
<FullWidthContainer>
Expand All @@ -169,7 +130,7 @@ const DatasetEntitySelector = () => {
</Text>
</Group>
<Divider my="xs" />
<Box style={{ maxHeight: "70vh", overflowY: "auto" }}>
<Box sx={{ maxHeight: "70vh", overflowY: "auto" }}>
{renderEntityList(entityType, activeEntity, datasetEntityObj)}
</Box>
</Paper>
Expand All @@ -179,19 +140,37 @@ const DatasetEntitySelector = () => {
{activeEntity ? (
<Paper shadow="sm" radius="md">
<DatasetTreeViewRenderer
onFolderClick={(folderName, folderContents, folderClickAction) =>
handleFolderClick(
entityType,
activeEntity,
datasetEntityObj,
folderContents,
folderClickAction
)
}
onFileClick={(fileName, fileContents) =>
handleFileClick(entityType, activeEntity, datasetEntityObj, fileContents)
}
getEntityForRelativePath={getEntityForRelativePath}
folderActions={{
"on-folder-click": (folderName, folderContents, folderIsSelected) =>
handleFolderClick(
entityType,
activeEntity,
datasetEntityObj,
folderContents,
folderIsSelected
),
"is-folder-selected": (folderName, folderContents) => {
const entity = getEntityForRelativePath(
datasetEntityObj,
entityType,
folderContents.relativePath
);
return entity === activeEntity;
},
}}
fileActions={{
"on-file-click": (fileName, fileContents) =>
handleFileClick(entityType, activeEntity, datasetEntityObj, fileContents),
"is-file-selected": (fileContents) => {
console.log("Determining if file is selected", fileContents);
const entity = getEntityForRelativePath(
datasetEntityObj,
entityType,
fileContents.relativePath
);
return entity === activeEntity;
},
}}
/>
</Paper>
) : (
Expand Down

0 comments on commit 0871146

Please sign in to comment.