From 7eed1dd25c70ed1af3f14f18257ed1fd96917c27 Mon Sep 17 00:00:00 2001 From: Tristan Timblin Date: Fri, 2 Jun 2023 11:07:12 -0400 Subject: [PATCH 01/12] CEC-4455: Add GMT conversion (#345) adds a checkbox to show time/date in GMT+0 regardless of the users timezone. --- .../__snapshots__/index.test.jsx.snap | 41 +++++++++++++++++++ .../CANSelfServe/SelfServe/index.jsx | 28 ++++++++++--- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/components/CANSelfServe/SelfServe/__snapshots__/index.test.jsx.snap b/src/components/CANSelfServe/SelfServe/__snapshots__/index.test.jsx.snap index 862780e..7c0453b 100644 --- a/src/components/CANSelfServe/SelfServe/__snapshots__/index.test.jsx.snap +++ b/src/components/CANSelfServe/SelfServe/__snapshots__/index.test.jsx.snap @@ -292,6 +292,47 @@ exports[`Render Render 1`] = ` +
+ +
{ const [selectedEndDate, setSelectedEndDate] = useState(new Date()); const [selectedCanSignals, setSelectedCanSignals] = useState([]); const [selectAllCanSignals, setSelectAllCanSignals] = useState(false); + const [gmtTimezone, setGmtTimezone] = useState(false); const { token: { @@ -86,6 +87,12 @@ const MainForm = ({ id }) => { } }; + const displayTimeAsGMT = (date) => { + return gmtTimezone + ? date.toLocaleString("en-US", {timeZone: "Etc/GMT"}) + : date; + } + return (
@@ -102,7 +109,7 @@ const MainForm = ({ id }) => { margin="normal" id="date-picker-inline" label="Date From" - value={selectedStartDate} + value={displayTimeAsGMT(selectedStartDate)} onChange={(value) => handleDateChange(value, "start")} KeyboardButtonProps={{ 'aria-label': 'change date', @@ -116,7 +123,7 @@ const MainForm = ({ id }) => { variant="inline" id="time-picker" label="Time From" - value={selectedStartDate} + value={displayTimeAsGMT(selectedStartDate)} onChange={handleTimeFromChange} KeyboardButtonProps={{ 'aria-label': 'change time', @@ -132,7 +139,7 @@ const MainForm = ({ id }) => { margin="normal" id="date-picker-inline" label="Date To" - value={selectedEndDate} + value={displayTimeAsGMT(selectedEndDate)} onChange={(value) => handleDateChange(value, "end")} KeyboardButtonProps={{ 'aria-label': 'change date', @@ -146,13 +153,24 @@ const MainForm = ({ id }) => { id="time-picker" variant="inline" label="Time To" - value={selectedEndDate} + value={displayTimeAsGMT(selectedEndDate)} onChange={handleTimeToChange} KeyboardButtonProps={{ 'aria-label': 'change time', }} /> + + setGmtTimezone((current) => !current)} + /> + } + /> + From 022e88d400631f115bec2b7252772955e02ca997 Mon Sep 17 00:00:00 2001 From: Tristan Timblin Date: Mon, 5 Jun 2023 15:30:54 -0400 Subject: [PATCH 02/12] CEC-4425: Fix responsive styles (#346) * CEC-4425: Fix responsive styles --- .../App/__snapshots__/App.test.js.snap | 64 +++++++++---------- src/components/Cars/Status/index.jsx | 1 + src/components/Layouts/MenuDrawer.jsx | 2 +- src/components/useStyles.jsx | 3 +- 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/components/App/__snapshots__/App.test.js.snap b/src/components/App/__snapshots__/App.test.js.snap index ddb06f1..bb550f6 100644 --- a/src/components/App/__snapshots__/App.test.js.snap +++ b/src/components/App/__snapshots__/App.test.js.snap @@ -467,7 +467,7 @@ exports[`App Route / authenticated 1`] = ` class="makeStyles-drawerHeader-0" />

@@ -8617,7 +8617,7 @@ exports[`App Route /tools/security-dll unauthenticated 1`] = ` class="makeStyles-drawerHeader-0" />

{
- {children} + {children}
); diff --git a/src/components/useStyles.jsx b/src/components/useStyles.jsx index edb09bc..5e7769e 100644 --- a/src/components/useStyles.jsx +++ b/src/components/useStyles.jsx @@ -127,6 +127,7 @@ const useStyles = makeStyles((theme) => ({ duration: theme.transitions.duration.enteringScreen, }), marginLeft: 0, + maxWidth: `calc(100% - ${DRAWER_WIDTH}px)`, }, rightToolbar: { marginLeft: "auto", @@ -161,7 +162,7 @@ const useStyles = makeStyles((theme) => ({ textAlign: "left", paddingLeft: theme.spacing(2), paddingRight: theme.spacing(1), - width: "100%", + maxWidth: "100%", }, logo: { height: 60, From 82d722d8f521b5dedc7955f1d6b347a1138170e8 Mon Sep 17 00:00:00 2001 From: Paul Adamsen <117673433+pauladamseniii@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:30:44 -0400 Subject: [PATCH 03/12] CEC-4351 - units for digital twin props (#347) * CEC-4351 - units for digital twin props * fix mocked data --- .../Status/__snapshots__/DigitalTwinTab.test.jsx.snap | 8 ++++---- src/components/Contexts/__mocks__/VehicleContext.jsx | 1 + src/components/DigitalTwin/index.js | 10 +++++----- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/Cars/Status/__snapshots__/DigitalTwinTab.test.jsx.snap b/src/components/Cars/Status/__snapshots__/DigitalTwinTab.test.jsx.snap index 1f8ffc2..2f68f73 100644 --- a/src/components/Cars/Status/__snapshots__/DigitalTwinTab.test.jsx.snap +++ b/src/components/Cars/Status/__snapshots__/DigitalTwinTab.test.jsx.snap @@ -53,14 +53,14 @@ exports[`DigitalTwinTab Render 1`] = ` Total Mileage : - unknown + 12000 km

Max Range : - 577 + 577 km

: - 17 + 17 m

@@ -227,7 +227,7 @@ exports[`DigitalTwinTab Render 1`] = ` Vehicle Speed : - 77.7 + 77.7 km/h

diff --git a/src/components/Contexts/__mocks__/VehicleContext.jsx b/src/components/Contexts/__mocks__/VehicleContext.jsx index 90844b5..1fca329 100644 --- a/src/components/Contexts/__mocks__/VehicleContext.jsx +++ b/src/components/Contexts/__mocks__/VehicleContext.jsx @@ -37,6 +37,7 @@ let vehicleState = { online: false, online_hmi: true, battery: { + total_mileage_odometer: 12000, percent: 95, }, max_range: { diff --git a/src/components/DigitalTwin/index.js b/src/components/DigitalTwin/index.js index 804e9e0..8548dc5 100644 --- a/src/components/DigitalTwin/index.js +++ b/src/components/DigitalTwin/index.js @@ -38,15 +38,15 @@ const DigitalTwin = (props) => {

Battery

{keyValueTemplate("Percentage", `${battery?.percent || 0}%`)} - {keyValueTemplate("Total Mileage", battery?.total_mileage_odometer || UNKNOWN)} - {keyValueTemplate("Max Range", max_range?.max_miles || UNKNOWN)} + {keyValueTemplate("Total Mileage", `${battery?.total_mileage_odometer} km` || UNKNOWN)} + {keyValueTemplate("Max Range", `${max_range?.max_miles} km` || UNKNOWN)}
)} {(vcu0x260 || charging_metrics) && (

Charging

{keyValueTemplate("Charge Type", vcu0x260?.charge_type || UNKNOWN)} - {keyValueTemplate("Remaining Time", charging_metrics?.remaining_charging_time || UNKNOWN)} + {keyValueTemplate("Remaining Time", `${charging_metrics?.remaining_charging_time} min` || UNKNOWN)}
)} {doors && ( @@ -95,7 +95,7 @@ const DigitalTwin = (props) => { return keyValueTemplate(value[0], "Invalid") } if (value[0] === "altitude") { - return keyValueTemplate(value[0], value[1]); + return keyValueTemplate(value[0], `${value[1]} m`); } else { return keyValueTemplate(value[0], `${value[1]}°`); } @@ -124,7 +124,7 @@ const DigitalTwin = (props) => { )} {vehicle_speed && (
- {keyValueTemplate("Vehicle Speed", vehicle_speed.speed)} + {keyValueTemplate("Vehicle Speed", `${vehicle_speed.speed} km/h`)}
)}
From 28f968efc7a5ef5319b803bfc80241a23a417d03 Mon Sep 17 00:00:00 2001 From: John Wu <76966357+jwu-fisker@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:08:05 -0700 Subject: [PATCH 04/12] CEC-4450 debug mask (#343) * CEC-4450 Enable debug mask using REACT_APP_ENABLE_DEBUG * rename --- .env.cec-euprd | 1 + .env.cec-prd | 1 + .env.dev | 1 + .env.local | 1 + .env.prd | 1 + .env.stg | 1 + src/components/Cars/Status/Details/index.jsx | 3 +-- src/components/Cars/Update/index.jsx | 17 ++++++++--------- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.env.cec-euprd b/.env.cec-euprd index 7b9dcef..74cb850 100644 --- a/.env.cec-euprd +++ b/.env.cec-euprd @@ -17,3 +17,4 @@ REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8 REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f REACT_APP_ECCKEY_ENV= REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":49.8327,"lng":9.8816,"zoom":4.5} +REACT_APP_ENABLE_DEBUGMASK=1 \ No newline at end of file diff --git a/.env.cec-prd b/.env.cec-prd index d30b7e4..074549f 100644 --- a/.env.cec-prd +++ b/.env.cec-prd @@ -17,3 +17,4 @@ REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8 REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f REACT_APP_ECCKEY_ENV= REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5} +REACT_APP_ENABLE_DEBUGMASK=1 \ No newline at end of file diff --git a/.env.dev b/.env.dev index a04f46a..7fdf5cb 100644 --- a/.env.dev +++ b/.env.dev @@ -17,3 +17,4 @@ REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8 REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f REACT_APP_ECCKEY_ENV=stage,prod REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5} +REACT_APP_ENABLE_DEBUGMASK=1 \ No newline at end of file diff --git a/.env.local b/.env.local index 788b410..2311225 100644 --- a/.env.local +++ b/.env.local @@ -17,3 +17,4 @@ REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8 REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f REACT_APP_ECCKEY_ENV=dev,stage,prod REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5} +REACT_APP_ENABLE_DEBUGMASK=1 \ No newline at end of file diff --git a/.env.prd b/.env.prd index f812b2a..878fe6b 100644 --- a/.env.prd +++ b/.env.prd @@ -17,3 +17,4 @@ REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8 REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f REACT_APP_ECCKEY_ENV=stage REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5} +REACT_APP_ENABLE_DEBUGMASK=1 \ No newline at end of file diff --git a/.env.stg b/.env.stg index 702381f..df9db72 100644 --- a/.env.stg +++ b/.env.stg @@ -17,3 +17,4 @@ REACT_APP_ROLE_SUPPLIER_APPROVER=a6c9805e-80b2-42b2-bfbb-9df52e5504d8 REACT_APP_ROLE_MANIFEST_MIGRATION=42798c8a-9fa7-4fb4-82c0-9582cabe364f REACT_APP_ECCKEY_ENV=prod REACT_APP_HOME_MAP_DEFAULT_LOCATION={"lat":37.0902,"lng":-95.7129,"zoom":4.5} +REACT_APP_ENABLE_DEBUGMASK=1 \ No newline at end of file diff --git a/src/components/Cars/Status/Details/index.jsx b/src/components/Cars/Status/Details/index.jsx index ac8bc70..585d15a 100644 --- a/src/components/Cars/Status/Details/index.jsx +++ b/src/components/Cars/Status/Details/index.jsx @@ -35,8 +35,7 @@ const MainForm = ({ vin }) => { providers, } = useUserContext(); - const ENV = process.env.REACT_APP_ENV; - const showDebugMask = (ENV === 'local' || ENV === 'dev' || ENV === 'stg' || ENV === 'prd') + const showDebugMask = (process.env.REACT_APP_ENABLE_DEBUGMASK === "1"); useEffect(() => { (async () => { diff --git a/src/components/Cars/Update/index.jsx b/src/components/Cars/Update/index.jsx index cdbf11d..2b4d965 100644 --- a/src/components/Cars/Update/index.jsx +++ b/src/components/Cars/Update/index.jsx @@ -1,6 +1,3 @@ -import React, { useEffect, useRef, useState } from "react"; -import { Redirect } from "react-router"; -import { useLocation } from "react-router-dom"; import { Button, Checkbox, @@ -11,15 +8,18 @@ import { RadioGroup, TextField } from "@material-ui/core"; +import React, { useEffect, useRef, useState } from "react"; +import { Redirect } from "react-router"; +import { useLocation } from "react-router-dom"; -import useStyles from "../../useStyles"; +import { logger } from "../../../services/monitoring"; +import { useStatusContext } from "../../Contexts/StatusContext"; +import { useUserContext } from "../../Contexts/UserContext"; import { useVehicleContext, VehicleProvider } from "../../Contexts/VehicleContext"; -import { useStatusContext } from "../../Contexts/StatusContext"; -import { useUserContext } from "../../Contexts/UserContext"; -import { logger } from "../../../services/monitoring"; +import useStyles from "../../useStyles"; const MainForm = () => { @@ -48,8 +48,7 @@ const MainForm = () => { const [maxDiskBufferSize, setMaxDiskBufferSize] = useState(0); const debugMaskEl = useRef(null); - const ENV = process.env.REACT_APP_ENV; - const showDebugMask = (ENV === 'local' || ENV === 'dev' || ENV === 'stg' || ENV === 'prd') + const showDebugMask = (process.env.REACT_APP_ENABLE_DEBUGMASK === "1"); useEffect(() => { setTitle("Update Vehicle"); From 4d1d2fb58e0039be8e3ac0fdb2fda6c1cadaf0bb Mon Sep 17 00:00:00 2001 From: Alexander Andrews <45926661+alexander-e-andrews@users.noreply.github.com> Date: Tue, 6 Jun 2023 13:21:58 -0400 Subject: [PATCH 05/12] CEC-4297: DTC enabled value for trex canbus (#344) --- .../Update/__snapshots__/index.test.jsx.snap | 38 +++++++++++++++++++ src/components/Cars/Update/index.jsx | 16 +++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/components/Cars/Update/__snapshots__/index.test.jsx.snap b/src/components/Cars/Update/__snapshots__/index.test.jsx.snap index dc0b8dd..ca24b59 100644 --- a/src/components/Cars/Update/__snapshots__/index.test.jsx.snap +++ b/src/components/Cars/Update/__snapshots__/index.test.jsx.snap @@ -884,6 +884,44 @@ exports[`VehicleUpdate Render 1`] = ` Data Logger Enabled +
{ const [dataLoggerEnabled, setDataLoggerEnabled] = useState(false); const [maxMemBufferSize, setMaxMemBufferSize] = useState(0); const [maxDiskBufferSize, setMaxDiskBufferSize] = useState(0); + const [dtcEnabled, setDTCEnabled] = useState(true); const debugMaskEl = useRef(null); const showDebugMask = (process.env.REACT_APP_ENABLE_DEBUGMASK === "1"); @@ -95,6 +96,7 @@ const MainForm = () => { setDataLoggerEnabled(vehicle.canbus.data_logger_enabled ?? dataLoggerEnabled); setMaxMemBufferSize(vehicle.canbus.max_mem_buffer_size ?? maxMemBufferSize); setMaxDiskBufferSize(vehicle.canbus.max_disk_buffer_size ?? maxDiskBufferSize); + setDTCEnabled(vehicle.canbus.dtc_enabled ?? dtcEnabled); } if (showDebugMask) { @@ -116,6 +118,10 @@ const MainForm = () => { setDataLoggerEnabled(event.target.checked); } + const onDtcEnabledChange = (event) => { + setDTCEnabled(event.target.checked); + } + const onMaxMemBufferSizeChange = (event) => { setMaxMemBufferSize(event.target.value); } @@ -143,7 +149,8 @@ const MainForm = () => { enabled: canbusEnabled, data_logger_enabled: canbusEnabled ? dataLoggerEnabled : false, 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, + dtc_enabled: canbusEnabled ? dtcEnabled : false }, debug_mask: debugMaskEl.current?.value }; @@ -371,6 +378,13 @@ const MainForm = () => { disabled={!canbusEnabled} /> } label="Data Logger Enabled" /> + + } label="Data Logger Enabled" /> Date: Tue, 6 Jun 2023 19:58:55 -0400 Subject: [PATCH 06/12] CEC-4248 - Add time settings to DTC timeline page (#348) --- .../__snapshots__/index.test.jsx.snap | 730 ++++++++++++++++++ .../DTCTimeline/DTCTimeline/index.jsx | 172 +++-- .../DTCTimeline/DTCTimeline/index.test.jsx | 42 + 3 files changed, 893 insertions(+), 51 deletions(-) create mode 100644 src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap create mode 100644 src/components/DTCTimeline/DTCTimeline/index.test.jsx diff --git a/src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap b/src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap new file mode 100644 index 0000000..222305a --- /dev/null +++ b/src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap @@ -0,0 +1,730 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render Render 1`] = ` +
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+ +
+
+
+
+ +
+ +
+ +
+
+ +
+
+
+ +
+
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
+ + Id + + + + + VIN + + + + + ECU + + + + + Trouble Code + + + + + Status Code + + + + Error Text + + + Date + + sorted descending + + + +
+
+
+
+
+
+
+`; diff --git a/src/components/DTCTimeline/DTCTimeline/index.jsx b/src/components/DTCTimeline/DTCTimeline/index.jsx index c632d36..bd788ae 100644 --- a/src/components/DTCTimeline/DTCTimeline/index.jsx +++ b/src/components/DTCTimeline/DTCTimeline/index.jsx @@ -1,6 +1,6 @@ import DateFnsUtils from '@date-io/date-fns'; -import { Button, CircularProgress, Grid, Table, TableBody, TableCell, TableFooter, TablePagination, TableRow } from "@material-ui/core"; -import { KeyboardDatePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'; +import { Button, Checkbox, CircularProgress, FormControlLabel, Grid, Table, TableBody, TableCell, TableFooter, TablePagination, TableRow } from "@material-ui/core"; +import { KeyboardDatePicker, KeyboardTimePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'; import clsx from "clsx"; import React, { useEffect, useState } from "react"; import { logger } from "../../../services/monitoring"; @@ -20,10 +20,11 @@ const MainForm = ({ vin }) => { const [pageIndex, setPageIndex] = useState(0); const [orderBy, setOrderBy] = useState("epoch_usec"); const [order, setOrder] = useState("desc"); - const { dtcData, getDTCData, total=0 } = useDTCTimelineContext(); + const { dtcData, getDTCData, total = 0 } = useDTCTimelineContext(); const [selectedStartDate, setSelectedStartDate] = useState(new Date(Date.now() - 24 * 60 * 60 * 1000)); const [selectedEndDate, setSelectedEndDate] = useState(new Date()); const [selectedECU, setSelectedECU] = useState(""); + const [gmtTimezone, setGmtTimezone] = useState(false); const [loading, setLoading] = useState(false); const { setMessage } = useStatusContext(); @@ -51,7 +52,7 @@ const MainForm = ({ vin }) => { { id: "ErrorText", label: "Error Text", - no_sort : true, + no_sort: true, }, { id: "epoch_usec", @@ -117,15 +118,119 @@ const MainForm = ({ vin }) => { return date.toLocaleString(); } - useEffect(() => { - fetchDTCData(); - // eslint-disable-next-line react-hooks/exhaustive-deps + const handleDateChange = (value, dateType) => { + const newDate = new Date(value); + const oldDate = dateType === "start" ? selectedStartDate || new Date() : selectedEndDate || new Date(); + newDate.setHours(oldDate.getHours()); + newDate.setMinutes(oldDate.getMinutes()); + newDate.setSeconds(oldDate.getSeconds()); + if (dateType === "start") { + setSelectedStartDate(newDate); + } else { + setSelectedEndDate(newDate); + } + }; + + const handleTimeFromChange = (value) => { + setSelectedStartDate(value); + }; + + const handleTimeToChange = (value) => { + setSelectedEndDate(value); + }; + + const displayTimeAsGMT = (date) => { + return gmtTimezone + ? date.toLocaleString("en-US", { timeZone: "Etc/GMT" }) + : date; + } + + useEffect(() => { + fetchDTCData(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [vin, selectedECU, selectedStartDate, selectedEndDate, pageIndex, pageSize, order, orderBy]); return (
- - + + + + + + handleDateChange(value, "start")} + KeyboardButtonProps={{ + 'aria-label': 'change date', + }} + /> + + + + + + handleDateChange(value, "end")} + KeyboardButtonProps={{ + 'aria-label': 'change date', + }} + /> + + + + + + setGmtTimezone((current) => !current)} + /> + } + /> + + + + +
{ />
- - - - - - - - - - - + - -
+
{ ))} - + { onPageChange={handleChangePageIndex} onRowsPerPageChange={handleChangePageSize} /> - - + +
-
+
+
); diff --git a/src/components/DTCTimeline/DTCTimeline/index.test.jsx b/src/components/DTCTimeline/DTCTimeline/index.test.jsx new file mode 100644 index 0000000..58e29f1 --- /dev/null +++ b/src/components/DTCTimeline/DTCTimeline/index.test.jsx @@ -0,0 +1,42 @@ +jest.mock("../../Contexts/StatusContext"); +jest.mock("../../Contexts/UserContext"); +jest.mock("../../../services/CANSignalAPI"); +jest.useFakeTimers(); +jest.setSystemTime(new Date(2023, 3, 1, 6, 30, 45, 100)); + +import { render, waitFor } from "@testing-library/react"; +import { BrowserRouter } from "react-router-dom"; +import addSnapshotSerializer from "../../../utils/snapshot"; +import { TEST_AUTH_OBJECT_FISKER } from "../../../utils/testing"; + +import { StatusProvider } from "../../Contexts/StatusContext"; +import { setToken, UserProvider } from "../../Contexts/UserContext"; +import DTCTimeline from "./index"; + +const renderDTCTimeline = async () => { + const { container } = render( + + + + + + + + ); + await waitFor(() => { + /* render */ + }); + return container; +}; + +describe("Render", () => { + beforeAll(() => { + addSnapshotSerializer(expect); + }); + + it("Render", async () => { + setToken(TEST_AUTH_OBJECT_FISKER); + const container = await renderDTCTimeline(); + expect(container).toMatchSnapshot(); + }); +}); From 5a8b847641a6d7f95a7ce9801921e858d5dc30b9 Mon Sep 17 00:00:00 2001 From: Paul Adamsen <117673433+pauladamseniii@users.noreply.github.com> Date: Wed, 7 Jun 2023 12:14:20 -0400 Subject: [PATCH 07/12] CEC-4248 - Fixes to DTC tab (#350) * CEC-4248 - Add time settings to DTC timeline page * CEC-4248 - fixes to DTC tab --- .../__snapshots__/index.test.jsx.snap | 52 +++++++------------ .../DTCTimeline/DTCTimeline/index.jsx | 22 +++++--- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap b/src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap index 222305a..3cde435 100644 --- a/src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap +++ b/src/components/DTCTimeline/DTCTimeline/__snapshots__/index.test.jsx.snap @@ -342,53 +342,39 @@ exports[`Render Render 1`] = ` style="margin-bottom: 8px;" >
- + +
diff --git a/src/components/DTCTimeline/DTCTimeline/index.jsx b/src/components/DTCTimeline/DTCTimeline/index.jsx index bd788ae..199bc83 100644 --- a/src/components/DTCTimeline/DTCTimeline/index.jsx +++ b/src/components/DTCTimeline/DTCTimeline/index.jsx @@ -1,5 +1,5 @@ import DateFnsUtils from '@date-io/date-fns'; -import { Button, Checkbox, CircularProgress, FormControlLabel, Grid, Table, TableBody, TableCell, TableFooter, TablePagination, TableRow } from "@material-ui/core"; +import { Button, Checkbox, CircularProgress, FormControlLabel, Grid, Table, TableBody, TableCell, TableFooter, TablePagination, TableRow, TextField } from "@material-ui/core"; import { KeyboardDatePicker, KeyboardTimePicker, MuiPickersUtilsProvider } from '@material-ui/pickers'; import clsx from "clsx"; import React, { useEffect, useState } from "react"; @@ -7,7 +7,6 @@ import { logger } from "../../../services/monitoring"; import { DTCTimelineProvider, useDTCTimelineContext } from '../../Contexts/DTCTimelineContext'; import { useStatusContext } from "../../Contexts/StatusContext"; import { useUserContext } from "../../Contexts/UserContext"; -import SearchField from '../../Controls/SearchField'; import TableHeaderSortable from "../../Table/HeaderSortable"; import { useLocalStorage } from "../../useLocalStorage"; import useStyles from "../../useStyles"; @@ -92,11 +91,9 @@ const MainForm = ({ vin }) => { setLoading(true); try { let start_date = new Date(selectedStartDate); - start_date.setHours(0, 0, 0, 0); start_date = start_date.toISOString(); let end_date = new Date(selectedEndDate); - end_date.setHours(23, 59, 59, 999); end_date = end_date.toISOString(); const search = { @@ -232,10 +229,19 @@ const MainForm = ({ vin }) => {
- { - setSelectedECU(searchValue); + { + setSelectedECU(e.target.value); }} />
From 8b73be55c51dad8f09b8174c5e9027a10d23fc71 Mon Sep 17 00:00:00 2001 From: upfisker <135734425+upfisker@users.noreply.github.com> Date: Thu, 8 Jun 2023 16:16:05 -0700 Subject: [PATCH 08/12] Removed 'Config' column as asked in the Jira ticket CEC-3509. (#352) * Removed 'Config' column as asked in the Jira ticket CEC-3509. * Updating snapshot (since UI is changed). --- .../__snapshots__/ECUsTab.test.jsx.snap | 43 ------------------- .../Controls/CarECUsTable/index.jsx | 4 -- 2 files changed, 47 deletions(-) diff --git a/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap b/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap index 8ec2646..36478a0 100644 --- a/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap +++ b/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap @@ -195,29 +195,6 @@ exports[`ECUsTab Render 1`] = ` - - - Config - - - - - - CONFIG - - @@ -433,16 +400,6 @@ exports[`ECUsTab Render 1`] = ` title="none" /> - - - CONFIG - - diff --git a/src/components/Controls/CarECUsTable/index.jsx b/src/components/Controls/CarECUsTable/index.jsx index 95d9b29..7bdb4e9 100644 --- a/src/components/Controls/CarECUsTable/index.jsx +++ b/src/components/Controls/CarECUsTable/index.jsx @@ -46,10 +46,6 @@ const tableColumns = [ id: "boot_loader_version", label: "Boot Loader", }, - { - id: "code_data_string", - label: "Config", - }, { id: "fingerprint", label: "Fingerprint", From f2377d9ed7119d5527bc6c2d6f742bef5cebd5af Mon Sep 17 00:00:00 2001 From: John Wu <76966357+jwu-fisker@users.noreply.github.com> Date: Fri, 9 Jun 2023 08:57:06 -0700 Subject: [PATCH 09/12] Revert "Removed 'Config' column as asked in the Jira ticket CEC-3509. (#352)" (#354) This reverts commit 8b73be55c51dad8f09b8174c5e9027a10d23fc71. --- .../__snapshots__/ECUsTab.test.jsx.snap | 43 +++++++++++++++++++ .../Controls/CarECUsTable/index.jsx | 4 ++ 2 files changed, 47 insertions(+) diff --git a/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap b/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap index 36478a0..8ec2646 100644 --- a/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap +++ b/src/components/Cars/Status/__snapshots__/ECUsTab.test.jsx.snap @@ -195,6 +195,29 @@ exports[`ECUsTab Render 1`] = ` + + + Config + + + + + + CONFIG + + @@ -400,6 +433,16 @@ exports[`ECUsTab Render 1`] = ` title="none" /> + + + CONFIG + + diff --git a/src/components/Controls/CarECUsTable/index.jsx b/src/components/Controls/CarECUsTable/index.jsx index 7bdb4e9..95d9b29 100644 --- a/src/components/Controls/CarECUsTable/index.jsx +++ b/src/components/Controls/CarECUsTable/index.jsx @@ -46,6 +46,10 @@ const tableColumns = [ id: "boot_loader_version", label: "Boot Loader", }, + { + id: "code_data_string", + label: "Config", + }, { id: "fingerprint", label: "Fingerprint", From a5f32151b276b86fcfdb1f06ecb96431b8ef2a0a Mon Sep 17 00:00:00 2001 From: Alexander Andrews <45926661+alexander-e-andrews@users.noreply.github.com> Date: Mon, 12 Jun 2023 17:54:32 -0400 Subject: [PATCH 10/12] CEC-4541: Force Config push (#355) --- .../App/__snapshots__/App.test.js.snap | 37 +++++++++++++++++++ .../Details/__snapshots__/index.test.jsx.snap | 37 +++++++++++++++++++ src/components/Cars/Status/Details/index.jsx | 18 ++++++++- .../__snapshots__/DetailsTab.test.jsx.snap | 37 +++++++++++++++++++ .../Status/__snapshots__/index.test.jsx.snap | 37 +++++++++++++++++++ src/components/Contexts/VehicleContext.jsx | 4 +- src/services/vehiclesAPI.js | 4 +- 7 files changed, 168 insertions(+), 6 deletions(-) diff --git a/src/components/App/__snapshots__/App.test.js.snap b/src/components/App/__snapshots__/App.test.js.snap index bb550f6..b23802c 100644 --- a/src/components/App/__snapshots__/App.test.js.snap +++ b/src/components/App/__snapshots__/App.test.js.snap @@ -11428,6 +11428,43 @@ exports[`App Route /vehicle-status authenticated 1`] = ` /> + + { const [redirect, setRedirect] = useState(null); const [showDeleteModal, setShowDeleteModal] = useState(false); const [showUploadConfigModal, setShowUploadConfigModal] = useState(false); + const [forced, setForced] = useState(false); const { token: { idToken: { jwtToken: token }, @@ -37,6 +38,10 @@ const MainForm = ({ vin }) => { const showDebugMask = (process.env.REACT_APP_ENABLE_DEBUGMASK === "1"); + const onForcedChange = (event) => { + setForced(event.target.checked); + } + useEffect(() => { (async () => { try { @@ -63,7 +68,7 @@ const MainForm = ({ vin }) => { const onUploadConfig = async () => { try { - await uploadConfig(vin, token); + await uploadConfig(vin, forced, token); setMessage(`Config Uploaded ${vin}`); } catch (e) { setMessage(e.message); @@ -159,6 +164,15 @@ const MainForm = ({ vin }) => { providers={providers} rolesPerProvider={Permissions.FiskerCreate} > + + } + /> setShowUploadConfigModal(true)}> diff --git a/src/components/Cars/Status/__snapshots__/DetailsTab.test.jsx.snap b/src/components/Cars/Status/__snapshots__/DetailsTab.test.jsx.snap index 7b0a25e..46d8008 100644 --- a/src/components/Cars/Status/__snapshots__/DetailsTab.test.jsx.snap +++ b/src/components/Cars/Status/__snapshots__/DetailsTab.test.jsx.snap @@ -176,6 +176,43 @@ exports[`DetailsTab Render 1`] = ` /> + + { } }; - const uploadConfig = async (vin, token) => { + const uploadConfig = async (vin, forced, token) => { try { setBusy(true); validateVIN(vin); - const result = await api.updateConfig(vin, token); + const result = await api.updateConfig(vin, forced, token); if (result.error) throw new Error(`Update vehicle error. ${result.message}`); return result; diff --git a/src/services/vehiclesAPI.js b/src/services/vehiclesAPI.js index a5e7d6e..4f9c359 100644 --- a/src/services/vehiclesAPI.js +++ b/src/services/vehiclesAPI.js @@ -173,8 +173,8 @@ const vehiclesAPI = { .then(fetchRespHandler) .catch(errorHandler), - updateConfig: async (vin, token) => - fetch(`${API_ENDPOINT}/car_config/${vin}`, { + updateConfig: async (vin, forced, token) => + fetch(`${API_ENDPOINT}/car_config/${vin}?forced=${forced}`, { method: "POST", headers: Object.assign( { "Content-Type": "application/json" }, From f74c717377e29b4698e6c1465160cb5324c5937c Mon Sep 17 00:00:00 2001 From: Tristan Timblin Date: Mon, 12 Jun 2023 22:41:55 -0400 Subject: [PATCH 11/12] CEC-4498 update fleetsAPI.addFleetVehicle to send vehicle in an array (#351) * CEC-4498 update fleet-vehicle-add api to take an array of vehicles --- .../App/__snapshots__/App.test.js.snap | 4 +- .../List/__snapshots__/index.test.jsx.snap | 2 +- src/components/Contexts/FleetContext.jsx | 11 +- src/components/Contexts/FleetContext.test.jsx | 14 +- .../Contexts/__mocks__/FleetContext.jsx | 2 +- .../Controls/CarSelectionTable/index.jsx | 2 +- .../Add/__snapshots__/index.test.jsx.snap | 1436 +++++++++++------ .../Fleets/Status/Vehicles/Add/index.jsx | 237 +-- src/components/useStyles.jsx | 8 + src/services/__mocks__/fleetsAPI.js | 4 +- src/services/fleetsAPI.js | 4 +- 11 files changed, 1078 insertions(+), 646 deletions(-) diff --git a/src/components/App/__snapshots__/App.test.js.snap b/src/components/App/__snapshots__/App.test.js.snap index b23802c..2b98119 100644 --- a/src/components/App/__snapshots__/App.test.js.snap +++ b/src/components/App/__snapshots__/App.test.js.snap @@ -4380,7 +4380,7 @@ exports[`App Route /package-deploy authenticated 1`] = ` data-testid="mocked-vehicleprovider" >
{ } }; - const addFleetVehicle = async (name, vehicle, token) => { + const addFleetVehicles = async (name, vehicles, token) => { try { setBusy(true); validateFleetName(name); - validateVIN(vehicle.vin); - const result = await api.addFleetVehicle(name, vehicle, token); + for (const vin of vehicles.vins) { + validateVIN(vin); + } + + const result = await api.addFleetVehicles(name, vehicles, token); if (result.error) { throw new Error(`Add fleet vehicle error. ${result.message}`); } @@ -250,7 +253,7 @@ export const FleetProvider = ({ children }) => { fleetVehicles, totalFleetVehicles, getFleetVehicles, - addFleetVehicle, + addFleetVehicles, deleteFleetVehicle, fleetCANFilters, diff --git a/src/components/Contexts/FleetContext.test.jsx b/src/components/Contexts/FleetContext.test.jsx index f595e2a..93b88a1 100644 --- a/src/components/Contexts/FleetContext.test.jsx +++ b/src/components/Contexts/FleetContext.test.jsx @@ -391,14 +391,14 @@ describe("FleetContext", () => { }); }); - describe("addFleetVehicle", () => { + describe("addFleetVehicles", () => { beforeEach(async () => { const TestComp = () => { - const { busy, addFleetVehicle } = useFleetContext(); + const { busy, addFleetVehicles } = useFleetContext(); const { message, setMessage } = useStatusContext(); const add = async (name, vehicle) => { try { - await addFleetVehicle(name, vehicle); + await addFleetVehicles(name, vehicle); } catch (e) { setMessage(e.message); } @@ -417,8 +417,8 @@ describe("FleetContext", () => { onClick={() => add({})} />
- -
-
- -
- - - - - - -
- -
- -
-
- - + + + +
-
- -
- - -
+
+ + + + + + + + + + + + + + +
+ + + + + + + + + + VIN + + sorted ascending + + + + + + Model + + + + + Year + + + + + Trim + + + + + Created + + + + + Updated + + +
- + +
+
+
+
+
+
+ +
+ + + + + + +
+ +
+ +
+ +
+ + +
+
+ +
+
+ +
+ + +
+
+
+
+
+
+
+
+
+ +
diff --git a/src/components/Fleets/Status/Vehicles/Add/index.jsx b/src/components/Fleets/Status/Vehicles/Add/index.jsx index 483b416..6b775df 100644 --- a/src/components/Fleets/Status/Vehicles/Add/index.jsx +++ b/src/components/Fleets/Status/Vehicles/Add/index.jsx @@ -1,6 +1,7 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useState } from "react"; import { Redirect, useParams } from "react-router"; import { + Box, Button, Checkbox, FormControlLabel, @@ -8,7 +9,11 @@ import { FormLabel, Radio, RadioGroup, - TextField + TextField, + Accordion, + AccordionSummary, + AccordionDetails, + Typography, } from "@material-ui/core"; import useStyles from "../../../../useStyles"; @@ -19,11 +24,14 @@ import { import { useStatusContext } from "../../../../Contexts/StatusContext"; import { useUserContext } from "../../../../Contexts/UserContext"; import { logger } from "../../../../../services/monitoring"; +import { VehicleProvider } from "../../../../Contexts/VehicleContext"; +import CarSelectionTable from "../../../../Controls/CarSelectionTable"; +import SearchField from "../../../../Controls/SearchField"; const MainForm = () => { const { name } = useParams(); const { setMessage, setTitle, setSitePath } = useStatusContext(); - const { addFleetVehicle, busy } = useFleetContext(); + const { addFleetVehicles, busy } = useFleetContext(); const { token: { idToken: { jwtToken: token }, @@ -32,7 +40,8 @@ const MainForm = () => { const classes = useStyles(); const [redirect, setRedirect] = useState(null); - const vinEl = useRef(null); + const [vins, setVins] = useState([]); + const [search, setSearch] = useState(""); const [selectedLogLevel, setSelectedLogLevel] = useState("info"); const [canbusEnabled, setCANBusEnabled] = useState(true); const [dataLoggerEnabled, setDataLoggerEnabled] = useState(false); @@ -58,6 +67,30 @@ const MainForm = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const handleSearch = (query) => { + setVins([]); + setSearch(query); + }; + + const handleSelectAll = (cars) => { + setVins(cars); + }; + + const handleSelect = (event, key) => { + try { + let newVins; + if (event.target.checked) { + newVins = [...vins]; + newVins.push(key); + } else { + newVins = vins.filter((vin) => vin !== key); + } + setVins(newVins); + } catch (e) { + logger.warn(e.stack); + } + }; + const onLogLevelChange = (event) => { setSelectedLogLevel(event.target.value); } @@ -79,11 +112,11 @@ const MainForm = () => { } const onSubmit = async (event) => { - try { - event.preventDefault(); + event.preventDefault(); + try { const formData = { - vin: vinEl.current.value, + vins, log_level: selectedLogLevel, canbus: { enabled: canbusEnabled, @@ -93,9 +126,9 @@ const MainForm = () => { } }; - const result = await addFleetVehicle(name, formData, token); + const result = await addFleetVehicles(name, formData, token); - setMessage(`Added ${result.vin}`); + setMessage(`Added ${result.vins.join(", ")}`); setRedirect(`/fleet/${name}#vehicles`); } catch (e) { setMessage(e.message); @@ -110,94 +143,106 @@ const MainForm = () => { return (
- - Log Level - - } label="Trace" /> - } label="Debug" /> - } label="Info" /> - } label="Warning" /> - } label="Error" /> - } label="Critical" /> - - CAN Bus - - - } label="CAN Bus Enabled" /> - + + - - } label="Data Logger Enabled" /> - - - + + + + + + Additional Options + + + + Log Level + + } label="Trace" /> + } label="Debug" /> + } label="Info" /> + } label="Warning" /> + } label="Error" /> + } label="Critical" /> + + CAN Bus + + + } label="CAN Bus Enabled" /> + + + } label="Data Logger Enabled" /> + + + + + + + +
); diff --git a/src/components/useStyles.jsx b/src/components/useStyles.jsx index 5e7769e..d3daf28 100644 --- a/src/components/useStyles.jsx +++ b/src/components/useStyles.jsx @@ -295,6 +295,14 @@ const useStyles = makeStyles((theme) => ({ whiteSpace: "normal", wordWrap: "break-word", }, + fleetVehicleAddSubmit: { + position: "sticky", + bottom: 0, + right: 0, + width: "100%", + padding: "16px 0", + backgroundColor: "#fafafa", + } })); export default useStyles; diff --git a/src/services/__mocks__/fleetsAPI.js b/src/services/__mocks__/fleetsAPI.js index c51b490..87fb172 100644 --- a/src/services/__mocks__/fleetsAPI.js +++ b/src/services/__mocks__/fleetsAPI.js @@ -62,8 +62,8 @@ const fleetsAPI = { getFleetVehicles: async () => { return { data: vehicles }; }, - addFleetVehicle: async (_name, vehicle) => { - vehicles.push(vehicle.vin); + addFleetVehicles: async (_name, vehicle) => { + vehicles.push(...vehicle.vins); return vehicle; }, deleteFleetVehicle: async (_name, vehicle) => { diff --git a/src/services/fleetsAPI.js b/src/services/fleetsAPI.js index 542cc5e..2576334 100644 --- a/src/services/fleetsAPI.js +++ b/src/services/fleetsAPI.js @@ -73,14 +73,14 @@ const fleetsAPI = { .then(fetchRespHandler) .catch(errorHandler), - addFleetVehicle: async (name, vehicle, token) => + addFleetVehicles: async (name, vehicles, token) => fetch(`${API_ENDPOINT}/fleet/${name}/vehicle`, { method: "POST", headers: Object.assign( { "Content-Type": "application/json" }, getAuthHeaderOptions(token) ), - body: JSON.stringify(vehicle), + body: JSON.stringify(vehicles), }) .then(fetchRespHandler) .catch(errorHandler), From 99e2058ffd76315d40487e9e6549cac8c521314e Mon Sep 17 00:00:00 2001 From: Alexander Andrews <45926661+alexander-e-andrews@users.noreply.github.com> Date: Tue, 13 Jun 2023 14:17:22 -0400 Subject: [PATCH 12/12] CEC-4356: DTC Enabled On car enabled and disable (#353) * CEC-4100: Added push config changes to vin * Fixed test * Dropped coveragte by 1% * CEC-4356: Enable dtc for create car * Updated snapshot --- .../App/__snapshots__/App.test.js.snap | 37 +++++++++++++++++++ .../Add/__snapshots__/index.test.jsx.snap | 37 +++++++++++++++++++ src/components/Cars/Add/index.jsx | 14 ++++++- .../Update/__snapshots__/index.test.jsx.snap | 2 +- src/components/Cars/Update/index.jsx | 5 +-- 5 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/components/App/__snapshots__/App.test.js.snap b/src/components/App/__snapshots__/App.test.js.snap index 2b98119..08771e4 100644 --- a/src/components/App/__snapshots__/App.test.js.snap +++ b/src/components/App/__snapshots__/App.test.js.snap @@ -10389,6 +10389,43 @@ exports[`App Route /vehicle-add authenticated 1`] = ` Data Logger Enabled +
+
{ const [dataLoggerEnabled, setDataLoggerEnabled] = useState(false); const [maxMemBufferSize, setMaxMemBufferSize] = useState(0); const [maxDiskBufferSize, setMaxDiskBufferSize] = useState(0); + const [dtcEnabled, setDTCEnabled] = useState(false); useEffect(() => { setTitle("Add Vehicle"); @@ -65,6 +66,10 @@ const MainForm = () => { setDataLoggerEnabled(event.target.checked); } + const onDtcEnabledChange = (event) => { + setDTCEnabled(event.target.checked); + } + const onMaxMemBufferSizeChange = (event) => { setMaxMemBufferSize(event.target.value); } @@ -84,7 +89,8 @@ const MainForm = () => { enabled: canbusEnabled, data_logger_enabled: canbusEnabled ? dataLoggerEnabled : false, 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, + dtc_enabled: dtcEnabled } }; @@ -166,6 +172,12 @@ const MainForm = () => { disabled={!canbusEnabled} /> } label="Data Logger Enabled" /> + + } label="DTC Enabled" /> - Data Logger Enabled + DTC Enabled
diff --git a/src/components/Cars/Update/index.jsx b/src/components/Cars/Update/index.jsx index b1d47dd..494c448 100644 --- a/src/components/Cars/Update/index.jsx +++ b/src/components/Cars/Update/index.jsx @@ -150,7 +150,7 @@ const MainForm = () => { data_logger_enabled: canbusEnabled ? dataLoggerEnabled : false, max_mem_buffer_size: canbusEnabled ? parseInt(maxMemBufferSize) : 0, max_disk_buffer_size: canbusEnabled && dataLoggerEnabled ? parseInt(maxDiskBufferSize) : 0, - dtc_enabled: canbusEnabled ? dtcEnabled : false + dtc_enabled: dtcEnabled }, debug_mask: debugMaskEl.current?.value }; @@ -382,9 +382,8 @@ const MainForm = () => { - } label="Data Logger Enabled" /> + } label="DTC Enabled" />