chenguittiMaroua commited on
Commit
0f53820
·
verified ·
1 Parent(s): a2a079f

Update static/test.js

Browse files
Files changed (1) hide show
  1. static/test.js +334 -255
static/test.js CHANGED
@@ -213,7 +213,6 @@ function showSection(sectionId) {
213
 
214
 
215
  // Function to show the selected section and hide the others
216
- // Main navigation and shared utility functions
217
  function showSection(sectionId) {
218
  // Show the selected section (in case it was hidden)
219
  const activeSection = document.getElementById(sectionId);
@@ -227,7 +226,6 @@ function showSection(sectionId) {
227
  }
228
  }
229
 
230
-
231
  function showCards() {
232
  // Show cards section
233
  document.querySelector('.cards').style.display = 'grid'; // or 'flex' depending on your layout
@@ -242,8 +240,6 @@ function showCards() {
242
  window.scrollTo({ top: 0, behavior: 'smooth' });
243
  }
244
 
245
-
246
-
247
  document.addEventListener('DOMContentLoaded', () => {
248
  // Set up card click handlers
249
  document.querySelectorAll('.card').forEach(card => {
@@ -258,11 +254,62 @@ document.addEventListener('DOMContentLoaded', () => {
258
  sections.forEach(section => {
259
  section.style.display = 'none';
260
  });
261
- });
262
 
263
  // Show first section by default
264
  showSection('document-image-analysis');
265
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  // Document Analysis Section Setup
267
  const summarizeDropArea = document.getElementById('upload-area');
268
  const summarizeFileInput = document.getElementById('file-input');
@@ -273,17 +320,20 @@ document.addEventListener('DOMContentLoaded', () => {
273
  const summarizeError = document.getElementById('error-message');
274
  const languageSelect = document.getElementById('language-select');
275
 
 
 
 
276
  // Set up drag and drop for file upload
277
  ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
278
  summarizeDropArea.addEventListener(eventName, preventDefaults, false);
279
  });
280
 
281
  ['dragenter', 'dragover'].forEach(eventName => {
282
- summarizeDropArea.addEventListener(eventName, highlight, false);
283
  });
284
 
285
  ['dragleave', 'drop'].forEach(eventName => {
286
- summarizeDropArea.addEventListener(eventName, unhighlight, false);
287
  });
288
 
289
  summarizeDropArea.addEventListener('drop', handleDrop, false);
@@ -291,6 +341,53 @@ document.addEventListener('DOMContentLoaded', () => {
291
  summarizeFileInput.addEventListener('change', handleFileSelect);
292
  textInput.addEventListener('input', validateInputs);
293
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  // Summarize button click handler
295
  summarizeBtn.addEventListener('click', async () => {
296
  const file = summarizeFileInput.files[0];
@@ -303,17 +400,13 @@ document.addEventListener('DOMContentLoaded', () => {
303
  }
304
 
305
  try {
306
- // Show loading state
307
- setLoading(true);
308
  hideError(summarizeError);
309
  summarizeResult.textContent = '';
310
 
311
  const formData = new FormData();
312
- if (file) {
313
- formData.append('file', file);
314
- } else {
315
- formData.append('text', text);
316
- }
317
  formData.append('language', language);
318
 
319
  const response = await fetch('/summarize', {
@@ -332,45 +425,75 @@ document.addEventListener('DOMContentLoaded', () => {
332
  showError(summarizeError, error.message);
333
  console.error("Summarization error:", error);
334
  } finally {
335
- setLoading(false);
336
  }
337
  });
338
 
339
- // Helper functions
340
- function preventDefaults(e) {
341
- e.preventDefault();
342
- e.stopPropagation();
343
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
 
345
- function highlight() {
346
- summarizeDropArea.classList.add('highlight');
 
 
 
 
 
347
  }
348
 
349
- function unhighlight() {
350
- summarizeDropArea.classList.remove('highlight');
 
351
  }
352
 
353
- function handleDrop(e) {
354
  const dt = e.dataTransfer;
355
  const files = dt.files;
356
- handleFiles(files);
357
  }
358
 
359
- function handleFileSelect(e) {
360
  const files = e.target.files;
361
  if (files.length) {
362
- handleFiles(files);
363
  }
364
  }
365
 
366
- function handleFiles(files) {
367
  const file = files[0];
368
- if (!isValidFileType(file)) {
369
- showError(summarizeError, "Unsupported file type. Please upload PDF, DOCX, TXT, or image files.");
 
 
 
 
 
 
 
370
  return;
371
  }
372
 
373
- summarizePreview.innerHTML = `
374
  <div class="file-info">
375
  <span class="file-icon">${getFileIcon(file)}</span>
376
  <div>
@@ -379,263 +502,219 @@ document.addEventListener('DOMContentLoaded', () => {
379
  </div>
380
  </div>
381
  `;
382
- validateInputs();
383
  }
384
 
385
- function validateInputs() {
386
- const hasFile = summarizeFileInput.files.length > 0;
387
- const hasText = textInput.value.trim() !== '';
388
- summarizeBtn.disabled = !(hasFile || hasText);
389
  }
390
 
391
- function isValidFileType(file) {
392
- const validTypes = [
393
- 'application/pdf',
394
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
395
- 'text/plain',
396
- 'image/jpeg',
397
- 'image/png'
398
- ];
399
- return validTypes.includes(file.type) ||
400
- file.name.endsWith('.pdf') ||
401
- file.name.endsWith('.docx') ||
402
- file.name.endsWith('.txt');
403
- }
404
 
405
- function getFileIcon(file) {
406
- if (file.type.startsWith('image/')) return '🖼️';
407
- if (file.type === 'application/pdf') return '📄';
408
- if (file.type.includes('wordprocessingml')) return '📝';
409
- return '📁';
410
- }
411
 
412
- function formatFileSize(bytes) {
413
- if (bytes === 0) return '0 Bytes';
414
- const k = 1024;
415
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
416
- const i = Math.floor(Math.log(bytes) / Math.log(k));
417
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
418
- }
 
419
 
420
- function setLoading(isLoading) {
421
- summarizeBtn.disabled = isLoading;
422
- const btnText = summarizeBtn.querySelector('span');
423
- btnText.textContent = isLoading ? 'Processing...' : 'Summarize Document';
424
- const spinner = summarizeBtn.querySelector('.spinner');
425
- spinner.classList.toggle('hidden', !isLoading);
426
- }
 
 
427
 
428
- function showError(element, message) {
429
- element.textContent = message;
430
- element.classList.remove('hidden');
 
 
 
 
 
431
  }
432
 
433
- function hideError() {
434
- summarizeError.classList.add('hidden');
435
  }
436
- });
437
-
438
-
439
- // Add this after your existing summarization code, inside the DOMContentLoaded event listener
440
- // Add this after your existing summarization code, inside the DOMContentLoaded event listener
441
-
442
- // Question Answering Section Setup
443
- const qaDropArea = document.getElementById('qa-upload-area');
444
- const qaFileInput = document.getElementById('qa-file-input');
445
- const qaPreview = document.getElementById('qa-file-preview');
446
- const qaQuestionInput = document.getElementById('qa-question');
447
- const qaSubmitBtn = document.getElementById('qa-submit-btn');
448
- const qaResult = document.getElementById('qa-answer');
449
- const qaError = document.getElementById('qa-error-message');
450
- const qaLanguageSelect = document.getElementById('qa-language');
451
-
452
- // Define QA-specific versions of the drag-drop functions
453
- function qaPreventDefaults(e) {
454
- e.preventDefault();
455
- e.stopPropagation();
456
- }
457
-
458
- function qaHighlight() {
459
- qaDropArea.classList.add('highlight');
460
- }
461
-
462
- function qaUnhighlight() {
463
- qaDropArea.classList.remove('highlight');
464
- }
465
-
466
- // Debug: Verify elements exist
467
- console.log('QA Elements:', {
468
- qaDropArea, qaFileInput, qaPreview, qaQuestionInput,
469
- qaSubmitBtn, qaResult, qaError, qaLanguageSelect
470
- });
471
-
472
- // Setup event listeners
473
- if (qaDropArea && qaFileInput) {
474
- ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
475
- qaDropArea.addEventListener(eventName, qaPreventDefaults, false);
476
- });
477
-
478
- ['dragenter', 'dragover'].forEach(eventName => {
479
- qaDropArea.addEventListener(eventName, qaHighlight, false);
480
- });
481
 
482
- ['dragleave', 'drop'].forEach(eventName => {
483
- qaDropArea.addEventListener(eventName, qaUnhighlight, false);
484
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
485
 
486
- qaDropArea.addEventListener('drop', handleQADrop, false);
487
- qaDropArea.addEventListener('click', () => qaFileInput.click());
488
- qaFileInput.addEventListener('change', handleQAFileSelect);
489
- }
490
 
491
- if (qaQuestionInput && qaSubmitBtn) {
492
- qaQuestionInput.addEventListener('input', validateQAInputs);
493
- qaSubmitBtn.addEventListener('click', handleQASubmit);
494
- }
495
 
496
- function handleQASubmit() {
497
- console.log('Submit button clicked!');
498
-
499
- const file = qaFileInput.files[0];
500
- const question = qaQuestionInput.value.trim();
501
- const language = qaLanguageSelect.value;
502
-
503
- console.log('Submission data:', { file, question, language });
504
-
505
- if (!file) {
506
- showError(qaError, "Please upload a document first");
507
- return;
508
  }
509
 
510
- if (!question) {
511
- showError(qaError, "Please enter your question");
512
- return;
513
  }
514
 
515
- submitQARequest(file, question, language);
516
- }
517
-
518
- async function submitQARequest(file, question, language) {
519
- try {
520
- setQALoading(true);
521
- hideError(qaError);
522
-
523
- const formData = new FormData();
524
- formData.append('file', file);
525
- formData.append('question', question);
526
- formData.append('language', language);
527
-
528
- console.log('Sending request to /qa...');
529
- const response = await fetch('/qa', {
530
- method: 'POST',
531
- body: formData
532
- });
533
-
534
- console.log('Response status:', response.status);
535
-
536
- if (!response.ok) {
537
- const error = await response.json();
538
- throw new Error(error.detail || "Failed to get answer");
539
- }
540
-
541
- const result = await response.json();
542
- console.log('API Response:', result);
543
-
544
- displayQAResult(result);
545
- } catch (error) {
546
- console.error("QA Error:", error);
547
- showError(qaError, error.message);
548
- } finally {
549
- setQALoading(false);
550
  }
551
- }
552
-
553
- // QA-specific helper functions
554
- function handleQADrop(e) {
555
- const dt = e.dataTransfer;
556
- const files = dt.files;
557
- handleQAFiles(files);
558
- }
559
 
560
- function handleQAFileSelect(e) {
561
- const files = e.target.files;
562
- if (files.length) {
563
- handleQAFiles(files);
564
  }
565
- }
566
 
567
- function handleQAFiles(files) {
568
- const file = files[0];
569
- if (!isValidFileType(file)) {
570
- showError(qaError, "Unsupported file type. Please upload PDF, DOCX, or TXT files.");
571
- return;
572
  }
573
 
574
- qaPreview.innerHTML = `
575
- <div class="file-info">
576
- <span class="file-icon">${getFileIcon(file)}</span>
577
- <div>
578
- <strong>${file.name}</strong>
579
- <span>${formatFileSize(file.size)}</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  </div>
581
- </div>
582
- `;
583
- validateQAInputs();
584
- }
585
 
586
- function validateQAInputs() {
587
- const hasFile = qaFileInput.files.length > 0;
588
- const hasQuestion = qaQuestionInput.value.trim() !== '';
589
- qaSubmitBtn.disabled = !(hasFile && hasQuestion);
590
- }
 
 
 
 
591
 
592
- function setQALoading(isLoading) {
593
- qaSubmitBtn.disabled = isLoading;
594
- const btnText = qaSubmitBtn.querySelector('span');
595
- btnText.textContent = isLoading ? 'Processing...' : 'Get Answer';
596
- const spinner = qaSubmitBtn.querySelector('.spinner');
597
- spinner.classList.toggle('hidden', !isLoading);
598
- }
599
 
600
- function displayQAResult(result) {
601
- qaResult.textContent = result.answer;
602
- // Add any additional result display logic here
603
- }
604
 
605
- function showError(element, message) {
606
- element.textContent = message;
607
- element.classList.remove('hidden');
608
- }
609
 
610
- function hideError(element) {
611
- element.classList.add('hidden');
612
- }
 
613
 
614
- function isValidFileType(file) {
615
- const validTypes = [
616
- 'application/pdf',
617
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
618
- 'text/plain'
619
- ];
620
- return validTypes.includes(file.type) ||
621
- file.name.endsWith('.pdf') ||
622
- file.name.endsWith('.docx') ||
623
- file.name.endsWith('.txt');
624
- }
625
 
626
- function getFileIcon(file) {
627
- if (file.type === 'application/pdf') return '📄';
628
- if (file.type.includes('wordprocessingml')) return '📝';
629
- return '📁';
630
- }
 
 
 
 
 
 
 
631
 
632
- function formatFileSize(bytes) {
633
- if (bytes === 0) return '0 Bytes';
634
- const k = 1024;
635
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
636
- const i = Math.floor(Math.log(bytes) / Math.log(k));
637
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
638
- }
639
 
 
 
 
640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
641
 
 
213
 
214
 
215
  // Function to show the selected section and hide the others
 
216
  function showSection(sectionId) {
217
  // Show the selected section (in case it was hidden)
218
  const activeSection = document.getElementById(sectionId);
 
226
  }
227
  }
228
 
 
229
  function showCards() {
230
  // Show cards section
231
  document.querySelector('.cards').style.display = 'grid'; // or 'flex' depending on your layout
 
240
  window.scrollTo({ top: 0, behavior: 'smooth' });
241
  }
242
 
 
 
243
  document.addEventListener('DOMContentLoaded', () => {
244
  // Set up card click handlers
245
  document.querySelectorAll('.card').forEach(card => {
 
254
  sections.forEach(section => {
255
  section.style.display = 'none';
256
  });
 
257
 
258
  // Show first section by default
259
  showSection('document-image-analysis');
260
 
261
+ // Helper functions
262
+ function preventDefaults(e) {
263
+ e.preventDefault();
264
+ e.stopPropagation();
265
+ }
266
+
267
+ function highlight(element) {
268
+ element.classList.add('highlight');
269
+ }
270
+
271
+ function unhighlight(element) {
272
+ element.classList.remove('highlight');
273
+ }
274
+
275
+ function isValidFileType(file, types, extensions) {
276
+ return types.includes(file.type) || extensions.some(ext => file.name.endsWith(ext));
277
+ }
278
+
279
+ function getFileIcon(file) {
280
+ if (file.type.startsWith('image/')) return '🖼️';
281
+ if (file.type === 'application/pdf') return '📄';
282
+ if (file.type.includes('wordprocessingml')) return '📝';
283
+ if (file.type.includes('spreadsheetml') || file.type === 'text/csv') return '📊';
284
+ return '📁';
285
+ }
286
+
287
+ function formatFileSize(bytes) {
288
+ if (bytes === 0) return '0 Bytes';
289
+ const k = 1024;
290
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
291
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
292
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
293
+ }
294
+
295
+ function showError(element, message) {
296
+ element.textContent = message;
297
+ element.classList.remove('hidden');
298
+ }
299
+
300
+ function hideError(element) {
301
+ element.classList.add('hidden');
302
+ }
303
+
304
+ function setLoading(button, isLoading, loadingText = 'Processing...') {
305
+ const btnText = button.querySelector('span:not(.spinner)');
306
+ const spinner = button.querySelector('.spinner');
307
+
308
+ button.disabled = isLoading;
309
+ btnText.textContent = isLoading ? loadingText : btnText.dataset.defaultText;
310
+ spinner.classList.toggle('hidden', !isLoading);
311
+ }
312
+
313
  // Document Analysis Section Setup
314
  const summarizeDropArea = document.getElementById('upload-area');
315
  const summarizeFileInput = document.getElementById('file-input');
 
320
  const summarizeError = document.getElementById('error-message');
321
  const languageSelect = document.getElementById('language-select');
322
 
323
+ // Store default button text
324
+ summarizeBtn.querySelector('span').dataset.defaultText = 'Summarize Document';
325
+
326
  // Set up drag and drop for file upload
327
  ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
328
  summarizeDropArea.addEventListener(eventName, preventDefaults, false);
329
  });
330
 
331
  ['dragenter', 'dragover'].forEach(eventName => {
332
+ summarizeDropArea.addEventListener(eventName, () => highlight(summarizeDropArea), false);
333
  });
334
 
335
  ['dragleave', 'drop'].forEach(eventName => {
336
+ summarizeDropArea.addEventListener(eventName, () => unhighlight(summarizeDropArea), false);
337
  });
338
 
339
  summarizeDropArea.addEventListener('drop', handleDrop, false);
 
341
  summarizeFileInput.addEventListener('change', handleFileSelect);
342
  textInput.addEventListener('input', validateInputs);
343
 
344
+ function handleDrop(e) {
345
+ const dt = e.dataTransfer;
346
+ const files = dt.files;
347
+ handleFiles(files);
348
+ }
349
+
350
+ function handleFileSelect(e) {
351
+ const files = e.target.files;
352
+ if (files.length) {
353
+ handleFiles(files);
354
+ }
355
+ }
356
+
357
+ function handleFiles(files) {
358
+ const file = files[0];
359
+ const validTypes = [
360
+ 'application/pdf',
361
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
362
+ 'text/plain',
363
+ 'image/jpeg',
364
+ 'image/png'
365
+ ];
366
+ const validExtensions = ['.pdf', '.docx', '.txt'];
367
+
368
+ if (!isValidFileType(file, validTypes, validExtensions)) {
369
+ showError(summarizeError, "Unsupported file type. Please upload PDF, DOCX, TXT, or image files.");
370
+ return;
371
+ }
372
+
373
+ summarizePreview.innerHTML = `
374
+ <div class="file-info">
375
+ <span class="file-icon">${getFileIcon(file)}</span>
376
+ <div>
377
+ <strong>${file.name}</strong>
378
+ <span>${formatFileSize(file.size)}</span>
379
+ </div>
380
+ </div>
381
+ `;
382
+ validateInputs();
383
+ }
384
+
385
+ function validateInputs() {
386
+ const hasFile = summarizeFileInput.files.length > 0;
387
+ const hasText = textInput.value.trim() !== '';
388
+ summarizeBtn.disabled = !(hasFile || hasText);
389
+ }
390
+
391
  // Summarize button click handler
392
  summarizeBtn.addEventListener('click', async () => {
393
  const file = summarizeFileInput.files[0];
 
400
  }
401
 
402
  try {
403
+ setLoading(summarizeBtn, true);
 
404
  hideError(summarizeError);
405
  summarizeResult.textContent = '';
406
 
407
  const formData = new FormData();
408
+ if (file) formData.append('file', file);
409
+ if (text) formData.append('text', text);
 
 
 
410
  formData.append('language', language);
411
 
412
  const response = await fetch('/summarize', {
 
425
  showError(summarizeError, error.message);
426
  console.error("Summarization error:", error);
427
  } finally {
428
+ setLoading(summarizeBtn, false);
429
  }
430
  });
431
 
432
+ // Question Answering Section Setup
433
+ const qaDropArea = document.getElementById('qa-upload-area');
434
+ const qaFileInput = document.getElementById('qa-file-input');
435
+ const qaPreview = document.getElementById('qa-file-preview');
436
+ const qaQuestionInput = document.getElementById('qa-question');
437
+ const qaSubmitBtn = document.getElementById('qa-submit-btn');
438
+ const qaResult = document.getElementById('qa-answer');
439
+ const qaError = document.getElementById('qa-error-message');
440
+ const qaLanguageSelect = document.getElementById('qa-language');
441
+
442
+ // Store default button text
443
+ qaSubmitBtn.querySelector('span').dataset.defaultText = 'Get Answer';
444
+
445
+ // Setup event listeners
446
+ if (qaDropArea && qaFileInput) {
447
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
448
+ qaDropArea.addEventListener(eventName, preventDefaults, false);
449
+ });
450
+
451
+ ['dragenter', 'dragover'].forEach(eventName => {
452
+ qaDropArea.addEventListener(eventName, () => highlight(qaDropArea), false);
453
+ });
454
 
455
+ ['dragleave', 'drop'].forEach(eventName => {
456
+ qaDropArea.addEventListener(eventName, () => unhighlight(qaDropArea), false);
457
+ });
458
+
459
+ qaDropArea.addEventListener('drop', handleQADrop, false);
460
+ qaDropArea.addEventListener('click', () => qaFileInput.click());
461
+ qaFileInput.addEventListener('change', handleQAFileSelect);
462
  }
463
 
464
+ if (qaQuestionInput && qaSubmitBtn) {
465
+ qaQuestionInput.addEventListener('input', validateQAInputs);
466
+ qaSubmitBtn.addEventListener('click', handleQASubmit);
467
  }
468
 
469
+ function handleQADrop(e) {
470
  const dt = e.dataTransfer;
471
  const files = dt.files;
472
+ handleQAFiles(files);
473
  }
474
 
475
+ function handleQAFileSelect(e) {
476
  const files = e.target.files;
477
  if (files.length) {
478
+ handleQAFiles(files);
479
  }
480
  }
481
 
482
+ function handleQAFiles(files) {
483
  const file = files[0];
484
+ const validTypes = [
485
+ 'application/pdf',
486
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
487
+ 'text/plain'
488
+ ];
489
+ const validExtensions = ['.pdf', '.docx', '.txt'];
490
+
491
+ if (!isValidFileType(file, validTypes, validExtensions)) {
492
+ showError(qaError, "Unsupported file type. Please upload PDF, DOCX, or TXT files.");
493
  return;
494
  }
495
 
496
+ qaPreview.innerHTML = `
497
  <div class="file-info">
498
  <span class="file-icon">${getFileIcon(file)}</span>
499
  <div>
 
502
  </div>
503
  </div>
504
  `;
505
+ validateQAInputs();
506
  }
507
 
508
+ function validateQAInputs() {
509
+ const hasFile = qaFileInput.files.length > 0;
510
+ const hasQuestion = qaQuestionInput.value.trim() !== '';
511
+ qaSubmitBtn.disabled = !(hasFile && hasQuestion);
512
  }
513
 
514
+ async function handleQASubmit() {
515
+ const file = qaFileInput.files[0];
516
+ const question = qaQuestionInput.value.trim();
517
+ const language = qaLanguageSelect.value;
518
+
519
+ if (!file) {
520
+ showError(qaError, "Please upload a document first");
521
+ return;
522
+ }
 
 
 
 
523
 
524
+ if (!question) {
525
+ showError(qaError, "Please enter your question");
526
+ return;
527
+ }
 
 
528
 
529
+ try {
530
+ setLoading(qaSubmitBtn, true);
531
+ hideError(qaError);
532
+
533
+ const formData = new FormData();
534
+ formData.append('file', file);
535
+ formData.append('question', question);
536
+ formData.append('language', language);
537
 
538
+ const response = await fetch('/qa', {
539
+ method: 'POST',
540
+ body: formData
541
+ });
542
+
543
+ if (!response.ok) {
544
+ const error = await response.json();
545
+ throw new Error(error.detail || "Failed to get answer");
546
+ }
547
 
548
+ const result = await response.json();
549
+ displayQAResult(result);
550
+ } catch (error) {
551
+ showError(qaError, error.message);
552
+ console.error("QA Error:", error);
553
+ } finally {
554
+ setLoading(qaSubmitBtn, false);
555
+ }
556
  }
557
 
558
+ function displayQAResult(result) {
559
+ qaResult.textContent = result.answer;
560
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
 
562
+ // Data Visualization Section Setup
563
+ const dataDropArea = document.getElementById('data-upload-area');
564
+ const dataFileInput = document.getElementById('data-file-input');
565
+ const dataPreview = document.getElementById('data-file-preview');
566
+ const visualizeBtn = document.getElementById('visualize-btn');
567
+ const visualizationPrompt = document.getElementById('visualization-prompt');
568
+ const chartTypeSelect = document.getElementById('chart-type-select');
569
+ const visualizationResult = document.getElementById('visualization-results');
570
+ const visualizationError = document.getElementById('visualization-error');
571
+ const visualizationImage = document.getElementById('generated-visualization');
572
+ const pythonCodeOutput = document.getElementById('python-code-output');
573
+ const dataPreviewContainer = document.getElementById('data-preview-container');
574
+ const copyCodeBtn = document.getElementById('copy-code-btn');
575
+
576
+ // Store default button text
577
+ visualizeBtn.querySelector('span').dataset.defaultText = 'Generate Visualization';
578
+
579
+ // Setup drag and drop for data visualization
580
+ if (dataDropArea && dataFileInput) {
581
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
582
+ dataDropArea.addEventListener(eventName, preventDefaults, false);
583
+ });
584
 
585
+ ['dragenter', 'dragover'].forEach(eventName => {
586
+ dataDropArea.addEventListener(eventName, () => highlight(dataDropArea), false);
587
+ });
 
588
 
589
+ ['dragleave', 'drop'].forEach(eventName => {
590
+ dataDropArea.addEventListener(eventName, () => unhighlight(dataDropArea), false);
591
+ });
 
592
 
593
+ dataDropArea.addEventListener('drop', handleDataDrop, false);
594
+ dataDropArea.addEventListener('click', () => dataFileInput.click());
595
+ dataFileInput.addEventListener('change', handleDataFileSelect);
 
 
 
 
 
 
 
 
 
596
  }
597
 
598
+ if (visualizeBtn) {
599
+ visualizeBtn.addEventListener('click', handleVisualizationSubmit);
 
600
  }
601
 
602
+ if (copyCodeBtn) {
603
+ copyCodeBtn.addEventListener('click', copyPythonCode);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
  }
 
 
 
 
 
 
 
 
605
 
606
+ function handleDataDrop(e) {
607
+ const dt = e.dataTransfer;
608
+ const files = dt.files;
609
+ handleDataFiles(files);
610
  }
 
611
 
612
+ function handleDataFileSelect(e) {
613
+ const files = e.target.files;
614
+ if (files.length) {
615
+ handleDataFiles(files);
616
+ }
617
  }
618
 
619
+ function handleDataFiles(files) {
620
+ const file = files[0];
621
+ const validTypes = [
622
+ 'application/vnd.ms-excel',
623
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
624
+ 'text/csv'
625
+ ];
626
+ const validExtensions = ['.xlsx', '.xls', '.csv'];
627
+
628
+ if (!isValidFileType(file, validTypes, validExtensions)) {
629
+ showVisualizationError("Unsupported file type. Please upload Excel or CSV files.");
630
+ return;
631
+ }
632
+
633
+ dataPreview.innerHTML = `
634
+ <div class="file-info">
635
+ <span class="file-icon">${getFileIcon(file)}</span>
636
+ <div>
637
+ <strong>${file.name}</strong>
638
+ <span>${formatFileSize(file.size)}</span>
639
+ </div>
640
  </div>
641
+ `;
642
+ }
 
 
643
 
644
+ async function handleVisualizationSubmit() {
645
+ const file = dataFileInput.files[0];
646
+ const prompt = visualizationPrompt.value.trim();
647
+ const chartType = chartTypeSelect.value;
648
+
649
+ if (!file) {
650
+ showVisualizationError("Please upload a file first");
651
+ return;
652
+ }
653
 
654
+ try {
655
+ setLoading(visualizeBtn, true, 'Generating...');
656
+ hideVisualizationError();
657
+ visualizationResult.classList.add('hidden');
 
 
 
658
 
659
+ const formData = new FormData();
660
+ formData.append('file', file);
661
+ formData.append('request', prompt);
662
+ formData.append('chart_type', chartType);
663
 
664
+ const response = await fetch('/generate-visualization', {
665
+ method: 'POST',
666
+ body: formData
667
+ });
668
 
669
+ if (!response.ok) {
670
+ const error = await response.json();
671
+ throw new Error(error.detail || "Failed to generate visualization");
672
+ }
673
 
674
+ const result = await response.json();
675
+ displayVisualizationResult(result);
676
+ } catch (error) {
677
+ showVisualizationError(error.message);
678
+ console.error("Visualization error:", error);
679
+ } finally {
680
+ setLoading(visualizeBtn, false);
681
+ }
682
+ }
 
 
683
 
684
+ function displayVisualizationResult(result) {
685
+ visualizationImage.src = result.image_url;
686
+ pythonCodeOutput.textContent = result.python_code;
687
+
688
+ // Display data preview
689
+ dataPreviewContainer.innerHTML = `
690
+ <p>Columns: ${result.columns.join(', ')}</p>
691
+ <small>Note: Only showing first few rows of data</small>
692
+ `;
693
+
694
+ visualizationResult.classList.remove('hidden');
695
+ }
696
 
697
+ function showVisualizationError(message) {
698
+ visualizationError.textContent = message;
699
+ visualizationError.classList.remove('hidden');
700
+ }
 
 
 
701
 
702
+ function hideVisualizationError() {
703
+ visualizationError.classList.add('hidden');
704
+ }
705
 
706
+ function copyPythonCode() {
707
+ const code = pythonCodeOutput.textContent;
708
+ navigator.clipboard.writeText(code)
709
+ .then(() => {
710
+ copyCodeBtn.textContent = 'Copied!';
711
+ setTimeout(() => {
712
+ copyCodeBtn.textContent = 'Copy Code';
713
+ }, 2000);
714
+ })
715
+ .catch(err => {
716
+ console.error('Failed to copy code:', err);
717
+ });
718
+ }
719
+ });
720