2026-08-14 18:02:25 +02:00
|
|
|
{% extends "base.html" %}
|
|
|
|
|
|
|
|
|
|
{% block title %}Derniers mails Outlook - GMAO Collège{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block content %}
|
|
|
|
|
<div class="container-fluid">
|
|
|
|
|
<div class="row mb-4">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
|
|
|
<div>
|
|
|
|
|
<h1>📧 Derniers mails</h1>
|
|
|
|
|
<p class="text-muted">
|
|
|
|
|
Compte: {{ account.email }}
|
|
|
|
|
{% if account.last_connected_at %}
|
2026-08-15 00:47:55 +02:00
|
|
|
| Dernière synchronisation: {{ account.last_connected_at|datetime_fmt }}
|
2026-08-14 18:02:25 +02:00
|
|
|
{% endif %}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<button onclick="syncMails({{ account.id }})" class="btn btn-primary">
|
|
|
|
|
<i class="fas fa-sync"></i> Synchroniser
|
|
|
|
|
</button>
|
|
|
|
|
<a href="{{ url_for('outlook_dashboard.dashboard') }}" class="btn btn-outline-secondary">
|
|
|
|
|
<i class="fas fa-arrow-left"></i> Retour
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Barre de contrôle -->
|
|
|
|
|
<div class="row mb-3">
|
|
|
|
|
<div class="col">
|
|
|
|
|
<div class="card">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<div class="row align-items-center">
|
|
|
|
|
<div class="col-md-6">
|
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
|
<button onclick="location.reload()" class="btn btn-outline-primary">
|
|
|
|
|
<i class="fas fa-sync"></i> Actualiser
|
|
|
|
|
</button>
|
|
|
|
|
<button onclick="markAllAsRead()" class="btn btn-outline-success">
|
|
|
|
|
<i class="fas fa-check"></i> Marquer tout comme lu
|
|
|
|
|
</button>
|
|
|
|
|
<button onclick="deleteSelected()" class="btn btn-outline-danger">
|
|
|
|
|
<i class="fas fa-trash"></i> Supprimer sélectionnés
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-md-6">
|
|
|
|
|
<div class="input-group">
|
|
|
|
|
<input type="text" class="form-control" id="searchInput"
|
|
|
|
|
placeholder="Rechercher dans les sujets ou expéditeurs...">
|
|
|
|
|
<button class="btn btn-outline-primary" onclick="searchMails()">
|
|
|
|
|
<i class="fas fa-search"></i>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Liste des mails -->
|
|
|
|
|
<div class="row">
|
|
|
|
|
<div class="col-12">
|
|
|
|
|
<div class="card">
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
<h5 class="mb-0">
|
|
|
|
|
Liste des mails ({{ mails|length }} mails)
|
|
|
|
|
<small class="text-muted">
|
|
|
|
|
Affichant les {{ limit }} derniers mails
|
|
|
|
|
</small>
|
|
|
|
|
</h5>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
{% if mails %}
|
|
|
|
|
<div class="table-responsive">
|
|
|
|
|
<table class="table table-hover" id="mailsTable">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th width="30">
|
|
|
|
|
<input type="checkbox" id="selectAll" onchange="toggleSelectAll()">
|
|
|
|
|
</th>
|
|
|
|
|
<th>Expéditeur</th>
|
|
|
|
|
<th>Sujet</th>
|
|
|
|
|
<th>Date</th>
|
|
|
|
|
<th>Statut</th>
|
|
|
|
|
<th>Pièces jointes</th>
|
|
|
|
|
<th>Actions</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{% for mail in mails %}
|
|
|
|
|
<tr>
|
|
|
|
|
<td>
|
|
|
|
|
<input type="checkbox" class="mail-checkbox" value="{{ mail.id }}">
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
<div>
|
|
|
|
|
<strong>{{ mail.sender|truncate(30, true) }}</strong>
|
|
|
|
|
{% if mail.sender_email %}
|
|
|
|
|
<br><small class="text-muted">{{ mail.sender_email }}</small>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
<a href="{{ url_for('outlook_pages.mail_view', account_id=mail.account_id, mail_id=mail.id) }}"
|
|
|
|
|
class="text-decoration-none">
|
|
|
|
|
{% if mail.is_read %}
|
|
|
|
|
<span class="text-muted">{{ mail.subject|truncate(60, true) }}</span>
|
|
|
|
|
{% else %}
|
|
|
|
|
<strong>{{ mail.subject|truncate(60, true) }}</strong>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</a>
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
2026-08-15 00:47:55 +02:00
|
|
|
<small>{{ mail.received_at|datetime_fmt }}</small>
|
2026-08-14 18:02:25 +02:00
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
{% if mail.importance == 'high' %}
|
|
|
|
|
<span class="badge bg-danger">Urgent</span>
|
|
|
|
|
{% elif mail.importance == 'low' %}
|
|
|
|
|
<span class="badge bg-secondary">Faible</span>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="badge bg-info">Normal</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
{% if mail.has_attachments %}
|
|
|
|
|
<span class="badge bg-warning">
|
|
|
|
|
<i class="fas fa-paperclip"></i> {{ mail.attachment_count }}
|
|
|
|
|
</span>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="text-muted">-</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
<div class="btn-group btn-group-sm">
|
|
|
|
|
<a href="{{ url_for('outlook_pages.mail_view', account_id=mail.account_id, mail_id=mail.id) }}"
|
|
|
|
|
class="btn btn-outline-primary" title="Voir">
|
|
|
|
|
<i class="fas fa-eye"></i>
|
|
|
|
|
</a>
|
|
|
|
|
{% if not mail.is_read %}
|
|
|
|
|
<button onclick="markAsRead({{ mail.id }})"
|
|
|
|
|
class="btn btn-outline-success" title="Marquer comme lu">
|
|
|
|
|
<i class="fas fa-check"></i>
|
|
|
|
|
</button>
|
|
|
|
|
{% endif %}
|
|
|
|
|
<button onclick="deleteMail({{ mail.id }})"
|
|
|
|
|
class="btn btn-outline-danger" title="Supprimer">
|
|
|
|
|
<i class="fas fa-trash"></i>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Pagination -->
|
|
|
|
|
<nav aria-label="Pagination" class="mt-3">
|
|
|
|
|
<ul class="pagination justify-content-center">
|
|
|
|
|
<li class="page-item disabled">
|
|
|
|
|
<a class="page-link" href="#" tabindex="-1">Précédent</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li class="page-item active">
|
|
|
|
|
<a class="page-link" href="#">1</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li class="page-item disabled">
|
|
|
|
|
<a class="page-link" href="#">Suivant</a>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</nav>
|
|
|
|
|
{% else %}
|
|
|
|
|
<div class="text-center py-4">
|
|
|
|
|
<i class="fas fa-inbox fa-3x text-muted mb-3"></i>
|
|
|
|
|
<h5>Aucun mail trouvé</h5>
|
|
|
|
|
<p class="text-muted">
|
|
|
|
|
{% if account.last_connected_at %}
|
|
|
|
|
Aucun mail n'a été synchronisé depuis la dernière connexion.
|
|
|
|
|
{% else %}
|
|
|
|
|
Le compte n'a jamais été synchronisé.
|
|
|
|
|
{% endif %}
|
|
|
|
|
</p>
|
|
|
|
|
<button onclick="syncMails({{ account.id }})" class="btn btn-primary">
|
|
|
|
|
<i class="fas fa-sync"></i> Synchroniser maintenant
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% block scripts %}
|
|
|
|
|
<script>
|
|
|
|
|
function syncMails(accountId) {
|
|
|
|
|
if (confirm('Synchroniser les nouveaux mails ?')) {
|
2026-08-14 20:55:47 +02:00
|
|
|
fetch(`/outlook/api/sync-mails/${accountId}`, {method: 'POST'})
|
2026-08-14 18:02:25 +02:00
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
|
|
|
|
if (data.success) {
|
|
|
|
|
alert(data.message);
|
|
|
|
|
location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('Erreur: ' + data.error);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
alert('Erreur réseau: ' + error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function markAsRead(mailId) {
|
|
|
|
|
fetch(`/outlook/api/mark-read/${mailId}`, {
|
|
|
|
|
method: 'POST'
|
|
|
|
|
})
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
|
|
|
|
if (data.success) {
|
|
|
|
|
location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('Erreur: ' + data.error);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
alert('Erreur réseau: ' + error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function markAllAsRead() {
|
|
|
|
|
if (confirm('Marquer tous les mails comme lus ?')) {
|
|
|
|
|
fetch(`/outlook/api/mark-all-read/{{ account.id }}`, {
|
|
|
|
|
method: 'POST'
|
|
|
|
|
})
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
|
|
|
|
if (data.success) {
|
|
|
|
|
location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('Erreur: ' + data.error);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
alert('Erreur réseau: ' + error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function deleteMail(mailId) {
|
|
|
|
|
if (confirm('Supprimer ce mail ?')) {
|
|
|
|
|
fetch(`/outlook/api/delete-mail/${mailId}`, {
|
|
|
|
|
method: 'DELETE'
|
|
|
|
|
})
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
|
|
|
|
if (data.success) {
|
|
|
|
|
location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('Erreur: ' + data.error);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
alert('Erreur réseau: ' + error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function deleteSelected() {
|
|
|
|
|
const selected = document.querySelectorAll('.mail-checkbox:checked');
|
|
|
|
|
if (selected.length === 0) {
|
|
|
|
|
alert('Veuillez sélectionner au moins un mail');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (confirm(`Supprimer ${selected.length} mail(s) sélectionné(s) ?`)) {
|
|
|
|
|
const ids = Array.from(selected).map(cb => cb.value);
|
|
|
|
|
fetch(`/outlook/api/delete-selected`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({ mail_ids: ids })
|
|
|
|
|
})
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
.then(data => {
|
|
|
|
|
if (data.success) {
|
|
|
|
|
alert(`${data.deleted_count} mail(s) supprimé(s)`);
|
|
|
|
|
location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
alert('Erreur: ' + data.error);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
alert('Erreur réseau: ' + error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toggleSelectAll() {
|
|
|
|
|
const selectAll = document.getElementById('selectAll').checked;
|
|
|
|
|
const checkboxes = document.querySelectorAll('.mail-checkbox');
|
|
|
|
|
checkboxes.forEach(cb => cb.checked = selectAll);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function searchMails() {
|
|
|
|
|
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
|
|
|
|
const rows = document.querySelectorAll('#mailsTable tbody tr');
|
|
|
|
|
|
|
|
|
|
rows.forEach(row => {
|
|
|
|
|
const subject = row.cells[2].textContent.toLowerCase();
|
|
|
|
|
const sender = row.cells[1].textContent.toLowerCase();
|
|
|
|
|
|
|
|
|
|
if (subject.includes(searchTerm) || sender.includes(searchTerm)) {
|
|
|
|
|
row.style.display = '';
|
|
|
|
|
} else {
|
|
|
|
|
row.style.display = 'none';
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Recherche en temps réel
|
|
|
|
|
document.getElementById('searchInput').addEventListener('input', searchMails);
|
|
|
|
|
</script>
|
2026-08-14 20:55:47 +02:00
|
|
|
{% endblock %}
|