Sélection par séance, réordonnancement et exclusion vie du labo
This commit is contained in:
@@ -118,7 +118,7 @@ class Thalim_NL_Admin_Page {
|
||||
</div>
|
||||
|
||||
<div id="thalim-nl-sections-wrap">
|
||||
<?php echo $this->render_sections_html($month_data, $existing_sections); ?>
|
||||
<?php echo $this->render_sections_html($month_data, $existing ? $existing_sections : null); ?>
|
||||
</div>
|
||||
|
||||
<div class="thalim-nl-conclusion">
|
||||
@@ -213,9 +213,18 @@ class Thalim_NL_Admin_Page {
|
||||
// Sections HTML (shared between initial render and AJAX)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
public function render_sections_html(array $month_data, array $checked_ids = []): string {
|
||||
/**
|
||||
* @param array $month_data Posts grouped by category for the month.
|
||||
* @param array|null $checked_ids Saved selection (cat_id => [post_id,...]) for an
|
||||
* existing newsletter. Pass null for a fresh month:
|
||||
* every item is then checked by default.
|
||||
*/
|
||||
public function render_sections_html(array $month_data, ?array $checked_ids = null): string {
|
||||
$groups = Thalim_NL_Post_Query::get_eligible_categories();
|
||||
|
||||
// No saved newsletter yet → everything checked by default.
|
||||
$check_all = ($checked_ids === null);
|
||||
|
||||
ob_start();
|
||||
$has_content = false;
|
||||
|
||||
@@ -249,8 +258,17 @@ class Thalim_NL_Admin_Page {
|
||||
continue;
|
||||
}
|
||||
$count = count($posts);
|
||||
$checked_in_section = (array) ($checked_ids[$cat_id] ?? $checked_ids[(string) $cat_id] ?? []);
|
||||
$has_checked = !empty($checked_in_section);
|
||||
$checked_in_section = $check_all
|
||||
? []
|
||||
: (array) ($checked_ids[$cat_id] ?? $checked_ids[(string) $cat_id] ?? []);
|
||||
$has_checked = $check_all || !empty($checked_in_section);
|
||||
|
||||
// Restore the saved drag-and-drop order ($checked_in_section is
|
||||
// stored in submit order). For seminars this also reorders the
|
||||
// seminar groups, since grouping below follows first appearance.
|
||||
if (!$check_all) {
|
||||
$posts = $this->reorder_posts_by_saved($posts, $checked_in_section);
|
||||
}
|
||||
?>
|
||||
<details class="thalim-nl-section" <?php if ($has_checked) echo 'open'; ?>>
|
||||
<summary class="thalim-nl-section-summary">
|
||||
@@ -258,49 +276,67 @@ class Thalim_NL_Admin_Page {
|
||||
<span class="thalim-nl-count">(<?php echo $count; ?>)</span>
|
||||
</summary>
|
||||
<div class="thalim-nl-section-body">
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<label class="thalim-nl-post-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="nl_sections[<?php echo (int) $cat_id; ?>][]"
|
||||
value="<?php echo (int) $post['id']; ?>"
|
||||
<?php checked(in_array((int) $post['id'], $checked_in_section)); ?>
|
||||
>
|
||||
<span class="thalim-nl-post-title"><?php echo esc_html($post['title']); ?></span>
|
||||
<a href="<?php echo esc_url($post['permalink']); ?>" target="_blank" rel="noopener"
|
||||
class="thalim-nl-post-view" title="Voir sur le site">
|
||||
<span class="dashicons dashicons-visibility"></span>
|
||||
</a>
|
||||
<span class="thalim-nl-post-date"><?php echo esc_html($this->format_post_date_hint($post)); ?></span>
|
||||
</label>
|
||||
<?php if (!empty($post['seances'])): ?>
|
||||
<ul class="thalim-nl-seances-list">
|
||||
<?php foreach ($post['seances'] as $seance): ?>
|
||||
<li class="thalim-nl-seance-item">
|
||||
<span class="thalim-nl-seance-title"><?php echo esc_html($seance['title']); ?></span>
|
||||
<span class="thalim-nl-seance-meta">
|
||||
<?php
|
||||
$parts = [];
|
||||
if ($seance['date_debut']) {
|
||||
$ts = strtotime($seance['date_debut']);
|
||||
$parts[] = $ts ? date_i18n('j M Y', $ts) : '';
|
||||
}
|
||||
if ($seance['heure_de_debut']) {
|
||||
$time = $seance['heure_de_debut'];
|
||||
if ($seance['heure_de_fin']) $time .= '–' . $seance['heure_de_fin'];
|
||||
$parts[] = $time;
|
||||
}
|
||||
if ($seance['lieu']) {
|
||||
$parts[] = $seance['lieu'];
|
||||
}
|
||||
echo esc_html(implode(' · ', array_filter($parts)));
|
||||
?>
|
||||
</span>
|
||||
</li>
|
||||
<?php if ((int) $cat_id === THALIM_NL_CAT_SEMINAIRES): ?>
|
||||
<?php
|
||||
// Seminars: posts are séance items carrying their parent
|
||||
// seminar. Group them under a (non-selectable) seminar
|
||||
// header; each séance is an individual checkbox.
|
||||
$by_seminar = [];
|
||||
foreach ($posts as $seance) {
|
||||
$sem_id = (int) $seance['seminar_id'];
|
||||
if (!isset($by_seminar[$sem_id])) {
|
||||
$by_seminar[$sem_id] = [
|
||||
'title' => $seance['seminar_title'],
|
||||
'permalink' => $seance['seminar_permalink'],
|
||||
'seances' => [],
|
||||
];
|
||||
}
|
||||
$by_seminar[$sem_id]['seances'][] = $seance;
|
||||
}
|
||||
?>
|
||||
<?php foreach ($by_seminar as $sem): ?>
|
||||
<div class="thalim-nl-seminar-group">
|
||||
<div class="thalim-nl-seminar-title">
|
||||
<span class="thalim-nl-drag-handle dashicons dashicons-menu" title="Glisser pour réordonner les séminaires" aria-hidden="true"></span>
|
||||
<span class="thalim-nl-seminar-name"><?php echo esc_html($sem['title']); ?></span>
|
||||
<a href="<?php echo esc_url($sem['permalink']); ?>" target="_blank" rel="noopener"
|
||||
class="thalim-nl-post-view" title="Voir sur le site">
|
||||
<span class="dashicons dashicons-visibility"></span>
|
||||
</a>
|
||||
</div>
|
||||
<?php foreach ($sem['seances'] as $seance): ?>
|
||||
<label class="thalim-nl-post-row thalim-nl-seance-row">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="nl_sections[<?php echo (int) $cat_id; ?>][]"
|
||||
value="<?php echo (int) $seance['id']; ?>"
|
||||
<?php checked($check_all || in_array((int) $seance['id'], $checked_in_section)); ?>
|
||||
>
|
||||
<span class="thalim-nl-post-title"><?php echo esc_html($seance['title']); ?></span>
|
||||
<span class="thalim-nl-post-date"><?php echo esc_html($this->format_seance_hint($seance)); ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<?php foreach ($posts as $post): ?>
|
||||
<label class="thalim-nl-post-row">
|
||||
<span class="thalim-nl-drag-handle dashicons dashicons-menu" title="Glisser pour réordonner" aria-hidden="true"></span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="nl_sections[<?php echo (int) $cat_id; ?>][]"
|
||||
value="<?php echo (int) $post['id']; ?>"
|
||||
<?php checked($check_all || in_array((int) $post['id'], $checked_in_section)); ?>
|
||||
>
|
||||
<span class="thalim-nl-post-title"><?php echo esc_html($post['title']); ?></span>
|
||||
<a href="<?php echo esc_url($post['permalink']); ?>" target="_blank" rel="noopener"
|
||||
class="thalim-nl-post-view" title="Voir sur le site">
|
||||
<span class="dashicons dashicons-visibility"></span>
|
||||
</a>
|
||||
<span class="thalim-nl-post-date"><?php echo esc_html($this->format_post_date_hint($post)); ?></span>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</details>
|
||||
<?php endforeach; ?>
|
||||
@@ -331,6 +367,53 @@ class Thalim_NL_Admin_Page {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder $posts so items whose 'id' appears in $order come first, in
|
||||
* $order's sequence; the rest keep their query order, appended after.
|
||||
* Restores the editor's saved drag-and-drop order in the admin UI.
|
||||
*/
|
||||
private function reorder_posts_by_saved(array $posts, array $order): array {
|
||||
if (empty($order)) {
|
||||
return $posts;
|
||||
}
|
||||
$rank = array_flip(array_map('intval', array_values($order)));
|
||||
$keyed = [];
|
||||
foreach ($posts as $idx => $post) {
|
||||
$keyed[] = [
|
||||
'post' => $post,
|
||||
'rank' => $rank[(int) $post['id']] ?? PHP_INT_MAX,
|
||||
'idx' => $idx,
|
||||
];
|
||||
}
|
||||
// Sort by saved rank, then original index (stable for un-ranked items).
|
||||
usort($keyed, fn($a, $b) => [$a['rank'], $a['idx']] <=> [$b['rank'], $b['idx']]);
|
||||
return array_map(fn($x) => $x['post'], $keyed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Date · heure · lieu hint shown next to each séance checkbox.
|
||||
*/
|
||||
private function format_seance_hint(array $seance): string {
|
||||
$parts = [];
|
||||
if (!empty($seance['date_debut']) && !str_starts_with($seance['date_debut'], '0000-00-00')) {
|
||||
$ts = strtotime($seance['date_debut']);
|
||||
if ($ts) {
|
||||
$parts[] = date_i18n('j M Y', $ts);
|
||||
}
|
||||
}
|
||||
if (!empty($seance['heure_de_debut'])) {
|
||||
$time = $seance['heure_de_debut'];
|
||||
if (!empty($seance['heure_de_fin'])) {
|
||||
$time .= '–' . $seance['heure_de_fin'];
|
||||
}
|
||||
$parts[] = $time;
|
||||
}
|
||||
if (!empty($seance['lieu'])) {
|
||||
$parts[] = $seance['lieu'];
|
||||
}
|
||||
return implode(' · ', $parts);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Save
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -490,7 +573,7 @@ class Thalim_NL_Admin_Page {
|
||||
$unsubscribe_url = get_post_meta($existing->ID, '_newsletter_unsubscribe_url', true) ?: '';
|
||||
}
|
||||
|
||||
$html = $this->render_sections_html($month_data, $existing_sections);
|
||||
$html = $this->render_sections_html($month_data, $existing ? $existing_sections : null);
|
||||
|
||||
wp_send_json_success([
|
||||
'html' => $html,
|
||||
|
||||
Reference in New Issue
Block a user