|
@@ -295,6 +295,8 @@ function setupEventListeners() {
|
|
|
const uploadBtn = document.getElementById('uploadBtn');
|
|
const uploadBtn = document.getElementById('uploadBtn');
|
|
|
const uploadBtnText = document.getElementById('uploadBtnText');
|
|
const uploadBtnText = document.getElementById('uploadBtnText');
|
|
|
const uploadProgress = document.getElementById('uploadProgress');
|
|
const uploadProgress = document.getElementById('uploadProgress');
|
|
|
|
|
+ const progressBar = document.getElementById('progressBar');
|
|
|
|
|
+ const progressPercent = document.getElementById('progressPercent');
|
|
|
const maxFileSizeMB = window.maxFileSizeMB || 16;
|
|
const maxFileSizeMB = window.maxFileSizeMB || 16;
|
|
|
if (!file) {
|
|
if (!file) {
|
|
|
showToast('Please select a file', 'error');
|
|
showToast('Please select a file', 'error');
|
|
@@ -314,74 +316,54 @@ function setupEventListeners() {
|
|
|
formData.append('file', file);
|
|
formData.append('file', file);
|
|
|
formData.append('user_session', getUserSession());
|
|
formData.append('user_session', getUserSession());
|
|
|
formData.append('duration_hours', duration);
|
|
formData.append('duration_hours', duration);
|
|
|
|
|
+ // Barra de progreso manual con fetch
|
|
|
let waitingTimeout, errorTimeout;
|
|
let waitingTimeout, errorTimeout;
|
|
|
try {
|
|
try {
|
|
|
- const xhr = new XMLHttpRequest();
|
|
|
|
|
- xhr.upload.addEventListener('progress', function(e) {
|
|
|
|
|
- if (e.lengthComputable) {
|
|
|
|
|
- updateProgress(e.loaded, e.total);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- xhr.upload.addEventListener('load', function() {
|
|
|
|
|
- // Barra llegó a 100%, pero aún esperando respuesta
|
|
|
|
|
- updateProgress(file.size, file.size, false, true);
|
|
|
|
|
- let waiting = document.getElementById('waitingServer');
|
|
|
|
|
- if (!waiting) {
|
|
|
|
|
- waiting = document.createElement('div');
|
|
|
|
|
- waiting.id = 'waitingServer';
|
|
|
|
|
- waiting.className = 'text-xs text-blue-600 dark:text-blue-400 mt-2 flex items-center gap-2';
|
|
|
|
|
- waiting.innerHTML = '<svg class="animate-spin h-4 w-4 mr-1 inline" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8z"></path></svg>Waiting for server confirmation...';
|
|
|
|
|
- uploadProgress.appendChild(waiting);
|
|
|
|
|
|
|
+ // Simular barra de progreso basada en tamaño y tiempo estimado
|
|
|
|
|
+ let loaded = 0;
|
|
|
|
|
+ const total = file.size;
|
|
|
|
|
+ const chunkSize = 1024 * 256; // 256KB
|
|
|
|
|
+ let isProcessing = false;
|
|
|
|
|
+ function simulateProgress() {
|
|
|
|
|
+ if (isProcessing) return;
|
|
|
|
|
+ if (loaded < total) {
|
|
|
|
|
+ loaded = Math.min(loaded + chunkSize, total);
|
|
|
|
|
+ updateProgress(loaded, total);
|
|
|
|
|
+ setTimeout(simulateProgress, 30);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Barra llena, mostrar processing
|
|
|
|
|
+ updateProgress(total, total, false, true);
|
|
|
|
|
+ isProcessing = true;
|
|
|
}
|
|
}
|
|
|
- // Si pasan 60s tras barra 100%, mostrar advertencia
|
|
|
|
|
- waitingTimeout = setTimeout(() => {
|
|
|
|
|
- waiting.textContent = 'The upload is taking longer than expected. Please check your connection.';
|
|
|
|
|
- }, 60000);
|
|
|
|
|
- // Si pasan 2 minutos, mostrar error y permitir reintentar
|
|
|
|
|
- errorTimeout = setTimeout(() => {
|
|
|
|
|
- waiting.remove();
|
|
|
|
|
- showToast('Upload failed: server did not respond. Please try again.', 'error');
|
|
|
|
|
- uploadBtn.disabled = false;
|
|
|
|
|
- uploadBtnText.textContent = 'Upload File';
|
|
|
|
|
- uploadProgress.classList.add('hidden');
|
|
|
|
|
- }, 120000);
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ simulateProgress();
|
|
|
|
|
+ // Real upload
|
|
|
|
|
+ const response = await fetch('/upload', {
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ body: formData
|
|
|
});
|
|
});
|
|
|
- xhr.addEventListener('load', function() {
|
|
|
|
|
- clearTimeout(waitingTimeout);
|
|
|
|
|
- clearTimeout(errorTimeout);
|
|
|
|
|
- updateProgress(file.size, file.size, true, false);
|
|
|
|
|
- document.getElementById('uploadSpeed').textContent = '';
|
|
|
|
|
- document.getElementById('timeRemaining').textContent = '';
|
|
|
|
|
- document.getElementById('waitingServer')?.remove();
|
|
|
|
|
- if (xhr.status === 200) {
|
|
|
|
|
- const result = JSON.parse(xhr.responseText);
|
|
|
|
|
- if (result.success) {
|
|
|
|
|
- showToast('File uploaded successfully!');
|
|
|
|
|
- clearFileSelection();
|
|
|
|
|
- loadUserFiles();
|
|
|
|
|
- } else {
|
|
|
|
|
- showToast(result.error || 'Error uploading file', 'error');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ clearTimeout(waitingTimeout);
|
|
|
|
|
+ clearTimeout(errorTimeout);
|
|
|
|
|
+ document.getElementById('waitingServer')?.remove();
|
|
|
|
|
+ if (response.ok) {
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ if (result.success) {
|
|
|
|
|
+ updateProgress(total, total, true, false);
|
|
|
|
|
+ showToast('File uploaded successfully!');
|
|
|
|
|
+ clearFileSelection();
|
|
|
|
|
+ loadUserFiles();
|
|
|
} else {
|
|
} else {
|
|
|
- showToast('Error uploading file', 'error');
|
|
|
|
|
|
|
+ showToast(result.error || 'Error uploading file', 'error');
|
|
|
}
|
|
}
|
|
|
- });
|
|
|
|
|
- xhr.addEventListener('error', function() {
|
|
|
|
|
- clearTimeout(waitingTimeout);
|
|
|
|
|
- clearTimeout(errorTimeout);
|
|
|
|
|
- document.getElementById('waitingServer')?.remove();
|
|
|
|
|
- showToast('Network error while uploading', 'error');
|
|
|
|
|
- });
|
|
|
|
|
- xhr.open('POST', '/upload');
|
|
|
|
|
- xhr.send(formData);
|
|
|
|
|
|
|
+ } else {
|
|
|
|
|
+ showToast('Error uploading file', 'error');
|
|
|
|
|
+ }
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
showToast('Error uploading file: ' + error.message, 'error');
|
|
showToast('Error uploading file: ' + error.message, 'error');
|
|
|
} finally {
|
|
} finally {
|
|
|
- setTimeout(() => {
|
|
|
|
|
- uploadBtn.disabled = false;
|
|
|
|
|
- uploadBtnText.textContent = 'Upload File';
|
|
|
|
|
- uploadProgress.classList.add('hidden');
|
|
|
|
|
- }, 1000);
|
|
|
|
|
|
|
+ uploadBtn.disabled = false;
|
|
|
|
|
+ uploadBtnText.textContent = 'Upload File';
|
|
|
|
|
+ uploadProgress.classList.add('hidden');
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
// Refrescar lista
|
|
// Refrescar lista
|