289 lines
13 KiB
HTML
289 lines
13 KiB
HTML
{% extends "layouts/base.html" %}
|
|
|
|
{% block title %}Résultats du scraping{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1 class="h3 mb-0">Résultats du scraping</h1>
|
|
<a href="{{ url_for('email_scraper_page') }}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left"></i> Retour
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Informations générales -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h3 class="text-primary">{{ results.contacts|length }}</h3>
|
|
<p class="text-muted mb-0">Contacts trouvés</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h3 class="text-info">{{ results.pages_scraped|length }}</h3>
|
|
<p class="text-muted mb-0">Pages scrapées</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h3 class="text-warning">{{ results.errors|length }}</h3>
|
|
<p class="text-muted mb-0">Erreurs</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<small class="text-muted">Durée</small>
|
|
<p class="mb-0">
|
|
{% if results.start_time and results.end_time %}
|
|
{% set start = results.start_time | parse_datetime %}
|
|
{% set end = results.end_time | parse_datetime %}
|
|
{{ ((end - start).total_seconds() / 60) | round(1) }} min
|
|
{% else %}
|
|
N/A
|
|
{% endif %}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- URL source -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">URL source</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<a href="{{ results.url }}" target="_blank" class="text-decoration-none">
|
|
{{ results.url }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Contacts trouvés -->
|
|
{% if results.contacts %}
|
|
<div class="card mb-4">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h5 class="card-title mb-0">Contacts trouvés ({{ results.contacts|length }})</h5>
|
|
<div>
|
|
<button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAllContacts()">
|
|
Tout sélectionner
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-primary" onclick="createProspectsFromSelected()">
|
|
Créer prospects sélectionnés
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th width="40"></th>
|
|
<th>Email</th>
|
|
<th>Nom</th>
|
|
<th>Entreprise</th>
|
|
<th>Téléphone</th>
|
|
<th>Localité</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for contact in results.contacts %}
|
|
<tr>
|
|
<td>
|
|
<div class="form-check">
|
|
<input class="form-check-input contact-checkbox" type="checkbox"
|
|
value="{{ contact.email }}" id="contact_{{ loop.index }}">
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<strong>{{ contact.email }}</strong>
|
|
</td>
|
|
<td>
|
|
{% if contact.first_name or contact.last_name %}
|
|
{{ contact.first_name }} {{ contact.last_name }}
|
|
{% elif contact.name %}
|
|
{{ contact.name }}
|
|
{% else %}
|
|
<span class="text-muted">-</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if contact.company %}
|
|
{{ contact.company }}
|
|
{% else %}
|
|
<span class="text-muted">-</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if contact.phone %}
|
|
{{ contact.phone }}
|
|
{% else %}
|
|
<span class="text-muted">-</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if contact.location %}
|
|
{{ contact.location }}
|
|
{% else %}
|
|
<span class="text-muted">-</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Pages scrapées -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">Pages scrapées ({{ results.pages_scraped|length }})</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>URL</th>
|
|
<th>Niveau</th>
|
|
<th>Contacts trouvés</th>
|
|
<th>Statut</th>
|
|
<th>Heure</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for page in results.pages_scraped %}
|
|
<tr class="{% if page.status == 'error' %}table-danger{% endif %}">
|
|
<td>
|
|
<a href="{{ page.url }}" target="_blank" class="text-decoration-none">
|
|
{{ page.url[:60] }}{% if page.url|length > 60 %}...{% endif %}
|
|
</a>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-secondary">{{ page.depth }}</span>
|
|
</td>
|
|
<td>
|
|
{% if page.contacts_found %}
|
|
<span class="badge bg-primary">{{ page.contacts_found }}</span>
|
|
{% if page.contacts and page.contacts|length > 0 %}
|
|
<small class="text-muted d-block">
|
|
{% for contact in page.contacts[:3] %}
|
|
{{ contact.email }}{% if not loop.last %}, {% endif %}
|
|
{% endfor %}
|
|
{% if page.contacts|length > 3 %}...{% endif %}
|
|
</small>
|
|
{% endif %}
|
|
{% else %}
|
|
<span class="badge bg-light text-dark">0</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
{% if page.status == 'success' %}
|
|
<span class="badge bg-success">Succès</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">Erreur</span>
|
|
{% if page.error %}
|
|
<small class="text-danger d-block">{{ page.error }}</small>
|
|
{% endif %}
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<small class="text-muted">
|
|
{{ page.timestamp | datetime('%H:%M:%S') }}
|
|
</small>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Erreurs -->
|
|
{% if results.errors %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0 text-danger">Erreurs ({{ results.errors|length }})</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% for error in results.errors %}
|
|
<div class="alert alert-danger mb-2">{{ error }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function selectAllContacts() {
|
|
const checkboxes = document.querySelectorAll('.contact-checkbox');
|
|
const allChecked = Array.from(checkboxes).every(cb => cb.checked);
|
|
|
|
checkboxes.forEach(cb => {
|
|
cb.checked = !allChecked;
|
|
});
|
|
}
|
|
|
|
function createProspectsFromSelected() {
|
|
const selectedEmails = Array.from(document.querySelectorAll('.contact-checkbox:checked'))
|
|
.map(cb => cb.value);
|
|
|
|
if (selectedEmails.length === 0) {
|
|
alert('Veuillez sélectionner au moins un contact');
|
|
return;
|
|
}
|
|
|
|
if (!confirm(`Créer ${selectedEmails.length} prospect(s) à partir des contacts sélectionnés ?`)) {
|
|
return;
|
|
}
|
|
|
|
fetch('/api/scraping/create_prospects', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
filename: '{{ filename }}',
|
|
emails: selectedEmails
|
|
})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
let message = `${data.created} prospect(s) créé(s) avec succès`;
|
|
if (data.existing > 0) {
|
|
message += ` (${data.existing} contact(s) déjà existant(s))`;
|
|
}
|
|
alert(message);
|
|
|
|
// Décocher les contacts traités
|
|
document.querySelectorAll('.contact-checkbox:checked').forEach(cb => {
|
|
cb.checked = false;
|
|
});
|
|
} else {
|
|
alert(`Erreur: ${data.error}`);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Erreur:', error);
|
|
alert('Erreur lors de la création des prospects');
|
|
});
|
|
}
|
|
</script>
|
|
{% endblock %}
|