diff --git a/src/components/Contexts/CarUpdatesContext.jsx b/src/components/Contexts/CarUpdatesContext.jsx index 1ce0bde..ef4d3d3 100644 --- a/src/components/Contexts/CarUpdatesContext.jsx +++ b/src/components/Contexts/CarUpdatesContext.jsx @@ -55,6 +55,21 @@ export const CarUpdatesProvider = ({ children }) => { return result; }; + const deployUpdate = async (id, token) => { + let result; + + try { + setBusy(true); + result = await api.deployCarUpdate(id, token); + if (result.error) + throw new Error(`Cancel car update error. ${result.message}`); + } finally { + setBusy(false); + } + + return result; + }; + const deployCarUpdates = async (data, token) => { let result; @@ -295,6 +310,7 @@ export const CarUpdatesProvider = ({ children }) => { totalCarUpdates, versions, cancelUpdate, + deployUpdate, deployCarUpdates, deployFleetUpdates, getCarUpdates, diff --git a/src/components/Controls/CarUpdatesTable/index.jsx b/src/components/Controls/CarUpdatesTable/index.jsx index dd5be6b..4498242 100644 --- a/src/components/Controls/CarUpdatesTable/index.jsx +++ b/src/components/Controls/CarUpdatesTable/index.jsx @@ -1,4 +1,5 @@ import { + IconButton, LinearProgress, Table, TableBody, @@ -6,9 +7,9 @@ import { TableFooter, TablePagination, TableRow, - Tooltip } from "@material-ui/core"; import CancelIcon from "@material-ui/icons/Cancel"; +import ReplayIcon from "@material-ui/icons/Replay"; import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; @@ -71,6 +72,7 @@ const MainForm = ({ vin, token }) => { const [order, setOrder] = useState("desc"); const { cancelUpdate, + deployUpdate, getCarUpdates, carUpdates, totalCarUpdates, @@ -158,6 +160,28 @@ const MainForm = ({ vin, token }) => { } }; + const sendDeploy = async (row) => { + try { + await deployUpdate(row.id, token); + setMessage(`Sent deploy for ${updateName(row)}`); + } catch (e) { + setMessage(e.message); + } + }; + + const isActiveCarUpdate = (status) => { + switch (status) { + case "manifest_error": + case "manifest_rollback": + case "manifest_succeeded": + case "manifest_cancelled": + case "cleanup_succeeded": + return false; + default: + return true; + } + } + return ( { providers={providers} rolesPerProvider={Permissions.FiskerMagnaCreate} > - - sendCancel(row)}> - - - + sendCancel(row)} + aria-label={`Send cancel for ${row.vin}`} + size="small" + color="primary" + > + + + sendDeploy(row)} + aria-label={`Send deploy for ${row.vin}`} + size="small" + disabled={!isActiveCarUpdate(row.status)} + > + + diff --git a/src/services/updatesAPI.js b/src/services/updatesAPI.js index 70cc1c8..83f0736 100644 --- a/src/services/updatesAPI.js +++ b/src/services/updatesAPI.js @@ -87,6 +87,18 @@ const updatesAPI = { .catch(errorHandler); }, + deployCarUpdate: async (id, token) => { + return fetch(`${API_ENDPOINT}/carupdate/${id}/deploy`, { + method: "POST", + headers: Object.assign( + { "Content-Type": "application/json" }, + getAuthHeaderOptions(token) + ), + }) + .then(fetchRespHandler) + .catch(errorHandler); + }, + getSUMSVersions: async (token) => { return fetch(`${API_ENDPOINT}/manifest/sums`, { method: "GET",