Skip to content

Commit 23fa6e1

Browse files
committed
Expanding ClowderFileSystem to select Folders as well
1 parent 3b61430 commit 23fa6e1

File tree

3 files changed

+154
-60
lines changed

3 files changed

+154
-60
lines changed

frontend/src/components/listeners/SubmitExtraction.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { RootState } from "../../types/data";
2525
import { EventListenerOut as Extractor } from "../../openapi/v2";
2626
import { ClowderRjsfSelectWidget } from "../styledComponents/ClowderRjsfSelectWidget";
2727
import { ClowderRjsfTextWidget } from "../styledComponents/ClowderRjsfTextWidget";
28-
import { ClowderFileSelector } from "../styledComponents/ClowderFileSelector";
28+
import { ClowderFileSystemSelector } from "../styledComponents/ClowderFileSystemSelector";
2929
import { ClowderImageAnnotator } from "../styledComponents/ClowderImageAnnotator";
3030
import ExtractorStatus from "./ExtractorStatus";
3131
import CloseIcon from "@mui/icons-material/Close";
@@ -43,7 +43,7 @@ type SubmitExtractionProps = {
4343
const widgets = {
4444
TextWidget: ClowderRjsfTextWidget,
4545
SelectWidget: ClowderRjsfSelectWidget,
46-
ClowderFile: ClowderFileSelector,
46+
ClowderFile: ClowderFileSystemSelector,
4747
ImageAnnotator: ClowderImageAnnotator,
4848
};
4949

@@ -270,4 +270,4 @@ export default function SubmitExtraction(props: SubmitExtractionProps) {
270270
</Dialog>
271271
</Container>
272272
);
273-
}
273+
}

frontend/src/components/navigation/FileSelector.tsx renamed to frontend/src/components/navigation/FileSystemSelector.tsx

Lines changed: 146 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,35 @@ import TextIcon from "@mui/icons-material/Description";
2424
import { fetchDatasets } from "../../actions/dataset";
2525
import { V2 } from "../../openapi";
2626

27-
// Define the file details
28-
interface FileDetails {
29-
fileId: string;
30-
fileName: string;
27+
interface SelectionDetails {
28+
selectionID: string;
29+
selectionName: string;
30+
selectionType: string;
31+
datasetId?: string;
3132
}
3233

33-
// Define the RecursiveComponent component with props type
3434
interface RecursiveComponentProps {
3535
item: FSItem;
3636
depth?: number;
37-
onSelectFile: (fileId: string, fileName: string) => void;
37+
onHighlightSelection: (
38+
selectionID: string,
39+
selectionName: string,
40+
datasetId: string,
41+
selectionType: string
42+
) => void;
43+
highlightedSelectionId: string;
44+
selectFolder: boolean;
3845
}
3946

40-
// Define a type for items in the directory structure
4147
interface FSItem {
4248
datasetId: string;
4349
id?: string;
4450
label: string;
4551
children?: FSItem[] | undefined;
46-
type: string; // A FSItem can be a folder or a file,
52+
type: string;
4753
content_type?: string;
4854
}
4955

50-
// Function to fetch children of a folder
5156
async function fetchFolderFiles(
5257
datasetid: string,
5358
folderId: string | undefined
@@ -57,7 +62,6 @@ async function fetchFolderFiles(
5762
await V2.DatasetsService.getDatasetFoldersAndFilesApiV2DatasetsDatasetIdFoldersAndFilesGet(
5863
datasetid,
5964
folderId,
60-
// TODO: Remove hardcoded values
6165
0,
6266
3000
6367
);
@@ -85,13 +89,15 @@ async function fetchFolderFiles(
8589
const RecursiveComponent: React.FC<RecursiveComponentProps> = ({
8690
item,
8791
depth = 0,
88-
onSelectFile,
92+
onHighlightSelection,
93+
highlightedSelectionId,
94+
selectFolder,
8995
}) => {
9096
const [expanded, setExpanded] = useState(false);
9197
const [children, setChildren] = useState<FSItem[] | undefined>(item.children);
9298
const isFolderOrDataset = item.type === "folder" || item.type === "dataset";
99+
const isHighlighted = item.id === highlightedSelectionId;
93100

94-
// Function to generate Icon based on item type
95101
const getIcon = () => {
96102
if (item.type === "folder") {
97103
return <FolderIcon />;
@@ -112,32 +118,35 @@ const RecursiveComponent: React.FC<RecursiveComponentProps> = ({
112118
}
113119
};
114120

115-
// Function to handle selection of folder or file
116-
const onSelect = () => {
121+
const expandFolder = () => {
117122
if (isFolderOrDataset) {
118-
if (!expanded) {
119-
fetchFolderFiles(item.datasetId, item.id).then((data) => {
120-
setChildren(data);
121-
});
122-
}
123+
fetchFolderFiles(item.datasetId, item.id).then((data) => {
124+
setChildren(data);
125+
});
123126
setExpanded(!expanded);
124-
} else {
125-
if (item.id !== undefined) {
126-
onSelectFile(item.id, item.label);
127-
}
127+
}
128+
};
129+
130+
const onSelect = () => {
131+
if (item.id !== undefined) {
132+
onHighlightSelection(item.id, item.label, item.datasetId, item.type);
128133
}
129134
};
130135

131136
return (
132137
<List disablePadding>
133-
{/* Indentation of item proportional to depth */}
134138
<ListItem
135139
sx={{
136140
pl: depth * 2,
137141
borderBottom: "none",
138142
py: 0.5,
143+
backgroundColor: isHighlighted
144+
? "rgba(25, 118, 210, 0.12)"
145+
: "transparent",
139146
"&:hover": {
140-
backgroundColor: "rgba(0, 0, 0, 0.1)", // or any other color
147+
backgroundColor: isHighlighted
148+
? "rgba(25, 118, 210, 0.2)"
149+
: "rgba(0, 0, 0, 0.1)",
141150
cursor: "pointer",
142151
},
143152
}}
@@ -147,6 +156,7 @@ const RecursiveComponent: React.FC<RecursiveComponentProps> = ({
147156
<IconButton
148157
size="small"
149158
sx={{ visibility: isFolderOrDataset ? "visible" : "hidden" }}
159+
onClick={expandFolder}
150160
>
151161
<ExpandMoreIcon
152162
style={{
@@ -166,7 +176,9 @@ const RecursiveComponent: React.FC<RecursiveComponentProps> = ({
166176
key={child.id}
167177
item={child}
168178
depth={depth + 1}
169-
onSelectFile={onSelectFile}
179+
onHighlightSelection={onHighlightSelection}
180+
highlightedSelectionId={highlightedSelectionId}
181+
selectFolder={selectFolder}
170182
/>
171183
))}
172184
</Box>
@@ -177,22 +189,26 @@ const RecursiveComponent: React.FC<RecursiveComponentProps> = ({
177189
};
178190

179191
const FileSystemViewer: React.FC<{
180-
onSelectFile: (fileId: string, fileName: string) => void;
181-
}> = ({ onSelectFile }) => {
192+
onHighlightSelection: (
193+
selectionID: string,
194+
selectionName: string,
195+
datasetId: string,
196+
selectionType: string
197+
) => void;
198+
highlightedSelectionId: string;
199+
selectFolder: boolean;
200+
}> = ({ onHighlightSelection, highlightedSelectionId, selectFolder }) => {
182201
const dispatch = useDispatch();
183202
const datasets = useSelector((state: any) => state.dataset.datasets);
184203
const [FSItems, setFSItems] = useState<FSItem[]>([]);
185204

186-
// API function call to get Datasets
187205
const listDatasets = (skip?: number, limit?: number, mine?: boolean) => {
188206
dispatch(fetchDatasets(skip, limit, mine));
189207
};
190208

191-
// Fetch datasets on component mount
192209
useEffect(() => {
193-
// TODO: Remove hardcoded values for skip and limit
194210
listDatasets(0, 3000, true);
195-
}, []); //
211+
}, []);
196212

197213
useEffect(() => {
198214
if (datasets.data) {
@@ -225,20 +241,33 @@ const FileSystemViewer: React.FC<{
225241
<RecursiveComponent
226242
key={FSItem.id}
227243
item={FSItem}
228-
onSelectFile={onSelectFile}
244+
onHighlightSelection={onHighlightSelection}
245+
highlightedSelectionId={highlightedSelectionId}
246+
selectFolder={selectFolder}
229247
/>
230248
))}
231249
</Box>
232250
) : null;
233251
};
234252

235253
const DatasetFileViewer: React.FC<{
236-
onSelectFile: (fileId: string, fileName: string) => void;
254+
onHighlightSelection: (
255+
selectionID: string,
256+
selectionName: string,
257+
datasetId: string,
258+
selectionType: string
259+
) => void;
260+
highlightedSelectionId: string;
237261
datasetId: string;
238-
}> = ({ onSelectFile, datasetId }) => {
262+
selectFolder: boolean;
263+
}> = ({
264+
onHighlightSelection,
265+
highlightedSelectionId,
266+
datasetId,
267+
selectFolder,
268+
}) => {
239269
const [FSItems, setFSItems] = useState<FSItem[]>([]);
240270

241-
// Only display contents of the passed dataset
242271
useEffect(() => {
243272
fetchFolderFiles(datasetId, undefined).then((data) => {
244273
setFSItems(data);
@@ -263,46 +292,90 @@ const DatasetFileViewer: React.FC<{
263292
<RecursiveComponent
264293
key={FSItem.id}
265294
item={FSItem}
266-
onSelectFile={onSelectFile}
295+
onHighlightSelection={onHighlightSelection}
296+
highlightedSelectionId={highlightedSelectionId}
297+
selectFolder={selectFolder}
267298
/>
268299
))}
269300
</Box>
270301
) : null;
271302
};
272303

273-
const FileSelector: React.FC<{
304+
const FileSystemSelector: React.FC<{
274305
showOnlyDatasetFiles: boolean;
306+
selectFolder: boolean;
275307
datasetId: string | undefined;
276-
onChange: (fileId: string) => void;
277-
}> = ({ showOnlyDatasetFiles, datasetId, onChange }) => {
308+
onChange: (SelectionDetails: string) => void;
309+
}> = ({ showOnlyDatasetFiles, selectFolder, datasetId, onChange }) => {
278310
const [open, setOpen] = useState(false);
279-
const [selectedFile, setSelectedFile] = useState<FileDetails>({
280-
fileId: "",
281-
fileName: "",
311+
const [selection, setSelection] = useState<SelectionDetails>({
312+
selectionID: "",
313+
selectionName: "",
314+
datasetId: "",
315+
selectionType: "",
282316
});
317+
const [highlightedSelection, setHighlightedFile] = useState<SelectionDetails>(
318+
{
319+
selectionID: "",
320+
selectionName: "",
321+
datasetId: "",
322+
selectionType: "",
323+
}
324+
);
283325

284326
const handleOpen = () => setOpen(true);
285-
const handleClose = () => setOpen(false);
327+
const handleClose = () => {
328+
setHighlightedFile({
329+
selectionID: "",
330+
selectionName: "",
331+
selectionType: "",
332+
});
333+
setOpen(false);
334+
};
286335

287-
const handleFileSelect = (fileId: string, fileName: string) => {
288-
setSelectedFile({ fileId: fileId, fileName: fileName });
289-
onChange(fileId);
290-
handleClose();
336+
const handleHighlight = (
337+
selectionID: string,
338+
selectionName: string,
339+
datasetId: string,
340+
selectionType: string
341+
) => {
342+
setHighlightedFile({
343+
selectionID,
344+
selectionName,
345+
datasetId,
346+
selectionType,
347+
});
348+
};
349+
350+
const handleConfirmSelection = () => {
351+
if (highlightedSelection.selectionID) {
352+
setSelection(highlightedSelection);
353+
const selection = {
354+
selectionID: highlightedSelection.selectionID,
355+
selectionName: highlightedSelection.selectionName,
356+
datasetId: highlightedSelection.datasetId,
357+
selectionType: highlightedSelection.selectionType,
358+
}
359+
// Convert to string
360+
const selectionString = JSON.stringify(selection);
361+
onChange(selectionString);
362+
handleClose();
363+
}
291364
};
292365

293366
return (
294367
<Box sx={{ display: "flex", alignItems: "center", gap: 2, p: 2 }}>
295-
{selectedFile.fileName && (
368+
{selection.selectionName && (
296369
<Typography variant="subtitle1" sx={{ ml: 2 }}>
297-
{selectedFile.fileName}
370+
{selection.selectionName}
298371
</Typography>
299372
)}
300373
<Button
301374
variant="outlined"
302375
onClick={handleOpen}
303376
startIcon={<InsertDriveFileIcon />}
304377
>
305-
Choose File
378+
{selectFolder ? "Select Folder" : "Select File"}
306379
</Button>
307380
<Modal
308381
open={open}
@@ -324,16 +397,35 @@ const FileSelector: React.FC<{
324397
>
325398
{showOnlyDatasetFiles ? (
326399
<DatasetFileViewer
327-
onSelectFile={handleFileSelect}
400+
onHighlightSelection={handleHighlight}
401+
highlightedSelectionId={highlightedSelection.selectionID}
328402
datasetId={datasetId as string}
403+
selectFolder={selectFolder}
329404
/>
330405
) : (
331-
<FileSystemViewer onSelectFile={handleFileSelect} />
406+
<FileSystemViewer
407+
onHighlightSelection={handleHighlight}
408+
highlightedSelectionId={highlightedSelection.selectionID}
409+
selectFolder={selectFolder}
410+
/>
332411
)}
412+
<Box sx={{ display: "flex", justifyContent: "flex-end", mt: 2 }}>
413+
<Button
414+
variant="contained"
415+
onClick={handleConfirmSelection}
416+
disabled={
417+
selectFolder
418+
? highlightedSelection.selectionType !== "folder"
419+
: highlightedSelection.selectionType !== "file"
420+
}
421+
>
422+
Select
423+
</Button>
424+
</Box>
333425
</Box>
334426
</Modal>
335427
</Box>
336428
);
337429
};
338430

339-
export default FileSelector;
431+
export default FileSystemSelector;

0 commit comments

Comments
 (0)