Files
geoip_block_generator/static/js/progress.js
Mateusz Gruszczyński 88a0574e86 fix i js
2026-02-23 13:15:17 +01:00

216 lines
6.9 KiB
JavaScript

let progressInterval = null;
function startProgressPolling() {
if (progressInterval) {
clearInterval(progressInterval);
}
progressInterval = setInterval(async () => {
try {
const response = await fetch('/api/progress');
const data = await response.json();
if (data.active) {
updateProgressUI(data.message, data.progress, data.total);
} else {
stopProgressPolling();
}
} catch (error) {
console.error('Progress polling error:', error);
}
}, 500);
}
function stopProgressPolling() {
if (progressInterval) {
clearInterval(progressInterval);
progressInterval = null;
}
}
function updateProgressUI(message, progress, total) {
if (window.progressInitTimeout) {
clearTimeout(window.progressInitTimeout);
window.progressInitTimeout = null;
}
const progressSection = document.getElementById('progressSection');
const progressBar = progressSection.querySelector('.progress-bar');
const progressMessage = document.getElementById('progressMessage');
const progressPercentage = document.getElementById('progressPercentage');
const percentage = total > 0 ? Math.round((progress / total) * 100) : 0;
progressBar.style.width = percentage + '%';
if (progressPercentage) {
progressPercentage.textContent = percentage + '%';
}
progressBar.setAttribute('aria-valuenow', percentage);
if (progressMessage) {
progressMessage.textContent = message;
}
}
function showProgress() {
const progressSection = document.getElementById('progressSection');
const progressBar = progressSection.querySelector('.progress-bar');
const progressMessage = document.getElementById('progressMessage');
const progressPercentage = document.getElementById('progressPercentage');
progressBar.style.width = '0%';
if (progressPercentage) {
progressPercentage.textContent = '0%';
}
if (progressMessage) {
progressMessage.textContent = 'Initializing...';
}
document.getElementById('resultSection').style.display = 'none';
progressSection.style.display = 'block';
document.getElementById('generateBtn').disabled = true;
window.progressInitTimeout = setTimeout(() => {
if (progressMessage && progressMessage.textContent === 'Initializing...') {
progressMessage.innerHTML = `
<div>Request is being processed..</div>
<div style="margin-top: 10px; color: #856404; background: #fff3cd; padding: 10px; border-radius: 4px; font-size: 0.9em;">
The task is queued and will start automatically.
</div>
`;
}
}, 5000);
startProgressPolling();
}
function hideProgress() {
const progressSection = document.getElementById('progressSection');
progressSection.style.display = 'none';
document.getElementById('generateBtn').disabled = false;
stopProgressPolling();
}
function showResult(message, type = 'danger') {
const resultSection = document.getElementById('resultSection');
const resultMessage = document.getElementById('resultMessage');
const alertDiv = resultSection.querySelector('.alert');
const iconMap = {
'success': 'check-circle',
'danger': 'exclamation-circle',
'warning': 'exclamation-triangle',
'info': 'info-circle'
};
const icon = iconMap[type] || 'info-circle';
alertDiv.className = `alert alert-${type}`;
resultMessage.innerHTML = `<i class="fas fa-${icon} me-2"></i>${message}`;
resultSection.style.display = 'block';
if (type === 'success') {
setTimeout(() => {
resultSection.style.display = 'none';
}, 5000);
}
}
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('generateForm');
if (form) {
form.addEventListener('submit', async function(e) {
e.preventDefault();
const formData = getFormData();
if (!formData) {
showResult('Please select at least one country to continue', 'warning');
return;
}
await downloadConfiguration(formData);
});
}
});
async function downloadConfiguration(formData) {
showProgress();
try {
const endpoint = formData.app_type === 'raw-cidr'
? '/api/generate/raw'
: '/api/generate';
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData)
});
hideProgress();
if (response.ok) {
const fromCache = response.headers.get('X-From-Cache') === 'true';
const generatedAt = response.headers.get('X-Generated-At');
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
const contentDisposition = response.headers.get('Content-Disposition');
let filename = 'geoblock_config.conf';
if (contentDisposition) {
const filenameMatch = contentDisposition.match(/filename="?(.+)"?/);
if (filenameMatch) {
filename = filenameMatch[1];
}
}
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
if (fromCache) {
showResult(`<i class="fas fa-bolt"></i> <strong>Ready!</strong> Downloaded from cache: ${filename}`, 'success');
} else {
showResult(`Configuration downloaded successfully: ${filename}`, 'success');
}
} else {
const error = await response.json();
showResult(error.error || 'An error occurred during download', 'danger');
}
} catch (error) {
hideProgress();
showResult('Network error: ' + error.message, 'danger');
}
}
function getFormData() {
const countries = Array.from(document.querySelectorAll('input[name="countries"]:checked'))
.map(input => input.value);
if (countries.length === 0) {
return null;
}
const useCacheCheckbox = document.getElementById('useCache');
return {
countries: countries,
app_type: document.getElementById('appType').value,
app_variant: document.getElementById('appVariant').value,
aggregate: document.getElementById('aggregate').checked,
use_cache: useCacheCheckbox ? useCacheCheckbox.checked : true
};
}