diff --git a/voxtelesys_integration/public/js/voxtelesys_call_popup.js b/voxtelesys_integration/public/js/voxtelesys_call_popup.js new file mode 100644 index 0000000..dfa6c57 --- /dev/null +++ b/voxtelesys_integration/public/js/voxtelesys_call_popup.js @@ -0,0 +1,117 @@ +/** + * voxtelesys_call_popup.js + * Overrides frappe.phone_call.handler for click-to-call via Voxtelesys. + * Subscribes to realtime events for incoming call popup + active call bar. + */ +(function () { + "use strict"; + + frappe.after_ajax(function () { + if (!frappe.boot.voxtelesys || !frappe.boot.voxtelesys.enabled) return; + VoxtelesysPhone.init(); + }); + + const VoxtelesysPhone = { + activeCallLog: null, popup: null, _popupTimeout: null, + + init() { + this._overridePhoneCallHandler(); + this._subscribeRealtime(); + console.log("[Voxtelesys] Telephony provider initialised."); + }, + + _overridePhoneCallHandler() { + frappe.phone_call = { + handler: (phoneNumbers, frm) => { + const numbers = Array.isArray(phoneNumbers) ? phoneNumbers : [phoneNumbers]; + if (numbers.length === 1) { VoxtelesysPhone.dialNumber(numbers[0], frm); } + else { VoxtelesysPhone._showNumberPicker(numbers, frm); } + }, + }; + }, + + dialNumber(number, frm) { + const args = { to: number, from_: frappe.boot.voxtelesys.caller_id || "" }; + if (frm && frm.doc) { args.reference_doctype = frm.doctype; args.reference_name = frm.docname; } + frappe.call({ + method: "voxtelesys_integration.api.voxtelesys.make_outbound_call", + args, + callback: (r) => { + if (r.message && r.message.ok) { + VoxtelesysPhone._showCallBar({ direction: "Outbound", number, callLog: r.message.call_log, callSid: r.message.call_sid }); + } else { + frappe.msgprint({ title: __("Call Failed"), message: __("Could not place call. Check Voxtelesys settings."), indicator: "red" }); + } + }, + }); + }, + + _subscribeRealtime() { + frappe.realtime.on("voxtelesys_call_initiated", (data) => { + if (data.direction === "Inbound") VoxtelesysPhone._showIncomingCallPopup(data); + }); + frappe.realtime.on("voxtelesys_call_disconnected", (data) => { + VoxtelesysPhone._handleCallDisconnected(data); + }); + }, + + _showIncomingCallPopup(data) { + if (this.popup && this.popup.call_sid === data.call_sid) return; + this.popup = new frappe.ui.Dialog({ + title: __("Incoming Call"), + fields: [{ fieldtype: "HTML", fieldname: "call_info", options: ` +