Merge branch 'release/0.0.3'
This commit is contained in:
20
package-lock.json
generated
20
package-lock.json
generated
@@ -33,6 +33,7 @@
|
|||||||
"react-router-dom": "^5.3.0",
|
"react-router-dom": "^5.3.0",
|
||||||
"react-router-hash-link": "^2.4.3",
|
"react-router-hash-link": "^2.4.3",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
|
"usehooks-ts": "^2.7.1",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -16432,6 +16433,19 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/usehooks-ts": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-DeLqSnGg9VvpwPZA+6lKVURJKM9EBu7bbIXuYclQ9COO3w4lacnJa0uP0iJbC/lAmY7GlmPinjZfGNNmDTlUpg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.15.0",
|
||||||
|
"npm": ">=8"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@@ -29270,6 +29284,12 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"usehooks-ts": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-DeLqSnGg9VvpwPZA+6lKVURJKM9EBu7bbIXuYclQ9COO3w4lacnJa0uP0iJbC/lAmY7GlmPinjZfGNNmDTlUpg==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"react-router-dom": "^5.3.0",
|
"react-router-dom": "^5.3.0",
|
||||||
"react-router-hash-link": "^2.4.3",
|
"react-router-hash-link": "^2.4.3",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
|
"usehooks-ts": "^2.7.1",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -67,9 +68,9 @@
|
|||||||
"coverageThreshold": {
|
"coverageThreshold": {
|
||||||
"global": {
|
"global": {
|
||||||
"branches": 39,
|
"branches": 39,
|
||||||
"functions": 45.5,
|
"functions": 47,
|
||||||
"lines": 50,
|
"lines": 55,
|
||||||
"statements": 49
|
"statements": 55
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"coverageReporters": [
|
"coverageReporters": [
|
||||||
|
|||||||
@@ -3311,7 +3311,7 @@ exports[`App Route /packages authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div>
|
<span>
|
||||||
<a
|
<a
|
||||||
class=""
|
class=""
|
||||||
href="/packages"
|
href="/packages"
|
||||||
@@ -3329,8 +3329,7 @@ exports[`App Route /packages authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div />
|
</span>
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -3460,6 +3459,7 @@ exports[`App Route /packages authenticated 1`] = `
|
|||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
<div />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
@@ -6015,7 +6015,7 @@ exports[`App Route /vehicle-add authenticated 1`] = `
|
|||||||
class="PrivateSwitchBase-input-0"
|
class="PrivateSwitchBase-input-0"
|
||||||
name="log-level-group"
|
name="log-level-group"
|
||||||
type="radio"
|
type="radio"
|
||||||
value="warn"
|
value="warning"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="PrivateRadioButtonIcon-root-0"
|
class="PrivateRadioButtonIcon-root-0"
|
||||||
@@ -6049,7 +6049,7 @@ exports[`App Route /vehicle-add authenticated 1`] = `
|
|||||||
<span
|
<span
|
||||||
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
||||||
>
|
>
|
||||||
Warn
|
Warning
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
@@ -6918,6 +6918,24 @@ exports[`App Route /vehicle-status authenticated 1`] = `
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
aria-controls="tabpanel-6"
|
||||||
|
aria-selected="false"
|
||||||
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit"
|
||||||
|
id="tab-6"
|
||||||
|
role="tab"
|
||||||
|
tabindex="-1"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTab-wrapper"
|
||||||
|
>
|
||||||
|
Fleets
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="PrivateTabIndicator-root-0 PrivateTabIndicator-colorSecondary-0 MuiTabs-indicator"
|
class="PrivateTabIndicator-root-0 PrivateTabIndicator-colorSecondary-0 MuiTabs-indicator"
|
||||||
@@ -7089,6 +7107,13 @@ exports[`App Route /vehicle-status authenticated 1`] = `
|
|||||||
id="tabpanel-5"
|
id="tabpanel-5"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
aria-labelledby="tab-6"
|
||||||
|
class="makeStyles-fullWidth-0"
|
||||||
|
hidden=""
|
||||||
|
id="tabpanel-6"
|
||||||
|
role="tabpanel"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ const PAGE_SIZE = "CAN_FILTER_TABLE_PAGE_SIZE";
|
|||||||
|
|
||||||
const MainForm = ({ vin }) => {
|
const MainForm = ({ vin }) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const [search, onSearch] = useState("");
|
||||||
const [pageSize, setPageSize] = useLocalStorage(PAGE_SIZE, 10);
|
const [pageSize, setPageSize] = useLocalStorage(PAGE_SIZE, 10);
|
||||||
const [pageIndex, setPageIndex] = useState(0);
|
const [pageIndex, setPageIndex] = useState(0);
|
||||||
const [orderBy, setOrderBy] = useState("id");
|
const [orderBy, setOrderBy] = useState("id");
|
||||||
@@ -68,6 +69,7 @@ const MainForm = ({ vin }) => {
|
|||||||
await getFilters(
|
await getFilters(
|
||||||
vin,
|
vin,
|
||||||
{
|
{
|
||||||
|
search,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
offset: pageSize * pageIndex,
|
offset: pageSize * pageIndex,
|
||||||
order: `${orderBy} ${order}`,
|
order: `${orderBy} ${order}`,
|
||||||
@@ -80,7 +82,7 @@ const MainForm = ({ vin }) => {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [vin, token, pageIndex, pageSize, orderBy, order]);
|
}, [vin, token, pageIndex, pageSize, orderBy, order, search]);
|
||||||
|
|
||||||
const handleChangePageIndex = (event, newIndex) => {
|
const handleChangePageIndex = (event, newIndex) => {
|
||||||
setPageIndex(newIndex);
|
setPageIndex(newIndex);
|
||||||
@@ -166,7 +168,7 @@ const MainForm = ({ vin }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item md={8} className={classes.textCenterAlign}>
|
<Grid item md={8} className={classes.textCenterAlign}>
|
||||||
<SearchField classes={classes} />
|
<SearchField classes={classes} onSearch={onSearch}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Table>
|
<Table>
|
||||||
|
|||||||
@@ -388,7 +388,7 @@ exports[`VehicleAddForm Render 1`] = `
|
|||||||
class="PrivateSwitchBase-input-0"
|
class="PrivateSwitchBase-input-0"
|
||||||
name="log-level-group"
|
name="log-level-group"
|
||||||
type="radio"
|
type="radio"
|
||||||
value="warn"
|
value="warning"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="PrivateRadioButtonIcon-root-0"
|
class="PrivateRadioButtonIcon-root-0"
|
||||||
@@ -422,7 +422,7 @@ exports[`VehicleAddForm Render 1`] = `
|
|||||||
<span
|
<span
|
||||||
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
||||||
>
|
>
|
||||||
Warn
|
Warning
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ const MainForm = () => {
|
|||||||
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
||||||
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
||||||
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
||||||
<FormControlLabel value="warn" control={<Radio />} label="Warn" />
|
<FormControlLabel value="warning" control={<Radio />} label="Warning" />
|
||||||
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
||||||
<FormControlLabel value="critical" control={<Radio />} label="Critical" />
|
<FormControlLabel value="critical" control={<Radio />} label="Critical" />
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const Main = ({ vin }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CANSignals = (props) => (
|
const CANSignals = (props) => (
|
||||||
<CANSignalProvider>
|
<CANSignalProvider {...{token:props.token}}>
|
||||||
<Main {...props} />
|
<Main {...props} />
|
||||||
</CANSignalProvider>
|
</CANSignalProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
39
src/components/Cars/Status/CANSignalsTab.test.jsx
Normal file
39
src/components/Cars/Status/CANSignalsTab.test.jsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import addSnapshotSerializer from "../../../utils/snapshot";
|
||||||
|
|
||||||
|
jest.mock("../../Contexts/VehicleContext");
|
||||||
|
jest.mock("../../Contexts/StatusContext");
|
||||||
|
jest.mock("../../Contexts/UserContext");
|
||||||
|
jest.mock("@material-ui/core/utils/unstable_useId", () =>
|
||||||
|
jest.fn().mockReturnValue("mui-test-id")
|
||||||
|
);
|
||||||
|
|
||||||
|
import { render, waitFor } from "@testing-library/react";
|
||||||
|
import { BrowserRouter } from "react-router-dom";
|
||||||
|
import CANSignalsTab from "./CANSignalsTab";
|
||||||
|
import {setToken} from "../../Contexts/UserContext";
|
||||||
|
import {TEST_AUTH_OBJECT} from "../../../utils/testing";
|
||||||
|
|
||||||
|
const renderCANSignalsTab = async () => {
|
||||||
|
const { container } = render(
|
||||||
|
<BrowserRouter>
|
||||||
|
<CANSignalsTab vin="TESTVIN1234567890" token="token"/>
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
await waitFor(() => {
|
||||||
|
/* render */
|
||||||
|
});
|
||||||
|
return container;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("CANSignalsTab", () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
addSnapshotSerializer(expect);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Render", async () => {
|
||||||
|
setToken(TEST_AUTH_OBJECT);
|
||||||
|
const container = await renderCANSignalsTab();
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
@@ -48,6 +48,9 @@ const Main = (props) => {
|
|||||||
<div>
|
<div>
|
||||||
<b>Connected</b>: {carState.online.toString()}
|
<b>Connected</b>: {carState.online.toString()}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>ICC Connected</b>: {carState?.online_hmi.toString()}
|
||||||
|
</div>
|
||||||
<DigitalTwin {...carState} />
|
<DigitalTwin {...carState} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
140
src/components/Cars/Status/FleetsTab.jsx
Normal file
140
src/components/Cars/Status/FleetsTab.jsx
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import useStyles from "../../useStyles";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import {Grid, Table, TableBody, TableCell, TableFooter, TablePagination, TableRow, Typography} from "@material-ui/core";
|
||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {useVehicleContext, VehicleProvider} from "../../Contexts/VehicleContext";
|
||||||
|
import SearchField from "../../Controls/SearchField";
|
||||||
|
import {useLocalStorage} from "../../useLocalStorage";
|
||||||
|
import {useStatusContext} from "../../Contexts/StatusContext";
|
||||||
|
import {useUserContext} from "../../Contexts/UserContext";
|
||||||
|
import {logger} from "../../../services/monitoring";
|
||||||
|
import TableHeaderSortable from "../../Table/HeaderSortable";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
|
const PAGE_SIZE = "VEHICLE_FLEETS_TABLE_PAGE_SIZE";
|
||||||
|
|
||||||
|
const tableColumns = [
|
||||||
|
{
|
||||||
|
id: "fleet",
|
||||||
|
label: "CAN ID"
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const MainForm = (props) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
const {vin} = props;
|
||||||
|
|
||||||
|
const [search, onSearch] = useState("");
|
||||||
|
const [pageSize, setPageSize] = useLocalStorage(PAGE_SIZE, 10);
|
||||||
|
const [pageIndex, setPageIndex] = useState(0);
|
||||||
|
const [orderBy, setOrderBy] = useState("id");
|
||||||
|
const [order, setOrder] = useState("desc");
|
||||||
|
const {setMessage} = useStatusContext();
|
||||||
|
const {token: {idToken: {jwtToken: token}}} = useUserContext();
|
||||||
|
const {getFleets, fleets, totalFleets} = useVehicleContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
if (!vin || !token) return;
|
||||||
|
await getFleets(
|
||||||
|
vin,
|
||||||
|
{
|
||||||
|
search,
|
||||||
|
limit: pageSize,
|
||||||
|
offset: pageSize * pageIndex,
|
||||||
|
order: `${orderBy} ${order}`,
|
||||||
|
},
|
||||||
|
token
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
setMessage(e.message);
|
||||||
|
logger.warn(e.stack);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [vin, token, pageIndex, pageSize, orderBy, order, search]);
|
||||||
|
|
||||||
|
const handleChangePageIndex = (event, newIndex) => {
|
||||||
|
setPageIndex(newIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangePageSize = (event) => {
|
||||||
|
setPageSize(parseInt(event.target.value, 10));
|
||||||
|
setPageIndex(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSort = (event, property) => {
|
||||||
|
try {
|
||||||
|
if (property === orderBy) {
|
||||||
|
if (order === "asc") {
|
||||||
|
setOrder("desc");
|
||||||
|
} else {
|
||||||
|
setOrder("asc");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setOrderBy(property);
|
||||||
|
setOrder("asc");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.warn(e.stack);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={clsx(classes.paper, classes.tableSize)}>
|
||||||
|
<Typography variant="h6">Fleets</Typography>
|
||||||
|
<Grid container className={classes.textCenterAlign} spacing={2} justifyContent="center">
|
||||||
|
<Grid item md={3} className={classes.textCenterAlign}>
|
||||||
|
<SearchField classes={classes} onSearch={onSearch}/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Table style={{width:"auto"}}>
|
||||||
|
<TableHeaderSortable
|
||||||
|
classes={classes}
|
||||||
|
orderBy={orderBy}
|
||||||
|
order={order}
|
||||||
|
columnData={tableColumns}
|
||||||
|
onSortRequest={handleSort}
|
||||||
|
/>
|
||||||
|
<TableBody>
|
||||||
|
{fleets.map((row) => (
|
||||||
|
<TableRow key={row} width="200px">
|
||||||
|
<TableCell align="center">
|
||||||
|
<Link to={`/fleet/${row}`}>{row}</Link>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
<TableFooter>
|
||||||
|
<TableRow>
|
||||||
|
<TablePagination
|
||||||
|
rowsPerPageOptions={[5, 10, 25, 100]}
|
||||||
|
colSpan={8}
|
||||||
|
count={totalFleets}
|
||||||
|
rowsPerPage={pageSize}
|
||||||
|
page={pageIndex}
|
||||||
|
SelectProps={{
|
||||||
|
inputProps: {"aria-label": "rows per page"},
|
||||||
|
native: true,
|
||||||
|
}}
|
||||||
|
onPageChange={handleChangePageIndex}
|
||||||
|
onRowsPerPageChange={handleChangePageSize}
|
||||||
|
/>
|
||||||
|
</TableRow>
|
||||||
|
</TableFooter>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const FleetsTab = (props) => {
|
||||||
|
return (
|
||||||
|
<VehicleProvider>
|
||||||
|
<MainForm {...props}/>
|
||||||
|
</VehicleProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default FleetsTab;
|
||||||
47
src/components/Cars/Status/FleetsTab.test.jsx
Normal file
47
src/components/Cars/Status/FleetsTab.test.jsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
jest.mock("../../Contexts/VehicleContext");
|
||||||
|
jest.mock("../../Contexts/StatusContext");
|
||||||
|
jest.mock("../../Contexts/UserContext");
|
||||||
|
jest.mock("@material-ui/core/utils/unstable_useId", () =>
|
||||||
|
jest.fn().mockReturnValue("mui-test-id")
|
||||||
|
);
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import {render, waitFor} from "@testing-library/react";
|
||||||
|
import { BrowserRouter } from "react-router-dom";
|
||||||
|
|
||||||
|
import {StatusProvider} from "../../Contexts/StatusContext";
|
||||||
|
import {VehicleProvider} from "../../Contexts/VehicleContext";
|
||||||
|
import {setToken, UserProvider} from "../../Contexts/UserContext";
|
||||||
|
import {TEST_AUTH_OBJECT} from "../../../utils/testing";
|
||||||
|
import addSnapshotSerializer from "../../../utils/snapshot";
|
||||||
|
import FleetsTab from "./FleetsTab";
|
||||||
|
|
||||||
|
const renderFleetsTab = async () => {
|
||||||
|
const {container} = render(
|
||||||
|
<StatusProvider>
|
||||||
|
<UserProvider>
|
||||||
|
<VehicleProvider>
|
||||||
|
<BrowserRouter>
|
||||||
|
<FleetsTab vin="TESTVIN1234567890"/>
|
||||||
|
</BrowserRouter>
|
||||||
|
</VehicleProvider>
|
||||||
|
</UserProvider>
|
||||||
|
</StatusProvider>
|
||||||
|
);
|
||||||
|
await waitFor(() => {
|
||||||
|
/* render */
|
||||||
|
});
|
||||||
|
return container;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("FleetsTab", () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
addSnapshotSerializer(expect);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Render", async () => {
|
||||||
|
setToken(TEST_AUTH_OBJECT);
|
||||||
|
const container = await renderFleetsTab();
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`CANSignalsTab Render 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
data-testid="mocked-vehicleprovider"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="makeStyles-paper-0 makeStyles-tableSize-0"
|
||||||
|
>
|
||||||
|
<h6
|
||||||
|
class="MuiTypography-root MuiTypography-h6"
|
||||||
|
style="padding-bottom: 10px;"
|
||||||
|
>
|
||||||
|
CAN Signals
|
||||||
|
</h6>
|
||||||
|
<h3>
|
||||||
|
Loading...
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
@@ -27,6 +27,13 @@ exports[`DigitalTwinTab Render 1`] = `
|
|||||||
:
|
:
|
||||||
false
|
false
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>
|
||||||
|
ICC Connected
|
||||||
|
</b>
|
||||||
|
:
|
||||||
|
true
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<b>
|
<b>
|
||||||
|
|||||||
280
src/components/Cars/Status/__snapshots__/FleetsTab.test.jsx.snap
Normal file
280
src/components/Cars/Status/__snapshots__/FleetsTab.test.jsx.snap
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`FleetsTab Render 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
data-testid="mocked-statusprovider"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="mocked-userprovider"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="mocked-vehicleprovider"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="mocked-vehicleprovider"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="makeStyles-paper-0 makeStyles-tableSize-0"
|
||||||
|
>
|
||||||
|
<h6
|
||||||
|
class="MuiTypography-root MuiTypography-h6"
|
||||||
|
>
|
||||||
|
Fleets
|
||||||
|
</h6>
|
||||||
|
<div
|
||||||
|
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-container MuiGrid-spacing-xs-2 MuiGrid-justify-content-xs-center"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiGrid-root makeStyles-textCenterAlign-0 MuiGrid-item MuiGrid-grid-md-3"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiFormControl-root makeStyles-margin-0 makeStyles-fullWidth-0"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated"
|
||||||
|
data-shrink="false"
|
||||||
|
for="search"
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="MuiInputBase-root MuiInput-root MuiInput-underline MuiInputBase-formControl MuiInput-formControl MuiInputBase-adornedEnd"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-invalid="false"
|
||||||
|
class="MuiInputBase-input MuiInput-input MuiInputBase-inputAdornedEnd"
|
||||||
|
id="search"
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="MuiInputAdornment-root MuiInputAdornment-positionEnd"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-label="search"
|
||||||
|
class="MuiButtonBase-root MuiIconButton-root"
|
||||||
|
tabindex="0"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table
|
||||||
|
class="MuiTable-root"
|
||||||
|
style="width: auto;"
|
||||||
|
>
|
||||||
|
<thead
|
||||||
|
class="MuiTableHead-root"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root MuiTableRow-head"
|
||||||
|
>
|
||||||
|
<th
|
||||||
|
class="MuiTableCell-root MuiTableCell-head MuiTableCell-alignCenter"
|
||||||
|
scope="col"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiTableSortLabel-root"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
CAN ID
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root MuiTableSortLabel-icon MuiTableSortLabel-iconDirectionAsc"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody
|
||||||
|
class="MuiTableBody-root"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root"
|
||||||
|
width="200px"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="/fleet/fleet1"
|
||||||
|
>
|
||||||
|
fleet1
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root"
|
||||||
|
width="200px"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="/fleet/fleet2"
|
||||||
|
>
|
||||||
|
fleet2
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot
|
||||||
|
class="MuiTableFooter-root"
|
||||||
|
>
|
||||||
|
<tr
|
||||||
|
class="MuiTableRow-root MuiTableRow-footer"
|
||||||
|
>
|
||||||
|
<td
|
||||||
|
class="MuiTableCell-root MuiTableCell-footer MuiTablePagination-root"
|
||||||
|
colspan="8"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiToolbar-root MuiToolbar-regular MuiTablePagination-toolbar MuiToolbar-gutters"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiTablePagination-spacer"
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
class="MuiTypography-root MuiTablePagination-caption MuiTypography-body2 MuiTypography-colorInherit"
|
||||||
|
>
|
||||||
|
Rows per page:
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
class="MuiInputBase-root MuiTablePagination-input MuiTablePagination-selectRoot"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
aria-label="rows per page"
|
||||||
|
class="MuiSelect-root MuiSelect-select MuiTablePagination-select MuiInputBase-input"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
class="MuiTablePagination-menuItem"
|
||||||
|
value="5"
|
||||||
|
>
|
||||||
|
5
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
class="MuiTablePagination-menuItem"
|
||||||
|
value="10"
|
||||||
|
>
|
||||||
|
10
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
class="MuiTablePagination-menuItem"
|
||||||
|
value="25"
|
||||||
|
>
|
||||||
|
25
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
class="MuiTablePagination-menuItem"
|
||||||
|
value="100"
|
||||||
|
>
|
||||||
|
100
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root MuiSelect-icon MuiTablePagination-selectIcon"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7 10l5 5 5-5z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
class="MuiTypography-root MuiTablePagination-caption MuiTypography-body2 MuiTypography-colorInherit"
|
||||||
|
>
|
||||||
|
1-2 of 2
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
class="MuiTablePagination-actions"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-label="Previous page"
|
||||||
|
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit Mui-disabled Mui-disabled"
|
||||||
|
disabled=""
|
||||||
|
tabindex="-1"
|
||||||
|
title="Previous page"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
aria-label="Next page"
|
||||||
|
class="MuiButtonBase-root MuiIconButton-root MuiIconButton-colorInherit Mui-disabled Mui-disabled"
|
||||||
|
disabled=""
|
||||||
|
tabindex="-1"
|
||||||
|
title="Next page"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiIconButton-label"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="MuiSvgIcon-root"
|
||||||
|
focusable="false"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
@@ -137,6 +137,24 @@ exports[`CarStatus Render 1`] = `
|
|||||||
class="MuiTouchRipple-root"
|
class="MuiTouchRipple-root"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
aria-controls="tabpanel-6"
|
||||||
|
aria-selected="false"
|
||||||
|
class="MuiButtonBase-root MuiTab-root MuiTab-textColorInherit"
|
||||||
|
id="tab-6"
|
||||||
|
role="tab"
|
||||||
|
tabindex="-1"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTab-wrapper"
|
||||||
|
>
|
||||||
|
Fleets
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="PrivateTabIndicator-root-0 PrivateTabIndicator-colorSecondary-0 MuiTabs-indicator"
|
class="PrivateTabIndicator-root-0 PrivateTabIndicator-colorSecondary-0 MuiTabs-indicator"
|
||||||
@@ -255,6 +273,13 @@ exports[`CarStatus Render 1`] = `
|
|||||||
id="tabpanel-5"
|
id="tabpanel-5"
|
||||||
role="tabpanel"
|
role="tabpanel"
|
||||||
/>
|
/>
|
||||||
|
<div
|
||||||
|
aria-labelledby="tab-6"
|
||||||
|
class="makeStyles-fullWidth-0"
|
||||||
|
hidden=""
|
||||||
|
id="tabpanel-6"
|
||||||
|
role="tabpanel"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { useStatusContext } from "../../Contexts/StatusContext";
|
|||||||
import useStyles from "../../useStyles";
|
import useStyles from "../../useStyles";
|
||||||
import CANSignalsTab from "./CANSignalsTab";
|
import CANSignalsTab from "./CANSignalsTab";
|
||||||
import RemoteCommandsTab from "./RemoteCommandsTab";
|
import RemoteCommandsTab from "./RemoteCommandsTab";
|
||||||
|
import FleetsTab from "./FleetsTab";
|
||||||
|
|
||||||
const tabHashes = ["details", "updates", "filters"];
|
const tabHashes = ["details", "updates", "filters"];
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ const CarStatus = () => {
|
|||||||
<Tab label="Digital Twin" {...tabProps(3)} />
|
<Tab label="Digital Twin" {...tabProps(3)} />
|
||||||
<Tab label="CAN Signals" {...tabProps(4)} />
|
<Tab label="CAN Signals" {...tabProps(4)} />
|
||||||
<Tab label="Remote Commands" {...tabProps(5)} />
|
<Tab label="Remote Commands" {...tabProps(5)} />
|
||||||
|
<Tab label="Fleets" {...tabProps(6)} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -92,6 +94,10 @@ const CarStatus = () => {
|
|||||||
<TabPanel value={tabIndex} index={5} className={classes.fullWidth}>
|
<TabPanel value={tabIndex} index={5} className={classes.fullWidth}>
|
||||||
<RemoteCommandsTab vin={vin} />
|
<RemoteCommandsTab vin={vin} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
|
||||||
|
<TabPanel value={tabIndex} index={6} className={classes.fullWidth}>
|
||||||
|
<FleetsTab vin={vin} />
|
||||||
|
</TabPanel>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ exports[`VehicleUpdate Render 1`] = `
|
|||||||
class="PrivateSwitchBase-input-0"
|
class="PrivateSwitchBase-input-0"
|
||||||
name="log-level-group"
|
name="log-level-group"
|
||||||
type="radio"
|
type="radio"
|
||||||
value="warn"
|
value="warning"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="PrivateRadioButtonIcon-root-0"
|
class="PrivateRadioButtonIcon-root-0"
|
||||||
@@ -424,7 +424,7 @@ exports[`VehicleUpdate Render 1`] = `
|
|||||||
<span
|
<span
|
||||||
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
||||||
>
|
>
|
||||||
Warn
|
Warning
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ const MainForm = () => {
|
|||||||
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
||||||
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
||||||
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
||||||
<FormControlLabel value="warn" control={<Radio />} label="Warn" />
|
<FormControlLabel value="warning" control={<Radio />} label="Warning" />
|
||||||
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
||||||
<FormControlLabel value="critical" control={<Radio />} label="Critical" />
|
<FormControlLabel value="critical" control={<Radio />} label="Critical" />
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { useContext, useState, useEffect } from "react";
|
import React, {useContext, useState} from "react";
|
||||||
|
|
||||||
import api from "../../services/vehiclesAPI";
|
import api from "../../services/vehiclesAPI";
|
||||||
import { useUserContext } from "./UserContext";
|
|
||||||
import { LocalDateTimeString } from "../../utils/dates";
|
import { LocalDateTimeString } from "../../utils/dates";
|
||||||
|
import {useInterval} from "usehooks-ts";
|
||||||
|
|
||||||
const CANSignalContext = React.createContext();
|
const CANSignalContext = React.createContext();
|
||||||
|
|
||||||
@@ -15,41 +15,26 @@ const BlankSignal = (msg) => ({
|
|||||||
const transformSignals = (signals) =>
|
const transformSignals = (signals) =>
|
||||||
signals
|
signals
|
||||||
.map((signal) => {
|
.map((signal) => {
|
||||||
const { Timestamp, ...Settings } = signal;
|
const { timestamp, value, name } = signal;
|
||||||
const keys = Object.keys(Settings);
|
|
||||||
|
|
||||||
return keys.map((key) => ({
|
return {
|
||||||
timestamp: LocalDateTimeString(Timestamp),
|
timestamp: LocalDateTimeString(timestamp),
|
||||||
signal: key,
|
signal: name,
|
||||||
value: Settings[key],
|
value: value,
|
||||||
}));
|
};
|
||||||
})
|
})
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
export const CANSignalProvider = ({ children }) => {
|
export const CANSignalProvider = ({ token, children }) => {
|
||||||
const {
|
|
||||||
token: {
|
|
||||||
idToken: { jwtToken: token },
|
|
||||||
},
|
|
||||||
} = useUserContext();
|
|
||||||
const [vin, setVIN] = useState(null);
|
const [vin, setVIN] = useState(null);
|
||||||
const [signals, setSignals] = useState([]);
|
const [signals, setSignals] = useState([]);
|
||||||
let delay = 500;
|
const [delay, setDelay] = useState(500);
|
||||||
|
|
||||||
useEffect(() => {
|
useInterval(
|
||||||
getCANSignals();
|
() => {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
getCANSignals()
|
||||||
}, [vin]);
|
}, vin?delay:null
|
||||||
|
)
|
||||||
useEffect(() => {
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
getCANSignals();
|
|
||||||
}, delay);
|
|
||||||
return () => {
|
|
||||||
clearTimeout(timer);
|
|
||||||
};
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [signals]);
|
|
||||||
|
|
||||||
const getCANSignals = async () => {
|
const getCANSignals = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -62,10 +47,10 @@ export const CANSignalProvider = ({ children }) => {
|
|||||||
const items = transformSignals(result.data);
|
const items = transformSignals(result.data);
|
||||||
|
|
||||||
if (items.length > 0) {
|
if (items.length > 0) {
|
||||||
delay = 500;
|
setDelay(500);
|
||||||
setSignals(items);
|
setSignals(items);
|
||||||
} else {
|
} else {
|
||||||
delay = 1000;
|
setDelay(1000);
|
||||||
setSignals([BlankSignal("No signals")]);
|
setSignals([BlankSignal("No signals")]);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
75
src/components/Contexts/CANSignalsContext.test.jsx
Normal file
75
src/components/Contexts/CANSignalsContext.test.jsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
jest.mock("../../services/vehiclesAPI");
|
||||||
|
|
||||||
|
import {
|
||||||
|
render,
|
||||||
|
cleanup,
|
||||||
|
screen,
|
||||||
|
fireEvent,
|
||||||
|
waitFor,
|
||||||
|
act,
|
||||||
|
} from "@testing-library/react";
|
||||||
|
import {CANSignalProvider, useCANSignalContext} from "./CANSignalsContext";
|
||||||
|
|
||||||
|
const checkSignalsResults = (filters) => {
|
||||||
|
expect(screen.getByTestId("signals").innerHTML).toEqual(filters);
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("CANSignalsContext", () => {
|
||||||
|
describe("getSignals", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers("setInterval");
|
||||||
|
const TestComp = () => {
|
||||||
|
const { signals, setVIN } = useCANSignalContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div data-testid="signals">{JSON.stringify(signals)}</div>
|
||||||
|
<button
|
||||||
|
data-testid="getSignals"
|
||||||
|
onClick={()=>{setVIN("TESTVIN1234567890")}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
render(
|
||||||
|
<CANSignalProvider>
|
||||||
|
<TestComp />
|
||||||
|
</CANSignalProvider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initial state", () => {
|
||||||
|
checkSignalsResults("[]");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("getSignals", async () => {
|
||||||
|
// eslint-disable-next-line testing-library/no-unnecessary-act
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByTestId("getSignals"));
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(screen.getByTestId("signals").innerHTML).toBe("[]")
|
||||||
|
);
|
||||||
|
jest.advanceTimersByTime(501);
|
||||||
|
})
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
return expect(screen.getByTestId("signals").innerHTML).not.toBe("[]");
|
||||||
|
} );
|
||||||
|
|
||||||
|
checkSignalsResults(JSON.stringify(expectedSignalsData));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const expectedSignalsData = [
|
||||||
|
{
|
||||||
|
timestamp: "7/14/2021 8:09:40 PM",
|
||||||
|
signal: "signal",
|
||||||
|
value: 123
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -139,7 +139,7 @@ describe("FleetContext", () => {
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
add({
|
add({
|
||||||
name: "EU-WEST",
|
name: "EU-WEST",
|
||||||
log_level: "warn",
|
log_level: "warning",
|
||||||
canbus: { enabled: false },
|
canbus: { enabled: false },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -219,7 +219,7 @@ describe("FleetContext", () => {
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
update({
|
update({
|
||||||
name: "EU-WEST",
|
name: "EU-WEST",
|
||||||
log_level: "warn",
|
log_level: "warning",
|
||||||
canbus: { enabled: false },
|
canbus: { enabled: false },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -782,7 +782,7 @@ const expectedFleetsData = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "US-CENTRAL",
|
name: "US-CENTRAL",
|
||||||
log_level: "warn",
|
log_level: "warning",
|
||||||
canbus: {
|
canbus: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
data_logger_enabled: false,
|
data_logger_enabled: false,
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
const [vehicle, setVehicle] = useState({});
|
const [vehicle, setVehicle] = useState({});
|
||||||
const [vehicles, setVehicles] = useState([]);
|
const [vehicles, setVehicles] = useState([]);
|
||||||
const [totalVehicles, setTotalVehicles] = useState(0);
|
const [totalVehicles, setTotalVehicles] = useState(0);
|
||||||
|
const [fleets, setFleets] = useState([]);
|
||||||
|
const [totalFleets, setTotalFleets] = useState(0);
|
||||||
const [models, setModels] = useState([]);
|
const [models, setModels] = useState([]);
|
||||||
const [years, setYears] = useState([]);
|
const [years, setYears] = useState([]);
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
cars.forEach((car) => {
|
cars.forEach((car) => {
|
||||||
car.connected = result[car.vin] || false;
|
car.connected = result[car.vin] || false;
|
||||||
|
car.connectedHMI = result[`2:${car.vin}`] || false;
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e.stack);
|
logger.error(e.stack);
|
||||||
@@ -219,6 +222,25 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getFleets = async (vin, search, token) => {
|
||||||
|
try {
|
||||||
|
setBusy(true);
|
||||||
|
validateVIN(vin);
|
||||||
|
|
||||||
|
const result = await api.getFleets(vin, search, token);
|
||||||
|
if (result.error) {
|
||||||
|
setFleets([]);
|
||||||
|
throw new Error(`Get Fleets of vehicle`)
|
||||||
|
}
|
||||||
|
setFleets(result.data ?? []);
|
||||||
|
if (result.total) {
|
||||||
|
setTotalFleets(result.total);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setBusy(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VehicleContext.Provider
|
<VehicleContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@@ -228,6 +250,8 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
vehicle,
|
vehicle,
|
||||||
vehicles,
|
vehicles,
|
||||||
years,
|
years,
|
||||||
|
fleets,
|
||||||
|
totalFleets,
|
||||||
addVehicle,
|
addVehicle,
|
||||||
deleteVehicle,
|
deleteVehicle,
|
||||||
getConnections,
|
getConnections,
|
||||||
@@ -241,6 +265,7 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
getVehicles,
|
getVehicles,
|
||||||
sendCommand,
|
sendCommand,
|
||||||
updateVehicle,
|
updateVehicle,
|
||||||
|
getFleets,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -13,19 +13,64 @@ import { StatusProvider, useStatusContext } from "./StatusContext";
|
|||||||
const checkVehicleResult = (error, busy, vehicle) => {
|
const checkVehicleResult = (error, busy, vehicle) => {
|
||||||
checkBaseResults(error, busy);
|
checkBaseResults(error, busy);
|
||||||
expect(screen.getByTestId("vehicle").innerHTML).toEqual(vehicle);
|
expect(screen.getByTestId("vehicle").innerHTML).toEqual(vehicle);
|
||||||
}
|
};
|
||||||
|
|
||||||
const checkVehiclesResult = (error, busy, vehicles) => {
|
const checkVehiclesResult = (error, busy, vehicles) => {
|
||||||
checkBaseResults(error, busy);
|
checkBaseResults(error, busy);
|
||||||
expect(screen.getByTestId("vehicles").innerHTML).toEqual(vehicles);
|
expect(screen.getByTestId("vehicles").innerHTML).toEqual(vehicles);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checkFleetsResult = (error, busy, fleets) => {
|
||||||
|
checkBaseResults(error, busy);
|
||||||
|
expect(screen.getByTestId("fleets").innerHTML).toEqual(fleets);
|
||||||
|
};
|
||||||
|
|
||||||
const checkBaseResults = (error, busy) => {
|
const checkBaseResults = (error, busy) => {
|
||||||
expect(screen.getByTestId("error").innerHTML).toEqual(error);
|
expect(screen.getByTestId("error").innerHTML).toEqual(error);
|
||||||
expect(screen.getByTestId("busy").innerHTML).toEqual(busy);
|
expect(screen.getByTestId("busy").innerHTML).toEqual(busy);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("VehicleContext", () => {
|
describe("VehicleContext", () => {
|
||||||
|
describe("getFleets", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const TestComp = () => {
|
||||||
|
const { busy, error, fleets, getFleets } = useVehicleContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div data-testid="error">{error}</div>
|
||||||
|
<div data-testid="busy">{busy.toString()}</div>
|
||||||
|
<div data-testid="fleets">{JSON.stringify(fleets)}</div>
|
||||||
|
<button
|
||||||
|
data-testid="getFleets"
|
||||||
|
onClick={() => getFleets("3C4PDCBG0ET127145")}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
render(
|
||||||
|
<VehicleProvider>
|
||||||
|
<TestComp />
|
||||||
|
</VehicleProvider>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Initial state", () => {
|
||||||
|
checkFleetsResult("", "false", "[]");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("getFleets", async () => {
|
||||||
|
fireEvent.click(screen.getByTestId("getFleets"));
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(screen.getByTestId("fleets").innerHTML).not.toBe("[]")
|
||||||
|
);
|
||||||
|
checkFleetsResult("", "false", JSON.stringify(["fleet1", "fleet2"]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("getVehicles", () => {
|
describe("getVehicles", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const TestComp = () => {
|
const TestComp = () => {
|
||||||
@@ -195,12 +240,22 @@ describe("VehicleContext", () => {
|
|||||||
<>
|
<>
|
||||||
<div data-testid="error">{message}</div>
|
<div data-testid="error">{message}</div>
|
||||||
<div data-testid="busy">{busy.toString()}</div>
|
<div data-testid="busy">{busy.toString()}</div>
|
||||||
<button data-testid="updateVehicleNull" onClick={() => update(null)} />
|
<button
|
||||||
<button data-testid="updateVehicleNoVIN" onClick={() => update({})} />
|
data-testid="updateVehicleNull"
|
||||||
|
onClick={() => update(null)}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
data-testid="updateVehicleNoVIN"
|
||||||
|
onClick={() => update({})}
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
data-testid="updateVehicle"
|
data-testid="updateVehicle"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
update({ vin: "3C4PDCBG0ET127145", log_level: "warn", canbus: { enabled: false } })
|
update({
|
||||||
|
vin: "3C4PDCBG0ET127145",
|
||||||
|
log_level: "warning",
|
||||||
|
canbus: { enabled: false },
|
||||||
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
@@ -265,13 +320,17 @@ describe("VehicleContext", () => {
|
|||||||
<>
|
<>
|
||||||
<div data-testid="error">{message}</div>
|
<div data-testid="error">{message}</div>
|
||||||
<div data-testid="busy">{busy.toString()}</div>
|
<div data-testid="busy">{busy.toString()}</div>
|
||||||
<button data-testid="deleteVehicleNull" onClick={() => deleteV(null)} />
|
<button
|
||||||
<button data-testid="deleteVehicleNonexistent" onClick={() => deleteV("11111111111111111")} />
|
data-testid="deleteVehicleNull"
|
||||||
|
onClick={() => deleteV(null)}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
data-testid="deleteVehicleNonexistent"
|
||||||
|
onClick={() => deleteV("11111111111111111")}
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
data-testid="deleteVehicle"
|
data-testid="deleteVehicle"
|
||||||
onClick={() =>
|
onClick={() => deleteV("3C4PDCBG0ET127145")}
|
||||||
deleteV("3C4PDCBG0ET127145")
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@@ -321,7 +380,7 @@ describe("VehicleContext", () => {
|
|||||||
describe("sendCommand", () => {
|
describe("sendCommand", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const TestComp = () => {
|
const TestComp = () => {
|
||||||
const {busy, sendCommand} = useVehicleContext();
|
const { busy, sendCommand } = useVehicleContext();
|
||||||
const { message, setMessage } = useStatusContext();
|
const { message, setMessage } = useStatusContext();
|
||||||
|
|
||||||
const sendC = async (vin, command) => {
|
const sendC = async (vin, command) => {
|
||||||
@@ -336,18 +395,31 @@ describe("VehicleContext", () => {
|
|||||||
<>
|
<>
|
||||||
<div data-testid="error">{message}</div>
|
<div data-testid="error">{message}</div>
|
||||||
<div data-testid="busy">{busy.toString()}</div>
|
<div data-testid="busy">{busy.toString()}</div>
|
||||||
<button data-testid="sendCommandNullVin" onClick={() => sendC(null, {command:"doors_lock"})} />
|
<button
|
||||||
<button data-testid="sendCommandNonexistentVin" onClick={() => sendC(["11111111111111111"], {command:"doors_lock"})} />
|
data-testid="sendCommandNullVin"
|
||||||
|
onClick={() => sendC(null, { command: "doors_lock" })}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
data-testid="sendCommandNonexistentVin"
|
||||||
|
onClick={() =>
|
||||||
|
sendC(["11111111111111111"], { command: "doors_lock" })
|
||||||
|
}
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
data-testid="sendCommandVin"
|
data-testid="sendCommandVin"
|
||||||
onClick={() => sendC("3C4PDCBG0ET127145", {command:"doors_lock"})}
|
onClick={() =>
|
||||||
|
sendC("3C4PDCBG0ET127145", { command: "doors_lock" })
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
data-testid="sendCommandWrongCommand"
|
data-testid="sendCommandWrongCommand"
|
||||||
onClick={() => sendC("3C4PDCBG0ET127145", {command:"noSuchCommand"})}
|
onClick={() =>
|
||||||
|
sendC("3C4PDCBG0ET127145", { command: "noSuchCommand" })
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);}
|
);
|
||||||
|
};
|
||||||
render(
|
render(
|
||||||
<StatusProvider>
|
<StatusProvider>
|
||||||
<VehicleProvider>
|
<VehicleProvider>
|
||||||
@@ -364,24 +436,23 @@ describe("VehicleContext", () => {
|
|||||||
it("initial state", () => {
|
it("initial state", () => {
|
||||||
checkBaseResults("", "false");
|
checkBaseResults("", "false");
|
||||||
});
|
});
|
||||||
|
});
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const expectedFilters = [
|
const expectedFilters = [
|
||||||
{
|
{
|
||||||
can_id: "123-456",
|
can_id: "123-456",
|
||||||
interval: 789
|
interval: 789,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
can_id: "1",
|
can_id: "1",
|
||||||
interval: 1000
|
interval: 1000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
can_id: "1000",
|
can_id: "1000",
|
||||||
interval: 1
|
interval: 1,
|
||||||
}
|
},
|
||||||
]
|
];
|
||||||
|
|
||||||
const expectedVehicleData = {
|
const expectedVehicleData = {
|
||||||
vin: "3C4PDCBG0ET127145",
|
vin: "3C4PDCBG0ET127145",
|
||||||
@@ -390,9 +461,16 @@ const expectedVehicleData = {
|
|||||||
trim: "Basic",
|
trim: "Basic",
|
||||||
ecu_list: "ECUA 2.0.0, ECUB 2.1.1",
|
ecu_list: "ECUA 2.0.0, ECUB 2.1.1",
|
||||||
log_level: "info",
|
log_level: "info",
|
||||||
canbus: { enabled: true, data_logger_enabled: true, max_mem_buffer_size: 1, max_disk_buffer_size: 2, filters: expectedFilters },
|
canbus: {
|
||||||
|
enabled: true,
|
||||||
|
data_logger_enabled: true,
|
||||||
|
max_mem_buffer_size: 1,
|
||||||
|
max_disk_buffer_size: 2,
|
||||||
|
filters: expectedFilters,
|
||||||
|
},
|
||||||
connected: true,
|
connected: true,
|
||||||
}
|
connectedHMI: false,
|
||||||
|
};
|
||||||
|
|
||||||
const expectedVehiclesData = [
|
const expectedVehiclesData = [
|
||||||
{
|
{
|
||||||
@@ -402,19 +480,44 @@ const expectedVehiclesData = [
|
|||||||
trim: "Basic",
|
trim: "Basic",
|
||||||
ecu_list: "ECUA 2.0.0, ECUB 2.1.1",
|
ecu_list: "ECUA 2.0.0, ECUB 2.1.1",
|
||||||
log_level: "info",
|
log_level: "info",
|
||||||
canbus: { enabled: true, data_logger_enabled: true, max_mem_buffer_size: 1, max_disk_buffer_size: 2, filters: expectedFilters },
|
canbus: {
|
||||||
connected: true,
|
enabled: true,
|
||||||
|
data_logger_enabled: true,
|
||||||
|
max_mem_buffer_size: 1,
|
||||||
|
max_disk_buffer_size: 2,
|
||||||
|
filters: expectedFilters,
|
||||||
|
},
|
||||||
|
connected: true,
|
||||||
|
connectedHMI: false,
|
||||||
|
},
|
||||||
|
{ vin: "1G1FP87S3GN100062", connected: true, connectedHMI: false },
|
||||||
|
{
|
||||||
|
vin: "1HGCG325XYA062256",
|
||||||
|
year: 2021,
|
||||||
|
connected: true,
|
||||||
|
connectedHMI: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "1J4GZ78YXWC160024",
|
||||||
|
year: 2021,
|
||||||
|
model: "Ocean",
|
||||||
|
connected: true,
|
||||||
|
connectedHMI: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vin: "2C3CCAAG8CH222800",
|
||||||
|
model: "Ocean",
|
||||||
|
trim: "Basic",
|
||||||
|
connected: true,
|
||||||
|
connectedHMI: false,
|
||||||
},
|
},
|
||||||
{ vin: "1G1FP87S3GN100062", connected: true },
|
|
||||||
{ vin: "1HGCG325XYA062256", year: 2021, connected: true },
|
|
||||||
{ vin: "1J4GZ78YXWC160024", year: 2021, model: "Ocean", connected: true },
|
|
||||||
{ vin: "2C3CCAAG8CH222800", model: "Ocean", trim: "Basic", connected: true },
|
|
||||||
{
|
{
|
||||||
vin: "KNADM4A39C6028108",
|
vin: "KNADM4A39C6028108",
|
||||||
year: 2021,
|
year: 2021,
|
||||||
model: "Ocean",
|
model: "Ocean",
|
||||||
trim: "Basic",
|
trim: "Basic",
|
||||||
connected: true,
|
connected: true,
|
||||||
|
connectedHMI: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
vin: "1G11C5SL9FF153507",
|
vin: "1G11C5SL9FF153507",
|
||||||
@@ -422,5 +525,6 @@ const expectedVehiclesData = [
|
|||||||
model: "Ocean",
|
model: "Ocean",
|
||||||
trim: "Basic",
|
trim: "Basic",
|
||||||
connected: true,
|
connected: true,
|
||||||
|
connectedHMI: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ let fleets = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "US-CENTRAL",
|
name: "US-CENTRAL",
|
||||||
log_level: "warn",
|
log_level: "warning",
|
||||||
canbus: { enabled: false, data_logger_enabled: false, max_mem_buffer_size: 0, max_disk_buffer_size: 0 },
|
canbus: { enabled: false, data_logger_enabled: false, max_mem_buffer_size: 0, max_disk_buffer_size: 0 },
|
||||||
vehicles: ["USCENTVIN12345678", "USCENTVIN12345679", "USCENTVIN12345670"]
|
vehicles: ["USCENTVIN12345678", "USCENTVIN12345679", "USCENTVIN12345670"]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ let vehicle = {
|
|||||||
let vehicleState = {
|
let vehicleState = {
|
||||||
data: {
|
data: {
|
||||||
online: false,
|
online: false,
|
||||||
|
online_hmi: true,
|
||||||
battery: {
|
battery: {
|
||||||
percent: 95,
|
percent: 95,
|
||||||
},
|
},
|
||||||
@@ -77,6 +78,8 @@ let vehicles = [];
|
|||||||
let models = ["Ocean", "PEAR"];
|
let models = ["Ocean", "PEAR"];
|
||||||
let years = [2023, 2024];
|
let years = [2023, 2024];
|
||||||
let totalVehicles = 0;
|
let totalVehicles = 0;
|
||||||
|
let fleets = ["fleet1", "fleet2"];
|
||||||
|
let totalFleets = 2;
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
export const VehicleProvider = ({ children }) => {
|
export const VehicleProvider = ({ children }) => {
|
||||||
@@ -86,6 +89,8 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
export const useVehicleContext = () => ({
|
export const useVehicleContext = () => ({
|
||||||
busy,
|
busy,
|
||||||
models,
|
models,
|
||||||
|
fleets,
|
||||||
|
totalFleets,
|
||||||
totalVehicles,
|
totalVehicles,
|
||||||
vehicle,
|
vehicle,
|
||||||
vehicles,
|
vehicles,
|
||||||
@@ -141,6 +146,10 @@ export const useVehicleContext = () => ({
|
|||||||
command,
|
command,
|
||||||
parameters,
|
parameters,
|
||||||
})),
|
})),
|
||||||
|
getFleets: jest.fn((vin, search,_token) => {return {
|
||||||
|
data: ["fleet1", "fleet2"],
|
||||||
|
total: 2,
|
||||||
|
}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setBusy = (val) => {
|
export const setBusy = (val) => {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import TableHeaderSortable from "../../Table/HeaderSortable";
|
|||||||
import { logger } from "../../../services/monitoring";
|
import { logger } from "../../../services/monitoring";
|
||||||
import ConnectedIcon from "../../Controls/ConnectedIcon";
|
import ConnectedIcon from "../../Controls/ConnectedIcon";
|
||||||
import ECUList from "../../Controls/ECUList";
|
import ECUList from "../../Controls/ECUList";
|
||||||
import {useLocalStorage} from "../../useLocalStorage";
|
import { useLocalStorage } from "../../useLocalStorage";
|
||||||
|
|
||||||
const tableColumns = [
|
const tableColumns = [
|
||||||
{
|
{
|
||||||
@@ -163,7 +163,8 @@ const CarSelectionTable = (props) => {
|
|||||||
<TableCell align="center">
|
<TableCell align="center">
|
||||||
<ConnectedIcon
|
<ConnectedIcon
|
||||||
connected={row.connected}
|
connected={row.connected}
|
||||||
style={{ marginRight: 5 }}
|
connectedHMI={row.connectedHMI}
|
||||||
|
style={{ marginRight: 3 }}
|
||||||
/>
|
/>
|
||||||
<Link to={`/vehicle-status/${row.vin}`}>{row.vin}</Link>
|
<Link to={`/vehicle-status/${row.vin}`}>{row.vin}</Link>
|
||||||
{row.ecu_list && (
|
{row.ecu_list && (
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
|
LinearProgress,
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
TableCell,
|
TableCell,
|
||||||
@@ -57,14 +58,21 @@ const MainForm = ({ vin, token }) => {
|
|||||||
const [pageIndex, setPageIndex] = useState(0);
|
const [pageIndex, setPageIndex] = useState(0);
|
||||||
const [orderBy, setOrderBy] = useState("id");
|
const [orderBy, setOrderBy] = useState("id");
|
||||||
const [order, setOrder] = useState("desc");
|
const [order, setOrder] = useState("desc");
|
||||||
const { cancelUpdate, getCarUpdates, carUpdates, totalCarUpdates } =
|
const {
|
||||||
useCarUpdatesContext();
|
cancelUpdate,
|
||||||
|
getCarUpdates,
|
||||||
|
carUpdates,
|
||||||
|
totalCarUpdates,
|
||||||
|
startMonitor,
|
||||||
|
stopMonitor,
|
||||||
|
} = useCarUpdatesContext();
|
||||||
const { setMessage } = useStatusContext();
|
const { setMessage } = useStatusContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
if (!vin || !token) return;
|
if (!vin || !token) return;
|
||||||
|
stopMonitor();
|
||||||
await getCarUpdates(
|
await getCarUpdates(
|
||||||
{
|
{
|
||||||
vin,
|
vin,
|
||||||
@@ -82,6 +90,20 @@ const MainForm = ({ vin, token }) => {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [vin, token, pageIndex, pageSize, orderBy, order]);
|
}, [vin, token, pageIndex, pageSize, orderBy, order]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
if (carUpdates.length === 0) return;
|
||||||
|
startMonitor(token);
|
||||||
|
} catch (e) {
|
||||||
|
setMessage(e.message);
|
||||||
|
logger.warn(e.stack);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
stopMonitor();
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [carUpdates]);
|
||||||
|
|
||||||
const handleChangePageIndex = (event, newIndex) => {
|
const handleChangePageIndex = (event, newIndex) => {
|
||||||
setPageIndex(newIndex);
|
setPageIndex(newIndex);
|
||||||
};
|
};
|
||||||
@@ -141,7 +163,12 @@ const MainForm = ({ vin, token }) => {
|
|||||||
{updateName(row)}
|
{updateName(row)}
|
||||||
</Link>
|
</Link>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">{row.status}</TableCell>
|
<TableCell align="center">
|
||||||
|
{row.status}
|
||||||
|
{row.progress > -1 && (
|
||||||
|
<LinearProgress variant="determinate" value={row.progress} />
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
<TableCell align="center">
|
<TableCell align="center">
|
||||||
{LocalDateTimeString(row.created)}
|
{LocalDateTimeString(row.created)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import CheckCircleIcon from "@material-ui/icons/CheckCircle";
|
import CheckCircleIcon from "@material-ui/icons/CheckCircle";
|
||||||
|
import CheckBoxIcon from "@material-ui/icons/CheckBox";
|
||||||
|
import { Tooltip } from "@material-ui/core";
|
||||||
|
|
||||||
const ConnectedIcon = (props) => {
|
const ConnectedIcon = (props) => {
|
||||||
if (props.connected) {
|
if (props.connected || props.connectedHMI) {
|
||||||
return (
|
return (
|
||||||
<span style={props.style}>
|
<span style={props.style}>
|
||||||
<CheckCircleIcon style={{ color: "Green", fontSize: 12 }} />
|
{props.connected && (
|
||||||
|
<Tooltip title="TBOX">
|
||||||
|
<CheckCircleIcon
|
||||||
|
style={{ color: "Green", fontSize: 12, marginRight: 3 }}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{props.connectedHMI && (
|
||||||
|
<Tooltip title="ICC">
|
||||||
|
<CheckBoxIcon
|
||||||
|
style={{ color: "Blue", fontSize: 12, marginRight: 3 }}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,9 @@
|
|||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import {FormControl} from "@material-ui/core";
|
import { FormControl } from "@material-ui/core";
|
||||||
import useStyles from "../../useStyles";
|
import useStyles from "../../useStyles";
|
||||||
import {MuiPickersUtilsProvider} from "@material-ui/pickers";
|
|
||||||
import DateFnsUtils from "@date-io/date-fns";
|
|
||||||
|
|
||||||
export const Dates = (
|
|
||||||
{
|
|
||||||
startDateFunc,
|
|
||||||
endDateFunc,
|
|
||||||
startDate,
|
|
||||||
handleStartChange,
|
|
||||||
endDate,
|
|
||||||
handleEndChange,
|
|
||||||
}) => {
|
|
||||||
if (startDateFunc && endDateFunc) {
|
|
||||||
return (<MuiPickersUtilsProvider utils={DateFnsUtils}>
|
|
||||||
{startDateFunc(startDate, handleStartChange)}
|
|
||||||
{endDateFunc(endDate, handleEndChange, startDate)}
|
|
||||||
</MuiPickersUtilsProvider>);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dates.propTypes = {
|
|
||||||
startDateFunc: PropTypes.func,
|
|
||||||
endDateFunc: PropTypes.func,
|
|
||||||
startDate: PropTypes.instanceOf(Date),
|
|
||||||
handleStartChange: PropTypes.func,
|
|
||||||
endDate: PropTypes.instanceOf(Date),
|
|
||||||
handleEndChange: PropTypes.func
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Parameters = (props) => {
|
export const Parameters = (props) => {
|
||||||
const {params} = props;
|
const { params } = props;
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
@@ -41,33 +11,19 @@ export const Parameters = (props) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {data, handleDataChange} = props;
|
const { data, handleDataChange } = props;
|
||||||
const {startDate, handleStartChange} = props;
|
|
||||||
const {endDate, handleEndChange} = props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl size="small" className={classes.formControl}>
|
<FormControl size="small" className={classes.formControl}>
|
||||||
<div style={{width: "300px", marginTop: "1em"}}>
|
<div style={{ width: "300px", marginTop: "1em" }}>
|
||||||
{params.dataFunc(data, handleDataChange)}
|
{params.dataFunc(data, handleDataChange)}
|
||||||
</div>
|
</div>
|
||||||
<Dates
|
|
||||||
startDateFunc={params.startDateFunc}
|
|
||||||
endDateFunc={params.endDateFunc}
|
|
||||||
startDate={startDate}
|
|
||||||
handleStartChange={handleStartChange}
|
|
||||||
endDate={endDate}
|
|
||||||
handleEndChange={handleEndChange}
|
|
||||||
></Dates>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
Parameters.propTypes = {
|
Parameters.propTypes = {
|
||||||
params: PropTypes.any,
|
params: PropTypes.any,
|
||||||
data: PropTypes.any,
|
data: PropTypes.any,
|
||||||
handleDataChange: PropTypes.func,
|
handleDataChange: PropTypes.func,
|
||||||
startDate: PropTypes.instanceOf(Date),
|
|
||||||
handleStartChange: PropTypes.func,
|
|
||||||
endDate: PropTypes.instanceOf(Date),
|
|
||||||
handleEndChange: PropTypes.func
|
|
||||||
};
|
};
|
||||||
@@ -1,140 +1,52 @@
|
|||||||
jest.mock("@material-ui/pickers/MuiPickersUtilsProvider")
|
import { render, waitFor } from "@testing-library/react";
|
||||||
|
import { Parameters } from "./Parameters";
|
||||||
|
|
||||||
import {render, waitFor} from "@testing-library/react";
|
|
||||||
import {Dates, Parameters} from "./Parameters";
|
|
||||||
import addSnapshotSerializer from "../../../utils/snapshot";
|
import addSnapshotSerializer from "../../../utils/snapshot";
|
||||||
|
|
||||||
|
|
||||||
const date = Date.parse("2011-10-10T14:48:00")
|
|
||||||
|
|
||||||
const renderDates = async (empty) => {
|
|
||||||
if (empty) {
|
|
||||||
await waitFor(() => {
|
|
||||||
/* render */
|
|
||||||
});
|
|
||||||
const { container } = render(<Dates startDateFunc={null} endDateFunc={null}/>)
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const [start, setStart] = [date, (_) => {}];
|
|
||||||
const [end, setEnd] = [date, (_) => {}];
|
|
||||||
|
|
||||||
const handleStartChange = (val) => {
|
|
||||||
setStart(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleEndChange = (val) => {
|
|
||||||
setEnd(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
/* render */
|
|
||||||
});
|
|
||||||
|
|
||||||
const {container} = render(
|
|
||||||
<div>
|
|
||||||
<Dates
|
|
||||||
startDateFunc={(val, handleValChange) => <div>{val.toString()}</div>}
|
|
||||||
endDateFunc={(val, handleValChange, prevVal) => <div>{val.toString()}, {prevVal.toString()}</div>}
|
|
||||||
startDate={start}
|
|
||||||
endDate={end}
|
|
||||||
handleStartChange={handleStartChange}
|
|
||||||
handleEndChange={handleEndChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
return container
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("Dates", () => {
|
|
||||||
beforeAll(() => {
|
|
||||||
addSnapshotSerializer(expect);
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Render empty", async () => {
|
|
||||||
const container = await renderDates(true);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Render filled", async () => {
|
|
||||||
const container = await renderDates(false);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const renderState = {
|
const renderState = {
|
||||||
EMPTY: 0,
|
EMPTY: 0,
|
||||||
JUST_DATA: 1,
|
JUST_DATA: 1,
|
||||||
WITH_DATE: 2,
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const renderParameters = async (rs) => {
|
const renderParameters = async (rs) => {
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
/* render */
|
/* render */
|
||||||
});
|
});
|
||||||
|
|
||||||
if (rs===renderState.EMPTY) {
|
if (rs === renderState.EMPTY) {
|
||||||
const { container } = render(<Parameters/>)
|
const { container } = render(<Parameters />);
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
const params = {dataFunc:(val, handleValChange) => <div>val.toString()</div>}
|
const params = {
|
||||||
const [data, handleDataChange] = [true, (_)=>{}];
|
dataFunc: (val, handleValChange) => <div>val.toString()</div>,
|
||||||
|
};
|
||||||
|
const [data, handleDataChange] = [true, (_) => {}];
|
||||||
|
|
||||||
if (rs===renderState.JUST_DATA) {
|
if (rs === renderState.JUST_DATA) {
|
||||||
const { container } = render(<Parameters
|
const { container } = render(
|
||||||
|
<Parameters
|
||||||
params={params}
|
params={params}
|
||||||
data={data}
|
data={data}
|
||||||
handleDataChange={handleDataChange}
|
handleDataChange={handleDataChange}
|
||||||
/>)
|
|
||||||
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
params.startDateFunc = (val, handleValChange) => (<div>val.toString()</div>)
|
|
||||||
params.endDateFunc = (val, handleValChange, prevVal) => (<div>val.toString(), prevVal.toString()</div>)
|
|
||||||
|
|
||||||
const [start, handleStartChange] = [date, (_)=>{}];
|
|
||||||
const [end, handleEndChange] = [date, (_)=>{}];
|
|
||||||
|
|
||||||
if (rs===renderState.WITH_DATE) {
|
|
||||||
const {container} = render(<Parameters
|
|
||||||
params={params}
|
|
||||||
data={data}
|
|
||||||
handleDataChange={handleDataChange}
|
|
||||||
start={start}
|
|
||||||
handleStartChange={handleStartChange}
|
|
||||||
end={end}
|
|
||||||
handleEndChange={handleEndChange}
|
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
|
|
||||||
return container
|
return container;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
describe("Params", () => {
|
describe("Params", () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
addSnapshotSerializer(expect);
|
addSnapshotSerializer(expect);
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Render empty", async () => {
|
it("Render empty", async () => {
|
||||||
const container = await renderParameters(renderState.EMPTY);
|
const container = await renderParameters(renderState.EMPTY);
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
})
|
});
|
||||||
|
|
||||||
it("Render just data", async () => {
|
it("Render just data", async () => {
|
||||||
const container = await renderDates(renderState.JUST_DATA);
|
const container = await renderParameters(renderState.JUST_DATA);
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
})
|
});
|
||||||
|
});
|
||||||
it("Render with date", async () => {
|
|
||||||
const container = await renderDates(renderState.WITH_DATE);
|
|
||||||
expect(container).toMatchSnapshot();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -1,24 +1,19 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`Dates Render empty 1`] = `<div />`;
|
exports[`Params Render empty 1`] = `<div />`;
|
||||||
|
|
||||||
exports[`Dates Render filled 1`] = `
|
exports[`Params Render just data 1`] = `
|
||||||
<div>
|
<div>
|
||||||
|
<div
|
||||||
|
class="MuiFormControl-root makeStyles-formControl-0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="width: 300px; margin-top: 1em;"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
val.toString()
|
||||||
1318258080000
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
1318258080000
|
|
||||||
,
|
|
||||||
1318258080000
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Params Render empty 1`] = `<div />`;
|
|
||||||
|
|
||||||
exports[`Params Render just data 1`] = `<div />`;
|
|
||||||
|
|
||||||
exports[`Params Render with date 1`] = `<div />`;
|
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ exports[`FleetAddForm Render 1`] = `
|
|||||||
class="PrivateSwitchBase-input-0"
|
class="PrivateSwitchBase-input-0"
|
||||||
name="log-level-group"
|
name="log-level-group"
|
||||||
type="radio"
|
type="radio"
|
||||||
value="warn"
|
value="warning"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="PrivateRadioButtonIcon-root-0"
|
class="PrivateRadioButtonIcon-root-0"
|
||||||
@@ -282,7 +282,7 @@ exports[`FleetAddForm Render 1`] = `
|
|||||||
<span
|
<span
|
||||||
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
||||||
>
|
>
|
||||||
Warn
|
Warning
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ const MainForm = () => {
|
|||||||
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
||||||
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
||||||
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
||||||
<FormControlLabel value="warn" control={<Radio />} label="Warn" />
|
<FormControlLabel value="warning" control={<Radio />} label="Warning" />
|
||||||
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
||||||
<FormControlLabel value="critical" control={<Radio />} label="Critical" />
|
<FormControlLabel value="critical" control={<Radio />} label="Critical" />
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ exports[`FleetVehiclesTable Render 1`] = `
|
|||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
>
|
>
|
||||||
<div>
|
<span>
|
||||||
<a
|
<a
|
||||||
class=""
|
class=""
|
||||||
href="/"
|
href="/"
|
||||||
@@ -172,7 +172,7 @@ exports[`FleetVehiclesTable Render 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div />
|
<div />
|
||||||
</div>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@@ -190,7 +190,7 @@ exports[`FleetVehiclesTable Render 1`] = `
|
|||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
>
|
>
|
||||||
<div>
|
<span>
|
||||||
<a
|
<a
|
||||||
class=""
|
class=""
|
||||||
href="/"
|
href="/"
|
||||||
@@ -209,7 +209,7 @@ exports[`FleetVehiclesTable Render 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div />
|
<div />
|
||||||
</div>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@@ -227,7 +227,7 @@ exports[`FleetVehiclesTable Render 1`] = `
|
|||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
>
|
>
|
||||||
<div>
|
<span>
|
||||||
<a
|
<a
|
||||||
class=""
|
class=""
|
||||||
href="/"
|
href="/"
|
||||||
@@ -246,7 +246,7 @@ exports[`FleetVehiclesTable Render 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div />
|
<div />
|
||||||
</div>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ const MainForm = ({ name }) => {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div>
|
<span key={`delete-${action.id}-of-div`}>
|
||||||
<Tooltip key={`delete-${action.id}`} title={action.tip}>
|
<Tooltip key={`delete-${action.id}`} title={action.tip}>
|
||||||
<Link to="#" onClick={() => onDelete(action.id)}>
|
<Link to="#" onClick={() => onDelete(action.id)}>
|
||||||
{action.icon}
|
{action.icon}
|
||||||
@@ -159,7 +159,7 @@ const MainForm = ({ name }) => {
|
|||||||
close={() => setShowDeleteModal(false)}
|
close={() => setShowDeleteModal(false)}
|
||||||
deleteFunction={() => onDelete(action.id)}
|
deleteFunction={() => onDelete(action.id)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ exports[`VehiclesTab Render 1`] = `
|
|||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
>
|
>
|
||||||
<div>
|
<span>
|
||||||
<a
|
<a
|
||||||
class=""
|
class=""
|
||||||
href="/"
|
href="/"
|
||||||
@@ -171,7 +171,7 @@ exports[`VehiclesTab Render 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div />
|
<div />
|
||||||
</div>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@@ -189,7 +189,7 @@ exports[`VehiclesTab Render 1`] = `
|
|||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
>
|
>
|
||||||
<div>
|
<span>
|
||||||
<a
|
<a
|
||||||
class=""
|
class=""
|
||||||
href="/"
|
href="/"
|
||||||
@@ -208,7 +208,7 @@ exports[`VehiclesTab Render 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div />
|
<div />
|
||||||
</div>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@@ -226,7 +226,7 @@ exports[`VehiclesTab Render 1`] = `
|
|||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
>
|
>
|
||||||
<div>
|
<span>
|
||||||
<a
|
<a
|
||||||
class=""
|
class=""
|
||||||
href="/"
|
href="/"
|
||||||
@@ -245,7 +245,7 @@ exports[`VehiclesTab Render 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
<div />
|
<div />
|
||||||
</div>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ exports[`FleetTable Render 1`] = `
|
|||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
>
|
>
|
||||||
warn
|
warning
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
class="MuiTableCell-root MuiTableCell-body MuiTableCell-alignCenter"
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ exports[`FleetUpdate Render 1`] = `
|
|||||||
class="PrivateSwitchBase-input-0"
|
class="PrivateSwitchBase-input-0"
|
||||||
name="log-level-group"
|
name="log-level-group"
|
||||||
type="radio"
|
type="radio"
|
||||||
value="warn"
|
value="warning"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="PrivateRadioButtonIcon-root-0"
|
class="PrivateRadioButtonIcon-root-0"
|
||||||
@@ -282,7 +282,7 @@ exports[`FleetUpdate Render 1`] = `
|
|||||||
<span
|
<span
|
||||||
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1"
|
||||||
>
|
>
|
||||||
Warn
|
Warning
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label
|
<label
|
||||||
|
|||||||
@@ -9,30 +9,30 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
Radio,
|
Radio,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
TextField
|
TextField,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
|
|
||||||
import useStyles from "../../useStyles";
|
import useStyles from "../../useStyles";
|
||||||
import {
|
import { useFleetContext, FleetProvider } from "../../Contexts/FleetContext";
|
||||||
useFleetContext,
|
|
||||||
FleetProvider
|
|
||||||
} from "../../Contexts/FleetContext";
|
|
||||||
import { useStatusContext } from "../../Contexts/StatusContext";
|
import { useStatusContext } from "../../Contexts/StatusContext";
|
||||||
import { useUserContext } from "../../Contexts/UserContext";
|
import { useUserContext } from "../../Contexts/UserContext";
|
||||||
import { logger } from "../../../services/monitoring";
|
import { logger } from "../../../services/monitoring";
|
||||||
|
|
||||||
|
|
||||||
const MainForm = () => {
|
const MainForm = () => {
|
||||||
const queries = new URLSearchParams(useLocation().search);
|
const queries = new URLSearchParams(useLocation().search);
|
||||||
|
|
||||||
const { fleet, getFleet, updateFleet, busy } = useFleetContext();
|
const { fleet, getFleet, updateFleet, busy } = useFleetContext();
|
||||||
const { token: { idToken: { jwtToken: token } } } = useUserContext();
|
const {
|
||||||
|
token: {
|
||||||
|
idToken: { jwtToken: token },
|
||||||
|
},
|
||||||
|
} = useUserContext();
|
||||||
const { setMessage, setTitle, setSitePath } = useStatusContext();
|
const { setMessage, setTitle, setSitePath } = useStatusContext();
|
||||||
const [redirect, setRedirect] = useState(null);
|
const [redirect, setRedirect] = useState(null);
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const [name, setName] = useState(queries.get("name") ?? "");
|
const [name, setName] = useState(queries.get("name") ?? "");
|
||||||
const [oldName, ] = useState(name);
|
const [oldName] = useState(name);
|
||||||
const [selectedLogLevel, setSelectedLogLevel] = useState("info");
|
const [selectedLogLevel, setSelectedLogLevel] = useState("info");
|
||||||
const [canbusEnabled, setCANBusEnabled] = useState(true);
|
const [canbusEnabled, setCANBusEnabled] = useState(true);
|
||||||
const [dataLoggerEnabled, setDataLoggerEnabled] = useState(false);
|
const [dataLoggerEnabled, setDataLoggerEnabled] = useState(false);
|
||||||
@@ -71,36 +71,40 @@ const MainForm = () => {
|
|||||||
|
|
||||||
if (fleet.canbus) {
|
if (fleet.canbus) {
|
||||||
setCANBusEnabled(fleet.canbus.enabled ?? canbusEnabled);
|
setCANBusEnabled(fleet.canbus.enabled ?? canbusEnabled);
|
||||||
setDataLoggerEnabled(fleet.canbus.data_logger_enabled ?? dataLoggerEnabled);
|
setDataLoggerEnabled(
|
||||||
|
fleet.canbus.data_logger_enabled ?? dataLoggerEnabled
|
||||||
|
);
|
||||||
setMaxMemBufferSize(fleet.canbus.max_mem_buffer_size ?? maxMemBufferSize);
|
setMaxMemBufferSize(fleet.canbus.max_mem_buffer_size ?? maxMemBufferSize);
|
||||||
setMaxDiskBufferSize(fleet.canbus.max_disk_buffer_size ?? maxDiskBufferSize);
|
setMaxDiskBufferSize(
|
||||||
|
fleet.canbus.max_disk_buffer_size ?? maxDiskBufferSize
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [fleet]);
|
}, [fleet]);
|
||||||
|
|
||||||
const onNameChange = (event) => {
|
const onNameChange = (event) => {
|
||||||
setName(event.target.value);
|
setName(event.target.value);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onLogLevelChange = (event) => {
|
const onLogLevelChange = (event) => {
|
||||||
setSelectedLogLevel(event.target.value);
|
setSelectedLogLevel(event.target.value);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onCANBusChange = (event) => {
|
const onCANBusChange = (event) => {
|
||||||
setCANBusEnabled(event.target.checked);
|
setCANBusEnabled(event.target.checked);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onDataLoggerChange = (event) => {
|
const onDataLoggerChange = (event) => {
|
||||||
setDataLoggerEnabled(event.target.checked);
|
setDataLoggerEnabled(event.target.checked);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onMaxMemBufferSizeChange = (event) => {
|
const onMaxMemBufferSizeChange = (event) => {
|
||||||
setMaxMemBufferSize(event.target.value);
|
setMaxMemBufferSize(event.target.value);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onMaxDiskBufferSizeChange = (event) => {
|
const onMaxDiskBufferSizeChange = (event) => {
|
||||||
setMaxDiskBufferSize(event.target.value);
|
setMaxDiskBufferSize(event.target.value);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onSubmit = async (event) => {
|
const onSubmit = async (event) => {
|
||||||
try {
|
try {
|
||||||
@@ -112,12 +116,13 @@ const MainForm = () => {
|
|||||||
enabled: canbusEnabled,
|
enabled: canbusEnabled,
|
||||||
data_logger_enabled: canbusEnabled ? dataLoggerEnabled : false,
|
data_logger_enabled: canbusEnabled ? dataLoggerEnabled : false,
|
||||||
max_mem_buffer_size: canbusEnabled ? parseInt(maxMemBufferSize) : 0,
|
max_mem_buffer_size: canbusEnabled ? parseInt(maxMemBufferSize) : 0,
|
||||||
max_disk_buffer_size: canbusEnabled && dataLoggerEnabled ? parseInt(maxDiskBufferSize) : 0
|
max_disk_buffer_size:
|
||||||
}
|
canbusEnabled && dataLoggerEnabled
|
||||||
|
? parseInt(maxDiskBufferSize)
|
||||||
|
: 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(oldName);
|
|
||||||
|
|
||||||
const result = await updateFleet(oldName, formData, token);
|
const result = await updateFleet(oldName, formData, token);
|
||||||
if (!result || result.error) return;
|
if (!result || result.error) return;
|
||||||
|
|
||||||
@@ -162,22 +167,30 @@ const MainForm = () => {
|
|||||||
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
<FormControlLabel value="trace" control={<Radio />} label="Trace" />
|
||||||
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
<FormControlLabel value="debug" control={<Radio />} label="Debug" />
|
||||||
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
<FormControlLabel value="info" control={<Radio />} label="Info" />
|
||||||
<FormControlLabel value="warn" control={<Radio />} label="Warn" />
|
<FormControlLabel
|
||||||
|
value="warning"
|
||||||
|
control={<Radio />}
|
||||||
|
label="Warning"
|
||||||
|
/>
|
||||||
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
<FormControlLabel value="error" control={<Radio />} label="Error" />
|
||||||
<FormControlLabel value="critical" control={<Radio />} label="Critical" />
|
<FormControlLabel
|
||||||
|
value="critical"
|
||||||
|
control={<Radio />}
|
||||||
|
label="Critical"
|
||||||
|
/>
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
<FormLabel id="demo-row-radio-buttons-group-label">CAN Bus</FormLabel>
|
<FormLabel id="demo-row-radio-buttons-group-label">CAN Bus</FormLabel>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
<FormControlLabel control={
|
<FormControlLabel
|
||||||
<Checkbox
|
control={
|
||||||
checked={canbusEnabled}
|
<Checkbox checked={canbusEnabled} onChange={onCANBusChange} />
|
||||||
onChange={onCANBusChange}
|
}
|
||||||
|
label="CAN Bus Enabled"
|
||||||
/>
|
/>
|
||||||
} label="CAN Bus Enabled" />
|
|
||||||
<TextField
|
<TextField
|
||||||
id="max_mem_buffer_size"
|
id="max_mem_buffer_size"
|
||||||
name="max_mem_buffer_size"
|
name="max_mem_buffer_size"
|
||||||
label='Max Memory Buffer Size (0 uses default size)'
|
label="Max Memory Buffer Size (0 uses default size)"
|
||||||
value={maxMemBufferSize}
|
value={maxMemBufferSize}
|
||||||
onChange={onMaxMemBufferSizeChange}
|
onChange={onMaxMemBufferSizeChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -190,18 +203,21 @@ const MainForm = () => {
|
|||||||
required
|
required
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
<FormControlLabel control={
|
<FormControlLabel
|
||||||
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={dataLoggerEnabled}
|
checked={dataLoggerEnabled}
|
||||||
onChange={onDataLoggerChange}
|
onChange={onDataLoggerChange}
|
||||||
disabled={!canbusEnabled}
|
disabled={!canbusEnabled}
|
||||||
/>
|
/>
|
||||||
} label="Data Logger Enabled" />
|
}
|
||||||
|
label="Data Logger Enabled"
|
||||||
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<TextField
|
<TextField
|
||||||
id="max_disk_buffer_size"
|
id="max_disk_buffer_size"
|
||||||
name="max_disk_buffer_size"
|
name="max_disk_buffer_size"
|
||||||
label='Max Disk Buffer Size (0 uses default size)'
|
label="Max Disk Buffer Size (0 uses default size)"
|
||||||
value={maxDiskBufferSize}
|
value={maxDiskBufferSize}
|
||||||
onChange={onMaxDiskBufferSizeChange}
|
onChange={onMaxDiskBufferSizeChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|||||||
@@ -68,7 +68,11 @@ const MainForm = () => {
|
|||||||
const [orderBy, setOrderBy] = useState("id");
|
const [orderBy, setOrderBy] = useState("id");
|
||||||
const [order, setOrder] = useState("asc");
|
const [order, setOrder] = useState("asc");
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
|
|
||||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||||
|
const [deleteId, setDeleteId] = useState("");
|
||||||
|
const [deleteRowName, setDeleteRowName] = useState("");
|
||||||
|
|
||||||
const { getManifests, deleteManifest, manifests, totalManifests } =
|
const { getManifests, deleteManifest, manifests, totalManifests } =
|
||||||
useManifestsContext();
|
useManifestsContext();
|
||||||
const { setMessage, setTitle, setSitePath } = useStatusContext();
|
const { setMessage, setTitle, setSitePath } = useStatusContext();
|
||||||
@@ -133,6 +137,12 @@ const MainForm = () => {
|
|||||||
setSearch(query);
|
setSearch(query);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setDeletePopup = (id, row) => {
|
||||||
|
setDeleteId(id);
|
||||||
|
setDeleteRowName(`${row.name} ${row.version}`);
|
||||||
|
setShowDeleteModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
const onDelete = async (manifest_id) => {
|
const onDelete = async (manifest_id) => {
|
||||||
try {
|
try {
|
||||||
await deleteManifest(parseInt(manifest_id), token);
|
await deleteManifest(parseInt(manifest_id), token);
|
||||||
@@ -180,19 +190,13 @@ const MainForm = () => {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div>
|
<span key={`delete-${action.id}-of-key`}>
|
||||||
<Tooltip key={`delete-${action.id}`} title={action.tip}>
|
<Tooltip key={`delete-${action.id}`} title={action.tip}>
|
||||||
<Link to="#" onClick={() => onDelete(action.id)}>
|
<Link to="#" onClick={() => setDeletePopup(action.id, row)}>
|
||||||
{action.icon}
|
{action.icon}
|
||||||
</Link>
|
</Link>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<DeleteConfirmation
|
</span>
|
||||||
message={action.id}
|
|
||||||
open={showDeleteModal}
|
|
||||||
close={() => setShowDeleteModal(false)}
|
|
||||||
deleteFunction={() => onDelete(action.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -261,6 +265,12 @@ const MainForm = () => {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</TableFooter>
|
</TableFooter>
|
||||||
</Table>
|
</Table>
|
||||||
|
<DeleteConfirmation
|
||||||
|
message={deleteRowName}
|
||||||
|
open={showDeleteModal}
|
||||||
|
close={() => setShowDeleteModal(false)}
|
||||||
|
deleteFunction={() => onDelete(deleteId)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,12 +74,16 @@ const Component = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
if (markers.length > 0) {
|
|
||||||
const vins = markers.map((marker) => marker[2]);
|
const vins = markers
|
||||||
|
.filter((marker) => marker[2].length > 0)
|
||||||
|
.map((marker) => marker[2]);
|
||||||
|
|
||||||
|
if (vins.length === 0) return;
|
||||||
|
|
||||||
getConnections(vins, token).then((conns) => {
|
getConnections(vins, token).then((conns) => {
|
||||||
setConnections(conns);
|
setConnections(conns);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [markers, token]);
|
}, [markers, token]);
|
||||||
|
|
||||||
@@ -151,7 +155,6 @@ const Component = () => {
|
|||||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
/>
|
/>
|
||||||
<CenterFocus center={center} zoom={zoom} />
|
<CenterFocus center={center} zoom={zoom} />
|
||||||
|
|
||||||
{markers.map((marker) => (
|
{markers.map((marker) => (
|
||||||
<Marker
|
<Marker
|
||||||
icon={getCarIcon(marker[2])}
|
icon={getCarIcon(marker[2])}
|
||||||
@@ -184,6 +187,7 @@ const Component = () => {
|
|||||||
key={carState.vin}
|
key={carState.vin}
|
||||||
vin={carState.vin}
|
vin={carState.vin}
|
||||||
online={carState.online}
|
online={carState.online}
|
||||||
|
onlineHMI={carState.online_hmi}
|
||||||
battery={carState.battery}
|
battery={carState.battery}
|
||||||
doors={carState.doors}
|
doors={carState.doors}
|
||||||
location={carState.location}
|
location={carState.location}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import CANSignals from "../Cars/CANSignals";
|
|||||||
const VehiclePopUp = (props) => {
|
const VehiclePopUp = (props) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [viewCAN, setViewCAN] = useState(false);
|
const [viewCAN, setViewCAN] = useState(false);
|
||||||
const { vin, online, onClose } = props;
|
const { vin, online, onClose, onlineHMI } = props;
|
||||||
|
|
||||||
const toggleView = (e) => {
|
const toggleView = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -43,6 +43,9 @@ const VehiclePopUp = (props) => {
|
|||||||
<p>
|
<p>
|
||||||
<b>Connected</b>: {online.toString()}
|
<b>Connected</b>: {online.toString()}
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>ICC Connected</b>: {onlineHMI?.toString()}
|
||||||
|
</p>
|
||||||
{viewCAN && <CANSignals vin={vin} />}
|
{viewCAN && <CANSignals vin={vin} />}
|
||||||
{!viewCAN && <DigitalTwin {...props} />}
|
{!viewCAN && <DigitalTwin {...props} />}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const fleets = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "US-CENTRAL",
|
name: "US-CENTRAL",
|
||||||
log_level: "warn",
|
log_level: "warning",
|
||||||
canbus: { enabled: false, data_logger_enabled: false, max_mem_buffer_size: 0, max_disk_buffer_size: 0 },
|
canbus: { enabled: false, data_logger_enabled: false, max_mem_buffer_size: 0, max_disk_buffer_size: 0 },
|
||||||
vehicles: ["USCENTVIN12345678", "USCENTVIN12345679", "USCENTVIN12345670"]
|
vehicles: ["USCENTVIN12345678", "USCENTVIN12345679", "USCENTVIN12345670"]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ const ecusData = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const signals = {data:[
|
||||||
|
{
|
||||||
|
timestamp: "2021-07-14T20:09:40.98187Z",
|
||||||
|
name: "signal",
|
||||||
|
value: 123
|
||||||
|
},
|
||||||
|
]};
|
||||||
|
|
||||||
const vehiclesAPI = {
|
const vehiclesAPI = {
|
||||||
addVehicle: async (vehicle) => {
|
addVehicle: async (vehicle) => {
|
||||||
data.push(vehicle);
|
data.push(vehicle);
|
||||||
@@ -89,6 +97,7 @@ const vehiclesAPI = {
|
|||||||
getVehicles: async () => {
|
getVehicles: async () => {
|
||||||
return { data };
|
return { data };
|
||||||
},
|
},
|
||||||
|
getFleets: async (vin) => {return { data: ["fleet1", "fleet2"]}},
|
||||||
getYears: async () => {
|
getYears: async () => {
|
||||||
return {
|
return {
|
||||||
data: [2021, 2022],
|
data: [2021, 2022],
|
||||||
@@ -104,6 +113,9 @@ const vehiclesAPI = {
|
|||||||
const index = data.findIndex(element => element.vin === vin);
|
const index = data.findIndex(element => element.vin === vin);
|
||||||
if (index >= 0) data[index] = vehicle;
|
if (index >= 0) data[index] = vehicle;
|
||||||
return vehicle;
|
return vehicle;
|
||||||
|
},
|
||||||
|
getCANSignals: async (vin, vehicle) => {
|
||||||
|
return signals;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,19 @@ const vehiclesAPI = {
|
|||||||
.catch(errorHandler);
|
.catch(errorHandler);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getFleets: async (vin, search, token) => {
|
||||||
|
const u = addQueryParams(`${API_ENDPOINT}/vehicle/${vin}/fleets`, search)
|
||||||
|
return fetch(u, {
|
||||||
|
method: "GET",
|
||||||
|
headers: Object.assign(
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
getAuthHeaderOptions(token)
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.then(fetchRespHandler)
|
||||||
|
.catch(errorHandler);
|
||||||
|
},
|
||||||
|
|
||||||
getYears: async (token) =>
|
getYears: async (token) =>
|
||||||
fetch(`${API_ENDPOINT}/vehicleyears`, {
|
fetch(`${API_ENDPOINT}/vehicleyears`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|||||||
Reference in New Issue
Block a user