From a10d02ec0854c1261ae8cc1d31f0a2df6e149436 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Tue, 12 Aug 2025 01:45:56 +0800
Subject: [PATCH 01/19] Added DialogMain, PendingBatchCard, DialogNewBatchCard
Component
---
src/components/DataImport/DialogMain.jsx | 73 +++++++++++++++++++
src/components/DataImport/DialogNewBatch.jsx | 25 +++++++
.../DataImport/PendingBatchCard.jsx | 40 ++++++++++
src/pages/DataImport.jsx | 14 +++-
4 files changed, 149 insertions(+), 3 deletions(-)
create mode 100644 src/components/DataImport/DialogMain.jsx
create mode 100644 src/components/DataImport/DialogNewBatch.jsx
create mode 100644 src/components/DataImport/PendingBatchCard.jsx
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
new file mode 100644
index 0000000..956eeba
--- /dev/null
+++ b/src/components/DataImport/DialogMain.jsx
@@ -0,0 +1,73 @@
+import { Button, Dialog, Portal, Flex, Box, Text, VStack } from "@chakra-ui/react";
+import DialogNewBatch from "./DialogNewBatch";
+import hp1 from "../../assets/hp1.png";
+import PendingBatchCard from "./PendingBatchCard";
+
+function DialogMain({ pendingBatches }) {
+ return (
+
+
+
+
+
+
+
+
+
+ Upload Artefacts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload to Pending Batches
+
+
+ {pendingBatches.length === 0 ? (
+
+ No pending batches.
+
+ ) : (
+ pendingBatches.map((batch) => (
+ console.log("Clicked batch", batch.id)}
+ />
+ ))
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default DialogMain
\ No newline at end of file
diff --git a/src/components/DataImport/DialogNewBatch.jsx b/src/components/DataImport/DialogNewBatch.jsx
new file mode 100644
index 0000000..5d23222
--- /dev/null
+++ b/src/components/DataImport/DialogNewBatch.jsx
@@ -0,0 +1,25 @@
+import { Button, Dialog, Portal, Flex, Box, Text } from "@chakra-ui/react"
+
+function DialogNewBatch() {
+ return (
+
+
+
+
+
+
+
+
+
+ Dialog Title
+
+
+
+
+
+
+
+ )
+}
+
+export default DialogNewBatch
\ No newline at end of file
diff --git a/src/components/DataImport/PendingBatchCard.jsx b/src/components/DataImport/PendingBatchCard.jsx
new file mode 100644
index 0000000..37f1578
--- /dev/null
+++ b/src/components/DataImport/PendingBatchCard.jsx
@@ -0,0 +1,40 @@
+import { Box, Flex, Image, Text } from "@chakra-ui/react";
+
+const PendingBatchCard = ({ batchName, displayMessage, timestamp, thumbnail, onClick }) => {
+ return (
+
+
+
+
+
+ {batchName}
+
+
+ {displayMessage || "Pending upload"}
+
+
+ {timestamp}
+
+
+
+
+ );
+};
+
+export default PendingBatchCard;
\ No newline at end of file
diff --git a/src/pages/DataImport.jsx b/src/pages/DataImport.jsx
index 8cfca43..804db69 100644
--- a/src/pages/DataImport.jsx
+++ b/src/pages/DataImport.jsx
@@ -6,7 +6,8 @@ import { useSelector } from "react-redux";
import ToastWizard from '../components/toastWizard'
import server, { JSONResponse } from "../networking";
import BatchCard from "../components/DataImport/BatchCard";
-import DialogUpload from "../components/DataImport/DialogUpload";
+// import DialogUpload from "../components/DataImport/DialogUpload";
+import DialogMain from "../components/DataImport/DialogMain.jsx";
import CentredSpinner from "../components/centredSpinner.jsx";
const stageCollection = createListCollection({
@@ -20,7 +21,7 @@ const stageCollection = createListCollection({
],
});
-function formatTimestamp(dateString) {
+export function formatTimestamp(dateString) {
const created = new Date(dateString);
const now = new Date();
@@ -151,6 +152,8 @@ function DataImport() {
});
}, [batches, selectedStages]);
+ const pendingBatches = batches.filter(b => b.stage === "upload_pending");
+
if (loading) {
return ;
}
@@ -188,7 +191,12 @@ function DataImport() {
{/* Upload Button */}
-
+ ({
+ ...batch,
+ created: formatTimestamp(batch.created)
+ }))}
+ />
{/* Second Row: Stage Filter + Upload Button */}
From 2253ecde3886eae4a791a276885fe251d98b157b Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Tue, 12 Aug 2025 13:54:59 +0800
Subject: [PATCH 02/19] Modified PBC to have artefactCount instead of status
---
src/components/DataImport/DialogMain.jsx | 12 ++++++++---
.../DataImport/PendingBatchCard.jsx | 12 ++++++-----
src/pages/DataImport.jsx | 21 ++++++++++++-------
3 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 956eeba..19b28c0 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -14,7 +14,7 @@ function DialogMain({ pendingBatches }) {
- Upload Artefacts
+ Upload Artefacts to
@@ -36,10 +36,16 @@ function DialogMain({ pendingBatches }) {
+
Upload to Pending Batches
-
+
{pendingBatches.length === 0 ? (
No pending batches.
@@ -49,7 +55,7 @@ function DialogMain({ pendingBatches }) {
console.log("Clicked batch", batch.id)}
diff --git a/src/components/DataImport/PendingBatchCard.jsx b/src/components/DataImport/PendingBatchCard.jsx
index 37f1578..8d3b462 100644
--- a/src/components/DataImport/PendingBatchCard.jsx
+++ b/src/components/DataImport/PendingBatchCard.jsx
@@ -1,6 +1,6 @@
import { Box, Flex, Image, Text } from "@chakra-ui/react";
-const PendingBatchCard = ({ batchName, displayMessage, timestamp, thumbnail, onClick }) => {
+const PendingBatchCard = ({ batchName, artefactCount, timestamp, thumbnail, onClick }) => {
return (
-
+
{batchName}
-
- {displayMessage || "Pending upload"}
+
+ {artefactCount != null
+ ? `${artefactCount} Artefact${artefactCount === 1 ? '' : 's'}`
+ : "No artefacts"}
{timestamp}
diff --git a/src/pages/DataImport.jsx b/src/pages/DataImport.jsx
index 804db69..fecff34 100644
--- a/src/pages/DataImport.jsx
+++ b/src/pages/DataImport.jsx
@@ -21,7 +21,7 @@ const stageCollection = createListCollection({
],
});
-export function formatTimestamp(dateString) {
+function formatTimestamp(dateString) {
const created = new Date(dateString);
const now = new Date();
@@ -152,7 +152,16 @@ function DataImport() {
});
}, [batches, selectedStages]);
- const pendingBatches = batches.filter(b => b.stage === "upload_pending");
+ const pendingBatches = useMemo(() =>
+ batches
+ .filter(b => b.stage === "upload_pending")
+ .map(batch => ({
+ ...batch,
+ created: formatTimestamp(batch.created),
+ artefactCount: batch.artefactSummary?.total ?? 0
+ }))
+ , [batches]);
+
if (loading) {
return ;
@@ -191,12 +200,8 @@ function DataImport() {
{/* Upload Button */}
- ({
- ...batch,
- created: formatTimestamp(batch.created)
- }))}
- />
+
+
{/* Second Row: Stage Filter + Upload Button */}
From 2b2a80b55dec78ca34c59ff76778879ce5e57b07 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Tue, 12 Aug 2025 14:36:05 +0800
Subject: [PATCH 03/19] Added Custom FileUpload Button and Show File List
---
src/components/DataImport/DialogMain.jsx | 6 +-
src/components/DataImport/DialogNewBatch.jsx | 25 ----
.../DataImport/DialogUploadFile.jsx | 130 ++++++++++++++++++
3 files changed, 133 insertions(+), 28 deletions(-)
delete mode 100644 src/components/DataImport/DialogNewBatch.jsx
create mode 100644 src/components/DataImport/DialogUploadFile.jsx
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 19b28c0..cf703eb 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -1,5 +1,5 @@
import { Button, Dialog, Portal, Flex, Box, Text, VStack } from "@chakra-ui/react";
-import DialogNewBatch from "./DialogNewBatch";
+import DialogUploadFile from "./DialogUploadFile";
import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
@@ -21,7 +21,7 @@ function DialogMain({ pendingBatches }) {
-
+
@@ -76,4 +76,4 @@ function DialogMain({ pendingBatches }) {
)
}
-export default DialogMain
\ No newline at end of file
+export default DialogMain;
\ No newline at end of file
diff --git a/src/components/DataImport/DialogNewBatch.jsx b/src/components/DataImport/DialogNewBatch.jsx
deleted file mode 100644
index 5d23222..0000000
--- a/src/components/DataImport/DialogNewBatch.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Button, Dialog, Portal, Flex, Box, Text } from "@chakra-ui/react"
-
-function DialogNewBatch() {
- return (
-
-
-
-
-
-
-
-
-
- Dialog Title
-
-
-
-
-
-
-
- )
-}
-
-export default DialogNewBatch
\ No newline at end of file
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
new file mode 100644
index 0000000..38d7e61
--- /dev/null
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -0,0 +1,130 @@
+import { Button, Dialog, Portal, Flex, Box, Text, IconButton, CloseButton } from "@chakra-ui/react";
+import { useRef, useState } from "react";
+import { HiUpload } from "react-icons/hi";
+
+function DialogUploadFile() {
+ const fileInputRef = useRef(null);
+ const [selectedFiles, setSelectedFiles] = useState([]);
+
+ const handleButtonClick = () => {
+ fileInputRef.current?.click();
+ };
+
+ const handleFileChange = (event) => {
+ const files = Array.from(event.target.files); // Convert FileList to array
+ if (files.length > 0) {
+ setSelectedFiles((prev) => [...prev, ...files]);
+ }
+ };
+
+ const removeFile = (fileToRemove) => {
+ setSelectedFiles((prev) => prev.filter((file) => file !== fileToRemove));
+ };
+
+ const clearAll = () => {
+ setSelectedFiles([]);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+ Upload Artefacts
+
+
+ Uploading to: New Batch
+
+
+
+ }
+ variant="outline"
+ width="full"
+ justifyContent="start"
+ mt={2}
+ onClick={handleButtonClick}
+ >
+ Choose Files
+
+
+ {/* Selected Files List */}
+ {selectedFiles.length > 0 && (
+
+
+
+ {selectedFiles.length} file(s) selected
+
+
+
+
+
+ {selectedFiles.map((file, index) => (
+
+
+ {file.name}
+
+ {(file.size / 1024).toFixed(1)} KB
+
+
+ removeFile(file)}
+ aria-label={`Remove ${file.name}`}
+ />
+
+ ))}
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default DialogUploadFile;
From bcfcee1736095bec5f4bd0504991bb2a8d86c4d9 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Tue, 12 Aug 2025 16:37:22 +0800
Subject: [PATCH 04/19] Custom FileItem Component to show error/sucess status
of file(s)
---
src/components/DataImport/DialogMain.jsx | 2 +-
.../DataImport/DialogUploadFile.jsx | 107 ++++++++++++------
src/components/DataImport/FileItem.jsx | 47 ++++++++
3 files changed, 123 insertions(+), 33 deletions(-)
create mode 100644 src/components/DataImport/FileItem.jsx
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index cf703eb..95f3405 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -45,7 +45,7 @@ function DialogMain({ pendingBatches }) {
Upload to Pending Batches
-
+
{pendingBatches.length === 0 ? (
No pending batches.
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 38d7e61..0dde539 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -1,32 +1,91 @@
-import { Button, Dialog, Portal, Flex, Box, Text, IconButton, CloseButton } from "@chakra-ui/react";
+import { Button, Dialog, Portal, Flex, Box, Text, CloseButton } from "@chakra-ui/react";
import { useRef, useState } from "react";
import { HiUpload } from "react-icons/hi";
+import server from "../../networking";
+import ToastWizard from "../../components/toastWizard";
+import FileItem from "./FileItem";
function DialogUploadFile() {
const fileInputRef = useRef(null);
const [selectedFiles, setSelectedFiles] = useState([]);
+ const [fileStatuses, setFileStatuses] = useState({});
+ const [isSubmitting, setIsSubmitting] = useState(false);
const handleButtonClick = () => {
fileInputRef.current?.click();
};
const handleFileChange = (event) => {
- const files = Array.from(event.target.files); // Convert FileList to array
+ const files = Array.from(event.target.files);
if (files.length > 0) {
setSelectedFiles((prev) => [...prev, ...files]);
+ // Clear statuses for newly added files
+ const newStatuses = { ...fileStatuses };
+ files.forEach((file) => {
+ delete newStatuses[file.name]; // remove old status
+ });
+ setFileStatuses(newStatuses);
}
};
const removeFile = (fileToRemove) => {
setSelectedFiles((prev) => prev.filter((file) => file !== fileToRemove));
+ setFileStatuses((prev) => {
+ const updated = { ...prev };
+ delete updated[fileToRemove.name];
+ return updated;
+ });
};
const clearAll = () => {
setSelectedFiles([]);
+ setFileStatuses({});
+ };
+
+ const handleUpload = async () => {
+ if (selectedFiles.length === 0 || isSubmitting) return;
+
+ const formData = new FormData();
+ selectedFiles.forEach((file) => {
+ formData.append("file", file);
+ });
+
+ setIsSubmitting(true);
+
+ try {
+ const res = await server.post("/dataImport/upload", formData, {
+ headers: { "Content-Type": "multipart/form-data" },
+ });
+
+ const data = res.data;
+ const updates = data.raw?.updates || {};
+ const batchID = data.raw?.batchID;
+
+ setFileStatuses(updates);
+
+ ToastWizard.standard("success", "Upload Complete", `Batch ID: ${batchID}. Ready for processing.`);
+
+ } catch (err) {
+ const updates = err?.response?.data?.raw?.updates;
+ if (updates) {
+ setFileStatuses(updates);
+ } else {
+ // If no detailed errors, mark all files as failed
+ const fallbackStatus = {};
+ selectedFiles.forEach((file) => {
+ fallbackStatus[file.name] = "ERROR: Failed to upload.";
+ });
+ setFileStatuses(fallbackStatus);
+ }
+
+ ToastWizard.standard("error", "Upload Failed", "Some or all files failed to upload.");
+ } finally {
+ setIsSubmitting(false);
+ }
};
return (
-
+
@@ -35,10 +94,10 @@ function DialogUploadFile() {
- Upload Artefacts
+ Upload Artefacts
- Uploading to: New Batch
+ To: New Batch
Choose Files
@@ -81,28 +140,12 @@ function DialogUploadFile() {
bg="gray.50"
>
{selectedFiles.map((file, index) => (
-
-
- {file.name}
-
- {(file.size / 1024).toFixed(1)} KB
-
-
- removeFile(file)}
- aria-label={`Remove ${file.name}`}
- />
-
+ file={file}
+ statusMsg={fileStatuses[file.name]}
+ onRemove={removeFile}
+ />
))}
@@ -110,12 +153,12 @@ function DialogUploadFile() {
-
+ { clearAll(); }} />
@@ -124,7 +167,7 @@ function DialogUploadFile() {
- )
+ );
}
-export default DialogUploadFile;
+export default DialogUploadFile;
\ No newline at end of file
diff --git a/src/components/DataImport/FileItem.jsx b/src/components/DataImport/FileItem.jsx
new file mode 100644
index 0000000..87ede1a
--- /dev/null
+++ b/src/components/DataImport/FileItem.jsx
@@ -0,0 +1,47 @@
+import { Flex, Box, Text, CloseButton } from "@chakra-ui/react";
+
+function FileItem({ file, statusMsg, onRemove }) {
+ const isError = statusMsg && statusMsg.startsWith("ERROR");
+ const isSuccess = statusMsg && statusMsg.startsWith("SUCCESS");
+
+ return (
+
+
+
+ {file.name}
+
+ {(file.size / 1024).toFixed(1)} KB
+
+
+ onRemove(file)}
+ aria-label={`Remove ${file.name}`}
+ />
+
+ {statusMsg && (
+
+ {statusMsg.replace(/^(SUCCESS|ERROR):\s*/, "")}
+
+ )}
+
+ );
+}
+
+export default FileItem;
\ No newline at end of file
From 4122d91c3863bbd3e169b48df8bb8b9c6cee1233 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Tue, 12 Aug 2025 18:02:53 +0800
Subject: [PATCH 05/19] Fixed batch number and Added Responsiveness
---
src/components/DataImport/DialogMain.jsx | 19 ++++++++------
.../DataImport/DialogUploadFile.jsx | 2 +-
src/components/DataImport/FileItem.jsx | 4 +--
.../DataImport/PendingBatchCard.jsx | 21 ++++++++-------
src/pages/DataImport.jsx | 26 ++++++++++++++-----
5 files changed, 44 insertions(+), 28 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 95f3405..491a1e5 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -1,11 +1,11 @@
-import { Button, Dialog, Portal, Flex, Box, Text, VStack } from "@chakra-ui/react";
+import { Button, Dialog, Portal, Flex, Box, Text, VStack, CloseButton } from "@chakra-ui/react";
import DialogUploadFile from "./DialogUploadFile";
import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
function DialogMain({ pendingBatches }) {
return (
-
+
@@ -18,7 +18,7 @@ function DialogMain({ pendingBatches }) {
-
+
@@ -35,7 +35,7 @@ function DialogMain({ pendingBatches }) {
-
+
- Upload to Pending Batches
+ Upload to Pending Batches
-
+
{pendingBatches.length === 0 ? (
No pending batches.
@@ -54,7 +54,7 @@ function DialogMain({ pendingBatches }) {
pendingBatches.map((batch) => (
+
+
+
-
+
)
}
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 0dde539..ad60c83 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -85,7 +85,7 @@ function DialogUploadFile() {
};
return (
-
+
diff --git a/src/components/DataImport/FileItem.jsx b/src/components/DataImport/FileItem.jsx
index 87ede1a..1946c35 100644
--- a/src/components/DataImport/FileItem.jsx
+++ b/src/components/DataImport/FileItem.jsx
@@ -12,9 +12,7 @@ function FileItem({ file, statusMsg, onRemove }) {
px={2}
borderRadius="md"
bg={isError ? "red.50" : isSuccess ? "green.50" : undefined}
- _hover={{
- bg: isError ? "red.100" : isSuccess ? "green.100" : "gray.100",
- }}
+ _hover={{ bg: isError ? "red.100" : isSuccess ? "green.100" : "gray.100" }}
mb={2}
>
diff --git a/src/components/DataImport/PendingBatchCard.jsx b/src/components/DataImport/PendingBatchCard.jsx
index 8d3b462..732a259 100644
--- a/src/components/DataImport/PendingBatchCard.jsx
+++ b/src/components/DataImport/PendingBatchCard.jsx
@@ -4,33 +4,34 @@ const PendingBatchCard = ({ batchName, artefactCount, timestamp, thumbnail, onCl
return (
-
+
-
+
{batchName}
-
+
{artefactCount != null
? `${artefactCount} Artefact${artefactCount === 1 ? '' : 's'}`
: "No artefacts"}
-
+
{timestamp}
diff --git a/src/pages/DataImport.jsx b/src/pages/DataImport.jsx
index fecff34..3fa5d5b 100644
--- a/src/pages/DataImport.jsx
+++ b/src/pages/DataImport.jsx
@@ -152,16 +152,30 @@ function DataImport() {
});
}, [batches, selectedStages]);
- const pendingBatches = useMemo(() =>
- batches
+ const batchData = useMemo(() => {
+ const sorted = [...batches].sort((a, b) => new Date(a.created) - new Date(b.created));
+
+ const batchNumberMap = {};
+ const numberedBatches = sorted.map((batch, i) => {
+ batchNumberMap[batch.id] = i + 1;
+ return {
+ ...batch,
+ batchNumber: i + 1,
+ };
+ });
+
+ const pendingBatches = numberedBatches
.filter(b => b.stage === "upload_pending")
.map(batch => ({
...batch,
created: formatTimestamp(batch.created),
- artefactCount: batch.artefactSummary?.total ?? 0
- }))
- , [batches]);
+ artefactCount: batch.artefactSummary?.total ?? 0,
+ }));
+
+ return { pendingBatches, batchNumberMap };
+ }, [batches]);
+ const { pendingBatches, batchNumberMap } = batchData;
if (loading) {
return ;
@@ -262,7 +276,7 @@ function DataImport() {
filtered.map((batch, idx) => (
Date: Wed, 13 Aug 2025 00:25:39 +0800
Subject: [PATCH 06/19] Modified to change state instead of nested dialog
---
src/components/DataImport/DialogMain.jsx | 88 +++++-----
.../DataImport/DialogUploadFile.jsx | 152 ++++++++----------
.../DataImport/PendingBatchCard.jsx | 4 +-
3 files changed, 117 insertions(+), 127 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 491a1e5..472cd2e 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -2,12 +2,28 @@ import { Button, Dialog, Portal, Flex, Box, Text, VStack, CloseButton } from "@c
import DialogUploadFile from "./DialogUploadFile";
import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
+import { useState } from "react";
function DialogMain({ pendingBatches }) {
+
+ const [view, setView] = useState("pendingList");
+ const [isOpen, setIsOpen] = useState(false);
+
+ const handleOpen = () => {
+ setView("pendingList");
+ setIsOpen(true);
+ };
+
+ const handleClose = () => {
+ setView("pendingList");
+ setIsOpen(false);
+ };
+
return (
-
+
-
+
@@ -17,41 +33,29 @@ function DialogMain({ pendingBatches }) {
Upload Artefacts to
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Upload to Pending Batches
-
-
- {pendingBatches.length === 0 ? (
-
- No pending batches.
-
- ) : (
- pendingBatches.map((batch) => (
+ {view === "upload" && (
+
+ )}
+
+ {view === "pendingList" && (
+
+
+
+
+
+
+
+
+
+ Pending Batches
+
+ {pendingBatches.length === 0 ? (
+
+ No pending batches.
+
+ ) : (
+
+ {pendingBatches.map((batch) => (
console.log("Clicked batch", batch.id)}
/>
- ))
- )}
-
+ ))}
+
+ )}
-
-
+
+ )}
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index ad60c83..5b6fea4 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -5,7 +5,7 @@ import server from "../../networking";
import ToastWizard from "../../components/toastWizard";
import FileItem from "./FileItem";
-function DialogUploadFile() {
+function DialogUploadFile({ onCancel }) {
const fileInputRef = useRef(null);
const [selectedFiles, setSelectedFiles] = useState([]);
const [fileStatuses, setFileStatuses] = useState({});
@@ -22,7 +22,7 @@ function DialogUploadFile() {
// Clear statuses for newly added files
const newStatuses = { ...fileStatuses };
files.forEach((file) => {
- delete newStatuses[file.name]; // remove old status
+ delete newStatuses[file.name];
});
setFileStatuses(newStatuses);
}
@@ -65,6 +65,8 @@ function DialogUploadFile() {
ToastWizard.standard("success", "Upload Complete", `Batch ID: ${batchID}. Ready for processing.`);
+ onCancel();
+
} catch (err) {
const updates = err?.response?.data?.raw?.updates;
if (updates) {
@@ -85,88 +87,72 @@ function DialogUploadFile() {
};
return (
-
-
-
-
-
-
-
-
-
- Upload Artefacts
-
-
- To: New Batch
-
-
+ To: New Batch
+
+
+
+ }
+ variant="outline"
+ width="full"
+ justifyContent="start"
+ mb={4}
+ onClick={handleButtonClick}
+ >
+ Choose Files
+
+
+ {/* Selected Files List */}
+ {selectedFiles.length > 0 && (
+
+
+
+ {selectedFiles.length} file(s) selected
+
+
+
+
+
+ {selectedFiles.map((file, index) => (
+
-
- }
- variant="outline"
- width="full"
- justifyContent="start"
- mt={4}
- onClick={handleButtonClick}
- >
- Choose Files
-
-
- {/* Selected Files List */}
- {selectedFiles.length > 0 && (
-
-
-
- {selectedFiles.length} file(s) selected
-
-
-
-
-
- {selectedFiles.map((file, index) => (
-
- ))}
-
-
- )}
-
-
-
- { clearAll(); }} />
-
-
-
-
-
-
-
+ ))}
+
+
+ )}
+
+
+
+
+
+ >
);
}
diff --git a/src/components/DataImport/PendingBatchCard.jsx b/src/components/DataImport/PendingBatchCard.jsx
index 732a259..563bdea 100644
--- a/src/components/DataImport/PendingBatchCard.jsx
+++ b/src/components/DataImport/PendingBatchCard.jsx
@@ -10,14 +10,14 @@ const PendingBatchCard = ({ batchName, artefactCount, timestamp, thumbnail, onCl
shadow="sm"
_hover={{ shadow: "md", cursor: "pointer" }}
width={{ base: "220px", md: "300px" }}
- height={{ base: "140px", md: "180px" }}
+ height={{ base: "65px", md: "75px" }}
onClick={onClick}
>
Date: Wed, 13 Aug 2025 04:00:39 +0800
Subject: [PATCH 07/19] Added UploadExisting State, force user to clear before
adding new files to exisitng batch
---
src/components/DataImport/DialogMain.jsx | 42 ++++++++++++++++--
.../DataImport/DialogUploadFile.jsx | 44 +++++++++++++------
2 files changed, 69 insertions(+), 17 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 472cd2e..6a87c7c 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -8,6 +8,9 @@ function DialogMain({ pendingBatches }) {
const [view, setView] = useState("pendingList");
const [isOpen, setIsOpen] = useState(false);
+ const [currentBatchID, setCurrentBatchID] = useState(null);
+ const [selectedFiles, setSelectedFiles] = useState([]);
+ const [fileStatuses, setFileStatuses] = useState({});
const handleOpen = () => {
setView("pendingList");
@@ -19,6 +22,11 @@ function DialogMain({ pendingBatches }) {
setIsOpen(false);
};
+ const handleUploadSuccess = (batchID) => {
+ setCurrentBatchID(batchID);
+ setView("uploadExisting");
+ };
+
return (
@@ -33,14 +41,37 @@ function DialogMain({ pendingBatches }) {
Upload Artefacts to
- {view === "upload" && (
-
+ {view === "uploadNew" && (
+
+ )}
+
+ {view === "uploadExisting" && (
+
)}
{view === "pendingList" && (
-
+
@@ -62,7 +93,10 @@ function DialogMain({ pendingBatches }) {
artefactCount={batch.artefactCount}
timestamp={batch.created}
thumbnail={hp1}
- onClick={() => console.log("Clicked batch", batch.id)}
+ onClick={() => {
+ setCurrentBatchID(batch.id);
+ setView("uploadExisting");
+ }}
/>
))}
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 5b6fea4..3c2e200 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -1,20 +1,22 @@
-import { Button, Dialog, Portal, Flex, Box, Text, CloseButton } from "@chakra-ui/react";
+import { Button, Flex, Box, Text } from "@chakra-ui/react";
import { useRef, useState } from "react";
import { HiUpload } from "react-icons/hi";
import server from "../../networking";
import ToastWizard from "../../components/toastWizard";
import FileItem from "./FileItem";
-function DialogUploadFile({ onCancel }) {
+function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID, selectedFiles, setSelectedFiles, fileStatuses, setFileStatuses }) {
const fileInputRef = useRef(null);
- const [selectedFiles, setSelectedFiles] = useState([]);
- const [fileStatuses, setFileStatuses] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const handleButtonClick = () => {
fileInputRef.current?.click();
};
+ const hasSuccessfullyUploadedFiles = selectedFiles.some(file =>
+ fileStatuses[file.name]?.startsWith("SUCCESS")
+ );
+
const handleFileChange = (event) => {
const files = Array.from(event.target.files);
if (files.length > 0) {
@@ -42,6 +44,13 @@ function DialogUploadFile({ onCancel }) {
setFileStatuses({});
};
+ const hasPreviousStatus = selectedFiles.some(file => fileStatuses[file.name]);
+
+ const isDisabled =
+ selectedFiles.length === 0 ||
+ isSubmitting ||
+ hasPreviousStatus;
+
const handleUpload = async () => {
if (selectedFiles.length === 0 || isSubmitting) return;
@@ -50,6 +59,10 @@ function DialogUploadFile({ onCancel }) {
formData.append("file", file);
});
+ if (batchID) {
+ formData.append("batchID", batchID);
+ }
+
setIsSubmitting(true);
try {
@@ -59,14 +72,15 @@ function DialogUploadFile({ onCancel }) {
const data = res.data;
const updates = data.raw?.updates || {};
- const batchID = data.raw?.batchID;
+ const returnedBatchID = data.raw?.batchID;
setFileStatuses(updates);
+ ToastWizard.standard("success", "Upload Complete", `Batch ID: ${returnedBatchID}. Ready for processing.`);
- ToastWizard.standard("success", "Upload Complete", `Batch ID: ${batchID}. Ready for processing.`);
+ if (onSuccess) {
+ onSuccess(returnedBatchID);
+ }
- onCancel();
-
} catch (err) {
const updates = err?.response?.data?.raw?.updates;
if (updates) {
@@ -88,7 +102,7 @@ function DialogUploadFile({ onCancel }) {
return (
<>
- To: New Batch
+ To: {toLabel}
- {/* Selected Files List */}
{selectedFiles.length > 0 && (
@@ -142,16 +155,21 @@ function DialogUploadFile({ onCancel }) {
)}
+ {hasPreviousStatus && (
+
+ Click "Remove All" to upload new files.
+
+ )}
+
-
>
);
}
From 934d084e4180b338811d1c86514963da7abd1212 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 05:39:46 +0800
Subject: [PATCH 08/19] Modified from showing BatchID to BatchNumber
---
src/components/DataImport/DialogMain.jsx | 19 +++++++++++++------
.../DataImport/DialogUploadFile.jsx | 15 ++++++++-------
2 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 6a87c7c..2eb8e0d 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -9,6 +9,7 @@ function DialogMain({ pendingBatches }) {
const [view, setView] = useState("pendingList");
const [isOpen, setIsOpen] = useState(false);
const [currentBatchID, setCurrentBatchID] = useState(null);
+ const [currentBatchNumber, setCurrentBatchNumber] = useState("");
const [selectedFiles, setSelectedFiles] = useState([]);
const [fileStatuses, setFileStatuses] = useState({});
@@ -18,17 +19,21 @@ function DialogMain({ pendingBatches }) {
};
const handleClose = () => {
- setView("pendingList");
setIsOpen(false);
+ setSelectedFiles([]);
+ setFileStatuses({});
+ setCurrentBatchID(null);
+ setCurrentBatchNumber("");
};
- const handleUploadSuccess = (batchID) => {
- setCurrentBatchID(batchID);
+ const handleUploadSuccess = (returnedBatchID) => {
+ setCurrentBatchID(returnedBatchID);
setView("uploadExisting");
};
return (
-
+
@@ -58,9 +63,10 @@ function DialogMain({ pendingBatches }) {
{
setCurrentBatchID(batch.id);
+ setCurrentBatchNumber(batch.batchNumber);
setView("uploadExisting");
}}
/>
@@ -107,7 +114,7 @@ function DialogMain({ pendingBatches }) {
-
+
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 3c2e200..4ebc410 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -5,7 +5,7 @@ import server from "../../networking";
import ToastWizard from "../../components/toastWizard";
import FileItem from "./FileItem";
-function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID, selectedFiles, setSelectedFiles, fileStatuses, setFileStatuses }) {
+function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID, batchNumber, selectedFiles, setSelectedFiles, fileStatuses, setFileStatuses }) {
const fileInputRef = useRef(null);
const [isSubmitting, setIsSubmitting] = useState(false);
@@ -13,10 +13,6 @@ function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID,
fileInputRef.current?.click();
};
- const hasSuccessfullyUploadedFiles = selectedFiles.some(file =>
- fileStatuses[file.name]?.startsWith("SUCCESS")
- );
-
const handleFileChange = (event) => {
const files = Array.from(event.target.files);
if (files.length > 0) {
@@ -73,10 +69,15 @@ function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID,
const data = res.data;
const updates = data.raw?.updates || {};
const returnedBatchID = data.raw?.batchID;
+ const returnedBatchNumber = data.raw?.batchNumber;
+ const displayBatchNumber = batchNumber || returnedBatchNumber || returnedBatchID;
setFileStatuses(updates);
- ToastWizard.standard("success", "Upload Complete", `Batch ID: ${returnedBatchID}. Ready for processing.`);
-
+ ToastWizard.standard(
+ "success",
+ "Upload Complete",
+ `Uploaded files to Batch ${displayBatchNumber}. Ready for processing.`
+ );
if (onSuccess) {
onSuccess(returnedBatchID);
}
From 0fab6036b2b3b8069727e8da1b79ee4a54273758 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 11:36:37 +0800
Subject: [PATCH 09/19] Cleaned up codes
---
src/components/DataImport/DialogMain.jsx | 69 ++++---------------
.../DataImport/DialogUploadFile.jsx | 30 +++++---
src/pages/DataImport.jsx | 10 ++-
3 files changed, 41 insertions(+), 68 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 2eb8e0d..fa01c83 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -2,40 +2,26 @@ import { Button, Dialog, Portal, Flex, Box, Text, VStack, CloseButton } from "@c
import DialogUploadFile from "./DialogUploadFile";
import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
-import { useState } from "react";
+import { useEffect, useState } from "react";
function DialogMain({ pendingBatches }) {
-
- const [view, setView] = useState("pendingList");
const [isOpen, setIsOpen] = useState(false);
- const [currentBatchID, setCurrentBatchID] = useState(null);
- const [currentBatchNumber, setCurrentBatchNumber] = useState("");
- const [selectedFiles, setSelectedFiles] = useState([]);
- const [fileStatuses, setFileStatuses] = useState({});
-
- const handleOpen = () => {
- setView("pendingList");
- setIsOpen(true);
- };
+ const [view, setView] = useState('pendingList');
+ const [targetBatchID, setTargetBatchID] = useState(null);
const handleClose = () => {
setIsOpen(false);
- setSelectedFiles([]);
- setFileStatuses({});
- setCurrentBatchID(null);
- setCurrentBatchNumber("");
- };
-
- const handleUploadSuccess = (returnedBatchID) => {
- setCurrentBatchID(returnedBatchID);
- setView("uploadExisting");
- };
+ setTimeout(() => {
+ setView('pendingList');
+ setTargetBatchID(null);
+ }, 0);
+ }
return (
+ placement="center" size={{ base: "md", md: "xl" }} closeOnInteractOutside={false} closeOnEscape={false} open={isOpen} onOpenChange={(e) => setIsOpen(e.open)} unmountOnExit>
-
@@ -46,38 +32,12 @@ function DialogMain({ pendingBatches }) {
Upload Artefacts to
- {view === "uploadNew" && (
-
- )}
-
- {view === "uploadExisting" && (
-
- )}
+ {view === 'uploadExisting' && }
{view === "pendingList" && (
- setView("uploadNew")}>New Batch
+ setView("uploadExisting")}>New Batch
@@ -100,8 +60,7 @@ function DialogMain({ pendingBatches }) {
timestamp={batch.created}
thumbnail={hp1}
onClick={() => {
- setCurrentBatchID(batch.id);
- setCurrentBatchNumber(batch.batchNumber);
+ setTargetBatchID(batch.id);
setView("uploadExisting");
}}
/>
@@ -114,7 +73,7 @@ function DialogMain({ pendingBatches }) {
-
+
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 4ebc410..ffcc68f 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -1,13 +1,15 @@
import { Button, Flex, Box, Text } from "@chakra-ui/react";
-import { useRef, useState } from "react";
+import { useEffect, useRef, useState } from "react";
import { HiUpload } from "react-icons/hi";
import server from "../../networking";
import ToastWizard from "../../components/toastWizard";
import FileItem from "./FileItem";
-function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID, batchNumber, selectedFiles, setSelectedFiles, fileStatuses, setFileStatuses }) {
+function DialogUploadFile({ batchID, setBatchID }) {
const fileInputRef = useRef(null);
const [isSubmitting, setIsSubmitting] = useState(false);
+ const [selectedFiles, setSelectedFiles] = useState([]);
+ const [fileStatuses, setFileStatuses] = useState({});
const handleButtonClick = () => {
fileInputRef.current?.click();
@@ -64,25 +66,25 @@ function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID,
try {
const res = await server.post("/dataImport/upload", formData, {
headers: { "Content-Type": "multipart/form-data" },
+ transformRequest: formData => formData
});
const data = res.data;
const updates = data.raw?.updates || {};
const returnedBatchID = data.raw?.batchID;
- const returnedBatchNumber = data.raw?.batchNumber;
- const displayBatchNumber = batchNumber || returnedBatchNumber || returnedBatchID;
+ if (returnedBatchID) {
+ setBatchID(returnedBatchID);
+ }
setFileStatuses(updates);
+
ToastWizard.standard(
"success",
"Upload Complete",
- `Uploaded files to Batch ${displayBatchNumber}. Ready for processing.`
+ `Uploaded files to Batch ${returnedBatchID || ''}. Ready for processing.`
);
- if (onSuccess) {
- onSuccess(returnedBatchID);
- }
-
} catch (err) {
+ console.log(`Non-success response in file upload to batch ${batchID || 'New Batch'}`, err)
const updates = err?.response?.data?.raw?.updates;
if (updates) {
setFileStatuses(updates);
@@ -101,9 +103,15 @@ function DialogUploadFile({ onCancel, onSuccess, toLabel, buttonLabel, batchID,
}
};
+ useEffect(() => {
+ return () => {
+ clearAll();
+ }
+ }, []);
+
return (
<>
- To: {toLabel}
+ To: {batchID || "New Batch"}
- {buttonLabel} ({selectedFiles.length})
+ {batchID ? 'Upload to Existing Batch': 'Create New Batch and Upload'} ({selectedFiles.length})
>
diff --git a/src/pages/DataImport.jsx b/src/pages/DataImport.jsx
index 3fa5d5b..e4e6bf0 100644
--- a/src/pages/DataImport.jsx
+++ b/src/pages/DataImport.jsx
@@ -114,6 +114,8 @@ function DataImport() {
};
});
+ // here
+
setBatches(batchList);
} else {
@@ -176,6 +178,7 @@ function DataImport() {
}, [batches]);
const { pendingBatches, batchNumberMap } = batchData;
+ const getBatchNumber = (batchID) => batchNumberMap[batchID];
if (loading) {
return ;
@@ -214,8 +217,11 @@ function DataImport() {
{/* Upload Button */}
-
-
+
{/* Second Row: Stage Filter + Upload Button */}
From c8ac5c9f9d0d27c2d27a59d54e5631c3b5a1bf50 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 12:42:28 +0800
Subject: [PATCH 10/19] Added Done Button to be visible only after file
successfully uploaded once
---
src/components/DataImport/DialogMain.jsx | 16 ++++++-------
.../DataImport/DialogUploadFile.jsx | 24 +++++++++++++++----
.../DataImport/PendingBatchCard.jsx | 14 +++++------
3 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index fa01c83..927eddd 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -2,7 +2,7 @@ import { Button, Dialog, Portal, Flex, Box, Text, VStack, CloseButton } from "@c
import DialogUploadFile from "./DialogUploadFile";
import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
-import { useEffect, useState } from "react";
+import { useState } from "react";
function DialogMain({ pendingBatches }) {
const [isOpen, setIsOpen] = useState(false);
@@ -32,22 +32,22 @@ function DialogMain({ pendingBatches }) {
Upload Artefacts to
- {view === 'uploadExisting' && }
+ {view === 'uploadExisting' && { handleClose() }} />}
{view === "pendingList" && (
-
+
- setView("uploadExisting")}>New Batch
+ setView("uploadExisting")} size={{ base: 'sm', md: 'lg' }}>New Batch
-
+
-
+
Pending Batches
{pendingBatches.length === 0 ? (
-
+
No pending batches.
) : (
@@ -55,7 +55,7 @@ function DialogMain({ pendingBatches }) {
{pendingBatches.map((batch) => (
{
fileInputRef.current?.click();
@@ -77,6 +78,7 @@ function DialogUploadFile({ batchID, setBatchID }) {
setBatchID(returnedBatchID);
}
setFileStatuses(updates);
+ setUploadSucceeded(true);
ToastWizard.standard(
"success",
@@ -170,15 +172,29 @@ function DialogUploadFile({ batchID, setBatchID }) {
)}
-
+
+ {uploadSucceeded && (
+ { onClose(); }}
+ width="fit-content"
+ >
+ Done
+
+ )}
+
- {batchID ? 'Upload to Existing Batch': 'Create New Batch and Upload'} ({selectedFiles.length})
+ {batchID ? 'Upload to Existing Batch' : 'Create New Batch and Upload'} ({selectedFiles.length})
-
+
>
);
}
diff --git a/src/components/DataImport/PendingBatchCard.jsx b/src/components/DataImport/PendingBatchCard.jsx
index 563bdea..616a799 100644
--- a/src/components/DataImport/PendingBatchCard.jsx
+++ b/src/components/DataImport/PendingBatchCard.jsx
@@ -9,8 +9,8 @@ const PendingBatchCard = ({ batchName, artefactCount, timestamp, thumbnail, onCl
bg="white"
shadow="sm"
_hover={{ shadow: "md", cursor: "pointer" }}
- width={{ base: "220px", md: "300px" }}
- height={{ base: "65px", md: "75px" }}
+ width={{ base: "210px", md: "320px" }}
+ height={{ base: "60px", md: "80px" }}
onClick={onClick}
>
@@ -18,20 +18,20 @@ const PendingBatchCard = ({ batchName, artefactCount, timestamp, thumbnail, onCl
src={thumbnail || "/placeholder.jpg"}
alt={batchName}
height={{ base: "50px", md: "60px" }}
- width={{ base: "60px", md: "80px" }}
+ width={{ base: "50px", md: "80px" }}
borderRadius={{ base: "xs", md: "md" }}
mr={{ base: "2", md: "4" }}
/>
-
-
+
+
{batchName}
-
+
{artefactCount != null
? `${artefactCount} Artefact${artefactCount === 1 ? '' : 's'}`
: "No artefacts"}
-
+
{timestamp}
From 0f9242bd9aea05bc43478a8da0be8a52e873fe21 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 14:39:23 +0800
Subject: [PATCH 11/19] Modified to auto update changes of batches
---
src/components/DataImport/DialogMain.jsx | 6 +++---
src/components/DataImport/DialogUploadFile.jsx | 8 ++++++--
src/pages/DataImport.jsx | 1 -
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 927eddd..7696876 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -4,7 +4,7 @@ import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
import { useState } from "react";
-function DialogMain({ pendingBatches }) {
+function DialogMain({ pendingBatches, fetchBatches }) {
const [isOpen, setIsOpen] = useState(false);
const [view, setView] = useState('pendingList');
const [targetBatchID, setTargetBatchID] = useState(null);
@@ -32,12 +32,12 @@ function DialogMain({ pendingBatches }) {
Upload Artefacts to
- {view === 'uploadExisting' && { handleClose() }} />}
+ {view === 'uploadExisting' && }
{view === "pendingList" && (
- setView("uploadExisting")} size={{ base: 'sm', md: 'lg' }}>New Batch
+ setView("uploadExisting")} size={{ base: 'sm', md: 'lg' }}>New Batch
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index b4fcbe0..9e6f4ac 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -5,7 +5,7 @@ import server from "../../networking";
import ToastWizard from "../../components/toastWizard";
import FileItem from "./FileItem";
-function DialogUploadFile({ batchID, setBatchID, onClose }) {
+function DialogUploadFile({ batchID, setBatchID, onClose, fetchBatches }) {
const fileInputRef = useRef(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [selectedFiles, setSelectedFiles] = useState([]);
@@ -79,6 +79,7 @@ function DialogUploadFile({ batchID, setBatchID, onClose }) {
}
setFileStatuses(updates);
setUploadSucceeded(true);
+ fetchBatches();
ToastWizard.standard(
"success",
@@ -172,7 +173,10 @@ function DialogUploadFile({ batchID, setBatchID, onClose }) {
)}
-
+
+
+ Cancel
+
{uploadSucceeded && (
From 03a52dc43d68ba8c35f4936ee512557ffd88f981 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 16:27:40 +0800
Subject: [PATCH 12/19] Modified DialogUploadFile instead of batchid shows the
batchcard
---
src/components/DataImport/DialogMain.jsx | 17 +-
.../DataImport/DialogUploadFile.jsx | 149 +++++++++++-------
.../DataImport/PendingBatchCard.jsx | 2 +-
3 files changed, 105 insertions(+), 63 deletions(-)
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/DialogMain.jsx
index 7696876..c2ec5eb 100644
--- a/src/components/DataImport/DialogMain.jsx
+++ b/src/components/DataImport/DialogMain.jsx
@@ -19,7 +19,14 @@ function DialogMain({ pendingBatches, fetchBatches }) {
return (
setIsOpen(e.open)} unmountOnExit>
+ placement="center"
+ size={view === "uploadExisting" ? { base: "sm", md: "md" } : { base: "sm", md: "xl" }}
+ closeOnInteractOutside={false}
+ closeOnEscape={false}
+ open={isOpen}
+ onOpenChange={(e) => setIsOpen(e.open)}
+ unmountOnExit
+ >
Upload Artefacts
@@ -32,7 +39,13 @@ function DialogMain({ pendingBatches, fetchBatches }) {
Upload Artefacts to
- {view === 'uploadExisting' && }
+ {view === 'uploadExisting' &&
+ b.id === targetBatchID) || null}
+ setBatchID={(id) => setTargetBatchID(id)}
+ onClose={handleClose}
+ fetchBatches={fetchBatches}
+ onBackToPending={() => setView("pendingList")} />}
{view === "pendingList" && (
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 9e6f4ac..8490536 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -4,8 +4,12 @@ import { HiUpload } from "react-icons/hi";
import server from "../../networking";
import ToastWizard from "../../components/toastWizard";
import FileItem from "./FileItem";
+import { IoArrowBackCircleSharp } from "react-icons/io5";
+import PendingBatchCard from "./PendingBatchCard";
+import hp1 from "../../assets/hp1.png";
-function DialogUploadFile({ batchID, setBatchID, onClose, fetchBatches }) {
+function DialogUploadFile({ batch, setBatchID, onClose, fetchBatches, onBackToPending }) {
+ const batchID = batch?.id;
const fileInputRef = useRef(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [selectedFiles, setSelectedFiles] = useState([]);
@@ -114,8 +118,30 @@ function DialogUploadFile({ batchID, setBatchID, onClose, fetchBatches }) {
return (
<>
- To: {batchID || "New Batch"}
+
+
+ {
+ clearAll();
+ setBatchID(null);
+ onBackToPending();
+ }}
+ >
+
+
+
+
+
+
+
}
variant="outline"
- width="full"
+ width={{ base: "400px", md: "full" }}
justifyContent="start"
mb={4}
onClick={handleButtonClick}
@@ -136,68 +162,71 @@ function DialogUploadFile({ batchID, setBatchID, onClose, fetchBatches }) {
Choose Files
- {selectedFiles.length > 0 && (
-
-
-
- {selectedFiles.length} file(s) selected
-
-
- Remove All
-
-
-
-
- {selectedFiles.map((file, index) => (
-
- ))}
+ {
+ selectedFiles.length > 0 && (
+
+
+
+ {selectedFiles.length} file(s) selected
+
+
+ Remove All
+
+
+
+
+ {selectedFiles.map((file, index) => (
+
+ ))}
+
-
- )}
-
- {hasPreviousStatus && (
-
- Click "Remove All" to upload new files.
-
- )}
-
-
-
- Cancel
-
- {uploadSucceeded && (
+ )
+ }
+
+ {
+ hasPreviousStatus && (
+
+ Click "Remove All" to upload new files.
+
+ )
+ }
+
+
+
+ {uploadSucceeded && (
+ { onClose(); }}
+ width="fit-content"
+ >
+ Done
+
+ )}
+
{ onClose(); }}
+ variant="ArchPrimary"
+ disabled={isDisabled}
+ onClick={handleUpload}
width="fit-content"
>
- Done
+ {batchID ? 'Upload to Existing Batch' : 'Create New Batch and Upload'} ({selectedFiles.length})
- )}
-
-
- {batchID ? 'Upload to Existing Batch' : 'Create New Batch and Upload'} ({selectedFiles.length})
-
+
>
);
diff --git a/src/components/DataImport/PendingBatchCard.jsx b/src/components/DataImport/PendingBatchCard.jsx
index 616a799..52a2e24 100644
--- a/src/components/DataImport/PendingBatchCard.jsx
+++ b/src/components/DataImport/PendingBatchCard.jsx
@@ -9,7 +9,7 @@ const PendingBatchCard = ({ batchName, artefactCount, timestamp, thumbnail, onCl
bg="white"
shadow="sm"
_hover={{ shadow: "md", cursor: "pointer" }}
- width={{ base: "210px", md: "320px" }}
+ width={{ base: "210px", md: "350px" }}
height={{ base: "60px", md: "80px" }}
onClick={onClick}
>
From ceb421558ccce949726cffd5998cf61a2389d62b Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 17:10:15 +0800
Subject: [PATCH 13/19] Added isLoading, loadingText to show loading msg while
uploading
---
src/components/DataImport/DialogUploadFile.jsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 8490536..58a134a 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -222,7 +222,8 @@ function DialogUploadFile({ batch, setBatchID, onClose, fetchBatches, onBackToPe
variant="ArchPrimary"
disabled={isDisabled}
onClick={handleUpload}
- width="fit-content"
+ isLoading={isSubmitting}
+ loadingText={batchID ? `Uploading ${selectedFiles.length} file(s)...` : `Creating batch...`}
>
{batchID ? 'Upload to Existing Batch' : 'Create New Batch and Upload'} ({selectedFiles.length})
From afe19b1d182e4c7fb1c34e1bd3c72b362afae702 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 17:21:26 +0800
Subject: [PATCH 14/19] Deleted DialogUpload, Changed name for DialogMain to
UploadArtefact
---
src/components/DataImport/DialogUpload.jsx | 256 ------------------
.../DataImport/DialogUploadFile.jsx | 2 +-
.../{DialogMain.jsx => UploadArtefact.jsx} | 0
3 files changed, 1 insertion(+), 257 deletions(-)
delete mode 100644 src/components/DataImport/DialogUpload.jsx
rename src/components/DataImport/{DialogMain.jsx => UploadArtefact.jsx} (100%)
diff --git a/src/components/DataImport/DialogUpload.jsx b/src/components/DataImport/DialogUpload.jsx
deleted file mode 100644
index ff7c556..0000000
--- a/src/components/DataImport/DialogUpload.jsx
+++ /dev/null
@@ -1,256 +0,0 @@
-import { Button, FileUpload, VStack, Text, Box, CloseButton, Dialog, Portal, Badge } from "@chakra-ui/react";
-import { HiUpload } from "react-icons/hi";
-import { useState, useRef } from "react";
-import server from "../../networking";
-import ToastWizard from "../../components/toastWizard";
-import { FaPlus } from "react-icons/fa";
-
-function DialogUpload() {
- const [files, setFiles] = useState([]);
- const [fileStatuses, setFileStatuses] = useState({});
- const [isSubmitting, setIsSubmitting] = useState(false);
- const [batchID, setBatchID] = useState(null);
- const [isConfirmed, setIsConfirmed] = useState(false);
- const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false);
- const inputRef = useRef();
- const isUploading = useRef(false);
-
- // Handle file upload
- const handleFileChange = async (e) => {
- if (isUploading.current) return;
- isUploading.current = true;
-
- const selected = Array.from(e.target.files);
- setFiles(selected);
- setFileStatuses({});
- if (selected.length === 0) return;
-
- const formData = new FormData();
- selected.forEach((file) => formData.append("file", file));
-
- setIsSubmitting(true);
- try {
- const res = await server.post("/dataImport/upload", formData, {
- headers: { "Content-Type": "multipart/form-data" },
- });
-
- const data = res.data;
- const updates = data.raw?.updates || {};
- const newBatchID = data.raw?.batchID;
-
- setFileStatuses(updates);
- setBatchID(newBatchID);
- setIsConfirmed(false);
-
- ToastWizard.standard("success", "Upload Complete", `Batch ID: ${newBatchID}. Ready for confirmation.`);
- } catch (err) {
- const updates = err?.response?.data?.raw?.updates;
- if (updates) {
- setFileStatuses(updates);
- }
- ToastWizard.standard("error", "Upload Failed", "Failed to upload files.");
- } finally {
- setIsSubmitting(false);
- isUploading.current = false;
- }
- };
-
- const handleConfirmBatch = async () => {
- if (!batchID) return;
-
- setIsSubmitting(true);
- try {
- const res = await server.post("/dataImport/confirm", { batchID });
-
- if (res.status === 200 || res.data.raw.success !== false) {
- setIsConfirmed(true);
- ToastWizard.standard("success", "Processing Started", `Batch ${batchID} is now being processed.`);
- setIsConfirmDialogOpen(false);
-
- } else {
- ToastWizard.standard("error", "Failed to Confirm", res.data.message || "Unknown error.");
- }
- } catch (err) {
- const errorMsg = err?.response?.data?.message || "Failed to confirm batch.";
- ToastWizard.standard("error", "Confirm Error", errorMsg);
-
- } finally {
- setIsSubmitting(false);
- }
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- Upload Files
-
-
-
-
-
-
-
-
-
- }
- isLoading={isSubmitting}
- >
- Upload
-
-
-
- {/* Custom file list with status and remove button */}
- {files.length > 0 && (
-
- {files.map((file) => {
- const status = fileStatuses[file.name];
- return (
-
-
-
- {file.name}
-
-
- {(file.size / 1024).toFixed(1)} KB
-
-
-
- {status && (
-
- {status.startsWith("ERROR") && (
-
- Error
-
- )}
-
- {status}
-
-
- {
- setFiles((prev) =>
- prev.filter((f) => f.name !== file.name)
- );
- setFileStatuses((prev) => {
- const updated = { ...prev };
- delete updated[file.name];
- return updated;
- });
- }}
- />
-
- )}
-
- );
- })}
-
- )}
-
-
-
-
- setFiles([])}
- isDisabled={isSubmitting}
- >
- Clear
-
-
- {/* Only show Confirm button after upload */}
- {batchID && !isConfirmed && (
- setIsConfirmDialogOpen(true)}
- isDisabled={isSubmitting}
- >
- Confirm & Process
-
- )}
-
- {isConfirmed && (
-
- Processing started for Batch {batchID}
-
- )}
-
-
-
-
-
- setIsConfirmDialogOpen(open)}>
-
-
-
-
- Confirm Processing
-
-
- Are you sure you want to process batch{" "}
-
- {batchID}
-
- ? This will start processing the artefacts in the batch.
-
-
-
- setIsConfirmDialogOpen(false)}>
- Cancel
-
-
- Confirm
-
-
-
-
-
-
-
- );
-}
-
-export default DialogUpload;
\ No newline at end of file
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/DialogUploadFile.jsx
index 58a134a..3d14878 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/DialogUploadFile.jsx
@@ -2,7 +2,7 @@ import { Button, Flex, Box, Text } from "@chakra-ui/react";
import { useEffect, useRef, useState } from "react";
import { HiUpload } from "react-icons/hi";
import server from "../../networking";
-import ToastWizard from "../../components/toastWizard";
+import ToastWizard from "../toastWizard";
import FileItem from "./FileItem";
import { IoArrowBackCircleSharp } from "react-icons/io5";
import PendingBatchCard from "./PendingBatchCard";
diff --git a/src/components/DataImport/DialogMain.jsx b/src/components/DataImport/UploadArtefact.jsx
similarity index 100%
rename from src/components/DataImport/DialogMain.jsx
rename to src/components/DataImport/UploadArtefact.jsx
From 712adb4f372043714e710b6fbf159faccc313f4c Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 17:25:09 +0800
Subject: [PATCH 15/19] Change function name from DialogName to UploadArtefact
---
src/components/DataImport/UploadArtefact.jsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/DataImport/UploadArtefact.jsx b/src/components/DataImport/UploadArtefact.jsx
index c2ec5eb..cbc5a85 100644
--- a/src/components/DataImport/UploadArtefact.jsx
+++ b/src/components/DataImport/UploadArtefact.jsx
@@ -4,7 +4,7 @@ import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
import { useState } from "react";
-function DialogMain({ pendingBatches, fetchBatches }) {
+function UploadArtefact({ pendingBatches, fetchBatches }) {
const [isOpen, setIsOpen] = useState(false);
const [view, setView] = useState('pendingList');
const [targetBatchID, setTargetBatchID] = useState(null);
@@ -96,4 +96,4 @@ function DialogMain({ pendingBatches, fetchBatches }) {
)
}
-export default DialogMain;
\ No newline at end of file
+export default UploadArtefact;
\ No newline at end of file
From dfd544679b54e05d0ee0b5ac24a0672991a59274 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 17:39:26 +0800
Subject: [PATCH 16/19] Change import from DialogMain to UploadArtefact
---
src/pages/DataImport.jsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/pages/DataImport.jsx b/src/pages/DataImport.jsx
index c443436..ea91fae 100644
--- a/src/pages/DataImport.jsx
+++ b/src/pages/DataImport.jsx
@@ -7,7 +7,7 @@ import ToastWizard from '../components/toastWizard'
import server, { JSONResponse } from "../networking";
import BatchCard from "../components/DataImport/BatchCard";
// import DialogUpload from "../components/DataImport/DialogUpload";
-import DialogMain from "../components/DataImport/DialogMain.jsx";
+import UploadArtefact from "../components/DataImport/UploadArtefact.jsx";
import CentredSpinner from "../components/centredSpinner.jsx";
const stageCollection = createListCollection({
@@ -217,7 +217,7 @@ function DataImport() {
{/* Upload Button */}
-
From 22605771a4350d49d6601e1cb7192efe06847ecc Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 18:35:37 +0800
Subject: [PATCH 17/19] Change File & Function Name, added toastwizard
---
...{DialogUploadFile.jsx => ArtefactUploadView.jsx} | 13 ++++++++-----
.../{UploadArtefact.jsx => ImportMenuDialog.jsx} | 10 +++++-----
src/pages/DataImport.jsx | 5 ++---
3 files changed, 15 insertions(+), 13 deletions(-)
rename src/components/DataImport/{DialogUploadFile.jsx => ArtefactUploadView.jsx} (94%)
rename src/components/DataImport/{UploadArtefact.jsx => ImportMenuDialog.jsx} (95%)
diff --git a/src/components/DataImport/DialogUploadFile.jsx b/src/components/DataImport/ArtefactUploadView.jsx
similarity index 94%
rename from src/components/DataImport/DialogUploadFile.jsx
rename to src/components/DataImport/ArtefactUploadView.jsx
index 3d14878..70467d4 100644
--- a/src/components/DataImport/DialogUploadFile.jsx
+++ b/src/components/DataImport/ArtefactUploadView.jsx
@@ -8,7 +8,7 @@ import { IoArrowBackCircleSharp } from "react-icons/io5";
import PendingBatchCard from "./PendingBatchCard";
import hp1 from "../../assets/hp1.png";
-function DialogUploadFile({ batch, setBatchID, onClose, fetchBatches, onBackToPending }) {
+function ArtefactUploadView({ batch, setBatchID, onClose, fetchBatches, onBackToPending }) {
const batchID = batch?.id;
const fileInputRef = useRef(null);
const [isSubmitting, setIsSubmitting] = useState(false);
@@ -55,7 +55,10 @@ function DialogUploadFile({ batch, setBatchID, onClose, fetchBatches, onBackToPe
hasPreviousStatus;
const handleUpload = async () => {
- if (selectedFiles.length === 0 || isSubmitting) return;
+ if (selectedFiles.length === 0 || isSubmitting) {
+ ToastWizard.standard("warning", "No Files Selected", "Please choose at least one file before uploading.");
+ return;
+ }
const formData = new FormData();
selectedFiles.forEach((file) => {
@@ -207,8 +210,8 @@ function DialogUploadFile({ batch, setBatchID, onClose, fetchBatches, onBackToPe
{uploadSucceeded && (
{ onClose(); }}
@@ -233,4 +236,4 @@ function DialogUploadFile({ batch, setBatchID, onClose, fetchBatches, onBackToPe
);
}
-export default DialogUploadFile;
\ No newline at end of file
+export default ArtefactUploadView;
\ No newline at end of file
diff --git a/src/components/DataImport/UploadArtefact.jsx b/src/components/DataImport/ImportMenuDialog.jsx
similarity index 95%
rename from src/components/DataImport/UploadArtefact.jsx
rename to src/components/DataImport/ImportMenuDialog.jsx
index cbc5a85..65be9a4 100644
--- a/src/components/DataImport/UploadArtefact.jsx
+++ b/src/components/DataImport/ImportMenuDialog.jsx
@@ -1,10 +1,10 @@
import { Button, Dialog, Portal, Flex, Box, Text, VStack, CloseButton } from "@chakra-ui/react";
-import DialogUploadFile from "./DialogUploadFile";
+import ArtefactUploadView from "./ArtefactUploadView";
import hp1 from "../../assets/hp1.png";
import PendingBatchCard from "./PendingBatchCard";
import { useState } from "react";
-function UploadArtefact({ pendingBatches, fetchBatches }) {
+function ImportMenuDialog({ pendingBatches, fetchBatches }) {
const [isOpen, setIsOpen] = useState(false);
const [view, setView] = useState('pendingList');
const [targetBatchID, setTargetBatchID] = useState(null);
@@ -36,11 +36,11 @@ function UploadArtefact({ pendingBatches, fetchBatches }) {
- Upload Artefacts to
+ Upload Artefacts
{view === 'uploadExisting' &&
- b.id === targetBatchID) || null}
setBatchID={(id) => setTargetBatchID(id)}
onClose={handleClose}
@@ -96,4 +96,4 @@ function UploadArtefact({ pendingBatches, fetchBatches }) {
)
}
-export default UploadArtefact;
\ No newline at end of file
+export default ImportMenuDialog;
\ No newline at end of file
diff --git a/src/pages/DataImport.jsx b/src/pages/DataImport.jsx
index ea91fae..e79b0c8 100644
--- a/src/pages/DataImport.jsx
+++ b/src/pages/DataImport.jsx
@@ -6,8 +6,7 @@ import { useSelector } from "react-redux";
import ToastWizard from '../components/toastWizard'
import server, { JSONResponse } from "../networking";
import BatchCard from "../components/DataImport/BatchCard";
-// import DialogUpload from "../components/DataImport/DialogUpload";
-import UploadArtefact from "../components/DataImport/UploadArtefact.jsx";
+import ImportMenuDialog from "../components/DataImport/ImportMenuDialog.jsx";
import CentredSpinner from "../components/centredSpinner.jsx";
const stageCollection = createListCollection({
@@ -217,7 +216,7 @@ function DataImport() {
{/* Upload Button */}
-
From b89adc8cd8c0c8f2cb88d44882a77157e09bc925 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 18:45:32 +0800
Subject: [PATCH 18/19] Remove redundant filtering and filter while fetching
the batch
---
.../DataImport/ArtefactUploadView.jsx | 2 +-
src/pages/DataImport.jsx | 56 ++++++++-----------
2 files changed, 25 insertions(+), 33 deletions(-)
diff --git a/src/components/DataImport/ArtefactUploadView.jsx b/src/components/DataImport/ArtefactUploadView.jsx
index 70467d4..756e2ce 100644
--- a/src/components/DataImport/ArtefactUploadView.jsx
+++ b/src/components/DataImport/ArtefactUploadView.jsx
@@ -225,7 +225,7 @@ function ArtefactUploadView({ batch, setBatchID, onClose, fetchBatches, onBackTo
variant="ArchPrimary"
disabled={isDisabled}
onClick={handleUpload}
- isLoading={isSubmitting}
+ loading={isSubmitting}
loadingText={batchID ? `Uploading ${selectedFiles.length} file(s)...` : `Creating batch...`}
>
{batchID ? 'Upload to Existing Batch' : 'Create New Batch and Upload'} ({selectedFiles.length})
diff --git a/src/pages/DataImport.jsx b/src/pages/DataImport.jsx
index e79b0c8..93b0c7f 100644
--- a/src/pages/DataImport.jsx
+++ b/src/pages/DataImport.jsx
@@ -59,6 +59,9 @@ function DataImport() {
const [loading, setLoading] = useState(true);
const [selectedStages, setSelectedStages] = useState([]);
const [isRefreshing, setIsRefreshing] = useState(false);
+ const [batchNumberMap, setBatchNumberMap] = useState({});
+ const [pendingBatches, setPendingBatches] = useState([]);
+
const { loaded } = useSelector(state => state.auth);
@@ -113,9 +116,23 @@ function DataImport() {
};
});
- // here
+ const sorted = batchList.sort((a, b) => new Date(a.created) - new Date(b.created));
+ const batchNumberMap = {};
+ sorted.forEach((batch, i) => {
+ batchNumberMap[batch.id] = i + 1;
+ });
+
+ const pendingBatches = sorted
+ .filter(b => b.stage === "upload_pending")
+ .map(b => ({
+ ...b,
+ created: formatTimestamp(b.created),
+ artefactCount: b.artefactSummary?.total ?? 0,
+ }));
- setBatches(batchList);
+ setBatches(sorted);
+ setBatchNumberMap(batchNumberMap);
+ setPendingBatches(pendingBatches);
} else {
throw new Error("Unexpected response format");
@@ -147,37 +164,12 @@ function DataImport() {
const stageGroups = useMemo(() => {
return stages
.filter(stage => selectedStages.length === 0 || selectedStages.includes(stage))
- .map(stage => {
- const filtered = batches.filter(batch => batch.stage === stage);
- return { stage, label: stageLabels[stage], batches: filtered };
- });
- }, [batches, selectedStages]);
-
- const batchData = useMemo(() => {
- const sorted = [...batches].sort((a, b) => new Date(a.created) - new Date(b.created));
-
- const batchNumberMap = {};
- const numberedBatches = sorted.map((batch, i) => {
- batchNumberMap[batch.id] = i + 1;
- return {
- ...batch,
- batchNumber: i + 1,
- };
- });
-
- const pendingBatches = numberedBatches
- .filter(b => b.stage === "upload_pending")
- .map(batch => ({
- ...batch,
- created: formatTimestamp(batch.created),
- artefactCount: batch.artefactSummary?.total ?? 0,
+ .map(stage => ({
+ stage,
+ label: stageLabels[stage],
+ batches: batches.filter(batch => batch.stage === stage),
}));
-
- return { pendingBatches, batchNumberMap };
- }, [batches]);
-
- const { pendingBatches, batchNumberMap } = batchData;
- const getBatchNumber = (batchID) => batchNumberMap[batchID];
+ }, [batches, selectedStages, stageLabels, stages]);
if (loading) {
return ;
From 21442438d98fa3fee37c832df87408f8eea44cab Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Wed, 13 Aug 2025 18:58:30 +0800
Subject: [PATCH 19/19] Removed Done Button
---
src/components/DataImport/ArtefactUploadView.jsx | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/src/components/DataImport/ArtefactUploadView.jsx b/src/components/DataImport/ArtefactUploadView.jsx
index 756e2ce..e41d223 100644
--- a/src/components/DataImport/ArtefactUploadView.jsx
+++ b/src/components/DataImport/ArtefactUploadView.jsx
@@ -14,7 +14,6 @@ function ArtefactUploadView({ batch, setBatchID, onClose, fetchBatches, onBackTo
const [isSubmitting, setIsSubmitting] = useState(false);
const [selectedFiles, setSelectedFiles] = useState([]);
const [fileStatuses, setFileStatuses] = useState({});
- const [uploadSucceeded, setUploadSucceeded] = useState(false);
const handleButtonClick = () => {
fileInputRef.current?.click();
@@ -85,7 +84,6 @@ function ArtefactUploadView({ batch, setBatchID, onClose, fetchBatches, onBackTo
setBatchID(returnedBatchID);
}
setFileStatuses(updates);
- setUploadSucceeded(true);
fetchBatches();
ToastWizard.standard(
@@ -208,19 +206,6 @@ function ArtefactUploadView({ batch, setBatchID, onClose, fetchBatches, onBackTo
- {uploadSucceeded && (
- { onClose(); }}
- width="fit-content"
- >
- Done
-
- )}
-