Spaces:
Running
Running
Update static/application.js
Browse files- static/application.js +48 -17
static/application.js
CHANGED
@@ -167,37 +167,61 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
167 |
const sendBtn = document.querySelector(".sendingQA");
|
168 |
const fileBtn = document.querySelector(".fa-file");
|
169 |
const imageBtn = document.querySelector(".fa-image");
|
|
|
170 |
|
171 |
let selectedFile = null;
|
172 |
let filePreviewBubble = null;
|
173 |
|
174 |
-
// Hidden
|
175 |
const fileInput = document.createElement("input");
|
176 |
fileInput.type = "file";
|
177 |
fileInput.style.display = "none";
|
178 |
document.body.appendChild(fileInput);
|
179 |
|
180 |
-
// Trigger file input (DOCS)
|
181 |
fileBtn.addEventListener("click", () => {
|
182 |
-
fileInput.value = "";
|
183 |
fileInput.accept = ".pdf,.docx,.pptx,.xlsx";
|
184 |
fileInput.click();
|
185 |
});
|
186 |
|
187 |
-
// Trigger file input (IMAGES)
|
188 |
imageBtn.addEventListener("click", () => {
|
189 |
-
fileInput.value = "";
|
190 |
fileInput.accept = "image/*";
|
191 |
fileInput.click();
|
192 |
});
|
193 |
|
194 |
-
// When file selected
|
195 |
fileInput.addEventListener("change", () => {
|
196 |
const file = fileInput.files[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
if (file) {
|
198 |
selectedFile = file;
|
199 |
|
200 |
-
// Replace preview bubble
|
201 |
if (filePreviewBubble) filePreviewBubble.remove();
|
202 |
|
203 |
filePreviewBubble = document.createElement("div");
|
@@ -208,6 +232,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
208 |
}
|
209 |
});
|
210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
function createMessageBubble(text, sender = "You", audioSrc = null, fileName = null) {
|
212 |
const bubble = document.createElement("div");
|
213 |
bubble.className = `bubble ${sender === "You" ? "right" : "left"}`;
|
@@ -220,7 +252,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
220 |
message.className = "text";
|
221 |
message.style.whiteSpace = "pre-wrap";
|
222 |
|
223 |
-
// User message with file
|
224 |
if (sender === "You") {
|
225 |
const fileLine = fileName ? `π Selected file: ${fileName}\n` : "";
|
226 |
message.innerText = `${fileLine}β ${text}`;
|
@@ -233,7 +264,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
233 |
msgSpan.innerText = text;
|
234 |
message.appendChild(msgSpan);
|
235 |
|
236 |
-
// Chris answer with speaker
|
237 |
if (audioSrc) {
|
238 |
const icon = document.createElement("i");
|
239 |
icon.className = "fa-solid fa-volume-high audio-toggle";
|
@@ -246,7 +276,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
246 |
|
247 |
icon.addEventListener("click", () => {
|
248 |
if (audio.muted) {
|
249 |
-
audio.currentTime = 0;
|
250 |
audio.muted = false;
|
251 |
audio.play();
|
252 |
icon.classList.replace("fa-volume-xmark", "fa-volume-high");
|
@@ -270,6 +300,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
270 |
}
|
271 |
|
272 |
sendBtn.addEventListener("click", async () => {
|
|
|
273 |
const question = input.value.trim();
|
274 |
if (!question) return;
|
275 |
|
@@ -283,15 +314,17 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
283 |
filePreviewBubble = null;
|
284 |
}
|
285 |
|
286 |
-
// User message
|
287 |
createMessageBubble(question, "You", null, selectedFile.name);
|
288 |
-
|
289 |
-
// Thinking bubble
|
290 |
const thinkingBubble = createMessageBubble("π§ Let me think...", "Chris");
|
291 |
|
|
|
|
|
|
|
|
|
|
|
292 |
const formData = new FormData();
|
293 |
formData.append("question", question);
|
294 |
-
formData.append("file",
|
295 |
|
296 |
try {
|
297 |
const response = await fetch("/predict", {
|
@@ -306,7 +339,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
306 |
const message = thinkingBubble.querySelector(".text");
|
307 |
message.innerText = answerText;
|
308 |
|
309 |
-
// Re-add speaker icon if audio
|
310 |
if (audioSrc) {
|
311 |
const icon = document.createElement("i");
|
312 |
icon.className = "fa-solid fa-volume-high audio-toggle";
|
@@ -342,7 +374,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
342 |
message.innerText = "β οΈ Chris had trouble responding.";
|
343 |
}
|
344 |
|
345 |
-
|
346 |
-
// Do NOT clear selectedFile so user can ask follow-up questions
|
347 |
});
|
348 |
});
|
|
|
167 |
const sendBtn = document.querySelector(".sendingQA");
|
168 |
const fileBtn = document.querySelector(".fa-file");
|
169 |
const imageBtn = document.querySelector(".fa-image");
|
170 |
+
const resetBtn = document.querySelector(".reset-chat");
|
171 |
|
172 |
let selectedFile = null;
|
173 |
let filePreviewBubble = null;
|
174 |
|
175 |
+
// Hidden input
|
176 |
const fileInput = document.createElement("input");
|
177 |
fileInput.type = "file";
|
178 |
fileInput.style.display = "none";
|
179 |
document.body.appendChild(fileInput);
|
180 |
|
|
|
181 |
fileBtn.addEventListener("click", () => {
|
182 |
+
fileInput.value = "";
|
183 |
fileInput.accept = ".pdf,.docx,.pptx,.xlsx";
|
184 |
fileInput.click();
|
185 |
});
|
186 |
|
|
|
187 |
imageBtn.addEventListener("click", () => {
|
188 |
+
fileInput.value = "";
|
189 |
fileInput.accept = "image/*";
|
190 |
fileInput.click();
|
191 |
});
|
192 |
|
|
|
193 |
fileInput.addEventListener("change", () => {
|
194 |
const file = fileInput.files[0];
|
195 |
+
if (file) {
|
196 |
+
selectedFile = file;
|
197 |
+
if (filePreviewBubble) filePreviewBubble.remove();
|
198 |
+
|
199 |
+
filePreviewBubble = document.createElement("div");
|
200 |
+
filePreviewBubble.className = "file-preview-bubble bubble right";
|
201 |
+
filePreviewBubble.textContent = `π Selected: ${file.name}`;
|
202 |
+
convo.appendChild(filePreviewBubble);
|
203 |
+
convo.scrollTop = convo.scrollHeight;
|
204 |
+
}
|
205 |
+
});
|
206 |
+
|
207 |
+
// Drag & drop
|
208 |
+
convo.addEventListener("dragover", (e) => {
|
209 |
+
e.preventDefault();
|
210 |
+
convo.classList.add("drag-over");
|
211 |
+
});
|
212 |
+
|
213 |
+
convo.addEventListener("dragleave", () => {
|
214 |
+
convo.classList.remove("drag-over");
|
215 |
+
});
|
216 |
+
|
217 |
+
convo.addEventListener("drop", (e) => {
|
218 |
+
e.preventDefault();
|
219 |
+
convo.classList.remove("drag-over");
|
220 |
+
|
221 |
+
const file = e.dataTransfer.files[0];
|
222 |
if (file) {
|
223 |
selectedFile = file;
|
224 |
|
|
|
225 |
if (filePreviewBubble) filePreviewBubble.remove();
|
226 |
|
227 |
filePreviewBubble = document.createElement("div");
|
|
|
232 |
}
|
233 |
});
|
234 |
|
235 |
+
// Reset chat
|
236 |
+
resetBtn.addEventListener("click", () => {
|
237 |
+
convo.innerHTML = "";
|
238 |
+
selectedFile = null;
|
239 |
+
filePreviewBubble = null;
|
240 |
+
input.value = "";
|
241 |
+
});
|
242 |
+
|
243 |
function createMessageBubble(text, sender = "You", audioSrc = null, fileName = null) {
|
244 |
const bubble = document.createElement("div");
|
245 |
bubble.className = `bubble ${sender === "You" ? "right" : "left"}`;
|
|
|
252 |
message.className = "text";
|
253 |
message.style.whiteSpace = "pre-wrap";
|
254 |
|
|
|
255 |
if (sender === "You") {
|
256 |
const fileLine = fileName ? `π Selected file: ${fileName}\n` : "";
|
257 |
message.innerText = `${fileLine}β ${text}`;
|
|
|
264 |
msgSpan.innerText = text;
|
265 |
message.appendChild(msgSpan);
|
266 |
|
|
|
267 |
if (audioSrc) {
|
268 |
const icon = document.createElement("i");
|
269 |
icon.className = "fa-solid fa-volume-high audio-toggle";
|
|
|
276 |
|
277 |
icon.addEventListener("click", () => {
|
278 |
if (audio.muted) {
|
279 |
+
audio.currentTime = 0;
|
280 |
audio.muted = false;
|
281 |
audio.play();
|
282 |
icon.classList.replace("fa-volume-xmark", "fa-volume-high");
|
|
|
300 |
}
|
301 |
|
302 |
sendBtn.addEventListener("click", async () => {
|
303 |
+
input.value = "";
|
304 |
const question = input.value.trim();
|
305 |
if (!question) return;
|
306 |
|
|
|
314 |
filePreviewBubble = null;
|
315 |
}
|
316 |
|
|
|
317 |
createMessageBubble(question, "You", null, selectedFile.name);
|
|
|
|
|
318 |
const thinkingBubble = createMessageBubble("π§ Let me think...", "Chris");
|
319 |
|
320 |
+
// Rewrap file if needed (for reuse in FormData)
|
321 |
+
const wrappedFile = new File([selectedFile], selectedFile.name, {
|
322 |
+
type: selectedFile.type,
|
323 |
+
});
|
324 |
+
|
325 |
const formData = new FormData();
|
326 |
formData.append("question", question);
|
327 |
+
formData.append("file", wrappedFile);
|
328 |
|
329 |
try {
|
330 |
const response = await fetch("/predict", {
|
|
|
339 |
const message = thinkingBubble.querySelector(".text");
|
340 |
message.innerText = answerText;
|
341 |
|
|
|
342 |
if (audioSrc) {
|
343 |
const icon = document.createElement("i");
|
344 |
icon.className = "fa-solid fa-volume-high audio-toggle";
|
|
|
374 |
message.innerText = "β οΈ Chris had trouble responding.";
|
375 |
}
|
376 |
|
377 |
+
// selectedFile is NOT cleared, so multiple questions work β
|
|
|
378 |
});
|
379 |
});
|