Merge development (#86)

This commit is contained in:
John Wu
2021-09-13 09:15:20 -07:00
committed by GitHub
parent 74eb2707a3
commit 680280dbf2
32 changed files with 465 additions and 466 deletions

View File

@@ -4,7 +4,7 @@ jest.mock("../Contexts/UserContext");
jest.mock("../Contexts/ManifestsContext"); jest.mock("../Contexts/ManifestsContext");
jest.mock("../Contexts/CarUpdatesContext"); jest.mock("../Contexts/CarUpdatesContext");
jest.mock("../../services/monitoring"); jest.mock("../../services/monitoring");
jest.mock("../../services/grafana"); jest.mock("../../services/grafanaAPI");
import { render, screen, cleanup, waitFor, waitForElementToBeRemoved } from "@testing-library/react"; import { render, screen, cleanup, waitFor, waitForElementToBeRemoved } from "@testing-library/react";
import { setToken } from "../Contexts/UserContext"; import { setToken } from "../Contexts/UserContext";

File diff suppressed because it is too large Load Diff

View File

@@ -24,9 +24,9 @@ const MainForm = () => {
}, },
} = useUserContext(); } = useUserContext();
const handleSearch = (search) => { const handleSearch = (query) => {
setSelected([]); setSelected([]);
setSearch(search); setSearch(query);
}; };
const handleSelectAll = (cars) => { const handleSelectAll = (cars) => {

View File

@@ -5,6 +5,7 @@ import { Button, Grid, Typography } from "@material-ui/core";
import CarECUsTable from "../../Controls/CarECUsTable"; import CarECUsTable from "../../Controls/CarECUsTable";
import CarUpdatesTable from "../../Controls/CarUpdatesTable"; import CarUpdatesTable from "../../Controls/CarUpdatesTable";
import { logger } from "../../../services/monitoring";
import { import {
VehicleProvider, VehicleProvider,
useVehicleContext, useVehicleContext,
@@ -12,7 +13,6 @@ import {
import { useUserContext } from "../../Contexts/UserContext"; import { useUserContext } from "../../Contexts/UserContext";
import { useStatusContext } from "../../Contexts/StatusContext"; import { useStatusContext } from "../../Contexts/StatusContext";
import useStyles from "../../useStyles"; import useStyles from "../../useStyles";
import { logger } from "../../../services/monitoring";
const MainForm = () => { const MainForm = () => {
const { vin } = useParams(); const { vin } = useParams();
@@ -28,9 +28,9 @@ const MainForm = () => {
try { try {
await sendCommand([vin], "ecu", "", token); await sendCommand([vin], "ecu", "", token);
setMessage(`Sent command to ${vin}`); setMessage(`Sent command to ${vin}`);
} catch (e) { } catch (error) {
setMessage(e.message); setMessage(error.message);
logger.error(e.stack); logger.error(error.stack);
} }
}; };
@@ -52,7 +52,7 @@ const MainForm = () => {
return ( return (
<div className={clsx(classes.paper, classes.tableSize)}> <div className={clsx(classes.paper, classes.tableSize)}>
<Typography variant="h6">Car Updates</Typography> <Typography variant="h6">Car Updates</Typography>
<CarUpdatesTable vin={vin} token={token} /> <CarUpdatesTable vin={vin} token={token} classes={classes} />
<Grid container className={classes.root} spacing={2}> <Grid container className={classes.root} spacing={2}>
<Grid item md={4} className={classes.textJustifyAlign}></Grid> <Grid item md={4} className={classes.textJustifyAlign}></Grid>
<Grid item md={4} className={classes.textCenterAlign}> <Grid item md={4} className={classes.textCenterAlign}>
@@ -73,7 +73,7 @@ const MainForm = () => {
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>
<CarECUsTable vin={vin} token={token} /> <CarECUsTable vin={vin} token={token} classes={classes} />
</div> </div>
); );
}; };

View File

@@ -1,5 +1,4 @@
import React, { useEffect } from "react"; import React, { useEffect, useState } from "react";
import { useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { Grid, TextField } from "@material-ui/core"; import { Grid, TextField } from "@material-ui/core";
@@ -126,7 +125,7 @@ const MainForm = () => {
</> </>
)} )}
<Grid item md={12}> <Grid item md={12}>
<CarUpdateStatusProgress status={status} /> <CarUpdateStatusProgress status={status} classes={classes} />
</Grid> </Grid>
<Grid item md={12}> <Grid item md={12}>
<CarUpdateStatusTable carupdateid={carupdateid} token={token} /> <CarUpdateStatusTable carupdateid={carupdateid} token={token} />

View File

@@ -1,6 +1,6 @@
import React, { useContext, useState } from "react"; import React, { useContext, useState } from "react";
import api from "../../services/updates"; import api from "../../services/updatesAPI";
import { validateStatusMessage } from "../../utils/statusMessage"; import { validateStatusMessage } from "../../utils/statusMessage";
const FINAL_UPDATE_STATES = ["package_install_complete"]; const FINAL_UPDATE_STATES = ["package_install_complete"];
@@ -122,9 +122,9 @@ export const CarUpdatesProvider = ({ children }) => {
let items = JSON.parse(JSON.stringify(carUpdates)); let items = JSON.parse(JSON.stringify(carUpdates));
statuses.forEach((status) => { statuses.forEach((status) => {
let item = items.find((item) => status.car_update_id === item.id); let x = items.find((item) => status.car_update_id === item.id);
if (!item || status.car_update_id === 0) return; if (!x || status.car_update_id === 0) return;
applyProgressStatus(item, status); applyProgressStatus(x, status);
}); });
setCarUpdates(items); setCarUpdates(items);

View File

@@ -1,6 +1,6 @@
import React, { useContext, useState } from "react"; import React, { useContext, useState } from "react";
import api from "../../services/manifests"; import api from "../../services/manifestsAPI";
import { uploadFile, getCancelToken } from "../../services/uploadFile"; import { uploadFile, getCancelToken } from "../../services/uploadFile";
const ManifestsContext = React.createContext(); const ManifestsContext = React.createContext();

View File

@@ -1,6 +1,6 @@
import React, { useContext, useEffect, useState } from "react"; import React, { useContext, useEffect, useState } from "react";
import auth from "../../services/auth"; import auth from "../../services/auth";
import getTimerWorker from "../../services/timer"; import getTimerWorker from "../../services/getTimerWorker";
import { parsePayload } from "../../utils/jwt"; import { parsePayload } from "../../utils/jwt";
import { getGroups } from "../../utils/roles"; import { getGroups } from "../../utils/roles";
@@ -37,8 +37,7 @@ export const UserProvider = ({ children }) => {
const refreshTokens = async () => { const refreshTokens = async () => {
if (!token || !token.refreshToken || !token.refreshToken.token) return null; if (!token || !token.refreshToken || !token.refreshToken.token) return null;
const result = await refresh(token.refreshToken.token); return refresh(token.refreshToken.token);
return result;
}; };
const startSessionTimer = () => { const startSessionTimer = () => {

View File

@@ -1,5 +1,5 @@
jest.mock("../../services/auth"); jest.mock("../../services/auth");
jest.mock("../../services/timer"); jest.mock("../../services/getTimerWorker");
import { import {
render, render,
@@ -10,7 +10,7 @@ import {
} from "@testing-library/react"; } from "@testing-library/react";
import { UserProvider, useUserContext } from "../Contexts/UserContext"; import { UserProvider, useUserContext } from "../Contexts/UserContext";
import auth from "../../services/auth"; import auth from "../../services/auth";
import getTimerWorker from "../../services/timer"; import getTimerWorker from "../../services/getTimerWorker";
import { TEST_AUTH_OBJECT, TEST_EXPECTED_GROUPS } from "../../utils/testing"; import { TEST_AUTH_OBJECT, TEST_EXPECTED_GROUPS } from "../../utils/testing";
const INVALID_TOKEN_RESPONSE = { const INVALID_TOKEN_RESPONSE = {
@@ -125,14 +125,8 @@ describe("UseContext", () => {
describe("Signout", () => { describe("Signout", () => {
beforeEach(async () => { beforeEach(async () => {
const TestComp = () => { const TestComp = () => {
const { const { signIn, signOut, error, token, groups, fetching } =
signIn, useUserContext();
signOut,
error,
token,
groups,
fetching,
} = useUserContext();
return ( return (
<> <>
<div data-testid="error">{error}</div> <div data-testid="error">{error}</div>

View File

@@ -13,7 +13,6 @@ import { LocalDateTimeString } from "../../../utils/dates";
import TableHeaderSortable from "../../Table/HeaderSortable"; import TableHeaderSortable from "../../Table/HeaderSortable";
import { useVehicleContext } from "../../Contexts/VehicleContext"; import { useVehicleContext } from "../../Contexts/VehicleContext";
import { useStatusContext } from "../../Contexts/StatusContext"; import { useStatusContext } from "../../Contexts/StatusContext";
import useStyles from "../../useStyles";
import { logger } from "../../../services/monitoring"; import { logger } from "../../../services/monitoring";
const tableColumns = [ const tableColumns = [
@@ -59,10 +58,9 @@ const tableColumns = [
}, },
]; ];
const CarECUsTable = ({ vin, token }) => { const CarECUsTable = ({ vin, token, classes }) => {
const [ecus, setECUs] = useState([]); const [ecus, setECUs] = useState([]);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const classes = useStyles();
const [pageSize, setPageSize] = useState(10); const [pageSize, setPageSize] = useState(10);
const [pageIndex, setPageIndex] = useState(0); const [pageIndex, setPageIndex] = useState(0);
const [orderBy, setOrderBy] = useState("ecu"); const [orderBy, setOrderBy] = useState("ecu");

View File

@@ -1,14 +1,11 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import Typography from "@material-ui/core/Typography";
import { CheckCircle, RadioButtonUnchecked, Error } from "@material-ui/icons"; import { CheckCircle, RadioButtonUnchecked, Error } from "@material-ui/icons";
import Typography from "@material-ui/core/Typography";
import clsx from "clsx"; import clsx from "clsx";
import CircularProgress from "../CircularProgress"; import CircularProgress from "../CircularProgress";
import useStyles from "../../useStyles";
const Progress = ({ value }) => {
const classes = useStyles();
const Progress = ({ value, classes }) => {
if (value === 100) if (value === 100)
return ( return (
<CheckCircle <CheckCircle
@@ -24,14 +21,13 @@ const Progress = ({ value }) => {
return <RadioButtonUnchecked className={classes.progressIcon} />; return <RadioButtonUnchecked className={classes.progressIcon} />;
}; };
const CarUpdateStatus = ({ status }) => { const CarUpdateStatus = ({ status, classes }) => {
const classes = useStyles();
const [received, setReceived] = useState(-1);
const [approval, setApproval] = useState(-1); const [approval, setApproval] = useState(-1);
const [precondition, setPrecondition] = useState(-1); const [cleanup, setCleanup] = useState(-1);
const [download, setDownload] = useState(-1); const [download, setDownload] = useState(-1);
const [install, setInstall] = useState(-1); const [install, setInstall] = useState(-1);
const [cleanup, setCleanup] = useState(-1); const [precondition, setPrecondition] = useState(-1);
const [received, setReceived] = useState(-1);
const [updated, setUpdated] = useState(-1); const [updated, setUpdated] = useState(-1);
useEffect(() => { useEffect(() => {
@@ -39,10 +35,15 @@ const CarUpdateStatus = ({ status }) => {
if (!status) return; if (!status) return;
// update previous steps // update previous steps
switch (status.msg) { switch (status.msg) {
case "cleanup_success": case "manifest_succeeded":
setUpdated(100); setUpdated(100);
case "cleanup_success":
setCleanup(100);
case "package_install_complete": case "package_install_complete":
setInstall(100); setInstall(100);
case "install_approval_received":
setApproval(100);
case "install_approval_await":
case "install_start": case "install_start":
case "installing": case "installing":
case "install_complete": case "install_complete":
@@ -53,10 +54,10 @@ const CarUpdateStatus = ({ status }) => {
case "downloading": case "downloading":
case "download_complete": case "download_complete":
case "download_error": case "download_error":
case "install_approval_received": case "package_download_start":
setApproval(100);
case "requirements_succeeded": case "requirements_succeeded":
setPrecondition(100); setPrecondition(100);
case "manifest_accepted":
case "manifest_received": case "manifest_received":
setReceived(100); setReceived(100);
} }
@@ -90,35 +91,35 @@ const CarUpdateStatus = ({ status }) => {
}} }}
> >
<div className={classes.textCenterAlign}> <div className={classes.textCenterAlign}>
<Progress value={100} /> <Progress value={100} classes={classes} />
<Typography>Pending</Typography> <Typography>Pending</Typography>
</div> </div>
<div className={classes.textCenterAlign}> <div className={classes.textCenterAlign}>
<Progress value={received} /> <Progress value={received} classes={classes} />
<Typography>Recieved</Typography> <Typography>Recieved</Typography>
</div> </div>
<div className={classes.textCenterAlign}> <div className={classes.textCenterAlign}>
<Progress value={approval} /> <Progress value={precondition} classes={classes} />
<Typography>Approved</Typography>
</div>
<div className={classes.textCenterAlign}>
<Progress value={precondition} />
<Typography>Precondition</Typography> <Typography>Precondition</Typography>
</div> </div>
<div className={classes.textCenterAlign}> <div className={classes.textCenterAlign}>
<Progress value={download} /> <Progress value={download} classes={classes} />
<Typography>Download</Typography> <Typography>Download</Typography>
</div> </div>
<div className={classes.textCenterAlign}> <div className={classes.textCenterAlign}>
<Progress value={install} /> <Progress value={approval} classes={classes} />
<Typography>Approved</Typography>
</div>
<div className={classes.textCenterAlign}>
<Progress value={install} classes={classes} />
<Typography>Install</Typography> <Typography>Install</Typography>
</div> </div>
<div className={classes.textCenterAlign}> <div className={classes.textCenterAlign}>
<Progress value={cleanup} /> <Progress value={cleanup} classes={classes} />
<Typography>Clean up</Typography> <Typography>Clean up</Typography>
</div> </div>
<div className={classes.textCenterAlign}> <div className={classes.textCenterAlign}>
<Progress value={updated} /> <Progress value={updated} classes={classes} />
<Typography>Updated</Typography> <Typography>Updated</Typography>
</div> </div>
</div> </div>

View File

@@ -49,16 +49,16 @@ const SendCommand = ({ vins }) => {
} else { } else {
setMessage(`Sent command to ${vins.length} cars`); setMessage(`Sent command to ${vins.length} cars`);
} }
} catch (e) { } catch (error) {
setMessage(e.message); setMessage(error.message);
logger.error(e.stack); logger.error(error.stack);
} }
}; };
const getParameters = (command) => { const getParameters = (cmd) => {
for (let i = 0, len = commands.length; i < len; i += 1) { for (let i = 0, len = commands.length; i < len; i += 1) {
const item = commands[i]; const item = commands[i];
if (item.value === command) { if (item.value === cmd) {
if (!item.parameters) { if (!item.parameters) {
break; break;
} }

View File

@@ -1,8 +1,7 @@
import React from "react"; import React, { useState } from "react";
import { TableCell, TableRow, TextField } from "@material-ui/core"; import { TableCell, TableRow, TextField } from "@material-ui/core";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import DeleteIcon from "@material-ui/icons/Delete"; import DeleteIcon from "@material-ui/icons/Delete";
import { useState } from "react";
const DataDisplay = ({ data, option, onDelete }) => { const DataDisplay = ({ data, option, onDelete }) => {
const [text, setText] = useState(data[option.field]); const [text, setText] = useState(data[option.field]);

View File

@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
import { Button, Grid, Link, Paper } from "@material-ui/core"; import { Button, Grid, Link, Paper } from "@material-ui/core";
import CreateIcon from "@material-ui/icons/Create"; import CreateIcon from "@material-ui/icons/Create";
import api from "../../../services/grafana"; import api from "../../../services/grafanaAPI";
import { useStatusContext } from "../../Contexts/StatusContext"; import { useStatusContext } from "../../Contexts/StatusContext";
import useStyles from "../../useStyles"; import useStyles from "../../useStyles";
import ResponsiveIFrame from "../../Controls/ResponsiveIFrame"; import ResponsiveIFrame from "../../Controls/ResponsiveIFrame";

View File

@@ -64,27 +64,18 @@ const MenuItem = ({ item, children }) => {
); );
}; };
const ExpandableSideMenuItem = ({ item }) => { const ExpandableSideMenuItem = ({ item }) => (
/* <>
const [expanded, setExpanded] = useState(true); <span>
const clickHandler = (e) => { <MenuItem item={item}></MenuItem>
setExpanded(!expanded); </span>
}; <ul style={{ marginLeft: 50 }}>
*/ {item.submenus.map((subitem, index) => (
<MenuItem key={`submenu-${index}`} item={subitem} />
return ( ))}
<> </ul>
<span> </>
<MenuItem item={item}></MenuItem> );
</span>
<ul style={{ marginLeft: 50 }}>
{item.submenus.map((subitem, index) => (
<MenuItem key={`submenu-${index}`} item={subitem} />
))}
</ul>
</>
);
};
const SideMenu = () => { const SideMenu = () => {
const { groups } = useUserContext(); const { groups } = useUserContext();

View File

@@ -21,13 +21,13 @@ const renderMenu = async () => {
describe("SideMenu", () => { describe("SideMenu", () => {
it("Unauthenticated", async () => { it("Unauthenticated", async () => {
setToken(null); setToken(null);
const container = await renderMenu(null); const container = await renderMenu();
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
}); });
it("Authenticated", async () => { it("Authenticated", async () => {
setToken(TEST_AUTH_OBJECT); setToken(TEST_AUTH_OBJECT);
const container = await renderMenu(TEST_AUTH_OBJECT); const container = await renderMenu();
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
}); });
}); });

View File

@@ -182,7 +182,7 @@ exports[`SideMenu Authenticated 1`] = `
<li> <li>
<a <a
aria-disabled="false" aria-disabled="false"
class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiButtonBase-root MuiListItem-root makeStyles-menuExternalLink-53 MuiListItem-gutters MuiListItem-button MuiTypography-colorPrimary" class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiButtonBase-root MuiListItem-root makeStyles-menuExternalLink-54 MuiListItem-gutters MuiListItem-button MuiTypography-colorPrimary"
href="https://grafana.fiskerdps.com" href="https://grafana.fiskerdps.com"
rel="noopener" rel="noopener"
role="button" role="button"

View File

@@ -38,9 +38,9 @@ const MainForm = () => {
const [redirect, setRedirect] = useState(""); const [redirect, setRedirect] = useState("");
const classes = useStyles(); const classes = useStyles();
const handleSearch = (search) => { const handleSearch = (query) => {
setSelected([]); setSelected([]);
setSearch(search); setSearch(query);
}; };
const handleSelectAll = (cars) => { const handleSelectAll = (cars) => {

View File

@@ -122,8 +122,8 @@ const MainForm = () => {
setPageIndex(0); setPageIndex(0);
}; };
const handleSearch = (search) => { const handleSearch = (query) => {
setSearch(search); setSearch(query);
}; };
const onDelete = async (manifest_id) => { const onDelete = async (manifest_id) => {
@@ -161,7 +161,7 @@ const MainForm = () => {
]); ]);
} }
if (actions.length === 0) return "No actions"; if (actions.length === 0) return ["No actions"];
return actions.map((action) => { return actions.map((action) => {
if (action.link != null) { if (action.link != null) {

View File

@@ -3,7 +3,7 @@
exports[`Sign In Form Should render 1`] = ` exports[`Sign In Form Should render 1`] = `
<div> <div>
<div <div
class="makeStyles-paper-3 makeStyles-textJustifyAlign-48" class="makeStyles-paper-3 makeStyles-textJustifyAlign-49"
> >
<a <a
aria-disabled="false" aria-disabled="false"

View File

@@ -27,20 +27,21 @@ const Component = () => {
const [markers, setMarkers] = useState([]); const [markers, setMarkers] = useState([]);
useEffect(() => { useEffect(() => {
retrieveAndStoreLocations().then((points) => { if (!token) return;
retrieveAndStoreLocations(token).then((points) => {
centerAroundMarkers(points); centerAroundMarkers(points);
}); });
const id = setInterval(function () { const id = setInterval(function () {
retrieveAndStoreLocations(); retrieveAndStoreLocations(token);
}, REQUEST_INTERVAL); }, REQUEST_INTERVAL);
return () => { return () => {
clearInterval(id); clearInterval(id);
}; };
// eslint-disable-next-line // eslint-disable-next-line
}, []); }, [token]);
const retrieveAndStoreLocations = () => { const retrieveAndStoreLocations = (accessToken) => {
return getLocations(token) return getLocations(accessToken)
.then((result) => { .then((result) => {
if (result.data != null) { if (result.data != null) {
const points = result.data.map((point) => [ const points = result.data.map((point) => [
@@ -73,6 +74,7 @@ const Component = () => {
const [connections, setConnections] = useState({}); const [connections, setConnections] = useState({});
useEffect(() => { useEffect(() => {
if (!token) return;
if (markers.length > 0) { if (markers.length > 0) {
const vins = markers.map((marker) => marker[2]); const vins = markers.map((marker) => marker[2]);
getConnections(vins, token).then((connections) => { getConnections(vins, token).then((connections) => {
@@ -177,6 +179,7 @@ const Component = () => {
doors={carState.doors} doors={carState.doors}
location={carState.location} location={carState.location}
windows={carState.windows} windows={carState.windows}
updatedAt={carState.updated}
className={classes.popup} className={classes.popup}
onClose={handleClose} onClose={handleClose}
/> />

View File

@@ -6,10 +6,11 @@ import CloseIcon from '@material-ui/icons/Close';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import useStyles from "../useStyles"; import useStyles from "../useStyles";
import { LocalDateTimeString } from "../../utils/dates";
const VehiclePopUp = (props) => { const VehiclePopUp = (props) => {
const classes = useStyles(); const classes = useStyles();
const { vin, online, battery, doors, location, windows, onClose } = props; const { vin, online, battery, doors, location, updatedAt, windows, onClose } = props;
return ( return (
<Dialog <Dialog
@@ -24,24 +25,35 @@ const VehiclePopUp = (props) => {
{online && ( {online && (
<div> <div>
{battery != null && ( {battery != null && (
<p><b>battery</b>: {battery.percent}%</p> <p><b>Battery</b>: {battery.percent}%</p>
)} )}
{doors != null && ( {doors != null && (
<div> <div className={classes.popupSection}>
<h3>Doors</h3> <h3>Doors</h3>
{Object.entries(doors).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1] ? "open" : "closed"}</p>))} {Object.entries(doors).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1] ? "open" : "closed"}</p>))}
</div> </div>
)} )}
{windows != null && ( {windows != null && (
<div> <div className={classes.popupSection}>
<h3>Windows</h3> <h3>Windows</h3>
{Object.entries(windows).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1] ? "open" : "closed"}</p>))} {Object.entries(windows).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1] ? "open" : "closed"}</p>))}
</div> </div>
)} )}
{location != null && ( {location != null && (
<div> <div className={classes.popupSection}>
<h3>Location</h3> <h3>Location</h3>
{Object.entries(location).map((value) => (<p key={value[0]}><b>{value[0]}</b>: {value[1]}</p>))} {Object.entries(location).map((value) => {
if (value[0] === "altitude") {
return (<p key={value[0]}><b>{value[0]}</b>: {value[1]}</p>);
} else {
return (<p key={value[0]}><b>{value[0]}</b>: {value[1]}°</p>)
}
})}
</div>
)}
{updatedAt != null && (
<div className={classes.popupSection}>
<p><b>Updated at</b>: {LocalDateTimeString(updatedAt)}</p>
</div> </div>
)} )}
</div> </div>

View File

@@ -5,6 +5,6 @@ function menuItemStyle(item, selectedItems, theme) {
? theme.typography.fontWeightRegular ? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium, : theme.typography.fontWeightMedium,
}; };
}; }
export default menuItemStyle export default menuItemStyle;

View File

@@ -203,6 +203,9 @@ const useStyles = makeStyles((theme) => ({
}, },
paddingBottom: "2vh", paddingBottom: "2vh",
}, },
popupSection: {
marginBottom: "1vh",
},
toolbarFooter: { toolbarFooter: {
width: "100%", width: "100%",
textAlign: "right", textAlign: "right",

View File

@@ -1,6 +1,6 @@
const updatesAPI = { const manifestsAPI = {
createCarUpdates: async (data, token) => { createCarUpdates: async (data, token) => {
if (!data.id) data.id = 0; if (!data.id) data.id = 0;
data.id++; data.id++;
@@ -14,21 +14,21 @@ const updatesAPI = {
id: 1, id: 1,
package_name: "Test", package_name: "Test",
version: "1.0", version: "1.0",
link: "http://cloudfront.com/download", link: "https://cloudfront.com/download",
ecu_list: "ECU1 1.0.0,ECU2 1.0.2", ecu_list: "ECU1 1.0.0,ECU2 1.0.2",
}, },
{ {
id: 2, id: 2,
package_name: "Test", package_name: "Test",
version: "1.1", version: "1.1",
link: "http://cloudfront.com/download", link: "https://cloudfront.com/download",
ecu_list: "ECU1 1.0.1,ECU2 1.0.2", ecu_list: "ECU1 1.0.1,ECU2 1.0.2",
}, },
{ {
id: 3, id: 3,
package_name: "Test", package_name: "Test",
version: "1.2", version: "1.2",
link: "http://cloudfront.com/download", link: "https://cloudfront.com/download",
ecu_list: "ECU1 1.1.0,ECU2 1.1.2", ecu_list: "ECU1 1.1.0,ECU2 1.1.2",
} }
] ]
@@ -56,4 +56,4 @@ const updatesAPI = {
}, },
}; };
export default updatesAPI; export default manifestsAPI;

View File

@@ -1,10 +1,10 @@
import { fetchRespHandler } from "../utils/http" import { fetchRespHandler } from "../utils/http"
import { logger } from "../services/monitoring"; import { logger } from "./monitoring";
const API_ENDPOINT = "https://grafana.fiskerdps.com/api/datasources/proxy/2" const API_ENDPOINT = "https://grafana.fiskerdps.com/api/datasources/proxy/2"
const grafanaAPI = { const grafanaAPI = {
getCarsCount: async () => fetch(`${API_ENDPOINT}/?query=SELECT%20countDistinct(vin)%20as%20count%0AFROM%20default.vehicle_data%20FORMAT%20JSON`, { getCarsCount: async () => fetch(`${API_ENDPOINT}/?query=SELECT%20countDistinct(VIN)%20as%20count%0AFROM%20default.vehicle_signal%0AWHERE%20Timestamp%20%3C%3D%20toDateTime64(${Date.now() / Math.pow(10, 3)}%2C%203)%20AND%20Timestamp%20%3E%3D%20toDateTime64(${Date.now() / Math.pow(10, 3) - 60 * 60 * 24}%2C%203)%20FORMAT%20JSON`, {
method: "GET", method: "GET",
headers: Object.assign({ "Content-Type": "application/json" }), headers: Object.assign({ "Content-Type": "application/json" }),
}) })