Files / templates /index.html
lea97338's picture
Upload 2 files
b266b9e verified
Raw
History Blame Contribute Delete
41.3 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>📁 Gestionnaire de Fichiers Pro</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 30px;
text-align: center;
position: relative;
}
.header h1 {
font-size: 2.5em;
margin-bottom: 10px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}
.header p {
font-size: 1.2em;
opacity: 0.9;
}
.user-info {
position: absolute;
top: 20px;
right: 20px;
background: rgba(255,255,255,0.2);
padding: 10px 15px;
border-radius: 20px;
color: white;
font-size: 0.9em;
display: flex;
align-items: center;
gap: 10px;
}
.admin-badge {
background: #dc3545;
color: white;
font-size: 0.7em;
padding: 2px 6px;
border-radius: 10px;
margin-left: 5px;
}
.logout-btn, .admin-btn {
background: rgba(255,255,255,0.2);
color: white;
border: 1px solid rgba(255,255,255,0.3);
padding: 5px 10px;
border-radius: 15px;
text-decoration: none;
font-size: 0.8em;
transition: all 0.3s ease;
cursor: pointer;
}
.logout-btn:hover, .admin-btn:hover {
background: rgba(255,255,255,0.3);
}
.stats {
display: flex;
justify-content: space-around;
background: #f8f9fa;
padding: 20px;
border-bottom: 1px solid #e9ecef;
}
.stat-item {
text-align: center;
}
.stat-number {
font-size: 2em;
font-weight: bold;
color: #4facfe;
}
.stat-label {
color: #6c757d;
font-size: 0.9em;
}
.upload-section {
padding: 40px;
text-align: center;
}
.upload-area {
border: 3px dashed #4facfe;
border-radius: 15px;
padding: 60px 20px;
background: #f8f9ff;
transition: all 0.3s ease;
cursor: pointer;
position: relative;
overflow: hidden;
}
.upload-area:hover {
border-color: #00f2fe;
background: #f0f8ff;
transform: translateY(-2px);
}
.upload-area.dragover {
border-color: #00f2fe;
background: #e6f3ff;
transform: scale(1.02);
}
.upload-icon {
font-size: 4em;
color: #4facfe;
margin-bottom: 20px;
}
.upload-text {
font-size: 1.3em;
color: #333;
margin-bottom: 15px;
}
.upload-subtext {
color: #6c757d;
font-size: 1em;
}
#fileInput {
display: none;
}
.btn {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
border: none;
padding: 15px 30px;
border-radius: 50px;
font-size: 1.1em;
cursor: pointer;
transition: all 0.3s ease;
margin: 10px;
box-shadow: 0 4px 15px rgba(79, 172, 254, 0.4);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(79, 172, 254, 0.6);
}
.btn:active {
transform: translateY(0);
}
.progress-container {
margin: 20px 0;
display: none;
}
.progress-bar {
width: 100%;
height: 20px;
background: #e9ecef;
border-radius: 10px;
overflow: hidden;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #4facfe, #00f2fe);
width: 0%;
transition: width 0.3s ease;
border-radius: 10px;
}
.progress-text {
text-align: center;
margin-top: 10px;
font-weight: bold;
color: #333;
}
.files-section {
padding: 40px;
background: #f8f9fa;
}
.files-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
}
.files-title {
font-size: 1.8em;
color: #333;
}
.refresh-btn {
background: #28a745;
font-size: 0.9em;
padding: 10px 20px;
}
.files-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.file-card {
background: white;
border-radius: 15px;
padding: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
transition: all 0.3s ease;
border: 1px solid #e9ecef;
position: relative;
overflow: hidden;
}
.file-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
}
.file-preview {
width: 100%;
height: 150px;
background: #f8f9fa;
border-radius: 10px;
margin-bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
cursor: pointer;
}
.file-preview img {
max-width: 100%;
max-height: 100%;
object-fit: cover;
border-radius: 8px;
}
.file-preview video {
max-width: 100%;
max-height: 100%;
object-fit: cover;
border-radius: 8px;
}
.file-preview-icon {
font-size: 3em;
color: #dee2e6;
}
.video-overlay {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.7);
color: white;
border-radius: 50%;
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2em;
cursor: pointer;
transition: all 0.3s ease;
}
.video-overlay:hover {
background: rgba(0,0,0,0.9);
transform: translate(-50%, -50%) scale(1.1);
}
.preview-modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.9);
backdrop-filter: blur(5px);
}
.modal-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 90vw;
max-height: 90vh;
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(0,0,0,0.3);
}
.modal-header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-title {
font-size: 1.2em;
font-weight: 600;
}
.modal-close {
background: none;
border: none;
color: white;
font-size: 1.5em;
cursor: pointer;
padding: 5px;
border-radius: 5px;
transition: background 0.3s ease;
}
.modal-close:hover {
background: rgba(255,255,255,0.2);
}
.modal-body {
padding: 0;
text-align: center;
}
.modal-body img,
.modal-body video {
max-width: 100%;
max-height: 70vh;
object-fit: contain;
}
.modal-body video {
width: 100%;
}
.file-info {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.file-details h3 {
color: #333;
font-size: 1.1em;
margin-bottom: 5px;
word-break: break-word;
}
.file-meta {
color: #6c757d;
font-size: 0.9em;
}
.file-actions {
display: flex;
gap: 10px;
}
.btn-small {
padding: 8px 16px;
font-size: 0.9em;
border-radius: 20px;
}
.btn-download {
background: linear-gradient(135deg, #28a745, #20c997);
}
.btn-delete {
background: linear-gradient(135deg, #dc3545, #fd7e14);
}
.message {
padding: 15px;
border-radius: 10px;
margin: 20px 0;
font-weight: bold;
text-align: center;
}
.message.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.message.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.empty-state {
text-align: center;
padding: 60px 20px;
color: #6c757d;
}
.empty-icon {
font-size: 4em;
margin-bottom: 20px;
opacity: 0.5;
}
.loading {
display: none;
text-align: center;
padding: 40px;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #4facfe;
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Admin Panel */
.admin-panel {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 15px;
padding: 30px;
margin: 20px 40px;
display: none;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.admin-panel h3 {
color: #333;
margin-bottom: 25px;
font-size: 1.5em;
text-align: center;
}
.admin-tabs {
display: flex;
gap: 10px;
margin-bottom: 25px;
justify-content: center;
}
.admin-tab {
background: #e9ecef;
color: #495057;
border: none;
padding: 10px 20px;
border-radius: 25px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
}
.admin-tab.active {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
}
.admin-content {
background: white;
border-radius: 10px;
padding: 25px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.add-user-section {
display: none;
}
.add-user-section.active {
display: block;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr auto;
gap: 15px;
align-items: end;
margin-bottom: 20px;
}
.form-group-admin {
display: flex;
flex-direction: column;
}
.form-label-admin {
font-weight: 600;
color: #333;
margin-bottom: 5px;
font-size: 0.9em;
}
.form-input-admin {
padding: 12px 15px;
border: 2px solid #e9ecef;
border-radius: 8px;
font-size: 14px;
transition: border-color 0.3s ease;
outline: none;
}
.form-input-admin:focus {
border-color: #4facfe;
box-shadow: 0 0 0 3px rgba(79, 172, 254, 0.1);
}
.btn-add-user {
background: linear-gradient(135deg, #28a745, #20c997);
color: white;
border: none;
padding: 12px 20px;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
white-space: nowrap;
}
.btn-add-user:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3);
}
.users-list-section {
display: block;
}
.users-list-section.active {
display: block;
}
.users-grid {
display: grid;
gap: 15px;
}
.user-card {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 10px;
padding: 15px;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.3s ease;
}
.user-card:hover {
background: #e9ecef;
transform: translateY(-2px);
}
.user-info {
display: flex;
align-items: center;
gap: 10px;
}
.user-avatar {
width: 40px;
height: 40px;
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
.user-details h4 {
margin: 0;
color: #333;
font-size: 1.1em;
}
.user-role {
font-size: 0.8em;
color: #6c757d;
margin-top: 2px;
}
.btn-delete-user {
background: linear-gradient(135deg, #dc3545, #fd7e14);
color: white;
border: none;
padding: 8px 15px;
border-radius: 6px;
cursor: pointer;
font-size: 0.9em;
transition: all 0.3s ease;
}
.btn-delete-user:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(220, 53, 69, 0.3);
}
.btn-delete-user:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
}
/* Responsive Design */
@media (max-width: 768px) {
body {
padding: 10px;
}
.header h1 {
font-size: 2em;
}
.header p {
font-size: 1em;
}
.user-info {
position: static;
margin-bottom: 20px;
justify-content: center;
}
.upload-section, .files-section {
padding: 20px;
}
.upload-area {
padding: 40px 15px;
}
.upload-icon {
font-size: 3em;
}
.upload-text {
font-size: 1.1em;
}
.stats {
flex-direction: column;
gap: 15px;
}
.files-header {
flex-direction: column;
gap: 15px;
text-align: center;
}
.files-grid {
grid-template-columns: 1fr;
}
.file-actions {
flex-direction: column;
}
.admin-panel {
margin: 20px;
padding: 20px;
}
.admin-tabs {
flex-direction: column;
gap: 5px;
}
.admin-tab {
padding: 8px 15px;
font-size: 0.9em;
}
.form-grid {
grid-template-columns: 1fr;
gap: 10px;
}
.form-group-admin {
margin-bottom: 15px;
}
.btn-add-user {
width: 100%;
margin-top: 10px;
}
.user-card {
flex-direction: column;
gap: 15px;
text-align: center;
}
.user-info {
justify-content: center;
}
}
@media (max-width: 480px) {
.header {
padding: 20px;
}
.header h1 {
font-size: 1.8em;
}
.upload-area {
padding: 30px 10px;
}
.btn {
padding: 12px 24px;
font-size: 1em;
}
}
</style>
</head>
<body>
<div class="container">
<!-- Header -->
<div class="header">
<div class="user-info">
<i class="fas fa-user"></i> {{ username }}
{% if is_admin %}
<span class="admin-badge">ADMIN</span>
<button class="admin-btn" onclick="toggleAdminPanel()">
<i class="fas fa-cog"></i> Admin
</button>
{% endif %}
<a class="logout-btn" href="/logout">
<i class="fas fa-sign-out-alt"></i> Déconnexion
</a>
</div>
<h1>📁 Gestionnaire de Fichiers Pro</h1>
<p>Upload, téléchargez et gérez vos fichiers facilement</p>
</div>
<!-- Admin Panel -->
{% if is_admin %}
<div class="admin-panel" id="adminPanel">
<h3><i class="fas fa-users-cog"></i> Panel d'Administration</h3>
<div class="admin-tabs">
<button class="admin-tab active" onclick="switchAdminTab('add-user')">
<i class="fas fa-user-plus"></i> Ajouter Utilisateur
</button>
<button class="admin-tab" onclick="switchAdminTab('manage-users')">
<i class="fas fa-users"></i> Gérer Utilisateurs
</button>
</div>
<div class="admin-content">
<!-- Ajouter un utilisateur -->
<div class="add-user-section active" id="add-user-section">
<h4 style="margin-bottom: 20px; color: #333;">
<i class="fas fa-user-plus"></i> Créer un nouvel utilisateur
</h4>
<div class="form-grid">
<div class="form-group-admin">
<label class="form-label-admin">Nom d'utilisateur</label>
<input class="form-input-admin" id="newUsername" placeholder="Entrez le nom d'utilisateur" type="text"/>
</div>
<div class="form-group-admin">
<label class="form-label-admin">Mot de passe</label>
<input class="form-input-admin" id="newPassword" placeholder="Entrez le mot de passe" type="password"/>
</div>
<div class="form-group-admin">
<label class="form-label-admin">Rôle</label>
<select class="form-input-admin" id="newRole">
<option value="user">Utilisateur</option>
<option value="admin">Administrateur</option>
</select>
</div>
<button class="btn-add-user" onclick="addUser()">
<i class="fas fa-plus"></i> Créer
</button>
</div>
</div>
<!-- Gérer les utilisateurs -->
<div class="users-list-section" id="manage-users-section" style="display: none;">
<h4 style="margin-bottom: 20px; color: #333;">
<i class="fas fa-users"></i> Utilisateurs existants
</h4>
<div class="users-grid" id="usersList">
<!-- Liste des utilisateurs chargée dynamiquement -->
</div>
</div>
</div>
</div>
{% endif %}
<!-- Stats -->
<div class="stats">
<div class="stat-item">
<div class="stat-number" id="totalFiles">0</div>
<div class="stat-label">Fichiers</div>
</div>
<div class="stat-item">
<div class="stat-number" id="totalSize">0 B</div>
<div class="stat-label">Taille totale</div>
</div>
<div class="stat-item">
<div class="stat-number">8 GB</div>
<div class="stat-label">Limite par fichier</div>
</div>
</div>
<!-- Upload Section -->
<div class="upload-section">
<div class="upload-area" id="uploadArea">
<div class="upload-icon">📤</div>
<div class="upload-text">Glissez-déposez vos fichiers ici</div>
<div class="upload-subtext">ou cliquez pour sélectionner</div>
<input id="fileInput" multiple="" type="file"/>
</div>
<div class="progress-container" id="progressContainer">
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="progress-text" id="progressText">Upload en cours...</div>
</div>
<button class="btn" onclick="document.getElementById('fileInput').click()">
📁 Sélectionner des fichiers
</button>
</div>
<!-- Messages -->
<div id="messageContainer"></div>
<!-- Files Section -->
<div class="files-section">
<div class="files-header">
<h2 class="files-title">📂 Mes Fichiers</h2>
<button class="btn refresh-btn" onclick="loadFiles()">
🔄 Actualiser
</button>
</div>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>Chargement des fichiers...</p>
</div>
<div class="files-grid" id="filesGrid"></div>
</div>
</div>
<!-- Modal de prévisualisation -->
<div class="preview-modal" id="previewModal">
<div class="modal-content">
<div class="modal-header">
<div class="modal-title" id="modalTitle">Aperçu du fichier</div>
<button class="modal-close" onclick="closePreview()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body" id="modalBody">
<!-- Contenu dynamique -->
</div>
</div>
</div>
<script>
// Variables globales
let isUploading = false;
const isAdmin = {{ 'true' if is_admin else 'false' }};
// Initialisation
document.addEventListener('DOMContentLoaded', function() {
loadFiles();
setupEventListeners();
if (isAdmin) {
loadUsers();
}
});
function setupEventListeners() {
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
// Drag & Drop
uploadArea.addEventListener('dragover', function(e) {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', function(e) {
e.preventDefault();
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', function(e) {
e.preventDefault();
uploadArea.classList.remove('dragover');
const files = e.dataTransfer.files;
if (files.length > 0) {
handleFiles(files);
}
});
// Click to upload
uploadArea.addEventListener('click', function() {
if (!isUploading) {
fileInput.click();
}
});
// File input change
fileInput.addEventListener('change', function(e) {
if (e.target.files.length > 0) {
handleFiles(e.target.files);
}
});
}
function handleFiles(files) {
if (isUploading) {
showMessage('Un upload est déjà en cours...', 'error');
return;
}
if (files.length === 0) {
showMessage('Aucun fichier sélectionné', 'error');
return;
}
uploadFilesSequentially(Array.from(files), 0);
}
function uploadFilesSequentially(files, index) {
if (index >= files.length) {
hideProgress();
loadFiles();
return;
}
const file = files[index];
const totalFiles = files.length;
showProgress();
updateProgress(0, `Upload ${index + 1}/${totalFiles}: ${file.name}`);
uploadSingleFile(file, function(success) {
if (success) {
updateProgress(100, `✅ ${file.name} uploadé avec succès`);
} else {
updateProgress(100, `❌ Erreur lors de l'upload de ${file.name}`);
}
setTimeout(() => {
uploadFilesSequentially(files, index + 1);
}, 1000);
});
}
function uploadSingleFile(file, callback) {
const formData = new FormData();
formData.append('file', file);
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
const percentComplete = (e.loaded / e.total) * 100;
updateProgress(percentComplete, `Upload en cours: ${file.name}`);
}
});
xhr.addEventListener('load', function() {
isUploading = false;
try {
const response = JSON.parse(xhr.responseText);
if (xhr.status === 200 && response.success) {
showMessage(response.message, 'success');
callback(true);
} else {
showMessage(response.error || 'Erreur lors de l\'upload', 'error');
callback(false);
}
} catch (e) {
showMessage('Erreur lors de l\'upload', 'error');
callback(false);
}
});
xhr.addEventListener('error', function() {
isUploading = false;
showMessage('Erreur réseau lors de l\'upload', 'error');
callback(false);
});
isUploading = true;
xhr.open('POST', '/upload');
xhr.send(formData);
}
function loadFiles() {
const loading = document.getElementById('loading');
const filesGrid = document.getElementById('filesGrid');
loading.style.display = 'block';
filesGrid.innerHTML = '';
fetch('/api/files')
.then(response => response.json())
.then(data => {
loading.style.display = 'none';
displayFiles(data.files);
updateStats(data.total_files, data.total_size);
})
.catch(error => {
loading.style.display = 'none';
showMessage('Erreur lors du chargement des fichiers', 'error');
console.error('Error:', error);
});
}
function displayFiles(files) {
const filesGrid = document.getElementById('filesGrid');
if (files.length === 0) {
filesGrid.innerHTML = `
<div class="empty-state">
<div class="empty-icon">📭</div>
<h3>Aucun fichier</h3>
<p>Uploadez vos premiers fichiers pour commencer</p>
</div>
`;
return;
}
filesGrid.innerHTML = files.map(file => {
let previewHtml = '';
if (file.is_image && file.thumbnail) {
previewHtml = `
<div class="file-preview" onclick="openPreview('${file.name}', 'image')">
<img src="/thumbnail/${file.thumbnail}" alt="${file.name}" loading="lazy">
</div>
`;
} else if (file.is_video) {
previewHtml = `
<div class="file-preview" onclick="openPreview('${file.name}', 'video')">
<video preload="metadata">
<source src="/preview/${encodeURIComponent(file.name)}" type="video/mp4">
</video>
<div class="video-overlay">
<i class="fas fa-play"></i>
</div>
</div>
`;
} else {
previewHtml = `
<div class="file-preview">
<div class="file-preview-icon">${getFileIcon(file.name)}</div>
</div>
`;
}
return `
<div class="file-card">
${previewHtml}
<div class="file-info">
<div class="file-details">
<h3>${file.name}</h3>
<div class="file-meta">
${file.size}${file.date}
</div>
</div>
</div>
<div class="file-actions">
<button class="btn btn-small btn-download" onclick="downloadFile('${file.name}')">
<i class="fas fa-download"></i> Télécharger
</button>
<button class="btn btn-small btn-delete" onclick="deleteFile('${file.name}')">
<i class="fas fa-trash"></i> Supprimer
</button>
</div>
</div>
`;
}).join('');
}
function getFileIcon(filename) {
const ext = filename.split('.').pop().toLowerCase();
const icons = {
'pdf': '📄',
'doc': '📝', 'docx': '📝',
'xls': '📊', 'xlsx': '📊',
'ppt': '📽️', 'pptx': '📽️',
'txt': '📃',
'jpg': '🖼️', 'jpeg': '🖼️', 'png': '🖼️', 'gif': '🖼️',
'mp3': '🎵', 'wav': '🎵',
'mp4': '🎬', 'avi': '🎬', 'mov': '🎬',
'zip': '📦', 'rar': '📦', '7z': '📦',
'py': '🐍', 'js': '💛', 'html': '🌐', 'css': '🎨'
};
return icons[ext] || '📄';
}
function downloadFile(filename) {
window.open(`/download/${encodeURIComponent(filename)}`, '_blank');
}
function deleteFile(filename) {
if (!confirm(`Êtes-vous sûr de vouloir supprimer "${filename}" ?`)) {
return;
}
fetch(`/delete/${encodeURIComponent(filename)}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
if (data.success) {
showMessage(data.message, 'success');
loadFiles();
} else {
showMessage(data.error, 'error');
}
})
.catch(error => {
showMessage('Erreur lors de la suppression', 'error');
console.error('Error:', error);
});
}
function showProgress() {
document.getElementById('progressContainer').style.display = 'block';
}
function hideProgress() {
document.getElementById('progressContainer').style.display = 'none';
document.getElementById('progressFill').style.width = '0%';
}
function updateProgress(percent, text) {
document.getElementById('progressFill').style.width = percent + '%';
document.getElementById('progressText').textContent = text;
}
function updateStats(totalFiles, totalSize) {
document.getElementById('totalFiles').textContent = totalFiles;
document.getElementById('totalSize').textContent = totalSize;
}
function showMessage(message, type) {
const container = document.getElementById('messageContainer');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
messageDiv.textContent = message;
container.appendChild(messageDiv);
setTimeout(() => {
messageDiv.remove();
}, 5000);
}
// Fonctions de prévisualisation
function openPreview(filename, type) {
const modal = document.getElementById('previewModal');
const modalTitle = document.getElementById('modalTitle');
const modalBody = document.getElementById('modalBody');
modalTitle.textContent = filename;
if (type === 'image') {
modalBody.innerHTML = `<img src="/preview/${encodeURIComponent(filename)}" alt="${filename}">`;
} else if (type === 'video') {
modalBody.innerHTML = `
<video controls autoplay>
<source src="/preview/${encodeURIComponent(filename)}" type="video/mp4">
Votre navigateur ne supporte pas la lecture vidéo.
</video>
`;
}
modal.style.display = 'block';
document.body.style.overflow = 'hidden';
}
function closePreview() {
const modal = document.getElementById('previewModal');
const modalBody = document.getElementById('modalBody');
modal.style.display = 'none';
document.body.style.overflow = 'auto';
modalBody.innerHTML = '';
}
// Fermer la modal en cliquant à l'extérieur
document.getElementById('previewModal').addEventListener('click', function(e) {
if (e.target === this) {
closePreview();
}
});
// Fermer la modal avec la touche Escape
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closePreview();
}
});
// Fonctions d'administration
function toggleAdminPanel() {
const panel = document.getElementById('adminPanel');
if (panel.style.display === 'none' || panel.style.display === '') {
panel.style.display = 'block';
loadUsers();
} else {
panel.style.display = 'none';
}
}
function switchAdminTab(tab) {
// Gérer les onglets
document.querySelectorAll('.admin-tab').forEach(t => t.classList.remove('active'));
document.querySelector(`[onclick="switchAdminTab('${tab}')"]`).classList.add('active');
// Gérer les sections
document.getElementById('add-user-section').style.display = tab === 'add-user' ? 'block' : 'none';
document.getElementById('manage-users-section').style.display = tab === 'manage-users' ? 'block' : 'none';
// Charger les utilisateurs si on va sur l'onglet de gestion
if (tab === 'manage-users') {
loadUsers();
}
}
function loadUsers() {
if (!isAdmin) return;
fetch('/admin/users')
.then(response => response.json())
.then(data => {
const usersList = document.getElementById('usersList');
usersList.innerHTML = data.users.map(user => `
<div class="user-card">
<div class="user-info">
<div class="user-avatar">
${user.username.charAt(0).toUpperCase()}
</div>
<div class="user-details">
<h4>${user.username}</h4>
<div class="user-role">
${user.role === 'admin' ? '👑 Administrateur' : '👤 Utilisateur'}
</div>
</div>
</div>
${user.username !== 'admin' ?
`<button class="btn-delete-user" onclick="deleteUser('${user.username}')">
<i class="fas fa-trash"></i> Supprimer
</button>` :
`<button class="btn-delete-user" disabled>
<i class="fas fa-shield-alt"></i> Protégé
</button>`
}
</div>
`).join('');
})
.catch(error => {
console.error('Erreur lors du chargement des utilisateurs:', error);
showMessage('Erreur lors du chargement des utilisateurs', 'error');
});
}
function addUser() {
const username = document.getElementById('newUsername').value.trim();
const password = document.getElementById('newPassword').value.trim();
const role = document.getElementById('newRole').value;
if (!username || !password) {
showMessage('Nom d\'utilisateur et mot de passe requis', 'error');
return;
}
fetch('/admin/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password,
role: role
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
showMessage(data.message, 'success');
document.getElementById('newUsername').value = '';
document.getElementById('newPassword').value = '';
document.getElementById('newRole').value = 'user';
loadUsers();
} else {
showMessage(data.error, 'error');
}
})
.catch(error => {
showMessage('Erreur lors de l\'ajout de l\'utilisateur', 'error');
console.error('Error:', error);
});
}
function deleteUser(username) {
if (!confirm(`Êtes-vous sûr de vouloir supprimer l'utilisateur "${username}" et tous ses fichiers ?`)) {
return;
}
fetch(`/admin/users/${encodeURIComponent(username)}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
if (data.success) {
showMessage(data.message, 'success');
loadUsers();
} else {
showMessage(data.error, 'error');
}
})
.catch(error => {
showMessage('Erreur lors de la suppression de l\'utilisateur', 'error');
console.error('Error:', error);
});
}
// Reset file input après upload
function resetFileInput() {
document.getElementById('fileInput').value = '';
}
</script>
</body>
</html>