From b3363beb63f8761b5a2db455db88f5879710db7d Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Thu, 14 Aug 2025 19:11:34 +0800
Subject: [PATCH 1/3] Updated itemChat
Passed down artefactID form section to catalogueItemView to itemChat
---
.../Catalogue/catalogueItemView.jsx | 56 ++++----
src/components/Catalogue/itemChat.jsx | 129 +++++++++++++++++-
src/components/Catalogue/section.jsx | 11 +-
3 files changed, 161 insertions(+), 35 deletions(-)
diff --git a/src/components/Catalogue/catalogueItemView.jsx b/src/components/Catalogue/catalogueItemView.jsx
index 2afa607..7a6073e 100644
--- a/src/components/Catalogue/catalogueItemView.jsx
+++ b/src/components/Catalogue/catalogueItemView.jsx
@@ -12,7 +12,7 @@ import { IoOpen } from "react-icons/io5";
const MotionBox = motion.create(Box);
const MotionChevron = motion.create(Box);
-const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialogTitle, imageSrc }) => {
+const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialogTitle, imageSrc, artefactID }) => {
const [isNavigating, setIsNavigating] = useState(false);
const [direction, setDirection] = useState(0);
const [isInitialRender, setIsInitialRender] = useState(true);
@@ -92,11 +92,11 @@ const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialog
debounceTimeout = setTimeout(() => {
const scrollLeft = scrollRef.current.scrollLeft;
const newIndex = Math.round(scrollLeft / window.innerWidth);
-
+
if (newIndex !== currentIndex && items[newIndex]) {
setDialogTitle(items[newIndex].title);
}
-
+
// Reset scrolling flag after debounce
isScrolling = false;
}, 100); // Keep the debounce time reasonable (100ms)
@@ -104,7 +104,7 @@ const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialog
const scrollEl = scrollRef.current;
scrollEl.addEventListener("scroll", handleScroll);
-
+
return () => {
scrollEl.removeEventListener("scroll", handleScroll);
if (debounceTimeout) clearTimeout(debounceTimeout);
@@ -151,13 +151,13 @@ const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialog
left: isMobile
? "10px"
: isTablet
- ? "calc(5vw - 50px)"
- : "calc(10vw - 60px)",
+ ? "calc(5vw - 50px)"
+ : "calc(10vw - 60px)",
right: isMobile
? "10px"
: isTablet
- ? "calc(5vw - 50px)"
- : "calc(10vw - 60px)",
+ ? "calc(5vw - 50px)"
+ : "calc(10vw - 60px)",
top: "50%",
};
@@ -362,15 +362,15 @@ const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialog
{item.title}
-
- navigate(`/studio/${sectionId}/${currentId}`)} cursor={"pointer"}/>
+ navigate(`/studio/${sectionId}/${currentId}`)} cursor={"pointer"} />
@@ -394,14 +394,14 @@ const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialog
{selectedSegment ===
- "metadata" ? (
+ "metadata" ? (
) : selectedSegment ===
- "chat" ? (
-
+ "chat" ? (
+
) : null}
@@ -500,15 +500,15 @@ const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialog
{title}
-
- navigate(`/studio/${sectionId}/${currentId}`)} cursor={"pointer"}/>
+ navigate(`/studio/${sectionId}/${currentId}`)} cursor={"pointer"} />
@@ -532,14 +532,14 @@ const CatalogueItemView = ({ isOpen, onClose, title, sectionId, items, setDialog
{selectedSegment ===
- "metadata" ? (
+ "metadata" ? (
) : selectedSegment ===
- "chat" ? (
-
+ "chat" ? (
+
) : null}
diff --git a/src/components/Catalogue/itemChat.jsx b/src/components/Catalogue/itemChat.jsx
index 415be99..50209ac 100644
--- a/src/components/Catalogue/itemChat.jsx
+++ b/src/components/Catalogue/itemChat.jsx
@@ -1,5 +1,128 @@
-function ItemChat() {
- return
ItemChat
;
+import { useState, useEffect, useRef } from "react";
+import { Input, Box, Button, VStack, HStack, Text } from "@chakra-ui/react";
+import { IoIosSend } from "react-icons/io";
+import server, { JSONResponse } from "../../networking";
+import ToastWizard from "../toastWizard";
+
+function ItemChat({ artefactID }) {
+ const [messages, setMessages] = useState([]);
+ const [input, setInput] = useState("");
+ const [loading, setLoading] = useState(false);
+ const messagesEndRef = useRef(null);
+
+ useEffect(() => {
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
+ }, [messages]);
+
+ const sendMessage = async () => {
+ if (!input.trim() || loading) return;
+
+ const userMessageContent = input;
+ setInput("");
+ setLoading(true);
+
+ try {
+ const response = await server.post('/chatbot/query', {
+ artefactID: artefactID,
+ newPrompt: userMessageContent,
+ history: messages
+ })
+
+ if (response.data instanceof JSONResponse) {
+ if (response.data.isErrorStatus()) {
+ const errObject = {
+ response: {
+ data: response.data
+ }
+ };
+ throw new Error(errObject);
+ }
+
+ // Success case
+ if (response.data?.raw?.history) {
+ setMessages(response.data.raw.history);
+ }
+ } else {
+ throw new Error("Unexpected response format");
+ }
+ } catch (err) {
+ if (err.response && err.response.data instanceof JSONResponse) {
+ console.log("Error response in chatbot query:", err.response.data.fullMessage());
+ if (err.response.data.userErrorType()) {
+ ToastWizard.standard("error", "Chatbot query failed.", err.response.data.message);
+ } else {
+ ToastWizard.standard("error", "Chatbot query failed.", "An unexpected error occurred.");
+ }
+ } else {
+ console.log("Unexpected error in chatbot query:", err);
+ ToastWizard.standard("error", "Chatbot query failed.", "An unexpected error occurred.");
+ }
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleKeyDown = (e) => {
+ if (e.key === "Enter" && !e.shiftKey) {
+ e.preventDefault();
+ sendMessage();
+ }
+ };
+
+ return (
+
+
+ {messages.length === 0 ? (
+
+ No messages yet. Start chatting!
+
+ ) : (
+ messages.map((msg, idx) => (
+
+
+ {msg.role === "user" ? "You: " : "Archivus: "}
+
+ {msg.content}
+
+ ))
+ )}
+
+
+
+
+ setInput(e.target.value)}
+ onKeyDown={handleKeyDown}
+ disabled={loading}
+ />
+ }
+ px={6}
+ >
+ Send
+
+
+
+ );
}
-export default ItemChat;
+export default ItemChat;
\ No newline at end of file
diff --git a/src/components/Catalogue/section.jsx b/src/components/Catalogue/section.jsx
index 0d9bb91..8206c51 100644
--- a/src/components/Catalogue/section.jsx
+++ b/src/components/Catalogue/section.jsx
@@ -25,6 +25,7 @@ const Section = ({ sectionTitle, sectionId, onItemClick, artefacts = [] }) => {
const [atEnd, setAtEnd] = useState(false);
const [dialogOpen, setDialogOpen] = useState(false);
const [dialogTitle, setDialogTitle] = useState("");
+ const [dialogArtefactID, setDialogArtefactID] = useState("");
const checkScrollEdges = () => {
const node = scrollRef.current;
@@ -45,10 +46,11 @@ const Section = ({ sectionTitle, sectionId, onItemClick, artefacts = [] }) => {
});
};
- const handleCardClick = (title) => {
- setDialogTitle(title);
+ const handleCardClick = (item) => {
+ setDialogTitle(item.title);
+ setDialogArtefactID(item.id);
setDialogOpen(true);
- if (onItemClick) onItemClick(title);
+ if (onItemClick) onItemClick(item.id);
};
useEffect(() => {
@@ -129,7 +131,7 @@ const Section = ({ sectionTitle, sectionId, onItemClick, artefacts = [] }) => {
flex="0 0 auto"
cursor="pointer"
borderRadius="md"
- onClick={() => handleCardClick(item.title)}
+ onClick={() => handleCardClick(item)}
>
{
setDialogOpen(false)}
+ artefactID={dialogArtefactID}
title={dialogTitle}
sectionId={sectionId}
items={items}
From 2055d737e150a4a43da559fa3c9161e6814582f6 Mon Sep 17 00:00:00 2001
From: ZacTohZY <234453p@mymail.nyp.edu.sg>
Date: Thu, 14 Aug 2025 23:37:00 +0800
Subject: [PATCH 2/3] Modified to create msg object immediately added
---
src/components/Catalogue/itemChat.jsx | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/src/components/Catalogue/itemChat.jsx b/src/components/Catalogue/itemChat.jsx
index 50209ac..e21ea9a 100644
--- a/src/components/Catalogue/itemChat.jsx
+++ b/src/components/Catalogue/itemChat.jsx
@@ -17,14 +17,15 @@ function ItemChat({ artefactID }) {
const sendMessage = async () => {
if (!input.trim() || loading) return;
- const userMessageContent = input;
+ const userMessage = { role: "user", content: input };
+ setMessages(prev => [...prev, userMessage]);
setInput("");
setLoading(true);
try {
const response = await server.post('/chatbot/query', {
- artefactID: artefactID,
- newPrompt: userMessageContent,
+ artefactID,
+ newPrompt: input,
history: messages
})
@@ -38,10 +39,14 @@ function ItemChat({ artefactID }) {
throw new Error(errObject);
}
- // Success case
- if (response.data?.raw?.history) {
- setMessages(response.data.raw.history);
+ if (response.data?.raw?.data?.history) {
+ setMessages(response.data.raw.data.history);
+ } else if (response.data?.raw?.data?.response) {
+ setMessages(prev => [...prev,
+ { role: "assistant", content: response.data.raw.data.response }
+ ]);
}
+
} else {
throw new Error("Unexpected response format");
}
@@ -82,7 +87,7 @@ function ItemChat({ artefactID }) {
>
{messages.length === 0 ? (
- No messages yet. Start chatting!
+ Let's discover this artefact together !
) : (
messages.map((msg, idx) => (
@@ -105,7 +110,7 @@ function ItemChat({ artefactID }) {
setInput(e.target.value)}
onKeyDown={handleKeyDown}
@@ -114,7 +119,7 @@ function ItemChat({ artefactID }) {
}
px={6}
>
From 82cbbaea4e163a5316d6b82f0b805ab83f2a96e6 Mon Sep 17 00:00:00 2001
From: Prakhar Trivedi
Date: Fri, 15 Aug 2025 10:50:35 +0800
Subject: [PATCH 3/3] removed initemchat send button nonexistent righticon
attribute
---
src/components/Catalogue/itemChat.jsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/Catalogue/itemChat.jsx b/src/components/Catalogue/itemChat.jsx
index e21ea9a..51d1ebb 100644
--- a/src/components/Catalogue/itemChat.jsx
+++ b/src/components/Catalogue/itemChat.jsx
@@ -120,7 +120,6 @@ function ItemChat({ artefactID }) {
onClick={sendMessage}
loading={loading}
variant={"ArchPrimaryAlt"}
- rightIcon={}
px={6}
>
Send