Skip to content

Commit

Permalink
Added set of auto offline if agent is not answering chats for 120 sec…
Browse files Browse the repository at this point in the history
…onds.
  • Loading branch information
martini committed Jan 6, 2016
1 parent 4803fa9 commit f5fa05b
Show file tree
Hide file tree
Showing 12 changed files with 143 additions and 40 deletions.
26 changes: 23 additions & 3 deletions app/assets/javascripts/app/controllers/chat.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class App.CustomerChat extends App.Controller
@maxChatWindows = parseInt(preferences.chat.max_windows)

@pushStateIntervalOn = undefined
@idleTimeout = parseInt(@Config.get('chat_agent_idle_timeout') || 120)
@messageCounter = 0
@meta =
active: false
Expand Down Expand Up @@ -107,10 +108,10 @@ class App.CustomerChat extends App.Controller

@el.find('.js-waitingCustomers').popover(
trigger: 'hover'
container: 'body'
html: true
animation: false
delay: 100
placement: 'bottom'
title: ->
App.i18n.translateContent('Waiting Customers')
content: =>
Expand All @@ -119,10 +120,10 @@ class App.CustomerChat extends App.Controller

@el.find('.js-chattingCustomers').popover(
trigger: 'hover'
container: 'body'
html: true
animation: false
delay: 100
placement: 'bottom'
title: ->
App.i18n.translateContent('Chatting Customers')
content: =>
Expand All @@ -131,10 +132,10 @@ class App.CustomerChat extends App.Controller

@el.find('.js-activeAgents').popover(
trigger: 'hover'
container: 'body'
html: true
animation: false
delay: 100
placement: 'bottom'
title: ->
App.i18n.translateContent('Active Agents')
content: =>
Expand Down Expand Up @@ -225,8 +226,11 @@ class App.CustomerChat extends App.Controller
updateMeta: =>
if @meta.waiting_chat_count && @maxChatWindows > @windowCount()
@$('.js-acceptChat').addClass('is-clickable is-blinking')
@idleTimeoutStart()
else
@$('.js-acceptChat').removeClass('is-clickable is-blinking')
@idleTimeoutStop()

@$('.js-badgeWaitingCustomers').text(@meta.waiting_chat_count)
@$('.js-badgeChattingCustomers').text(@meta.running_chat_count)
@$('.js-badgeActiveAgents').text(@meta.active_agent_count)
Expand Down Expand Up @@ -271,13 +275,29 @@ class App.CustomerChat extends App.Controller
acceptChat: =>
return if @windowCount() >= @maxChatWindows
App.WebSocket.send(event:'chat_session_start')
@idleTimeoutStop()

settings: (errors = {}) ->
new Setting(
windowSpace: @
errors: errors
)

idleTimeoutStart: =>
return if @idleTimeoutId
switchOff = =>
@switch(false)
@notify(
type: 'notice'
msg: App.i18n.translateContent('Chat not answered, set to offline automatically.')
)
@idleTimeoutId = @delay(switchOff, @idleTimeout * 1000)

idleTimeoutStop: =>
return if !@idleTimeoutId
@clearDelay(@idleTimeoutId)
@idleTimeoutId = undefined

class CustomerChatRouter extends App.ControllerPermanent
constructor: (params) ->
super
Expand Down
51 changes: 51 additions & 0 deletions app/models/chat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,57 @@ def self.seads_available(diff = 2.minutes)

=begin
broadcast new agent status to all agents
Chat.broadcast_agent_state_update
optional you can ignore it for dedecated user
Chat.broadcast_agent_state_update(ignore_user_id)
=end

def self.broadcast_agent_state_update(ignore_user_id = nil)

# send broadcast to agents
Chat::Agent.where('active = ? OR updated_at > ?', true, Time.zone.now - 15.minutes).each {|item|
next if item.updated_by_id == ignore_user_id
data = {
event: 'chat_status_agent',
data: Chat.agent_state(item.updated_by_id),
}
Sessions.send_to(item.updated_by_id, data)
}
end

=begin
broadcast new customer queue position to all waiting customers
Chat.broadcast_customer_state_update
=end

def self.broadcast_customer_state_update

# send position update to other waiting sessions
position = 0
Chat::Session.where(state: 'waiting').order('created_at ASC').each {|local_chat_session|
position += 1
data = {
event: 'chat_session_queue',
data: {
state: 'queue',
position: position,
session_id: local_chat_session.session_id,
},
}
local_chat_session.send_to_recipients(data)
}
end

=begin
cleanup old chat messages
Chat.cleanup
Expand Down
1 change: 1 addition & 0 deletions app/models/observer/chat/leave/background_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def perform
}
chat_session.send_to_recipients(message, @client_id)

Chat.broadcast_agent_state_update
end

end
25 changes: 25 additions & 0 deletions db/migrate/20160106000001_update_chat5.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class UpdateChat5 < ActiveRecord::Migration
def change

Setting.create_if_not_exists(
title: 'Agent idle timeout',
name: 'chat_agent_idle_timeout',
area: 'Chat::Extended',
description: 'Idle timeout in seconds till agent is set offline automatically.',
options: {
form: [
{
display: '',
null: false,
name: 'chat_agent_idle_timeout',
tag: 'input',
},
],
},
preferences: {},
state: '120',
frontend: true
)

end
end
20 changes: 20 additions & 0 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,26 @@
frontend: true
)

Setting.create_if_not_exists(
title: 'Agent idle timeout',
name: 'chat_agent_idle_timeout',
area: 'Chat::Extended',
description: 'Idle timeout in seconds till agent is set offline automatically.',
options: {
form: [
{
display: '',
null: false,
name: 'chat_agent_idle_timeout',
tag: 'input',
},
],
},
preferences: {},
state: '120',
frontend: true
)

Setting.create_if_not_exists(
title: 'Define searchable models.',
name: 'models_searchable',
Expand Down
2 changes: 1 addition & 1 deletion lib/sessions/event/chat_agent_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def run
Chat::Agent.state(@session['id'], @payload['data']['active'])

# broadcast new state to agents
broadcast_agent_state_update(@session['id'])
Chat.broadcast_agent_state_update(@session['id'])

{
event: 'chat_agent_state',
Expand Down
31 changes: 0 additions & 31 deletions lib/sessions/event/chat_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,6 @@ def run
}
end

def broadcast_agent_state_update(ignore_user_id = nil)

# send broadcast to agents
Chat::Agent.where(active: true).each {|item|
next if item.updated_by_id == ignore_user_id
data = {
event: 'chat_status_agent',
data: Chat.agent_state(item.updated_by_id),
}
Sessions.send_to(item.updated_by_id, data)
}
end

def broadcast_customer_state_update

# send position update to other waiting sessions
position = 0
Chat::Session.where(state: 'waiting').order('created_at ASC').each {|local_chat_session|
position += 1
data = {
event: 'chat_session_queue',
data: {
state: 'queue',
position: position,
session_id: local_chat_session.session_id,
},
}
local_chat_session.send_to_recipients(data)
}
end

def agent_permission_check
if !@session
error = {
Expand Down
4 changes: 2 additions & 2 deletions lib/sessions/event/chat_session_close.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def run
chat_session.save

# set state update to all agents
broadcast_agent_state_update
Chat.broadcast_agent_state_update

# send position update to other waiting sessions
broadcast_customer_state_update
Chat.broadcast_customer_state_update

# notify about "leaving"
else
Expand Down
2 changes: 1 addition & 1 deletion lib/sessions/event/chat_session_init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def run
)

# send broadcast to agents
broadcast_agent_state_update
Chat.broadcast_agent_state_update

# return new session
{
Expand Down
4 changes: 2 additions & 2 deletions lib/sessions/event/chat_session_start.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ def run
Sessions.send(@client_id, data)

# send state update with sessions to agents
broadcast_agent_state_update
Chat.broadcast_agent_state_update

# send position update to other waiting sessions
broadcast_customer_state_update
Chat.broadcast_customer_state_update

nil
end
Expand Down
1 change: 1 addition & 0 deletions script/build/test_startup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export ZAMMAD_SETTING_TTL=15
rails r "Setting.set('developer_mode', true)"
rails r "Setting.set('websocket_port', '$WS_PORT')"
rails r "Setting.set('fqdn', '$IP:$BROWSER_PORT')"
rails r "Setting.set('chat_agent_idle_timeout', '45')"

pumactl start --pidfile tmp/pids/puma.pid -d -p $APP_PORT -e $RAILS_ENV
script/websocket-server.rb start -d -p $WS_PORT
Expand Down
16 changes: 16 additions & 0 deletions test/browser/chat_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,11 @@ def test_timeouts
)
agent.find_elements( { css: '.active .chat-window .js-close' } ).each(&:click)

exists(
browser: agent,
css: '#navigation .js-switch input[checked]'
)

# no customer action, hide widget
customer = browser_instance
location(
Expand Down Expand Up @@ -618,6 +623,17 @@ def test_timeouts
timeout: 120,
)

# check if agent is offline, idle timeout, chat not answered
exists_not(
browser: agent,
css: '#navigation .js-switch input[checked]'
)
switch(
browser: agent,
css: '#navigation .js-switch',
type: 'on',
)

# no customer action, show sorry screen
reload(
browser: customer,
Expand Down

0 comments on commit f5fa05b

Please sign in to comment.