|
@@ -95,13 +95,13 @@ function getTimeRemaining(expirationDate) {
|
|
|
const now = new Date();
|
|
const now = new Date();
|
|
|
const expiry = new Date(expirationDate);
|
|
const expiry = new Date(expirationDate);
|
|
|
const diff = expiry - now;
|
|
const diff = expiry - now;
|
|
|
- if (diff <= 0) return 'Expirado';
|
|
|
|
|
|
|
+ if (diff <= 0) return 'Expired';
|
|
|
const hours = Math.floor(diff / (1000 * 60 * 60));
|
|
const hours = Math.floor(diff / (1000 * 60 * 60));
|
|
|
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
|
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
|
|
if (hours > 0) {
|
|
if (hours > 0) {
|
|
|
- return `${hours}h ${minutes}m restantes`;
|
|
|
|
|
|
|
+ return `${hours}h ${minutes}m remaining`;
|
|
|
} else {
|
|
} else {
|
|
|
- return `${minutes}m restantes`;
|
|
|
|
|
|
|
+ return `${minutes}m remaining`;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -124,7 +124,7 @@ function updateProgress(loaded, total) {
|
|
|
const remaining = (total - loaded) / speed;
|
|
const remaining = (total - loaded) / speed;
|
|
|
const minutes = Math.floor(remaining / 60);
|
|
const minutes = Math.floor(remaining / 60);
|
|
|
const seconds = Math.floor(remaining % 60);
|
|
const seconds = Math.floor(remaining % 60);
|
|
|
- timeRemaining.textContent = `${minutes}:${seconds.toString().padStart(2, '0')} restantes`;
|
|
|
|
|
|
|
+ timeRemaining.textContent = `${minutes}:${seconds.toString().padStart(2, '0')} remaining`;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -133,7 +133,13 @@ function handleFileSelection(file) {
|
|
|
const fileInfo = document.getElementById('file-info');
|
|
const fileInfo = document.getElementById('file-info');
|
|
|
const fileName = document.getElementById('file-name');
|
|
const fileName = document.getElementById('file-name');
|
|
|
const fileSize = document.getElementById('file-size');
|
|
const fileSize = document.getElementById('file-size');
|
|
|
|
|
+ const maxFileSizeMB = window.maxFileSizeMB || 16;
|
|
|
if (file) {
|
|
if (file) {
|
|
|
|
|
+ if (file.size > maxFileSizeMB * 1024 * 1024) {
|
|
|
|
|
+ showToast(`File size exceeds the allowed limit (${maxFileSizeMB} MB)`, 'error');
|
|
|
|
|
+ clearFileSelection();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
fileName.textContent = file.name;
|
|
fileName.textContent = file.name;
|
|
|
fileName.classList.add('truncate');
|
|
fileName.classList.add('truncate');
|
|
|
fileName.setAttribute('data-tooltip', file.name);
|
|
fileName.setAttribute('data-tooltip', file.name);
|
|
@@ -176,34 +182,34 @@ async function loadUserFiles() {
|
|
|
</div>
|
|
</div>
|
|
|
<div class="flex-1 min-w-0">
|
|
<div class="flex-1 min-w-0">
|
|
|
<p class="text-sm font-medium text-gray-900 dark:text-white truncate file-tooltip" data-tooltip="${file.original_filename}">${file.original_filename}</p>
|
|
<p class="text-sm font-medium text-gray-900 dark:text-white truncate file-tooltip" data-tooltip="${file.original_filename}">${file.original_filename}</p>
|
|
|
- <p class="text-xs text-gray-500 dark:text-gray-400">${formatFileSize(file.file_size)} • Subido ${formatDate(file.upload_date)}</p>
|
|
|
|
|
|
|
+ <p class="text-xs text-gray-500 dark:text-gray-400">${formatFileSize(file.file_size)} • Uploaded ${formatDate(file.upload_date)}</p>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="flex items-center space-x-2">
|
|
<div class="flex items-center space-x-2">
|
|
|
<div class="text-right">
|
|
<div class="text-right">
|
|
|
- <p class="text-xs text-gray-500 dark:text-gray-400">${getTimeRemaining(file.expiration_date)}</p>
|
|
|
|
|
|
|
+ <p class="text-xs text-gray-500 dark:text-gray-400 file-remaining-time" data-expiration="${file.expiration_date}">${getTimeRemaining(file.expiration_date)}</p>
|
|
|
</div>
|
|
</div>
|
|
|
<a href="${file.download_url}" class="inline-flex items-center px-3 py-1 text-xs font-medium text-blue-600 dark:text-blue-400 bg-blue-100 dark:bg-blue-900/30 hover:bg-blue-200 dark:hover:bg-blue-900/50 rounded-full transition-colors">
|
|
<a href="${file.download_url}" class="inline-flex items-center px-3 py-1 text-xs font-medium text-blue-600 dark:text-blue-400 bg-blue-100 dark:bg-blue-900/30 hover:bg-blue-200 dark:hover:bg-blue-900/50 rounded-full transition-colors">
|
|
|
- Descargar
|
|
|
|
|
|
|
+ Download
|
|
|
</a>
|
|
</a>
|
|
|
<button onclick="deleteFile('${file.id}')" class="inline-flex items-center px-3 py-1 text-xs font-medium text-red-600 dark:text-red-400 bg-red-100 dark:bg-red-900/30 hover:bg-red-200 dark:hover:bg-red-900/50 rounded-full transition-colors">
|
|
<button onclick="deleteFile('${file.id}')" class="inline-flex items-center px-3 py-1 text-xs font-medium text-red-600 dark:text-red-400 bg-red-100 dark:bg-red-900/30 hover:bg-red-200 dark:hover:bg-red-900/50 rounded-full transition-colors">
|
|
|
- Eliminar
|
|
|
|
|
|
|
+ Delete
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
`).join('');
|
|
`).join('');
|
|
|
}
|
|
}
|
|
|
- // Tooltips personalizados para nombres truncados
|
|
|
|
|
document.querySelectorAll('.file-tooltip').forEach(el => {
|
|
document.querySelectorAll('.file-tooltip').forEach(el => {
|
|
|
el.addEventListener('mouseenter', function(e) {
|
|
el.addEventListener('mouseenter', function(e) {
|
|
|
showCustomTooltip(e.target, e.target.getAttribute('data-tooltip'));
|
|
showCustomTooltip(e.target, e.target.getAttribute('data-tooltip'));
|
|
|
});
|
|
});
|
|
|
el.addEventListener('mouseleave', hideCustomTooltip);
|
|
el.addEventListener('mouseleave', hideCustomTooltip);
|
|
|
});
|
|
});
|
|
|
|
|
+ updateRemainingTimes();
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- showToast('Error al cargar archivos', 'error');
|
|
|
|
|
|
|
+ showToast('Error loading files', 'error');
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -232,13 +238,13 @@ async function confirmDeleteFile() {
|
|
|
});
|
|
});
|
|
|
const result = await response.json();
|
|
const result = await response.json();
|
|
|
if (result.success) {
|
|
if (result.success) {
|
|
|
- showToast('Archivo eliminado correctamente');
|
|
|
|
|
|
|
+ showToast('File deleted successfully');
|
|
|
loadUserFiles();
|
|
loadUserFiles();
|
|
|
} else {
|
|
} else {
|
|
|
- showToast(result.error || 'Error al eliminar', 'error');
|
|
|
|
|
|
|
+ showToast(result.error || 'Error deleting file', 'error');
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- showToast('Error al eliminar: ' + error.message, 'error');
|
|
|
|
|
|
|
+ showToast('Error deleting file: ' + error.message, 'error');
|
|
|
} finally {
|
|
} finally {
|
|
|
closeDeleteModal();
|
|
closeDeleteModal();
|
|
|
}
|
|
}
|
|
@@ -277,12 +283,18 @@ 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 maxFileSizeMB = window.maxFileSizeMB || 16;
|
|
|
if (!file) {
|
|
if (!file) {
|
|
|
- showToast('Por favor selecciona un archivo', 'error');
|
|
|
|
|
|
|
+ showToast('Please select a file', 'error');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (file.size > maxFileSizeMB * 1024 * 1024) {
|
|
|
|
|
+ showToast(`File size exceeds the allowed limit (${maxFileSizeMB} MB)`, 'error');
|
|
|
|
|
+ clearFileSelection();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
uploadBtn.disabled = true;
|
|
uploadBtn.disabled = true;
|
|
|
- uploadBtnText.textContent = 'Subiendo...';
|
|
|
|
|
|
|
+ uploadBtnText.textContent = 'Uploading...';
|
|
|
uploadProgress.classList.remove('hidden');
|
|
uploadProgress.classList.remove('hidden');
|
|
|
uploadStartTime = Date.now();
|
|
uploadStartTime = Date.now();
|
|
|
uploadedBytes = 0;
|
|
uploadedBytes = 0;
|
|
@@ -301,27 +313,27 @@ function setupEventListeners() {
|
|
|
if (xhr.status === 200) {
|
|
if (xhr.status === 200) {
|
|
|
const result = JSON.parse(xhr.responseText);
|
|
const result = JSON.parse(xhr.responseText);
|
|
|
if (result.success) {
|
|
if (result.success) {
|
|
|
- showToast('Archivo subido correctamente!');
|
|
|
|
|
|
|
+ showToast('File uploaded successfully!');
|
|
|
clearFileSelection();
|
|
clearFileSelection();
|
|
|
loadUserFiles();
|
|
loadUserFiles();
|
|
|
} else {
|
|
} else {
|
|
|
- showToast(result.error || 'Error al subir', 'error');
|
|
|
|
|
|
|
+ showToast(result.error || 'Error uploading file', 'error');
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- showToast('Error al subir', 'error');
|
|
|
|
|
|
|
+ showToast('Error uploading file', 'error');
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
xhr.addEventListener('error', function() {
|
|
xhr.addEventListener('error', function() {
|
|
|
- showToast('Error de red al subir', 'error');
|
|
|
|
|
|
|
+ showToast('Network error while uploading', 'error');
|
|
|
});
|
|
});
|
|
|
xhr.open('POST', '/upload');
|
|
xhr.open('POST', '/upload');
|
|
|
xhr.send(formData);
|
|
xhr.send(formData);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- showToast('Error al subir: ' + error.message, 'error');
|
|
|
|
|
|
|
+ showToast('Error uploading file: ' + error.message, 'error');
|
|
|
} finally {
|
|
} finally {
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
uploadBtn.disabled = false;
|
|
uploadBtn.disabled = false;
|
|
|
- uploadBtnText.textContent = 'Subir archivo';
|
|
|
|
|
|
|
+ uploadBtnText.textContent = 'Upload File';
|
|
|
uploadProgress.classList.add('hidden');
|
|
uploadProgress.classList.add('hidden');
|
|
|
}, 1000);
|
|
}, 1000);
|
|
|
}
|
|
}
|
|
@@ -335,5 +347,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
setupEventListeners();
|
|
setupEventListeners();
|
|
|
setupDeleteModalEvents();
|
|
setupDeleteModalEvents();
|
|
|
loadUserFiles();
|
|
loadUserFiles();
|
|
|
- setInterval(loadUserFiles, 30000);
|
|
|
|
|
-});
|
|
|
|
|
|
|
+ setInterval(updateRemainingTimes, 60000);
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+function updateRemainingTimes() {
|
|
|
|
|
+ document.querySelectorAll('.file-remaining-time').forEach(el => {
|
|
|
|
|
+ const expiration = el.getAttribute('data-expiration');
|
|
|
|
|
+ el.textContent = getTimeRemaining(expiration);
|
|
|
|
|
+ });
|
|
|
|
|
+}
|