This commit is contained in:
Joris Bertomeu
2025-08-19 16:34:19 +02:00
commit 5c6da90f98
33 changed files with 8066 additions and 0 deletions

119
public/css/style.css Normal file
View File

@@ -0,0 +1,119 @@
/* Styles personnalisés pour Mail Notifier */
/* Styles globaux */
body {
background-color: #f8f9fc;
font-family: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
/* Sidebar */
.sidebar {
min-height: 100vh;
}
/* Styles pour les cartes */
.card {
margin-bottom: 24px;
border: none;
box-shadow: 0 0.15rem 1.75rem 0 rgba(58, 59, 69, 0.15);
}
.card .card-header {
background-color: #f8f9fc;
border-bottom: 1px solid #e3e6f0;
}
.card-body {
padding: 1.25rem;
}
/* Styles pour les bordures colorées */
.border-left-primary {
border-left: 0.25rem solid #4e73df !important;
}
.border-left-success {
border-left: 0.25rem solid #1cc88a !important;
}
.border-left-warning {
border-left: 0.25rem solid #f6c23e !important;
}
.border-left-danger {
border-left: 0.25rem solid #e74a3b !important;
}
/* Styles pour le tableau de bord */
.dashboard-card {
position: relative;
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border: 1px solid #e3e6f0;
border-radius: 0.35rem;
}
/* Styles pour la page de connexion */
.login-page {
background-color: #4e73df;
background-image: linear-gradient(180deg, #4e73df 10%, #224abe 100%);
background-size: cover;
}
/* Styles pour les tableaux */
.table-responsive {
overflow-x: auto;
}
.table-hover tbody tr:hover {
background-color: rgba(0, 0, 0, 0.075);
}
/* Styles pour les boutons d'action */
.btn-group .btn {
margin-right: 0.25rem;
}
.btn-group form {
display: inline-block;
}
/* Styles pour le contenu des emails */
.email-content-html {
border: 1px solid #e3e6f0;
border-radius: 0.35rem;
overflow: hidden;
}
.text-content {
font-family: monospace;
white-space: pre-wrap;
background-color: #f8f9fc;
border-radius: 0.35rem;
padding: 1rem;
}
/* Styles pour les formulaires */
.form-text {
color: #858796;
}
/* Styles responsive */
@media (max-width: 768px) {
.ms-auto {
margin-left: 0 !important;
}
.col-lg-2 {
display: none;
}
.col-lg-10 {
flex: 0 0 100%;
max-width: 100%;
}
}

159
public/js/main.js Normal file
View File

@@ -0,0 +1,159 @@
/**
* Fichier JavaScript principal pour l'application Mail Notifier
*/
document.addEventListener('DOMContentLoaded', function() {
// Fermeture automatique des alertes après 5 secondes
setTimeout(function() {
const alerts = document.querySelectorAll('.alert');
alerts.forEach(function(alert) {
const bsAlert = new bootstrap.Alert(alert);
bsAlert.close();
});
}, 5000);
// Activer les tooltips Bootstrap
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// Gestionnaire d'événements pour la confirmation de suppression
const deleteForms = document.querySelectorAll('form[data-confirm]');
deleteForms.forEach(function(form) {
form.addEventListener('submit', function(event) {
const message = form.getAttribute('data-confirm') || 'Êtes-vous sûr de vouloir effectuer cette action?';
if (!confirm(message)) {
event.preventDefault();
}
});
});
// Affichage du temps écoulé depuis la réception des emails
const timestampElements = document.querySelectorAll('.timestamp');
timestampElements.forEach(function(element) {
const timestamp = new Date(element.getAttribute('data-timestamp'));
element.textContent = timeAgo(timestamp);
});
// Mise à jour automatique du tableau de bord
if (document.querySelector('#dashboard-content')) {
setInterval(refreshDashboard, 60000); // Actualiser toutes les minutes
}
// Fonction pour tester la configuration Pushover
const testPushoverBtn = document.getElementById('testPushover');
if (testPushoverBtn) {
testPushoverBtn.addEventListener('click', function() {
const user = document.getElementById('pushoverUser').value;
const token = document.getElementById('pushoverToken').value;
if (!user || !token) {
alert('Veuillez d\'abord configurer votre clé utilisateur et votre token d\'application Pushover.');
return;
}
testPushoverBtn.disabled = true;
testPushoverBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Envoi en cours...';
// Le formulaire est soumis par un événement onclick dans le HTML
});
}
});
/**
* Convertit une date en texte "il y a X temps"
* @param {Date} date - La date à convertir
* @returns {string} - Le texte formaté
*/
function timeAgo(date) {
const seconds = Math.floor((new Date() - date) / 1000);
let interval = Math.floor(seconds / 31536000);
if (interval > 1) {
return 'il y a ' + interval + ' ans';
}
if (interval === 1) {
return 'il y a 1 an';
}
interval = Math.floor(seconds / 2592000);
if (interval > 1) {
return 'il y a ' + interval + ' mois';
}
if (interval === 1) {
return 'il y a 1 mois';
}
interval = Math.floor(seconds / 86400);
if (interval > 1) {
return 'il y a ' + interval + ' jours';
}
if (interval === 1) {
return 'hier';
}
interval = Math.floor(seconds / 3600);
if (interval > 1) {
return 'il y a ' + interval + ' heures';
}
if (interval === 1) {
return 'il y a 1 heure';
}
interval = Math.floor(seconds / 60);
if (interval > 1) {
return 'il y a ' + interval + ' minutes';
}
if (interval === 1) {
return 'il y a 1 minute';
}
return 'à l\'instant';
}
/**
* Actualise le contenu du tableau de bord
*/
function refreshDashboard() {
fetch('/api/emails?limit=5')
.then(response => response.json())
.then(data => {
// Mettre à jour les compteurs
const totalCount = data.length;
const unreadCount = data.filter(email => !email.read).length;
document.getElementById('total-count').textContent = totalCount;
document.getElementById('unread-count').textContent = unreadCount;
// Mettre à jour la liste des derniers emails
const emailsList = document.getElementById('latest-emails');
if (emailsList && data.length > 0) {
let html = '';
data.forEach(email => {
const date = new Date(email.receivedAt).toLocaleString();
const status = email.read
? '<span class="badge bg-success">Lu</span>'
: '<span class="badge bg-warning">Non lu</span>';
html += `
<tr>
<td>${date}</td>
<td>${email.from}</td>
<td>${email.subject}</td>
<td>${status}</td>
<td>
<a href="/emails/${email.id}" class="btn btn-sm btn-info">
<i class="fas fa-eye"></i>
</a>
</td>
</tr>
`;
});
emailsList.innerHTML = html;
}
})
.catch(error => console.error('Erreur lors de l\'actualisation du tableau de bord:', error));
}