CEC-179 Car download progress (#32)

* Display download progress

* Change default

* Fix

* Fix

* Update readme

* Update readme and defaults
Fix Dockerfile
This commit is contained in:
John Wu
2021-04-30 12:58:31 -07:00
committed by GitHub
parent 7a1125cb1f
commit 4280191e49
21 changed files with 268 additions and 72 deletions

View File

@@ -99,7 +99,7 @@ describe("App", () => {
it("Route /package-upload authenticated", async () => {
setToken(TEST_AUTH_OBJECT);
await check("/package-upload", "h1", "Upload Update Package");
await check("/package-upload", "h1", "Create Update Package");
});
it("Route /vehicle-add authenticated", async () => {
@@ -109,17 +109,17 @@ describe("App", () => {
it("Route /updates authenticated", async () => {
setToken(TEST_AUTH_OBJECT);
await check("/updates", "h1", "Updates");
await check("/updates", "h1", "Update Packages");
});
it("Route /update authenticated", async () => {
setToken(TEST_AUTH_OBJECT);
await check("/update/1", "h1", "Update Package 1");
await check("/update/1", "h1", "Edit Update Package 1");
});
it("Route /carupdate-deploy authenticated", async () => {
setToken(TEST_AUTH_OBJECT);
await check("/carupdate-deploy/1", "h1", "[1] ");
await check("/carupdate-deploy/1", "h1", "Deploy [1]");
});
it("Route /carupdate-status authenticated", async () => {

View File

@@ -134,7 +134,7 @@ exports[`App Route / authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -156,7 +156,7 @@ exports[`App Route / authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -427,7 +427,7 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -449,7 +449,7 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -525,7 +525,8 @@ exports[`App Route /carupdate-deploy authenticated 1`] = `
<h1
class="MuiTypography-root MuiTypography-h5"
>
[1]
Deploy
[1]
</h1>
<form
action="{onSubmit}"
@@ -891,7 +892,7 @@ exports[`App Route /carupdate-status authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -913,7 +914,7 @@ exports[`App Route /carupdate-status authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -1356,7 +1357,7 @@ exports[`App Route /home authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -1378,7 +1379,7 @@ exports[`App Route /home authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -1649,7 +1650,7 @@ exports[`App Route /package-upload authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -1671,7 +1672,7 @@ exports[`App Route /package-upload authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -1744,7 +1745,7 @@ exports[`App Route /package-upload authenticated 1`] = `
<h1
class="MuiTypography-root MuiTypography-h5"
>
Upload Update Package
Create Update Package
</h1>
<form
action="{onSubmit}"
@@ -1847,12 +1848,19 @@ exports[`App Route /package-upload authenticated 1`] = `
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
for="description"
id="description-label"
>
Description
<span
aria-hidden="true"
class="MuiFormLabel-asterisk MuiInputLabel-asterisk"
>
*
</span>
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-multiline MuiOutlinedInput-multiline"
@@ -1864,6 +1872,7 @@ exports[`App Route /package-upload authenticated 1`] = `
maxlength="5120"
name="description"
placeholder="Package description"
required=""
rows="4"
/>
<fieldset
@@ -1875,6 +1884,7 @@ exports[`App Route /package-upload authenticated 1`] = `
>
<span>
Description
 *
</span>
</legend>
</fieldset>
@@ -1884,12 +1894,19 @@ exports[`App Route /package-upload authenticated 1`] = `
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
for="releasenotes"
id="releasenotes-label"
>
Release Notes URL
<span
aria-hidden="true"
class="MuiFormLabel-asterisk MuiInputLabel-asterisk"
>
*
</span>
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl"
@@ -1901,6 +1918,7 @@ exports[`App Route /package-upload authenticated 1`] = `
maxlength="1024"
name="releasenotes"
placeholder="Release Notes URL"
required=""
type="text"
value=""
/>
@@ -1913,6 +1931,7 @@ exports[`App Route /package-upload authenticated 1`] = `
>
<span>
Release Notes URL
 *
</span>
</legend>
</fieldset>
@@ -2164,7 +2183,7 @@ exports[`App Route /page-not-found authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -2186,7 +2205,7 @@ exports[`App Route /page-not-found authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -2446,7 +2465,7 @@ exports[`App Route /update authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -2468,7 +2487,7 @@ exports[`App Route /update authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -2541,7 +2560,7 @@ exports[`App Route /update authenticated 1`] = `
<h1
class="MuiTypography-root MuiTypography-h5"
>
Update Package
Edit Update Package
1
</h1>
<form
@@ -2999,7 +3018,7 @@ exports[`App Route /updates authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -3021,7 +3040,7 @@ exports[`App Route /updates authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -3095,7 +3114,7 @@ exports[`App Route /updates authenticated 1`] = `
<h1
class="MuiTypography-root MuiTypography-h5"
>
Updates
Update Packages
</h1>
<div
class="MuiTableContainer-root"
@@ -3465,7 +3484,7 @@ exports[`App Route /vehicle-add authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -3487,7 +3506,7 @@ exports[`App Route /vehicle-add authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -3921,7 +3940,7 @@ exports[`App Route /vehicle-status authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -3943,7 +3962,7 @@ exports[`App Route /vehicle-status authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span
@@ -4388,7 +4407,7 @@ exports[`App Route /vehicles authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -4410,7 +4429,7 @@ exports[`App Route /vehicles authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router";
import { useParams, Redirect } from "react-router";
import {
Button,
Chip,
@@ -44,6 +44,7 @@ const MainForm = () => {
const [releaseNotesLink, setReleaseNotesLink] = useState("");
const [createDate, setCreateDate] = useState("");
const [selectedVehicles, setSelectedVehicles] = useState([]);
const [redirect, setRedirect] = useState("");
const classes = useStyles();
const theme = useTheme();
const handleVehiclesChange = (event) => {
@@ -60,7 +61,7 @@ const MainForm = () => {
setMessage(
`Deployed ${packageName} ${version} to ${selectedVehicles.length} cars`
);
setSelectedVehicles([]);
setRedirect(`/carupdate-status/${packageid}`);
} catch (e) {
setMessage(e.message);
}
@@ -95,10 +96,14 @@ const MainForm = () => {
setCreateDate(tsLocalDateTimeString(data.timestamp));
}, [packages]);
if (redirect.length > 0) {
return <Redirect to={redirect} />;
}
return (
<div className={classes.paper}>
<Typography component="h1" variant="h5">
{`[${packageid}] ${packageName} ${version}`}
Deploy {`${packageName} ${version} [${packageid}]`}
</Typography>
<form className={classes.form} noValidate action="{onSubmit}">
<TextField

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router";
import {
LinearProgress,
Table,
TableBody,
TableCell,
@@ -25,16 +26,17 @@ import VehicleStatus from "../../Cars/StatusModal";
const MainForm = () => {
const { packageid } = useParams();
const classes = useStyles();
const [pageSize, setPageSize] = useState(10);
const [pageSize, setPageSize] = useState(25);
const [pageIndex, setPageIndex] = useState(0);
const [viewVIN, setViewVIN] = useState(null);
const {
getCarUpdates,
carUpdates,
totalCarUpdates,
getPackages,
packages,
startMonitor,
stopMonitor,
} = useUpdatesContext();
const { setMessage } = useStatusContext();
const {
@@ -54,6 +56,7 @@ const MainForm = () => {
useEffect(() => {
try {
stopMonitor();
getCarUpdates(
{
packageid,
@@ -68,6 +71,19 @@ const MainForm = () => {
// eslint-disable-next-line
}, [pageIndex, pageSize, token]);
useEffect(() => {
try {
if (carUpdates.length === 0) return;
startMonitor(token);
} catch (e) {
setMessage(e.message);
}
return () => {
stopMonitor();
};
// eslint-disable-next-line
}, [carUpdates]);
const handleChangePageIndex = (event, newIndex) => {
setPageIndex(newIndex);
};
@@ -113,7 +129,15 @@ const MainForm = () => {
{row.vin}
</span>
</TableCell>
<TableCell align="center">{row.status}</TableCell>
<TableCell align="center">
{row.status}
{row.progress > 0 && (
<LinearProgress
variant="determinate"
value={row.progress}
/>
)}
</TableCell>
<TableCell align="center">
{LocalDateTimeString(row.created)}
</TableCell>

View File

@@ -23,7 +23,7 @@ import { LocalDateTimeString } from "../../../utils/dates";
const MainForm = () => {
const classes = useStyles();
const [pageSize, setPageSize] = useState(5);
const [pageSize, setPageSize] = useState(25);
const [pageIndex, setPageIndex] = useState(0);
const { getVehicles, vehicles, totalVehicles } = useVehicleContext();
const { setMessage } = useStatusContext();

View File

@@ -8,7 +8,6 @@ export const FileUploadProvider = ({ children }) => {
const [progress, setProgress] = useState(0);
const [status, setStatus] = useState(null);
const [cancelUpload, setCancelUpload] = useState(null);
const [linkURL, setLinkURL] = useState(null);
const [files, setFiles] = useState(null);
const done = () => {
@@ -45,6 +44,14 @@ export const FileUploadProvider = ({ children }) => {
if (!accessToken || accessToken.length === 0) {
throw new Error("Access token required");
}
if (!formData.description || formData.description.length === 0) {
throw new Error("Package update description required");
}
if (!formData.releasenotes || formData.releasenotes.length === 0) {
throw new Error("Package update release notes link required");
}
};
const upload = async (formData, accessToken, uploadFiles) => {
@@ -55,7 +62,6 @@ export const FileUploadProvider = ({ children }) => {
const filename = file.name;
setUploading(true);
setLinkURL(null);
setProgress(0);
setStatus(`Uploading ${filename}`);
setCancelUpload(getCancelToken());
@@ -70,11 +76,11 @@ export const FileUploadProvider = ({ children }) => {
if (data.message) {
throw new Error(`${data.error}. ${data.message}`);
}
const url = data && data.link ? data.link : "No URL available";
setLinkURL(url);
setStatus(`Uploaded ${filename}`);
setCancelUpload(null);
setProgress(100);
return data;
} catch (e) {
setUploading(true);
setStatus(`Error occured: ${e.message}`);
@@ -88,7 +94,6 @@ export const FileUploadProvider = ({ children }) => {
uploading,
progress,
status,
linkURL,
files,
upload,
cancel,

View File

@@ -7,6 +7,7 @@ import {
fireEvent,
waitFor,
} from "@testing-library/react";
import { useState } from "react";
import { setUploadFileDelay } from "../../services/uploadFile";
import {
@@ -30,21 +31,26 @@ describe("FileUploadContext", () => {
progress,
uploading,
status,
linkURL,
upload,
cancel,
} = useFileUploadContext();
const { message, setMessage } = useStatusContext();
const [link, setLink] = useState(null);
const TEST_FILE = [{ name: "test.jpg", size: 0 }];
const TEST_ACCESSTOKEN = "ACCESSTOKEN";
const TEST_FORMDATA = {
packagename: "TEST",
version: "VERSION",
vehicles: ["VIN"],
description: "TEST DESC",
releasenotes: "http://releasenotes.com",
};
const exec = async (form, token, file) => {
try {
await upload(form, token, file);
const data = await upload(form, token, file);
if (data.link) {
setLink(data.link);
}
} catch (e) {
setMessage(e.message);
}
@@ -56,7 +62,7 @@ describe("FileUploadContext", () => {
<div data-testid="progress">{progress.toString()}</div>
<div data-testid="status">{status}</div>
<div data-testid="message">{message}</div>
<div data-testid="linkURL">{linkURL}</div>
<div data-testid="linkURL">{link}</div>
<button
data-testid="uploadNoFile"
onClick={() => {

View File

@@ -10,6 +10,8 @@ export const UpdatesProvider = ({ children }) => {
const [carUpdates, setCarUpdates] = useState([]);
const [totalPackages, setTotalPackages] = useState(0);
const [totalCarUpdates, setTotalCarUpdates] = useState(0);
const [delayCount, setDelayCount] = useState(0);
let progressTimer = 0;
const getPackages = async (search, token) => {
let result;
@@ -96,6 +98,86 @@ export const UpdatesProvider = ({ children }) => {
return result;
};
const applyProgressStatus = (item, status) => {
if (status.msg === "DONE") {
delete item.progress;
item.status = "downloaded";
} else if (status.msg === "downloading" && status.total > 0) {
let progress = Math.floor((100 * status.bytes) / status.total);
if (progress > 99) progress = 0;
item.progress = progress;
item.status = `downloading ${progress}%`;
} else if (status.error > 0) {
item.status = "download error";
} else {
item.status = "downloading";
}
};
const applyProgressStatuses = (statuses) => {
let items = JSON.parse(JSON.stringify(carUpdates));
statuses.forEach((status) => {
let item = items.find((item) => status.id === item.id);
if (!item || status.id === 0) return;
applyProgressStatus(item, status);
});
setCarUpdates(items);
};
const updateStatusProgress = async (token) => {
stopMonitor();
if (!token || carUpdates.length === 0) return;
try {
setBusy(true);
const carupdateids = carUpdates.reduce((accum, update) => {
if (update.status !== "downloaded") accum.push(update.id);
return accum;
}, []);
if (carupdateids.length === 0) return;
const result = await api.getCarUpdateProgress(
carupdateids.join(","),
token
);
if (result.error)
throw new Error(`Get update progress error. ${result.message}`);
applyProgressStatuses(result.statuses);
} catch (e) {
} finally {
setBusy(false);
}
};
const getDelay = () => {
if (delayCount < 3) {
setDelayCount(delayCount + 1);
return 1000;
}
for (let i = 0, len = carUpdates.length; i < len; i++) {
if (carUpdates[i].status.indexOf("downloading") > -1) return 1000;
}
return 10000;
};
const startMonitor = async (token) => {
const delay = getDelay();
stopMonitor();
progressTimer = setTimeout(() => {
updateStatusProgress(token);
}, delay);
};
const stopMonitor = async () => {
if (progressTimer === 0) return;
clearTimeout(progressTimer);
progressTimer = 0;
};
return (
<UpdatesContext.Provider
value={{
@@ -109,6 +191,8 @@ export const UpdatesProvider = ({ children }) => {
createCarUpdates,
getCarUpdates,
getVINUpdates,
startMonitor,
stopMonitor,
}}
>
{children}

View File

@@ -23,4 +23,6 @@ export const useUpdatesContext = () => ({
createCarUpdates: jest.fn((data) => data),
getCarUpdates: jest.fn(() => carUpdates),
getVINUpdates: jest.fn(() => carUpdates),
startMonitor: jest.fn(),
stopMonitor: jest.fn(),
});

View File

@@ -11,12 +11,12 @@ const menuData = [
roles: [],
},
{
label: "View Updates",
label: "View Packages",
to: "/updates",
roles: [Roles.CREATE, Roles.READ],
},
{
label: "Create Updates",
label: "Create Packages",
to: "/package-upload",
roles: [Roles.CREATE],
},

View File

@@ -44,7 +44,7 @@ exports[`SideMenu Authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
View Updates
View Packages
</span>
</div>
<span
@@ -66,7 +66,7 @@ exports[`SideMenu Authenticated 1`] = `
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Updates
Create Packages
</span>
</div>
<span

View File

@@ -11,7 +11,7 @@ exports[`File Upload Form Should render 1`] = `
<h1
class="MuiTypography-root MuiTypography-h5"
>
Upload Update Package
Create Update Package
</h1>
<form
action="{onSubmit}"
@@ -114,12 +114,19 @@ exports[`File Upload Form Should render 1`] = `
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
for="description"
id="description-label"
>
Description
<span
aria-hidden="true"
class="MuiFormLabel-asterisk MuiInputLabel-asterisk"
>
*
</span>
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-multiline MuiOutlinedInput-multiline"
@@ -131,6 +138,7 @@ exports[`File Upload Form Should render 1`] = `
maxlength="5120"
name="description"
placeholder="Package description"
required=""
rows="4"
/>
<fieldset
@@ -142,6 +150,7 @@ exports[`File Upload Form Should render 1`] = `
>
<span>
Description
 *
</span>
</legend>
</fieldset>
@@ -151,12 +160,19 @@ exports[`File Upload Form Should render 1`] = `
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined"
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
for="releasenotes"
id="releasenotes-label"
>
Release Notes URL
<span
aria-hidden="true"
class="MuiFormLabel-asterisk MuiInputLabel-asterisk"
>
*
</span>
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl"
@@ -168,6 +184,7 @@ exports[`File Upload Form Should render 1`] = `
maxlength="1024"
name="releasenotes"
placeholder="Release Notes URL"
required=""
type="text"
value=""
/>
@@ -180,6 +197,7 @@ exports[`File Upload Form Should render 1`] = `
>
<span>
Release Notes URL
 *
</span>
</legend>
</fieldset>

View File

@@ -1,4 +1,4 @@
import React, { useRef } from "react";
import React, { useRef, useState } from "react";
import { Button, TextField, Typography } from "@material-ui/core";
import { DropzoneArea } from "material-ui-dropzone";
import { useUserContext } from "../../Contexts/UserContext";
@@ -9,6 +9,7 @@ import {
} from "../../Contexts/FileUploadContext";
import ModalProgressBar from "../../ModalProgressBar";
import useStyles from "../../useStyles";
import { Redirect } from "react-router";
const FileUploadZone = ({ classes, token }) => {
const { setFiles } = useFileUploadContext();
@@ -39,9 +40,10 @@ const FileUploadZone = ({ classes, token }) => {
};
const MainForm = () => {
const { uploading, upload, files } = useFileUploadContext();
const { uploading, upload, files, cancel } = useFileUploadContext();
const { token } = useUserContext();
const { setMessage } = useStatusContext();
const [redirect, setRedirect] = useState(null);
const classes = useStyles();
const packagenameEl = useRef(null);
const versionEl = useRef(null);
@@ -59,17 +61,26 @@ const MainForm = () => {
description: descEl.current.value,
releasenotes: releasenotesEl.current.value,
};
const result = await upload(formData, authToken, files);
await upload(formData, authToken, files);
if (!result || result.error) return;
cancel();
setMessage(`Package uploaded`);
setRedirect(`/carupdate-deploy/${result.id}`);
} catch (e) {
setMessage(e.message);
}
};
if (redirect && redirect.length > 0) {
return <Redirect to={redirect} />;
}
return (
<div className={classes.paper}>
<Typography component="h1" variant="h5">
Upload Update Package
Create Update Package
</Typography>
<form className={classes.form} noValidate action="{onSubmit}">
<TextField
@@ -107,6 +118,7 @@ const MainForm = () => {
inputProps={{
maxLength: "5120",
}}
required
fullWidth
multiline
rows={4}
@@ -122,6 +134,7 @@ const MainForm = () => {
inputProps={{
maxLength: "1024",
}}
required
fullWidth
placeholder="Release Notes URL"
inputRef={releasenotesEl}

View File

@@ -87,7 +87,7 @@ const MainForm = () => {
return (
<div className={classes.paper}>
<Typography component="h1" variant="h5">
Update Package {id}
Edit Update Package {id}
</Typography>
<form className={classes.form} noValidate action="{onSubmit}">
<TextField

View File

@@ -26,7 +26,7 @@ import { Roles, hasRole } from "../../../utils/roles";
const UpdatePackagesList = () => {
const classes = useStyles();
const [pageSize, setPageSize] = useState(5);
const [pageSize, setPageSize] = useState(25);
const [pageIndex, setPageIndex] = useState(0);
const { getPackages, packages, totalPackages } = useUpdatesContext();
const {
@@ -98,7 +98,7 @@ const UpdatePackagesList = () => {
return (
<div className={classes.paper} style={{ height: 700, width: "100%" }}>
<Typography component="h1" variant="h5">
Updates
Update Packages
</Typography>
<TableContainer>
<Table>

View File

@@ -41,11 +41,15 @@ const updatesAPI = {
},
getCarUpdates: async (filter, token) => {
return { data:[] };
return { data: [] };
},
getVINUpdates: async (vin, token) => {
return { data:[] };
return { data: [] };
},
getCarUpdateProgress: async (carupdateids, token) => {
return { statuses: [] };
},
};

View File

@@ -45,6 +45,15 @@ const updatesAPI = {
})
.then(fetchRespHandler);
},
getCarUpdateProgress: async (carupdateids, token) => {
var u = `${API_ENDPOINT}/carupdatesstatuses?carupdateids=${carupdateids}`;
return fetch(u, {
method: "GET",
headers: Object.assign({ "Content-Type": "application/json" }, getAuthHeaderOptions(token)),
})
.then(fetchRespHandler);
},
};
export default updatesAPI;