diff --git a/src/components/App/__snapshots__/App.test.js.snap b/src/components/App/__snapshots__/App.test.js.snap index ebdfb75..cb1b82f 100644 --- a/src/components/App/__snapshots__/App.test.js.snap +++ b/src/components/App/__snapshots__/App.test.js.snap @@ -4487,7 +4487,7 @@ exports[`App Route /package-deploy authenticated 1`] = ` class="MuiIconButton-label" > { + const closeLabel = hideSubmit ? "Close" : "Cancel"; + return ( ) diff --git a/src/components/BulkActions/actions/Diagnostic.jsx b/src/components/BulkActions/actions/Diagnostic.jsx new file mode 100644 index 0000000..d00476b --- /dev/null +++ b/src/components/BulkActions/actions/Diagnostic.jsx @@ -0,0 +1,120 @@ +import { forwardRef, useImperativeHandle, useState, useEffect } from "react"; +import { + FormControl, + InputLabel, + Select, +} from "@material-ui/core"; +import api from "../../../services/vehiclesAPI"; +import TaskRunner from "../../../utils/taskRunner"; +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 commands = [ + { val: "remote_reset", displayname: "Remote Reset" }, +]; + +async function getECUsByVINs(vins, token) { + return new Promise((resolve, reject) => { + const taskRunner = new TaskRunner(10, vins.length); + + const task = (vin) => { + return async () => api.getECUs({ vin, unique: true }, token) + .then((result) => { + if (result.total === 0) { + reject([]); + } + return result.data.map(({ ecu }) => ecu); + }) + .catch(() => reject([])); + } + + vins.forEach((vin) => { + taskRunner.push(task(vin)); + }); + + taskRunner.onComplete().then((results) => { + const ecus = unionIntersect(...results); + resolve(ecus.map(ecu => ({ ecu }))); + }); + }); +} + +export default forwardRef(({ + ids, + idCSV, +}, ref) => { + const [ecus, setECUs] = useState([{ ecu: "TBOX" }]); + const [currentECU, setCurrentECU] = useState(""); + const [validateECUs, setValidateECUs] = useState(false); + const [command, setCommand] = useState(""); + const classes = useStyles(); + const { setMessage } = useStatusContext(); + const { token: { idToken: { jwtToken: token } } } = useUserContext(); + + useImperativeHandle(ref, () => ({ + async submit() { + if (!validateECUs) { + return Promise.reject("Invalid ECUs found, cannot submit"); + } + + return api.sendDiagnosticCommand(ids, { + command, + ecu_name: currentECU, + }, token) + .then(() => { + setMessage(`Sent ${command} command to ${ids.length} vehicles.`); + }) + .catch(() => { + setMessage(`Failed to send ${command} command.`); + }); + } + })); + + const handleSelectCommand = (e) => { + setCommand(e.target.value); + }; + + useEffect(() => { + async function fetchData() { + setValidateECUs(false); + const ecus = await getECUsByVINs(ids, token); + setECUs(() => [{ ecu: "TBOX" }, ...ecus]); // TBOX is a hardcoded ECU + } + fetchData(); + }, [ids, token]); + + useEffect(() => { + setValidateECUs(true); + }, [ecus]); + + return ( +
+ Attempt to send a vehicle diagnostic command to the following VINs: {idCSV}. +
++ Send a remote command to the following VINs: {idCSV}. +
+