Merge pull request 'v1.6.9 — tri titre/date dans admin/articles' (#77) from dev into main

Merge PR #77 : v1.6.9
This commit was merged in pull request #77.
This commit is contained in:
2026-05-15 19:20:19 +00:00
4 changed files with 59 additions and 5 deletions
+7
View File
@@ -9,6 +9,13 @@ Format : [Keep a Changelog](https://keepachangelog.com/fr/1.0.0/) — versionnag
---
## [1.6.9] - 2026-05-15
### Ajouté
- `/admin/articles` : tri par **Titre** (A→Z / Z→A) et par **Date** (publication) en cliquant les en-têtes de colonne — indicateur ↑ / ↓ sur la colonne active, paramètres `sort` et `dir` préservés lors du filtrage
---
## [1.6.8] - 2026-05-15
### Corrigé
+17 -2
View File
@@ -2333,7 +2333,6 @@ switch ($action) {
$me = currentUserEmail() ?? '';
$allArticles = array_values(array_filter($allArticles, fn ($a) => ($a['author'] ?? '') === $me));
}
usort($allArticles, fn ($a, $b) => strcmp($b['updated_at'] ?? '', $a['updated_at'] ?? ''));
$adminData['filter_authors'] = array_values(array_unique(array_filter(array_column($allArticles, 'author'))));
$adminData['filter_categories'] = array_values(array_unique(array_filter(array_column($allArticles, 'category'))));
@@ -2362,7 +2361,23 @@ switch ($action) {
$allArticles = array_values(array_filter($allArticles, fn ($a) => $a['published'] && strtotime((string)($a['published_at'] ?? '')) > $nowTs));
}
$adminData['articles'] = $allArticles;
$sortBy = in_array($_GET['sort'] ?? '', ['title', 'published', 'updated']) ? $_GET['sort'] : 'updated';
$sortDir = ($_GET['dir'] ?? '') === 'asc' ? 'asc' : 'desc';
usort($allArticles, function ($a, $b) use ($sortBy, $sortDir) {
$cmp = match ($sortBy) {
'title' => strcmp($a['title'] ?? '', $b['title'] ?? ''),
'published' => strcmp(
$a['published_at'] ?? $a['created_at'] ?? '',
$b['published_at'] ?? $b['created_at'] ?? ''
),
default => strcmp($a['updated_at'] ?? '', $b['updated_at'] ?? ''),
};
return $sortDir === 'asc' ? $cmp : -$cmp;
});
$adminData['articles'] = $allArticles;
$adminData['sort_by'] = $sortBy;
$adminData['sort_dir'] = $sortDir;
}
if ($tab === 'roles') {
+1 -1
View File
@@ -1 +1 @@
1.6.8
1.6.9
+34 -2
View File
@@ -205,8 +205,30 @@ function adminStatusBadge(array $a, int $now): string
<!-- ─────────────────────────── ARTICLES ─────────────────────────── -->
<?php elseif ($tab === 'articles'): ?>
<?php
$_sortBy = $adminData['sort_by'] ?? 'updated';
$_sortDir = $adminData['sort_dir'] ?? 'desc';
$_mkSortUrl = function (string $col) use ($_sortBy, $_sortDir, $adminData): string {
$dir = ($_sortBy === $col && $_sortDir === 'asc') ? 'desc' : 'asc';
$p = array_filter([
'filter_author' => $adminData['filter_author'] ?? '',
'filter_category' => $adminData['filter_category'] ?? '',
'filter_status' => $adminData['filter_status'] ?? '',
], fn ($v) => $v !== '');
$p['sort'] = $col;
$p['dir'] = $dir;
return '/admin/articles?' . http_build_query($p);
};
$_sortIcon = function (string $col) use ($_sortBy, $_sortDir): string {
if ($_sortBy !== $col) { return '<span class="text-muted ms-1" style="font-size:.75em">↕</span>'; }
return '<span class="ms-1" style="font-size:.75em">' . ($_sortDir === 'asc' ? '↑' : '↓') . '</span>';
};
?>
<!-- Filtres -->
<form class="row g-2 align-items-center mb-3" method="get" action="/admin/articles">
<input type="hidden" name="sort" value="<?= htmlspecialchars($_sortBy) ?>">
<input type="hidden" name="dir" value="<?= htmlspecialchars($_sortDir) ?>">
<?php if (isAdmin() && !empty($adminData['filter_authors'])): ?>
<div class="col-auto">
<select name="filter_author" class="form-select form-select-sm">
@@ -273,11 +295,21 @@ function adminStatusBadge(array $a, int $now): string
<thead>
<tr>
<th style="width:2rem"></th>
<th>Titre</th>
<th>
<a href="<?= htmlspecialchars($_mkSortUrl('title')) ?>"
class="text-decoration-none text-reset">
Titre<?= $_sortIcon('title') ?>
</a>
</th>
<?php if (isAdmin()): ?><th>Auteur</th><?php endif; ?>
<th>Catégorie</th>
<th>Statut</th>
<th>Date</th>
<th>
<a href="<?= htmlspecialchars($_mkSortUrl('published')) ?>"
class="text-decoration-none text-reset">
Date<?= $_sortIcon('published') ?>
</a>
</th>
<th></th>
</tr>
</thead>