198 lines
6.3 KiB
JavaScript
198 lines
6.3 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) {
|
|
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;
|
|
|
|
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>Lightning fast!</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
|
|
};
|
|
}
|