2025-09-01 18:28:23 +02:00
|
|
|
{% extends 'base.html.twig' %}
|
|
|
|
|
|
|
|
{% block title %}Comparaison Wiki OSM - {{ key }}{% endblock %}
|
|
|
|
|
|
|
|
{% block body %}
|
|
|
|
<style>
|
|
|
|
|
|
|
|
.limited-height-table {
|
|
|
|
max-height: 80vh;
|
|
|
|
overflow-y: auto;
|
|
|
|
display: block;
|
|
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.grammalecte-emphasis {
|
|
|
|
text-decoration: underline;
|
|
|
|
text-decoration-style: wavy;
|
|
|
|
text-decoration-color: #ff0766;
|
|
|
|
background: #ece5e5;
|
|
|
|
border-radius: 3px;
|
|
|
|
padding: 3px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.section-title,
|
|
|
|
.suggestion-before, .suggestion-after {
|
|
|
|
cursor: pointer;
|
|
|
|
min-width: 80%;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
|
|
|
|
|
|
|
.section-title:hover,
|
|
|
|
.suggestion-before:hover, .suggestion-after:hover {
|
|
|
|
color: #d1e7dd;
|
|
|
|
background: #0f5132;
|
|
|
|
}
|
|
|
|
|
|
|
|
.suggestion-correction {
|
|
|
|
color: #0f5132;
|
|
|
|
background: #d1e7dd;
|
|
|
|
border-radius: 3px;
|
|
|
|
padding: 3px;
|
|
|
|
display: block;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
.suggestion-correction:hover {
|
|
|
|
color: #d1e7dd;
|
|
|
|
background: #0f5132;
|
|
|
|
}
|
|
|
|
|
|
|
|
.comparaison-sections .card-body li {
|
|
|
|
min-height: 40px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.card:hover {
|
|
|
|
transform: none !important;
|
|
|
|
box-shadow: none !important;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title-level-1 {
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title-level-2 {
|
|
|
|
padding-left: 1.5rem;
|
|
|
|
opacity: 0.8;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title-level-3 {
|
|
|
|
padding-left: 2.8rem;
|
|
|
|
opacity: 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title-level-4 {
|
|
|
|
padding-left: 4rem;
|
|
|
|
opacity: 0.4;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title-level-5 {
|
|
|
|
padding-left: 5.2rem;
|
|
|
|
opacity: 0.3;
|
|
|
|
}
|
|
|
|
|
|
|
|
.title-level-6 {
|
|
|
|
padding-left: 6.4rem;
|
|
|
|
font-size: 0.9rem;
|
|
|
|
opacity: 0.2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Style for placeholder sections */
|
|
|
|
.list-group-item-warning.title-level-2,
|
|
|
|
.list-group-item-warning.title-level-3,
|
|
|
|
.list-group-item-warning.title-level-4,
|
|
|
|
.list-group-item-warning.title-level-5,
|
|
|
|
.list-group-item-warning.title-level-6 {
|
|
|
|
border-left: 4px solid #ffc107;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make placeholder text more visible */
|
|
|
|
.text-muted.fst-italic {
|
|
|
|
color: #dc3545 !important;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
<div class="container mt-4">
|
|
|
|
|
2025-09-08 10:20:51 +02:00
|
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
|
|
<div>
|
|
|
|
{% if prev_page is defined and prev_page is not null %}
|
|
|
|
<a href="{{ path('app_admin_wiki_compare', {'key': prev_page.key}) }}" class="btn btn-outline-primary">
|
|
|
|
<i class="bi bi-arrow-left"></i> Page précédente: {{ prev_page.key }}
|
|
|
|
</a>
|
|
|
|
{% else %}
|
|
|
|
<button class="btn btn-outline-secondary" disabled>
|
|
|
|
<i class="bi bi-arrow-left"></i> Pas de page précédente
|
|
|
|
</button>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
{% if next_page is defined and next_page is not null %}
|
|
|
|
<a href="{{ path('app_admin_wiki_compare', {'key': next_page.key}) }}" class="btn btn-outline-primary">
|
|
|
|
Page suivante: {{ next_page.key }} <i class="bi bi-arrow-right"></i>
|
|
|
|
</a>
|
|
|
|
{% else %}
|
|
|
|
<button class="btn btn-outline-secondary" disabled>
|
|
|
|
Pas de page suivante <i class="bi bi-arrow-right"></i>
|
|
|
|
</button>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-09-01 18:28:23 +02:00
|
|
|
|
2025-09-08 10:20:51 +02:00
|
|
|
<h1>Comparaison Wiki OpenStreetMap - {{ key }}
|
2025-09-01 18:28:23 +02:00
|
|
|
{% if en_page.is_specific_page is defined and en_page.is_specific_page %}
|
|
|
|
<a href="{{ fr_page.url|default('https://wiki.openstreetmap.org/wiki/FR:' ~ key) }}">fr</a>
|
|
|
|
<a href="{{ en_page.url }}">en</a>
|
|
|
|
{% else %}
|
2025-09-03 17:18:21 +02:00
|
|
|
<a href="https://wiki.openstreetmap.org/wiki/FR:{{ key }}">fr</a>
|
|
|
|
<a href="https://wiki.openstreetmap.org/wiki/{{ key }}">en</a>
|
2025-09-01 18:28:23 +02:00
|
|
|
{% endif %}
|
|
|
|
</h1>
|
|
|
|
|
|
|
|
<p class="lead">
|
|
|
|
{% if en_page.is_specific_page is defined and en_page.is_specific_page %}
|
|
|
|
Comparaison détaillée des pages wiki en français et en anglais pour "{{ key }}".
|
|
|
|
{% else %}
|
|
|
|
Comparaison détaillée des pages wiki en français et en anglais pour la clé OSM "{{ key }}".
|
|
|
|
{% endif %}
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<div id="illustrations" class="row mb-4">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h3>Page anglaise</h3>
|
|
|
|
</div>
|
|
|
|
<div class="card-body text-center">
|
|
|
|
{% if en_page.description_img_url is defined and en_page.description_img_url %}
|
|
|
|
<img src="{{ en_page.description_img_url }}" alt="{{ key }}" class="img-fluid"
|
|
|
|
style="max-height: 200px; object-fit: contain;">
|
|
|
|
{% else %}
|
|
|
|
<div class="alert alert-secondary">Pas d'image d'illustration</div>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h3>Page française</h3>
|
|
|
|
</div>
|
|
|
|
<div class="card-body text-center">
|
|
|
|
{% if fr_page is defined and fr_page is not null and fr_page.description_img_url is defined and fr_page.description_img_url %}
|
|
|
|
<img src="{{ fr_page.description_img_url }}" alt="{{ key }}" class="img-fluid"
|
|
|
|
style="max-height: 200px; object-fit: contain;">
|
|
|
|
{% else %}
|
|
|
|
<div class="alert alert-secondary">Pas d'image d'illustration</div>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-09-08 10:20:51 +02:00
|
|
|
{% if history_data is defined and history_data is not empty %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-success text-white">
|
|
|
|
<h2>Évolution du classement</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-12">
|
|
|
|
<canvas id="rankingEvolutionChart" width="800" height="300"></canvas>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="row mt-3">
|
|
|
|
<div class="col-md-12">
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Date</th>
|
|
|
|
<th>Score de décrépitude</th>
|
|
|
|
<th>Différence de mots</th>
|
|
|
|
<th>Différence de sections</th>
|
|
|
|
<th>Différence de liens</th>
|
|
|
|
<th>Différence d'images</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for entry in history_data %}
|
|
|
|
<tr>
|
|
|
|
<td>{{ entry.date }}</td>
|
|
|
|
<td>
|
|
|
|
<div class="progress" style="height: 20px;">
|
|
|
|
{% set score = entry.metrics.staleness_score %}
|
|
|
|
{% set score_class = score > 70 ? 'bg-danger' : (score > 40 ? 'bg-warning' : 'bg-success') %}
|
|
|
|
<div class="progress-bar {{ score_class }}" role="progressbar"
|
|
|
|
style="width: {{ score }}%;"
|
|
|
|
aria-valuenow="{{ score }}"
|
|
|
|
aria-valuemin="0"
|
|
|
|
aria-valuemax="100">
|
|
|
|
{{ score }}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
<td>{{ entry.metrics.word_diff }}</td>
|
|
|
|
<td>{{ entry.metrics.section_diff }}</td>
|
|
|
|
<td>{{ entry.metrics.link_diff }}</td>
|
|
|
|
<td>{{ entry.metrics.media_diff }}</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
2025-09-09 16:03:24 +02:00
|
|
|
{# <hr>#}
|
|
|
|
{# <pre>#}
|
|
|
|
{# {{ dump(staleness_distribution) }}#}
|
|
|
|
{# </pre>#}
|
|
|
|
{# <pre>#}
|
|
|
|
{# {{ dump(en_sections) }}#}
|
|
|
|
{# </pre>#}
|
|
|
|
{# <pre>#}
|
|
|
|
{# {{ dump(fr_sections) }}#}
|
|
|
|
{# </pre>#}
|
|
|
|
{# <hr>#}
|
2025-09-01 18:28:23 +02:00
|
|
|
{# suggestions de grammalecte #}
|
|
|
|
{% if fr_page is defined and fr_page is not null %}
|
|
|
|
{% if detailed_comparison is defined and detailed_comparison is not null and detailed_comparison.section_comparison is defined and detailed_comparison.section_comparison is not null %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Comparaison des sections</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body comparaison-sections">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h3>Sections en anglais</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.adjusted_en_section_count is defined %}
|
|
|
|
{{ detailed_comparison.adjusted_en_section_count }} sections ({{ en_page.sections|default(0) }} avec "Contents")
|
|
|
|
{% else %}
|
|
|
|
{{ en_page.sections|default(0) }} sections
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group mb-3">
|
|
|
|
{% if detailed_comparison['section_comparison']['en_only'] is defined and detailed_comparison['section_comparison']['en_only'] is iterable %}
|
|
|
|
{% for section in detailed_comparison['section_comparison']['en_only'] %}
|
|
|
|
<li class="list-group-item title-level-{{ section.level|default(1) }}">
|
|
|
|
<span class="badge bg-secondary pull-right">h{{ section.level|default(1) }}</span>
|
|
|
|
{% if section.title is defined and section.title is not empty %}
|
|
|
|
<span class="section-title">{{ section.title }}</span>
|
|
|
|
{% endif %}
|
|
|
|
</li>
|
|
|
|
{% endfor %}
|
|
|
|
{% endif %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h3>Sections en français</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.adjusted_fr_section_count is defined %}
|
|
|
|
{{ detailed_comparison.adjusted_fr_section_count }} sections ({{ fr_page.sections|default(0) }} avec "Sommaire")
|
|
|
|
{% else %}
|
|
|
|
{{ fr_page.sections|default(0) }} sections
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group mb-3">
|
|
|
|
{% if detailed_comparison['section_comparison']['fr_only'] is defined and detailed_comparison['section_comparison']['fr_only'] is iterable %}
|
|
|
|
{% for section in detailed_comparison['section_comparison']['fr_only'] %}
|
|
|
|
<li class="list-group-item title-level-{{ section.level|default(1) }}">
|
|
|
|
<span class="badge bg-secondary pull-right">h{{ section.level|default(1) }}</span>
|
|
|
|
{% if section.title is defined and section.title is not empty %}
|
|
|
|
<span class="section-title">{{ section.title }}</span>
|
|
|
|
{% endif %}
|
|
|
|
</li>
|
|
|
|
{% endfor %}
|
|
|
|
{% endif %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-09-08 10:20:51 +02:00
|
|
|
<div class="row mt-4">
|
|
|
|
<div class="col-12">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-success text-white">
|
|
|
|
<h3>Sections communes</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison['section_comparison']['common'] is defined %}
|
|
|
|
{{ detailed_comparison['section_comparison']['common']|length }} sections communes
|
|
|
|
{% else %}
|
|
|
|
0 sections communes
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th class="bg-primary text-white">Section anglaise</th>
|
|
|
|
<th class="bg-info text-white">Section française</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% if detailed_comparison['section_comparison']['common'] is defined and detailed_comparison['section_comparison']['common'] is iterable %}
|
|
|
|
{% for section in detailed_comparison['section_comparison']['common'] %}
|
|
|
|
<tr>
|
|
|
|
<td class="title-level-{{ section.en.level|default(1) }}">
|
|
|
|
<span class="badge bg-secondary">h{{ section.en.level|default(1) }}</span>
|
|
|
|
{% if section.en.title is defined and section.en.title is not empty %}
|
|
|
|
<span class="section-title">{{ section.en.title }}</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
<td class="title-level-{{ section.fr.level|default(1) }}">
|
|
|
|
<span class="badge bg-secondary">h{{ section.fr.level|default(1) }}</span>
|
|
|
|
{% if section.fr.title is defined and section.fr.title is not empty %}
|
|
|
|
<span class="section-title">{{ section.fr.title }}</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<tr>
|
|
|
|
<td colspan="2" class="text-center">Aucune section commune trouvée</td>
|
|
|
|
</tr>
|
|
|
|
{% endif %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-09-01 18:28:23 +02:00
|
|
|
<div class="text-center mt-3">
|
|
|
|
{% if detailed_comparison is defined and detailed_comparison is not null and detailed_comparison.section_comparison is defined and detailed_comparison.section_comparison is not null %}
|
|
|
|
<button class="btn btn-outline-secondary copy-btn" data-content="different-sections">
|
|
|
|
<i class="bi bi-clipboard"></i> Copier les titres de sections différentes
|
|
|
|
</button>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
{% if fr_page is defined and fr_page is not null and detailed_comparison['grammar_suggestions'] is defined and detailed_comparison['grammar_suggestions'] is not null and detailed_comparison['grammar_suggestions']|length > 0 %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
|
|
<h2>Suggestions de corrections grammaticales</h2>
|
|
|
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal"
|
|
|
|
data-bs-target="#allCorrectionsModal">
|
|
|
|
Voir toutes les corrections
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="alert alert-info">
|
|
|
|
<p><i class="bi bi-info-circle"></i> Ces suggestions sont générées automatiquement par l'outil
|
|
|
|
Grammalecte et peuvent contenir des erreurs.</p>
|
|
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-bordered limited-height-table">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Texte</th>
|
|
|
|
<th>Message</th>
|
|
|
|
<th>Suggestions</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for suggestion in detailed_comparison['grammar_suggestions'] %}
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
{% if suggestion.before is defined and suggestion.text is defined and suggestion.after is defined %}
|
|
|
|
<div>
|
|
|
|
<span class="suggestion-before">
|
|
|
|
|
|
|
|
{{ suggestion.before|slice(-20)|trim }}
|
|
|
|
</span>
|
|
|
|
<strong class="text-danger grammalecte-emphasis">{{ suggestion.text }}</strong>
|
|
|
|
|
|
|
|
<span class="suggestion-after">
|
|
|
|
|
|
|
|
{{ suggestion.after|slice(0, 20)|trim }}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{% if suggestion.paraghraph is defined %}
|
|
|
|
<code>$ {{ suggestion.paragraph }} {{ suggestion.start }}
|
|
|
|
- {{ suggestion.end }}</code>
|
|
|
|
{% endif %}
|
|
|
|
{% if suggestion.message is defined %}
|
|
|
|
{{ suggestion.message }}
|
|
|
|
{% endif %}
|
|
|
|
{# <pre> #}
|
|
|
|
{# {{ dump(suggestion) }} #}
|
|
|
|
{# </pre> #}
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{% if suggestion.suggestions is defined and suggestion.suggestions is iterable and suggestion.suggestions|length > 0 %}
|
|
|
|
<div class="dropdown">
|
|
|
|
{# <button class="btn btn-sm btn-outline-primary dropdown-toggle" #}
|
|
|
|
{# type="button" id="dropdownMenuButton{{ loop.index }}" #}
|
|
|
|
{# data-bs-toggle="dropdown" aria-expanded="false"> #}
|
|
|
|
{# Suggestions ({{ suggestion.suggestions|length }}) #}
|
|
|
|
{# </button> #}
|
|
|
|
<ul class="dropdown-menu-grammalecte"
|
|
|
|
aria-labelledby="dropdownMenuButton{{ loop.index }}">
|
|
|
|
{% for correction in suggestion.suggestions %}
|
|
|
|
<li><code class="suggestion-correction">{{ correction }}</code>
|
|
|
|
</li>
|
|
|
|
{% endfor %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
{% else %}
|
|
|
|
<span class="text-muted">Aucune suggestion</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Modal for all corrections -->
|
|
|
|
<div class="modal fade" id="allCorrectionsModal" tabindex="-1" aria-labelledby="allCorrectionsModalLabel"
|
|
|
|
aria-hidden="true">
|
|
|
|
<div class="modal-dialog modal-xl">
|
|
|
|
<div class="modal-content">
|
|
|
|
<div class="modal-header">
|
|
|
|
<h5 class="modal-title" id="allCorrectionsModalLabel">Toutes les suggestions de
|
|
|
|
corrections</h5>
|
|
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-bordered">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Texte</th>
|
|
|
|
<th>Message</th>
|
|
|
|
<th>Suggestions</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for suggestion in detailed_comparison['grammar_suggestions'] %}
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
{% if suggestion.before is defined and suggestion.text is defined and suggestion.after is defined %}
|
|
|
|
<code>{{ suggestion.before|slice(-30)|trim }}
|
|
|
|
<span class="text-danger">{{ suggestion.text }}</span>
|
|
|
|
{{ suggestion.after|slice(0, 30)|trim }}</code>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{% if suggestion.message is defined %}
|
|
|
|
{{ suggestion.message }}
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{% if suggestion.suggestions is defined and suggestion.suggestions is iterable and suggestion.suggestions|length > 0 %}
|
|
|
|
<div class="dropdown">
|
|
|
|
<button class="btn btn-sm btn-outline-primary dropdown-toggle"
|
|
|
|
type="button"
|
|
|
|
id="modalDropdownMenuButton{{ loop.index }}"
|
|
|
|
data-bs-toggle="dropdown" aria-expanded="false">
|
|
|
|
Suggestions ({{ suggestion.suggestions|length }})
|
|
|
|
</button>
|
|
|
|
<ul class="dropdown-menu"
|
|
|
|
aria-labelledby="modalDropdownMenuButton{{ loop.index }}">
|
|
|
|
{% for correction in suggestion.suggestions %}
|
|
|
|
<li><a class="dropdown-item"
|
|
|
|
href="#">{{ correction }}</a></li>
|
|
|
|
{% endfor %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
{% else %}
|
|
|
|
<span class="text-muted">Aucune suggestion</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
{# fin des suggestions de grammalecte #}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{% if fr_page is defined and fr_page is not null and fr_page.categories is defined and (fr_page.categories|length == 0) and en_page is defined and en_page.categories is defined and (en_page.categories|length > 0) %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-warning text-dark">
|
|
|
|
<h2>Suggestion d'ajout de catégories</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="alert alert-warning">
|
|
|
|
<p><i class="bi bi-exclamation-triangle"></i> <strong>La page française ne contient aucune
|
|
|
|
catégorie.</strong></p>
|
|
|
|
<p>Les catégories aident à organiser les pages wiki et à les rendre plus facilement
|
|
|
|
découvrables. Considérez ajouter les catégories suivantes de la page anglaise :</p>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h3>Catégories suggérées</h3>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group">
|
|
|
|
{% for category in en_page.categories %}
|
|
|
|
<li class="list-group-item">
|
|
|
|
{{ category }}
|
|
|
|
</li>
|
|
|
|
{% endfor %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h3>Comment ajouter des catégories</h3>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Pour ajouter des catégories à la page wiki :</p>
|
|
|
|
<ol>
|
|
|
|
<li>Éditez la page française sur le wiki OSM</li>
|
|
|
|
<li>Ajoutez les catégories à la fin de la page en utilisant la syntaxe suivante
|
|
|
|
:
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
<div class="bg-light p-3 mb-3">
|
|
|
|
<code>
|
|
|
|
[[Category:Nom de la catégorie]]<br>
|
|
|
|
[[Category:Autre catégorie]]
|
|
|
|
</code>
|
|
|
|
</div>
|
|
|
|
<p>Vous pouvez également utiliser l'interface d'édition du wiki pour ajouter des
|
|
|
|
catégories.</p>
|
|
|
|
<div class="d-grid gap-2 mt-3">
|
|
|
|
<a href="{{ fr_page.url }}" target="_blank" class="btn btn-primary">
|
|
|
|
<i class="bi bi-pencil-square"></i> Éditer la page française
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
{% if detailed_comparison and detailed_comparison.media_comparison %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Comparaison des médias</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h3>Images en anglais</h3>
|
|
|
|
<span class="badge bg-light text-dark">{{ en_page.media_count|default(0) }} images</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<h4>Images uniquement en anglais
|
|
|
|
({{ detailed_comparison.media_comparison.en_only|length }} uniques
|
|
|
|
sur {{ detailed_comparison.media_comparison.en_only_count }} total)</h4>
|
|
|
|
<div class="row">
|
|
|
|
{% for media in detailed_comparison.media_comparison.en_only %}
|
|
|
|
<div class="col-12 mb-2">
|
|
|
|
<div class="card border-warning">
|
|
|
|
<img src="{{ media.src }}" class="card-img-top"
|
|
|
|
alt="{{ media.alt }}"
|
|
|
|
style="max-height: 150px; object-fit: contain;">
|
|
|
|
<div class="card-body p-2">
|
|
|
|
<p class="card-text small">{{ media.alt }}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endfor %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h3>Images en français</h3>
|
|
|
|
<span class="badge bg-light text-dark">{{ fr_page.media_count|default(0) }} images</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
|
|
|
|
|
|
<h4>Images uniquement en français
|
|
|
|
({{ detailed_comparison.media_comparison.fr_only|length }} uniques
|
|
|
|
sur {{ detailed_comparison.media_comparison.fr_only_count }} total)</h4>
|
|
|
|
<div class="row">
|
|
|
|
{% for media in detailed_comparison.media_comparison.fr_only %}
|
|
|
|
<div class="col-12 mb-2">
|
|
|
|
<div class="card border-info">
|
|
|
|
<img src="{{ media.src }}" class="card-img-top"
|
|
|
|
alt="{{ media.alt }}"
|
|
|
|
style="max-height: 150px; object-fit: contain;">
|
|
|
|
<div class="card-body p-2">
|
|
|
|
<p class="card-text small">{{ media.alt }}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endfor %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-09-08 10:20:51 +02:00
|
|
|
|
|
|
|
<div class="row mt-4">
|
|
|
|
<div class="col-12">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-success text-white">
|
|
|
|
<h3>Images communes</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.media_comparison.common is defined %}
|
|
|
|
{{ detailed_comparison.media_comparison.common|length }} images communes
|
|
|
|
{% else %}
|
|
|
|
0 images communes
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
|
|
{% if detailed_comparison.media_comparison.common is defined and detailed_comparison.media_comparison.common is iterable %}
|
|
|
|
{% for media in detailed_comparison.media_comparison.common %}
|
|
|
|
<div class="col-md-6 mb-3">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h5>Version anglaise</h5>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<img src="{{ media.en.src }}" class="img-fluid"
|
|
|
|
alt="{{ media.en.alt }}"
|
|
|
|
style="max-height: 150px; object-fit: contain;">
|
|
|
|
<p class="card-text small mt-2">{{ media.en.alt }}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h5>Version française</h5>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<img src="{{ media.fr.src }}" class="img-fluid"
|
|
|
|
alt="{{ media.fr.alt }}"
|
|
|
|
style="max-height: 150px; object-fit: contain;">
|
|
|
|
<p class="card-text small mt-2">{{ media.fr.alt }}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<div class="col-12">
|
|
|
|
<div class="alert alert-info">
|
|
|
|
Aucune image commune trouvée entre les versions anglaise et française.
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-09-01 18:28:23 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
2025-09-08 10:20:51 +02:00
|
|
|
{% if detailed_comparison and detailed_comparison.link_comparison %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Comparaison des liens</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h3>Liens uniquement en anglais</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.link_comparison.en_only is defined %}
|
|
|
|
{{ detailed_comparison.link_comparison.en_only|length }} liens
|
|
|
|
{% else %}
|
|
|
|
0 liens
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-sm">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Texte du lien</th>
|
|
|
|
<th>URL</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% if detailed_comparison.link_comparison.en_only is defined and detailed_comparison.link_comparison.en_only is iterable %}
|
|
|
|
{% for link in detailed_comparison.link_comparison.en_only %}
|
|
|
|
<tr>
|
|
|
|
<td>{{ link.text }}</td>
|
|
|
|
<td>
|
|
|
|
<a href="{{ link.href }}" target="_blank" class="small">
|
|
|
|
{{ link.href|slice(0, 30) }}{% if link.href|length > 30 %}...{% endif %}
|
|
|
|
</a>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<tr>
|
|
|
|
<td colspan="2" class="text-center">Aucun lien uniquement en anglais</td>
|
|
|
|
</tr>
|
|
|
|
{% endif %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h3>Liens uniquement en français</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.link_comparison.fr_only is defined %}
|
|
|
|
{{ detailed_comparison.link_comparison.fr_only|length }} liens
|
|
|
|
{% else %}
|
|
|
|
0 liens
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-sm">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Texte du lien</th>
|
|
|
|
<th>URL</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% if detailed_comparison.link_comparison.fr_only is defined and detailed_comparison.link_comparison.fr_only is iterable %}
|
|
|
|
{% for link in detailed_comparison.link_comparison.fr_only %}
|
|
|
|
<tr>
|
|
|
|
<td>{{ link.text }}</td>
|
|
|
|
<td>
|
|
|
|
<a href="{{ link.href }}" target="_blank" class="small">
|
|
|
|
{{ link.href|slice(0, 30) }}{% if link.href|length > 30 %}...{% endif %}
|
|
|
|
</a>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<tr>
|
|
|
|
<td colspan="2" class="text-center">Aucun lien uniquement en français</td>
|
|
|
|
</tr>
|
|
|
|
{% endif %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="row mt-4">
|
|
|
|
<div class="col-12">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-success text-white">
|
|
|
|
<h3>Liens communs</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.link_comparison.common is defined %}
|
|
|
|
{{ detailed_comparison.link_comparison.common|length }} liens communs
|
|
|
|
{% else %}
|
|
|
|
0 liens communs
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th class="bg-primary text-white">Texte EN</th>
|
|
|
|
<th class="bg-primary text-white">URL EN</th>
|
|
|
|
<th class="bg-info text-white">Texte FR</th>
|
|
|
|
<th class="bg-info text-white">URL FR</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% if detailed_comparison.link_comparison.common is defined and detailed_comparison.link_comparison.common is iterable %}
|
|
|
|
{% for link in detailed_comparison.link_comparison.common %}
|
|
|
|
<tr>
|
|
|
|
<td>{{ link.en.text }}</td>
|
|
|
|
<td>
|
|
|
|
<a href="{{ link.en.href }}" target="_blank" class="small">
|
|
|
|
{{ link.en.href|slice(0, 30) }}{% if link.en.href|length > 30 %}...{% endif %}
|
|
|
|
</a>
|
|
|
|
</td>
|
|
|
|
<td>{{ link.fr.text }}</td>
|
|
|
|
<td>
|
|
|
|
<a href="{{ link.fr.href }}" target="_blank" class="small">
|
|
|
|
{{ link.fr.href|slice(0, 30) }}{% if link.fr.href|length > 30 %}...{% endif %}
|
|
|
|
</a>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<tr>
|
|
|
|
<td colspan="4" class="text-center">Aucun lien commun trouvé</td>
|
|
|
|
</tr>
|
|
|
|
{% endif %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
2025-09-01 18:28:23 +02:00
|
|
|
|
2025-09-08 10:20:51 +02:00
|
|
|
{% if detailed_comparison and detailed_comparison.category_comparison %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Comparaison des catégories</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h3>Catégories uniquement en anglais</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.category_comparison.en_only is defined %}
|
|
|
|
{{ detailed_comparison.category_comparison.en_only|length }} catégories
|
|
|
|
{% else %}
|
|
|
|
0 catégories
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group">
|
|
|
|
{% if detailed_comparison.category_comparison.en_only is defined and detailed_comparison.category_comparison.en_only is iterable and detailed_comparison.category_comparison.en_only|length > 0 %}
|
|
|
|
{% for category in detailed_comparison.category_comparison.en_only %}
|
|
|
|
<li class="list-group-item list-group-item-warning">{{ category }}</li>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<li class="list-group-item text-center">Aucune catégorie uniquement en anglais</li>
|
|
|
|
{% endif %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h3>Catégories uniquement en français</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.category_comparison.fr_only is defined %}
|
|
|
|
{{ detailed_comparison.category_comparison.fr_only|length }} catégories
|
|
|
|
{% else %}
|
|
|
|
0 catégories
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group">
|
|
|
|
{% if detailed_comparison.category_comparison.fr_only is defined and detailed_comparison.category_comparison.fr_only is iterable and detailed_comparison.category_comparison.fr_only|length > 0 %}
|
|
|
|
{% for category in detailed_comparison.category_comparison.fr_only %}
|
|
|
|
<li class="list-group-item list-group-item-info">{{ category }}</li>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<li class="list-group-item text-center">Aucune catégorie uniquement en français</li>
|
|
|
|
{% endif %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="row mt-4">
|
|
|
|
<div class="col-12">
|
|
|
|
<div class="card">
|
|
|
|
<div class="card-header bg-success text-white">
|
|
|
|
<h3>Catégories communes</h3>
|
|
|
|
<span class="badge bg-light text-dark">
|
|
|
|
{% if detailed_comparison.category_comparison.common is defined %}
|
|
|
|
{{ detailed_comparison.category_comparison.common|length }} catégories communes
|
|
|
|
{% else %}
|
|
|
|
0 catégories communes
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group">
|
|
|
|
{% if detailed_comparison.category_comparison.common is defined and detailed_comparison.category_comparison.common is iterable and detailed_comparison.category_comparison.common|length > 0 %}
|
|
|
|
{% for category in detailed_comparison.category_comparison.common %}
|
|
|
|
<li class="list-group-item">{{ category }}</li>
|
|
|
|
{% endfor %}
|
|
|
|
{% else %}
|
|
|
|
<li class="list-group-item text-center">Aucune catégorie commune trouvée</li>
|
|
|
|
{% endif %}
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
2025-09-01 18:28:23 +02:00
|
|
|
{# {% else %} #}
|
|
|
|
{# <div class="card mb-4"> #}
|
|
|
|
{# <div class="card-header bg-warning text-dark"> #}
|
|
|
|
{# <h2>Traduction française manquante</h2> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# <div class="card-body"> #}
|
|
|
|
{# <div class="alert alert-warning"> #}
|
|
|
|
{# <p><i class="bi bi-exclamation-triangle"></i> <strong>La page wiki pour la clé "{{ key }}" #}
|
|
|
|
{# n'existe pas en français.</strong></p> #}
|
|
|
|
{# <p>Vous pouvez contribuer en créant cette page sur le wiki OpenStreetMap.</p> #}
|
|
|
|
{# </div> #}
|
|
|
|
|
|
|
|
{# <div class="row"> #}
|
|
|
|
{# <div class="col-md-6"> #}
|
|
|
|
{# <div class="card h-100"> #}
|
|
|
|
{# <div class="card-header bg-primary text-white"> #}
|
|
|
|
{# <h3>Version anglaise</h3> #}
|
|
|
|
{# <p class="mb-0"> #}
|
|
|
|
{# <small>Dernière modification: {{ en_page.last_modified }}</small> #}
|
|
|
|
{# </p> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# <div class="card-body"> #}
|
|
|
|
{# <ul class="list-group mb-3"> #}
|
|
|
|
{# <li class="list-group-item d-flex justify-content-between align-items-center"> #}
|
|
|
|
{# Sections #}
|
|
|
|
{# <span class="badge bg-primary rounded-pill"> #}
|
|
|
|
{# {% if detailed_comparison.adjusted_en_section_count is defined %} #}
|
|
|
|
{# {{ detailed_comparison.adjusted_en_section_count }} #}
|
|
|
|
{# {% else %} #}
|
|
|
|
{# {{ en_page.sections }} #}
|
|
|
|
{# {% endif %} #}
|
|
|
|
{# </span> #}
|
|
|
|
{# </li> #}
|
|
|
|
{# <li class="list-group-item d-flex justify-content-between align-items-center"> #}
|
|
|
|
{# Mots #}
|
|
|
|
{# <span class="badge bg-primary rounded-pill">{{ en_page.word_count }}</span> #}
|
|
|
|
{# </li> #}
|
|
|
|
{# <li class="list-group-item d-flex justify-content-between align-items-center"> #}
|
|
|
|
{# Liens #}
|
|
|
|
{# <span class="badge bg-primary rounded-pill">{{ en_page.link_count }}</span> #}
|
|
|
|
{# </li> #}
|
|
|
|
{# </ul> #}
|
|
|
|
{# <div class="d-grid gap-2"> #}
|
|
|
|
{# <a href="{{ en_page.url }}" target="_blank" class="btn btn-outline-primary"> #}
|
|
|
|
{# <i class="bi bi-box-arrow-up-right"></i> Voir la page anglaise #}
|
|
|
|
{# </a> #}
|
|
|
|
{# <button class="btn btn-outline-secondary copy-btn" data-content="sections-en"> #}
|
|
|
|
{# <i class="bi bi-clipboard"></i> Copier la liste des sections #}
|
|
|
|
{# </button> #}
|
|
|
|
{# <button class="btn btn-outline-secondary copy-btn" data-content="links-en"> #}
|
|
|
|
{# <i class="bi bi-clipboard"></i> Copier la liste des liens #}
|
|
|
|
{# </button> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# <div class="col-md-6"> #}
|
|
|
|
{# <div class="card h-100"> #}
|
|
|
|
{# <div class="card-header bg-info text-white"> #}
|
|
|
|
{# <h3>Créer la version française</h3> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# <div class="card-body"> #}
|
|
|
|
{# <p>Vous pouvez créer la page française en suivant ces étapes :</p> #}
|
|
|
|
{# <ol> #}
|
|
|
|
{# <li>Consultez la version anglaise pour comprendre le contenu</li> #}
|
|
|
|
{# <li>Créez une nouvelle page avec le préfixe "FR:" sur le wiki OSM</li> #}
|
|
|
|
{# <li>Traduisez le contenu en respectant la structure de la page anglaise</li> #}
|
|
|
|
{# <li>Ajoutez des exemples pertinents pour le contexte français</li> #}
|
|
|
|
{# </ol> #}
|
|
|
|
{# <div class="d-grid gap-2 mt-4"> #}
|
|
|
|
{# <a href="{{ create_fr_url }}" target="_blank" class="btn btn-success"> #}
|
|
|
|
{# <i class="bi bi-plus-circle"></i> Créer la page française #}
|
|
|
|
{# </a> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# </div> #}
|
|
|
|
{# {% endif %} #}
|
|
|
|
|
|
|
|
|
2025-09-03 17:18:21 +02:00
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Score de décrépitude</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Le score de décrépitude est calculé en prenant en compte plusieurs facteurs, avec une pondération
|
|
|
|
plus importante pour la différence de nombre de mots :</p>
|
|
|
|
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Facteur</th>
|
|
|
|
<th>Valeur</th>
|
|
|
|
<th>Poids</th>
|
|
|
|
<th>Contribution</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for key, component in score_components %}
|
|
|
|
<tr>
|
|
|
|
<td>{{ component.description }}</td>
|
|
|
|
<td>{{ component.value }}</td>
|
|
|
|
<td>{{ component.weight * 100 }}%</td>
|
|
|
|
<td>{{ component.component|round(2) }}</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
<tr class="table-dark">
|
|
|
|
<td colspan="3"><strong>Score total</strong></td>
|
|
|
|
<td>
|
|
|
|
{% set total_score = 0 %}
|
|
|
|
{% for key, component in score_components %}
|
|
|
|
{% set total_score = total_score + component.component %}
|
|
|
|
{% endfor %}
|
|
|
|
<strong>{{ total_score|round(2) }}</strong>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
2025-09-01 18:28:23 +02:00
|
|
|
|
2025-09-03 17:18:21 +02:00
|
|
|
<div class="alert alert-info">
|
|
|
|
<p><strong>Comment interpréter ce score :</strong></p>
|
|
|
|
<ul>
|
|
|
|
<li>Plus le score est élevé, plus la page française est considérée comme "décrépite" par rapport
|
|
|
|
à la version anglaise.
|
|
|
|
</li>
|
|
|
|
<li>La différence de nombre de mots compte pour 50% du score, car c'est l'indicateur le plus
|
|
|
|
important de la complétude de la traduction.
|
|
|
|
</li>
|
|
|
|
<li>Les différences de sections (15%), de liens (15%) et de date de modification (20%)
|
|
|
|
complètent le score.
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
2025-09-08 10:20:51 +02:00
|
|
|
{% if staleness_distribution is defined and staleness_distribution is not null %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Répartition des scores de décrépitude</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Ce graphique montre la répartition des scores de décrépitude pour toutes les pages wiki et où se situe la page courante :</p>
|
|
|
|
|
|
|
|
<div class="mb-4">
|
|
|
|
<canvas id="distributionChart" width="400" height="200"></canvas>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="alert alert-info">
|
|
|
|
<p><strong>Statistiques de décrépitude :</strong></p>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<ul>
|
|
|
|
<li><strong>Nombre total de pages :</strong> {{ staleness_distribution.totalPages }}</li>
|
|
|
|
<li><strong>Score minimum :</strong> {{ staleness_distribution.min|round(2) }}</li>
|
|
|
|
<li><strong>Score maximum :</strong> {{ staleness_distribution.max|round(2) }}</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<ul>
|
|
|
|
<li><strong>Score moyen :</strong> {{ staleness_distribution.avg|round(2) }}</li>
|
|
|
|
<li><strong>Score médian :</strong> {{ staleness_distribution.median|round(2) }}</li>
|
|
|
|
<li><strong>Score de cette page :</strong> {{ staleness_distribution.currentPageScore|round(2) }}</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
2025-09-04 00:15:25 +02:00
|
|
|
{% if history_data is defined and history_data|length > 0 %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Historique des mesures</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Ce graphique montre l'évolution du score de décrépitude et des métriques associées au fil du temps :</p>
|
|
|
|
|
|
|
|
<div class="mb-4">
|
|
|
|
<canvas id="historyChart" width="400" height="200"></canvas>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-sm">
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Date</th>
|
|
|
|
<th>Score de décrépitude</th>
|
|
|
|
<th>Diff. de date (jours)</th>
|
|
|
|
<th>Diff. de mots</th>
|
|
|
|
<th>Diff. de sections</th>
|
|
|
|
<th>Diff. de liens</th>
|
|
|
|
<th>Diff. d'images</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for entry in history_data %}
|
|
|
|
<tr>
|
|
|
|
<td>{{ entry.date }}</td>
|
|
|
|
<td>{{ entry.metrics.staleness_score|round(2) }}</td>
|
|
|
|
<td>{{ entry.metrics.date_diff }}</td>
|
|
|
|
<td>{{ entry.metrics.word_diff }}</td>
|
|
|
|
<td>{{ entry.metrics.section_diff }}</td>
|
|
|
|
<td>{{ entry.metrics.link_diff }}</td>
|
|
|
|
<td>{{ entry.metrics.media_diff }}</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="alert alert-info mt-3">
|
|
|
|
<p><strong>À propos de l'historique :</strong></p>
|
|
|
|
<ul>
|
|
|
|
<li>L'historique montre l'évolution des métriques au fil du temps, permettant de suivre les progrès ou la dégradation de la traduction.</li>
|
|
|
|
<li>Une tendance à la baisse du score de décrépitude indique une amélioration de la qualité de la traduction.</li>
|
|
|
|
<li>Les données sont collectées à chaque exécution du script d'analyse.</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
2025-09-03 17:18:21 +02:00
|
|
|
<div class="mt-3">
|
|
|
|
<a href="{{ path('app_admin_wiki') }}" class="btn btn-secondary">
|
|
|
|
<i class="bi bi-arrow-left"></i> Retour à la liste des pages wiki
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Comparaison des versions</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h3>Version anglaise</h3>
|
|
|
|
<p class="mb-0">
|
|
|
|
<small>Dernière modification: {{ en_page.last_modified }}</small>
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group mb-3">
|
|
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
|
|
Sections
|
|
|
|
<span class="badge bg-primary rounded-pill">
|
|
|
|
{% if detailed_comparison.adjusted_en_section_count is defined %}
|
|
|
|
{{ detailed_comparison.adjusted_en_section_count }}
|
|
|
|
{% else %}
|
|
|
|
{{ en_page.sections }}
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
|
|
Mots
|
|
|
|
<span class="badge bg-primary rounded-pill">{{ en_page.word_count }}</span>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
|
|
Liens
|
|
|
|
<span class="badge bg-primary rounded-pill">{{ en_page.link_count }}</span>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
<div class="d-grid gap-2">
|
|
|
|
<a href="{{ en_page.url }}" target="_blank" class="btn btn-outline-primary">
|
|
|
|
<i class="bi bi-box-arrow-up-right"></i> Voir la page
|
|
|
|
</a>
|
|
|
|
<button class="btn btn-outline-secondary copy-btn" data-content="sections-en">
|
|
|
|
<i class="bi bi-clipboard"></i> Copier la liste des sections
|
|
|
|
</button>
|
|
|
|
<button class="btn btn-outline-secondary copy-btn" data-content="links-en">
|
|
|
|
<i class="bi bi-clipboard"></i> Copier la liste des liens
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<div class="card h-100">
|
|
|
|
<div class="card-header bg-info text-white">
|
|
|
|
<h3>Version française</h3>
|
|
|
|
<p class="mb-0">
|
|
|
|
<small>Dernière modification: {{ fr_page.last_modified }}</small>
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<ul class="list-group mb-3">
|
|
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
|
|
Sections
|
|
|
|
<span class="badge bg-info rounded-pill">
|
|
|
|
{% if detailed_comparison.adjusted_fr_section_count is defined %}
|
|
|
|
{{ detailed_comparison.adjusted_fr_section_count }}
|
|
|
|
{% else %}
|
|
|
|
{{ fr_page.sections }}
|
|
|
|
{% endif %}
|
|
|
|
</span>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
|
|
Mots
|
|
|
|
<span class="badge bg-info rounded-pill">{{ fr_page.word_count }}</span>
|
|
|
|
</li>
|
|
|
|
<li class="list-group-item d-flex justify-content-between align-items-center">
|
|
|
|
Liens
|
|
|
|
<span class="badge bg-info rounded-pill">{{ fr_page.link_count }}</span>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
<div class="d-grid gap-2">
|
|
|
|
<a href="{{ fr_page.url }}" target="_blank" class="btn btn-outline-info">
|
|
|
|
<i class="bi bi-box-arrow-up-right"></i> Voir la page
|
|
|
|
</a>
|
|
|
|
<button class="btn btn-outline-secondary copy-btn" data-content="sections-fr">
|
|
|
|
<i class="bi bi-clipboard"></i> Copier la liste des sections
|
|
|
|
</button>
|
|
|
|
<button class="btn btn-outline-secondary copy-btn" data-content="links-fr">
|
|
|
|
<i class="bi bi-clipboard"></i> Copier la liste des liens
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-09-01 18:28:23 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<!-- Hidden content for copy functionality -->
|
|
|
|
<div id="sections-en" style="display: none;">
|
|
|
|
{{ en_sections|default('Sections de la page anglaise pour ' ~ key) }}
|
|
|
|
</div>
|
|
|
|
<div id="links-en" style="display: none;">
|
|
|
|
{{ en_links|default('Liens de la page anglaise pour ' ~ key) }}
|
|
|
|
</div>
|
|
|
|
{% if fr_page is defined and fr_page is not null %}
|
|
|
|
<div id="sections-fr" style="display: none;">
|
|
|
|
{{ fr_sections|default('Sections de la page française pour ' ~ key) }}
|
|
|
|
</div>
|
|
|
|
<div id="links-fr" style="display: none;">
|
|
|
|
{{ fr_links|default('Liens de la page française pour ' ~ key) }}
|
|
|
|
</div>
|
|
|
|
<div id="different-sections" style="display: none;">
|
|
|
|
{% if detailed_comparison is defined and detailed_comparison is not null and detailed_comparison.aligned_sections is defined and detailed_comparison.aligned_sections is iterable %}
|
|
|
|
{# Add sections that are in English but missing in French #}
|
|
|
|
{% for section in detailed_comparison.aligned_sections %}
|
|
|
|
{% if section.en is defined and section.en.title is defined and section.en.title is not empty and section.fr is defined and section.fr.is_placeholder is defined and section.fr.is_placeholder %}
|
|
|
|
{{ "=" | repeat(section.en.level|default(1)) }} {{ section.en.title }} {{ "=" | repeat(section.en.level|default(1)) }} (À traduire en français)
|
|
|
|
{% endif %}
|
|
|
|
{% endfor %}
|
|
|
|
|
|
|
|
{# Add sections that are in French but missing in English #}
|
|
|
|
{% for section in detailed_comparison.aligned_sections %}
|
|
|
|
{% if section.fr is defined and section.fr.title is defined and section.fr.title is not empty and section.en is defined and section.en.is_placeholder is defined and section.en.is_placeholder %}
|
|
|
|
{{ "=" | repeat(section.fr.level|default(1)) }} {{ section.fr.title }} {{ "=" | repeat(section.fr.level|default(1)) }} (FR only)
|
|
|
|
{% endif %}
|
|
|
|
{% endfor %}
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
{% block javascripts %}
|
2025-09-04 00:15:25 +02:00
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script>
|
2025-09-01 18:28:23 +02:00
|
|
|
<script>
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
// Add click event listeners to all copy buttons
|
|
|
|
document.querySelectorAll('.copy-btn').forEach(function (button) {
|
|
|
|
button.addEventListener('click', function () {
|
|
|
|
// Get the content to copy
|
|
|
|
const contentId = this.getAttribute('data-content');
|
|
|
|
const content = document.getElementById(contentId).textContent;
|
|
|
|
|
|
|
|
// Copy to clipboard
|
|
|
|
navigator.clipboard.writeText(content).then(function () {
|
|
|
|
// Change button text temporarily to indicate success
|
|
|
|
const originalText = button.innerHTML;
|
|
|
|
button.innerHTML = '<i class="bi bi-check"></i> Copié!';
|
|
|
|
setTimeout(function () {
|
|
|
|
button.innerHTML = originalText;
|
|
|
|
}, 2000);
|
|
|
|
}).catch(function (err) {
|
|
|
|
console.error('Erreur lors de la copie :', err);
|
|
|
|
// alert('Erreur lors de la copie. Veuillez réessayer.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add click event listeners to all suggestion-correction elements
|
|
|
|
document.querySelectorAll('.suggestion-correction, .suggestion-before, .suggestion-after, .section-title').forEach(function (element) {
|
|
|
|
element.addEventListener('click', function () {
|
|
|
|
// Get the text content to copy
|
|
|
|
const content = this.textContent.trim();
|
|
|
|
|
|
|
|
// Copy to clipboard
|
|
|
|
navigator.clipboard.writeText(content).then(function () {
|
|
|
|
// Add a temporary class for visual feedback
|
|
|
|
element.classList.add('bg-success');
|
|
|
|
element.classList.add('text-white');
|
|
|
|
|
|
|
|
// Create and show a tooltip
|
|
|
|
const tooltip = document.createElement('div');
|
|
|
|
tooltip.textContent = 'Copié!';
|
|
|
|
tooltip.style.position = 'absolute';
|
|
|
|
tooltip.style.backgroundColor = '#28a745';
|
|
|
|
tooltip.style.color = 'white';
|
|
|
|
tooltip.style.padding = '5px 10px';
|
|
|
|
tooltip.style.borderRadius = '3px';
|
|
|
|
tooltip.style.fontSize = '12px';
|
|
|
|
tooltip.style.zIndex = '1000';
|
|
|
|
|
|
|
|
// Position the tooltip near the element
|
|
|
|
const rect = element.getBoundingClientRect();
|
|
|
|
tooltip.style.top = (window.scrollY + rect.bottom + 5) + 'px';
|
|
|
|
tooltip.style.left = (window.scrollX + rect.left) + 'px';
|
|
|
|
|
|
|
|
// Add the tooltip to the document
|
|
|
|
document.body.appendChild(tooltip);
|
|
|
|
|
|
|
|
// Remove the visual feedback and tooltip after a delay
|
|
|
|
setTimeout(function () {
|
|
|
|
element.classList.remove('bg-success');
|
|
|
|
element.classList.remove('text-white');
|
|
|
|
document.body.removeChild(tooltip);
|
|
|
|
}, 1500);
|
|
|
|
}).catch(function (err) {
|
|
|
|
console.error('Erreur lors de la copie :', err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add click event listeners to dropdown items in the modal
|
|
|
|
document.querySelectorAll('#allCorrectionsModal .dropdown-item').forEach(function (element) {
|
|
|
|
element.addEventListener('click', function (e) {
|
|
|
|
e.preventDefault(); // Prevent the default link behavior
|
|
|
|
|
|
|
|
// Get the text content to copy
|
|
|
|
const content = this.textContent.trim();
|
|
|
|
|
|
|
|
// Copy to clipboard
|
|
|
|
navigator.clipboard.writeText(content).then(function () {
|
|
|
|
// Add a temporary class for visual feedback
|
|
|
|
element.classList.add('bg-success');
|
|
|
|
element.classList.add('text-white');
|
|
|
|
|
|
|
|
// Remove the visual feedback after a delay
|
|
|
|
setTimeout(function () {
|
|
|
|
element.classList.remove('bg-success');
|
|
|
|
element.classList.remove('text-white');
|
|
|
|
}, 1500);
|
|
|
|
}).catch(function (err) {
|
|
|
|
console.error('Erreur lors de la copie :', err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2025-09-04 00:15:25 +02:00
|
|
|
|
2025-09-08 10:20:51 +02:00
|
|
|
// Create ranking evolution chart if the element exists
|
|
|
|
const rankingEvolutionChartElement = document.getElementById('rankingEvolutionChart');
|
|
|
|
const historyData = {{ history_data|json_encode|raw }};
|
|
|
|
if (rankingEvolutionChartElement && historyData && historyData.length > 0) {
|
|
|
|
// Format the data for the chart
|
|
|
|
const dates = historyData.map(entry => entry.date);
|
|
|
|
const stalenessScores = historyData.map(entry => entry.metrics.staleness_score || 0);
|
|
|
|
const wordDiffs = historyData.map(entry => entry.metrics.word_diff || 0);
|
|
|
|
const sectionDiffs = historyData.map(entry => entry.metrics.section_diff || 0);
|
|
|
|
const linkDiffs = historyData.map(entry => entry.metrics.link_diff || 0);
|
|
|
|
|
|
|
|
// Create the chart
|
|
|
|
new Chart(rankingEvolutionChartElement, {
|
|
|
|
type: 'line',
|
|
|
|
data: {
|
|
|
|
labels: dates,
|
|
|
|
datasets: [
|
|
|
|
{
|
|
|
|
label: 'Score de décrépitude',
|
|
|
|
data: stalenessScores,
|
|
|
|
borderColor: 'rgba(255, 99, 132, 1)',
|
|
|
|
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
|
|
|
fill: false,
|
|
|
|
tension: 0.1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Différence de mots / 10',
|
|
|
|
data: wordDiffs.map(val => val / 10),
|
|
|
|
borderColor: 'rgba(54, 162, 235, 1)',
|
|
|
|
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
|
|
|
fill: false,
|
|
|
|
tension: 0.1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Différence de sections',
|
|
|
|
data: sectionDiffs,
|
|
|
|
borderColor: 'rgba(255, 206, 86, 1)',
|
|
|
|
backgroundColor: 'rgba(255, 206, 86, 0.2)',
|
|
|
|
fill: false,
|
|
|
|
tension: 0.1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Différence de liens',
|
|
|
|
data: linkDiffs,
|
|
|
|
borderColor: 'rgba(75, 192, 192, 1)',
|
|
|
|
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
|
|
|
fill: false,
|
|
|
|
tension: 0.1
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
options: {
|
|
|
|
responsive: true,
|
|
|
|
plugins: {
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Évolution des métriques au fil du temps'
|
|
|
|
},
|
|
|
|
tooltip: {
|
|
|
|
mode: 'index',
|
|
|
|
intersect: false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
scales: {
|
|
|
|
y: {
|
|
|
|
beginAtZero: true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create distribution histogram if the element exists
|
|
|
|
const distributionChartElement = document.getElementById('distributionChart');
|
|
|
|
if (distributionChartElement) {
|
|
|
|
// Get staleness distribution data from the template
|
|
|
|
const distributionData = {{ staleness_distribution|json_encode|raw }};
|
|
|
|
|
|
|
|
if (distributionData) {
|
|
|
|
// Prepare data for the histogram
|
|
|
|
const labels = distributionData.binLabels;
|
|
|
|
const counts = distributionData.bins;
|
|
|
|
const currentPageBin = distributionData.currentPageBin;
|
|
|
|
|
|
|
|
// Create colors array with the current page bin highlighted
|
|
|
|
const colors = counts.map((_, index) =>
|
|
|
|
index === currentPageBin ? 'rgba(255, 99, 132, 0.8)' : 'rgba(54, 162, 235, 0.6)'
|
|
|
|
);
|
|
|
|
|
|
|
|
// Create the histogram
|
|
|
|
const ctx = distributionChartElement.getContext('2d');
|
|
|
|
const distributionChart = new Chart(ctx, {
|
|
|
|
type: 'bar',
|
|
|
|
data: {
|
|
|
|
labels: labels,
|
|
|
|
datasets: [{
|
|
|
|
label: 'Nombre de pages',
|
|
|
|
data: counts,
|
|
|
|
backgroundColor: colors,
|
|
|
|
borderColor: colors.map(color => color.replace('0.6', '1').replace('0.8', '1')),
|
|
|
|
borderWidth: 1
|
|
|
|
}]
|
|
|
|
},
|
|
|
|
options: {
|
|
|
|
responsive: true,
|
|
|
|
scales: {
|
|
|
|
y: {
|
|
|
|
beginAtZero: true,
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Nombre de pages'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
x: {
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Score de décrépitude'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
plugins: {
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Répartition des scores de décrépitude (la page courante est en rouge)'
|
|
|
|
},
|
|
|
|
tooltip: {
|
|
|
|
callbacks: {
|
|
|
|
title: function(tooltipItems) {
|
|
|
|
const item = tooltipItems[0];
|
|
|
|
const binRange = item.label;
|
|
|
|
return `Score: ${binRange}`;
|
|
|
|
},
|
|
|
|
label: function(context) {
|
|
|
|
let label = 'Nombre de pages: ' + context.raw;
|
|
|
|
if (context.dataIndex === currentPageBin) {
|
|
|
|
label += ' (inclut la page courante)';
|
|
|
|
}
|
|
|
|
return label;
|
|
|
|
},
|
|
|
|
afterLabel: function(context) {
|
|
|
|
if (context.dataIndex === currentPageBin) {
|
|
|
|
return `Score de cette page: ${distributionData.currentPageScore.toFixed(2)}`;
|
|
|
|
}
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
legend: {
|
|
|
|
display: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-09-04 00:15:25 +02:00
|
|
|
// Create history chart if the element exists
|
|
|
|
const historyChartElement = document.getElementById('historyChart');
|
|
|
|
if (historyChartElement) {
|
|
|
|
// Get history data from the template
|
|
|
|
const historyData = {{ history_data|json_encode|raw }};
|
|
|
|
|
|
|
|
if (historyData && historyData.length > 0) {
|
|
|
|
// Prepare data for the chart
|
|
|
|
const labels = historyData.map(entry => entry.date);
|
|
|
|
const stalenessScores = historyData.map(entry => entry.metrics.staleness_score);
|
|
|
|
const wordDiffs = historyData.map(entry => entry.metrics.word_diff);
|
|
|
|
const sectionDiffs = historyData.map(entry => entry.metrics.section_diff);
|
|
|
|
const linkDiffs = historyData.map(entry => entry.metrics.link_diff);
|
|
|
|
|
|
|
|
// Create the chart
|
|
|
|
const ctx = historyChartElement.getContext('2d');
|
|
|
|
const historyChart = new Chart(ctx, {
|
|
|
|
type: 'line',
|
|
|
|
data: {
|
|
|
|
labels: labels,
|
|
|
|
datasets: [
|
|
|
|
{
|
|
|
|
label: 'Score de décrépitude',
|
|
|
|
data: stalenessScores,
|
|
|
|
borderColor: 'rgba(255, 99, 132, 1)',
|
|
|
|
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
|
|
|
borderWidth: 2,
|
|
|
|
tension: 0.1,
|
|
|
|
yAxisID: 'y'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Différence de mots',
|
|
|
|
data: wordDiffs,
|
|
|
|
borderColor: 'rgba(54, 162, 235, 1)',
|
|
|
|
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
|
|
|
borderWidth: 2,
|
|
|
|
tension: 0.1,
|
|
|
|
yAxisID: 'y1',
|
|
|
|
hidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Différence de sections',
|
|
|
|
data: sectionDiffs,
|
|
|
|
borderColor: 'rgba(75, 192, 192, 1)',
|
|
|
|
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
|
|
|
borderWidth: 2,
|
|
|
|
tension: 0.1,
|
|
|
|
yAxisID: 'y1',
|
|
|
|
hidden: true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Différence de liens',
|
|
|
|
data: linkDiffs,
|
|
|
|
borderColor: 'rgba(153, 102, 255, 1)',
|
|
|
|
backgroundColor: 'rgba(153, 102, 255, 0.2)',
|
|
|
|
borderWidth: 2,
|
|
|
|
tension: 0.1,
|
|
|
|
yAxisID: 'y1',
|
|
|
|
hidden: true
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
options: {
|
|
|
|
responsive: true,
|
|
|
|
interaction: {
|
|
|
|
mode: 'index',
|
|
|
|
intersect: false,
|
|
|
|
},
|
|
|
|
stacked: false,
|
|
|
|
scales: {
|
|
|
|
y: {
|
|
|
|
type: 'linear',
|
|
|
|
display: true,
|
|
|
|
position: 'left',
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Score de décrépitude'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
y1: {
|
|
|
|
type: 'linear',
|
|
|
|
display: true,
|
|
|
|
position: 'right',
|
|
|
|
grid: {
|
|
|
|
drawOnChartArea: false,
|
|
|
|
},
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Différences'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
plugins: {
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Évolution des métriques au fil du temps'
|
|
|
|
},
|
|
|
|
tooltip: {
|
|
|
|
callbacks: {
|
|
|
|
label: function(context) {
|
|
|
|
let label = context.dataset.label || '';
|
|
|
|
if (label) {
|
|
|
|
label += ': ';
|
|
|
|
}
|
|
|
|
if (context.parsed.y !== null) {
|
|
|
|
label += context.parsed.y.toFixed(2);
|
|
|
|
}
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2025-09-01 18:28:23 +02:00
|
|
|
});
|
|
|
|
</script>
|
|
|
|
{% endblock %}
|
|
|
|
{% endif %}
|
|
|
|
{% endblock %}
|