Merge branch 'development' into main

This commit is contained in:
jwu-fisker
2021-05-18 12:58:05 -07:00
9 changed files with 811 additions and 190 deletions

View File

@@ -299,17 +299,17 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
data-testid="mocked-userprovider" data-testid="mocked-userprovider"
> >
<div <div
class="makeStyles-root-551" class="makeStyles-root-559"
> >
<header <header
class="MuiPaper-root MuiAppBar-root MuiAppBar-positionFixed MuiAppBar-colorPrimary makeStyles-appBar-552 makeStyles-appBarShift-553 mui-00000fixed MuiPaper-elevation4" class="MuiPaper-root MuiAppBar-root MuiAppBar-positionFixed MuiAppBar-colorPrimary makeStyles-appBar-560 makeStyles-appBarShift-561 mui-00000fixed MuiPaper-elevation4"
> >
<div <div
class="MuiToolbar-root MuiToolbar-regular MuiToolbar-gutters" class="MuiToolbar-root MuiToolbar-regular MuiToolbar-gutters"
> >
<button <button
aria-label="open drawer" aria-label="open drawer"
class="MuiButtonBase-root MuiIconButton-root makeStyles-menuButton-554 MuiIconButton-colorInherit MuiIconButton-edgeStart" class="MuiButtonBase-root MuiIconButton-root makeStyles-menuButton-562 MuiIconButton-colorInherit MuiIconButton-edgeStart"
tabindex="0" tabindex="0"
type="button" type="button"
> >
@@ -337,7 +337,7 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
Fisker OTA Portal Fisker OTA Portal
</h6> </h6>
<button <button
class="MuiButtonBase-root MuiButton-root MuiButton-text makeStyles-rightToolbar-561 MuiButton-colorInherit" class="MuiButtonBase-root MuiButton-root MuiButton-text makeStyles-rightToolbar-569 MuiButton-colorInherit"
tabindex="0" tabindex="0"
type="button" type="button"
> >
@@ -353,13 +353,13 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
</div> </div>
</header> </header>
<div <div
class="MuiDrawer-root MuiDrawer-docked makeStyles-drawer-556" class="MuiDrawer-root MuiDrawer-docked makeStyles-drawer-564"
> >
<div <div
class="MuiPaper-root MuiDrawer-paper makeStyles-drawerPaper-557 MuiDrawer-paperAnchorLeft MuiDrawer-paperAnchorDockedLeft MuiPaper-elevation0" class="MuiPaper-root MuiDrawer-paper makeStyles-drawerPaper-565 MuiDrawer-paperAnchorLeft MuiDrawer-paperAnchorDockedLeft MuiPaper-elevation0"
> >
<div <div
class="makeStyles-drawerHeader-558" class="makeStyles-drawerHeader-566"
> >
<button <button
class="MuiButtonBase-root MuiIconButton-root" class="MuiButtonBase-root MuiIconButton-root"
@@ -505,10 +505,10 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
</div> </div>
</div> </div>
<main <main
class="makeStyles-content-559 makeStyles-contentShift-560" class="makeStyles-content-567 makeStyles-contentShift-568"
> >
<div <div
class="makeStyles-drawerHeader-558" class="makeStyles-drawerHeader-566"
/> />
<main <main
class="MuiContainer-root MuiContainer-maxWidthLg" class="MuiContainer-root MuiContainer-maxWidthLg"
@@ -517,7 +517,7 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
data-testid="mocked-updatesprovider" data-testid="mocked-updatesprovider"
> >
<div <div
class="makeStyles-paper-540" class="makeStyles-paper-548"
> >
<h1 <h1
class="MuiTypography-root MuiTypography-h5" class="MuiTypography-root MuiTypography-h5"
@@ -527,7 +527,7 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
</h1> </h1>
<form <form
action="{onSubmit}" action="{onSubmit}"
class="makeStyles-form-542" class="makeStyles-form-550"
novalidate="" novalidate=""
> >
<div <div
@@ -631,10 +631,10 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
data-testid="mocked-vehicleprovider" data-testid="mocked-vehicleprovider"
> >
<div <div
class="makeStyles-form-542" class="makeStyles-form-550"
> >
<div <div
class="MuiFormControl-root makeStyles-formControlInline-545" class="MuiFormControl-root makeStyles-formControlInline-553"
> >
<label <label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled" class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
@@ -676,11 +676,11 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
</svg> </svg>
<fieldset <fieldset
aria-hidden="true" aria-hidden="true"
class="PrivateNotchedOutline-root-563 MuiOutlinedInput-notchedOutline" class="PrivateNotchedOutline-root-571 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;" style="padding-left: 8px;"
> >
<legend <legend
class="PrivateNotchedOutline-legend-564" class="PrivateNotchedOutline-legend-572"
style="width: 0.01px;" style="width: 0.01px;"
> >
<span> <span>
@@ -691,7 +691,7 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
</div> </div>
</div> </div>
<div <div
class="MuiFormControl-root makeStyles-formControlInline-545" class="MuiFormControl-root makeStyles-formControlInline-553"
> >
<label <label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled" class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
@@ -733,11 +733,11 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
</svg> </svg>
<fieldset <fieldset
aria-hidden="true" aria-hidden="true"
class="PrivateNotchedOutline-root-563 MuiOutlinedInput-notchedOutline" class="PrivateNotchedOutline-root-571 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;" style="padding-left: 8px;"
> >
<legend <legend
class="PrivateNotchedOutline-legend-564" class="PrivateNotchedOutline-legend-572"
style="width: 0.01px;" style="width: 0.01px;"
> >
<span> <span>
@@ -748,14 +748,14 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
</div> </div>
</div> </div>
<div <div
class="makeStyles-labelInline-546" class="makeStyles-labelInline-554"
> >
No Cars Selected No Cars Selected
</div> </div>
</div> </div>
</div> </div>
<button <button
class="MuiButtonBase-root MuiButton-root MuiButton-contained makeStyles-submit-543 MuiButton-containedPrimary MuiButton-fullWidth" class="MuiButtonBase-root MuiButton-root MuiButton-contained makeStyles-submit-551 MuiButton-containedPrimary MuiButton-fullWidth"
tabindex="0" tabindex="0"
type="submit" type="submit"
> >
@@ -2132,17 +2132,17 @@ exports[`App Route /page-not-found authenticated 1`] = `
data-testid="mocked-userprovider" data-testid="mocked-userprovider"
> >
<div <div
class="makeStyles-root-526" class="makeStyles-root-534"
> >
<header <header
class="MuiPaper-root MuiAppBar-root MuiAppBar-positionFixed MuiAppBar-colorPrimary makeStyles-appBar-527 makeStyles-appBarShift-528 mui-00000fixed MuiPaper-elevation4" class="MuiPaper-root MuiAppBar-root MuiAppBar-positionFixed MuiAppBar-colorPrimary makeStyles-appBar-535 makeStyles-appBarShift-536 mui-00000fixed MuiPaper-elevation4"
> >
<div <div
class="MuiToolbar-root MuiToolbar-regular MuiToolbar-gutters" class="MuiToolbar-root MuiToolbar-regular MuiToolbar-gutters"
> >
<button <button
aria-label="open drawer" aria-label="open drawer"
class="MuiButtonBase-root MuiIconButton-root makeStyles-menuButton-529 MuiIconButton-colorInherit MuiIconButton-edgeStart" class="MuiButtonBase-root MuiIconButton-root makeStyles-menuButton-537 MuiIconButton-colorInherit MuiIconButton-edgeStart"
tabindex="0" tabindex="0"
type="button" type="button"
> >
@@ -2170,7 +2170,7 @@ exports[`App Route /page-not-found authenticated 1`] = `
Fisker OTA Portal Fisker OTA Portal
</h6> </h6>
<button <button
class="MuiButtonBase-root MuiButton-root MuiButton-text makeStyles-rightToolbar-536 MuiButton-colorInherit" class="MuiButtonBase-root MuiButton-root MuiButton-text makeStyles-rightToolbar-544 MuiButton-colorInherit"
tabindex="0" tabindex="0"
type="button" type="button"
> >
@@ -2186,13 +2186,13 @@ exports[`App Route /page-not-found authenticated 1`] = `
</div> </div>
</header> </header>
<div <div
class="MuiDrawer-root MuiDrawer-docked makeStyles-drawer-531" class="MuiDrawer-root MuiDrawer-docked makeStyles-drawer-539"
> >
<div <div
class="MuiPaper-root MuiDrawer-paper makeStyles-drawerPaper-532 MuiDrawer-paperAnchorLeft MuiDrawer-paperAnchorDockedLeft MuiPaper-elevation0" class="MuiPaper-root MuiDrawer-paper makeStyles-drawerPaper-540 MuiDrawer-paperAnchorLeft MuiDrawer-paperAnchorDockedLeft MuiPaper-elevation0"
> >
<div <div
class="makeStyles-drawerHeader-533" class="makeStyles-drawerHeader-541"
> >
<button <button
class="MuiButtonBase-root MuiIconButton-root" class="MuiButtonBase-root MuiIconButton-root"
@@ -2338,16 +2338,16 @@ exports[`App Route /page-not-found authenticated 1`] = `
</div> </div>
</div> </div>
<main <main
class="makeStyles-content-534 makeStyles-contentShift-535" class="makeStyles-content-542 makeStyles-contentShift-543"
> >
<div <div
class="makeStyles-drawerHeader-533" class="makeStyles-drawerHeader-541"
/> />
<main <main
class="MuiContainer-root MuiContainer-maxWidthLg" class="MuiContainer-root MuiContainer-maxWidthLg"
> >
<div <div
class="makeStyles-paper-515" class="makeStyles-paper-523"
> >
<h1 <h1
class="MuiTypography-root MuiTypography-h2" class="MuiTypography-root MuiTypography-h2"
@@ -2368,10 +2368,10 @@ exports[`App Route /page-not-found unauthenticated 1`] = `
data-testid="mocked-userprovider" data-testid="mocked-userprovider"
> >
<div <div
class="makeStyles-root-501" class="makeStyles-root-509"
> >
<header <header
class="MuiPaper-root MuiAppBar-root MuiAppBar-positionFixed MuiAppBar-colorPrimary makeStyles-appBar-502 mui-00000fixed MuiPaper-elevation4" class="MuiPaper-root MuiAppBar-root MuiAppBar-positionFixed MuiAppBar-colorPrimary makeStyles-appBar-510 mui-00000fixed MuiPaper-elevation4"
> >
<div <div
class="MuiToolbar-root MuiToolbar-regular MuiToolbar-gutters" class="MuiToolbar-root MuiToolbar-regular MuiToolbar-gutters"
@@ -2384,16 +2384,16 @@ exports[`App Route /page-not-found unauthenticated 1`] = `
</div> </div>
</header> </header>
<main <main
class="makeStyles-content-509" class="makeStyles-content-517"
> >
<div <div
class="makeStyles-drawerHeader-508" class="makeStyles-drawerHeader-516"
/> />
<main <main
class="MuiContainer-root MuiContainer-maxWidthLg" class="MuiContainer-root MuiContainer-maxWidthLg"
> >
<div <div
class="makeStyles-paper-490" class="makeStyles-paper-498"
> >
<h1 <h1
class="MuiTypography-root MuiTypography-h2" class="MuiTypography-root MuiTypography-h2"
@@ -4102,6 +4102,9 @@ exports[`App Route /vehicle-status authenticated 1`] = `
/> />
<main <main
class="MuiContainer-root MuiContainer-maxWidthLg" class="MuiContainer-root MuiContainer-maxWidthLg"
>
<div
data-testid="mocked-vehicleprovider"
> >
<div <div
data-testid="mocked-updatesprovider" data-testid="mocked-updatesprovider"
@@ -4284,6 +4287,304 @@ exports[`App Route /vehicle-status authenticated 1`] = `
</tfoot> </tfoot>
</table> </table>
</div> </div>
<div
class="MuiGrid-root makeStyles-root-476 MuiGrid-container MuiGrid-spacing-xs-2"
>
<div
class="MuiGrid-root MuiGrid-item MuiGrid-grid-md-12 MuiGrid-grid-lg-6"
>
<div
class="makeStyles-form-467"
>
<div
class="MuiFormControl-root makeStyles-formControlInline-470"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
data-shrink="true"
for="send-command"
style="background-color: White;"
>
Command
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
>
<select
aria-invalid="false"
class="MuiSelect-root MuiSelect-select MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
id="send-command"
name="send-command"
>
<option
value="LFRD"
>
Lock front right door
</option>
<option
value="UFRD"
>
Unlock front right door
</option>
<option
value="LFLD"
>
Lock front left door
</option>
<option
value="UFLD"
>
Unlock front left door
</option>
<option
value="LRRD"
>
Lock rear right door
</option>
<option
value="URRD"
>
Unlock rear right door
</option>
<option
value="LRLD"
>
Lock rear left door
</option>
<option
value="URLD"
>
Unlock rear left door
</option>
<option
value="LTRK"
>
Lock trunk
</option>
<option
value="UTRK"
>
Unlock trunk
</option>
<option
value="OWIN"
>
Open Windows
</option>
<option
value="CWIN"
>
Close Windows
</option>
<option
value="FLASH"
>
Flash headlights
</option>
</select>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-488 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;"
>
<legend
class="PrivateNotchedOutline-legend-489"
style="width: 0.01px;"
>
<span>
</span>
</legend>
</fieldset>
</div>
</div>
<span
aria-disabled="false"
aria-label="send command"
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorPrimary"
role="button"
tabindex="0"
>
<span
class="MuiIconButton-label"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeLarge"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</span>
</div>
</div>
<div
class="MuiGrid-root MuiGrid-item MuiGrid-grid-md-12 MuiGrid-grid-lg-6"
style="text-align: right;"
>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-2 MuiGrid-align-items-xs-center"
>
<div
class="MuiGrid-root MuiGrid-item"
>
<label
class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementTop"
>
<span
class="MuiSwitch-root"
>
<span
aria-disabled="false"
class="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-492 MuiSwitch-switchBase MuiSwitch-colorPrimary PrivateSwitchBase-checked-493 Mui-checked"
>
<span
class="MuiIconButton-label"
>
<input
checked=""
class="PrivateSwitchBase-input-495 MuiSwitch-input"
name="logStart"
type="checkbox"
value=""
/>
<span
class="MuiSwitch-thumb"
/>
</span>
<span
class="MuiTouchRipple-root"
/>
</span>
<span
class="MuiSwitch-track"
/>
</span>
<span
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
>
Logging
</span>
</label>
</div>
<div
class="MuiGrid-root MuiGrid-item"
>
<div
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined"
data-shrink="false"
for="log-filter"
id="log-filter-label"
>
Filter
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
>
<input
aria-invalid="false"
class="MuiInputBase-input MuiOutlinedInput-input"
id="log-filter"
maxlength="17"
name="log-filter"
type="text"
value=""
/>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-488 MuiOutlinedInput-notchedOutline"
>
<legend
class="PrivateNotchedOutline-legendLabelled-490"
>
<span>
Filter
</span>
</legend>
</fieldset>
</div>
</div>
</div>
<div
class="MuiGrid-root MuiGrid-item"
>
<div
class="MuiFormControl-root MuiTextField-root"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiFormLabel-filled"
data-shrink="true"
for="log-frequency"
id="log-frequency-label"
>
Frequency
</label>
<div
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl"
>
<input
aria-invalid="false"
class="MuiInputBase-input MuiInput-input"
id="log-frequency"
type="number"
value="0"
/>
</div>
</div>
</div>
<div
class="MuiGrid-root MuiGrid-item"
>
<span
aria-disabled="false"
aria-label="send log command"
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorPrimary"
role="button"
tabindex="0"
>
<span
class="MuiIconButton-label"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeLarge"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"
/>
</svg>
</span>
<span
class="MuiTouchRipple-root"
/>
</span>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</main> </main>

View File

@@ -0,0 +1,123 @@
import React, { useState } from "react";
import PropTypes from "prop-types";
import {
FormControlLabel,
Grid,
IconButton,
TextField,
Switch,
} from "@material-ui/core";
import SendIcon from "@material-ui/icons/Send";
import { useVehicleContext } from "../../Contexts/VehicleContext";
import { useUserContext } from "../../Contexts/UserContext";
import { useStatusContext } from "../../Contexts/StatusContext";
const LogFilter = ({ vin }) => {
const { sendLogFilter, busy } = useVehicleContext();
const {
token: {
idToken: { jwtToken: token },
},
} = useUserContext();
const { setMessage } = useStatusContext();
const [filter, setFilter] = useState("");
const [enableLog, setEnableLog] = useState(true);
const [freq, setFreq] = useState(0);
const changeFilterHandler = (e) => {
setFilter(e.target.value);
};
const changeStartHandler = (e) => {
setEnableLog(e.target.checked);
};
const changeFreqHandler = (e) => {
setFreq(e.target.value);
};
const clickHandler = async (e) => {
try {
const data = {
enable: enableLog,
frequency: freq,
filter,
};
await sendLogFilter(vin, data, token);
setMessage(`Sent log command to ${vin}`);
} catch (e) {
setMessage(e.message);
}
};
return (
<Grid
container
direction="row"
justify="flex-start"
alignItems="center"
spacing={2}
>
<Grid item>
<FormControlLabel
control={
<Switch
checked={enableLog}
onChange={changeStartHandler}
name="logStart"
color="primary"
/>
}
labelPlacement="top"
label="Logging"
/>
</Grid>
<Grid item>
<TextField
id="log-filter"
name="log-filter"
label="Filter"
variant="outlined"
margin="normal"
inputProps={{
maxLength: "17",
}}
disabled={!enableLog}
value={filter}
onChange={changeFilterHandler}
/>
</Grid>
<Grid item>
<TextField
id="log-frequency"
label="Frequency"
type="number"
disabled={!enableLog}
InputLabelProps={{
shrink: true,
}}
value={freq}
onChange={changeFreqHandler}
/>
</Grid>
<Grid item>
<IconButton
color="primary"
aria-label="send log command"
component="span"
onClick={clickHandler}
disabled={busy}
>
<SendIcon fontSize="large" />
</IconButton>
</Grid>
</Grid>
);
};
LogFilter.propTypes = {
vin: PropTypes.string.isRequired,
};
export default LogFilter;

View File

@@ -0,0 +1,81 @@
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { FormControl, IconButton, InputLabel, Select } from "@material-ui/core";
import SendIcon from "@material-ui/icons/Send";
import { useVehicleContext } from "../../Contexts/VehicleContext";
import commands from "../../../services/commands";
import useStyles from "../../useStyles";
import { useUserContext } from "../../Contexts/UserContext";
import { useStatusContext } from "../../Contexts/StatusContext";
const SendCommand = ({ vin }) => {
const classes = useStyles();
const { sendCommand, busy } = useVehicleContext();
const {
token: {
idToken: { jwtToken: token },
},
} = useUserContext();
const { setMessage } = useStatusContext();
const [command, setCommand] = useState("");
const changeHandler = (e) => {
setCommand(e.target.value);
};
const clickHandler = async (e) => {
try {
await sendCommand(vin, command, token);
setMessage(`Sent command to ${vin}`);
} catch (e) {
setMessage(e.message);
}
};
useEffect(() => {
if (!commands || commands.length === 0) return;
setCommand(commands[0].value);
}, []);
return (
<div className={classes.form}>
<FormControl className={classes.formControlInline} variant="outlined">
<InputLabel htmlFor="send-command" style={{ backgroundColor: "White" }}>
Command
</InputLabel>
<Select
native
value={command}
variant="outlined"
inputProps={{
name: "send-command",
id: "send-command",
}}
onChange={changeHandler}
>
{commands.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</Select>
</FormControl>
<IconButton
color="primary"
aria-label="send command"
component="span"
onClick={clickHandler}
disabled={busy}
>
<SendIcon fontSize="large" />
</IconButton>
</div>
);
};
SendCommand.propTypes = {
vin: PropTypes.string.isRequired,
};
export default SendCommand;

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useParams } from "react-router"; import { useParams } from "react-router";
import { import {
Grid,
Table, Table,
TableBody, TableBody,
TableCell, TableCell,
@@ -16,10 +17,14 @@ import {
UpdatesProvider, UpdatesProvider,
useUpdatesContext, useUpdatesContext,
} from "../../Contexts/UpdatesContext"; } from "../../Contexts/UpdatesContext";
import { VehicleProvider } from "../../Contexts/VehicleContext";
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 { LocalDateTimeString } from "../../../utils/dates"; import { LocalDateTimeString } from "../../../utils/dates";
import SendCommand from "../SendCommand";
import LogFilter from "../LogFilter";
const MainForm = () => { const MainForm = () => {
const { vin } = useParams(); const { vin } = useParams();
@@ -109,14 +114,24 @@ const MainForm = () => {
</TableFooter> </TableFooter>
</Table> </Table>
</TableContainer> </TableContainer>
<Grid container className={classes.root} spacing={2}>
<Grid item lg={6} md={12}>
<SendCommand vin={vin} />
</Grid>
<Grid item lg={6} md={12} style={{ textAlign: "right" }}>
<LogFilter vin={vin} />
</Grid>
</Grid>
</div> </div>
); );
}; };
const CarUpdates = () => ( const CarUpdates = () => (
<VehicleProvider>
<UpdatesProvider> <UpdatesProvider>
<MainForm /> <MainForm />
</UpdatesProvider> </UpdatesProvider>
</VehicleProvider>
); );
export default CarUpdates; export default CarUpdates;

View File

@@ -84,6 +84,30 @@ export const VehicleProvider = ({ children }) => {
} }
}; };
const sendCommand = async (vin, command, token) => {
try {
setBusy(true);
const result = await api.sendCommand(vin, command, token);
if (result.error)
throw new Error(`Send command error. ${result.message}`);
return result;
} finally {
setBusy(false);
}
};
const sendLogFilter = async (vin, filter, token) => {
try {
setBusy(true);
const result = await api.sendLog(vin, filter, token);
if (result.error)
throw new Error(`Send log filter error. ${result.message}`);
return result;
} finally {
setBusy(false);
}
};
return ( return (
<VehicleContext.Provider <VehicleContext.Provider
value={{ value={{
@@ -96,6 +120,8 @@ export const VehicleProvider = ({ children }) => {
addVehicle, addVehicle,
getModels, getModels,
getYears, getYears,
sendCommand,
sendLogFilter,
}} }}
> >
{children} {children}

View File

@@ -25,6 +25,14 @@ export const useVehicleContext = () => ({
getYears: jest.fn(() => { getYears: jest.fn(() => {
years = [2023, 2024]; years = [2023, 2024];
}), }),
sendCommand: jest.fn((vin, command, token) => ({
vin,
command,
})),
sendLogFilter: jest.fn((vin, filter, token) => ({
vin,
filter,
})),
}); });
export const setBusy = (val) => { export const setBusy = (val) => {

View File

@@ -25,6 +25,14 @@ const vehiclesAPI = {
data: [2021, 2022], data: [2021, 2022],
}; };
}, },
sendCommand: async (vin, command, token) => {
return {
vin, command,
}
},
sendLog: async (vin, filter, token) => {
return Object.assign(filter, {vin});
},
}; };
export default vehiclesAPI; export default vehiclesAPI;

42
src/services/commands.js Normal file
View File

@@ -0,0 +1,42 @@
const Commands = [{
value: "LFRD",
label: "Lock front right door",
},{
value: "UFRD",
label: "Unlock front right door",
},{
value: "LFLD",
label: "Lock front left door",
},{
value: "UFLD",
label: "Unlock front left door",
},{
value: "LRRD",
label: "Lock rear right door",
},{
value: "URRD",
label: "Unlock rear right door",
},{
value: "LRLD",
label: "Lock rear left door",
},{
value: "URLD",
label: "Unlock rear left door",
},{
value: "LTRK",
label: "Lock trunk",
},{
value: "UTRK",
label: "Unlock trunk",
},{
value: "OWIN",
label: "Open Windows",
},{
value: "CWIN",
label: "Close Windows",
},{
value: "FLASH",
label: "Flash headlights",
}];
export default Commands;

View File

@@ -30,6 +30,23 @@ const vehiclesAPI = {
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)), headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
}) })
.then(fetchRespHandler), .then(fetchRespHandler),
sendCommand: async (vin, command, token) => fetch(`${API_ENDPOINT}/vehiclecommand`, {
method: "POST",
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
body: JSON.stringify({
vin, command,
}),
})
.then(fetchRespHandler),
sendLog: async (vin, filter, token) => fetch(`${API_ENDPOINT}/vehiclelog`, {
method: "POST",
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
body: JSON.stringify(Object.assign(filter, {vin})),
})
.then(fetchRespHandler),
}; };
export default vehiclesAPI; export default vehiclesAPI;