Development (#67)
* preliminary map for vehicles * weird zoom bug * passing react tests * fixing warnings and updating snapshots * update node environment to 14 * addressing comments by changing variable types and adding styles to home page title * adding CODEOWNERS file * fixing token error
This commit is contained in:
BIN
src/assets/green-car.png
Normal file
BIN
src/assets/green-car.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 676 B |
BIN
src/assets/red-car.png
Normal file
BIN
src/assets/red-car.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 648 B |
@@ -6,7 +6,7 @@ jest.mock("../Contexts/ManifestsContext");
|
||||
jest.mock("../Contexts/CarUpdatesContext");
|
||||
jest.mock("../../services/monitoring");
|
||||
|
||||
import { render, screen, cleanup, waitForElementToBeRemoved } from "@testing-library/react";
|
||||
import { render, screen, cleanup, waitFor, waitForElementToBeRemoved } from "@testing-library/react";
|
||||
import { setToken } from "../Contexts/UserContext";
|
||||
import { TEST_AUTH_OBJECT } from "../../utils/testing"
|
||||
import App from ".";
|
||||
@@ -28,6 +28,13 @@ const check = async (path, selector, compare) => {
|
||||
expect(container).toMatchSnapshot();
|
||||
};
|
||||
|
||||
const sleepAndCheck = async (path, selector, compare) => {
|
||||
const container = await renderRoute(path);
|
||||
await waitFor(() => { });
|
||||
expect(container.querySelector(selector).innerHTML).toEqual(compare);
|
||||
expect(container).toMatchSnapshot();
|
||||
};
|
||||
|
||||
describe("App", () => {
|
||||
beforeAll(() => {
|
||||
// Stablize Table Pagination control ids
|
||||
@@ -107,12 +114,12 @@ describe("App", () => {
|
||||
|
||||
it("Route / authenticated", async () => {
|
||||
setToken(TEST_AUTH_OBJECT);
|
||||
await check("/", "h1", "Welcome John!");
|
||||
await sleepAndCheck("/", "h1", "Welcome John!");
|
||||
});
|
||||
|
||||
it("Route /home authenticated", async () => {
|
||||
setToken(TEST_AUTH_OBJECT);
|
||||
await check("/home", "h1", "Welcome John!");
|
||||
await sleepAndCheck("/home", "h1", "Welcome John!");
|
||||
});
|
||||
|
||||
it("Route /package-upload authenticated", async () => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -150,8 +150,8 @@ const MainForm = () => {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
}}
|
||||
onChangePage={handleChangePageIndex}
|
||||
onChangeRowsPerPage={handleChangePageSize}
|
||||
onPageChange={handleChangePageIndex}
|
||||
onRowsPerPageChange={handleChangePageSize}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
||||
@@ -176,8 +176,8 @@ const CarSelectionTable = (props) => {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
}}
|
||||
onChangePage={handleChangePageIndex}
|
||||
onChangeRowsPerPage={handleChangePageSize}
|
||||
onPageChange={handleChangePageIndex}
|
||||
onRowsPerPageChange={handleChangePageSize}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
||||
@@ -170,8 +170,8 @@ const MainForm = () => {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
}}
|
||||
onChangePage={handleChangePageIndex}
|
||||
onChangeRowsPerPage={handleChangePageSize}
|
||||
onPageChange={handleChangePageIndex}
|
||||
onRowsPerPageChange={handleChangePageSize}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
||||
@@ -147,8 +147,8 @@ const MainForm = () => {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
}}
|
||||
onChangePage={handleChangePageIndex}
|
||||
onChangeRowsPerPage={handleChangePageSize}
|
||||
onPageChange={handleChangePageIndex}
|
||||
onRowsPerPageChange={handleChangePageSize}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
||||
@@ -103,7 +103,7 @@ export const VehicleProvider = ({ children }) => {
|
||||
const result = await api.getConnections(vins, token);
|
||||
|
||||
if (result.error) {
|
||||
throw new Error(`Get connections error. ${result.message}`);
|
||||
throw new Error(`Add connections error. ${result.message}`);
|
||||
}
|
||||
cars.forEach((car) => {
|
||||
car.connected = result[car.vin] || false;
|
||||
@@ -125,6 +125,30 @@ export const VehicleProvider = ({ children }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getLocations = async (token) => {
|
||||
try {
|
||||
setBusy(true);
|
||||
const result = await api.getLocations(token);
|
||||
if (result.error)
|
||||
throw new Error(`Get locations error. ${result.message}`);
|
||||
return result;
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getState = async (token, vin) => {
|
||||
try {
|
||||
setBusy(true);
|
||||
const result = await api.getState(token, vin);
|
||||
if (result.error)
|
||||
throw new Error(`Get state error. ${result.message}`);
|
||||
return result;
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<VehicleContext.Provider
|
||||
value={{
|
||||
@@ -139,6 +163,8 @@ export const VehicleProvider = ({ children }) => {
|
||||
getYears,
|
||||
sendCommand,
|
||||
getConnections,
|
||||
getLocations,
|
||||
getState,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -39,6 +39,9 @@ export const useVehicleContext = () => ({
|
||||
|
||||
return result;
|
||||
}),
|
||||
getLocations: jest.fn().mockResolvedValue([
|
||||
{ "altitude": 5, "longitude": 10, "latitude": 15, "vin": "TESTVIN123" },
|
||||
])
|
||||
});
|
||||
|
||||
export const setBusy = (val) => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import useStyles from "../useStyles";
|
||||
import { useUserContext } from "../Contexts/UserContext";
|
||||
import { useStatusContext } from "../Contexts/StatusContext";
|
||||
import { parsePayload } from "../../utils/jwt";
|
||||
import VehicleMap from "../VehicleMap";
|
||||
|
||||
const DEFAULT_GREETING = "Welcome";
|
||||
|
||||
@@ -25,16 +26,18 @@ const Home = () => {
|
||||
const greeting = getGreeting(token);
|
||||
const { setTitle } = useStatusContext();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setTitle("");
|
||||
setTitle("Home");
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={classes.paper}>
|
||||
<Typography component="h1" variant="h5">
|
||||
<Typography className={classes.homePageTitle} component="h1" variant="h5">
|
||||
{greeting}
|
||||
</Typography>
|
||||
<VehicleMap />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ const menuData = [
|
||||
{
|
||||
label: "Dashboard",
|
||||
to: "/dashboard",
|
||||
roles: [],
|
||||
roles: [Roles.CREATE, Roles.READ],
|
||||
},
|
||||
{
|
||||
label: "Deploy Packages",
|
||||
@@ -45,7 +45,7 @@ const menuData = [
|
||||
label: "Send Command",
|
||||
to: "/vehicles-command",
|
||||
roles: [Roles.CREATE],
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
export default function SideMenu() {
|
||||
|
||||
@@ -219,28 +219,6 @@ exports[`SideMenu Unauthenticated 1`] = `
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
aria-disabled="false"
|
||||
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||
href="/dashboard"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="MuiListItemText-root"
|
||||
>
|
||||
<span
|
||||
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||
>
|
||||
Dashboard
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="MuiTouchRipple-root"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -230,8 +230,8 @@ const MainForm = () => {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
}}
|
||||
onChangePage={handleChangePageIndex}
|
||||
onChangeRowsPerPage={handleChangePageSize}
|
||||
onPageChange={handleChangePageIndex}
|
||||
onRowsPerPageChange={handleChangePageSize}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
||||
@@ -153,8 +153,8 @@ const MainForm = () => {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
}}
|
||||
onChangePage={handleChangePageIndex}
|
||||
onChangeRowsPerPage={handleChangePageSize}
|
||||
onPageChange={handleChangePageIndex}
|
||||
onRowsPerPageChange={handleChangePageSize}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
||||
@@ -75,7 +75,7 @@ const HeaderSortable = (props) => {
|
||||
<TableCell
|
||||
key={column.id}
|
||||
align={column.numeric ? "right" : "center"}
|
||||
padding={column.disablePadding ? "none" : "default"}
|
||||
padding={column.disablePadding ? "none" : "normal"}
|
||||
sortDirection={orderBy === column.id ? order : false}
|
||||
>
|
||||
{ColumnLabel(column)}
|
||||
|
||||
@@ -46,10 +46,10 @@ exports[`File Upload Form Should render 1`] = `
|
||||
/>
|
||||
<fieldset
|
||||
aria-hidden="true"
|
||||
class="PrivateNotchedOutline-root-33 MuiOutlinedInput-notchedOutline"
|
||||
class="PrivateNotchedOutline-root-39 MuiOutlinedInput-notchedOutline"
|
||||
>
|
||||
<legend
|
||||
class="PrivateNotchedOutline-legendLabelled-35"
|
||||
class="PrivateNotchedOutline-legendLabelled-41"
|
||||
>
|
||||
<span>
|
||||
Package name
|
||||
@@ -92,10 +92,10 @@ exports[`File Upload Form Should render 1`] = `
|
||||
/>
|
||||
<fieldset
|
||||
aria-hidden="true"
|
||||
class="PrivateNotchedOutline-root-33 MuiOutlinedInput-notchedOutline"
|
||||
class="PrivateNotchedOutline-root-39 MuiOutlinedInput-notchedOutline"
|
||||
>
|
||||
<legend
|
||||
class="PrivateNotchedOutline-legendLabelled-35"
|
||||
class="PrivateNotchedOutline-legendLabelled-41"
|
||||
>
|
||||
<span>
|
||||
Version
|
||||
@@ -138,10 +138,10 @@ exports[`File Upload Form Should render 1`] = `
|
||||
/>
|
||||
<fieldset
|
||||
aria-hidden="true"
|
||||
class="PrivateNotchedOutline-root-33 MuiOutlinedInput-notchedOutline"
|
||||
class="PrivateNotchedOutline-root-39 MuiOutlinedInput-notchedOutline"
|
||||
>
|
||||
<legend
|
||||
class="PrivateNotchedOutline-legendLabelled-35"
|
||||
class="PrivateNotchedOutline-legendLabelled-41"
|
||||
>
|
||||
<span>
|
||||
Description
|
||||
@@ -185,10 +185,10 @@ exports[`File Upload Form Should render 1`] = `
|
||||
/>
|
||||
<fieldset
|
||||
aria-hidden="true"
|
||||
class="PrivateNotchedOutline-root-33 MuiOutlinedInput-notchedOutline"
|
||||
class="PrivateNotchedOutline-root-39 MuiOutlinedInput-notchedOutline"
|
||||
>
|
||||
<legend
|
||||
class="PrivateNotchedOutline-legendLabelled-35"
|
||||
class="PrivateNotchedOutline-legendLabelled-41"
|
||||
>
|
||||
<span>
|
||||
Release Notes URL
|
||||
|
||||
@@ -225,8 +225,8 @@ const UpdatePackagesList = () => {
|
||||
inputProps: { "aria-label": "rows per page" },
|
||||
native: true,
|
||||
}}
|
||||
onChangePage={handleChangePageIndex}
|
||||
onChangeRowsPerPage={handleChangePageSize}
|
||||
onPageChange={handleChangePageIndex}
|
||||
onRowsPerPageChange={handleChangePageSize}
|
||||
/>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
||||
205
src/components/VehicleMap/index.jsx
Normal file
205
src/components/VehicleMap/index.jsx
Normal file
@@ -0,0 +1,205 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import useStyles from "../useStyles";
|
||||
import L from "leaflet";
|
||||
import { MapContainer, TileLayer, Marker, Popup, useMap } from "react-leaflet";
|
||||
import { Button } from "@material-ui/core";
|
||||
|
||||
import { useUserContext } from "../Contexts/UserContext";
|
||||
import { useVehicleContext, VehicleProvider } from "../Contexts/VehicleContext";
|
||||
import { VehiclePopUp } from "./popup";
|
||||
import GreenCarIcon from "../../assets/green-car.png";
|
||||
import RedCarIcon from "../../assets/red-car.png";
|
||||
|
||||
const Component = () => {
|
||||
const classes = useStyles();
|
||||
const {
|
||||
token: {
|
||||
idToken: { jwtToken: token },
|
||||
}
|
||||
} = useUserContext();
|
||||
const { getConnections, getLocations, getState } = useVehicleContext();
|
||||
|
||||
const REQUEST_INTERVAL = 10000;
|
||||
|
||||
const [center, setCenter] = useState([0, 0]);
|
||||
const [zoom, setZoom] = useState(2);
|
||||
const [markers, setMarkers] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
retrieveAndStoreLocations()
|
||||
.then(points => {
|
||||
centerAroundMarkers(points);
|
||||
})
|
||||
const id = setInterval(function () {
|
||||
retrieveAndStoreLocations();
|
||||
}, REQUEST_INTERVAL);
|
||||
return () => { clearInterval(id) };
|
||||
// eslint-disable-next-line
|
||||
}, []);
|
||||
|
||||
const retrieveAndStoreLocations = () => {
|
||||
return getLocations(token)
|
||||
.then(result => {
|
||||
if (result.data != null) {
|
||||
const points = result.data.map(point => [point.latitude, point.longitude, point.vin]);
|
||||
setMarkers(points);
|
||||
return points
|
||||
}
|
||||
return []
|
||||
})
|
||||
.catch(error => console.log(error));
|
||||
}
|
||||
|
||||
const centerAroundMarkers = (markers) => {
|
||||
if (markers == null) {
|
||||
markers = []
|
||||
}
|
||||
const coord = markers.reduce((coord, marker) => {
|
||||
coord[0] += marker[0] / markers.length;
|
||||
coord[1] += marker[1] / markers.length;
|
||||
return coord;
|
||||
}, [0, 0])
|
||||
|
||||
setCenter(coord);
|
||||
setZoom(4);
|
||||
}
|
||||
|
||||
const [connections, setConnections] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
if (markers.length > 0) {
|
||||
const vins = markers.map(marker => marker[2]);
|
||||
getConnections(vins, token)
|
||||
.then(connections => {
|
||||
setConnections(connections);
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [markers, token])
|
||||
|
||||
const [selectedVIN, setSelectedVIN] = useState(null);
|
||||
const [carState, setCarState] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedVIN != null) {
|
||||
retrieveAndStoreCarState(selectedVIN);
|
||||
const id = setInterval(function () {
|
||||
retrieveAndStoreCarState(selectedVIN);
|
||||
}, REQUEST_INTERVAL);
|
||||
return () => { clearInterval(id) };
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
}, [selectedVIN]);
|
||||
|
||||
const selectCar = (e, vin) => {
|
||||
e.preventDefault();
|
||||
setSelectedVIN(vin);
|
||||
}
|
||||
|
||||
const retrieveAndStoreCarState = (vin) => {
|
||||
getState(token, vin)
|
||||
.then(results => {
|
||||
setCarState({ ...results.data, vin: vin });
|
||||
});
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setSelectedVIN(null);
|
||||
setCarState(null);
|
||||
};
|
||||
|
||||
function getCarIcon(vin) {
|
||||
let icon = RedCarIcon;
|
||||
|
||||
if (connections[vin]) {
|
||||
icon = GreenCarIcon;
|
||||
} else {
|
||||
icon = RedCarIcon;
|
||||
}
|
||||
|
||||
return new L.Icon({
|
||||
iconUrl: icon,
|
||||
iconAnchor: [15, 0]
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '900px'
|
||||
}}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
<CenterFocus center={center} zoom={zoom} />
|
||||
|
||||
{markers.map((marker) => (
|
||||
<Marker
|
||||
icon={getCarIcon(marker[2])}
|
||||
key={marker[2]}
|
||||
position={[marker[0], marker[1]]}
|
||||
title={marker[2]}
|
||||
opacity={0.9}
|
||||
>
|
||||
<Popup>
|
||||
<div align="center">
|
||||
<p className={classes.markerTitle}><b>{marker[2]}</b></p>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={e => selectCar(e, marker[2])}
|
||||
>
|
||||
View Stats
|
||||
</Button>
|
||||
</div>
|
||||
</Popup>
|
||||
</Marker>
|
||||
))
|
||||
}
|
||||
|
||||
{
|
||||
carState ? (
|
||||
<VehiclePopUp
|
||||
key={carState.vin}
|
||||
vin={carState.vin}
|
||||
online={carState.online}
|
||||
battery={carState.battery}
|
||||
doors={carState.doors}
|
||||
location={carState.location}
|
||||
windows={carState.windows}
|
||||
className={classes.popup}
|
||||
onClose={handleClose}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
</MapContainer >
|
||||
);
|
||||
};
|
||||
|
||||
const CenterFocus = ({ center, zoom }) => {
|
||||
const map = useMap();
|
||||
|
||||
useEffect(() => {
|
||||
if (center[0] === 0 && center[1] === 0) {
|
||||
map.flyTo([0, 0], 2, { duration: 1.5 });
|
||||
} else {
|
||||
map.flyTo(center, zoom, { duration: 1.5 });
|
||||
}
|
||||
}, [center, zoom, map]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
const VehicleMap = () => (
|
||||
<VehicleProvider>
|
||||
<Component />
|
||||
</VehicleProvider>
|
||||
)
|
||||
|
||||
export default VehicleMap;
|
||||
72
src/components/VehicleMap/popup.jsx
Normal file
72
src/components/VehicleMap/popup.jsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React from "react";
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import MuiDialogTitle from '@material-ui/core/DialogTitle';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import CloseIcon from '@material-ui/icons/Close';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
||||
import useStyles from "../useStyles";
|
||||
|
||||
const VehiclePopUp = (props) => {
|
||||
const classes = useStyles();
|
||||
const { vin, online, battery, doors, location, windows, onClose } = props;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
fullWidth
|
||||
classes={{ paper: classes.popUp }}
|
||||
open={true}
|
||||
onClose={onClose}
|
||||
>
|
||||
<DialogTitle align="center" onClose={onClose}>{vin}</DialogTitle>
|
||||
<div align="center" className={classes.popUpContent}>
|
||||
<p><b>Connected</b>: {online.toString()}</p>
|
||||
{online && (
|
||||
<div>
|
||||
{battery != null && (
|
||||
<p><b>battery</b>: {battery.percent}%</p>
|
||||
)}
|
||||
{doors != null && (
|
||||
<div>
|
||||
<h3>Doors</h3>
|
||||
{Object.entries(doors).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1] ? "open" : "closed"}</p>))}
|
||||
</div>
|
||||
)}
|
||||
{windows != null && (
|
||||
<div>
|
||||
<h3>Windows</h3>
|
||||
{Object.entries(windows).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1] ? "open" : "closed"}</p>))}
|
||||
</div>
|
||||
)}
|
||||
{location != null && (
|
||||
<div>
|
||||
<h3>Location</h3>
|
||||
{Object.entries(location).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1]}</p>))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{(!online || (battery == null && doors == null && location == null && windows == null)) && (
|
||||
<p>No vehicle data to display.</p>
|
||||
)}
|
||||
</div>
|
||||
</Dialog >
|
||||
);
|
||||
};
|
||||
|
||||
const DialogTitle = (props) => {
|
||||
const { children, onClose, ...other } = props;
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<MuiDialogTitle disableTypography className={classes.ppopUpTItle} {...other}>
|
||||
<Typography variant="h6">{children}</Typography>
|
||||
{onClose ? (
|
||||
<IconButton aria-label="close" className={classes.closeButton} onClick={onClose}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
) : null}
|
||||
</MuiDialogTitle>
|
||||
);
|
||||
};
|
||||
|
||||
export { VehiclePopUp };
|
||||
@@ -173,6 +173,31 @@ const useStyles = makeStyles((theme) => ({
|
||||
width: "100%",
|
||||
paddingTop: "56.25%",
|
||||
},
|
||||
closeButton: {
|
||||
position: 'absolute',
|
||||
right: theme.spacing(1),
|
||||
top: theme.spacing(1),
|
||||
color: theme.palette.grey[500],
|
||||
},
|
||||
homePageTitle: {
|
||||
marginBottom: 25,
|
||||
},
|
||||
markerTitle: {
|
||||
margin: 5,
|
||||
},
|
||||
popUp: {
|
||||
minHeight: "15vh",
|
||||
},
|
||||
popUpTitle: {
|
||||
margin: 0,
|
||||
padding: theme.spacing(2),
|
||||
},
|
||||
popUpContent: {
|
||||
"& p": {
|
||||
margin: 0,
|
||||
},
|
||||
paddingBottom: "2vh",
|
||||
},
|
||||
}));
|
||||
|
||||
export default useStyles;
|
||||
|
||||
@@ -11,7 +11,7 @@ const data = [
|
||||
|
||||
const vehiclesAPI = {
|
||||
getVehicles: async (search, token) => { return { data }; },
|
||||
addVehicle: async (vehicle, token) => {
|
||||
addVehicle: async (vehicle, token) => {
|
||||
data.push(vehicle);
|
||||
return vehicle;
|
||||
},
|
||||
@@ -38,7 +38,10 @@ const vehiclesAPI = {
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
},
|
||||
getLocations: jest.fn().mockResolvedValue([
|
||||
{ "altitude": 5, "longitude": 10, "latitude": 15, "vin": "TESTVIN123" },
|
||||
]),
|
||||
};
|
||||
|
||||
export default vehiclesAPI;
|
||||
|
||||
@@ -9,10 +9,10 @@ const vehiclesAPI = {
|
||||
body: JSON.stringify(vehicle),
|
||||
})
|
||||
.then(fetchRespHandler),
|
||||
|
||||
|
||||
getVehicles: async (search, token) => {
|
||||
const u = addQueryParams(`${API_ENDPOINT}/vehicles`, search);
|
||||
return fetch(u, {
|
||||
return fetch(u, {
|
||||
method: "GET",
|
||||
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
|
||||
})
|
||||
@@ -20,10 +20,10 @@ const vehiclesAPI = {
|
||||
},
|
||||
|
||||
getModels: async (token) => fetch(`${API_ENDPOINT}/vehiclemodels`, {
|
||||
method: "GET",
|
||||
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
|
||||
})
|
||||
.then(fetchRespHandler),
|
||||
method: "GET",
|
||||
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
|
||||
})
|
||||
.then(fetchRespHandler),
|
||||
|
||||
getYears: async (token) => fetch(`${API_ENDPOINT}/vehicleyears`, {
|
||||
method: "GET",
|
||||
@@ -39,15 +39,27 @@ const vehiclesAPI = {
|
||||
}),
|
||||
})
|
||||
.then(fetchRespHandler),
|
||||
|
||||
|
||||
getConnections: async (vins, token) => {
|
||||
const u = `${API_ENDPOINT}/carsconnected?vins=${vins.join(",")}`
|
||||
return fetch(u, {
|
||||
return fetch(u, {
|
||||
method: "GET",
|
||||
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
|
||||
})
|
||||
.then(fetchRespHandler)
|
||||
},
|
||||
|
||||
getLocations: async (token) => fetch(`${API_ENDPOINT}/carslocations`, {
|
||||
method: "GET",
|
||||
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
|
||||
})
|
||||
.then(fetchRespHandler),
|
||||
|
||||
getState: async (token, vin) => fetch(`${API_ENDPOINT}/carstate?vin=${vin}`, {
|
||||
method: "GET",
|
||||
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
|
||||
})
|
||||
.then(fetchRespHandler),
|
||||
};
|
||||
|
||||
export default vehiclesAPI;
|
||||
|
||||
Reference in New Issue
Block a user