Improved shown caller log.

This commit is contained in:
Martin Edenhofer 2016-04-29 10:23:12 +02:00
parent bd06f59fbf
commit 882beff8fa
9 changed files with 175 additions and 33 deletions

View file

@ -41,7 +41,10 @@ class App.CTI extends App.Controller
App.Event.bind( App.Event.bind(
'cti_list_push' 'cti_list_push'
(data) => (data) =>
@list = data if data.assets
App.Collection.loadAssets(data.assets)
if data.list
@list = data.list
@render() @render()
'cti_list_push' 'cti_list_push'
) )
@ -64,7 +67,10 @@ class App.CTI extends App.Controller
type: 'GET' type: 'GET'
url: "#{@apiPath}/cti/log" url: "#{@apiPath}/cti/log"
success: (data) => success: (data) =>
@list = data if data.assets
App.Collection.loadAssets(data.assets)
if data.list
@list = data.list
@render() @render()
) )
@ -133,7 +139,7 @@ class App.CTI extends App.Controller
@html App.view('cti/index')( @html App.view('cti/index')(
list: @list list: @list
) )
@userPopups()
@updateNavMenu() @updateNavMenu()
done: (e) => done: (e) =>

View file

@ -8,17 +8,57 @@
<th style="width: 28px;"></th> <th style="width: 28px;"></th>
<th><%- @T('From') %></th> <th><%- @T('From') %></th>
<th><%- @T('To') %></th> <th><%- @T('To') %></th>
<th style="width: 200px;"></th> <th style="width: 130px;"></th>
<th style="width: 100px;"><%- @T('Duration') %></th> <th style="width: 100px;"><%- @T('Duration') %></th>
<th><%- @T('Time') %></th> <th style="width: 170px;"><%- @T('Time') %></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% for item in @list: %> <% for item in @list: %>
<tr <% if item.state is 'hangup' && item.done: %>class="is-inactive"<% end %> data-id="<%- item.id %>"> <tr <% if item.state is 'hangup' && item.done: %>class="is-inactive"<% end %> data-id="<%- item.id %>">
<td><% if item.state is 'hangup': %><input type="checkbox" class="js-check" <% if item.done: %>checked<% end %>><% end %> <td><% if item.state is 'hangup': %><input type="checkbox" class="js-check" <% if item.done: %>checked<% end %>><% end %>
<td><% if item.from_comment: %><%= item.from_comment %><br><% end %><%= item.from %></td> <td>
<td><% if item.to_comment: %><%= item.to_comment %><br><% end %><%= item.to %></td> <% shown = false %>
<% if item.preferences.from && !_.isEmpty(item.preferences.from): %>
<% for caller_id in item.preferences.from: %>
<% if caller_id.user_id && App.User.exists(caller_id.user_id): %>
<% shown = true %>
<% user = App.User.find(caller_id.user_id) %>
<% if caller_id.level isnt 'known': %><%- @T('maybe') %> <% end %>
<span class="user-popover" data-id="<%- user.id %>"><%= user.displayNameLong() %></span><br>
<% else if caller_id.comment: %>
<% shown = true %>
<%- @T('maybe') %> <%= caller_id.comment %><br>
<% end %>
<% end %>
<% end %>
<% if !shown: %>
<% if item.from_comment: %><%= item.from_comment %><% end %>
<br>
<% end %>
<%= item.from %>
</td>
<td>
<% shown = false %>
<% if item.preferences.to && !_.isEmpty(item.preferences.to): %>
<% for caller_id in item.preferences.to: %>
<% if caller_id.user_id && App.User.exists(caller_id.user_id): %>
<% shown = true %>
<% user = App.User.find(caller_id.user_id) %>
<% if caller_id.level isnt 'known': %><%- @T('maybe') %> <% end %>
<span class="user-popover" data-id="<%- user.id %>"><%= user.displayNameLong() %></span><br>
<% else if caller_id.comment: %>
<% shown = true %>
<%- @T('maybe') %> <%= caller_id.comment %><br>
<% end %>
<% end %>
<% end %>
<% if !shown: %>
<% if item.to_comment: %><%= item.to_comment %><% end %>
<br>
<% end %>
<%= item.to %>
</td>
<td><%- @T(item.state_human) %></td> <td><%- @T(item.state_human) %></td>
<td><%= item.duration %></td> <td><%= item.duration %></td>
<td><%- @humanTime(item.created_at) %></td> <td><%- @humanTime(item.created_at) %></td>

View file

@ -3785,6 +3785,12 @@ footer {
padding-left: 3px; padding-left: 3px;
} }
.user-popover,
.ticket-popover,
.organization-popover {
@extend .u-clickable;
}
.stat-icon { .stat-icon {
position: relative; position: relative;
} }

View file

@ -8,8 +8,7 @@ class Integration::SipgateController < ApplicationController
def index def index
return if !authentication_check return if !authentication_check
return if deny_if_not_role('CTI') return if deny_if_not_role('CTI')
list = Cti::Log.order('created_at DESC, id DESC').limit(60) render json: Cti::Log.log
render json: list
end end
# set caller log to done # set caller log to done
@ -128,13 +127,15 @@ class Integration::SipgateController < ApplicationController
end end
from_comment = nil from_comment = nil
to_comment = nil to_comment = nil
preferences = nil
if params['direction'] == 'in' if params['direction'] == 'in'
to_comment = user to_comment = user
from_comment = update_log_item('from') from_comment, preferences = update_log_item('from')
else else
from_comment = user from_comment = user
to_comment = update_log_item('to') to_comment, preferences = update_log_item('to')
end end
comment = nil comment = nil
if params['cause'] if params['cause']
comment = params['cause'] comment = params['cause']
@ -150,6 +151,7 @@ class Integration::SipgateController < ApplicationController
call_id: params['callId'], call_id: params['callId'],
comment: comment, comment: comment,
state: params['event'], state: params['event'],
preferences: preferences,
) )
elsif params['event'] == 'answer' elsif params['event'] == 'answer'
log = Cti::Log.find_by(call_id: params['callId']) log = Cti::Log.find_by(call_id: params['callId'])
@ -183,8 +185,17 @@ class Integration::SipgateController < ApplicationController
def update_log_item(direction) def update_log_item(direction)
from_comment_known = '' from_comment_known = ''
from_comment_maybe = '' from_comment_maybe = ''
preferences_known = {}
preferences_known[direction] = []
preferences_maybe = {}
preferences_maybe[direction] = []
caller_ids = Cti::CallerId.lookup(params[direction]) caller_ids = Cti::CallerId.lookup(params[direction])
caller_ids.each {|record| caller_ids.each {|record|
if record.level == 'known'
preferences_known[direction].push record
else
preferences_maybe[direction].push record
end
comment = '' comment = ''
if record.user_id if record.user_id
user = User.lookup(id: record.user_id) user = User.lookup(id: record.user_id)
@ -206,8 +217,8 @@ class Integration::SipgateController < ApplicationController
from_comment_maybe += comment from_comment_maybe += comment
end end
} }
return from_comment_known if !from_comment_known.empty? return [from_comment_known, preferences_known] if !from_comment_known.empty?
return "maybe #{from_comment_maybe}" if !from_comment_maybe.empty? return ["maybe #{from_comment_maybe}", preferences_maybe] if !from_comment_maybe.empty?
nil nil
end end

View file

@ -45,9 +45,16 @@ returns
=end =end
def self.lookup(caller_id) def self.lookup(caller_id)
Cti::CallerId.where( result = Cti::CallerId.where(
caller_id: caller_id, caller_id: caller_id,
).order('id DESC') ).order('id DESC').limit(20)
# in case do lookups in external databases
if result.empty?
# ...
end
result
end end
=begin =begin
@ -124,6 +131,7 @@ returns
=end =end
def self.rebuild def self.rebuild
Cti::CallerId.delete_all
map = config map = config
map.each {|item| map.each {|item|
level = item[:level] level = item[:level]

View file

@ -2,6 +2,8 @@ module Cti
class Log < ApplicationModel class Log < ApplicationModel
self.table_name = 'cti_logs' self.table_name = 'cti_logs'
store :preferences
after_create :push_event, :push_caller_list after_create :push_event, :push_caller_list
after_update :push_event, :push_caller_list after_update :push_event, :push_caller_list
after_destroy :push_event, :push_caller_list after_destroy :push_event, :push_caller_list
@ -43,6 +45,43 @@ module Cti
=end =end
=begin
Cti::Log.log
returns
{
list: [...]
assets: {...}
}
=end
def self.log
list = Cti::Log.order('created_at DESC, id DESC').limit(60)
# add assets
assets = {}
list.each {|item|
next if !item.preferences
%w(from to).each {|direction|
next if !item.preferences[direction]
item.preferences[direction].each {|caller_id|
next if !caller_id['user_id']
user = User.lookup(id: caller_id['user_id'])
next if !user
assets = user.assets(assets)
}
}
}
{
list: list,
assets: assets,
}
end
def push_event def push_event
users = User.of_role('CTI') users = User.of_role('CTI')
users.each {|user| users.each {|user|
@ -59,7 +98,7 @@ module Cti
end end
def push_caller_list def push_caller_list
list = Cti::Log.order('created_at DESC').limit(60) list = Cti::Log.log
users = User.of_role('CTI') users = User.of_role('CTI')
users.each {|user| users.each {|user|

View file

@ -0,0 +1,14 @@
class UpdateCtiCallerId < ActiveRecord::Migration
def up
Setting.create_if_not_exists(
title: 'Define transaction backend.',
name: '9100_cti_caller_id_detection',
area: 'Transaction::Backend',
description: 'Define the transaction backend which detects caller ids in objects and store them for cti lookups.',
options: {},
state: 'Transaction::CtiCallerIdDetection',
frontend: false
)
add_column :cti_logs, :preferences, :text, limit: 500.kilobytes + 1, null: true
end
end

View file

@ -1906,6 +1906,15 @@ Setting.create_if_not_exists(
state: 'Transaction::ClearbitEnrichment', state: 'Transaction::ClearbitEnrichment',
frontend: false frontend: false
) )
Setting.create_if_not_exists(
title: 'Define transaction backend.',
name: '9100_cti_caller_id_detection',
area: 'Transaction::Backend',
description: 'Define the transaction backend which detects caller ids in objects and store them for cti lookups.',
options: {},
state: 'Transaction::CtiCallerIdDetection',
frontend: false
)
signature = Signature.create_if_not_exists( signature = Signature.create_if_not_exists(
id: 1, id: 1,

View file

@ -457,6 +457,8 @@ class SipgateControllerTest < ActionDispatch::IntegrationTest
assert_equal('in', log.direction) assert_equal('in', log.direction)
assert_equal('user 1,user 2', log.to_comment) assert_equal('user 1,user 2', log.to_comment)
assert_equal('CallerId Customer3,CallerId Customer2', log.from_comment) assert_equal('CallerId Customer3,CallerId Customer2', log.from_comment)
assert_not(log.preferences['to'])
assert(log.preferences['from'])
assert_equal(nil, log.comment) assert_equal(nil, log.comment)
assert_equal('newCall', log.state) assert_equal('newCall', log.state)
assert_equal(true, log.done) assert_equal(true, log.done)
@ -465,26 +467,33 @@ class SipgateControllerTest < ActionDispatch::IntegrationTest
get '/api/v1/cti/log' get '/api/v1/cti/log'
assert_response(401) assert_response(401)
customer2 = User.lookup(login: 'ticket-caller_id_sipgate-customer2@example.com')
customer3 = User.lookup(login: 'ticket-caller_id_sipgate-customer3@example.com')
headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' } headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
credentials = ActionController::HttpAuthentication::Basic.encode_credentials('cti-agent@example.com', 'agentpw') credentials = ActionController::HttpAuthentication::Basic.encode_credentials('cti-agent@example.com', 'agentpw')
get '/api/v1/cti/log', {}, headers.merge('Authorization' => credentials) get '/api/v1/cti/log', {}, headers.merge('Authorization' => credentials)
assert_response(200) assert_response(200)
result = JSON.parse(@response.body) result = JSON.parse(@response.body)
assert_equal(result.class, Array) assert_equal(result['list'].class, Array)
assert_equal(6, result.count) assert_equal(6, result['list'].count)
assert_equal('1234567890-6', result[0]['call_id']) assert(result['assets'])
assert_equal('1234567890-5', result[1]['call_id']) assert(result['assets']['User'])
assert_equal('1234567890-4', result[2]['call_id']) assert(result['assets']['User'][customer2.id.to_s])
assert_equal('1234567890-3', result[3]['call_id']) assert(result['assets']['User'][customer3.id.to_s])
assert_equal('1234567890-2', result[4]['call_id']) assert_equal('1234567890-6', result['list'][0]['call_id'])
assert_equal('hangup', result[4]['state']) assert_equal('1234567890-5', result['list'][1]['call_id'])
assert_equal('4930777000000', result[4]['from']) assert_equal('1234567890-4', result['list'][2]['call_id'])
assert_equal('user 1', result[4]['from_comment']) assert_equal('1234567890-3', result['list'][3]['call_id'])
assert_equal('4912347114711', result[4]['to']) assert_equal('1234567890-2', result['list'][4]['call_id'])
assert_equal('CallerId Customer1', result[4]['to_comment']) assert_equal('hangup', result['list'][4]['state'])
assert_equal('normalClearing', result[4]['comment']) assert_equal('4930777000000', result['list'][4]['from'])
assert_equal('hangup', result[4]['state']) assert_equal('user 1', result['list'][4]['from_comment'])
assert_equal('1234567890-1', result[5]['call_id']) assert_equal('4912347114711', result['list'][4]['to'])
assert_equal('CallerId Customer1', result['list'][4]['to_comment'])
assert_equal('normalClearing', result['list'][4]['comment'])
assert_equal('hangup', result['list'][4]['state'])
assert_equal('1234567890-1', result['list'][5]['call_id'])
end end