${__('No issue raised by the customer.')}`
+ }, {
+ 'fieldtype': 'Column Break',
+ }, {
+ 'fieldtype': 'Small Text',
+ 'label': __('Call Summary'),
+ 'fieldname': 'call_summary',
+ }, {
+ 'fieldtype': 'Button',
+ 'label': __('Save'),
+ 'click': () => {
+ const call_summary = this.dialog.get_value('call_summary');
+ if (!call_summary) return;
+ frappe.xcall('erpnext.crm.doctype.utils.add_call_summary', {
+ 'docname': this.call_log.id,
+ 'summary': call_summary,
+ }).then(() => {
+ this.close_modal();
+ frappe.show_alert({
+ message: `${__('Call Summary Saved')}
${__('View call log')}`,
+ indicator: 'green'
+ });
+ });
+ }
+ }],
+ });
+ this.set_call_status();
+ this.make_caller_info_section();
+ this.dialog.get_close_btn().show();
+ this.dialog.$body.addClass('call-popup');
+ this.dialog.set_secondary_action(this.close_modal.bind(this));
+ frappe.utils.play_sound('incoming-call');
+ this.dialog.show();
+ }
+
+ make_caller_info_section() {
+ const wrapper = this.dialog.get_field('caller_info').$wrapper;
+ wrapper.append(` ${__("Loading...")}
`);
+ frappe.xcall('erpnext.crm.doctype.utils.get_document_with_phone_number', {
+ 'number': this.caller_number
+ }).then(contact_doc => {
+ wrapper.empty();
+ const contact = this.contact = contact_doc;
+ if (!contact) {
+ this.setup_unknown_caller(wrapper);
+ } else {
+ this.setup_known_caller(wrapper);
+ this.set_call_status();
+ this.make_last_interaction_section();
+ }
+ });
+ }
+
+ setup_unknown_caller(wrapper) {
+ wrapper.append(`
+
+ ${__('Unknown Number')}: ${this.caller_number}
+
+
+ `).find('button').click(
+ () => frappe.set_route(`Form/Contact/New Contact?phone=${this.caller_number}`)
+ );
+ }
+
+ setup_known_caller(wrapper) {
+ const contact = this.contact;
+ const contact_name = frappe.utils.get_form_link(contact.doctype, contact.name, true, this.get_caller_name());
+ const links = contact.links ? contact.links : [];
+
+ let contact_links = '';
+
+ links.forEach(link => {
+ contact_links += `${link.link_doctype}: ${frappe.utils.get_form_link(link.link_doctype, link.link_name, true)}
`;
+ });
+ wrapper.append(`
+
+ ${frappe.avatar(null, 'avatar-xl', contact.name, contact.image)}
+
+
${contact_name}
+
${contact.mobile_no || ''}
+
${contact.phone_no || ''}
+ ${contact_links}
+
+
+ `);
+ }
+
+ set_indicator(color, blink=false) {
+ let classes = `indicator ${color} ${blink ? 'blink': ''}`;
+ this.dialog.header.find('.indicator').attr('class', classes);
+ }
+
+ set_call_status(call_status) {
+ let title = '';
+ call_status = call_status || this.call_log.status;
+ if (['Ringing'].includes(call_status) || !call_status) {
+ title = __('Incoming call from {0}', [this.get_caller_name()]);
+ this.set_indicator('blue', true);
+ } else if (call_status === 'In Progress') {
+ title = __('Call Connected');
+ this.set_indicator('yellow');
+ } else if (call_status === 'Missed') {
+ this.set_indicator('red');
+ title = __('Call Missed');
+ } else if (['Completed', 'Disconnected'].includes(call_status)) {
+ this.set_indicator('red');
+ title = __('Call Disconnected');
+ } else {
+ this.set_indicator('blue');
+ title = call_status;
+ }
+ this.dialog.set_title(title);
+ }
+
+ update_call_log(call_log) {
+ this.call_log = call_log;
+ this.set_call_status();
+ }
+
+ close_modal() {
+ this.dialog.hide();
+ delete erpnext.call_popup;
+ }
+
+ call_disconnected(call_log) {
+ frappe.utils.play_sound('call-disconnect');
+ this.update_call_log(call_log);
+ setTimeout(() => {
+ if (!this.dialog.get_value('call_summary')) {
+ this.close_modal();
+ }
+ }, 10000);
+ }
+
+ make_last_interaction_section() {
+ frappe.xcall('erpnext.crm.doctype.utils.get_last_interaction', {
+ 'number': this.caller_number,
+ 'reference_doc': this.contact
+ }).then(data => {
+ const comm_field = this.dialog.get_field('last_communication');
+ if (data.last_communication) {
+ const comm = data.last_communication;
+ comm_field.set_value(comm.content);
+ }
+
+ if (data.last_issue) {
+ const issue = data.last_issue;
+ const issue_field = this.dialog.get_field("last_issue");
+ issue_field.set_value(issue.subject);
+ issue_field.$wrapper.append(`
+ ${__('View all issues from {0}', [issue.customer])}
+ `);
+ }
+ });
+ }
+ get_caller_name() {
+ return this.contact ? this.contact.lead_name || this.contact.name || '' : this.caller_number;
+ }
+ setup_listener() {
+ frappe.realtime.on(`call_${this.call_log.id}_disconnected`, call_log => {
+ this.call_disconnected(call_log);
+ // Remove call disconnect listener after the call is disconnected
+ frappe.realtime.off(`call_${this.call_log.id}_disconnected`);
+ });
+ }
+}
+
+$(document).on('app_ready', function () {
+ frappe.realtime.on('show_call_popup', call_log => {
+ if (!erpnext.call_popup) {
+ erpnext.call_popup = new CallPopup(call_log);
+ } else {
+ erpnext.call_popup.update_call_log(call_log);
+ erpnext.call_popup.dialog.show();
+ }
+ });
+});
diff --git a/erpnext/public/less/call_popup.less b/erpnext/public/less/call_popup.less
new file mode 100644
index 00000000000..32e85ce16d9
--- /dev/null
+++ b/erpnext/public/less/call_popup.less
@@ -0,0 +1,9 @@
+.call-popup {
+ a:hover {
+ text-decoration: underline;
+ }
+ .for-description {
+ max-height: 250px;
+ overflow: scroll;
+ }
+}
\ No newline at end of file
diff --git a/erpnext/public/sounds/call-disconnect.mp3 b/erpnext/public/sounds/call-disconnect.mp3
new file mode 100644
index 00000000000..1202273dfe5
Binary files /dev/null and b/erpnext/public/sounds/call-disconnect.mp3 differ
diff --git a/erpnext/public/sounds/incoming-call.mp3 b/erpnext/public/sounds/incoming-call.mp3
new file mode 100644
index 00000000000..60431e30884
Binary files /dev/null and b/erpnext/public/sounds/incoming-call.mp3 differ