diff --git a/src/components/BulkActions/actions/Diagnostic.jsx b/src/components/BulkActions/actions/Diagnostic.jsx
index 2120abb..a124957 100644
--- a/src/components/BulkActions/actions/Diagnostic.jsx
+++ b/src/components/BulkActions/actions/Diagnostic.jsx
@@ -1,17 +1,31 @@
import { forwardRef, useImperativeHandle, useState, useEffect } from "react";
import {
+ Box,
FormControl,
+ FormControlLabel,
+ Grid,
+ TextField,
InputLabel,
Select,
+ Switch,
} from "@material-ui/core";
import api from "../../../services/vehiclesAPI";
import TaskRunner from "../../../utils/taskRunner";
-import { AllECUsCommand, DIAGNOSTIC_COMMANDS } from "../../Controls/SendDiagnosticCommand";
+import { AllECUsCommand } from "../../Controls/SendDiagnosticCommand";
import useStyles from "../../useStyles";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import unionIntersect from "../../../utils/unionIntersect";
+const DIAGNOSTIC_COMMANDS = [
+ { displayname: "Reset", val: "remote_reset", ecu_name: true },
+ { displayname: "Set CAN Network State", val: "can_network", state: "can_net_action" },
+ { displayname: "Set Remote Ignition", val: "remote_ignition", state: "can_net_action" },
+ { displayname: "Read ECU versions", val: "read_ecu_versions", allowAll: true, ecu_name: true },
+];
+
+const DEFAULT_SECONDS = 180;
+
async function getECUsByVINs(vins, token) {
return new Promise((resolve, reject) => {
const taskRunner = new TaskRunner(30, vins.length);
@@ -46,6 +60,8 @@ export default forwardRef(({
const [currentECU, setCurrentECU] = useState("");
const [validateECUs, setValidateECUs] = useState(false);
const [command, setCommand] = useState(DIAGNOSTIC_COMMANDS[0]);
+ const [checked, setChecked] = useState(false);
+ const [seconds, setSeconds] = useState(DEFAULT_SECONDS);
const classes = useStyles();
const { setMessage } = useStatusContext();
const { token: { idToken: { jwtToken: token } } } = useUserContext();
@@ -56,15 +72,12 @@ export default forwardRef(({
return Promise.reject("Invalid ECUs found, cannot submit");
}
- return api.sendDiagnosticCommand(ids, {
- command: command.val,
- ecu_name: currentECU,
- }, token)
+ return api.sendDiagnosticCommand(ids, createDiagnosticPayload(command, checked, currentECU, seconds), token)
.then(() => {
- setMessage(`Sent ${command} command to ${ids.length} vehicles.`);
+ setMessage(`Sent ${command.val} command to ${ids.length} vehicles.`);
})
.catch(() => {
- setMessage(`Failed to send ${command} command.`);
+ setMessage(`Failed to send ${command.val} command.`);
});
}
}));
@@ -73,6 +86,17 @@ export default forwardRef(({
setCommand(DIAGNOSTIC_COMMANDS[e.target.value]);
};
+ const handleSwitch = (e) => {
+ setChecked(e.target.checked);
+ }
+
+ const handleSecondsChange = (e) => {
+ const value = Number(e.target.value);
+ if (value > 0) {
+ setSeconds();
+ }
+ }
+
useEffect(() => {
async function fetchData() {
setValidateECUs(false);
@@ -82,22 +106,26 @@ export default forwardRef(({
fetchData();
}, [ids, token]);
+ useEffect(() => {
+ if (!checked) {
+ setSeconds(DEFAULT_SECONDS);
+ }
+ }, [checked, setSeconds]);
+
+ useEffect(() => {
+ setChecked(false);
+ }, [command, setChecked]);
+
useEffect(() => {
setValidateECUs(true);
setCurrentECU(ecus[0].ecu);
}, [ecus]);
return (
-
+
Attempt to send a vehicle diagnostic command to the following VINs: {idCSV}.
-
@@ -117,6 +145,57 @@ export default forwardRef(({
))}
-
+
+ {["remote_reset", "read_ecu_versions"].includes(command.val) && }
+
+ {["can_network", "remote_ignition"].includes(command.val) && (
+
+
+ }
+ />
+
+
+
+ )}
+
);
-});
\ No newline at end of file
+});
+
+const hasOwnProperty = (obj, key) => {
+ return Object.prototype.hasOwnProperty.call(obj, key);
+}
+
+const createDiagnosticPayload = (command = {}, checked, ecu, seconds) => {
+ const payload = {
+ command: command.val,
+ };
+
+ if (hasOwnProperty(command, "ecu_name")) {
+ payload.ecu_name = ecu;
+ }
+
+ if (hasOwnProperty(command, "state")) {
+ payload[command.state] = checked ? "on" : "off";
+ payload.timeout = seconds;
+ }
+
+ return payload;
+}
\ No newline at end of file
diff --git a/src/components/Cars/List/useQuery.js b/src/components/Cars/List/useQuery.js
index 48d353b..186a8e3 100644
--- a/src/components/Cars/List/useQuery.js
+++ b/src/components/Cars/List/useQuery.js
@@ -14,6 +14,8 @@ function parseVin(vin = "") {
return [true, vin.replace(prefix, "")];
}
+ vin = vin.replace(/[^\p{L}\d]/gu, '');
+
var re = new RegExp("^[A-HJ-NPR-Z0-9]{8}[0-9X][A-HJ-NPR-Z0-9]{2}[0-9]{6}$");
return [vin.match(re), vin];
}
diff --git a/src/components/Cars/List/useQuery.test.jsx b/src/components/Cars/List/useQuery.test.jsx
index fbf2e1b..04b8b7e 100644
--- a/src/components/Cars/List/useQuery.test.jsx
+++ b/src/components/Cars/List/useQuery.test.jsx
@@ -89,6 +89,22 @@ describe("useQuery", () => {
["test", "VCF1EBE2008016235,VCF1EBE20PG001002,VCF1EBE20PG001162", "test vin:VCF1EBE2008016235 vin:VCF1EBE20PG001002 vin:VCF1EBE20PG001162"]
],
+ [
+ "parses a space separated search query with special characters",
+ "[ocean] pe@r a!aska r*nin",
+ ["[ocean] pe@r a!aska r*nin", "", "[ocean] pe@r a!aska r*nin"]
+ ],
+ [
+ "parses a space separated vin query with special characters",
+ "[\"VCF1EBE2008016235\", \"VCF1EBE20PG001002\", \"VCF1EBE20PG001162\"]",
+ ["", "VCF1EBE2008016235,VCF1EBE20PG001002,VCF1EBE20PG001162", "vin:VCF1EBE2008016235 vin:VCF1EBE20PG001002 vin:VCF1EBE20PG001162"]
+ ],
+ [
+ "parses a space separated mixed search and vin query with special characters",
+ "te$t VCF1EBE20@*(08016235 [VCF1EBE2]0PG001002 VCF*1EBE20PG001162",
+ ["te$t", "VCF1EBE2008016235,VCF1EBE20PG001002,VCF1EBE20PG001162", "te$t vin:VCF1EBE2008016235 vin:VCF1EBE20PG001002 vin:VCF1EBE20PG001162"]
+ ],
+
[
"trims extraneous values from search",
"ocean,, , ,,,,pear,,, ",
diff --git a/src/components/Controls/SendDiagnosticCommand/index.jsx b/src/components/Controls/SendDiagnosticCommand/index.jsx
index 68c878b..cdcfc6c 100644
--- a/src/components/Controls/SendDiagnosticCommand/index.jsx
+++ b/src/components/Controls/SendDiagnosticCommand/index.jsx
@@ -13,13 +13,13 @@ import {
useVehicleContext
} from "../../Contexts/VehicleContext";
-export const DIAGNOSTIC_COMMANDS = [
+const DIAGNOSTIC_COMMANDS = [
{ displayname: "Reset", val: "remote_reset" },
{ displayname: "Set CAN Network State", val: "can_network" },
{ displayname: "Set Remote Ignition", val: "remote_ignition" },
{ displayname: "Send Wake Up SMS", val: "sms" },
// { displayname: "Update SecOC keys", val: "write_secoc_key" },
- { displayname: "Read ECU versions", val: "read_ecu_versions", allowAll: true },
+ { displayname: "Read ECU versions", val: "read_ecu_versions" },
]
const SendDiagnosticCommand = ({ vin, token, classes }) => {
@@ -195,6 +195,7 @@ export const AllECUsCommand = ({ classes, ecus, currentECU, setCurrentECU }) =>
className={classes.formControl}
variant="outlined"
size="small"
+ margin="normal"
>
ECU