You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

658 lines
28 KiB

define(function(require){
var $ = require('jquery')
,_ = require('underscore')
,monster = require('monster')
,toastr = require('toastr')
;
var app = {
name: 'callcenter',
css: [ 'app', 'icons' ],
i18n: {
'en-US': { customCss: false },
'de-DE': { customCss: false },
'dk-DK': { customCss: false },
'it-IT': { customCss: false },
'fr-FR': { customCss: false },
'nl-NL': { customCss: false },
'ro-RO': { customCss: false },
'ru-RU': { customCss: false },
'pt-PT': { customCss: false },
'zh-CN': { customCss: false },
'es-ES': { customCss: false }
},
load: function(callback){
var self = this;
self.initApp(function() {
callback && callback(self);
});
},
global_timer: false,
current_queue_id: undefined,
hide_logout: false,
map_timers: {
calls_waiting: {},
calls_in_progress: {}
},
initApp: function(callback) {
var self = this;
monster.pub('auth.initApp', {
app: self,
callback: callback
});
},
// API Calls
queue_eavesdrop: function(callback) {
var self = this;
self.callApi({
resource: 'queues.queue_eavesdrop',
data: {
accountId: self.accountId
},
success: function(queue_eavesdrop) {
callback(queue_eavesdrop.data);
}
});
},
listDevices: function(callback) {
var self = this;
self.callApi({
resource: 'device.list',
data: {
accountId: self.accountId
},
success: function(devices) {
callback(devices.data);
}
});
},
poll_agents: function(global_data, _container) {
var self = this,
container = _container,
polling_interval = 6,
map_agents = {},
cpt = 0,
current_queue,
current_global_data = global_data,
stop_light_polling = false,
poll = function() {
var data_template = $.extend(true, {}, {agents: current_global_data.agents, queues: current_global_data.queues}); //copy without reference;
if(stop_light_polling === false) {
monster.parallel(
{
queues_livestats: function(callback) {
self.get_queues_livestats(function(_data_live_queues) {
callback(null, _data_live_queues);
});
},
agents_livestats: function(callback) {
self.get_agents_livestats(function(_data_live_agents) {
callback(null, _data_live_agents);
});
},
agents_status: function(callback) {
self.get_agents_status(function(_data_live_status) {
callback(null, _data_live_status);
},
function(_data_live_status) {
callback(null, {});
}
);
},
},
function(err, results) {
data_template = self.format_live_data(data_template,{
agents_live_stats: results.agents_livestats,
queues_live_stats: results.queues_livestats,
agents_live_status: results.agents_status
});
}
);
}
},
huge_poll = function() {
if($('#dashboard-content').size() === 0) {
self.clean_timers();
}
else {
if(++cpt % 30 === 0) {
self.fetch_all_data(function(data) {
current_global_data = data;
});
}
else {
poll();
}
}
};
$.each(global_data.agents, function(k, v) {
map_agents[v.id] = 'logged_out';
});
self.global_timer = setInterval(huge_poll, polling_interval * 1000);
},
get_queues_livestats: function(callback) {
var self = this;
self.callApi({
resource: 'queues.queues_livestats',
data: {
accountId: self.accountId
},
success: function(queue_livestats) {
callback(queue_livestats.data);
}
});
},
get_agents_status: function(callback) {
var self = this;
self.callApi({
resource: 'agents.agents_status',
data: {
accountId: self.accountId
},
success: function(agents_status) {
callback(agents_status.data);
}
});
},
get_agents_livestats: function(callback) {
var self = this;
self.callApi({
resource: 'agents.agents_livestats',
data: {
accountId: self.accountId
},
success: function(agents_livestats) {
callback(agents_livestats.data);
}
});
},
get_agents_stats: function(callback) {
var self = this;
self.callApi({
resource: 'agents.agents_status',
data: {
accountId: self.accountId
},
success: function(agents_status) {
callback(agents_status.data);
}
});
},
get_queues_stats: function(callback) {
var self = this;
self.callApi({
resource: 'queues.queues_stats',
data: {
accountId: self.accountId
},
success: function(queues_stats) {
callback(queues_stats.data);
}
});
},
get_queues: function(callback) {
var self = this;
self.callApi({
resource: 'queues.queues_list',
data: {
accountId: self.accountId
},
success: function(data) {
callback && callback(data.data);
}
});
},
get_agents: function(callback) {
var self = this;
self.callApi({
resource: 'agents.agents_list',
data: {
accountId: self.accountId
},
success: function(agents) {
callback(agents.data);
}
});
},
render_callwaiting_list: function(_container){
var self = this,
container = _container || $('#dashboard-content');
$('#callwaiting-list', container).empty().listpanel({
label: 'Call Waiting',
identifier: 'callwaiting-listview',
data: []
});
$('.add_flow', container).empty().html('call_waiting_log');
},
get_time_seconds: function(seconds) {
var seconds = Math.floor(seconds),
hours = Math.floor(seconds / 3600),
minutes = Math.floor(seconds / 60) % 60,
remaining_seconds = seconds % 60,
display_time = (hours < 10 ? '0' + hours : '' + hours) + ':' + (minutes < 10 ? '0' + minutes : '' + minutes) + ':' + (remaining_seconds < 10 ? '0' + remaining_seconds : '' + remaining_seconds);
return seconds >= 0 ? display_time : '00:00:00';
},
format_live_data: function(formatted_data, data) {
var self = this,
current_agents_by_queue = {};
formatted_data.current_timestamp = data.queues_live_stats.current_timestamp;
formatted_data.calls_waiting = {};
formatted_data.calls_in_progress = {};
formatted_data.agent_status = {
busy: {},
wrapup: {},
paused: {}
};
//Reinitializing previous data;
$.each(formatted_data.queues, function(k, queue) {
queue.abandoned_calls = 0;
queue.average_hold_time = self.get_time_seconds(0);
queue.current_calls = 0;
queue.total_calls = 0;
queue.total_wait_time = 0;
});
if(data.agents_live_status) {
$.each(data.agents_live_status, function(k, agent_status) {
if(k in formatted_data.agents) {
if(agent_status.status === 'outbound') {
agent_status.status = 'busy';
}
if(agent_status.status === 'connected') {
agent_status.status = 'handling';
}
var current_status = agent_status.status;
formatted_data.agents[k].status = current_status;
formatted_data.agents[k].status_started = agent_status.timestamp;
if($.inArray(current_status, ['busy', 'wrapup', 'paused']) >= 0) {
formatted_data.agent_status[current_status][k] = agent_status;
if(current_status === 'busy') {
formatted_data.agents[k].call_time = self.get_time_seconds(formatted_data.current_timestamp - agent_status.timestamp)
}
else if(current_status === 'paused') {
if('pause_time' in agent_status) {
formatted_data.agents[k].call_time = self.get_time_seconds(agent_status.pause_time - (formatted_data.current_timestamp - agent_status.timestamp))
}
else {
formatted_data.agents[k].call_time = self.get_time_seconds(formatted_data.current_timestamp - agent_status.timestamp)
}
}
else {
formatted_data.agents[k].call_time = self.get_time_seconds(agent_status.wait_time - (formatted_data.current_timestamp - agent_status.timestamp));
}
}
else if(current_status === 'connecting') {
formatted_data.agents[k].current_call = { friendly_title: agent_status.caller_id_name || agent_status.caller_id_number || agent_status.call_id };
}
if(current_status !== 'logged_out') {
$.each(formatted_data.agents[k].queues_list, function(queue_id, queue_data) {
if(!(queue_id in current_agents_by_queue)) {
current_agents_by_queue[queue_id] = 1;
}
else {
current_agents_by_queue[queue_id]++;
}
});
}
}
});
}
$.each(current_agents_by_queue, function(queue_id, count) {
if(queue_id in formatted_data.queues) {
formatted_data.queues[queue_id].current_agents = count || 0;
}
});
$.each(data.agents_live_stats, function(k, agent_stats) {
if(k in formatted_data.agents) {
formatted_data.agents[k].missed_calls = agent_stats.missed_calls || 0;
formatted_data.agents[k].total_calls = agent_stats.total_calls || 0;
if('queues' in agent_stats) {
$.each(agent_stats.queues, function(queue_id, queue_stat) {
if(queue_id in formatted_data.agents[k].queues_list) {
formatted_data.agents[k].queues_list[queue_id] = {
id: queue_id || '',
missed_calls: queue_stat.missed_calls || 0,
total_calls: queue_stat.total_calls || 0
};
}
});
}
}
});
if('stats' in data.queues_live_stats) {
$.each(data.queues_live_stats.stats, function(index, queue_stats) {
var k = queue_stats.queue_id,
call_id = queue_stats.call_id;
if(typeof formatted_data.queues[k] == "object") {
formatted_data.queues[k].current_calls = formatted_data.queues[k].current_calls || 0;
if('wait_time' in queue_stats && queue_stats.status !== 'abandoned') {
formatted_data.queues[k].total_wait_time += queue_stats.wait_time;
}
if(queue_stats.status === 'abandoned') {
formatted_data.queues[k].abandoned_calls++;
formatted_data.queues[k].total_calls++;
}
else if(queue_stats.status === 'waiting') {
formatted_data.calls_waiting[call_id] = queue_stats;
formatted_data.calls_waiting[call_id].friendly_duration = self.get_time_seconds(formatted_data.current_timestamp - queue_stats.entered_timestamp);
formatted_data.calls_waiting[call_id].friendly_title = queue_stats.caller_id_name || queue_stats.caller_id_number || call_id;
formatted_data.queues[k].current_calls++;
}
else if(queue_stats.status === 'handled') {
formatted_data.calls_in_progress[call_id] = queue_stats;
formatted_data.agents[queue_stats.agent_id].call_time = self.get_time_seconds(formatted_data.current_timestamp - queue_stats.handled_timestamp);
formatted_data.agents[queue_stats.agent_id].current_call = queue_stats;
formatted_data.agents[queue_stats.agent_id].current_call.friendly_title = queue_stats.caller_id_name || queue_stats.caller_id_number || call_id;
formatted_data.calls_in_progress[call_id].friendly_duration = self.get_time_seconds(formatted_data.current_timestamp - queue_stats.entered_timestamp);
formatted_data.queues[k].total_calls++;
formatted_data.queues[k].current_calls++;
}
else if(queue_stats.status === 'processed') {
formatted_data.queues[k].total_calls++;
}}
});
}
$.each(formatted_data.queues, function(k, v) {
if(v.total_calls > 0) {
var completed_calls = v.total_calls - v.abandoned_calls;
v.average_hold_time = self.get_time_seconds(v.total_wait_time / completed_calls);
}
});
return formatted_data;
},
format_data: function(data) {
var self = this,
formatted_data = {};
/* Formatting Queues */
formatted_data.queues = {};
$.each(data.queues, function(k, v) {
formatted_data.queues[v.id] = $.extend(true, {
current_calls: 0,
total_calls: 0,
current_agents: 0,
max_agents: 0,
average_hold_time: self.get_time_seconds(0),
total_wait_time: 0,
abandoned_calls: 0
}, v);
});
/* Formatting Agents */
formatted_data.agents = {};
$.each(data.agents, function(k, v) {
if(v.queues && v.queues.length > 0) {
formatted_data.agents[v.id] = $.extend(true, {
status: 'logged_out',
missed_calls: 0,
total_calls: 0,
queues_list: {}
}, v);
}
$.each(v.queues, function(k, queue_id) {
if(queue_id in formatted_data.queues) {
formatted_data.queues[queue_id].max_agents++;
formatted_data.agents[v.id].queues_list[queue_id] = {
missed_calls: 0,
total_calls: 0
};
}
});
});
formatted_data = self.format_live_data(formatted_data, data);
return formatted_data;
},
render: function(_container) {
var self = this,
container = _container || $('#monster_content');
// account switching for monster-ui
self.accountId = monster.apps.auth.accountId;
self.clean_timers();
self.fetch_all_data(function(data) {
queues_html = $(monster.template(self, 'queues_dashboard', {queues: data.queues}));
agents_html = $(monster.template(self, 'agents_dashboard', {agents: data.agents}));
calls_html = $(monster.template(self, 'calls_dashboard', {progress: data.calls_in_progress, waits: data.calls_waiting} ));
html = $(monster.template(self, 'dashboard', {}));
container.empty().append(html);
scroll_value = $('.topbar-right .list_queues_inner', container).scrollLeft() || 0;
container.find('#dashboard-view').empty().append(agents_html);
container.find('.topbar-right').empty().append(queues_html);
container.find('.topbar-right .list_queues_inner').animate({ scrollLeft: scroll_value }, 0);
container.find('#callwaiting-list').append(calls_html);
self.poll_agents(data, container);
(container).empty().append(html);
self.bind_live_events(container);
if(typeof queue_id != 'undefined') {
self.detail_stat(queue_id, container);
}
});
},
fetch_all_data: function(callback) {
var self = this;
monster.parallel({
queues_livestats: function(callback) {
self.get_queues_livestats(function(_data_live_queues) {
callback(null, _data_live_queues);
});
},
agents_livestats: function(callback) {
self.get_agents_livestats(function(_data_live_agents) {
callback(null, _data_live_agents);
});
},
agents_status: function(callback) {
self.get_agents_status(function(_data_live_status) {
callback(null, _data_live_status);
},
function(_data_live_status) {
callback(null, {});
}
);
},
queues: function(callback) {
self.get_queues(function(_data_queues) {
callback(null, _data_queues);
});
},
agents: function(callback) {
self.get_agents(function(_data_agents) {
callback(null, _data_agents);
});
},
},
function(err, results) {
var _data = {
queues: results.queues,
agents: results.agents,
agents_live_stats: results.agents_livestats,
queues_live_stats: results.queues_livestats,
agents_live_status: results.agents_status
};
_data = self.format_data(_data);
if(typeof callback === 'function') {
callback(_data);
}
}
);
},
bind_live_events: function(container) {
var self = this;
// list of queues
$('.list_queues_inner > li', container).on('click', function(event) {
queue_id = this.id;
var $self_queue = $(self);
if($self_queue.hasClass('active')) {
self.current_queue_id = undefined;
$('.agent_wrapper', container).css('display', 'inline-block');
$('.all_data', container).show();
$('.queue_data', container).hide();
$('#callwaiting-list li', container).show();
$('.icon.edit_queue', container).hide();
$('.icon.eavesdrop_queue', container).hide();
$('.list_queues_inner > li', container).removeClass('active');
}
else {
self.detail_stat(queue_id, container);
}
});
},
detail_stat: function(queue_id, container) {
var self = this,
$self_queue = $('#'+queue_id, container);
self.current_queue_id = queue_id;
$('.list_queues_inner > li', container).removeClass('active');
$self_queue.addClass('active');
$('#callwaiting-list li', container).each(function(k, v) {
var $v = $(v);
if(v.getAttribute('data-queue_id') !== queue_id) {
$v.hide();
}
else {
$v.show();
}
});
},
clean_timers: function() {
var self = this;
if(self.global_timer !== false) {
clearInterval(self.global_timer);
self.global_timer = false;
}
$.each(self.map_timers, function(type, list_timers) {
$.each(list_timers, function(k, v) {
clearInterval(v.timer);
});
});
self.map_timers = {};
},
activate_queue_stat: function(args) {
//TODO check render global data
var self = this,
container = args.container || $('#monster-content');
container.empty();
self.render(container, function() {
var $self_queue = $('#'+args.id, container);
self.detail_stat(args.id, container);
});
},
activate: function(_container) {
var self = this,
container = _container || $('#monster-content');
container.empty();
self.current_queue_id = undefined;
self.hide_logout = false;
//TODO check render global data
self.render(container);
},
login: function(agent, callback) {
var self = this,
agentId = $(agent).attr('id');
self.callApi({
resource: 'agents.agents_toggle',
data: {
accountId: self.accountId,
agentId: agentId,
data: {status: 'login'}
}
});
},
logout: function(agent, callback) {
var self = this,
agentId = $(agent).attr('id');
self.callApi({
resource: 'agents.agents_toggle',
data: {
accountId: self.accountId,
agentId: agentId,
data: {status: 'logout'}
}
});
}
}
return app;
});