diff --git a/src/components/Contexts/ManifestsContext.jsx b/src/components/Contexts/ManifestsContext.jsx
index 66bf4e7..c1dbde0 100644
--- a/src/components/Contexts/ManifestsContext.jsx
+++ b/src/components/Contexts/ManifestsContext.jsx
@@ -9,6 +9,21 @@ export const ManifestsProvider = ({ children }) => {
const [manifests, setManifests] = useState([]);
const [totalManifests, setTotalManifests] = useState(0);
+ const getManifest = async (id, token) => {
+ let result;
+
+ try {
+ setBusy(true);
+ result = await api.getManifest(id, token);
+ if (result.error)
+ throw new Error(`Get manifests error. ${result.message}`);
+ } finally {
+ setBusy(false);
+ }
+
+ return result;
+ };
+
const getManifests = async (search, token) => {
let result;
@@ -54,6 +69,7 @@ export const ManifestsProvider = ({ children }) => {
busy,
manifests,
totalManifests,
+ getManifest,
getManifests,
deleteManifest,
}}
diff --git a/src/components/Contexts/__mocks__/ManifestsContext.jsx b/src/components/Contexts/__mocks__/ManifestsContext.jsx
index 057eccc..0d3dbfd 100644
--- a/src/components/Contexts/__mocks__/ManifestsContext.jsx
+++ b/src/components/Contexts/__mocks__/ManifestsContext.jsx
@@ -3,6 +3,37 @@ import React from "react";
const ManifestsContext = React.createContext();
let busy = false;
+let manifest = {
+ id: 1,
+ name: "Test Deployment",
+ version: "1.0.100",
+ description: "Deployment folder test",
+ release_notes: "https://releasenotes.com",
+ ecu_list: "ICC 1000",
+ ecu_updates: [
+ {
+ name: "ICC",
+ part_number: "BBBBBB",
+ version: "1000",
+ files: [
+ {
+ file_id: "b0cda514c94080b4",
+ filename: "LARGE.jpg",
+ url: "https://upload-dev.fiskerdps.com/92bbc448-99c8-4851-91ad-f8042e4deb49/LARGE.jpg",
+ file_size: 14559274,
+ size: 14488498,
+ type: "ODX Data",
+ created: "2021-12-09T22:38:29.102813Z",
+ updated: "2021-12-09T22:38:29.102813Z",
+ },
+ ],
+ created: "2021-12-09T22:38:20.408351Z",
+ updated: "2022-01-14T00:47:08.996451Z",
+ },
+ ],
+ created: "2021-12-09T22:38:11.679943Z",
+ updated: "2022-01-14T00:47:08.996451Z",
+};
let manifests = [
{
id: 1,
@@ -22,6 +53,7 @@ export const useManifestsContext = () => ({
busy,
manifests,
totalManifests,
+ getManifest: jest.fn(() => manifest),
getManifests: jest.fn(() => manifests),
deleteManifest: jest.fn(),
});
diff --git a/src/components/Manifest/Details/__snapshots__/index.test.jsx.snap b/src/components/Manifest/Details/__snapshots__/index.test.jsx.snap
new file mode 100644
index 0000000..c34c539
--- /dev/null
+++ b/src/components/Manifest/Details/__snapshots__/index.test.jsx.snap
@@ -0,0 +1,223 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Manifest Details Component Render Hidden 1`] = `
+Object {
+ "asFragment": [Function],
+ "baseElement":
+
+ ,
+ "container":
,
+ "debug": [Function],
+ "findAllByAltText": [Function],
+ "findAllByDisplayValue": [Function],
+ "findAllByLabelText": [Function],
+ "findAllByPlaceholderText": [Function],
+ "findAllByRole": [Function],
+ "findAllByTestId": [Function],
+ "findAllByText": [Function],
+ "findAllByTitle": [Function],
+ "findByAltText": [Function],
+ "findByDisplayValue": [Function],
+ "findByLabelText": [Function],
+ "findByPlaceholderText": [Function],
+ "findByRole": [Function],
+ "findByTestId": [Function],
+ "findByText": [Function],
+ "findByTitle": [Function],
+ "getAllByAltText": [Function],
+ "getAllByDisplayValue": [Function],
+ "getAllByLabelText": [Function],
+ "getAllByPlaceholderText": [Function],
+ "getAllByRole": [Function],
+ "getAllByTestId": [Function],
+ "getAllByText": [Function],
+ "getAllByTitle": [Function],
+ "getByAltText": [Function],
+ "getByDisplayValue": [Function],
+ "getByLabelText": [Function],
+ "getByPlaceholderText": [Function],
+ "getByRole": [Function],
+ "getByTestId": [Function],
+ "getByText": [Function],
+ "getByTitle": [Function],
+ "queryAllByAltText": [Function],
+ "queryAllByDisplayValue": [Function],
+ "queryAllByLabelText": [Function],
+ "queryAllByPlaceholderText": [Function],
+ "queryAllByRole": [Function],
+ "queryAllByTestId": [Function],
+ "queryAllByText": [Function],
+ "queryAllByTitle": [Function],
+ "queryByAltText": [Function],
+ "queryByDisplayValue": [Function],
+ "queryByLabelText": [Function],
+ "queryByPlaceholderText": [Function],
+ "queryByRole": [Function],
+ "queryByTestId": [Function],
+ "queryByText": [Function],
+ "queryByTitle": [Function],
+ "rerender": [Function],
+ "unmount": [Function],
+}
+`;
+
+exports[`Manifest Details Component Render Shown 1`] = `
+Object {
+ "asFragment": [Function],
+ "baseElement":
+
+
+
+
+ Hide Details
+
+
+ -
+ Test Deployment 1.0.100
+
+ -
+ Deployment folder test https://releasenotes.com
+
+ -
+ ECUs:
+
+ -
+ ICC, Part: BBBBBB, Version: 1000
+
+
+ -
+ ODX Data: LARGE.jpg
+
+
+
+
+
+
+
+
+
+ ,
+ "container":
+
+
+
+ Hide Details
+
+
+ -
+ Test Deployment 1.0.100
+
+ -
+ Deployment folder test https://releasenotes.com
+
+ -
+ ECUs:
+
+ -
+ ICC, Part: BBBBBB, Version: 1000
+
+
+ -
+ ODX Data: LARGE.jpg
+
+
+
+
+
+
+
+
+
,
+ "debug": [Function],
+ "findAllByAltText": [Function],
+ "findAllByDisplayValue": [Function],
+ "findAllByLabelText": [Function],
+ "findAllByPlaceholderText": [Function],
+ "findAllByRole": [Function],
+ "findAllByTestId": [Function],
+ "findAllByText": [Function],
+ "findAllByTitle": [Function],
+ "findByAltText": [Function],
+ "findByDisplayValue": [Function],
+ "findByLabelText": [Function],
+ "findByPlaceholderText": [Function],
+ "findByRole": [Function],
+ "findByTestId": [Function],
+ "findByText": [Function],
+ "findByTitle": [Function],
+ "getAllByAltText": [Function],
+ "getAllByDisplayValue": [Function],
+ "getAllByLabelText": [Function],
+ "getAllByPlaceholderText": [Function],
+ "getAllByRole": [Function],
+ "getAllByTestId": [Function],
+ "getAllByText": [Function],
+ "getAllByTitle": [Function],
+ "getByAltText": [Function],
+ "getByDisplayValue": [Function],
+ "getByLabelText": [Function],
+ "getByPlaceholderText": [Function],
+ "getByRole": [Function],
+ "getByTestId": [Function],
+ "getByText": [Function],
+ "getByTitle": [Function],
+ "queryAllByAltText": [Function],
+ "queryAllByDisplayValue": [Function],
+ "queryAllByLabelText": [Function],
+ "queryAllByPlaceholderText": [Function],
+ "queryAllByRole": [Function],
+ "queryAllByTestId": [Function],
+ "queryAllByText": [Function],
+ "queryAllByTitle": [Function],
+ "queryByAltText": [Function],
+ "queryByDisplayValue": [Function],
+ "queryByLabelText": [Function],
+ "queryByPlaceholderText": [Function],
+ "queryByRole": [Function],
+ "queryByTestId": [Function],
+ "queryByText": [Function],
+ "queryByTitle": [Function],
+ "rerender": [Function],
+ "unmount": [Function],
+}
+`;
diff --git a/src/components/Manifest/Details/index.jsx b/src/components/Manifest/Details/index.jsx
new file mode 100644
index 0000000..e87389d
--- /dev/null
+++ b/src/components/Manifest/Details/index.jsx
@@ -0,0 +1,94 @@
+import React, { useState, useEffect } from "react";
+import { useParams } from "react-router";
+
+import { useManifestsContext } from "../../Contexts/ManifestsContext";
+import { useStatusContext } from "../../Contexts/StatusContext";
+import { useUserContext } from "../../Contexts/UserContext";
+import useStyles from "../../useStyles";
+
+const ECUFileList = (files) => {
+ if (!files || files.length === 0) return "No files";
+ return (
+
+ {files.map((file) => (
+ - {`${file.type}: ${file.filename} `}
+ ))}
+
+ );
+};
+
+const ECUList = (ecus) => {
+ if (!ecus || ecus.length === 0) return "None";
+ return (
+
+ {ecus.map((ecu) => (
+ -
+ {`${ecu.name}, Part: ${ecu.part_number}, Version: ${ecu.version}`}
+
+ {ECUFileList(ecu.files)}
+
+ ))}
+
+ );
+};
+
+const ManifestDetails = ({ opened }) => {
+ const classes = useStyles();
+ const { manifest_id } = useParams();
+ const [manifest, setManifest] = useState(null);
+ const [open, setOpen] = useState(opened || false);
+ const { getManifest } = useManifestsContext();
+ const { setMessage } = useStatusContext();
+ const {
+ token: {
+ idToken: { jwtToken: token },
+ },
+ } = useUserContext();
+
+ const init = async () => {
+ try {
+ const result = await getManifest(manifest_id, token);
+ if (result.error) {
+ throw new Error(`Get manifest error. ${result.message}`);
+ } else {
+ setManifest(result);
+ }
+ } catch (e) {
+ setMessage(e.message);
+ }
+ };
+
+ const toggleOpen = (e) => {
+ e.preventDefault();
+ setOpen(!open);
+ };
+
+ useEffect(() => {
+ if (!open || manifest) return;
+ init();
+ // eslint-disable-next-line
+ }, [open]);
+
+ if (!open)
+ return (
+
toggleOpen(e)}>
+ Show Details
+
+ );
+ if (manifest === null) return
Loading Manifest...
;
+
+ return (
+ <>
+
toggleOpen(e)}>
+ Hide Details
+
+
+ - {`${manifest.name} ${manifest.version}`}
+ - {`${manifest.description} ${manifest.release_notes}`}
+ - ECUs: {ECUList(manifest.ecu_updates)}
+
+ >
+ );
+};
+
+export default ManifestDetails;
diff --git a/src/components/Manifest/Details/index.test.jsx b/src/components/Manifest/Details/index.test.jsx
new file mode 100644
index 0000000..33289de
--- /dev/null
+++ b/src/components/Manifest/Details/index.test.jsx
@@ -0,0 +1,46 @@
+jest.mock("../../Contexts/ManifestsContext");
+jest.mock("../../Contexts/UserContext");
+
+import React from "react";
+import { render, waitFor } from "@testing-library/react";
+import { BrowserRouter } from "react-router-dom";
+
+import { ManifestsProvider } from "../../Contexts/ManifestsContext";
+import { UserProvider, setToken } from "../../Contexts/UserContext";
+import { StatusProvider } from "../../Contexts/StatusContext";
+import ManifestDetails from ".";
+import { TEST_AUTH_OBJECT } from "../../../utils/testing";
+
+const TestComponent = (opened) => (
+
+
+
+
+
+
+
+
+
+);
+
+describe("Manifest Details Component", () => {
+ beforeAll(() => {
+ setToken(TEST_AUTH_OBJECT);
+ });
+
+ it("Render Hidden", async () => {
+ const rendered = render(TestComponent(false));
+ await waitFor(() => {
+ // pause for render
+ });
+ expect(rendered).toMatchSnapshot();
+ });
+
+ it("Render Shown", async () => {
+ const rendered = render(TestComponent(true));
+ await waitFor(() => {
+ // pause for render
+ });
+ expect(rendered).toMatchSnapshot();
+ });
+});
diff --git a/src/components/Manifest/Status/index.jsx b/src/components/Manifest/Status/index.jsx
index 7334238..93f0bc8 100644
--- a/src/components/Manifest/Status/index.jsx
+++ b/src/components/Manifest/Status/index.jsx
@@ -26,6 +26,7 @@ import { useStatusContext } from "../../Contexts/StatusContext";
import useStyles from "../../useStyles";
import { LocalDateTimeString } from "../../../utils/dates";
import { logger } from "../../../services/monitoring";
+import ManifestDetails from "../Details";
const MainForm = () => {
const { manifest_id } = useParams();
@@ -182,6 +183,7 @@ const MainForm = () => {
const ManifestStatus = () => (
+
diff --git a/src/services/__mocks__/manifestsAPI.js b/src/services/__mocks__/manifestsAPI.js
index 11436c8..312d4f5 100644
--- a/src/services/__mocks__/manifestsAPI.js
+++ b/src/services/__mocks__/manifestsAPI.js
@@ -1,12 +1,10 @@
-
-
const manifestsAPI = {
createCarUpdates: async (data, token) => {
if (!data.id) data.id = 0;
data.id++;
return data;
},
-
+
getPackages: async (search, token) => {
return {
data: [
@@ -30,9 +28,9 @@ const manifestsAPI = {
version: "1.2",
link: "https://cloudfront.com/download",
ecu_list: "ECU1 1.1.0,ECU2 1.1.2",
- }
- ]
- }
+ },
+ ],
+ };
},
updatePackage: async (data, token) => {
@@ -54,6 +52,40 @@ const manifestsAPI = {
getCarUpdateProgress: async (carupdateids, token) => {
return { statuses: [] };
},
+
+ getManifest: async (id, token) => {
+ return {
+ id,
+ name: "Test Deployment",
+ version: "1.0.100",
+ description: "Deployment folder test",
+ release_notes: "https://releasenotes.com",
+ ecu_list: "ICC 1000",
+ ecu_updates: [
+ {
+ name: "ICC",
+ part_number: "BBBBBB",
+ version: "1000",
+ files: [
+ {
+ file_id: "b0cda514c94080b4",
+ filename: "LARGE.jpg",
+ url: "https://upload-dev.fiskerdps.com/92bbc448-99c8-4851-91ad-f8042e4deb49/LARGE.jpg",
+ file_size: 14559274,
+ size: 14488498,
+ type: "ODX Data",
+ created: "2021-12-09T22:38:29.102813Z",
+ updated: "2021-12-09T22:38:29.102813Z",
+ },
+ ],
+ created: "2021-12-09T22:38:20.408351Z",
+ updated: "2022-01-14T00:47:08.996451Z",
+ },
+ ],
+ created: "2021-12-09T22:38:11.679943Z",
+ updated: "2022-01-14T00:47:08.996451Z",
+ };
+ },
};
export default manifestsAPI;
diff --git a/src/services/manifestsAPI.js b/src/services/manifestsAPI.js
index 473b6ab..96cc485 100644
--- a/src/services/manifestsAPI.js
+++ b/src/services/manifestsAPI.js
@@ -16,6 +16,17 @@ const manifestsAPI = {
),
}).then(fetchRespHandler),
+ getManifest: async (id, token) => {
+ const u = addQueryParams(`${API_ENDPOINT}/manifest`, { id });
+ return fetch(u, {
+ method: "GET",
+ headers: Object.assign(
+ { "Content-Type": "application/json" },
+ getAuthHeaderOptions(token)
+ ),
+ }).then(fetchRespHandler);
+ },
+
getManifests: async (search, token) => {
const u = addQueryParams(`${API_ENDPOINT}/manifests`, search);
return fetch(u, {