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
This commit is contained in:
parent
c541877cf7
commit
002b6cdc68
11 changed files with 168 additions and 38 deletions
|
@ -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
|
||||
|
|
1
frontend/.n
Normal file
1
frontend/.n
Normal file
|
@ -0,0 +1 @@
|
|||
hydrogen
|
|
@ -1 +0,0 @@
|
|||
lts/hydrogen
|
|
@ -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",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [[ $CI != 1 ]]; then
|
||||
nvm use
|
||||
n $(cat .n)
|
||||
fi
|
||||
|
||||
corepack enable && yarn
|
||||
|
|
|
@ -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 (
|
||||
<Box sx={{ display: "flex", flexDirection: "column", width: "100%" }}>
|
||||
<NavigationBar />
|
||||
<Box component="main" sx={{ display: "flex", paddingTop: "10px" }}>
|
||||
<Box component="div" sx={{ flexGrow: 1 }}>
|
||||
<FileList data={mockData} />
|
||||
<FileList data={data} />
|
||||
</Box>
|
||||
{location.label === routeLabels.ITEM_DETAILS ? (
|
||||
<Box component="div" sx={{ flexGrow: 1 }}>
|
||||
|
@ -48,12 +39,16 @@ const App = () => {
|
|||
)
|
||||
}
|
||||
|
||||
const queryClient = new QueryClient()
|
||||
|
||||
const AppWithContexts = () => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AsyncTaskContext>
|
||||
<LocationContext routes={routes}>
|
||||
<App />
|
||||
</LocationContext>
|
||||
</AsyncTaskContext>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
|
||||
export default AppWithContexts
|
||||
|
|
|
@ -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 (
|
||||
<MuiCard sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
|
||||
<MuiBox
|
||||
|
@ -34,9 +36,11 @@ function FileDetails({ itemId }: FileDetailsProps) {
|
|||
>
|
||||
<MuiArticleIcon sx={{ fontSize: 120 }} />
|
||||
<MuiTypography variant="h1" sx={{ fontSize: 30 }}>
|
||||
{mockData.title}
|
||||
{currentFileDetails.title ?? currentFileDetails.filename}
|
||||
</MuiTypography>
|
||||
<MuiTypography>
|
||||
{byteSizeToUnits(currentFileDetails.size)}
|
||||
</MuiTypography>
|
||||
<MuiTypography>{byteSizeToUnits(mockData.size)}</MuiTypography>
|
||||
</MuiBox>
|
||||
<MuiBox sx={{ display: "flex", justifyContent: "center" }}>
|
||||
<>
|
||||
|
|
|
@ -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}
|
||||
|
|
19
frontend/src/queries/files.ts
Normal file
19
frontend/src/queries/files.ts
Normal file
|
@ -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 }
|
|
@ -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 = [
|
||||
|
|
|
@ -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"
|
||||
|
|
Reference in a new issue