2025-09-01 18:28:23 +02:00
|
|
|
{% extends 'base.html.twig' %}
|
|
|
|
|
|
|
|
{% block title %}Pages Wiki OSM{% endblock %}
|
|
|
|
|
|
|
|
{% block body %}
|
|
|
|
<div class="container mt-4">
|
|
|
|
{% include 'admin/_wiki_navigation.html.twig' %}
|
|
|
|
|
|
|
|
<h1>Pages Wiki OpenStreetMap</h1>
|
|
|
|
<p class="lead">Outil de qualité des des pages wiki OpenStreetMap en français et en anglais pour les clés OSM
|
|
|
|
les plus utilisées.
|
|
|
|
<a href="https://forum.openstreetmap.fr/t/fabriquer-un-outil-de-qualite-pour-le-wiki-osm/36814">
|
|
|
|
Venez discuter QualiWiki sur le forum
|
|
|
|
</a>
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Liste des pages wiki</h2>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="card-body">
|
2025-09-03 17:18:21 +02:00
|
|
|
{% if wiki_pages_stats is defined %}
|
|
|
|
<div class="alert alert-info mb-3">
|
|
|
|
<h4>Statistiques des pages wiki</h4>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-6">
|
|
|
|
<h5>Pages en anglais</h5>
|
|
|
|
<ul>
|
|
|
|
<li><strong>Sections :</strong> Moyenne: {{ wiki_pages_stats.en_sections.mean }}, Écart type: {{ wiki_pages_stats.en_sections.std_dev }}</li>
|
|
|
|
<li><strong>Mots :</strong> Moyenne: {{ wiki_pages_stats.en_words.mean }}, Écart type: {{ wiki_pages_stats.en_words.std_dev }}</li>
|
|
|
|
<li><strong>Liens :</strong> Moyenne: {{ wiki_pages_stats.en_links.mean }}, Écart type: {{ wiki_pages_stats.en_links.std_dev }}</li>
|
|
|
|
<li><strong>Images :</strong> Moyenne: {{ wiki_pages_stats.en_media.mean }}, Écart type: {{ wiki_pages_stats.en_media.std_dev }}</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
|
|
<h5>Pages en français</h5>
|
|
|
|
<ul>
|
|
|
|
<li><strong>Sections :</strong> Moyenne: {{ wiki_pages_stats.fr_sections.mean }}, Écart type: {{ wiki_pages_stats.fr_sections.std_dev }}</li>
|
|
|
|
<li><strong>Mots :</strong> Moyenne: {{ wiki_pages_stats.fr_words.mean }}, Écart type: {{ wiki_pages_stats.fr_words.std_dev }}</li>
|
|
|
|
<li><strong>Liens :</strong> Moyenne: {{ wiki_pages_stats.fr_links.mean }}, Écart type: {{ wiki_pages_stats.fr_links.std_dev }}</li>
|
|
|
|
<li><strong>Images :</strong> Moyenne: {{ wiki_pages_stats.fr_media.mean }}, Écart type: {{ wiki_pages_stats.fr_media.std_dev }}</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
2025-09-01 18:28:23 +02:00
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
<thead class="thead-dark">
|
|
|
|
<tr>
|
|
|
|
<th rowspan="2">Image</th>
|
|
|
|
<th rowspan="2">Clé</th>
|
|
|
|
<th colspan="4" class="text-center">Différences FR vs EN</th>
|
|
|
|
<th rowspan="2" class="text-center">Score de<br>décrépitude</th>
|
|
|
|
<th rowspan="2" class="text-center">Liens</th>
|
|
|
|
</tr>
|
|
|
|
<tr>
|
|
|
|
<th class="text-center">Sections</th>
|
|
|
|
<th class="text-center">Mots</th>
|
|
|
|
<th class="text-center">Liens</th>
|
|
|
|
<th class="text-center">Images</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for key, languages in wiki_pages %}
|
|
|
|
{% if languages['en'] is defined and languages['fr'] is defined %}
|
|
|
|
<tr>
|
|
|
|
|
|
|
|
<td>
|
|
|
|
<img src="{{ languages['en'].description_img_url }}" alt="image"
|
|
|
|
style="height: 2rem;">
|
|
|
|
|
|
|
|
</td>
|
|
|
|
<td>
|
2025-09-03 16:34:33 +02:00
|
|
|
<a href="https://wiki.openstreetmap.org/wiki/{{ key }}">
|
2025-09-01 18:28:23 +02:00
|
|
|
<strong>{{ key }}</strong>
|
2025-09-03 16:04:16 +02:00
|
|
|
</a>
|
2025-09-01 18:28:23 +02:00
|
|
|
</td>
|
|
|
|
|
|
|
|
{% set diff = page_differences[key] %}
|
|
|
|
|
|
|
|
<td class="text-center">
|
|
|
|
{% if diff.section_diff > 0 %}
|
|
|
|
<span class="badge bg-success">{{ diff.section_diff_formatted }}</span>
|
|
|
|
{% elseif diff.section_diff < 0 %}
|
|
|
|
<span class="badge bg-danger">{{ diff.section_diff_formatted }}</span>
|
|
|
|
{% else %}
|
|
|
|
<span class="badge bg-secondary">0</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td class="text-center">
|
|
|
|
{% if diff.word_diff > 0 %}
|
|
|
|
<span class="badge bg-success">{{ diff.word_diff_formatted }}</span>
|
|
|
|
{% elseif diff.word_diff < 0 %}
|
|
|
|
<span class="badge bg-danger">{{ diff.word_diff_formatted }}</span>
|
|
|
|
{% else %}
|
|
|
|
<span class="badge bg-secondary">0</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td class="text-center">
|
|
|
|
{% if diff.link_diff > 0 %}
|
|
|
|
<span class="badge bg-success">{{ diff.link_diff_formatted }}</span>
|
|
|
|
{% elseif diff.link_diff < 0 %}
|
|
|
|
<span class="badge bg-danger">{{ diff.link_diff_formatted }}</span>
|
|
|
|
{% else %}
|
|
|
|
<span class="badge bg-secondary">0</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td class="text-center">
|
|
|
|
{% if diff.media_diff > 0 %}
|
|
|
|
<span class="badge bg-success">{{ diff.media_diff_formatted }}</span>
|
|
|
|
{% elseif diff.media_diff < 0 %}
|
|
|
|
<span class="badge bg-danger">{{ diff.media_diff_formatted }}</span>
|
|
|
|
{% else %}
|
|
|
|
<span class="badge bg-secondary">0</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
|
|
|
|
<td class="text-center">
|
|
|
|
{% set score = languages['en'].staleness_score|default(0) %}
|
|
|
|
{% if score > 50 %}
|
|
|
|
<span class="badge bg-danger">{{ score }}</span>
|
|
|
|
{% elseif score > 20 %}
|
|
|
|
<span class="badge bg-warning text-dark">{{ score }}</span>
|
|
|
|
{% else %}
|
|
|
|
<span class="badge bg-success">{{ score }}</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
<td class="text-center">
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
<a href="{{ languages['en'].url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-primary" title="Version anglaise">
|
|
|
|
<i class="bi bi-translate"></i> EN
|
|
|
|
</a>
|
|
|
|
<a href="{{ languages['fr'].url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-info" title="Version française">
|
|
|
|
<i class="bi bi-translate"></i> FR
|
|
|
|
</a>
|
|
|
|
<a href="{{ path('app_admin_wiki_compare', {'key': key}) }}"
|
|
|
|
class="btn btn-sm btn-outline-secondary" title="Comparer les versions">
|
|
|
|
<i class="bi bi-arrows-angle-expand"></i> Comparer
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endif %}
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{% if missing_translations|length > 0 %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-warning text-dark">
|
|
|
|
<h2>Pages manquantes en français ({{ missing_translations|length }})</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Ces pages wiki ont une version anglaise mais pas de traduction française.</p>
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
<thead class="thead-dark">
|
|
|
|
<tr>
|
|
|
|
<th>Clé</th>
|
|
|
|
<th>Sections</th>
|
|
|
|
<th>Mots</th>
|
|
|
|
<th>Liens</th>
|
|
|
|
<th>Actions</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for key, page in missing_translations %}
|
|
|
|
<tr>
|
|
|
|
<td><strong>{{ key }}</strong></td>
|
|
|
|
<td>{{ page.sections }}</td>
|
|
|
|
<td>{{ page.word_count }}</td>
|
|
|
|
<td>{{ page.link_count }}</td>
|
|
|
|
<td class="text-center">
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
<a href="{{ page.url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-info" title="Version anglaise">
|
|
|
|
<i class="bi bi-flag-fill"></i> EN
|
|
|
|
</a>
|
|
|
|
<a href="{{ path('app_admin_wiki_create_french', {'key': key}) }}"
|
|
|
|
class="btn btn-sm btn-success"
|
|
|
|
title="Créer une traduction française">
|
|
|
|
<i class="bi bi-plus-circle"></i> Traduire
|
|
|
|
</a>
|
2025-09-04 00:15:25 +02:00
|
|
|
{% if available_translations[key] is defined %}
|
|
|
|
<a href="{{ path('app_admin_wiki_update_translation', {'key': key}) }}"
|
|
|
|
class="btn btn-sm btn-warning"
|
|
|
|
title="Mettre à jour la traduction automatique">
|
|
|
|
<i class="bi bi-arrow-clockwise"></i> Mettre à jour
|
|
|
|
</a>
|
|
|
|
{% else %}
|
|
|
|
<a href="{{ path('app_admin_wiki_translate', {'key': key}) }}"
|
|
|
|
class="btn btn-sm btn-primary"
|
|
|
|
title="Traduire automatiquement avec Ollama">
|
|
|
|
<i class="bi bi-robot"></i> Auto traduire
|
|
|
|
</a>
|
|
|
|
{% endif %}
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
{% if available_translations is defined and available_translations|length > 0 %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h2>Traductions automatiques disponibles ({{ available_translations|length }})</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Ces pages ont été traduites automatiquement par le modèle Mistral:7b via Ollama. Vous pouvez copier le contenu pour créer une page wiki.</p>
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
<thead class="thead-dark">
|
|
|
|
<tr>
|
|
|
|
<th>Clé</th>
|
|
|
|
<th>Date de traduction</th>
|
|
|
|
<th>Modèle</th>
|
|
|
|
<th>Actions</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for key, translation in available_translations %}
|
|
|
|
<tr>
|
|
|
|
<td><strong>{{ key }}</strong></td>
|
|
|
|
<td>{{ translation.translated_at|date('Y-m-d H:i:s') }}</td>
|
|
|
|
<td>{{ translation.model }}</td>
|
|
|
|
<td class="text-center">
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
<a href="{{ translation.en_page.url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-info" title="Version anglaise">
|
|
|
|
<i class="bi bi-flag-fill"></i> EN
|
|
|
|
</a>
|
|
|
|
<button class="btn btn-sm btn-success copy-translation"
|
|
|
|
data-translation="{{ translation.translated_content|e('html_attr') }}"
|
|
|
|
title="Copier la traduction">
|
|
|
|
<i class="bi bi-clipboard"></i> Copier
|
|
|
|
</button>
|
|
|
|
<a href="{{ path('app_admin_wiki_update_translation', {'key': key}) }}"
|
|
|
|
class="btn btn-sm btn-warning"
|
|
|
|
title="Mettre à jour la traduction">
|
|
|
|
<i class="bi bi-arrow-clockwise"></i> Mettre à jour
|
|
|
|
</a>
|
|
|
|
<a href="{{ path('app_admin_wiki_create_french', {'key': key}) }}"
|
|
|
|
class="btn btn-sm btn-primary"
|
|
|
|
title="Créer une page wiki avec cette traduction">
|
|
|
|
<i class="bi bi-plus-circle"></i> Créer page
|
|
|
|
</a>
|
2025-09-01 18:28:23 +02:00
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
{% if specific_pages is defined and specific_pages|length > 0 %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-primary text-white">
|
|
|
|
<h2>Pages spécifiques ({{ specific_pages|length }})</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Ces pages wiki sont des pages spécifiques qui ont été sélectionnées pour une comparaison
|
|
|
|
particulière.</p>
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
<thead class="thead-dark">
|
|
|
|
<tr>
|
|
|
|
<th>Titre</th>
|
|
|
|
<th>Raison</th>
|
|
|
|
<th>Score de décrépitude</th>
|
|
|
|
<th>Actions</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for page in specific_pages %}
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<div class="d-flex align-items-center">
|
|
|
|
{% if page.en_page.description_img_url is defined and page.en_page.description_img_url %}
|
|
|
|
<div class="me-3">
|
|
|
|
<img src="{{ page.en_page.description_img_url }}"
|
|
|
|
alt="{{ page.key }}"
|
|
|
|
style="max-width: 80px; max-height: 60px; object-fit: contain;">
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
<div>
|
|
|
|
<strong>{{ page.key }}</strong>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{{ page.reason }}
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{% if page.staleness_score is defined %}
|
|
|
|
<div class="progress" style="height: 20px;">
|
|
|
|
{% set score_class = page.staleness_score > 70 ? 'bg-danger' : (page.staleness_score > 40 ? 'bg-warning' : 'bg-success') %}
|
|
|
|
<div class="progress-bar {{ score_class }}" role="progressbar"
|
|
|
|
style="width: {{ page.staleness_score }}%;"
|
|
|
|
aria-valuenow="{{ page.staleness_score }}"
|
|
|
|
aria-valuemin="0"
|
|
|
|
aria-valuemax="100">
|
|
|
|
{{ page.staleness_score }}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% else %}
|
|
|
|
<span class="text-muted">Non disponible</span>
|
|
|
|
{% endif %}
|
|
|
|
</td>
|
|
|
|
<td class="text-center">
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
<a href="{{ page.en_page.url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-primary" title="Version anglaise">
|
|
|
|
<i class="bi bi-translate"></i> EN
|
|
|
|
</a>
|
|
|
|
{% if page.fr_page %}
|
|
|
|
<a href="{{ page.fr_page.url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-info" title="Version française">
|
|
|
|
<i class="bi bi-translate"></i> FR
|
|
|
|
</a>
|
|
|
|
<a href="{{ path('app_admin_wiki_compare', {'key': page.key}) }}"
|
|
|
|
class="btn btn-sm btn-outline-secondary"
|
|
|
|
title="Comparer les versions">
|
|
|
|
<i class="bi bi-arrows-angle-expand"></i> Comparer
|
|
|
|
</a>
|
|
|
|
{% else %}
|
|
|
|
<a href="{{ path('app_admin_wiki_create_french', {'key': page.key}) }}"
|
|
|
|
class="btn btn-sm btn-success"
|
|
|
|
title="Créer une traduction française">
|
|
|
|
<i class="bi bi-plus-circle"></i> Traduire
|
|
|
|
</a>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
{% if pages_unavailable_in_english|length > 0 %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-info text-dark">
|
|
|
|
<h2>Pages françaises non disponibles en Anglais ({{ pages_unavailable_in_english|length }})</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Ces pages wiki ont une version française mais pas de traduction anglaise.</p>
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
<thead class="thead-dark">
|
|
|
|
<tr>
|
|
|
|
<th>Titre</th>
|
2025-09-03 17:18:21 +02:00
|
|
|
{# <th>Score de décrépitude</th>#}
|
2025-09-01 18:28:23 +02:00
|
|
|
<th>Actions</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for page in pages_unavailable_in_english %}
|
2025-09-03 17:18:21 +02:00
|
|
|
{% if "FR:Réunions" not in page.title %}
|
2025-09-01 18:28:23 +02:00
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<div class="d-flex align-items-center">
|
|
|
|
{% if page.description_img_url is defined and page.description_img_url %}
|
|
|
|
<div class="me-3">
|
|
|
|
<img src="{{ page.description_img_url }}" alt="{{ page.title }}"
|
|
|
|
style="max-width: 80px; max-height: 60px; object-fit: contain;">
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
<div>
|
|
|
|
<strong>{{ page.title }}</strong>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</td>
|
2025-09-03 17:18:21 +02:00
|
|
|
{# <td>#}
|
|
|
|
{# {% if page.outdatedness_score is defined %}#}
|
|
|
|
{# <div class="progress" style="height: 20px;">#}
|
|
|
|
{# {% set score_class = page.outdatedness_score > 70 ? 'bg-danger' : (page.outdatedness_score > 40 ? 'bg-warning' : 'bg-success') %}#}
|
|
|
|
{# <div class="progress-bar {{ score_class }}" role="progressbar"#}
|
|
|
|
{# style="width: {{ page.outdatedness_score }}%;"#}
|
|
|
|
{# aria-valuenow="{{ page.outdatedness_score }}"#}
|
|
|
|
{# aria-valuemin="0"#}
|
|
|
|
{# aria-valuemax="100">#}
|
|
|
|
{# {{ page.outdatedness_score }}#}
|
|
|
|
{# </div>#}
|
|
|
|
{# </div>#}
|
|
|
|
{# {% else %}#}
|
|
|
|
{# <span class="text-muted">Non disponible</span>#}
|
|
|
|
{# {% endif %}#}
|
|
|
|
{# </td>#}
|
2025-09-01 18:28:23 +02:00
|
|
|
<td class="text-center">
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
<a href="{{ page.url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-info" title="Version française">
|
|
|
|
<i class="bi bi-flag-fill"></i> FR
|
|
|
|
</a>
|
|
|
|
{% set en_url = page.url|replace({'FR:': ''}) %}
|
|
|
|
<a href="{{ en_url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-primary"
|
|
|
|
title="Créer une traduction anglaise">
|
|
|
|
<i class="bi bi-translate"></i> créer EN
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
</tr>
|
2025-09-03 17:18:21 +02:00
|
|
|
{% endif %}
|
2025-09-01 18:28:23 +02:00
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
{% if newly_created_pages is defined and newly_created_pages|length > 0 %}
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header bg-success text-white">
|
|
|
|
<h2>Pages françaises récemment créées ({{ newly_created_pages|length }})</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
|
|
<p>Ces pages wiki françaises ont été récemment créées et étaient auparavant dans la liste des pages
|
|
|
|
non disponibles en français.</p>
|
|
|
|
<div class="table-responsive">
|
|
|
|
<table class="table table-striped table-hover">
|
|
|
|
<thead class="thead-dark">
|
|
|
|
<tr>
|
|
|
|
<th>Titre</th>
|
|
|
|
<th>Version anglaise</th>
|
|
|
|
<th>Date de création</th>
|
|
|
|
<th>Créée par</th>
|
|
|
|
<th>Actions</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
{% for page in newly_created_pages %}
|
|
|
|
<tr>
|
|
|
|
<td>
|
|
|
|
<div class="d-flex align-items-center">
|
|
|
|
<div>
|
|
|
|
<strong>{{ page.title }}</strong>
|
|
|
|
<span class="badge bg-success">Nouvelle</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{{ page.en_title }}
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{{ page.created_at }}
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
{{ page.created_by }}
|
|
|
|
</td>
|
|
|
|
<td class="text-center">
|
|
|
|
<div class="btn-group" role="group">
|
|
|
|
<a href="{{ page.url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-info" title="Version française">
|
|
|
|
<i class="bi bi-flag-fill"></i> FR
|
|
|
|
</a>
|
|
|
|
<a href="{{ page.en_url }}" target="_blank"
|
|
|
|
class="btn btn-sm btn-outline-primary" title="Version anglaise">
|
|
|
|
<i class="bi bi-flag-fill"></i> EN
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
{% endfor %}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
<p>
|
|
|
|
le score de fraîcheur prend en compte d'avantage la différence entre le nombre de mots que l'ancienneté de
|
|
|
|
modification.
|
|
|
|
On compte aussi le nombre de sections et de liens.
|
|
|
|
</p>
|
|
|
|
<div class="mt-3">
|
|
|
|
<div class="card mb-4">
|
|
|
|
<div class="card-header">
|
|
|
|
<h2>Graphe de décrépitude</h2>
|
|
|
|
</div>
|
|
|
|
<div class="card-body">
|
2025-09-03 17:18:21 +02:00
|
|
|
{% if staleness_stats is defined %}
|
|
|
|
<div class="alert alert-info mb-3">
|
|
|
|
<strong>Statistiques :</strong>
|
|
|
|
Moyenne : {{ staleness_stats.mean }} |
|
|
|
|
Écart type : {{ staleness_stats.std_dev }} |
|
|
|
|
Min : {{ staleness_stats.min }} |
|
|
|
|
Max : {{ staleness_stats.max }} |
|
|
|
|
Nombre de pages : {{ staleness_stats.count }}
|
|
|
|
</div>
|
|
|
|
{% endif %}
|
2025-09-01 18:28:23 +02:00
|
|
|
<canvas id="decrepitudeChart" height="300"></canvas>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
{% block javascripts %}
|
|
|
|
{{ parent() }}
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
|
|
<script>
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
2025-09-04 00:15:25 +02:00
|
|
|
// Handle copy translation buttons
|
|
|
|
const copyButtons = document.querySelectorAll('.copy-translation');
|
|
|
|
copyButtons.forEach(button => {
|
|
|
|
button.addEventListener('click', function() {
|
|
|
|
const translation = this.getAttribute('data-translation');
|
|
|
|
|
|
|
|
// Create a temporary textarea element to copy from
|
|
|
|
const textarea = document.createElement('textarea');
|
|
|
|
textarea.value = translation;
|
|
|
|
textarea.setAttribute('readonly', '');
|
|
|
|
textarea.style.position = 'absolute';
|
|
|
|
textarea.style.left = '-9999px';
|
|
|
|
document.body.appendChild(textarea);
|
|
|
|
|
|
|
|
// Select and copy the text
|
|
|
|
textarea.select();
|
|
|
|
document.execCommand('copy');
|
|
|
|
|
|
|
|
// Remove the textarea
|
|
|
|
document.body.removeChild(textarea);
|
|
|
|
|
|
|
|
// Change button text temporarily to indicate success
|
|
|
|
const originalText = this.innerHTML;
|
|
|
|
this.innerHTML = '<i class="bi bi-check"></i> Copié!';
|
|
|
|
this.classList.remove('btn-success');
|
|
|
|
this.classList.add('btn-outline-success');
|
|
|
|
|
|
|
|
// Restore original button text after a delay
|
|
|
|
setTimeout(() => {
|
|
|
|
this.innerHTML = originalText;
|
|
|
|
this.classList.remove('btn-outline-success');
|
|
|
|
this.classList.add('btn-success');
|
|
|
|
}, 2000);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Collect data for the chart
|
2025-09-01 18:28:23 +02:00
|
|
|
const labels = [];
|
|
|
|
const scores = [];
|
|
|
|
const colors = [];
|
|
|
|
|
|
|
|
{% for key, languages in wiki_pages %}
|
|
|
|
{% if languages['en'] is defined and languages['fr'] is defined %}
|
|
|
|
labels.push("{{ key }}");
|
|
|
|
{% set score = languages['en'].staleness_score|default(0) %}
|
|
|
|
scores.push({{ score }});
|
|
|
|
|
2025-09-03 17:18:21 +02:00
|
|
|
// Set color based on score with more nuanced intermediate colors
|
|
|
|
{% if score > 80 %}
|
|
|
|
colors.push('rgba(220, 53, 69, 0.7)'); // danger (red)
|
|
|
|
{% elseif score > 60 %}
|
|
|
|
colors.push('rgba(232, 113, 55, 0.7)'); // dark orange
|
|
|
|
{% elseif score > 40 %}
|
|
|
|
colors.push('rgba(255, 153, 0, 0.7)'); // orange
|
2025-09-01 18:28:23 +02:00
|
|
|
{% elseif score > 20 %}
|
2025-09-03 17:18:21 +02:00
|
|
|
colors.push('rgba(255, 193, 7, 0.7)'); // warning (yellow)
|
|
|
|
{% elseif score > 10 %}
|
|
|
|
colors.push('rgba(140, 195, 38, 0.7)'); // light green
|
2025-09-01 18:28:23 +02:00
|
|
|
{% else %}
|
2025-09-03 17:18:21 +02:00
|
|
|
colors.push('rgba(25, 135, 84, 0.7)'); // success (green)
|
2025-09-01 18:28:23 +02:00
|
|
|
{% endif %}
|
|
|
|
{% endif %}
|
|
|
|
{% endfor %}
|
|
|
|
|
|
|
|
// Sort data by score (descending)
|
|
|
|
const indices = Array.from(Array(scores.length).keys())
|
|
|
|
.sort((a, b) => scores[b] - scores[a]);
|
|
|
|
|
|
|
|
const sortedLabels = indices.map(i => labels[i]);
|
|
|
|
const sortedScores = indices.map(i => scores[i]);
|
|
|
|
const sortedColors = indices.map(i => colors[i]);
|
|
|
|
|
|
|
|
// Limit to top 20 pages for readability
|
|
|
|
const displayLimit = 20;
|
|
|
|
const displayLabels = sortedLabels.slice(0, displayLimit);
|
|
|
|
const displayScores = sortedScores.slice(0, displayLimit);
|
|
|
|
const displayColors = sortedColors.slice(0, displayLimit);
|
|
|
|
|
|
|
|
// Create the chart
|
|
|
|
const ctx = document.getElementById('decrepitudeChart').getContext('2d');
|
|
|
|
new Chart(ctx, {
|
|
|
|
type: 'bar',
|
|
|
|
data: {
|
|
|
|
labels: displayLabels,
|
|
|
|
datasets: [{
|
|
|
|
label: 'Score de décrépitude',
|
|
|
|
data: displayScores,
|
|
|
|
backgroundColor: displayColors,
|
|
|
|
borderColor: displayColors.map(c => c.replace('0.7', '1')),
|
|
|
|
borderWidth: 1
|
|
|
|
}]
|
|
|
|
},
|
|
|
|
options: {
|
|
|
|
indexAxis: 'y',
|
|
|
|
responsive: true,
|
|
|
|
plugins: {
|
|
|
|
legend: {
|
|
|
|
display: false
|
|
|
|
},
|
|
|
|
tooltip: {
|
|
|
|
callbacks: {
|
|
|
|
label: function (context) {
|
|
|
|
return `Score: ${context.raw}`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
scales: {
|
|
|
|
x: {
|
|
|
|
beginAtZero: true,
|
|
|
|
max: 100,
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
text: 'Score de décrépitude (0-100)'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
{% endblock %}
|