From 002b6cdc68bc7adde64738751c76717dfb2bb932 Mon Sep 17 00:00:00 2001 From: Marc Cataford Date: Wed, 9 Aug 2023 00:52:26 -0400 Subject: [PATCH] feat(frontend): files API stub instead of hardcoded mocks (#3) * build(frontend): node version management * feat: use files API via network instead of hardcoded mock * fix: mock in tests --- Taskfile.yml | 7 +- frontend/.n | 1 + frontend/.nvmrc | 1 - frontend/package.json | 3 +- frontend/script/bootstrap | 2 +- frontend/src/App.tsx | 35 ++++---- frontend/src/components/FileDetails.tsx | 20 +++-- frontend/src/components/FileList.tsx | 4 +- frontend/src/queries/files.ts | 19 ++++ frontend/tests/FileList.test.tsx | 4 +- frontend/yarn.lock | 110 +++++++++++++++++++++++- 11 files changed, 168 insertions(+), 38 deletions(-) create mode 100644 frontend/.n delete mode 100644 frontend/.nvmrc create mode 100644 frontend/src/queries/files.ts diff --git a/Taskfile.yml b/Taskfile.yml index 6e7606e..895bf68 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -49,4 +49,9 @@ tasks: cmds: - yarn start dir: frontend - + fe.test: + desc: "Runs the frontend test suite." + deps: [fe.bootstrap] + cmds: + - yarn test + dir: frontend diff --git a/frontend/.n b/frontend/.n new file mode 100644 index 0000000..fa344f5 --- /dev/null +++ b/frontend/.n @@ -0,0 +1 @@ +hydrogen diff --git a/frontend/.nvmrc b/frontend/.nvmrc deleted file mode 100644 index a77793e..0000000 --- a/frontend/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -lts/hydrogen diff --git a/frontend/package.json b/frontend/package.json index 2db88be..fdf9467 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,8 @@ "@mui/icons-material": "^5.14.1", "@mui/material": "^5.14.2", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-query": "^3.39.3" }, "scripts": { "start": "parcel serve src/index.html --no-cache", diff --git a/frontend/script/bootstrap b/frontend/script/bootstrap index 106c07b..afdddd4 100644 --- a/frontend/script/bootstrap +++ b/frontend/script/bootstrap @@ -1,7 +1,7 @@ #!/bin/bash if [[ $CI != 1 ]]; then - nvm use + n $(cat .n) fi corepack enable && yarn diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ffbc729..6305808 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,25 +1,13 @@ import { Box } from "@mui/material" +import { QueryClient, QueryClientProvider, useQuery } from "react-query" import NavigationBar from "./components/NavigationBar" import FileList from "./components/FileList" import FileDetails from "./components/FileDetails" import AsyncTaskContext from "./contexts/AsyncTaskContext" import LocationContext, { useLocationContext } from "./contexts/LocationContext" +import { useOwnFileList } from "./queries/files" -const mockData = [ - { - title: "Test file", - filename: "testfile.txt", - size: 1023, - uid: "123", - }, - { - title: "Other file", - filename: "testfile2.txt", - size: 535346, - uid: "456", - }, -] const routeLabels = { ITEM_DETAILS: "item-details", } @@ -30,13 +18,16 @@ const routes = { const App = () => { const { location } = useLocationContext() + const { isLoading, data } = useOwnFileList() + + if (isLoading) return return ( - + {location.label === routeLabels.ITEM_DETAILS ? ( @@ -48,12 +39,16 @@ const App = () => { ) } +const queryClient = new QueryClient() + const AppWithContexts = () => ( - - - - - + + + + + + + ) export default AppWithContexts diff --git a/frontend/src/components/FileDetails.tsx b/frontend/src/components/FileDetails.tsx index 68a145d..52cfbaf 100644 --- a/frontend/src/components/FileDetails.tsx +++ b/frontend/src/components/FileDetails.tsx @@ -7,17 +7,17 @@ import MuiDeleteIcon from "@mui/icons-material/Delete" import MuiDownloadIcon from "@mui/icons-material/Download" import MuiIconButton from "@mui/material/IconButton" +import { useFileDetails } from "../queries/files" + interface FileDetailsProps { itemId: string } -// TODO: API data. -const mockData = { - title: "My File", - size: 123123123, -} - function FileDetails({ itemId }: FileDetailsProps) { + const { isLoading, data } = useFileDetails(itemId) + + if (isLoading) return null + const handleDownloadClick = () => { console.log("download click") } @@ -26,6 +26,8 @@ function FileDetails({ itemId }: FileDetailsProps) { console.log("delete click") } + const currentFileDetails = data + return ( - {mockData.title} + {currentFileDetails.title ?? currentFileDetails.filename} + + + {byteSizeToUnits(currentFileDetails.size)} - {byteSizeToUnits(mockData.size)} <> diff --git a/frontend/src/components/FileList.tsx b/frontend/src/components/FileList.tsx index 3d7e82c..e8bcbbc 100644 --- a/frontend/src/components/FileList.tsx +++ b/frontend/src/components/FileList.tsx @@ -23,7 +23,7 @@ interface FileListItemData { /* Size of the file in bytes. */ size: number /* Unique identifier */ - uid: string + id: string } interface FileListProps { @@ -110,7 +110,7 @@ function FileList({ data }: FileListProps) { size={itemData.size} filename={itemData.filename} onClickHandler={() => - onClickHandler("uid" in itemData ? itemData.uid : "") + onClickHandler("id" in itemData ? itemData.id : "") } onDownloadHandler={onDownloadHandler} onDeleteHandler={onDeleteHandler} diff --git a/frontend/src/queries/files.ts b/frontend/src/queries/files.ts new file mode 100644 index 0000000..7793d9e --- /dev/null +++ b/frontend/src/queries/files.ts @@ -0,0 +1,19 @@ +import { useQuery } from "react-query" + +function useOwnFileList() { + return useQuery("file-list", async () => { + const response = await fetch("http://localhost:8000/files/") + + return response.json() + }) +} + +function useFileDetails(fileId: string) { + return useQuery(`file-details-${fileId}`, async () => { + const response = await fetch(`http://localhost:8000/files/${fileId}/`) + + return response.json() + }) +} + +export { useOwnFileList, useFileDetails } diff --git a/frontend/tests/FileList.test.tsx b/frontend/tests/FileList.test.tsx index bd8e270..01a3982 100644 --- a/frontend/tests/FileList.test.tsx +++ b/frontend/tests/FileList.test.tsx @@ -5,8 +5,8 @@ import FileList from "../src/components/FileList" describe("FileList", () => { const mockItems = [ - { title: "Item 1", filename: "item1.txt", size: 1, uid: "123" }, - { title: "Item 2", filename: "item2.txt", size: 1, uid: "456" }, + { title: "Item 1", filename: "item1.txt", size: 1, id: "123" }, + { title: "Item 2", filename: "item2.txt", size: 1, id: "456" }, ] const mockAsyncTasks = [ diff --git a/frontend/yarn.lock b/frontend/yarn.lock index d8095c0..07a76e6 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -362,7 +362,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.7": version: 7.22.6 resolution: "@babel/runtime@npm:7.22.6" dependencies: @@ -2734,6 +2734,13 @@ __metadata: languageName: node linkType: hard +"big-integer@npm:^1.6.16": + version: 1.6.51 + resolution: "big-integer@npm:1.6.51" + checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518 + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -2769,6 +2776,22 @@ __metadata: languageName: node linkType: hard +"broadcast-channel@npm:^3.4.1": + version: 3.7.0 + resolution: "broadcast-channel@npm:3.7.0" + dependencies: + "@babel/runtime": ^7.7.2 + detect-node: ^2.1.0 + js-sha3: 0.8.0 + microseconds: 0.2.0 + nano-time: 1.0.0 + oblivious-set: 1.0.0 + rimraf: 3.0.2 + unload: 2.2.0 + checksum: 803794c48dcce7f03aca69797430bd8b1c4cfd70b7de22079cd89567eeffaa126a1db98c7c2d86af8131d9bb41ed367c0fef96dfb446151c927b831572c621fc + languageName: node + linkType: hard + "browserslist@npm:^4.21.9, browserslist@npm:^4.6.6": version: 4.21.10 resolution: "browserslist@npm:4.21.10" @@ -3280,6 +3303,13 @@ __metadata: languageName: node linkType: hard +"detect-node@npm:^2.0.4, detect-node@npm:^2.1.0": + version: 2.1.0 + resolution: "detect-node@npm:2.1.0" + checksum: 832184ec458353e41533ac9c622f16c19f7c02d8b10c303dfd3a756f56be93e903616c0bb2d4226183c9351c15fc0b3dba41a17a2308262afabcfa3776e6ae6e + languageName: node + linkType: hard + "diff-sequences@npm:^29.4.3": version: 29.4.3 resolution: "diff-sequences@npm:29.4.3" @@ -4868,6 +4898,13 @@ __metadata: languageName: node linkType: hard +"js-sha3@npm:0.8.0": + version: 0.8.0 + resolution: "js-sha3@npm:0.8.0" + checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce + languageName: node + linkType: hard + "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -5224,6 +5261,16 @@ __metadata: languageName: node linkType: hard +"match-sorter@npm:^6.0.2": + version: 6.3.1 + resolution: "match-sorter@npm:6.3.1" + dependencies: + "@babel/runtime": ^7.12.5 + remove-accents: 0.4.2 + checksum: a4b02b676ac4ce64a89a091539ee4a70a802684713bcf06f2b70787927f510fe8a2adc849f9288857a90906083ad303467e530e8723b4a9756df9994fc164550 + languageName: node + linkType: hard + "mdn-data@npm:2.0.14": version: 2.0.14 resolution: "mdn-data@npm:2.0.14" @@ -5248,6 +5295,13 @@ __metadata: languageName: node linkType: hard +"microseconds@npm:0.2.0": + version: 0.2.0 + resolution: "microseconds@npm:0.2.0" + checksum: 22bfa8553f92c7d95afff6de0aeb2aecf750680d41b8c72b02098ccc5bbbb0a384380ff539292dbd3788f5dfc298682f9d38a2b4c101f5ee2c9471d53934c5fa + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -5451,6 +5505,15 @@ __metadata: languageName: node linkType: hard +"nano-time@npm:1.0.0": + version: 1.0.0 + resolution: "nano-time@npm:1.0.0" + dependencies: + big-integer: ^1.6.16 + checksum: eef8548546cc1020625f8e44751a7263e9eddf0412a6a1a6c80a8d2be2ea7973622804a977cdfe796807b85b20ff6c8ba340e8dd20effcc7078193ed5edbb5d4 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -5645,6 +5708,13 @@ __metadata: languageName: node linkType: hard +"oblivious-set@npm:1.0.0": + version: 1.0.0 + resolution: "oblivious-set@npm:1.0.0" + checksum: f31740ea9c3a8242ad2324e4ebb9a35359fbc2e6e7131731a0fc1c8b7b1238eb07e4c8c631a38535243a7b8e3042b7e89f7dc2a95d2989afd6f80bd5793b0aab + languageName: node + linkType: hard + "once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -6014,6 +6084,24 @@ __metadata: languageName: node linkType: hard +"react-query@npm:^3.39.3": + version: 3.39.3 + resolution: "react-query@npm:3.39.3" + dependencies: + "@babel/runtime": ^7.5.5 + broadcast-channel: ^3.4.1 + match-sorter: ^6.0.2 + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + checksum: d2de6a0992dbf039ff2de564de1ae6361f8ac7310159dae42ec16f833b79c05caedced187235c42373ac331cc5f2fe9e2b31b14ae75a815e86d86e30ca9887ad + languageName: node + linkType: hard + "react-refresh@npm:^0.9.0": version: 0.9.0 resolution: "react-refresh@npm:0.9.0" @@ -6074,6 +6162,13 @@ __metadata: languageName: node linkType: hard +"remove-accents@npm:0.4.2": + version: 0.4.2 + resolution: "remove-accents@npm:0.4.2" + checksum: 84a6988555dea24115e2d1954db99509588d43fe55a1590f0b5894802776f7b488b3151c37ceb9e4f4b646f26b80b7325dcea2fae58bc3865df146e1fa606711 + languageName: node + linkType: hard + "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -6151,7 +6246,7 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^3.0.2": +"rimraf@npm:3.0.2, rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" dependencies: @@ -6212,6 +6307,7 @@ __metadata: process: ^0.11.10 react: ^18.2.0 react-dom: ^18.2.0 + react-query: ^3.39.3 rome: ^12.1.3 ts-jest: ^29.1.1 typescript: ^5.1.6 @@ -6766,6 +6862,16 @@ __metadata: languageName: node linkType: hard +"unload@npm:2.2.0": + version: 2.2.0 + resolution: "unload@npm:2.2.0" + dependencies: + "@babel/runtime": ^7.6.2 + detect-node: ^2.0.4 + checksum: 88ba950c5ff83ab4f9bbd8f63bbf19ba09687ed3c434efd43b7338cc595bc574df8f9b155ee6eee7a435de3d3a4a226726988428977a68ba4907045f1fac5d41 + languageName: node + linkType: hard + "update-browserslist-db@npm:^1.0.11": version: 1.0.11 resolution: "update-browserslist-db@npm:1.0.11"