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:
@@ -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,
|
||||
|
||||
@@ -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={() => {
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user