CEC-5421: remove delete functionality (#482)

This commit is contained in:
Tristan Timblin
2023-11-10 09:20:26 -08:00
committed by GitHub
parent 88212d6362
commit 4e29f86876
13 changed files with 3 additions and 247 deletions

View File

@@ -11842,7 +11842,6 @@ exports[`App Route /vehicle-status authenticated 1`] = `
</div>
</div>
<div />
<div />
</div>
</div>
</div>

View File

@@ -1,55 +0,0 @@
import { forwardRef, useImperativeHandle } from "react";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useUserContext } from "../../Contexts/UserContext";
import TaskRunner from "../../../utils/taskRunner";
import vehiclesAPI from "../../../services/vehiclesAPI";
export default forwardRef(({
ids,
idCSV,
}, ref) => {
const { setMessage } = useStatusContext();
const { token: { idToken: { jwtToken: token } } } = useUserContext();
useImperativeHandle(ref, () => ({
async submit() {
return new Promise((resolve, reject) => {
const taskRunner = new TaskRunner(5, ids.length);
let errorCount = 0;
const task = (vin, index) => {
const progressMessage = `${index + 1}/${ids.length}`;
return async () => vehiclesAPI.deleteVehicle(vin, token)
.then((response) => {
if (response.error) {
errorCount += 1;
setMessage(`${progressMessage} ${response.error}: ${response.message}`);
} else {
setMessage(`${progressMessage} Deleted ${vin}`);
}
return response;
})
.catch((error) => reject(error));
}
ids.forEach((vin, i) => {
taskRunner.push(task(vin, i));
});
taskRunner.onComplete().then((responses) => {
const completeMessage = `${ids.length - errorCount}/${ids.length}`;
setMessage(`Successfully deleted ${completeMessage} vehicles.`);
resolve(responses);
});
});
},
}));
return (
<div>
<p>
You are about to delete the following VINs: {idCSV}.
</p>
</div>
);
});

View File

@@ -1,40 +0,0 @@
jest.mock("../../Contexts/UserContext");
jest.mock("../../Contexts/StatusContext");
jest.mock("../../../services/vehiclesAPI");
import React from "react";
import {
render,
act,
} from "@testing-library/react";
import { UserProvider, setToken } from "../../Contexts/UserContext";
import { StatusProvider } from "../../Contexts/StatusContext";
import { TEST_AUTH_OBJECT_FISKER } from "../../../utils/testing";
import DeleteVehicles from "./DeleteVehicles";
import vehiclesAPI from "../../../services/vehiclesAPI";
describe("BulkActions/DeleteVehicles", () => {
beforeAll(() => {
setToken(TEST_AUTH_OBJECT_FISKER);
});
it("makes request to delete multiple vehicles", async () => {
const api = jest.spyOn(vehiclesAPI, "deleteVehicle");
const ref = React.createRef();
render(
<StatusProvider>
<UserProvider>
<DeleteVehicles
ref={ref}
ids={["TESTVIN123456789a", "TESTVIN123456789b", "TESTVIN123456789c"]}
idCSV=""
/>
</UserProvider>
</StatusProvider>
);
await act(async () => ref.current.submit());
expect(api).toHaveBeenCalledTimes(3);
});
});

View File

@@ -9,7 +9,6 @@ import truncateCSV from "../../utils/truncateCSV";
// https://react.dev/reference/react/lazy
const AddTags = lazy(() => import("./actions/AddTags"));
const AddToFleet = lazy(() => import("./actions/AddToFleet"));
const DeleteVehicles = lazy(() => import("./actions/DeleteVehicles"));
const UpdateConfig = lazy(() => import("./actions/UpdateConfig"));
const SendSMS = lazy(() => import("./actions/SendSMS"));
const Cancel = lazy(() => import("./actions/Cancel"));
@@ -41,12 +40,6 @@ export default function BulkActions({
disabled: false,
trigger: () => setActive("addToFleet"),
},
{
id: "deleteVehicles",
name: "Delete",
disabled: false,
trigger: () => setActive("deleteVehicles"),
},
{
id: "updateConfig",
name: "Update Config",
@@ -125,7 +118,6 @@ export default function BulkActions({
<section>
{active === "addTags" && <AddTags {...payload} />}
{active === "addToFleet" && <AddToFleet {...payload} />}
{active === "deleteVehicles" && <DeleteVehicles {...payload} />}
{active === "updateConfig" && <UpdateConfig {...payload} />}
{active === "sms" && <SendSMS {...payload} />}
{active === "cancel" && <Cancel {...payload} />}

View File

@@ -75,7 +75,7 @@ const MainForm = () => {
<AddCircleIcon fontSize="large" />
</Link>
</RoleWrap>
<BulkActions ids={selectedVins} actions={["addTags", "addToFleet", "deleteVehicles", "updateConfig"]} />
<BulkActions ids={selectedVins} actions={["addTags", "addToFleet", "updateConfig"]} />
</Grid>
<Grid item md={4} className={classes.textCenterAlign}>
<SearchField classes={classes} onSearch={handleSearch} savedSearchValue={query} />

View File

@@ -203,7 +203,6 @@ exports[`VehicleDetailsTab Render 1`] = `
</div>
</div>
<div />
<div />
</div>
</div>
</div>

View File

@@ -1,10 +1,8 @@
import { Box, Checkbox, FormControlLabel, Grid, Tooltip } from "@material-ui/core";
import DeleteIcon from "@material-ui/icons/Delete";
import EditIcon from "@material-ui/icons/Edit";
import UploadIcon from '@mui/icons-material/Upload';
import clsx from "clsx";
import React, { useEffect, useState } from "react";
import { Redirect } from "react-router";
import { Link } from "react-router-dom";
import { logger } from "../../../../services/monitoring";
@@ -16,16 +14,13 @@ import {
VehicleProvider
} from "../../../Contexts/VehicleContext";
import { RoleWrap } from "../../../Controls/RoleWrap";
import DeleteConfirmation from "../../../DeleteConfirmation";
import GeneralConfirmation from "../../../GeneralConfirmation";
import useStyles from "../../../useStyles";
const MainForm = ({ vin }) => {
const classes = useStyles();
const { setMessage } = useStatusContext();
const { vehicle, getVehicle, deleteVehicle, uploadConfig } = useVehicleContext();
const [redirect, setRedirect] = useState(null);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const { vehicle, getVehicle, uploadConfig } = useVehicleContext();
const [showUploadConfigModal, setShowUploadConfigModal] = useState(false);
const [forced, setForced] = useState(false);
const {
@@ -55,17 +50,6 @@ const MainForm = ({ vin }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [token]);
const onDelete = async () => {
try {
await deleteVehicle(vin, token);
setMessage(`Deleted ${vin}`);
setRedirect(`/vehicles`);
} catch (e) {
setMessage(e.message);
logger.warn(e.stack);
}
};
const onUploadConfig = async () => {
try {
await uploadConfig(vin, forced, token);
@@ -99,10 +83,6 @@ const MainForm = ({ vin }) => {
}
}
if (redirect && redirect.length > 0) {
return <Redirect to={redirect} />;
}
return (
<div className={clsx(classes.paper, classes.tableSize)}>
<Grid container className={classes.root} spacing={2}>
@@ -232,25 +212,8 @@ const MainForm = ({ vin }) => {
</Link>
</Tooltip>
</RoleWrap>
<RoleWrap
groups={groups}
providers={providers}
rolesPerProvider={Permissions.FiskerDelete}
>
<Tooltip key={`delete-${vin}`} title={`Delete "${vin}"`}>
<Link to="#" onClick={() => setShowDeleteModal(true)}>
<DeleteIcon aria-label={`Delete "${vin}"`} fontSize="large" />
</Link>
</Tooltip>
</RoleWrap>
</Grid>
</Grid>
<DeleteConfirmation
message={vin}
open={showDeleteModal}
close={() => setShowDeleteModal(false)}
deleteFunction={onDelete}
/>
<GeneralConfirmation
message={"push config update to:" + vin}
open={showUploadConfigModal}

View File

@@ -211,7 +211,6 @@ exports[`DetailsTab Render 1`] = `
</div>
</div>
<div />
<div />
</div>
</div>
</div>

View File

@@ -393,7 +393,6 @@ exports[`CarStatus Render 1`] = `
</div>
</div>
<div />
<div />
</div>
</div>
</div>

View File

@@ -243,20 +243,6 @@ export const VehicleProvider = ({ children }) => {
}
}
const deleteVehicle = async (vin, token) => {
try {
setBusy(true);
validateVIN(vin);
const result = await api.deleteVehicle(vin, token);
if (result.error)
throw new Error(`Delete vehicle error. ${result.message}`);
return result;
} finally {
setBusy(false);
}
};
const getCANSignals = async (vin, token) => {
try {
setBusy(true);
@@ -313,7 +299,6 @@ export const VehicleProvider = ({ children }) => {
fleets,
totalFleets,
addVehicle,
deleteVehicle,
getConnections,
getCANSignals,
getECUs,

View File

@@ -303,80 +303,6 @@ describe("VehicleContext", () => {
});
});
describe("deleteVehicle", () => {
beforeEach(async () => {
const TestComp = () => {
const { busy, deleteVehicle } = useVehicleContext();
const { message, setMessage } = useStatusContext();
const deleteV = async (name) => {
try {
await deleteVehicle(name);
} catch (e) {
setMessage(e.message);
}
};
return (
<>
<div data-testid="error">{message}</div>
<div data-testid="busy">{busy.toString()}</div>
<button
data-testid="deleteVehicleNull"
onClick={() => deleteV(null)}
/>
<button
data-testid="deleteVehicleNonexistent"
onClick={() => deleteV("11111111111111111")}
/>
<button
data-testid="deleteVehicle"
onClick={() => deleteV("3C4PDCBG0ET127145")}
/>
</>
);
};
render(
<StatusProvider>
<VehicleProvider>
<TestComp />
</VehicleProvider>
</StatusProvider>
);
});
afterEach(() => {
cleanup();
});
it("initial state", () => {
checkBaseResults("", "false");
});
it("deleteVehicleNull", async () => {
fireEvent.click(screen.getByTestId("deleteVehicleNull"));
await waitFor(() =>
expect(screen.getByTestId("busy").innerHTML).toEqual("false")
);
checkBaseResults("Invalid VIN", "false");
});
it("deleteVehicleNonexistent", async () => {
fireEvent.click(screen.getByTestId("deleteVehicleNonexistent"));
await waitFor(() =>
expect(screen.getByTestId("busy").innerHTML).toEqual("false")
);
checkBaseResults("", "false");
});
it("deleteVehicle", async () => {
fireEvent.click(screen.getByTestId("deleteVehicle"));
await waitFor(() =>
expect(screen.getByTestId("busy").innerHTML).toEqual("false")
);
checkBaseResults("", "false");
});
});
describe("sendCommand", () => {
beforeEach(async () => {
const TestComp = () => {

View File

@@ -179,7 +179,7 @@ const MainForm = ({ name }) => {
</Link>
</Grid>
<Grid item md={4}>
<BulkActions ids={selected} actions={["addTags", "deleteVehicles", "sms", "updateConfig", "remoteCommand", "diagnostic"]} />
<BulkActions ids={selected} actions={["addTags", "sms", "updateConfig", "remoteCommand", "diagnostic"]} />
</Grid>
<Grid item md={7} align="right" className={classes.textCenterAlign}>
<SearchField classes={classes} onSearch={handleSearch} />