Browse Source

update master

master
Urs Rüedi 10 years ago
parent
commit
f2abecc875
35 changed files with 2837 additions and 2 deletions
  1. +12
    -2
      README.md
  2. +656
    -0
      app.js
  3. +25
    -0
      i18n/de-DE.json
  4. +25
    -0
      i18n/dk-DK.json
  5. +25
    -0
      i18n/en-US.json
  6. +21
    -0
      i18n/es-ES.json
  7. +21
    -0
      i18n/fr-FR.json
  8. +21
    -0
      i18n/it-IT.json
  9. +21
    -0
      i18n/nl-NL.json
  10. +21
    -0
      i18n/ru-RU.json
  11. +21
    -0
      i18n/zh-CN.json
  12. +121
    -0
      metadata/app.json
  13. BIN
      metadata/icon/Callcenter_app.png
  14. BIN
      metadata/screenshots/callcenter_1.png
  15. BIN
      metadata/screenshots/callcenter_2.png
  16. BIN
      metadata/screenshots/callcenter_3.png
  17. BIN
      metadata/screenshots/callcenter_4.png
  18. +673
    -0
      style/app.css
  19. +1010
    -0
      style/icons.css
  20. BIN
      style/static/images/icons/icons_24x24_blue.png
  21. BIN
      style/static/images/icons/icons_24x24_gradient.png
  22. BIN
      style/static/images/icons/icons_24x24_red.261.delayed
  23. BIN
      style/static/images/icons/icons_24x24_red.png
  24. BIN
      style/static/images/icons/icons_32x32_blue.png
  25. BIN
      style/static/images/icons/icons_32x32_darkgrey.png
  26. BIN
      style/static/images/icons/icons_32x32_gradient.png
  27. BIN
      style/static/images/icons/icons_32x32_green.png
  28. BIN
      style/static/images/icons/icons_32x32_lightgrey.png
  29. BIN
      style/static/images/icons/icons_32x32_red.png
  30. BIN
      style/static/images/icons/icons_32x32_white.png
  31. BIN
      style/static/images/icons/icons_32x32_yellow.png
  32. +94
    -0
      views/agents_dashboard.html
  33. +14
    -0
      views/calls_dashboard.html
  34. +15
    -0
      views/dashboard.html
  35. +41
    -0
      views/queues_dashboard.html

+ 12
- 2
README.md View File

@ -1,2 +1,12 @@
# monster-ui-callcenter
callcenter app for acdc in monster-ui
# monster-ui-callcenter (Cloudbased Callcenter GUI)
![callcenter](https://raw.githubusercontent.com/urueedi/monster-ui-callcenter/master/metadata/screenshots/callcenter_1.png)
![callcenter](https://raw.githubusercontent.com/urueedi/monster-ui-callcenter/master/metadata/screenshots/callcenter_2.png)
![callcenter](https://raw.githubusercontent.com/urueedi/monster-ui-callcenter/master/metadata/screenshots/callcenter_3.png)
![callcenter](https://raw.githubusercontent.com/urueedi/monster-ui-callcenter/master/metadata/screenshots/callcenter_4.png)
If you need ACD support for kazoo like additional strategy, monster-ui support and so, please ask for support from below
Additional Support
------------------
Open Phone Net AG infos@openent.ch Switzerland

+ 656
- 0
app.js View File

@ -0,0 +1,656 @@
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 },
'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;
});

+ 25
- 0
i18n/de-DE.json View File

@ -0,0 +1,25 @@
{
"callcenter": {
"hide_logged_out_agents": "abgemeldete Agenten ausblenden",
"hide_queues": "Anrufschleifen ausblenden",
"break_time": "Wartezeit",
"wrapping_up": "Abschluss",
"call_time": "Sprechzeit",
"busy_since": "Beschäftigt",
"no_active_call": "keine aktiven Anrufe",
"total_calls": "Anrufe",
"missed_calls": "Verpasst",
"no_active_call": "Inaktiv",
"current_call": "Akiv",
"select_the_device": "Wählen Sie das Gerät das angerufen werden soll",
"which_device": "Welches Gerät?",
"ring": "klingeln",
"cancel": "Abbrechen",
"call_waiting": "Wartende Anrufe",
"call_waiting_log": "Anklopf Aufzeichnung",
"eavesdrop_request_failed": "Antrag gescheitert. Fehler:",
"devices_title": "Geräte",
"hide_queues_html": "Warteräume ausblenden",
"show_queues_html": "Warteräume anzeigen"
}
}

+ 25
- 0
i18n/dk-DK.json View File

@ -0,0 +1,25 @@
{
"callcenter": {
"hide_logged_out_agents": "Hide Logged out Agents",
"hide_queues": "Hide Queues",
"break_time": "Break Time",
"wrapping_up": "Wrapping up",
"call_time": "Call Time",
"busy_since": "Busy since",
"total_calls": "Total Calls",
"missed_calls": "Missed Calls",
"current_call": "Acive call",
"no_active_call": "Inactive call",
"clicking_here_will_send_you": "Clicking here will send you to the Edit Queue page, where you can update settings for this queue, manage its agents and look at this queue reports.",
"select_the_device": "Select the device you want to ring",
"which_device": "Which device?",
"ring": "Ring",
"cancel": "Cancel",
"call_waiting": "Call Waiting",
"call_waiting_log": "Call Waiting Log...",
"eavesdrop_request_failed": "Eavesdrop Request failed. Error #",
"devices_title": "Devices",
"hide_queues_html": "Hide Queues",
"show_queues_html": "Show Queues"
}
}

+ 25
- 0
i18n/en-US.json View File

@ -0,0 +1,25 @@
{
"callcenter": {
"hide_logged_out_agents": "Hide Logged out Agents",
"hide_queues": "Hide Queues",
"break_time": "Break Time",
"wrapping_up": "Wrapping up",
"call_time": "Call Time",
"busy_since": "Busy since",
"total_calls": "Total Calls",
"missed_calls": "Missed Calls",
"current_call": "Acive call",
"no_active_call": "Inactive call",
"clicking_here_will_send_you": "Clicking here will send you to the Edit Queue page, where you can update settings for this queue, manage its agents and look at this queue reports.",
"select_the_device": "Select the device you want to ring",
"which_device": "Which device?",
"ring": "Ring",
"cancel": "Cancel",
"call_waiting": "Call Waiting",
"call_waiting_log": "Call Waiting Log...",
"eavesdrop_request_failed": "Eavesdrop Request failed. Error #",
"devices_title": "Devices",
"hide_queues_html": "Hide Queues",
"show_queues_html": "Show Queues"
}
}

+ 21
- 0
i18n/es-ES.json View File

@ -0,0 +1,21 @@
{
"hide_logged_out_agents": "Hide Logged out Agents",
"hide_queues": "Hide Queues",
"break_time": "Break Time",
"wrapping_up": "Wrapping up",
"call_time": "Call Time",
"busy_since": "Busy since",
"no_active_call": "No active call...",
"total_calls": "Total Calls",
"missed_calls": "Missed Calls",
"clicking_here_will_send_you": "Clicking here will send you to the Edit Queue page, where you can update settings for this queue, manage its agents and look at this queue reports.",
"select_the_device": "Select the device you want to ring",
"which_device": "Which device?",
"ring": "Ring",
"cancel": "Cancel",
"call_waiting_log": "Call Waiting Log...",
"eavesdrop_request_failed": "Eavesdrop Request failed. Error #",
"devices_title": "Devices",
"hide_queues_html": "Hide Queues",
"show_queues_html": "Show Queues"
}

+ 21
- 0
i18n/fr-FR.json View File

@ -0,0 +1,21 @@
{
"hide_logged_out_agents": "Hide Logged out Agents",
"hide_queues": "Hide Queues",
"break_time": "Break Time",
"wrapping_up": "Wrapping up",
"call_time": "Call Time",
"busy_since": "Busy since",
"no_active_call": "No active call...",
"total_calls": "Total Calls",
"missed_calls": "Missed Calls",
"clicking_here_will_send_you": "Clicking here will send you to the Edit Queue page, where you can update settings for this queue, manage its agents and look at this queue reports.",
"select_the_device": "Select the device you want to ring",
"which_device": "Which device?",
"ring": "Ring",
"cancel": "Cancel",
"call_waiting_log": "Call Waiting Log...",
"eavesdrop_request_failed": "Eavesdrop Request failed. Error #",
"devices_title": "Devices",
"hide_queues_html": "Hide Queues",
"show_queues_html": "Show Queues"
}

+ 21
- 0
i18n/it-IT.json View File

@ -0,0 +1,21 @@
{
"hide_logged_out_agents": "Hide Logged out Agents",
"hide_queues": "Hide Queues",
"break_time": "Break Time",
"wrapping_up": "Wrapping up",
"call_time": "Call Time",
"busy_since": "Busy since",
"no_active_call": "No active call...",
"total_calls": "Total Calls",
"missed_calls": "Missed Calls",
"clicking_here_will_send_you": "Clicking here will send you to the Edit Queue page, where you can update settings for this queue, manage its agents and look at this queue reports.",
"select_the_device": "Select the device you want to ring",
"which_device": "Which device?",
"ring": "Ring",
"cancel": "Cancel",
"call_waiting_log": "Call Waiting Log...",
"eavesdrop_request_failed": "Eavesdrop Request failed. Error #",
"devices_title": "Devices",
"hide_queues_html": "Hide Queues",
"show_queues_html": "Show Queues"
}

+ 21
- 0
i18n/nl-NL.json View File

@ -0,0 +1,21 @@
{
hide_logged_out_agents: "Verberg uitgelogde Agents",
hide_queues: "Verberg Queues",
break_time: "Pauze Tijd",
wrapping_up: "Wrapping up",
call_time: "Gesprekstijd",
busy_since: "In gesprek sinds",
no_active_call: "Geen gesprek actief...",
total_calls: "Totaal Gesprekken.",
missed_calls: "Gemisde Gesprekken.",
clicking_here_will_send_you: "Klik hier om de queue te bewerken, agents te beheren en voor rapportage.",
select_the_device: "Selecteer de device die moet overgaan",
which_device: "Welke device?",
ring: "Ring",
cancel: "Annuleren",
call_waiting_log: "Call Waiting Log...",
eavesdrop_request_failed: "Eavesdrop Verzoek mislukt. Erro #",
devices_title: "Devices",
hide_queues_html: "Verberg Queues",
show_queues_html: "Toon Queues"
}

+ 21
- 0
i18n/ru-RU.json View File

@ -0,0 +1,21 @@
{
"hide_logged_out_agents": "Скрыть операторов, не зарегистрированных в системе",
"hide_queues": "Скрыть очереди",
"break_time": "Время паузы",
"wrapping_up": "Закругление",
"call_time": "Время звонка",
"busy_since": "Разговаривает с",
"no_active_call": "Нет активного звонка...",
"total_calls": "Всего звонков",
"missed_calls": "Всего пропущено",
"clicking_here_will_send_you": "Нажатие здесь отправит вас на страницу редактирования очереди, где вы сможете обновить настройки этой очереди, управлять операторами очереди и смотреть отчёты.",
"select_the_device": "Выберите устройство для звонка",
"which_device": "Какое устройство?",
"ring": "Звонить",
"cancel": "Отмена",
"call_waiting_log": "Журнал ожидающих вызовов...",
"eavesdrop_request_failed": "Попытка присоединения не удалась. Ошибка #",
"devices_title": "Устройства",
"hide_queues_html": "Скрыть очереди",
"show_queues_html": "Показать очереди"
}

+ 21
- 0
i18n/zh-CN.json View File

@ -0,0 +1,21 @@
{
"hide_logged_out_agents": "隐藏登出的坐席",
"hide_queues": "隐藏队列",
"break_time": "休息时间",
"wrapping_up": "汇总",
"call_time": "呼叫时长",
"busy_since": "开始忙",
"no_active_call": "没有呼叫...",
"total_calls": "总呼叫数",
"missed_calls": "漏接呼叫",
"clicking_here_will_send_you": "点击这里将进入队列配置页面, 您可以更新队列配置, 管理坐席并查看队列报告.",
"select_the_device": "选择您想振铃的设备",
"which_device": "设备?",
"ring": "振铃",
"cancel": "取消",
"call_waiting_log": "呼叫等待日志...",
"eavesdrop_request_failed": "坚挺请求失败. 错误 #",
"devices_title": "设备",
"hide_queues_html": "隐藏队列",
"show_queues_html": "显示队列"
}

+ 121
- 0
metadata/app.json View File

@ -0,0 +1,121 @@
{
"name": "callcenter",
"i18n": {
"en-US": {
"label": "Callcenter",
"description": "The callcenters app allows you to customize routing calls per webapplication.",
"extended_description": "That allows you to effectively apply your own callcenters and make this product your own. (e.g. ask customer number to route them individually or authentication with your database)",
"features": [
"Add your own Callcenter",
"Change your Callcenter routes",
"Customize the Callcenter message"
]
},
"dk-DK": {
"label": "Callcenter",
"description": "The callcenters app allows you to customize routing calls per webapplication.",
"extended_description": "That allows you to effectively apply your own callcenters and make this product your own. (e.g. ask customer number to route them individually or authentication with your database)",
"features": [
"Add your own Callcenter",
"Change your Callcenter routes",
"Customize the Callcenter message"
]
},
"de-DE": {
"label": "Callcenter",
"description": "Die Callcenter App kann Agenten, Schleifen und Routen einrichten und entsprechnende Abläufe können angepasst werden.",
"extended_description": "Induviduell können Sie Anrufe Ihren Wünschen entgegennehmen und gemäss Ihren Abläufen anzupassen.",
"features": [
"Anpassen der Routen",
"Anpassen der Webapplikationen",
"Anpassung der Links"
]
},
"fr-FR": {
"label": "Callcenter",
"description": "L'application de Callcenter vous permet de personnaliser le routage des appels par application Web.",
"extended_description": "Cela vous permet d'appliquer efficacement votre propre Callcenter et font de ce produit de votre propre. (par exemple, demander le numéro de client pour les acheminer individuellement ou authentification avec votre base de données)",
"features": [
"Edit Callcenter",
"edit apps",
"edit links"
]
},
"it-IT": {
"label": "Callcenter",
"description": "L'applicazione del perno consente di personalizzare le chiamate di routing per ogni applicazione web.",
"extended_description": "Ciò consente di applicare in modo efficace il proprio perno e rendono questo prodotto il proprio. (ad esempio, chiedere il numero cliente di rotta singolarmente o l'autenticazione con il database)",
"features": [
"Edit Perno",
"edit apps",
"edit links"
]
},
"nl-NL": {
"label": "Callcenter",
"description": "De spil app kunt u routing oproepen per webapplicatie aan te passen.",
"extended_description": "Die u toelaat om effectief toe te passen uw eigen spil en maken dit product uw eigen. (bv vraag klantnummer om de route ze individueel of verificatie met uw database)",
"features": [
"Edit Spil",
"edit apps",
"edit links"
]
},
"zh-CN": {
"label": "Callcenter",
"description": "De spil app kunt u routing oproepen per webapplicatie aan te passen.",
"extended_description": "Die u toelaat om effectief toe te passen uw eigen spil en maken dit product uw eigen. (bv vraag klantnummer om de route ze individueel of verificatie met uw database)",
"features": [
"Edit Spil",
"edit apps",
"edit links"
]
},
"es-ES": {
"label": "Callcentere",
"description": "La aplicación de Callcentere le permite personalizar las llamadas de enrutamiento por aplicación web.",
"extended_description": "Eso le permite aplicar de manera efectiva su propio Callcentere y hacen de este producto el suyo propio. (por ejemplo, pedir el número de cliente para enrutar de forma individual o autenticación con su base de datos)",
"features": [
"Edit Callcentere",
"edit apps",
"edit links"
]
},
"ro-RO": {
"label": "Callcenter",
"description": "App Callcenter vă permite să personalizați apelurile de rutare pe aplicație web.",
"extended_description": "Care vă permite să se aplice în mod eficient propria Callcenter și să facă acest produs propriu. (de exemplu, cere numărul de client pentru a direcționa le individual sau autentificare cu baza de date)",
"features": [
"Edit Callcenter",
"edit apps",
"edit links"
]
},
"ru-RU": {
"label": "Callcenter",
"description": "Стержень приложение позволяет настроить звонки маршрутизации каждого веб-приложения.",
"extended_description": "Это позволяет эффективно применять свой собственный стержень и делают этот продукт самостоятельно. (например, попросить номер клиента, чтобы направить их по отдельности или аутентификации с базой данных)",
"features": [
"Edit стержень",
"edit apps",
"edit links"
]
}
},
"tags": [ "carrier", "developer" ],
"api_url": "http://kazoo.allip.ovh:8443/v2",
"icon": "Callcenter_app.png",
"author": "2600Hz",
"version": "1.0",
"license": "-",
"price": 0,
"screenshots": [
"callcenter_1.png",
"callcenter_2.png"
],
"urls": {
"documentation": "{documentation_url}",
"howto": "{howto_video_url}"
},
"pvt_type": "app"
}

BIN
metadata/icon/Callcenter_app.png View File

Before After
Width: 256  |  Height: 256  |  Size: 11 KiB

BIN
metadata/screenshots/callcenter_1.png View File

Before After
Width: 350  |  Height: 300  |  Size: 31 KiB

BIN
metadata/screenshots/callcenter_2.png View File

Before After
Width: 350  |  Height: 300  |  Size: 35 KiB

BIN
metadata/screenshots/callcenter_3.png View File

Before After
Width: 350  |  Height: 300  |  Size: 27 KiB

BIN
metadata/screenshots/callcenter_4.png View File

Before After
Width: 350  |  Height: 300  |  Size: 28 KiB

+ 673
- 0
style/app.css View File

@ -0,0 +1,673 @@
/* Top bar */
#dashboard-content #dashboard-topbar .settings-bar {
background: #B1AFAF;
cursor: pointer;
height: 20px;
line-height: 20px;
padding: 0 60px 3px;
width: auto;
}
#dashboard-content #dashboard-topbar .settings-bar label {
width: 300px;
text-align: left;
color: antiquewhite;
}
#dashboard-content #dashboard-topbar .settings-bar input[type=checkbox] {
margin-right: 10px;
}
#dashboard-content #dashboard-topbar .settings-bar .toggle-button {
text-decoration: underline;
cursor: pointer;
color: antiquewhite;
}
#dashboard-content #dashboard-topbar .settings-bar .toggle-button:hover {
font-weight: bold;
}
#dashboard-content #dashboard-topbar {
width: 100%;
background: transparent linear-gradient(to bottom, #326FB4 0%, #9FC7F5 25%, #CBD3FC 50%, #A9B8FB 75%, #FFF 100%) repeat scroll 0% 0%;
background-color: transparent;
background-image: linear-gradient(to bottom, #326FB4 0%, #9FC7F5 25%, #CBD3FC 50%, #A9B8FB 75%, #FFF 100%);
background-repeat: repeat;
background-attachment: scroll;
background-position: 0% 0%;
background-clip: border-box;
background-origin: padding-box;
background-size: auto auto;
}
/* Top-Right queues */
#dashboard-content #dashboard-topbar .topbar-right {
padding: 15px 0px;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues {
margin: 0px 20px;
height: 200px;
border-radius: 5px;
box-shadow: 1px 1px #333;
background: #4D4D4D;
border: 10px solid #324E93;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .slide {
background: #525252;
cursor: pointer;
height: 180px;
width: 32px;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .slide:hover {
box-shadow: inset 1px 1px 4px 1px #353535;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .slide > .icon {
margin-top: 66px;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .slide.left {
float: left;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .slide.right {
float: right;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner {
width: auto;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
height: 200px;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li{
width: auto;
height: 200px;
list-style-type: none;
display: inline-block;
color: #F0F0F0;
text-shadow: 1px 1px 1px #333;
cursor: pointer;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li.active, #dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li:hover {
background: #414141;
background: -moz-radial-gradient(center, ellipse cover, #414141 50%, #343434 100%);
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(50%,#414141), color-stop(100%,#343434));
background: -webkit-radial-gradient(center, ellipse cover, #414141 50%,#343434 100%);
background: -o-radial-gradient(center, ellipse cover, #414141 50%,#343434 100%);
background: -ms-radial-gradient(center, ellipse cover, #414141 50%,#343434 100%);
background: radial-gradient(center, ellipse cover, #414141 50%,#343434 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#414141', endColorstr='#343434',GradientType=1 );
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li.active .box_title {
color: #05addc;
font-weight: bold;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li:not(:first-child) {
border-left: 1px solid #555;
margin-left: -3px; /* Hack to prevent auto-spacing */
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li {
border-right: 2px solid #333;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .box_title {
height: 40px;
color: #FFF;
line-height: 40px;
font-size: 17px;
border-bottom: 1px solid #555;
text-align: center;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .box {
float: left;
width: 65px;
padding: 5px;
border-top: 1px solid #333;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .box:nth-child(2n) {
border-left: 1px solid #333;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .box > div {
height: 30px;
line-height: 30px;
font-size: 16px;
text-align: center;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .second_row .box > div {
height: 39px;
line-height: 22px;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .box .red {
color: #ff3322;
font-weight: bold;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .box .blue {
color: #05addc;
font-weight: bold;
}
#dashboard-content #dashboard-topbar .topbar-right .list_queues .list_queues_inner > li .box .orange {
color: #ff9933;
}
/* Bottom-left List panel */
#dashboard-content #callwaiting-list {
position:relative;
float: left;
}
#dashboard-content #callwaiting-list .add_flow {
line-height: 60px;
cursor: default;
color: #05addc;
font-size: 14px;
font-weight: bold;
}
#dashboard-content #callwaiting-list .list-panel-anchor ul li {
cursor: default;
}
#dashboard-content #callwaiting-list .list-panel-anchor ul li a {
padding-left: 5px;
width: 110px;
float: left;
overflow: hidden;
white-space: nowrap;
}
#dashboard-content #callwaiting-list .list-panel-anchor ul li:hover, #dashboard-content #callwaiting-list .list-panel-anchor ul li.selected {
background: #333;
}
#dashboard-content #callwaiting-list .list-panel-anchor ul li .timer {
float: left;
width: 45px;
height: 27px;
line-height: 27px;
color: #05addc;
}
/* Bottom-right content */
#dashboard-content .dashboard-bottom-right {
padding: 10px 10px 10px 220px;
}
#dashboard-content .dashboard-bottom-right #agents-view {
padding-left: 22px;
padding-top: 20px;
}
#dashboard-content .dashboard-bottom-right #agents-view.hide-logout .agent_wrapper.logged_out {
display: none !important;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper {
display: inline-block;
margin: 0 10px 20px;
padding: 0 5px 5px;
border-radius: 5px;
width: auto;
border: 5px solid #324E93;
background: transparent linear-gradient(to bottom, #747474 0%, #898989 25%, #747474 50%, #5C5C5C 75%, #4D4D4D 100%) repeat scroll 0% 0%;
background: rgb(34,34,34); /* Old browsers */
background: -moz-linear-gradient(top, rgba(34,34,34,1) 0%, rgba(68,68,68,1) 25%, rgba(85,85,85,1) 50%, rgba(68,68,68,1) 75%, rgba(34,34,34,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(34,34,34,1)), color-stop(25%,rgba(68,68,68,1)), color-stop(50%,rgba(85,85,85,1)), color-stop(75%,rgba(68,68,68,1)), color-stop(100%,rgba(34,34,34,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(34,34,34,1) 0%,rgba(68,68,68,1) 25%,rgba(85,85,85,1) 50%,rgba(68,68,68,1) 75%,rgba(34,34,34,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(34,34,34,1) 0%,rgba(68,68,68,1) 25%,rgba(85,85,85,1) 50%,rgba(68,68,68,1) 75%,rgba(34,34,34,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(34,34,34,1) 0%,rgba(68,68,68,1) 25%,rgba(85,85,85,1) 50%,rgba(68,68,68,1) 75%,rgba(34,34,34,1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(34,34,34,1) 0%,rgba(68,68,68,1) 25%,rgba(85,85,85,1) 50%,rgba(68,68,68,1) 75%,rgba(34,34,34,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#222222', endColorstr='#222222',GradientType=0 ); /* IE6-9 */
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper .agent_header{
border-radius: 0px 0px 2px 2px;
font-weight: bold;
color: #f4f4f4;
text-shadow: 1px 1px 0px #555;
background: #625B5B -moz-linear-gradient(center top , #3C3C3C, #444) repeat scroll 0% 0%;
background-color: #625B5B;
background-image: -moz-linear-gradient(center top , #3C3C3C, #444);
background-repeat: repeat;
background-attachment: scroll;
background-position: 0% 0%;
background-clip: border-box;
background-origin: padding-box;
background-size: auto auto;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#625B5B', endColorstr='#625BFF', GradientType=0);
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper .row_data {
padding: 5px 5px 0;
line-height: 27px;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper .data_title {
width: 90px;
display: inline-block;
text-align: left;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper .data_value {
width: 107px;
display: inline-block;
text-align: right;
font-size: 16px;
font-weight: bold;
color: #FFF;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper .call {
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper .call .data_title {
width: 157px;
font-weight: bold;
overflow: hidden;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper .call .icon {
cursor: pointer;
display: block;
float: right;
}
/* Color change based on agent's status */
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.handling{
border: 1px solid #62c462;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.handling .agent_header{
background: #62c462;
background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
background-image: -moz-linear-gradient(top, #62c462, #57a957);
background-image: -ms-linear-gradient(top, #62c462, #57a957);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
background-image: -webkit-linear-gradient(top, #62c462, #57a957);
background-image: -o-linear-gradient(top, #62c462, #57a957);
background-image: linear-gradient(top, #62c462, #57a957);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.handling .row_data.call_time .data_value{
color: #62c462;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.connecting{
border: 1px solid #3366cc;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.connecting .agent_header{
background: #3366cc;
background-image: -khtml-gradient(linear, left top, left bottom, from(#3366cc), to(#3333cc));
background-image: -moz-linear-gradient(top, #3366cc, #3333cc);
background-image: -ms-linear-gradient(top, #3366cc, #3333cc);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #3366cc), color-stop(100%, #3333cc));
background-image: -webkit-linear-gradient(top, #3366cc, #3333cc);
background-image: -o-linear-gradient(top, #3366cc, #3333cc);
background-image: linear-gradient(top, #3366cc, #3333cc);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3366cc', endColorstr='#3333cc', GradientType=0);
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.connecting .row_data.call_time .data_value{
color: #3366cc;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.ready {
border: 1px solid #05addc;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.ready .agent_header {
background: #05addc;
background-image: -khtml-gradient(linear, left top, left bottom, from(#05addc), to(#049cdb));
background-image: -moz-linear-gradient(top, #05addc, #049cdb);
background-image: -ms-linear-gradient(top, #05addc, #049cdb);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #05addc), color-stop(100%, #049cdb));
background-image: -webkit-linear-gradient(top, #05addc, #049cdb);
background-image: -o-linear-gradient(top, #05addc, #049cdb);
background-image: linear-gradient(top, #05addc, #049cdb);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#05addc', endColorstr='#049cdb', GradientType=0);
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.ready .row_data.call_time .data_value{
color: #05addc;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.paused{
border: 1px solid #ff7733;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.paused .agent_header{
background: #ff7733;
background-image: -khtml-gradient(linear, left top, left bottom, from(#ff7733), to(#FF5533));
background-image: -moz-linear-gradient(top, #ff7733, #FF5533);
background-image: -ms-linear-gradient(top, #ff7733, #FF5533);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ff7733), color-stop(100%, #FF5533));
background-image: -webkit-linear-gradient(top, #ff7733, #FF5533);
background-image: -o-linear-gradient(top, #ff7733, #FF5533);
background-image: linear-gradient(top, #ff7733, #FF5533);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff7733', endColorstr='#FF5533', GradientType=0);
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.paused .row_data.call_time .data_value{
color: #ff7733;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.busy {
border: 1px solid #ffbb33;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.busy .agent_header {
background: #ffbb33;
background-image: -khtml-gradient(linear, left top, left bottom, from(#ffbb33), to(#FF9933));
background-image: -moz-linear-gradient(top, #ffbb33, #FF9933);
background-image: -ms-linear-gradient(top, #ffbb33, #FF9933);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffbb33), color-stop(100%, #FF9933));
background-image: -webkit-linear-gradient(top, #ffbb33, #FF9933);
background-image: -o-linear-gradient(top, #ffbb33, #FF9933);
background-image: linear-gradient(top, #ffbb33, #FF9933);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbb33', endColorstr='#FF9933', GradientType=0);
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.busy .row_data.call_time .data_value {
color: #ffbb33;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.wrapup {
border: 1px solid #ffbb33;
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.wrapup .agent_header {
background: #ffbb33;
background-image: -khtml-gradient(linear, left top, left bottom, from(#ffbb33), to(#FF9933));
background-image: -moz-linear-gradient(top, #ffbb33, #FF9933);
background-image: -ms-linear-gradient(top, #ffbb33, #FF9933);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffbb33), color-stop(100%, #FF9933));
background-image: -webkit-linear-gradient(top, #ffbb33, #FF9933);
background-image: -o-linear-gradient(top, #ffbb33, #FF9933);
background-image: linear-gradient(top, #ffbb33, #FF9933);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbb33', endColorstr='#FF9933', GradientType=0);
}
#dashboard-content .dashboard-bottom-right #agents-view .agent_wrapper.wrapup .row_data.call_time .data_value{
color: #ffbb33;
}
#dashboard-content .agent_text {
font-weight: bold;
color: #FFF;
}
.timer {
float: right;
}
.list-panel-anchor ul li{
height:27px;
width: 210px;
border-bottom: 1px solid #666666;
list-style-type: none;
background-color:#333333;
}
.list-panel-anchor ul li:first-child{
border-top: none;
width: 210px;
}
.list-panel-anchor ul li:hover, .list-panel-anchor ul li.selected {
background-color: #05addc;
width: 210px;
}
.list-panel-anchor ul li a {
line-height:26px;
display:block;
height: 27px;
padding-left: 35px;
margin-right: 5px;
overflow: hidden;
color: #ffffff;
text-decoration: none;
white-space: nowrap;
/*border-right: 1px solid #7a7a7a;*/
}
/*List Panel*/
.list_panel {
width: 190px;
box-shadow: 2px 2px 2px #222222;
}
.add_flow {
padding-top: 5px;
height: 60px;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #222222;
text-align: center;
cursor: pointer;
background: rgb(90,90,90); /* Old browsers */
background: -moz-linear-gradient(top, rgba(90,90,90,1) 0%, rgba(68,68,68,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(90,90,90,1)), color-stop(100%,rgba(68,68,68,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(90,90,90,1) 0%,rgba(68,68,68,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(90,90,90,1) 0%,rgba(68,68,68,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(90,90,90,1) 0%,rgba(68,68,68,1) 100%); /* IE10+ */
background: linear-gradient(top, rgba(90,90,90,1) 0%,rgba(68,68,68,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#5a5a5a', endColorstr='#444444',GradientType=0 ); /* IE6-9 */
}
.add_flow:hover {
color: #05ADDC;
}
.add_flow:hover .plus_btn {
background-position: 0px 25px;
}
.add_flow span{
display: inline-block;
text-align: center;
text-transform: uppercase;
line-height: 60px;
}
.plus_btn {
background-image: url(../images/plus_btn.png);
width: 25px;
height: 25px;
background-position: 0px 0px;
margin-top: -4px;
margin-right: 7px;
vertical-align: middle;
}
.search_box {
height: 28px;
background-color:#444444;
padding-top: 7px;
border-bottom: 1px solid #222;
}
.search_box .searchsubmit1 {
float: left;
background: url(../images/search_left.png ) no-repeat top left;
height: 20px;
width: 23px;
}
.search_box .searchsubmit2 {
float: left;
background: url(../images/search_right.png ) no-repeat top right;
height: 20px;
width: 26px;
}
.search_box .searchfield {
background: url(../images/search_mid.png) repeat-x;
border: medium none;
float: left;
height: 14px;
width: 130px;
border-radius: 0px;
}
.search_box .searchfield:focus {
border: none;
border-color: transparent;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
/* New design for search button
We keep the old design for some templates (like ring groups, tables etc...) */
.new_search_box {
height: 28px;
background-color:#444444;
padding: 10px 0 8px;
border-bottom: 1px solid #222;
text-align: center;
}
.new_search_box .icon_wrapper {
width: 34px;
height: 26px;
float: left;
border-radius: 0px 5px 5px 0px;
background: rgb(0,0,0); /* Old browsers */
background: -moz-linear-gradient(top, rgba(0,0,0,1) 0%, rgba(34,34,34,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,1)), color-stop(100%,rgba(34,34,34,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* IE10+ */
background: linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#222222',GradientType=0 ); /* IE6-9 */
}
.new_search_box .icon_wrapper .search_icon {
width: 24px;
height: 24px;
padding: 0 5px;
display: block;
background: url(../images/new_search.png) no-repeat center center transparent;
}
.new_search_box .new_searchfield {
width: 141px;
margin-left: 5px;
border: medium none;
color: #fff;
float: left;
border-radius: 5px 0 0 5px;
background: rgb(0,0,0); /* Old browsers */
background: -moz-linear-gradient(top, rgba(0,0,0,1) 0%, rgba(34,34,34,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,1)), color-stop(100%,rgba(34,34,34,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* IE10+ */
background: linear-gradient(top, rgba(0,0,0,1) 0%,rgba(34,34,34,1) 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#222222',GradientType=0 ); /* IE6-9 */
}
.new_search_box .new_searchfield::-webkit-input-placeholder {
color: #888;
font-size: 11px;
}
.new_search_box .new_searchfield:-moz-placeholder {
color: #888;
font-size: 11px;
}
.new_search_box .new_searchfield:focus {
box-shadow: none !important;
border: none;
border-color: transparent;
}
/* End new search field design for list panel */
.list-panel-anchor {
filter:alpha(opacity=80);
-moz-opacity:0.8;
-khtml-opacity: 0.8;
opacity: 0.8;
background: #333;
/*height: 490px;*/
overflow: auto;
outline: none;
}
.list-panel-anchor .jspPane {
left: 0px !important;
}
.list-panel-anchor ul{
background-color:#989898;
}
.list-panel-anchor ul li{
height:27px;
border-bottom: 1px solid #666666;
list-style-type: none;
background-color:#333333;
}
.list-panel-anchor ul li:first-child{
border-top: none;
}
.list-panel-anchor ul li:hover, .list-panel-anchor ul li.selected {
background-color: #05addc;
}
.list-panel-anchor ul li a {
line-height:26px;
display:block;
height: 27px;
padding-left: 35px;
margin-right: 5px;
overflow: hidden;
color: #ffffff;
text-decoration: none;
white-space: nowrap;
/*border-right: 1px solid #7a7a7a;*/
}
.list-panel-anchor ul li .row_arrow a{
display: block;
width: 28px !important;
height: 27px !important;
background-image:url(../images/account_arrow.png) !important;
background-color:#989898;
float: left;
background-position: center center !important;
background-repeat: no-repeat !important;
padding: 0 !important;
border: none !important;
}
.list-panel-anchor ul li .row_arrow a:hover{
background-color: #bebebe !important;
}
.ui-listpanel li a.action { position: absolute; right: 2px; top: 2px; }
.ui-listpanel input.search { height: 14px; padding: 1px; opacity: 0.5; margin: 4px; width: 90%; }

+ 1010
- 0
style/icons.css
File diff suppressed because it is too large
View File


BIN
style/static/images/icons/icons_24x24_blue.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 86 KiB

BIN
style/static/images/icons/icons_24x24_gradient.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 163 KiB

BIN
style/static/images/icons/icons_24x24_red.261.delayed View File

Before After
Width: 1024  |  Height: 768  |  Size: 86 KiB

BIN
style/static/images/icons/icons_24x24_red.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 86 KiB

BIN
style/static/images/icons/icons_32x32_blue.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 107 KiB

BIN
style/static/images/icons/icons_32x32_darkgrey.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 107 KiB

BIN
style/static/images/icons/icons_32x32_gradient.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 207 KiB

BIN
style/static/images/icons/icons_32x32_green.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 107 KiB

BIN
style/static/images/icons/icons_32x32_lightgrey.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 107 KiB

BIN
style/static/images/icons/icons_32x32_red.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 107 KiB

BIN
style/static/images/icons/icons_32x32_white.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 106 KiB

BIN
style/static/images/icons/icons_32x32_yellow.png View File

Before After
Width: 1024  |  Height: 768  |  Size: 107 KiB

+ 94
- 0
views/agents_dashboard.html View File

@ -0,0 +1,94 @@
<div>
{{#if hide_logout}}
<div id="agents-view" class="hide-logout">
{{else}}
<div id="agents-view">
{{/if}}
{{#each agents}}
<div class="agent_wrapper {{status}}" id="{{id}}" data-queues="{{queues}}">
<div class="agent_header">
<span class="icon medium head1"/>
{{first_name}} {{last_name}} ( {{status}} )
</div>
<div class="agent_data">
<div class="row_data call_time">
{{#compare status "===" "paused"}}
<div class="data_title agent_text">{{ ../../i18n.callcenter.break_time }}</div>
<div class="data_value">{{call_time}}</div>
{{/compare}}
{{#compare status "===" 'wrapup'}}
<div class="data_title agent_text">{{ ../../i18n.callcenter.wrapping_up }}</div>
<div class="data_value">{{call_time}}</div>
{{/compare}}
{{#compare status "===" 'handling'}}
<div class="data_title agent_text">{{ ../../i18n.callcenter.call_time }}</div>
<div class="data_value">{{call_time}}</div>
{{/compare}}
{{#compare status "===" 'busy'}}
<div class="data_title agent_text">{{ ../../i18n.callcenter.busy_since }}</div>
<div class="data_value">{{call_time}}</div>
{{/compare}}
{{#compare status "===" 'ready'}}
<div class="data_title agent_text">{{ ../../i18n.callcenter.call_time }}</div>
<div class="data_value">-</div>
{{/compare}}
{{#compare status "===" 'logged_out'}}
<div class="data_title agent_text">{{ ../../i18n.callcenter.call_time }}</div>
<div class="data_value">-</div>
{{/compare}}
{{#compare status "===" 'logged_in'}}
<div class="data_title agent_text">{{ ../../i18n.callcenter.call_time }}</div>
<div class="data_value">-</div>
{{/compare}}
</div>
<div class="row_data call">
{{#compare status "===" 'handling'}}
{{#if current_call}}
<div class="data_title agent_text">{{ ../../../i18n.callcenter.current_call }}</div>
<span data-call_id="{{current_call.call_id}}" class="icon tech_support eavesdrop"/>
{{else}}
<div class="data_title agent_text">{{ ../../../i18n.callcenter.no_active_call }}</div>
{{/if}}
{{/compare}}
{{#compare status "===" 'connecting'}}
{{#if current_call}}
<div class="data_title agent_text">{{ ../../../i18n.callcenter.current_call }}</div>
{{else}}
<div class="data_title agent_text">{{ ../../../i18n.callcenter.no_active_call }}</div>
{{/if}}
{{/compare}}
{{#compare status "!==" 'connecting' }}
{{#compare status "!==" 'handling'}}
<div class="data_title agent_text">{{ ../../../i18n.callcenter.no_active_call }}</div>
{{/compare}}
{{/compare}}
</div>
<div class="all_data">
<div class="row_data call_hours">
<div class="data_title agent_text">{{ ../i18n.callcenter.total_calls }}</div>
<div class="data_value">{{total_calls}}</div>
</div>
<div class="row_data call_day">
<div class="data_title agent_text">{{ ../i18n.callcenter.missed_calls }}</div>
<div class="data_value">{{missed_calls}}</div>
</div>
</div>
<div class="queue_data" style="display: none;">
{{#each queues_list}}
<div class="queue_stat" data-id="{{id}}">
<div class="row_data call_hours">
<div class="data_title agent_text">{{ ../../i18n.callcenter.total_calls }}</div>
<div class="data_value">{{total_calls}}</div>
</div>
<div class="row_data call_day">
<div class="data_title agent_text">{{ ../../i18n.callcenter.missed_calls }}</div>
<div class="data_value">{{missed_calls}}</div>
</div>
</div>
{{/each}}
</div>
</div>
</div>
{{/each}}
</div>
</div>

+ 14
- 0
views/calls_dashboard.html View File

@ -0,0 +1,14 @@
<div>
{{#each waits}}
<li title="{{status}}" class="call-waiting list-element" style="display: block;" data-call_id="{{call_id}}" data-queue_id="{{queue_id}}">
<a href="#" data-module="activate" data-action="media">{{friendly_title}}</a>
<span class="timer">{{friendly_duration}}</span>
</li>
{{/each}}
{{#each progress}}
<li title="{{status}}" class="call-waiting list-element" style="display: block;" data-call_id="{{call_id}}" data-queue_id="{{queue_id}}">
<a href="#" data-module="activate" data-action="media">{{friendly_title}}</a>
<span class="timer">{{friendly_duration}}</span>
</li>
{{/each}}
</div>

+ 15
- 0
views/dashboard.html View File

@ -0,0 +1,15 @@
<div>
<div id="dashboard-content" class="clearfix page">
<div id="dashboard-topbar">
<div class="topbar-right">
</div>
</div>
<div id="callwaiting-list" class="sidebar list_panel"></div>
<div class="dashboard-bottom-right">
<div class="content">
<div id="dashboard-view">
</div>
</div>
</div>
</div>
</div>

+ 41
- 0
views/queues_dashboard.html View File

@ -0,0 +1,41 @@
<div>
<div class="list_queues">
<ul class="list_queues_inner">
{{#each queues}}
<li id="{{id}}" data-current_calls="{{current_calls}}" data-total_calls="{{total_calls}}">
<div class="box_title">
<span class="icon eavesdrop_queue medium tech_support" style="display: none;" rel="popover"></span>
{{name}}
<span class="icon edit_queue medium wrench_screw" style="display: none;" rel="popover" data-content="{{clicking_here_will_send_you}}"></span>
</div>
<div class="grid_bottom">
<div class="first_row">
<div class="box calls" title="{{ ../i18n.callcenter.missed_calls }}">
<div class="icon_wrapper"><span class="icon medium active_phone"></span></div>
<div class="stat" title="{{ ../i18n.callcenter.busy }}">
<span class="blue">{{current_calls}}</span> / {{total_calls}}
</div>
</div>
<div class="box users" title="{{ ../i18n.callcenter.missed_calls }}">
<div class="icon_wrapper"><span class="icon medium user"></span></div>
<div class="stat">
<span class="blue">{{current_agents}}</span> / {{max_agents}}
</div>
</div>
</div>
<div class="second_row">
<div class="box dropped_calls" title="{{ ../i18n.callcenter.missed_calls }}">
<div class="icon_wrapper"><span class="icon medium thumb_down"></span></div>
<div class="red">{{abandoned_calls}}</div>
</div>
<div class="box hold_time" title="{{ ../i18n.callcenter.missed_calls }}">
<div class="icon_wrapper"><span class="icon medium hand"></div>
<div class="orange">{{average_hold_time}}</div>
</div>
</div>
</div>
</li>
{{/each}}
</ul>
</div>
</div>

Loading…
Cancel
Save