diff --git a/app/active_calls/active_calls.php b/app/active_calls/active_calls.php index 127f3fa1e..d75d4234e 100644 --- a/app/active_calls/active_calls.php +++ b/app/active_calls/active_calls.php @@ -478,7 +478,8 @@ echo "\n"; // Ringing, Answer, Hangup function channel_callstate_event(call) { - const state = call.answer_state; + const state = normalize_answer_state(call); + call.answer_state = state; //update color const uuid = call.unique_id; //console.log(call.event_name, call.unique_id, state, call); @@ -528,6 +529,21 @@ echo "\n"; } } + function normalize_answer_state(call) { + const answer_state = String(call.answer_state ?? '').toLowerCase(); + if (answer_state !== 'ringing') { + return answer_state; + } + + // The in.progress bootstrap payload is currently synthesized as "ringing" + // even when a call is already established. Mark those request-seeded rows as answered. + if (call.__from_request === true) { + return 'answered'; + } + + return answer_state; + } + function channel_execute_event(call) { //console.log(call.event_name, call.unique_id, call); diff --git a/app/active_calls/resources/dashboard/active_calls.php b/app/active_calls/resources/dashboard/active_calls.php index 59930b39c..3e2cf8a2d 100644 --- a/app/active_calls/resources/dashboard/active_calls.php +++ b/app/active_calls/resources/dashboard/active_calls.php @@ -68,6 +68,9 @@ $c = 0; $row_style["0"] = "row_style0"; $row_style["1"] = "row_style1"; +// From the include statement +global $widget_chart_type; + //icon and count echo "
\n"; echo "".escape($widget_label)."\n"; @@ -362,7 +365,8 @@ if (!empty($_SESSION['user']['extension'])) { // Ringing, Answer, Hangup function channel_callstate_event(call) { - const state = call.answer_state; + const state = normalize_answer_state(call); + call.answer_state = state; //update color const uuid = call.unique_id; //console.log(call.event_name, call.unique_id, state, call); @@ -412,6 +416,21 @@ if (!empty($_SESSION['user']['extension'])) { } } + function normalize_answer_state(call) { + const answer_state = String(call.answer_state ?? '').toLowerCase(); + if (answer_state !== 'ringing') { + return answer_state; + } + + // The in.progress bootstrap payload is currently synthesized as "ringing" + // even when a call is already established. Mark those request-seeded rows as answered. + if (call.__from_request === true) { + return 'answered'; + } + + return answer_state; + } + ////////////////////// // Helper functions // ////////////////////// diff --git a/core/dashboard/resources/javascript/ws_client.js b/core/dashboard/resources/javascript/ws_client.js index 8954282c0..08ee1addf 100644 --- a/core/dashboard/resources/javascript/ws_client.js +++ b/core/dashboard/resources/javascript/ws_client.js @@ -48,6 +48,22 @@ class ws_client { if (status === 'ok' && code >= 200 && code < 300) { resolve({service, topic, payload, code, message}); + + // Some services stream event payloads while also echoing the request_id. + // Dispatch to event handlers so the first streamed event is not swallowed. + if (topic && this._eventHandlers.has(topic)) { + let event_message = message; + if (payload !== null && typeof payload === 'object' && !Array.isArray(payload)) { + event_message = { + ...message, + payload: { + ...payload, + __from_request: true + } + }; + } + this._dispatchEvent(event_message); + } } else { const err = new Error(message || `Error ${code}`); err.code = code;