Files
thalim-plugin-newsletter/assets/admin.js
T
valentin_le_moignandClaude Opus 5 3cf09ea74f Annonces à venir proposées, et dates d'événement au lieu des dates de publication
Retour du commanditaire après le premier envoi réel (juillet 2026) : des
annonces à venir n'étaient pas proposées à la coche, et les dates affichées
étaient les dates de publication.

- Fenêtre « à venir » de 12 mois (FUTURE_HORIZON_MONTHS), démarrant à la fin
  du mois de la newsletter ou à aujourd'hui si ce mois est passé, en
  remplacement du plafond « début de fenêtre <= fin du mois ». Idem pour les
  séances (SEANCE_WINDOW_MARGIN_DAYS de 5 jours supprimée). Ces items sont
  regroupés dans un bloc « À venir », décochés par défaut.
- event_date_label() centralise les libellés du thème (« Le X de H1 à H2 »,
  « Du X au Y », « Jusqu'au X », « X à H ») sur la convention
  date_de_debut > datetime > post_date. Utilisée par l'export et par la
  pastille de la liste à cocher, qui affichent donc la même chose.
- Tri par date d'événement (sql_event_date_order) et non par date de
  publication.
- Fenêtres de fin « +35 j » et « +3 mois » recalées sur la date d'événement :
  un événement annoncé plus de 35 jours à l'avance sortait de la fenêtre
  avant d'avoir eu lieu et manquait dans la newsletter de son propre mois.
- merge_selected_items() : une sélection déjà enregistrée est réinjectée dans
  la liste même si ses items sont sortis de la fenêtre — sans ça, rouvrir puis
  réenregistrer une ancienne newsletter l'amputait silencieusement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w7RzAHv4r1Yahnm2NwDDG
2026-08-27 17:48:08 +02:00

188 lines
7.2 KiB
JavaScript

/* global thalimNL, tinymce */
(function ($) {
'use strict';
// -------------------------------------------------------------------------
// Drag-and-drop reordering of items within each category list.
// The submit order of checkboxes follows DOM order, and the exporter
// renders each section in stored order — so reordering rows here is enough
// for the new order to appear in the generated HTML after saving.
// -------------------------------------------------------------------------
function makeSortable($container, itemSelector) {
if (!$.fn.sortable) return;
$container.sortable({
items: itemSelector,
handle: '.thalim-nl-drag-handle',
axis: 'y',
containment: 'parent',
tolerance: 'pointer',
cursor: 'grabbing',
opacity: 0.9,
placeholder: 'thalim-nl-sortable-placeholder',
forcePlaceholderSize: true,
});
}
function initSortable() {
var $root = $('#thalim-nl-sections-wrap');
$root.find('.thalim-nl-section-body').each(function () {
var $body = $(this);
if ($body.find('.thalim-nl-seminar-group').length) {
// Seminars: reorder whole seminars (séances stay chronological).
makeSortable($body, '> .thalim-nl-seminar-group');
} else {
// Normal categories: reorder post rows.
makeSortable($body, '> .thalim-nl-post-row');
}
});
// Le bloc « À venir » est une zone de tri à part, pour que ses lignes
// ne puissent pas se mélanger à celles du mois (l'ordre du DOM est
// l'ordre de soumission, donc l'ordre de rendu dans le mail).
$root.find('.thalim-nl-future').each(function () {
makeSortable($(this), '> .thalim-nl-post-row');
});
}
// A click on the drag handle must not toggle its enclosing checkbox label.
$(document).on('click', '.thalim-nl-drag-handle', function (e) {
e.preventDefault();
});
$(initSortable);
// -------------------------------------------------------------------------
// Month change → AJAX reload sections + update TinyMCE intro
// -------------------------------------------------------------------------
$('#thalim-nl-month').on('change', function () {
var month = $(this).val();
var $wrap = $('#thalim-nl-sections-wrap');
var $spin = $('.thalim-nl-spinner');
if (!month) return;
$spin.addClass('is-active');
$wrap.css('opacity', '0.5');
$.post(thalimNL.ajaxUrl, {
action: 'thalim_nl_load_month',
month: month,
_wpnonce: thalimNL.nonce,
})
.done(function (response) {
if (!response.success) return;
$wrap.html(response.data.html);
initSortable();
// Update TinyMCE intro — do NOT re-render wp_editor
var introEditor = typeof tinymce !== 'undefined' && tinymce.get('thalim_nl_intro');
if (introEditor) {
introEditor.setContent(response.data.intro || '');
} else {
$('#thalim_nl_intro').val(response.data.intro || '');
}
// Update TinyMCE conclusion
var conclusionEditor = typeof tinymce !== 'undefined' && tinymce.get('thalim_nl_conclusion');
if (conclusionEditor) {
conclusionEditor.setContent(response.data.conclusion || '');
} else {
$('#thalim_nl_conclusion').val(response.data.conclusion || '');
}
// Update subscribe/unsubscribe URLs
$('#thalim-nl-subscribe').val(response.data.subscribe_url || '');
$('#thalim-nl-unsubscribe').val(response.data.unsubscribe_url || '');
})
.fail(function () {
$wrap.html('<p class="thalim-nl-empty">Erreur lors du chargement.</p>');
})
.always(function () {
$spin.removeClass('is-active');
$wrap.css('opacity', '1');
});
});
// -------------------------------------------------------------------------
// Fetch newsletter HTML (shared by download & preview)
// -------------------------------------------------------------------------
function fetchNewsletterHTML(postId) {
return $.post(thalimNL.ajaxUrl, {
action: 'thalim_nl_export_html',
post_id: postId,
_wpnonce: thalimNL.nonce,
});
}
// -------------------------------------------------------------------------
// Download HTML file
// -------------------------------------------------------------------------
$(document).on('click', '.thalim-nl-download', function () {
var $btn = $(this);
var postId = $btn.data('post-id');
var filename = $btn.data('filename') || 'newsletter-THALIM.html';
var origText = $btn.text();
$btn.prop('disabled', true).text('…');
fetchNewsletterHTML(postId)
.done(function (response) {
if (!response.success) {
alert('Erreur : ' + (response.data || 'Impossible d\'exporter le HTML.'));
return;
}
var blob = new Blob([response.data.html], { type: 'text/html;charset=utf-8' });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
})
.fail(function () {
alert('Erreur réseau lors de l\'export.');
})
.always(function () {
$btn.prop('disabled', false).text(origText);
});
});
// -------------------------------------------------------------------------
// Preview in new window
// -------------------------------------------------------------------------
$(document).on('click', '.thalim-nl-preview', function () {
var $btn = $(this);
var postId = $btn.data('post-id');
var origText = $btn.text();
$btn.prop('disabled', true).text('…');
fetchNewsletterHTML(postId)
.done(function (response) {
if (!response.success) {
alert('Erreur : ' + (response.data || 'Impossible de charger la prévisualisation.'));
return;
}
var win = window.open('', '_blank');
if (win) {
win.document.open();
win.document.write(response.data.html);
win.document.close();
} else {
alert('Le navigateur a bloqué l\'ouverture de la fenêtre. Autorisez les pop-ups pour ce site.');
}
})
.fail(function () {
alert('Erreur réseau lors du chargement.');
})
.always(function () {
$btn.prop('disabled', false).text(origText);
});
});
}(jQuery));