chore(ui): replace specific examples with generic placeholders and generalize phone and gateway brands

This commit is contained in:
sorcier committed 2026-11-04 00:40:24 +01:00
1 parent b3c98834c8
commit a308f5d0ed
5 files changed
+50 -50

No files matched your search

+3 -3
View File
@@ -1145,7 +1145,7 @@ try {
}
if ($registration_mode === 'receive') {
if ($username === '' || $secret === '') {
throw new InvalidArgumentException("En mode Réception (ex: passerelle Grandstream HT813 / Livebox), l'Identifiant (Username) et le Mot de passe SIP sont requis pour authentifier la passerelle.");
throw new InvalidArgumentException("En mode Réception (ex: passerelle Grandstream HT813, Cisco SPA...), l'Identifiant (Username) et le Mot de passe SIP sont requis pour authentifier la passerelle.");
}
} else {
if ($host === '') {
@@ -1294,7 +1294,7 @@ try {
$ami->reloadPjsipAndDialplan();
} catch (\Throwable $e) {}
$displayHost = $host !== '' ? "{$host}:{$port}" : "Passerelle locale / HT813";
$displayHost = $host !== '' ? "{$host}:{$port}" : "Passerelle locale / FXO";
echo json_encode([
'success' => true,
'message' => "Trunk SIP « {$name} » ({$displayHost}) sauvegardé avec tous ses paramètres PJSIP.",
@@ -1455,7 +1455,7 @@ try {
$enabled = isset($payload['enabled']) ? (int)!empty($payload['enabled']) : 1;
if ($name === '') {
throw new InvalidArgumentException("Le nom de la Route Sortante est obligatoire (ex: OVH, Livebox, Emergency).");
throw new InvalidArgumentException("Le nom de la Route Sortante est obligatoire (ex: National, Mobile, Secours, Emergency).");
}
$trunkSeqRaw = is_array($payload['trunk_sequence'] ?? null) ? $payload['trunk_sequence'] : [];
+5 -5
View File
@@ -393,7 +393,7 @@ function renderDashboardMetrics() {
if (osVerEl && m.os_version) osVerEl.textContent = m.os_version;
const astVerEl = document.getElementById('sidebar-ast-version');
if (astVerEl && m.asterisk?.version) astVerEl.textContent = m.asterisk.version;
document.getElementById('sidebar-ip').textContent = m.network?.ip || '10.10.175.204';
document.getElementById('sidebar-ip').textContent = m.network?.ip || '192.168.1.100';
document.getElementById('sidebar-uptime').textContent = m.uptime || '—';
document.getElementById('sidebar-online-phones').textContent = `${m.asterisk?.online_contacts ?? 0} / ${(appState.extensions || []).length}`;
@@ -1906,7 +1906,7 @@ function addTrunkInboundRouteRow(cid = 'Any', did = 'Any', description = '', des
<label class="text-[11px] font-semibold text-slate-300 flex items-center gap-1">
<span>🏷️ Préfixe CID spécifique à cette règle :</span>
</label>
<input type="text" placeholder="ex: [Livebox] (vide = hériter du Trunk)" value="${escapeHtml(tcCidPrefix)}"
<input type="text" placeholder="ex: [Ligne-1] (vide = hériter du Trunk)" value="${escapeHtml(tcCidPrefix)}"
class="trunk-did-prefix px-2.5 py-1 rounded bg-anthracite-900 border border-anthracite-700 text-xs text-white font-mono w-56 focus:outline-none focus:border-indigo-500">
<span class="text-[10px] text-slate-400">Ajouté devant le nom de l'appelant sur le téléphone (laisser vide pour utiliser le préfixe général du Trunk).</span>
</div>
@@ -2131,7 +2131,7 @@ function onTrunkRegistrationModeChange(mode) {
if (mode === 'receive') {
if (hostInput) {
hostInput.required = false;
hostInput.placeholder = 'Optionnel (vide = IP découverte dynamiquement au REGISTER du HT813)';
hostInput.placeholder = 'Optionnel (vide = IP découverte dynamiquement au REGISTER de la passerelle)';
}
if (hostLabel) {
hostLabel.innerHTML = 'Serveur SIP / IP Passerelle <span class="text-emerald-400 font-semibold">(Optionnel en mode Réception)</span>';
@@ -2187,7 +2187,7 @@ function applyTrunkArchitecture(arch) {
qualify_frequency: 60
},
gateway_receive: {
label: 'Passerelle FXO / Analogique (Grandstream HT813, Livebox, ATA)',
label: 'Passerelle FXO / Ligne Box (Grandstream HT813, Cisco SPA, AudioCodes, ATA)',
port: 5060,
transport: 'udp',
auth_mode: 'userpass',
@@ -5578,7 +5578,7 @@ function openYealinkXmlModal() {
function updateYealinkXmlUrls() {
const sel = document.getElementById('yealink-modal-group-select');
const grp = sel ? sel.value : 'all';
const host = window.location.hostname || '10.10.175.204';
const host = window.location.hostname || '192.168.1.100';
const httpsPort = window.location.port || '8443';
const groupParam = grp !== 'all' ? `?group=${encodeURIComponent(grp)}` : `?group=all`;
+39 -39
View File
@@ -444,7 +444,7 @@ $currentUser = Auth::getUsername();
</div>
<div class="flex justify-between items-center">
<span class="text-slate-400">IP SIP :</span>
<code id="sidebar-ip" class="font-mono text-indigo-300 font-semibold">10.10.175.204</code>
<code id="sidebar-ip" class="font-mono text-indigo-300 font-semibold">192.168.1.100</code>
</div>
<div class="flex justify-between items-center">
<span class="text-slate-400">Uptime OS :</span>
@@ -1076,9 +1076,9 @@ $currentUser = Auth::getUsername();
<div>
<div class="flex items-center gap-2">
<h2 class="text-lg font-bold text-white">Annuaire d'Entreprise & Carnet d'Adresses IP Phone</h2>
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold bg-teal-500/20 text-teal-300 border border-teal-500/30">Yealink XML</span>
<span class="px-2 py-0.5 rounded-full text-[10px] font-bold bg-teal-500/20 text-teal-300 border border-teal-500/30">XML Téléphones IP</span>
</div>
<p class="text-xs text-slate-300">Répertoire unifié (postes internes & contacts externes) synchronisé automatiquement avec les téléphones IP Yealink via l'API XML <code class="text-teal-300">phonebook.php</code>.</p>
<p class="text-xs text-slate-300">Répertoire unifié (postes internes & contacts externes) synchronisé automatiquement avec les téléphones IP (Yealink, Fanvil, Grandstream, Snom...) via l'API XML <code class="text-teal-300">phonebook.php</code>.</p>
</div>
<div class="flex items-center flex-wrap gap-2">
<button type="button" onclick="openYealinkXmlModal()"
@@ -1253,7 +1253,7 @@ $currentUser = Auth::getUsername();
<div>
<h2 class="text-lg font-bold text-white">Routes Sortantes (Outbound Routes & Cascade de Priorité)</h2>
<p class="text-xs text-slate-300">
Définissez l'ordre d'utilisation de vos routes sortantes (ex: <strong>1. OVH</strong> → <strong>2. Livebox</strong>). Si le premier Trunk est indisponible <strong>ou si le poste/groupe appelant n'a pas les droits sur la première route</strong>, NexusPBX passe automatiquement à la route suivante !
Définissez l'ordre d'utilisation de vos routes sortantes (ex: <strong>1. Trunk SIP Principal</strong> → <strong>2. Ligne Box / Secours</strong>). Si le premier Trunk est indisponible <strong>ou si le poste/groupe appelant n'a pas les droits sur la première route</strong>, NexusPBX passe automatiquement à la route suivante !
</p>
</div>
<button type="button" onclick="openOutboundRouteModal()"
@@ -2078,7 +2078,7 @@ $currentUser = Auth::getUsername();
</div>
</div>
<!-- Guide d'interception & Touches BLF Yealink -->
<!-- Guide d'interception & Touches BLF Postes IP -->
<div class="bg-gradient-to-r from-indigo-950/60 to-anthracite-800 border border-indigo-500/30 rounded-2xl p-5 shadow-lg space-y-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2.5">
@@ -2086,7 +2086,7 @@ $currentUser = Auth::getUsername();
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
<span class="relative inline-flex rounded-full h-3 w-3 bg-emerald-500"></span>
</span>
<h3 class="text-sm font-bold text-white">Touches de Ligne BLF & Interception d'Appel sur Postes Yealink</h3>
<h3 class="text-sm font-bold text-white">Touches de Ligne BLF & Interception d'Appel sur Postes IP (Yealink, Fanvil, Grandstream, Snom...)</h3>
</div>
<span class="px-2.5 py-0.5 rounded-full text-[10px] font-bold bg-indigo-500/20 text-indigo-300 border border-indigo-500/40">FreePBX Compatible</span>
</div>
@@ -2094,7 +2094,7 @@ $currentUser = Auth::getUsername();
NexusPBX génère automatiquement les <strong>hints</strong> Asterisk pour surveiller l'état en direct de vos téléphones (<span class="text-emerald-400 font-semibold">Vert</span> = libre, <span class="text-rose-400 font-semibold animate-pulse">Rouge clignotant</span> = sonnerie en cours, <span class="text-rose-500 font-semibold">Rouge fixe</span> = en communication).
</p>
<div class="p-3 bg-anthracite-950/80 rounded-xl border border-anthracite-700/80 text-xs space-y-2">
<div class="font-semibold text-slate-200">Pour configurer une touche de surveillance et récupération d'appel sur votre Yealink (Dsskey / Line Key) :</div>
<div class="font-semibold text-slate-200">Pour configurer une touche de surveillance et récupération d'appel sur votre poste IP (Yealink, Fanvil, Grandstream, Snom...) :</div>
<div class="grid grid-cols-2 sm:grid-cols-5 gap-2 text-[11px] font-mono pt-1">
<div class="bg-anthracite-900 p-2 rounded-lg border border-anthracite-700"><span class="text-slate-400 block text-[10px] uppercase font-sans">Type</span><strong class="text-white">BLF</strong></div>
<div class="bg-anthracite-900 p-2 rounded-lg border border-anthracite-700"><span class="text-slate-400 block text-[10px] uppercase font-sans">Valeur (Value)</span><strong class="text-cyan-400">101</strong> (ou n° poste)</div>
@@ -2182,7 +2182,7 @@ $currentUser = Auth::getUsername();
<span>🔍 Détecter l'IP publique</span>
</button>
</div>
<input type="text" id="sip-external-ip" name="external_ip" placeholder="ex: sip.sorcier-research.com ou 82.122.84.60"
<input type="text" id="sip-external-ip" name="external_ip" placeholder="ex: sip.mondomaine.com ou 198.51.100.1"
class="w-full px-3 py-2 rounded-xl bg-anthracite-950 border border-anthracite-700 text-xs text-white font-mono focus:ring-2 focus:ring-cyan-500 focus:outline-none">
<p class="text-[11px] text-slate-400 leading-relaxed">
Si votre IP est dynamique, renseignez un <strong>nom de domaine FQDN / DynDNS</strong> (ex: <code>sip.mondomaine.fr</code>) pour ne jamais perdre vos téléphones distants lors d'un renouvellement de bail IP par votre opérateur.
@@ -2449,7 +2449,7 @@ $currentUser = Auth::getUsername();
</div>
<p class="text-xs text-slate-300 max-w-3xl leading-relaxed">
Définit la directive PJSIP <code>verify_client</code> sur le transport TLS (port 5061).
En mode standard, le combiné (Yealink) valide le serveur PBX et s'authentifie par identifiant / mot de passe SIP dans le tunnel crypté. En mode Mutual TLS strict, Asterisk exige en plus un certificat client X.509 installé sur chaque téléphone.
En mode standard, le combiné (Yealink, Fanvil, Cisco...) valide le serveur PBX et s'authentifie par identifiant / mot de passe SIP dans le tunnel crypté. En mode Mutual TLS strict, Asterisk exige en plus un certificat client X.509 installé sur chaque téléphone.
</p>
</div>
<div class="flex items-center gap-3 shrink-0">
@@ -2615,13 +2615,13 @@ $currentUser = Auth::getUsername();
<option value="2">Obligatoire / Forcé (SRTP Strict - Rejette l'appel si non chiffré)</option>
<option value="0">Désactivé (RTP standard en clair sans chiffrement audio)</option>
</select>
<p class="text-[11px] text-slate-400">Le mode optionnel négocie le SRTP automatiquement tout en évitant les échecs d'appels si le Yealink a le SRTP désactivé.</p>
<p class="text-[11px] text-slate-400">Le mode optionnel négocie le SRTP automatiquement tout en évitant les échecs d'appels si le poste IP a le SRTP désactivé.</p>
</div>
<div class="p-3.5 rounded-xl bg-anthracite-950 border border-anthracite-700 space-y-2">
<div class="flex items-center justify-between">
<span class="text-xs font-bold text-cyan-300">Appartenance aux Groupes d'Extensions (Sites & Droits)</span>
<span class="text-[11px] text-slate-400">ex: Nice, Paris, Commerciaux...</span>
<span class="text-[11px] text-slate-400">ex: Support, Direction, Commerciaux...</span>
</div>
<div id="extension-groups-checkboxes" class="grid grid-cols-1 sm:grid-cols-2 gap-2 max-h-32 overflow-y-auto"></div>
</div>
@@ -2721,7 +2721,7 @@ $currentUser = Auth::getUsername();
<span class="text-base">💡</span>
<div class="text-xs text-emerald-200">
<strong class="font-bold">Notification MWI automatique :</strong>
Le voyant LED rouge et l'enveloppe clignoteront sur votre téléphone Yealink dès qu'un message vocal est reçu.
Le voyant LED ou l'enveloppe clignoteront sur vos téléphones IP (Yealink, Fanvil, Grandstream, Snom...) dès qu'un message vocal est reçu.
</div>
</div>
</div>
@@ -2822,7 +2822,7 @@ $currentUser = Auth::getUsername();
<div class="flex items-center justify-between pb-3 mb-4 border-b border-anthracite-700">
<div>
<h3 id="modal-extgroup-title" class="text-base sm:text-lg font-bold text-white">Groupe d'Extensions (Sites & Droits)</h3>
<p class="text-xs text-slate-300">Regroupement sans numéro d'appel. Sert à autoriser ou bloquer ce groupe sur les Routes Sortantes (ex: OVH, Livebox...).</p>
<p class="text-xs text-slate-300">Regroupement sans numéro d'appel. Sert à autoriser ou bloquer ce groupe sur les Routes Sortantes (ex: Trunk SIP, Passerelle...).</p>
</div>
<button type="button" onclick="closeModal('modal-extgroup')" class="text-slate-300 hover:text-white text-lg">✕</button>
</div>
@@ -2830,13 +2830,13 @@ $currentUser = Auth::getUsername();
<input type="hidden" name="id">
<div class="grid grid-cols-1 sm:grid-cols-12 gap-4">
<div class="sm:col-span-6">
<label class="block text-xs font-medium text-slate-200 mb-1">Nom du Groupe * <span class="text-slate-400">(ex: Groupe Nice, Groupe Paris)</span></label>
<input type="text" name="name" placeholder="ex: Groupe Nice" required
<label class="block text-xs font-medium text-slate-200 mb-1">Nom du Groupe * <span class="text-slate-400">(ex: Groupe Direction, Groupe Support)</span></label>
<input type="text" name="name" placeholder="ex: Groupe Support" required
class="w-full px-3 py-2 rounded-lg bg-anthracite-950 border border-anthracite-700 text-sm text-white font-bold">
</div>
<div class="sm:col-span-6">
<label class="block text-xs font-medium text-slate-200 mb-1">Description / Emplacement</label>
<input type="text" name="description" placeholder="ex: Site de Nice - Sortie Livebox"
<input type="text" name="description" placeholder="ex: Équipe Commerciale - Sortie Prioritaire"
class="w-full px-3 py-2 rounded-lg bg-anthracite-950 border border-anthracite-700 text-sm text-white">
</div>
</div>
@@ -3012,13 +3012,13 @@ $currentUser = Auth::getUsername();
<div id="ob-panel-settings" class="ob-subpanel space-y-4">
<div class="grid grid-cols-1 sm:grid-cols-12 gap-4">
<div class="sm:col-span-4">
<label class="block text-xs font-medium text-slate-200 mb-1">Nom de la Route * <span class="text-slate-400">(ex: OVH, Livebox, Emergency)</span></label>
<input type="text" name="name" placeholder="ex: OVH" required
<label class="block text-xs font-medium text-slate-200 mb-1">Nom de la Route * <span class="text-slate-400">(ex: National, Mobile, International, Secours)</span></label>
<input type="text" name="name" placeholder="ex: National" required
class="w-full px-3 py-2 rounded-lg bg-anthracite-950 border border-anthracite-700 text-sm text-white font-semibold">
</div>
<div class="sm:col-span-5">
<label class="block text-xs font-medium text-slate-200 mb-1">Route CID <span class="text-slate-400">(CallerID Sortant affiché)</span></label>
<input type="text" name="outbound_callerid" placeholder="ex: Sytelis Consulting <0422560185>"
<input type="text" name="outbound_callerid" placeholder="ex: Mon Entreprise <0123456789>"
class="w-full px-3 py-2 rounded-lg bg-anthracite-950 border border-anthracite-700 text-sm text-white font-mono">
</div>
<div class="sm:col-span-3">
@@ -3279,7 +3279,7 @@ $currentUser = Auth::getUsername();
Trunk avec Enregistrement (REGISTER + Auth)
</button>
<button type="button" onclick="applyTrunkArchitecture('gateway_receive')" class="px-2.5 py-1 rounded-lg bg-anthracite-950 hover:bg-emerald-600/30 border border-emerald-500/50 text-emerald-300 font-medium transition flex items-center gap-1">
<span>📟 Passerelle FXO / Analogique (HT813, Livebox)</span>
<span>📟 Passerelle FXO / Ligne Box (Grandstream, Cisco SPA, AudioCodes)</span>
</button>
<button type="button" onclick="applyTrunkArchitecture('ip_peering')" class="px-2.5 py-1 rounded-lg bg-anthracite-950 hover:bg-indigo-600/30 border border-anthracite-600 text-purple-300 font-medium transition">
Peering IP / SBC / Passerelle (Sans REGISTER)
@@ -3367,7 +3367,7 @@ $currentUser = Auth::getUsername();
<span>Réception (Receive)</span>
<span class="text-[10px] px-1.5 py-0.2 rounded bg-emerald-500/20 text-emerald-300">Passerelle FXO</span>
</div>
<div class="text-[11px] text-slate-300 mt-0.5">La passerelle s'enregistre sur Asterisk (Grandstream HT813, Livebox). Hôte libre.</div>
<div class="text-[11px] text-slate-300 mt-0.5">La passerelle s'enregistre sur Asterisk (Grandstream HT813/HT503, Cisco SPA, AudioCodes, Box Internet / Ligne RTC). Hôte libre.</div>
</div>
</label>
<label class="flex items-start gap-2.5 p-3 rounded-xl bg-anthracite-900 border border-anthracite-700 cursor-pointer hover:border-purple-500/50 transition">
@@ -3382,23 +3382,23 @@ $currentUser = Auth::getUsername();
</label>
</div>
<!-- Guide interactif d'aide pour Grandstream HT813 / Livebox FXO -->
<!-- Guide interactif d'aide pour Passerelles FXO (Grandstream, Cisco SPA...) -->
<div id="trunk-receive-guide" class="hidden p-3.5 rounded-xl bg-emerald-950/40 border border-emerald-500/40 text-xs text-slate-200 space-y-2">
<div class="flex items-center gap-2 font-bold text-emerald-300 text-xs">
<span>💡 Guide Rapide : Paramétrage de votre Grandstream HT813 / HT503 (FXO)</span>
<span>💡 Guide Rapide : Paramétrage d'une passerelle FXO (Grandstream HT813/HT503, Cisco SPA3102...)</span>
</div>
<p class="text-[11px] text-slate-300 leading-relaxed">
Dans l'interface web du boîtier HT813 (onglet <strong>FXO Port</strong> relié à la prise téléphone verte de votre Livebox / Box opérateur) :
Dans l'interface web de votre passerelle (onglet <strong>FXO Port</strong> Grandstream ou <strong>Line 1/PSTN</strong> Cisco SPA relié à la prise téléphonique d'une Box Internet / modem FAI / ligne analogique) :
</p>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2 text-[11px] font-mono bg-anthracite-950 p-3 rounded-lg border border-emerald-500/25">
<div>• <strong>Primary SIP Server</strong> : <span class="text-emerald-300 font-bold"><?= htmlspecialchars($_SERVER['SERVER_ADDR'] ?? '10.10.175.204') ?>:5060</span></div>
<div>• <strong>Primary SIP Server</strong> : <span class="text-emerald-300 font-bold"><?= htmlspecialchars($_SERVER['SERVER_ADDR'] ?? '192.168.1.100') ?>:5060</span></div>
<div>• <strong>SIP Registration</strong> : <span class="text-emerald-300 font-bold">Yes</span></div>
<div>• <strong>SIP User ID</strong> : <span class="text-indigo-300 font-bold" id="ht813-guide-user">Même valeur que Username</span></div>
<div>• <strong>Authenticate ID</strong> : <span class="text-indigo-300 font-bold" id="ht813-guide-auth">Même valeur que Username</span></div>
<div>• <strong>Authenticate Password</strong> : <span class="text-indigo-300 font-bold">Votre mot de passe secret</span></div>
<div>• <strong>Stage Method (1/2)</strong> : <span class="text-slate-300">1 (Recommandé pour appel direct)</span></div>
<div class="sm:col-span-2 text-slate-300 font-sans border-t border-anthracite-800 pt-2 mt-1">
• <strong>Unconditional Call Forward to VoIP</strong> : Définir <em>User ID</em> = votre numéro (ex: <code class="text-amber-300 font-mono">0494679572</code>) et <em>SIP Server</em> = <code class="text-amber-300 font-mono">ch1:<?= htmlspecialchars($_SERVER['SERVER_ADDR'] ?? '10.10.175.204') ?>:5060;</code>
• <strong>Unconditional Call Forward to VoIP</strong> : Définir <em>User ID</em> = votre numéro (ex: <code class="text-amber-300 font-mono">0123456789</code>) et <em>SIP Server</em> = <code class="text-amber-300 font-mono">ch1:<?= htmlspecialchars($_SERVER['SERVER_ADDR'] ?? '192.168.1.100') ?>:5060;</code>
</div>
</div>
</div>
@@ -3407,14 +3407,14 @@ $currentUser = Auth::getUsername();
<div class="grid grid-cols-1 sm:grid-cols-4 gap-4">
<div class="sm:col-span-1">
<label class="block text-xs font-medium text-slate-200 mb-1">Nom du Trunk * <span class="text-slate-400">(ID PJSIP)</span></label>
<input type="text" name="name" placeholder="ex: mon-trunk-sip ou 0494679572" required
<input type="text" name="name" placeholder="ex: mon-trunk-sip ou passerelle-fxo" required
class="w-full px-3 py-2 rounded-lg bg-anthracite-950 border border-anthracite-700 text-sm text-white font-mono">
</div>
<div class="sm:col-span-2">
<label id="trunk-host-label" class="block text-xs font-medium text-slate-200 mb-1">Serveur SIP / SBC / Passerelle * <span class="text-slate-400">(Host / IP)</span></label>
<input type="text" name="host" id="trunk-host-input" placeholder="ex: sbc.operateur.net ou 192.168.1.250" required oninput="syncTrunkHostDomain(this.value)"
class="w-full px-3 py-2 rounded-lg bg-anthracite-950 border border-anthracite-700 text-sm text-white font-mono">
<div id="trunk-host-hint" class="hidden text-[10px] text-emerald-400 mt-1">En mode Réception (Receive), l'hôte peut rester vide (découverte dynamique du HT813 lors du REGISTER).</div>
<div id="trunk-host-hint" class="hidden text-[10px] text-emerald-400 mt-1">En mode Réception (Receive), l'hôte peut rester vide (découverte dynamique de la passerelle lors du REGISTER).</div>
</div>
<div class="sm:col-span-1">
<label class="block text-xs font-medium text-slate-200 mb-1">Port SIP * <span class="text-slate-400">(Port)</span></label>
@@ -3526,7 +3526,7 @@ $currentUser = Auth::getUsername();
<span class="px-1.5 py-0.2 rounded bg-indigo-500/20 text-indigo-300 text-[10px] font-mono font-semibold">FreePBX Dial Options</span>
</label>
<p class="text-[11px] text-slate-300">
Paramètres transmis à l'application Asterisk <code class="text-indigo-300">Dial()</code> pour ce Trunk. <code class="text-emerald-300">R</code> génère la tonalité de sonnerie locale (indispensable pour les passerelles analogiques/FXO type HT813/Livebox). <code class="text-indigo-300">T/t</code> autorise le transfert DTMF.
Paramètres transmis à l'application Asterisk <code class="text-indigo-300">Dial()</code> pour ce Trunk. <code class="text-emerald-300">R</code> génère la tonalité de sonnerie locale (indispensable pour les passerelles analogiques/FXO type Grandstream HT813, Cisco SPA3102, Box Internet / Ligne RTC). <code class="text-indigo-300">T/t</code> autorise le transfert DTMF.
</p>
</div>
<div class="flex items-center gap-2">
@@ -3570,11 +3570,11 @@ $currentUser = Auth::getUsername();
<span class="px-1.5 py-0.2 rounded bg-indigo-500/20 text-indigo-300 text-[10px] font-mono font-semibold">FreePBX CID Prefix</span>
</label>
<p class="text-[11px] text-slate-300">
Préfixe inséré devant le nom ou numéro de l'appelant sur l'écran de vos téléphones IP pour identifier la ligne appelée (ex: <code class="text-emerald-300">[Livebox] </code>, <code class="text-indigo-300">[Orange] </code>, <code class="text-cyan-300">[Fixe] </code>).
Préfixe inséré devant le nom ou numéro de l'appelant sur l'écran de vos téléphones IP pour identifier la ligne appelée (ex: <code class="text-emerald-300">[Ligne-1] </code>, <code class="text-indigo-300">[Support] </code>, <code class="text-cyan-300">[Fixe] </code>).
</p>
</div>
<div class="min-w-[240px]">
<input type="text" name="cid_name_prefix" placeholder="ex: [Livebox] "
<input type="text" name="cid_name_prefix" placeholder="ex: [Ligne-1] "
class="w-full px-3 py-2 rounded-xl bg-anthracite-900 border border-anthracite-700 text-xs text-white font-mono focus:outline-none focus:border-indigo-500">
</div>
</div>
@@ -3628,7 +3628,7 @@ $currentUser = Auth::getUsername();
<div id="trunk-panel-identity" class="trunk-subpanel hidden space-y-4">
<div id="trunk-reg-outbound-notice" class="hidden p-3.5 rounded-xl bg-indigo-950/40 border border-indigo-500/40 text-xs text-indigo-200 flex items-center gap-2">
<span>ℹ️</span>
<span>En mode <strong>Réception (Passerelle type HT813)</strong> ou <strong>Peering IP direct (None)</strong>, Asterisk n'émet aucun SIP REGISTER sortant. Les paramètres d'enregistrement ci-dessous ne s'appliquent qu'en mode <strong>Émission (Send)</strong>.</span>
<span>En mode <strong>Réception (Passerelle FXO / ATA)</strong> ou <strong>Peering IP direct (None)</strong>, Asterisk n'émet aucun SIP REGISTER sortant. Les paramètres d'enregistrement ci-dessous ne s'appliquent qu'en mode <strong>Émission (Send)</strong>.</span>
</div>
<div class="p-4 rounded-xl bg-anthracite-950 border border-anthracite-700 space-y-4">
@@ -4511,7 +4511,7 @@ $currentUser = Auth::getUsername();
</div>
<div class="flex-1 space-y-1">
<label class="block text-xs font-semibold text-slate-200">Photo / Avatar du Contact</label>
<p class="text-[11px] text-slate-400">Affiché sur l'interface et sur les téléphones Yealink écran couleur (T54W, T57W...).</p>
<p class="text-[11px] text-slate-400">Affiché sur l'interface et sur les téléphones IP à écran couleur (Yealink, Fanvil, Grandstream...).</p>
<div class="flex items-center gap-2 pt-1">
<label class="px-3 py-1 rounded-lg text-xs font-medium bg-anthracite-800 hover:bg-anthracite-750 text-slate-200 border border-anthracite-600 cursor-pointer transition">
<span>Choisir une photo...</span>
@@ -4562,10 +4562,10 @@ $currentUser = Auth::getUsername();
<!-- Groupe d'Annuaire -->
<div>
<label class="block text-xs font-medium text-slate-200 mb-1">Groupe d'Annuaire <span class="text-rose-400">*</span></label>
<input type="text" name="group_name" id="phonebook-input-group" list="phonebook-groups-datalist" required placeholder="Ex: Issy-Les-Moulineaux, Groupe Nice, Direction..."
<input type="text" name="group_name" id="phonebook-input-group" list="phonebook-groups-datalist" required placeholder="Ex: Direction, Commercial, Support, Technique..."
class="w-full px-3 py-2 rounded-lg bg-anthracite-950 border border-anthracite-700 text-sm text-white focus:outline-none focus:border-teal-500">
<datalist id="phonebook-groups-datalist"></datalist>
<p class="text-[11px] text-slate-400 mt-1">Ce nom de groupe correspond au paramètre <code class="text-teal-300">?cgroup=...</code> dans l'URL Yealink.</p>
<p class="text-[11px] text-slate-400 mt-1">Ce nom de groupe correspond au paramètre <code class="text-teal-300">?cgroup=...</code> dans l'URL de l'annuaire XML.</p>
</div>
<div class="pt-3 border-t border-anthracite-700 flex justify-end gap-2">
@@ -4599,9 +4599,9 @@ $currentUser = Auth::getUsername();
<div class="p-4 rounded-xl bg-teal-500/10 border border-teal-500/20 text-xs text-teal-200 space-y-1">
<div class="font-bold flex items-center gap-1.5">
<svg class="w-4 h-4 text-teal-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>
Comment configurer votre téléphone Yealink ?
Comment configurer votre téléphone IP (Yealink, Fanvil, Grandstream, Snom...) ?
</div>
<p class="text-slate-300">Dans l'interface web de votre Yealink (ex: T54W, T46S, DECT W60/W70), rendez-vous dans le menu :</p>
<p class="text-slate-300">Dans l'interface web de votre téléphone (ex: Yealink T54W/T46S, Fanvil X-Series, Grandstream GRP, Snom D-Series) :</p>
<p class="font-mono text-teal-300 bg-anthracite-950/60 px-2 py-1 rounded">Directory &gt; Remote Phonebook &gt; Phonebook URL</p>
<p class="text-slate-300">Collez simplement l'URL correspondant au groupe souhaité ci-dessous. Le téléphone téléchargera et mettra à jour l'annuaire automatiquement.</p>
</div>
@@ -4620,7 +4620,7 @@ $currentUser = Auth::getUsername();
<div class="flex items-center justify-between text-xs">
<span class="font-semibold text-white flex items-center gap-1.5">
<span class="w-2 h-2 rounded-full bg-emerald-400"></span>
<span>URL Recommandée (HTTP Port 8080 - Compatible tout Yealink)</span>
<span>URL Recommandée (HTTP Port 8080 - Compatible tous téléphones IP)</span>
</span>
<span class="text-[10px] text-emerald-400 font-mono font-bold">Sans certificat SSL requis</span>
</div>
@@ -4663,7 +4663,7 @@ $currentUser = Auth::getUsername();
<!-- Aperçu en direct du XML généré -->
<div class="space-y-1 pt-2 border-t border-anthracite-700/80">
<div class="flex items-center justify-between text-xs">
<span class="font-semibold text-slate-300">Aperçu en Direct du Flux XML Yealink</span>
<span class="font-semibold text-slate-300">Aperçu en Direct du Flux XML (Standard Téléphones IP)</span>
<a id="yealink-open-browser-btn" href="#" target="_blank" class="text-teal-400 hover:text-teal-300 text-[11px] underline">
Ouvrir dans le navigateur ↗
</a>
+1 -1
View File
@@ -327,7 +327,7 @@ class ConfigGenerator
$lines[] = "transport = {$transport}";
if ($regMode === 'receive') {
// Passerelle locale (ex: Grandstream HT813, Livebox, ATA) s'enregistrant sur Asterisk
// Passerelle locale (ex: Grandstream HT813, Cisco SPA, ATA, Ligne Box) s'enregistrant sur Asterisk
$lines[] = "auth = {$authName}";
$lines[] = "outbound_auth = {$authName}";
$lines[] = "aors = {$aorName}";
+2 -2
View File
@@ -601,7 +601,7 @@ class Database
$firstTrunkName = !empty($trunks) ? (string)$trunks[0]['name'] : 'ovh-telecom';
$firstTrunkCid = !empty($trunks) && trim((string)$trunks[0]['outbound_callerid']) !== ''
? trim((string)$trunks[0]['outbound_callerid'])
: 'Sytelis Consulting <0422560185>';
: 'Mon Entreprise <0123456789>';
$exts = $db->query('SELECT extension FROM extensions ORDER BY CAST(extension AS INTEGER) ASC')->fetchAll(PDO::FETCH_COLUMN);
$grps = $db->query('SELECT extension FROM groups ORDER BY CAST(extension AS INTEGER) ASC')->fetchAll(PDO::FETCH_COLUMN);
@@ -677,7 +677,7 @@ class Database
$stmt = $db->prepare('INSERT INTO extension_groups (name, description, color, members) VALUES (:n, :d, :c, :m)');
$stmt->execute([
':n' => 'Groupe Nice',
':d' => 'Extensions du site de Nice (Trunk local Livebox)',
':d' => 'Extensions du site secondaire (Trunk passerelle locale)',
':c' => 'emerald',
':m' => json_encode(['101', '102']),
]);