From 4f2ef912564ac4f95722c65f1f11b281fd02c31b Mon Sep 17 00:00:00 2001 From: Kai Arseneau Date: Fri, 22 Nov 2024 12:57:40 -0500 Subject: [PATCH] Added select bin --- .../com/mcmasterbaja/FileFetchResource.java | 15 +++++++++++ .../services/FileSystemStorageService.java | 12 +++++++++ .../mcmasterbaja/services/StorageService.java | 8 ++++++ front-end/src/components/model/Eevee.tsx | 27 +++++-------------- .../src/components/model/ModelViewer.tsx | 17 ++++++++++-- .../src/components/model/modelViewer.css | 1 - front-end/src/lib/apiUtils.ts | 10 +++++++ front-end/src/lib/modelUtils.ts | 10 +++---- 8 files changed, 72 insertions(+), 28 deletions(-) diff --git a/backend/src/main/java/com/mcmasterbaja/FileFetchResource.java b/backend/src/main/java/com/mcmasterbaja/FileFetchResource.java index a63c216b..721b746c 100644 --- a/backend/src/main/java/com/mcmasterbaja/FileFetchResource.java +++ b/backend/src/main/java/com/mcmasterbaja/FileFetchResource.java @@ -106,6 +106,21 @@ public List getInformationForFolder(@PathParam("folderkey") Str return fileInformationList; } + @GET + @jakarta.ws.rs.Path("/listBins") + public List getFolders() { + logger.info("Getting all folders"); + + Path dir = Paths.get("csv"); + + List folderNames = + storageService.loadDirectories(dir) + .map(path -> path.toString().replace("\\", "/")) + .collect(Collectors.toList()); + + return folderNames; + } + @GET @jakarta.ws.rs.Path("/timespan/folder/{folderkey}") public List getTimespan(@PathParam("folderkey") String folderkey) { diff --git a/backend/src/main/java/com/mcmasterbaja/services/FileSystemStorageService.java b/backend/src/main/java/com/mcmasterbaja/services/FileSystemStorageService.java index 03f3b218..dbdbe919 100644 --- a/backend/src/main/java/com/mcmasterbaja/services/FileSystemStorageService.java +++ b/backend/src/main/java/com/mcmasterbaja/services/FileSystemStorageService.java @@ -81,6 +81,18 @@ public Stream loadAll() { return loadAll(rootLocation); } + public Stream loadDirectories(Path dir) { + Path directory = rootLocation.resolve(dir); + try { + return Files.walk(rootLocation.resolve(dir), 1) + .filter(path -> Files.isDirectory(path) && !path.equals(rootLocation.resolve(dir))) + .map(directory::relativize); + } catch (IOException e) { + throw new FileNotFoundException( + "Could not list directories inside directory: " + dir.toString(), e); + } + } + public void delete(Path targetPath) { try { Files.delete(rootLocation.resolve(targetPath)); diff --git a/backend/src/main/java/com/mcmasterbaja/services/StorageService.java b/backend/src/main/java/com/mcmasterbaja/services/StorageService.java index 3b72c96f..8d64b6fb 100644 --- a/backend/src/main/java/com/mcmasterbaja/services/StorageService.java +++ b/backend/src/main/java/com/mcmasterbaja/services/StorageService.java @@ -47,6 +47,14 @@ public interface StorageService { */ Stream loadAll(Path dir); + /** + * Loads all directories in the root location. + * + * @param dir The directory to load directories from. + * @return A Stream of Paths representing the directories. + */ + Stream loadDirectories(Path dir); + /** * Deletes a file. * diff --git a/front-end/src/components/model/Eevee.tsx b/front-end/src/components/model/Eevee.tsx index 2e9588be..f1ece945 100644 --- a/front-end/src/components/model/Eevee.tsx +++ b/front-end/src/components/model/Eevee.tsx @@ -1,10 +1,5 @@ -/* -Auto-generated by: https://github.com/pmndrs/gltfjsx -*/ - import { useRef, useEffect } from 'react'; import { useFrame, useThree } from '@react-three/fiber'; -//import { Quaternion, Euler, Vector3 } from 'three'; import { GridHelper, AxesHelper, BoxHelper } from 'three'; import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'; import * as THREE from 'three'; @@ -19,22 +14,11 @@ export function Eevee({ objRef, onLoad }: EeveeProps) { const { scene } = useThree(); const boxHelperRef = useRef(); + // Execute every frame useFrame(() => { - if (objRef.current) { - // Add a random amount of rotation to the object each frame times delta - // This is so the rotation is smooth and not dependent on the frame rate - //const quaternion = new Quaternion(); - //quaternion.setFromAxisAngle(new Vector3(0, 1, 0), Math.random() * delta); - // meshRef.current.rotation.x += Math.random() * delta; - // meshRef.current.rotation.y += Math.random() * delta; - // meshRef.current.rotation.z += Math.random() * delta; - //meshRef.current.quaternion.multiply(quaternion); - - if (boxHelperRef.current) { - boxHelperRef.current.update(); - } + if (boxHelperRef.current) { + boxHelperRef.current.update(); } - }); // Load the objects into the scene @@ -49,7 +33,6 @@ export function Eevee({ objRef, onLoad }: EeveeProps) { const boxHelper = boxHelperRef.current = new BoxHelper(object, 0xffff00); scene.add(boxHelper); - console.log('Loaded Eevee'); if (onLoad) onLoad(); }); @@ -62,11 +45,15 @@ export function Eevee({ objRef, onLoad }: EeveeProps) { // Cleanup on component unmount return () => { + if (objRef.current) { + scene.remove(objRef.current); + } if (boxHelperRef.current) { scene.remove(boxHelperRef.current); } scene.remove(gridHelper); scene.remove(axesHelper); + }; }, [scene]); diff --git a/front-end/src/components/model/ModelViewer.tsx b/front-end/src/components/model/ModelViewer.tsx index 02e8c621..0b18ecb9 100644 --- a/front-end/src/components/model/ModelViewer.tsx +++ b/front-end/src/components/model/ModelViewer.tsx @@ -6,14 +6,16 @@ import { useRef } from 'react'; import { replayData, fetchData } from '@lib/modelUtils.js'; import './modelViewer.css'; import { quatReplayData } from 'types/ModelTypes.js'; +import { ApiUtil } from '@lib/apiUtils.js'; const ModelViewer = () => { const objRef = useRef(); const [data, setData] = useState([]); - const [objectLoaded, setObjectLoaded] = useState(false); + const [objectLoaded, setObjectLoaded] = useState(false); + const [bins, setBins] = useState([]); useEffect(() => { - fetchData().then(fetchedData => setData(fetchedData)); + ApiUtil.getBins().then(bins => setBins(bins)); }, []); useEffect(() => { @@ -22,8 +24,19 @@ const ModelViewer = () => { replayData(data, objRef.current); }, [data, objectLoaded]); + const handleBinChange = (event: React.ChangeEvent) => { + if (!event.target.value) return; + fetchData(event.target.value).then(setData); + }; + return (
+ diff --git a/front-end/src/components/model/modelViewer.css b/front-end/src/components/model/modelViewer.css index 95361dc0..2b1b1f7e 100644 --- a/front-end/src/components/model/modelViewer.css +++ b/front-end/src/components/model/modelViewer.css @@ -1,6 +1,5 @@ .modelContainer { /* margin: auto auto auto auto; */ - padding-top: 2em; border: 2px; height: 100%; width: 100%; diff --git a/front-end/src/lib/apiUtils.ts b/front-end/src/lib/apiUtils.ts index f19be174..bce51092 100644 --- a/front-end/src/lib/apiUtils.ts +++ b/front-end/src/lib/apiUtils.ts @@ -36,6 +36,16 @@ export const ApiUtil = { return response.json(); }, + /** + * @description Sends a GET request to the server to fetch all bins that have been uploaded. + * @returns {Promise} A promise that resolves to an array of bin names. + */ + getBins: async (): Promise => { + const response = await fetch(`http://${window.location.hostname}:8080/files/listBins`); + if (!response.ok) throw Error(response.statusText); + return response.json(); + }, + /** * @description Sends a GET request to the server to fetch the timespans of a folder. * @param {string} folderKey - The unique identifier of the folder. diff --git a/front-end/src/lib/modelUtils.ts b/front-end/src/lib/modelUtils.ts index 8cc11df7..d9669b27 100644 --- a/front-end/src/lib/modelUtils.ts +++ b/front-end/src/lib/modelUtils.ts @@ -24,13 +24,13 @@ const combineData = (timestamps, x, y, z, w) => { })); }; -export const fetchData = async () => { +export const fetchData = async (bin: string) => { let data: quatReplayData = []; await Promise.all([ - ApiUtil.getFile('data/IMU QUAT W.csv'), - ApiUtil.getFile('data/IMU QUAT X.csv'), - ApiUtil.getFile('data/IMU QUAT Y.csv'), - ApiUtil.getFile('data/IMU QUAT Z.csv') + ApiUtil.getFile(`${bin}/IMU QUAT W.csv`), + ApiUtil.getFile(`${bin}/IMU QUAT X.csv`), + ApiUtil.getFile(`${bin}/IMU QUAT Y.csv`), + ApiUtil.getFile(`${bin}/IMU QUAT Z.csv`) ]).then(([wDataRaw, xDataRaw, yDataRaw, zDataRaw]) => { const wData = parseCSV(wDataRaw); const xData = parseCSV(xDataRaw);