import React, { useContext, useState } from "react"; import api from "../../services/manifestsAPI"; import { uploadFile, getCancelToken } from "../../services/uploadFile"; import { useStatusContext } from "./StatusContext"; import { validateManifest, validateManifestECUs, } from "../../utils/manifestValidation"; const ManifestCreateContext = React.createContext(); const checkExistingManifest = async (data, token) => { const check = { name: data.name, version: data.version, }; const { data: result } = await api.getManifests(check, token); if (result.length > 0) throw new Error(`Update ${data.name} ${data.version} already exists`); }; const ECUTemplate = { name: "AGS", version: "", hw_version: "", configuration_mask: "", configuration: "", files: [], manifest_id: 0, }; const FileTemplate = { offset: "0", checksum: "", type: "none", }; export const ManifestCreateProvider = ({ children }) => { const { setMessage } = useStatusContext(); const [busy, setBusy] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [uploadStatus, setUploadStatus] = useState(null); const [cancelUploadToken, setCancelUploadToken] = useState(null); const [uploadFileIndex, setUploadFileIndex] = useState(0); const [uploadedFiles, setUploadedFiles] = useState([]); const [ecus, setECUs] = useState([]); const [ecuIndex, setECUIndex] = useState(0); const addECU = () => { try { const result = ecus.concat( Object.assign({ data_id: ecuIndex }, ECUTemplate) ); setECUIndex(ecuIndex + 1); setECUs(result); } catch (err) { setMessage(err.message); } }; const deleteECU = (data_id) => { try { const result = ecus.filter((item) => item.data_id !== data_id); setECUs(result); } catch (err) { setMessage(err.message); } }; const getECU = (ecu_data_id) => ecus.find((item) => item.data_id === ecu_data_id); const getECUFile = (ecu, filename) => ecu.files.find((file) => file.filename === filename); const validateECUFiles = (ecu, files) => { files.forEach((file) => { if (file.size === 0) throw new Error(`${file.name} is 0 size`); const result = getECUFile(ecu, file.name); if (result) throw new Error(`${file.name} already exists`); }); }; const getAllECUFiles = () => { let result = []; for (let i = 0, len = ecus.length; i < len; i++) { const ecu = ecus[i]; result = result.concat(ecu.files); } return result; }; const addECUFile = (ecu_data_id, items) => { try { const ecu = getECU(ecu_data_id); if (ecu === undefined) return; const files = Array.from(items); validateECUFiles(ecu, files); const total = ecu.files.length; const result = files.map((file, index) => Object.assign( { order: total + index, file: file, filename: file.name }, FileTemplate ) ); ecu.files = ecu.files.concat(result); updateECUs(); } catch (err) { setMessage(err.message); } }; const sortECUFiles = (ecu) => { ecu.files.sort((x, y) => { if (x.order === y.order) return 0; return x.order < y.order ? -1 : 1; }); }; const deleteECUFile = (ecu_data_id, filename) => { try { const ecu = getECU(ecu_data_id); if (ecu === undefined) return; ecu.files = ecu.files.filter((file) => file.filename !== filename); sortECUFiles(ecu); updateECUs(); } catch (err) { setMessage(err.message); } }; const updateECUs = () => { setECUs(ecus.concat([])); }; const createManifest = async (data, token) => { let result; let currentFileIndex = 0; const incremFileIndex = () => { setUploadFileIndex(currentFileIndex); currentFileIndex++; }; try { setBusy(true); validateManifest(data, token); validateManifestECUs(ecus); await checkExistingManifest(data, token); setUploadedFiles(getAllECUFiles()); if (result !== null) result = await api.createManifest(data, token); if (result.error) throw new Error(`Create manifest error. ${result.message}`); for (let i = 0, len = ecus.length; i < len; i++) { const ecu = ecus[i]; ecu.manifest_id = result.id; await createManifestECU(ecu, token, incremFileIndex); } } finally { setBusy(false); setUploadFileIndex(0); setUploadedFiles([]); } return result; }; const createManifestECU = async (ecu, token, incremFileIndexFn) => { const { files, ...data } = ecu; const result = await api.createManifestECU(data, token); if (result.error) throw new Error(`Create manifest error. ${result.message}`); for (let i = 0, len = ecu.files.length; i < len; i++) { const file = ecu.files[i]; file.manifest_ecu_id = result.id; incremFileIndexFn(); const resp = await uploadECUFile(file, token); if (resp.error) throw new Error(`Upload manifest file error. ${resp.error}`); } }; const cancelUpload = () => { if (cancelUploadToken) cancelUploadToken.cancel(); setBusy(false); setUploadStatus("Upload cancelled"); setCancelUploadToken(null); setUploadProgress(0); }; const uploadECUFile = async (file, accessToken) => { const cancel = getCancelToken(); setUploadProgress(0); setUploadStatus(`Uploading ${file.filename}`); setCancelUploadToken(cancel); const result = await uploadFile( file, accessToken, setUploadProgress, cancel.token ); if (result.message) { throw new Error(`${result.error}. ${result.message}`); } setUploadStatus(`Uploaded ${file.filename}`); setCancelUploadToken(null); setUploadProgress(100); return result; }; return ( {children} ); }; export const useManifestCreateContext = () => useContext(ManifestCreateContext);