Files
ETPlot/assets/js/utils.js
T
Kylian Schmidt dbd67f6039 Fix template rendering issue and improve export functionality
- Fix template rendering by storing rendered HTML in variable before writing
  This resolves subdirectories not appearing in navigation despite being
  correctly detected and included in template variables
- Add missing template variables (paths.work_dir) to gallery config
- Add CGI refresh handler for web-based gallery regeneration
- Improve PDF export functionality with better error handling
- Add ESC key shortcut documentation for exiting selection mode
- Enhanced export manager with proper dependency checking

Fixes issue where new subdirectories were detected but not displayed
in browser navigation due to incomplete template rendering.
2025-07-20 08:59:10 +02:00

152 lines
4.4 KiB
JavaScript

/**
* Utility functions and helpers
*/
export class Utils {
/**
* Format file size in human readable format
*/
static formatFileSize(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
/**
* Handle thumbnail highlighting from URL parameters
*/
static handleThumbnailHighlight() {
const urlParams = new URLSearchParams(window.location.search);
const highlightPlot = urlParams.get('highlight');
if (highlightPlot) {
// Find and highlight the thumbnail
const gridItems = document.querySelectorAll('.grid-item');
gridItems.forEach(item => {
const plotName = item.querySelector('.plot-name');
if (plotName && plotName.textContent.trim() === highlightPlot) {
item.classList.add('highlighted');
// Scroll to the highlighted item
setTimeout(() => {
item.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}, 100);
// Remove highlight after animation
setTimeout(() => {
item.classList.remove('highlighted');
}, 3000);
}
});
// Clean up URL
const newUrl = new URL(window.location);
newUrl.searchParams.delete('highlight');
window.history.replaceState({}, document.title, newUrl.toString());
}
}
/**
* Calculate approximate total size of displayed files
*/
static async calculateApproximateSize() {
const images = document.querySelectorAll('.grid-item img');
let totalSize = 0;
let loadedCount = 0;
const sizeElement = document.getElementById('totalSize');
if (!sizeElement) return;
sizeElement.textContent = 'Loading...';
// Estimate size based on a sample of images
const sampleSize = Math.min(images.length, 5);
const sampleImages = Array.from(images).slice(0, sampleSize);
if (sampleImages.length === 0) {
sizeElement.textContent = '0 KB';
return;
}
// Calculate average size from sample
for (const img of sampleImages) {
try {
const response = await fetch(img.src, { method: 'HEAD' });
const size = parseInt(response.headers.get('content-length') || '0');
if (size > 0) {
totalSize += size;
loadedCount++;
}
} catch (e) {
// Fallback: estimate 100KB per image
totalSize += 102400;
loadedCount++;
}
}
if (loadedCount > 0) {
const averageSize = totalSize / loadedCount;
const estimatedTotal = averageSize * images.length;
sizeElement.textContent = Utils.formatFileSize(estimatedTotal);
} else {
sizeElement.textContent = 'Unknown';
}
}
/**
* Refresh gallery by calling CGI script
*/
static async refreshGallery() {
const refreshBtn = document.getElementById('refreshBtn');
if (!refreshBtn) return;
refreshBtn.disabled = true;
refreshBtn.textContent = '⏳';
// Use the CGI script path from config if available
let cgiPath = '/cgi-bin/refresh_gallery.py';
if (window.galleryConfig && window.galleryConfig.paths && window.galleryConfig.paths.cgi_script) {
cgiPath = window.galleryConfig.paths.cgi_script;
// Ensure it starts with a slash for fetch
if (!cgiPath.startsWith('/')) cgiPath = '/' + cgiPath;
}
try {
const response = await fetch(cgiPath, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
});
if (response.ok) {
refreshBtn.textContent = '✅';
setTimeout(() => {
window.location.reload();
}, 1000);
} else {
throw new Error('Refresh failed');
}
} catch (error) {
console.error('Error refreshing gallery:', error);
refreshBtn.textContent = '❌';
setTimeout(() => {
refreshBtn.disabled = false;
refreshBtn.textContent = '🔄';
}, 3000);
}
}
/**
* Toggle keyboard shortcuts help display
*/
static toggleShortcutsHelp() {
const help = document.getElementById('shortcutsHelp');
if (help) {
help.style.display = help.style.display === 'block' ? 'none' : 'block';
}
}
}