Spaces:
Runtime error
Runtime error
Implement proper batch loading for map to handle all trees
Browse files- Frontend now makes multiple API requests (1000 trees each) to load all trees
- Keeps existing UI batching (50 trees at a time) for smooth rendering
- Works around Supabase 1000-row default limit
- Maintains progress indicators during loading
- Reverted complex database changes in favor of frontend solution
- static/index.html +2 -2
- static/map.html +2 -2
- static/map.js +45 -17
- static/sw.js +1 -1
- version.json +1 -1
static/index.html
CHANGED
|
@@ -947,7 +947,7 @@
|
|
| 947 |
// Force refresh if we detect cached version
|
| 948 |
(function() {
|
| 949 |
const currentVersion = '5.1.1';
|
| 950 |
-
const timestamp = '
|
| 951 |
const lastVersion = sessionStorage.getItem('treetrack_version');
|
| 952 |
const lastTimestamp = sessionStorage.getItem('treetrack_timestamp');
|
| 953 |
|
|
@@ -1193,7 +1193,7 @@
|
|
| 1193 |
</div>
|
| 1194 |
</div>
|
| 1195 |
|
| 1196 |
-
<script type="module" src="/static/js/tree-track-app.js?v=5.1.1&t=
|
| 1197 |
|
| 1198 |
<script>
|
| 1199 |
// Idle-time prefetch of map assets to speed up first navigation
|
|
|
|
| 947 |
// Force refresh if we detect cached version
|
| 948 |
(function() {
|
| 949 |
const currentVersion = '5.1.1';
|
| 950 |
+
const timestamp = '1761506562'; // Cache-busting bump
|
| 951 |
const lastVersion = sessionStorage.getItem('treetrack_version');
|
| 952 |
const lastTimestamp = sessionStorage.getItem('treetrack_timestamp');
|
| 953 |
|
|
|
|
| 1193 |
</div>
|
| 1194 |
</div>
|
| 1195 |
|
| 1196 |
+
<script type="module" src="/static/js/tree-track-app.js?v=5.1.1&t=1761506562"></script>
|
| 1197 |
|
| 1198 |
<script>
|
| 1199 |
// Idle-time prefetch of map assets to speed up first navigation
|
static/map.html
CHANGED
|
@@ -928,7 +928,7 @@
|
|
| 928 |
// Force refresh if we detect cached version
|
| 929 |
(function() {
|
| 930 |
const currentVersion = '5.1.1';
|
| 931 |
-
const timestamp = '
|
| 932 |
const lastVersion = sessionStorage.getItem('treetrack_version');
|
| 933 |
const lastTimestamp = sessionStorage.getItem('treetrack_timestamp');
|
| 934 |
|
|
@@ -1081,7 +1081,7 @@ const timestamp = '1761506303'; // Current timestamp for cache busting
|
|
| 1081 |
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
| 1082 |
<!-- Leaflet MarkerCluster JS for performance and grouping -->
|
| 1083 |
<script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
|
| 1084 |
-
<script src="/static/map.js?v=5.1.1&t=
|
| 1085 |
|
| 1086 |
"default-state": {
|
| 1087 |
gradients: [
|
|
|
|
| 928 |
// Force refresh if we detect cached version
|
| 929 |
(function() {
|
| 930 |
const currentVersion = '5.1.1';
|
| 931 |
+
const timestamp = '1761506562'; // Current timestamp for cache busting
|
| 932 |
const lastVersion = sessionStorage.getItem('treetrack_version');
|
| 933 |
const lastTimestamp = sessionStorage.getItem('treetrack_timestamp');
|
| 934 |
|
|
|
|
| 1081 |
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
| 1082 |
<!-- Leaflet MarkerCluster JS for performance and grouping -->
|
| 1083 |
<script src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
|
| 1084 |
+
<script src="/static/map.js?v=5.1.1&t=1761506562">
|
| 1085 |
|
| 1086 |
"default-state": {
|
| 1087 |
gradients: [
|
static/map.js
CHANGED
|
@@ -590,16 +590,47 @@ class TreeTrackMap {
|
|
| 590 |
console.log('Loading trees...');
|
| 591 |
|
| 592 |
try {
|
| 593 |
-
//
|
| 594 |
-
|
| 595 |
-
|
| 596 |
-
|
|
|
|
| 597 |
|
| 598 |
-
const allTrees = await response.json();
|
| 599 |
-
console.log(`Loaded ${allTrees.length} trees in single query`);
|
| 600 |
-
|
| 601 |
// Clear existing tree markers
|
| 602 |
this.clearTreeMarkers();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 603 |
|
| 604 |
// Filter out specific trees (e.g., ID 18 as requested)
|
| 605 |
const filteredTrees = allTrees.filter(tree => {
|
|
@@ -613,12 +644,12 @@ class TreeTrackMap {
|
|
| 613 |
|
| 614 |
console.log(`Filtered trees: ${filteredTrees.length} (excluded ${allTrees.length - filteredTrees.length})`);
|
| 615 |
|
| 616 |
-
// Add tree markers with progress tracking and batch processing
|
| 617 |
let loadedCount = 0;
|
| 618 |
-
const
|
| 619 |
|
| 620 |
-
for (let i = 0; i < filteredTrees.length; i +=
|
| 621 |
-
const batch = filteredTrees.slice(i, i +
|
| 622 |
|
| 623 |
// Process batch with small delay to prevent UI blocking
|
| 624 |
setTimeout(() => {
|
|
@@ -635,16 +666,13 @@ class TreeTrackMap {
|
|
| 635 |
document.getElementById('treeCount').textContent = `${loadedCount} trees`;
|
| 636 |
|
| 637 |
// If this is the last batch, finalize
|
| 638 |
-
if (i +
|
| 639 |
console.log(`Map loading complete: ${loadedCount} tree markers added`);
|
| 640 |
this.showMessage(`Loaded ${loadedCount} trees successfully`, 'success');
|
| 641 |
}
|
| 642 |
-
}, (i /
|
| 643 |
}
|
| 644 |
|
| 645 |
-
// Final count update
|
| 646 |
-
document.getElementById('treeCount').textContent = `${loadedCount} trees`;
|
| 647 |
-
|
| 648 |
// Auto-zoom to max level and center on trees after loading completes
|
| 649 |
setTimeout(() => {
|
| 650 |
if (loadedCount > 0) {
|
|
@@ -661,7 +689,7 @@ class TreeTrackMap {
|
|
| 661 |
console.log('Map auto-zoomed to maximum detail level');
|
| 662 |
}, 500);
|
| 663 |
}
|
| 664 |
-
}, 2000); // Wait for most batches to complete
|
| 665 |
|
| 666 |
} catch (error) {
|
| 667 |
console.error('Error loading trees:', error);
|
|
|
|
| 590 |
console.log('Loading trees...');
|
| 591 |
|
| 592 |
try {
|
| 593 |
+
// Load trees in batches to work around API limits
|
| 594 |
+
let allTrees = [];
|
| 595 |
+
let offset = 0;
|
| 596 |
+
const batchSize = 1000; // API batch size (Supabase limit)
|
| 597 |
+
let hasMoreTrees = true;
|
| 598 |
|
|
|
|
|
|
|
|
|
|
| 599 |
// Clear existing tree markers
|
| 600 |
this.clearTreeMarkers();
|
| 601 |
+
|
| 602 |
+
console.log('Loading trees in batches to handle large dataset...');
|
| 603 |
+
|
| 604 |
+
while (hasMoreTrees && allTrees.length < 3000) { // Safety limit
|
| 605 |
+
console.log(`Loading batch: offset=${offset}, limit=${batchSize}`);
|
| 606 |
+
|
| 607 |
+
const response = await this.authenticatedFetch(`/api/trees?limit=${batchSize}&offset=${offset}`);
|
| 608 |
+
if (!response) {
|
| 609 |
+
console.error('Failed to fetch batch');
|
| 610 |
+
break;
|
| 611 |
+
}
|
| 612 |
+
|
| 613 |
+
const batchTrees = await response.json();
|
| 614 |
+
console.log(`Loaded batch: ${batchTrees.length} trees`);
|
| 615 |
+
|
| 616 |
+
if (batchTrees.length === 0) {
|
| 617 |
+
hasMoreTrees = false;
|
| 618 |
+
break;
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
+
allTrees = allTrees.concat(batchTrees);
|
| 622 |
+
offset += batchSize;
|
| 623 |
+
|
| 624 |
+
// If we got less than the batch size, we've reached the end
|
| 625 |
+
if (batchTrees.length < batchSize) {
|
| 626 |
+
hasMoreTrees = false;
|
| 627 |
+
}
|
| 628 |
+
|
| 629 |
+
// Update progress
|
| 630 |
+
document.getElementById('treeCount').textContent = `${allTrees.length} trees loaded...`;
|
| 631 |
+
}
|
| 632 |
+
|
| 633 |
+
console.log(`Total trees loaded: ${allTrees.length}`);
|
| 634 |
|
| 635 |
// Filter out specific trees (e.g., ID 18 as requested)
|
| 636 |
const filteredTrees = allTrees.filter(tree => {
|
|
|
|
| 644 |
|
| 645 |
console.log(`Filtered trees: ${filteredTrees.length} (excluded ${allTrees.length - filteredTrees.length})`);
|
| 646 |
|
| 647 |
+
// Add tree markers with progress tracking and UI batch processing
|
| 648 |
let loadedCount = 0;
|
| 649 |
+
const uiBatchSize = 50; // UI processing batch size for smooth rendering
|
| 650 |
|
| 651 |
+
for (let i = 0; i < filteredTrees.length; i += uiBatchSize) {
|
| 652 |
+
const batch = filteredTrees.slice(i, i + uiBatchSize);
|
| 653 |
|
| 654 |
// Process batch with small delay to prevent UI blocking
|
| 655 |
setTimeout(() => {
|
|
|
|
| 666 |
document.getElementById('treeCount').textContent = `${loadedCount} trees`;
|
| 667 |
|
| 668 |
// If this is the last batch, finalize
|
| 669 |
+
if (i + uiBatchSize >= filteredTrees.length) {
|
| 670 |
console.log(`Map loading complete: ${loadedCount} tree markers added`);
|
| 671 |
this.showMessage(`Loaded ${loadedCount} trees successfully`, 'success');
|
| 672 |
}
|
| 673 |
+
}, (i / uiBatchSize) * 50); // Stagger UI batches by 50ms
|
| 674 |
}
|
| 675 |
|
|
|
|
|
|
|
|
|
|
| 676 |
// Auto-zoom to max level and center on trees after loading completes
|
| 677 |
setTimeout(() => {
|
| 678 |
if (loadedCount > 0) {
|
|
|
|
| 689 |
console.log('Map auto-zoomed to maximum detail level');
|
| 690 |
}, 500);
|
| 691 |
}
|
| 692 |
+
}, 2000); // Wait for most UI batches to complete
|
| 693 |
|
| 694 |
} catch (error) {
|
| 695 |
console.error('Error loading trees:', error);
|
static/sw.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
// TreeTrack Service Worker - PWA and Offline Support
|
| 2 |
-
const VERSION =
|
| 3 |
const CACHE_NAME = `treetrack-v${VERSION}`;
|
| 4 |
const STATIC_CACHE = `static-v${VERSION}`;
|
| 5 |
const API_CACHE = `api-v${VERSION}`;
|
|
|
|
| 1 |
// TreeTrack Service Worker - PWA and Offline Support
|
| 2 |
+
const VERSION = 1761506562; // Cache busting bump - force clients to fetch new static assets and header image change
|
| 3 |
const CACHE_NAME = `treetrack-v${VERSION}`;
|
| 4 |
const STATIC_CACHE = `static-v${VERSION}`;
|
| 5 |
const API_CACHE = `api-v${VERSION}`;
|
version.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
{
|
| 2 |
"version": "5.1.1",
|
| 3 |
-
"timestamp":
|
| 4 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"version": "5.1.1",
|
| 3 |
+
"timestamp": 1761506562
|
| 4 |
}
|