CEC-5443 - Ability to add Flashpack/ECU mappings

This commit is contained in:
padamsen_fisker
2023-11-30 10:59:31 -05:00
parent f4652b5de7
commit 076b7ab7b5
8 changed files with 590 additions and 0 deletions

View File

@@ -456,6 +456,28 @@ exports[`App Route / authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -1853,6 +1875,28 @@ exports[`App Route /home authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -2627,6 +2671,28 @@ exports[`App Route /issue-info authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -3239,6 +3305,28 @@ exports[`App Route /issues authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -4220,6 +4308,28 @@ exports[`App Route /package-deploy authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -5324,6 +5434,28 @@ exports[`App Route /package-status authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -6383,6 +6515,28 @@ exports[`App Route /packages authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -7561,6 +7715,28 @@ exports[`App Route /page-not-found authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -8189,6 +8365,28 @@ exports[`App Route /tools/certificates/add authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -9483,6 +9681,28 @@ exports[`App Route /tools/sms/send authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -10210,6 +10430,28 @@ exports[`App Route /vehicle-add authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -11392,6 +11634,28 @@ exports[`App Route /vehicle-status authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
@@ -12503,6 +12767,28 @@ exports[`App Route /vehicles authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>

View File

@@ -30,6 +30,8 @@ export const VehicleProvider = ({ children }) => {
const [totalFleets, setTotalFleets] = useState(0);
const [models, setModels] = useState([]);
const [years, setYears] = useState([]);
const [flashpacks, setFlashpacks] = useState([]);
const [totalFlashpacks, setTotalFlashpacks] = useState(0);
const addConnections = async (cars, token) => {
try {
@@ -287,6 +289,26 @@ export const VehicleProvider = ({ children }) => {
}
};
const getAllFlashpacks = async (options, token) => {
let result;
try {
setBusy(true);
result = await api.getAllFlashpacks(options, token);
if (result.error)
throw new Error(`Get all flashpacks error. ${result.message}`);
setFlashpacks(result.data);
if (options && options.offset === 0 && result.total) {
setTotalFlashpacks(result.total);
}
} finally {
setBusy(false);
}
return result;
};
return (
<VehicleContext.Provider
value={{
@@ -316,6 +338,12 @@ export const VehicleProvider = ({ children }) => {
getVersionLog,
uploadConfig,
addTags,
flashpacks,
totalFlashpacks,
getAllFlashpacks,
// getFlashpackECUMappings,
// addFlashpackECUMapping,
// deleteFlashpackECUMapping,
}}
>
{children}

View File

@@ -0,0 +1,154 @@
import {
Table,
TableBody,
TableCell,
TableFooter,
TablePagination,
TableRow,
} from "@material-ui/core";
import { logger } from "../../services/monitoring";
import React, { useEffect, useState } from "react";
import { useVehicleContext, VehicleProvider } from "../Contexts/VehicleContext";
import { useStatusContext } from "../Contexts/StatusContext";
import { useUserContext } from "../Contexts/UserContext";
import TableHeaderSortable from "../Table/HeaderSortable";
import { useLocalStorage } from "../useLocalStorage";
import useStyles from "../useStyles";
const tableColumns = [
{
id: "flashpack",
label: "Flashpack Number",
},
];
const PAGE_SIZE = "FLASHPACKS_TABLE_PAGE_SIZE";
const MainForm = () => {
const classes = useStyles();
const { setMessage, setTitle, setSitePath } = useStatusContext();
const [pageSize, setPageSize] = useLocalStorage(PAGE_SIZE, 10);
const [pageIndex, setPageIndex] = useState(0);
const [orderBy, setOrderBy] = useState("flashpack");
const [order, setOrder] = useState("desc");
const {
getAllFlashpacks,
flashpacks,
totalFlashpacks,
} = useVehicleContext();
const {
token: {
idToken: { jwtToken: token },
},
} = useUserContext();
useEffect(() => {
setTitle("Flashpacks");
setSitePath([
{
label: "Tools",
link: "/tools/flashpacks",
},
]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
loadFlashpacks();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [token, token, pageIndex, pageSize, orderBy, order]);
const loadFlashpacks = async () => {
try {
if (!token) return;
await getAllFlashpacks(
{
limit: pageSize,
offset: pageSize * pageIndex,
order: `${orderBy} ${order}`,
},
token
);
} catch (e) {
setMessage(e.message);
logger.warn(e.stack);
}
};
const handleChangePageIndex = (event, newIndex) => {
setPageIndex(newIndex);
};
const handleChangePageSize = (event) => {
setPageSize(parseInt(event.target.value, 10));
setPageIndex(0);
};
const handleSort = (event, property) => {
try {
if (property === orderBy) {
if (order === "asc") {
setOrder("desc");
} else {
setOrder("asc");
}
} else {
setOrderBy(property);
setOrder("asc");
}
} catch (e) {
logger.warn(e.stack);
}
};
return (
<div>
<Table>
<TableHeaderSortable
classes={classes}
orderBy={orderBy}
order={order}
columnData={tableColumns}
onSortRequest={handleSort}
/>
<TableBody>
{flashpacks && flashpacks.map((row, index) => (
<TableRow key={index}>
<TableCell align="center">
{row}
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
{!flashpacks || flashpacks.length === 0 ? (
<TableCell colSpan={8} align="center">No Flashpack Numbers</TableCell>
) : (
<TablePagination
rowsPerPageOptions={[5, 10, 25, 100]}
colSpan={1}
count={totalFlashpacks}
rowsPerPage={pageSize}
page={pageIndex}
SelectProps={{
inputProps: { "aria-label": "rows per page" },
native: true,
}}
onPageChange={handleChangePageIndex}
onRowsPerPageChange={handleChangePageSize}
/>)}
</TableRow>
</TableFooter>
</Table>
</div>
);
};
const Flashpacks = () => (
<VehicleProvider>
<MainForm />
</VehicleProvider>
);
export default Flashpacks;

View File

@@ -79,6 +79,11 @@ const menuData = [
to: "/tools/sms/send",
rolesPerProvider: Permissions.FiskerCreate,
},
{
label: "Flashpack",
to: "/tools/flashpacks",
rolesPerProvider: Permissions.FiskerRead,
},
],
},
];

View File

@@ -375,6 +375,28 @@ exports[`SideMenu Authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/tools/flashpacks"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Flashpack
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>

View File

@@ -40,6 +40,7 @@ const SecurityDLL = React.lazy(() => import("../Magna/SecurityDLL"));
const SMSSend = React.lazy(() => import("../SMS/Send"));
const SuppliersList = React.lazy(() => import("../Suppliers/List"));
const SupplierDetails = React.lazy(() => import("../Suppliers/Details"));
const Flashpacks = React.lazy(() => import("../Flashpack"));
const Datascope = React.lazy(() => import("../Dashboard"));
const SumsRxSwin = React.lazy(() => import("../SUMS"));
const SumsRxSwinAdd = React.lazy(() => import("../SUMS/Add"));
@@ -280,6 +281,24 @@ const SiteRoutes = () => {
rolesPerGroup={Permissions.FiskerCreate}
providers={providers}
/>
<AuthRoute
path="/tools/flashpacks"
render={() => <Flashpacks />}
type={TYPES.PROTECTED}
token={token}
groups={groups}
rolesPerGroup={Permissions.FiskerRead}
providers={providers}
/>
{/* <AuthRoute
path="/tools/flashpack/:flashpack"
render={() => <Flashpack />}
type={TYPES.PROTECTED}
token={token}
groups={groups}
rolesPerGroup={Permissions.FiskerCreate}
providers={providers}
/> */}
<AuthRoute
path="/suppliers"
render={() => <SuppliersList />}

View File

@@ -199,6 +199,36 @@ const vehiclesAPI = {
sendDiagnosticCommand: async (search) => ({
Message: `remote diagnostic command sent to ${search.vins.length} vehicles`
}),
getAllFlashpacks: async (token) => {
return {
data: ["41.14", "43.19"],
};
},
getFlashpackECUMappings: async (model, year, flashpack, token) => {
return {
"data": [
{
"flashpack": "41.14",
"car_model": "Ocean",
"car_year": 2023,
"car_ecu_name": "ADAS",
"car_ecu_version": "ADASVersion"
},
{
"flashpack": "41.14",
"car_model": "Ocean",
"car_year": 2023, "car_ecu_name": "ACUN",
"car_ecu_version": "ACUNVersion"
}
],
};
},
addFlashpackECUMapping: async (data, token) => {
return { message: "Created" };
},
deleteFlashpackECUMapping: async (data, token) => {
return { message: "Deleted" };
},
};
export default vehiclesAPI;

View File

@@ -260,6 +260,52 @@ const vehiclesAPI = {
}).then(fetchRespHandler)
.catch(errorHandler)
},
getAllFlashpacks: async (options, token) => {
return fetch(addQueryParams(`${API_ENDPOINT}/flashpack_get_all`, options), {
method: "GET",
headers: Object.assign(
{ "Content-Type": "application/json" },
getAuthHeaderOptions(token)
),
}).then(fetchRespHandler)
.catch(errorHandler)
},
getFlashpackECUMappings: async (model, year, flashpack, options, token) => {
return fetch(addQueryParams(`${API_ENDPOINT}/flashpack_ecu_mappings/${model}/${year}/${flashpack}`, options), {
method: "GET",
headers: Object.assign(
{ "Content-Type": "application/json" },
getAuthHeaderOptions(token)
),
}).then(fetchRespHandler)
.catch(errorHandler)
},
addFlashpackECUMapping: async (data, token) => {
return fetch(`${API_ENDPOINT}/flashpack_ecu_mapping`, {
method: "POST",
headers: Object.assign(
{ "Content-Type": "application/json" },
getAuthHeaderOptions(token),
),
body: JSON.stringify(data),
}).then(fetchRespHandler)
.catch(errorHandler)
},
deleteFlashpackECUMapping: async (data, token) => {
return fetch(`${API_ENDPOINT}/flashpack_ecu_mapping`, {
method: "DELETE",
headers: Object.assign(
{ "Content-Type": "application/json" },
getAuthHeaderOptions(token)
),
body: JSON.stringify(data),
}).then(fetchRespHandler)
.catch(errorHandler)
},
};
export default vehiclesAPI;