release: v2.8.21

This commit is contained in:
Christian 2026-09-26 09:51:42 +02:00
parent 9b662c3f1a
commit 4058451565
5 changed files with 31 additions and 15 deletions

View File

@ -1 +1 @@
2.8.20
2.8.21

View File

@ -732,7 +732,8 @@ async def mission_telefoni_ringing(event: MissionCallEvent, request: Request, to
timestamp = event.timestamp or datetime.utcnow()
context = MissionService.resolve_contact_context(event.caller_number)
queue_name = _display_destination(event)
queue_name = (event.queue_name or "Ukendt kø").strip()
recipient_name = _display_destination(event)
execute_query(
"""
@ -753,7 +754,13 @@ async def mission_telefoni_ringing(event: MissionCallEvent, request: Request, to
answered_at = NULL,
started_at = LEAST(mission_call_state.started_at, EXCLUDED.started_at),
updated_at = NOW(),
last_payload = EXCLUDED.last_payload
last_payload = jsonb_set(
EXCLUDED.last_payload,
'{ringing_phones}',
COALESCE(mission_call_state.last_payload->'ringing_phones', '[]'::jsonb)
|| COALESCE(EXCLUDED.last_payload->'ringing_phones', '[]'::jsonb),
true
)
""",
(
event.call_id,
@ -763,7 +770,7 @@ async def mission_telefoni_ringing(event: MissionCallEvent, request: Request, to
context.get("company_name"),
context.get("customer_tag"),
timestamp,
json.dumps(event.model_dump(mode="json")),
json.dumps({**event.model_dump(mode="json"), "ringing_phones": [recipient_name]}),
),
)
@ -786,6 +793,7 @@ async def mission_telefoni_ringing(event: MissionCallEvent, request: Request, to
"queue_name": queue_name,
"caller_number": event.caller_number,
"recipient_extension": event.recipient_extension,
"ringing_phones": [recipient_name],
**context,
"timestamp": timestamp,
}

View File

@ -26,12 +26,10 @@ class MissionService:
@staticmethod
def get_ring_timeout_seconds() -> int:
raw = MissionService.get_setting_value("mission_call_ring_timeout_seconds", "180") or "180"
try:
value = int(raw)
except (TypeError, ValueError):
value = 180
return max(30, min(value, 3600))
# A Yealink "Incoming call" event has no matching event when the
# caller abandons the call. Keep it briefly, then remove it from the
# live boards so stale ringing phones cannot remain visible.
return 30
@staticmethod
def expire_stale_ringing_calls() -> None:
@ -216,7 +214,8 @@ class MissionService:
MissionService.expire_stale_ringing_calls()
rows = execute_query(
"""
SELECT call_id, queue_name, caller_number, contact_name, company_name, customer_tag, state, started_at, answered_at, ended_at, updated_at
SELECT call_id, queue_name, caller_number, contact_name, company_name, customer_tag, state, started_at, answered_at, ended_at, updated_at,
COALESCE(last_payload->'ringing_phones', jsonb_build_array(queue_name)) AS ringing_phones
FROM mission_call_state
WHERE state = 'ringing'
ORDER BY started_at DESC

View File

@ -2956,8 +2956,10 @@
}
const call = state.activeCalls[0];
const phones = [...new Set((Array.isArray(call.ringing_phones) ? call.ringing_phones : [call.queue_name]).filter(Boolean))];
title.textContent = `${call.queue_name || 'Ukendt kø'} - ${call.caller_number || 'Ukendt nummer'}`;
const parts = [];
if (phones.length) parts.push(`Ringer hos: ${phones.join(' · ')}`);
if (call.contact_name) parts.push(call.contact_name);
if (call.company_name) parts.push(call.company_name);
parts.push(`Start: ${formatDate(call.started_at)}`);
@ -2973,16 +2975,20 @@
return;
}
list.innerHTML = state.activeCalls.map((call) => `
list.innerHTML = state.activeCalls.map((call) => {
const phones = [...new Set((Array.isArray(call.ringing_phones) ? call.ringing_phones : [call.queue_name]).filter(Boolean))];
return `
<div class="mc-feed-item">
<div class="mc-feed-title">${escapeHtml(call.queue_name || 'Ukendt kø')} - ${escapeHtml(call.caller_number || '-')}</div>
<div class="mc-feed-meta">
${phones.length ? `Ringer hos: ${escapeHtml(phones.join(' · '))} • ` : ''}
${escapeHtml(call.contact_name || 'Ukendt kontakt')}
${call.company_name ? ` • ${escapeHtml(call.company_name)}` : ''}
${call.started_at ? ` • ${escapeHtml(formatDate(call.started_at))}` : ''}
</div>
</div>
`).join('');
`;
}).join('');
}
function renderCallHistory() {

View File

@ -338,13 +338,16 @@ function renderLiveCalls(calls) {
list.innerHTML = calls.map((call) => {
const caller = escapeHtml(normalizeDisplayNumber(call.caller_number) || call.caller_number || 'Ukendt nummer');
const recipient = escapeHtml(call.queue_name || 'Ukendt telefon');
const phones = [...new Set((Array.isArray(call.ringing_phones) ? call.ringing_phones : [call.queue_name]).filter(Boolean))];
const recipient = escapeHtml(phones.join(' · ') || 'Ukendt telefon');
const queue = escapeHtml(call.queue_name || 'Ukendt kø');
const contactParts = [call.contact_name, call.company_name].filter(Boolean).map(escapeHtml);
const contact = contactParts.length ? ` <span class="text-muted">· ${contactParts.join(' · ')}</span>` : '';
return `<div class="d-flex align-items-center flex-wrap gap-2 py-1">
<span class="badge text-bg-danger">RINGER</span>
<strong>${recipient}</strong>
<span>fra ${caller}</span>${contact}
<span>fra ${caller}</span>
<span class="badge text-bg-light border">${queue}</span>${contact}
</div>`;
}).join('');
}