Implement auto-sync configuration for ChronoTrack API. Add functionality to save auto-sync settings, including frequency and end date, enhancing user control over synchronization. Update push panel to reflect new options and improve user feedback during the sync process. This change lays the groundwork for future cron integration.

This commit is contained in:
2026-07-14 12:08:03 -04:00
parent f9a75e8aba
commit 0db8da9810
4 changed files with 253 additions and 4 deletions

View File

@ -103,7 +103,7 @@ function fxChronotrackApiAdminRenderEventPage($intEveId, $strLangue = 'fr', $bln
// Sync dabord (usage courant) ; config repliable ensuite. MSIN-4328
if ($arrConfig !== null && $blnEventLinked && $blnConfigured) {
fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed);
fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed, $arrConfig);
}
if ($arrConfig !== null && $blnEventLinked) {
@ -244,7 +244,7 @@ function fxChronotrackApiAdminRenderRaceMapping($intEveId, $arrConfig, $strLangu
echo '</div></div></div>';
}
function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false) {
function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false, $arrConfig = null) {
echo '<div class="card mb-4 border-primary" id="ct_api_push_card">';
echo '<div class="card-header">Synchronisation ChronoTrack</div>';
echo '<div class="card-body">';
@ -252,7 +252,63 @@ function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false) {
echo '<div class="alert alert-warning py-2 small mb-2">Événement fermé — envoi manuel encore possible.</div>';
}
// Zone employé : statut clair + actions dabord. MSIN-4328
// MSIN-4328 — Phase A : config sync auto (exécutée plus tard par cron)
$blnAutoOn = (intval($arrConfig['auto_sync_enabled'] ?? 0) === 1);
$intAutoInterval = intval($arrConfig['auto_sync_interval_min'] ?? 15);
if (!in_array($intAutoInterval, array(1, 5, 15, 30, 60), true)) {
$intAutoInterval = 15;
}
$strUntilRaw = trim((string)($arrConfig['auto_sync_until'] ?? ''));
$strUntilLocal = '';
if ($strUntilRaw !== '' && $strUntilRaw !== '0000-00-00 00:00:00') {
$intUntilTs = strtotime($strUntilRaw);
if ($intUntilTs !== false) {
$strUntilLocal = date('Y-m-d\TH:i', $intUntilTs);
}
}
echo '<div class="ct-api-auto-wrap mb-3' . ($blnClosed ? ' ct-api-auto-wrap--disabled' : '') . '" id="ct_api_auto_wrap">';
echo '<div class="form-check mb-2">';
echo '<input class="form-check-input" type="checkbox" id="ct_api_auto_enabled" value="1"'
. ($blnAutoOn ? ' checked' : '') . ($blnClosed ? ' disabled' : '') . '>';
echo '<label class="form-check-label font-weight-bold" for="ct_api_auto_enabled">Mise à jour automatique</label>';
echo '</div>';
echo '<div class="form-row align-items-end" id="ct_api_auto_options">';
echo '<div class="form-group col-sm-4 mb-2 mb-sm-0">';
echo '<label class="small text-muted mb-1" for="ct_api_auto_interval">Fréquence</label>';
echo '<select class="form-control form-control-sm" id="ct_api_auto_interval"'
. ($blnClosed ? ' disabled' : '') . '>';
foreach (array(1 => 'Toutes les minutes', 5 => 'Toutes les 5 minutes', 15 => 'Toutes les 15 minutes',
30 => 'Toutes les 30 minutes', 60 => 'Toutes les heures') as $intMin => $strLabel) {
echo '<option value="' . $intMin . '"' . ($intAutoInterval === $intMin ? ' selected' : '') . '>'
. fxChronotrackApiAdminEsc($strLabel) . '</option>';
}
echo '</select></div>';
echo '<div class="form-group col-sm-5 mb-2 mb-sm-0">';
echo '<label class="small text-muted mb-1" for="ct_api_auto_until">Date et heure de fin</label>';
echo '<input type="datetime-local" class="form-control form-control-sm" id="ct_api_auto_until" value="'
. fxChronotrackApiAdminEsc($strUntilLocal) . '"' . ($blnClosed ? ' disabled' : '') . '>';
echo '</div>';
if (!$blnClosed) {
echo '<div class="form-group col-sm-3 mb-0">';
echo '<button type="button" class="btn btn-outline-primary btn-sm btn-block" id="ct_api_btn_auto_save">'
. 'Enregistrer</button>';
echo '</div>';
}
echo '</div>';
echo '<p class="small text-muted mb-0 mt-2" id="ct_api_auto_hint">';
if ($blnAutoOn && $strUntilRaw !== '') {
echo 'Config enregistrée — exécution serveur (cron) à brancher. Arrêt prévu : '
. fxChronotrackApiAdminEsc($strUntilRaw) . '.';
} else {
echo 'Quand cest coché, le serveur (cron) poussera le différentiel à cet intervalle jusquà la date de fin. '
. 'Pas encore actif côté serveur.';
}
echo '</p>';
echo '<div id="ct_api_auto_msg" class="small mt-1"></div>';
echo '</div>';
// Zone employé : statut clair + actions
echo '<div id="ct_api_push_status" class="ct-api-push-status mb-3">';
echo '<div class="text-muted small">Cliquez <strong>Actualiser</strong> pour vérifier sil y a des changements à envoyer.</div>';
echo '</div>';
@ -263,7 +319,7 @@ function fxChronotrackApiAdminRenderPushPanel($intEveId, $blnClosed = false) {
echo '<button type="button" class="btn btn-primary btn-lg" id="ct_api_btn_push" disabled>';
echo '<i class="fa fa-cloud-upload" aria-hidden="true"></i>&nbsp;Envoyer vers ChronoTrack</button>';
echo '</div>';
echo '<p class="small text-muted mb-2">La sync automatique arrivera bientôt — pour linstant, un clic suffit quand il y a du nouveau.</p>';
echo '<p class="small text-muted mb-2">Envoi manuel : uniquement les nouveaux / modifiés depuis le dernier push OK.</p>';
echo '<div id="ct_api_push_result" class="small mb-3"></div>';
// Détails / debug : sous les boutons, repliés par défaut
@ -355,6 +411,13 @@ function fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed
}
.ct-api-push-actions .btn-lg { font-size: 1.05rem; padding: 0.55rem 1.1rem; }
#ct_api_push_details_card .card-header a { text-decoration: none; }
.ct-api-auto-wrap {
padding: 12px 14px;
border-radius: 8px;
border: 1px dashed #adb5bd;
background: #fafbfc;
}
.ct-api-auto-wrap--disabled { opacity: 0.7; }
</style>
<?php fxChronotrackApiAdminRenderLoaderAssets($vDomaine); ?>
<script>
@ -1080,6 +1143,50 @@ function fxChronotrackApiAdminRenderPageScript($intEveId, $arrConfig, $blnClosed
loadPushPreview(false);
}
function syncAutoOptionsState() {
var blnOn = $('#ct_api_auto_enabled').is(':checked');
$('#ct_api_auto_interval, #ct_api_auto_until').prop('disabled', blnClosed || !blnOn);
}
syncAutoOptionsState();
$('#ct_api_auto_enabled').on('change', syncAutoOptionsState);
$('#ct_api_btn_auto_save').on('click', function () {
var $btn = $(this);
var $msg = $('#ct_api_auto_msg');
var $hint = $('#ct_api_auto_hint');
var blnOn = $('#ct_api_auto_enabled').is(':checked');
$btn.prop('disabled', true);
$msg.removeClass('text-success text-danger').text('Enregistrement…');
$.post(strAjaxUrl, {
a: 'sync_auto_save',
eve_id: intEveId,
enabled: blnOn ? 1 : 0,
interval_min: $('#ct_api_auto_interval').val(),
until: $('#ct_api_auto_until').val()
}, function (res) {
if (rejectIfSessionLost(res)) {
return;
}
if (!res || res.state !== 'ok') {
$msg.addClass('text-danger').text((res && res.message) ? res.message : 'Erreur');
return;
}
$msg.addClass('text-success').text(res.message || 'Enregistré');
if (res.auto_sync) {
if (res.auto_sync.enabled && res.auto_sync.until) {
$hint.text('Config enregistrée — exécution serveur (cron) à brancher. Arrêt prévu : '
+ res.auto_sync.until + '.');
} else {
$hint.text('Sync auto désactivée. Le cron (phase B) ne traitera pas cet événement.');
}
}
}, 'json').fail(function () {
$msg.addClass('text-danger').text('Erreur réseau');
}).always(function () {
$btn.prop('disabled', false);
});
});
$('#ct_api_btn_push_refresh').on('click', function () {
loadPushPreview(true);
$('#ct_api_push_result').empty();