From 6c2d8e3c8f79ad0584f5e0b4eef90e12dc50c4cd Mon Sep 17 00:00:00 2001 From: Denis Thiessen Date: Tue, 30 Jan 2024 17:46:04 +0100 Subject: [PATCH] Added file error handling. --- src/components/SingleFileUpload.jsx | 58 +++++++++++++++++++++++----- src/components/TimelineAreaChart.jsx | 4 +- src/index.js | 8 +++- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/components/SingleFileUpload.jsx b/src/components/SingleFileUpload.jsx index 6ae1d42..f82517f 100644 --- a/src/components/SingleFileUpload.jsx +++ b/src/components/SingleFileUpload.jsx @@ -2,16 +2,20 @@ import React, { useState, useEffect } from "react" import csv from "csvtojson" import PropTypes from "prop-types" -export var fileContent = "{}" +export var fileContent = "{}"; +var uploadFailed = false; function SingleFileUpload({ onFileUploaded }) { const [, setFile] = useState() - const [fileUploaded, setFileUploaded] = useState(false) + const [fileUploaded, setFileUploaded] = useState(false); useEffect(() => { if (fileUploaded) { onFileUploaded() } + if(uploadFailed && !fileUploaded) { + onFileUploaded(); + } }, [fileUploaded]) // Reads file. @@ -19,16 +23,29 @@ function SingleFileUpload({ onFileUploaded }) { csv() .fromString(content) .preRawData((csvRawData) => { - csvRawData = csvRawData.replaceAll("Start Date", "Start_Date") - csvRawData = csvRawData.replaceAll("Start Time", "Start_Time") - csvRawData = csvRawData.replaceAll("End Date", "End_Date") - csvRawData = csvRawData.replaceAll("End Time", "End_Time") - csvRawData = csvRawData.replaceAll("Duration (decimal)", "Duration_Decimal") + + if(!checkCSVValidity(csvRawData)) { + alert("Invalid CSV File"); + uploadFailed = true; + setFileUploaded(false); + fileContent = {}; + return "{}"; + } + + csvRawData = csvRawData.replaceAll("Start Date", "Start_Date"); + csvRawData = csvRawData.replaceAll("Start Time", "Start_Time"); + csvRawData = csvRawData.replaceAll("End Date", "End_Date"); + csvRawData = csvRawData.replaceAll("End Time", "End_Time"); + csvRawData = csvRawData.replaceAll("Duration (decimal)", "Duration_Decimal"); + uploadFailed = false; + return csvRawData }) .then((csvRow) => { - fileContent = csvRow - setFileUploaded(true) + if(!uploadFailed) { + fileContent = csvRow; + setFileUploaded(true); + } }) } @@ -39,6 +56,12 @@ function SingleFileUpload({ onFileUploaded }) { const reader = new FileReader() reader.readAsText(changedFile) reader.onload = function (evt) { + var uploadedFile = document.getElementById('fileInput').files[0]; + if (uploadedFile.type != "application/vnd.ms-excel") { + alert("Wrong file type"); + fileContent = "{}"; + return; + } readCallback(evt.target.result) } } @@ -47,12 +70,27 @@ function SingleFileUpload({ onFileUploaded }) {

Upload file

- +
) } +function checkCSVValidity(rawCSV) { + const containsProjectKey = rawCSV.includes("\"Project\""); + const containsDescriptionKey = rawCSV.includes("\"Description\""); + const containsTaskKey = rawCSV.includes("\"Task\""); + const containsUserKey = rawCSV.includes("\"User\""); + const containsStartDateKey = rawCSV.includes("\"Start Date\""); + const containsStartTimeKey = rawCSV.includes("\"Start Time\""); + const containsEndDateKey = rawCSV.includes("\"End Date\""); + const containsEndTimeKey = rawCSV.includes("\"End Time\""); + const containsDurationHourKey = rawCSV.includes("\"Duration (h)\""); + const containsDurationDecimalKey = rawCSV.includes("\"Duration (decimal)\""); + + return containsProjectKey && containsDescriptionKey && containsTaskKey && containsUserKey && containsStartDateKey && containsStartTimeKey && containsEndDateKey && containsEndTimeKey && containsDurationHourKey && containsDurationDecimalKey; +} + SingleFileUpload.propTypes = { onFileUploaded: PropTypes.func.isRequired, } diff --git a/src/components/TimelineAreaChart.jsx b/src/components/TimelineAreaChart.jsx index c6b5094..1465736 100644 --- a/src/components/TimelineAreaChart.jsx +++ b/src/components/TimelineAreaChart.jsx @@ -4,8 +4,8 @@ import HighchartsReact from "highcharts-react-official" import { fileContent } from "./SingleFileUpload" // Date, Map -var projectDataMap = new Map() -var allSeriesEnabled = false +var projectDataMap = new Map(); +var allSeriesEnabled = true; export default function AreaChart() { const chartComponent = useRef(null) diff --git a/src/index.js b/src/index.js index 9457d9e..3326a6e 100644 --- a/src/index.js +++ b/src/index.js @@ -3,14 +3,18 @@ import ReactDOM from "react-dom/client" import "./index.css" import TimelineAreaChart from "./components/TimelineAreaChart" import TotalPieChart from "./components/TotalPieChart" -import SingleFileUploader from "./components/SingleFileUpload" +import SingleFileUploader, {fileContent} from "./components/SingleFileUpload" import { GeistProvider, CssBaseline, Tabs } from "@geist-ui/core" export default function App() { const [fileUploaded, setFileUploaded] = useState(false) const handleUploadedFile = function () { - setFileUploaded(true) + if(Array.isArray(fileContent)) { + setFileUploaded(true); + } else { + setFileUploaded(false); + } } return (