sloneckity commited on
Commit
da0b374
·
1 Parent(s): 44d1643

Fix Safari compatibility issues: CSV download and image navigation

Browse files
Files changed (2) hide show
  1. app.py +6 -0
  2. static/script.js +52 -32
app.py CHANGED
@@ -179,6 +179,12 @@ def download_file(job_id, filename):
179
 
180
  if safe_filename.lower() == "results.csv":
181
  mime_type = 'text/csv'
 
 
 
 
 
 
182
 
183
  return send_file(str(file_path), mimetype=mime_type)
184
  except Exception as e:
 
179
 
180
  if safe_filename.lower() == "results.csv":
181
  mime_type = 'text/csv'
182
+ return send_file(
183
+ str(file_path),
184
+ mimetype=mime_type,
185
+ as_attachment=True,
186
+ download_name=safe_filename
187
+ )
188
 
189
  return send_file(str(file_path), mimetype=mime_type)
190
  except Exception as e:
static/script.js CHANGED
@@ -611,38 +611,50 @@ document.addEventListener('DOMContentLoaded', () => {
611
 
612
  if (result.annotated_filename) {
613
  const imageUrl = `/results/${currentJobId}/${result.annotated_filename}`;
614
- previewImage.src = imageUrl;
615
- previewImage.alt = result.filename;
616
 
617
- // Update image info with the new function
618
- updateImageInfo();
619
-
620
- // Enable zoom controls
621
- zoomInBtn.disabled = false;
622
- zoomOutBtn.disabled = false;
 
 
 
 
 
 
623
 
624
- // Calculate which page this image should be on
625
- const targetPage = Math.floor(index / RESULTS_PER_PAGE) + 1;
626
-
627
- // If we're not on the correct page, switch to it
628
- if (currentPage !== targetPage) {
629
- currentPage = targetPage;
630
- displayResultsPage(currentPage);
631
- }
632
 
633
- // Remove selection from all rows
634
- document.querySelectorAll('.results-table tr').forEach(r => r.classList.remove('selected'));
635
-
636
- // Find and highlight the corresponding row
637
- const rows = resultsTableBody.querySelectorAll('tr');
638
- rows.forEach(row => {
639
- if (parseInt(row.dataset.originalIndex) === index) {
640
- row.classList.add('selected');
641
  }
642
- });
 
 
 
643
 
644
- // Reset panning when a new image is displayed
645
- resetPanZoom();
 
 
 
 
 
646
  } else {
647
  clearPreview();
648
  }
@@ -686,16 +698,24 @@ document.addEventListener('DOMContentLoaded', () => {
686
  updatePanCursorState();
687
  }
688
 
689
- // Image Navigation
690
- prevBtn.addEventListener('click', () => {
691
- if (currentImageIndex > 0) {
 
 
 
 
692
  displayImage(currentImageIndex - 1);
 
693
  }
694
  });
695
 
696
- nextBtn.addEventListener('click', () => {
697
- if (currentImageIndex < currentResults.length - 1) {
 
 
698
  displayImage(currentImageIndex + 1);
 
699
  }
700
  });
701
 
 
611
 
612
  if (result.annotated_filename) {
613
  const imageUrl = `/results/${currentJobId}/${result.annotated_filename}`;
 
 
614
 
615
+ // Create a new image object to handle loading
616
+ const tempImage = new Image();
617
+ tempImage.onload = function() {
618
+ previewImage.src = imageUrl;
619
+ previewImage.alt = result.filename;
620
+
621
+ // Update image info with the new function
622
+ updateImageInfo();
623
+
624
+ // Enable zoom controls
625
+ zoomInBtn.disabled = false;
626
+ zoomOutBtn.disabled = false;
627
 
628
+ // Calculate which page this image should be on
629
+ const targetPage = Math.floor(index / RESULTS_PER_PAGE) + 1;
630
+
631
+ // If we're not on the correct page, switch to it
632
+ if (currentPage !== targetPage) {
633
+ currentPage = targetPage;
634
+ displayResultsPage(currentPage);
635
+ }
636
 
637
+ // Remove selection from all rows
638
+ document.querySelectorAll('.results-table tr').forEach(r => r.classList.remove('selected'));
639
+
640
+ // Find and highlight the corresponding row
641
+ const rows = Array.from(resultsTableBody.querySelectorAll('tr'));
642
+ const targetRow = rows.find(row => parseInt(row.dataset.originalIndex, 10) === index);
643
+ if (targetRow) {
644
+ targetRow.classList.add('selected');
645
  }
646
+
647
+ // Reset panning when a new image is displayed
648
+ resetPanZoom();
649
+ };
650
 
651
+ tempImage.onerror = function() {
652
+ console.error('Failed to load image:', imageUrl);
653
+ clearPreview();
654
+ };
655
+
656
+ // Start loading the image
657
+ tempImage.src = imageUrl;
658
  } else {
659
  clearPreview();
660
  }
 
698
  updatePanCursorState();
699
  }
700
 
701
+ // Image Navigation with debouncing
702
+ let navigationInProgress = false;
703
+
704
+ prevBtn.addEventListener('click', (e) => {
705
+ e.preventDefault();
706
+ if (!navigationInProgress && currentImageIndex > 0) {
707
+ navigationInProgress = true;
708
  displayImage(currentImageIndex - 1);
709
+ setTimeout(() => { navigationInProgress = false; }, 300);
710
  }
711
  });
712
 
713
+ nextBtn.addEventListener('click', (e) => {
714
+ e.preventDefault();
715
+ if (!navigationInProgress && currentImageIndex < currentResults.length - 1) {
716
+ navigationInProgress = true;
717
  displayImage(currentImageIndex + 1);
718
+ setTimeout(() => { navigationInProgress = false; }, 300);
719
  }
720
  });
721