lisa-api
Version:
Lisa Javascript XMPP Library =============
375 lines (292 loc) • 8.7 kB
JavaScript
var conn;
var model;
// update every 5 seconds, max 300 points = 25 minutes
var GRAPH_MAX_POINTS = 300;
var GRAPH_REFRESH_INTERVAL = 5*1000;
$(document).ready(function() {
// Default server (SpeakUp NL production)
$('#login_server').val('uc.pbx.speakup-telecom.com');
$('#login_form').submit(function() {
login();
return false;
});
var username = localStorage ? localStorage.getItem('username') : null;
if (username) {
$('#login_username').val(username);
$('#login_server').val(localStorage.getItem('server'));
}
});
function login() {
$('#login').hide();
$('#loading').show();
$('#login_error').hide();
var username = $('#login_username').val();
var password = $('#login_password').val();
var server = $('#login_server').val();
localStorage.setItem('username', username);
localStorage.setItem('server', server);
conn = new Lisa.Connection();
// Setup logging and status messages.
conn.logging.setCallback(function(msg) {
console.log(msg);
});
conn.logging.setStatusCallback(function(msg) {
$('#status').text(msg);
});
// Setup connection-status callback.
conn.connectionStatusObservable.addObserver(connectionStatusCallback);
$('#status').text('Connecting...');
var jid = username; // either username or username@domain
if (jid.indexOf('@') == -1) {
jid = username + '@' + server;
}
/*
* Get the correct https://bosh.<basedomain> bosh-proxy server
*/
boshServer = getEnvWithPrefix("bosh", server);
conn.connect(boshServer, jid, password);
// Get the company-model
conn.getModel().done(gotModel);
conn.getModel().fail(function() {
connectionStatusCallback("INITFAIL");
});
}
function connectionStatusCallback(status) {
console.log("Strophe: status is ", status);
if (status == Strophe.Status.CONNFAIL) {
$('#connect').get(0).value = 'connect';
} else if (status == Strophe.Status.DISCONNECTED) {
$('#connect').get(0).value = 'connect';
} else if (status == Strophe.Status.CONNECTED) {
$('#status').text('Loading...');
} else if (status == Strophe.Status.AUTHFAIL) {
$('#loading').hide();
$('#login').show();
$('#login_error').show();
$('#login_error').text('Authentication failed.');
} else if (status == "INITFAIL") {
$('#loading').hide();
$('#login').show();
$('#login_error').show();
$('#login_error').text("Authentication successfull, but server not responding as expected. Try again later, or contact support.");
}
}
function gotModel(newModel) {
// Show interface
$('#loading').hide();
$('#container').show();
model = newModel;
refreshModel(model);
initGraph();
// Listen for added or removed users or queues, which requires to redraw the whole structure.
model.userListObservable.addObserver(refreshModel);
model.queueListObservable.addObserver(refreshModel);
model.callListObservable.addObserver(updateCalls);
setInterval(updateGraph, GRAPH_REFRESH_INTERVAL);
}
function refreshModel(model) {
console.log("Refreshing interface.")
$('#queue-list').empty();
// Add queues to interface.
for ( var queueId in model.queues) {
addQueue(model.queues[queueId]);
}
// Add users to interface.
for ( var userId in model.users) {
// We're only listening for changes in the logged-on user. Remove if to listen for all users.
if (userId == Lisa.Connection.myUserId) {
var user = model.getUser(userId);
var entry = $('#tpl_own_user').clone().attr('id', 'myuser');
user.observable.addObserver(function(changedUser) { updateUser(changedUser, entry); });
user.observable.notify(user);
$('#myuser').html(user.name + ' [' + user.extension + ']');
}
}
}
function updateUser(user, entry) {
entry.find('.user_name').text(user.name);
var status_entry = entry.find('.user_status');
if (_.size(user.calls) > 0) {
status_entry.text('Calling...');
$(entry).animate({backgroundColor: "#CCCCCC"}, 1000);
} else {
status_entry.text('Extension: ' + user.extension);
$(entry).animate({backgroundColor: "transparant"}, 1000);
}
}
/* Add / Update the page-elements for queues */
function addQueue(queue) {
var entry = $('#tpl_queue').clone().attr('id', 'queue_' + queue.id);
entry.find('.queue_name').text(queue.name);
$('#queue-list').append(entry);
updateQueue(queue);
queue.observable.addObserver(function(queue) {
updateQueue(queue);
});
}
function updateQueue(queue) {
var entry = $('#queue_' + queue.id);
var agents = 0;
for ( var userId in queue.users) {
var user = queue.users[userId];
if (user.loggedIn) {
++agents;
}
}
var calls = _.size(queue.calls);
entry.find('.queue_agents').text('Agents: ' + agents);
entry.find('.queue_calls').text('Calls in queue: ' + calls);
entry.find('.queue_waiting').text(
'Total calls today: ' + queue.totalCalls);
if (calls == 0) {
entry.css('background-color', "lightblue");
$(entry).animate({
backgroundColor : "transparant"
}, 1000);
} else if (calls < 5) {
entry.css('background-color', "00FF00");
$(entry).animate({
backgroundColor : "#85FF5C"
}, 1000);
} else {
entry.css('background-color', "FF0000");
$(entry).animate({
backgroundColor : "#FF5050"
}, 1000);
}
}
// http://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
function safeId(myid) {
return myid.replace(/(:|\.|\[|\]|\@|\/)/g, "\\$1");
}
/* Add / Update the page-elements for calls */
function updateCalls(call, type) {
if (type == 'remove') {
var elem = $('#call_' + safeId(call.id));
var txt = elem.text();
elem.text(txt + ' ... ENDED');
elem.css('background-color', '#FA5858');
setTimeout(function() {
elem.remove();
}, 500);
// add to history
var historyElem = $('#tpl_call').clone();
historyElem.text('Ended at ' + ((new Date()).toLocaleTimeString())
+ ': ' + txt);
$('#call-history').append(historyElem);
} else if (type == 'add') {
var elem = $('#tpl_call').clone().attr('id', 'call_' + call.id);
updateCall(call, elem);
$('#current-calls').append(elem);
call.observable.addObserver(function(call) {
updateCall(call);
});
}
}
function updateCall(call, elem) {
if (!elem) {
elem = $('#call_' + safeId(call.id));
}
elem.text(callToString(call));
}
function callToString(call) {
if (call == null)
return "";
var str = 'Call from ';
str += endpointToString(call.source);
str += ' to ';
str += endpointToString(call.destination);
str += '.';
return str;
}
function endpointToString(endpoint) {
if (endpoint == null)
return "";
switch (endpoint.attr('type')) {
case 'User':
var userId = endpoint.find('userId').text();
var user = model.getUser(userId);
return user.name + " [" + user.extension + "]";
case 'Dialplan':
var txt = endpoint.find('description').text();
if (txt != '' ) return txt;
return endpoint.find('exten').text();
case 'Queue':
var queueId = endpoint.find('queueId').text();
var queue = model.getQueue(queueId);
return "queue '" + queue.name + "'";
case 'External':
return endpoint.find('number').text();
default:
console.log('Cannot represent endpointType ' + endpoint.attr('type'));
return '[unknown]';
}
}
/* Graph */
var graphSeries = [];
var jqPlot;
var maxYvalue = 0;
function initGraph() {
for(var queueId in model.queues) {
graphSeries.push([]);
}
updateGraph();
}
function updateGraph() {
var i=0;
var timestamp = Math.round(new Date().getTime());
// TODO: account for dynamically adding/removing queues
for(queueId in model.queues) {
var queue = model.queues[queueId];
var val = _.size(queue.calls);
var point = [timestamp, val];
if (val > maxYvalue)
maxYvalue = val;
graphSeries[i].push(point);
// limit amount of data points
while(graphSeries[i].length > GRAPH_MAX_POINTS) {
graphSeries[i].shift();
}
i++;
}
// jqPlot cannot draw an empty graph
if (graphSeries.length == 0)
return;
if (!jqPlot) {
var labels = [];
for(queueId in model.queues) {
var queue = model.queues[queueId];
labels.push(queue.name);
}
console.log('plotting: ' + graphSeries);
jqPlot = $.jqplot('chartdiv', graphSeries, {
title: 'Number of Calls',
axes:{
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
tickOptions:{formatString:'%H:%M'},
},
yaxis:{
min: 0,
max: maxYvalue,
},
},
legend: {
show: true,
labels: labels,
location: 'nw',
},
seriesDefaults: {
showMarker: false,
},
});
} else {
for (i in jqPlot.series) {
jqPlot.series[i].data = graphSeries[i]
}
jqPlot.resetAxesScale();
// no negative values
jqPlot.axes.yaxis.min = 0;
jqPlot.replot();
}
}