Compare commits

..
4 Commits
5 changed files with 41 additions and 59 deletions

No files matched your search

-1
View File
@@ -2621,7 +2621,6 @@ try {
break;
case 'run_update':
@set_time_limit(300);
$output = [];
$code = 0;
exec("sudo /var/www/nexus-pbx/scripts/update.sh 2>&1", $output, $code);
+20 -38
View File
@@ -6330,12 +6330,7 @@ async function checkSystemUpdate(notify = false) {
if (pingDot) pingDot.classList.remove('hidden');
if (changelogList && Array.isArray(data.changelog) && data.changelog.length > 0) {
changelogList.innerHTML = data.changelog.flatMap(item => {
if (item && typeof item === 'object' && Array.isArray(item.changes)) {
return item.changes.map(c => `<li>${escapeHtml(String(c))}</li>`);
}
return [`<li>${escapeHtml(String(item ?? ''))}</li>`];
}).join('');
changelogList.innerHTML = data.changelog.map(item => `<li>${escapeHtml(item)}</li>`).join('');
if (changelogContainer) changelogContainer.classList.remove('hidden');
}
} else {
@@ -6417,29 +6412,11 @@ async function executeSystemUpdate() {
showToast("Mise à jour en cours d'exécution en arrière-plan...", 'info');
// Pause du polling métriques pour éviter un 502 Nginx pendant le reload php-fpm/nginx
stopMetricsPolling();
// Purge préventive du cache local
localStorage.removeItem('nexus_update_last_check_ts');
localStorage.removeItem('nexus_update_cached_data');
async function probeUpdateReady(maxAttempts = 6, delayMs = 1500) {
for (let i = 0; i < maxAttempts; i++) {
await new Promise(r => setTimeout(r, delayMs));
try {
const probeRes = await fetch('/api.php?action=check_update&_t=' + Date.now());
if (!probeRes.ok) continue;
const probeData = await probeRes.json();
if (probeData && probeData.success && probeData.current_version) {
return probeData;
}
} catch (_) {}
}
return null;
}
async function finalizeUpdateSuccess(newVer) {
function finalizeUpdateSuccess(newVer) {
newVer = String(newVer || '').replace(/^v/, '');
localStorage.setItem('nexus_update_last_check_ts', Date.now().toString());
localStorage.setItem('nexus_update_cached_data', JSON.stringify({
@@ -6472,11 +6449,10 @@ async function executeSystemUpdate() {
btnModalConfirm.innerHTML = '✓ Mise à jour terminée ! Rechargement...';
}
// Attendre que le reload différé php-fpm/nginx soit terminé avant de recharger la page
await new Promise(r => setTimeout(r, 2500));
await probeUpdateReady(5, 1000);
setTimeout(() => {
closeUpdateConfirmModal();
window.location.href = window.location.origin + window.location.pathname + '?_t=' + Date.now();
}, 1800);
}
try {
@@ -6500,15 +6476,18 @@ async function executeSystemUpdate() {
}
// Si la réponse n'était pas un JSON valide ou a été interrompue par le rechargement de php-fpm/nginx,
// on sonde le serveur à plusieurs reprises pour laisser Nginx/PHP-FPM terminer leur reload
const probeData = await probeUpdateReady(6, 1500);
if (probeData) {
await finalizeUpdateSuccess(probeData.current_version);
// on sonde le serveur pour vérifier si la mise à jour a en réalité bien été appliquée sur le disque
await new Promise(r => setTimeout(r, 2000));
try {
const probeRes = await fetch('/api.php?action=check_update&_t=' + Date.now());
const probeData = await probeRes.json();
if (probeData && probeData.success && probeData.current_version) {
finalizeUpdateSuccess(probeData.current_version);
return;
}
} catch (_) {}
// En cas d'échec réel avéré
startMetricsPolling();
closeUpdateConfirmModal();
const errMsg = (data && (data.output || data.message)) ? (data.output || data.message) : (rawText.slice(0, 150) || "Erreur inconnue");
alert("Erreur lors de la mise à jour :\n\n" + errMsg);
@@ -6524,14 +6503,17 @@ async function executeSystemUpdate() {
} catch (e) {
// En cas d'interruption réseau du socket (Safari WebKit DOMException ou timeout),
// on vérifie à plusieurs reprises si le serveur a quand même réussi à déployer les fichiers
const probeData = await probeUpdateReady(6, 1500);
if (probeData) {
await finalizeUpdateSuccess(probeData.current_version);
// on vérifie avant d'alerter si le serveur a quand même réussi à déployer les fichiers
await new Promise(r => setTimeout(r, 2000));
try {
const probeRes = await fetch('/api.php?action=check_update&_t=' + Date.now());
const probeData = await probeRes.json();
if (probeData && probeData.success && probeData.current_version) {
finalizeUpdateSuccess(probeData.current_version);
return;
}
} catch (_) {}
startMetricsPolling();
closeUpdateConfirmModal();
alert("Erreur réseau lors de la mise à jour : " + (e.message || "Connexion interrompue"));
if (btnRun) {
+4 -11
View File
@@ -261,7 +261,7 @@ if [ -t 1 ]; then
systemctl reload nginx 2>/dev/null || true
fail2ban-client reload >/dev/null 2>&1 || true
else
(nohup bash -c "sleep 1 && (systemctl reload php8.4-fpm 2>/dev/null || systemctl reload php8.2-fpm 2>/dev/null || systemctl reload php*-fpm 2>/dev/null || true); systemctl reload nginx 2>/dev/null || true; fail2ban-client reload >/dev/null 2>&1 || true" </dev/null >/dev/null 2>&1 &)
(nohup bash -c "sleep 2 && (systemctl reload php8.4-fpm 2>/dev/null || systemctl reload php8.2-fpm 2>/dev/null || systemctl reload php*-fpm 2>/dev/null || true); systemctl reload nginx 2>/dev/null || true; fail2ban-client reload >/dev/null 2>&1 || true" >/dev/null 2>&1 &)
fi
NEW_VER="Inconnue"
@@ -279,17 +279,10 @@ echo ""
if [ -f "$APP_DIR/version.json" ]; then
echo -e "${C_CYAN}${C_BOLD}Nouveautés de cette version :${C_RESET}"
php -r '
$v = json_decode(@file_get_contents("/var/www/nexus-pbx/version.json"), true);
if (!empty($v["changelog"]) && is_array($v["changelog"])) {
$first = $v["changelog"][0];
if (is_array($first) && !empty($first["changes"])) {
foreach ($first["changes"] as $line) {
echo " • " . $line . "\n";
}
} else {
$v = json_decode(file_get_contents("/var/www/nexus-pbx/version.json"), true);
if (!empty($v["changelog"])) {
foreach ($v["changelog"] as $line) {
if (is_string($line)) echo " • " . $line . "\n";
}
echo " • " . $line . "\n";
}
}
'
+1 -3
View File
@@ -95,14 +95,12 @@ class PhonebookManager
$existing = $findStmt->fetch(PDO::FETCH_ASSOC);
if ($existing) {
$existingEmail = trim((string)($existing['email'] ?? ''));
$finalEmail = $existingEmail !== '' ? $existingEmail : $email;
$updateStmt->execute([
':id' => (int)$existing['id'],
':ext_id' => $extId,
':name' => $extName,
':num' => $extNum,
':email' => $finalEmail,
':email' => $email,
':grp' => $group,
]);
} else {
+16 -6
View File
@@ -1,14 +1,24 @@
{
"version": "2.7.3",
"version": "2.7.0",
"codename": "Pulsar UCP",
"release_date": "2026-11-12",
"min_php_version": "8.2",
"changelog": [
"Correctif v2.7.3 : conservation de l'adresse email renseignée sur un contact interne de l'Annuaire lors de la synchronisation des postes",
"Correctif v2.7.2 : formatage uniforme du changelog dans version.json (suppression de [object Object] dans la fiche de mise à jour)",
"Correctif v2.7.1 : suppression de l'erreur Nginx 502 transitoire après mise à jour 1-Clic (pause du polling métriques, sonde multi-essais avant rechargement)",
"Nouveauté v2.7.0 : logo spécifique optionnel pour le portail UCP (thème clair), avec repli automatique sur le logo principal puis NexusPBX",
"UI v2.6.7 : remplacement de l'ensemble des icônes emoji par des icônes vectorielles SVG uniformes sur Admin & UCP (sans modifier le menu latéral Admin)",
{
"version": "2.7.0",
"date": "2026-11-12",
"changes": [
"Branding UCP : Ajout d'un logo spécifique optionnel pour le portail UCP (thème clair), avec repli automatique sur le logo principal puis sur le logo NexusPBX par défaut"
]
},
{
"version": "2.6.7",
"date": "2026-11-12",
"changes": [
"UI Admin & UCP : Remplacement de l'ensemble des icônes emoji par des icônes vectorielles SVG uniformes (style Heroicons), sans modifier le menu latéral Admin",
"Correction d'un problème de syntaxe JS sur le badge d'avertissement TLS dans app.js"
]
},
"UI v2.6.6 : menu déroulant personnalisé sombre avec icônes SVG Heroicons pour toutes les destinations d'appel (sans emojis natifs)",
"UI v2.6.5 : refonte des intitulés de destinations audio (Musique d'attente & Annonce vocale en boucle continue), nouveau wallpaper clair UCP et placeholder générique",
"Correctif v2.6.4 : prise en charge multi-groupes dans l'annuaire UCP & Admin (un poste appartenant à plusieurs groupes apparaît bien dans chacun des onglets correspondants)",