Skip to content

Commit

Permalink
Implemented feature to transfer chat sessions to another chat topic.
Browse files Browse the repository at this point in the history
  • Loading branch information
zammad-sync committed Dec 3, 2019
1 parent 3c788ca commit 133b570
Show file tree
Hide file tree
Showing 15 changed files with 491 additions and 160 deletions.
186 changes: 120 additions & 66 deletions app/assets/javascripts/app/controllers/chat.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ class App.CustomerChat extends App.Controller
'click .js-settings': 'settings'

elements:
'.js-acceptChat': 'acceptChatElement'
'.js-badgeWaitingCustomers': 'badgeWaitingCustomers'
'.js-acceptChat': 'acceptChatElement'
'.js-badgeWaitingCustomers': 'badgeWaitingCustomers'
'.js-totalInfo': 'totalInfo'
'.js-badgeChattingCustomers': 'badgeChattingCustomers'
'.js-badgeActiveAgents': 'badgeActiveAgents'
'.chat-workspace': 'workspace'
'.js-badgeActiveAgents': 'badgeActiveAgents'
'.chat-workspace': 'workspace'

sounds:
chat_new: new Audio('assets/sounds/chat_new.mp3')
Expand All @@ -28,7 +29,9 @@ class App.CustomerChat extends App.Controller
@meta =
active: false
waiting_chat_count: 0
waiting_chat_count_by_chat: {}
waiting_chat_session_list: []
waiting_chat_session_list_by_chat: {}
running_chat_count: 0
running_chat_session_list: []
active_agent_count: 0
Expand Down Expand Up @@ -99,65 +102,23 @@ class App.CustomerChat extends App.Controller

@html App.view('customer_chat/index')()

chatSessionList = (list) ->
for chat_session in list
chat = App.Chat.find(chat_session.chat_id)
chat_session.name = "#{chat.displayName()} [##{chat_session.id}]"
chat_session.geo_data = ''
if chat_session.preferences && chat_session.preferences.geo_ip
if chat_session.preferences.geo_ip.country_name
chat_session.geo_data += chat_session.preferences.geo_ip.country_name
if chat_session.preferences.geo_ip.city_name
chat_session.geo_data += " #{chat_session.preferences.geo_ip.city_name}"
if chat_session.user_id
chat_session.user = App.User.find(chat_session.user_id)
App.view('customer_chat/chat_list')(
chat_sessions: list
)

@el.find('.js-waitingCustomers .js-info').popover(
trigger: 'hover'
html: true
animation: false
delay: 0
placement: 'bottom'
container: 'body' # place in body do prevent it from animating
title: ->
App.i18n.translateContent('Waiting Customers')
content: =>
chatSessionList(@meta.waiting_chat_session_list)
)

@el.find('.js-chattingCustomers .js-info').popover(
trigger: 'hover'
html: true
animation: false
delay: 0
placement: 'bottom'
container: 'body'
title: ->
App.i18n.translateContent('Chatting Customers')
content: =>
chatSessionList(@meta.running_chat_session_list)
chatSessionList: (list) ->
list = [] if !list
for chat_session in list
chat = App.Chat.find(chat_session.chat_id)
chat_session.name = "#{chat.displayName()} [##{chat_session.id}]"
chat_session.geo_data = ''
if chat_session.preferences && chat_session.preferences.geo_ip
if chat_session.preferences.geo_ip.country_name
chat_session.geo_data += chat_session.preferences.geo_ip.country_name
if chat_session.preferences.geo_ip.city_name
chat_session.geo_data += " #{chat_session.preferences.geo_ip.city_name}"
if chat_session.user_id
chat_session.user = App.User.find(chat_session.user_id)
App.view('customer_chat/chat_list')(
chat_sessions: list
)

@el.find('.js-activeAgents .js-info').popover(
trigger: 'hover'
html: true
animation: false
delay: 0
placement: 'bottom'
container: 'body'
title: ->
App.i18n.translateContent('Active Agents')
content: =>
users = []
for user_id in @meta.active_agent_ids
users.push App.User.find(user_id)
App.view('customer_chat/user_list')(
users: users
)
)

show: (params) =>
@title 'Customer Chat', true
Expand Down Expand Up @@ -248,15 +209,68 @@ class App.CustomerChat extends App.Controller
@stopPushState()
@pushState()

activeChatTopcis: =>
preferences = @Session.get('preferences')
return [] if !preferences
return [] if !preferences.chat
return [] if !preferences.chat.active
chats = []
for chat in App.Chat.all()
if preferences.chat.active[chat.id] is 'on' || preferences.chat.active[chat.id.toString()] is 'on'
chats.push chat
chats

updateMeta: =>
$('.popover').remove()
activeChatTopcis = @activeChatTopcis()
@$('.js-header').html(App.view('customer_chat/chat_header')(chats: activeChatTopcis))
@refreshElements()
if @meta.waiting_chat_count && @maxChatWindows > @windowCount()
@acceptChatElement.addClass('is-clickable is-blinking')

# activate normal button
@acceptChatElement.not('[data-chat-id]').addClass('is-active pulsate-animation')

# activate specific chat buttons
if activeChatTopcis.length > 1
for chat in activeChatTopcis
if @meta.waiting_chat_count_by_chat[chat.id]
@$(".js-header .js-acceptChat[data-chat-id=#{chat.id}]").addClass('is-active pulsate-animation').attr('disabled', false)
@idleTimeoutStart()
else
@acceptChatElement.removeClass('is-clickable is-blinking')
@acceptChatElement.removeClass('is-active pulsate-animation')
@idleTimeoutStop()

@badgeWaitingCustomers.text(@meta.waiting_chat_count)
if activeChatTopcis.length > 1
for chat in App.Chat.all()
do (chat) =>
@$(".js-header .js-waitingCustomers[data-chat-id=#{chat.id}] .js-badgeWaitingCustomers").text(@meta.waiting_chat_count_by_chat[chat.id])
@el.find(".js-waitingCustomers[data-chat-id=#{chat.id}] .js-info").popover(
trigger: 'hover'
html: true
animation: false
delay: 0
placement: 'bottom'
container: 'body' # place in body do prevent it from animating
title: ->
App.i18n.translateContent('Waiting Customers')
content: =>
@chatSessionList(@meta.waiting_chat_session_list_by_chat[chat.id])
)
else
@badgeWaitingCustomers.text(@meta.waiting_chat_count)
@el.find('.js-waitingCustomers .js-totalInfo').popover(
trigger: 'hover'
html: true
animation: false
delay: 0
placement: 'bottom'
container: 'body' # place in body do prevent it from animating
title: ->
App.i18n.translateContent('Waiting Customers')
content: =>
@chatSessionList(@meta.waiting_chat_session_list_by_chat[activeChatTopcis[0].id])
)

@badgeChattingCustomers.text(@meta.running_chat_count)
@badgeActiveAgents.text(@meta.active_agent_count)

Expand All @@ -266,6 +280,37 @@ class App.CustomerChat extends App.Controller
@addChat(session)
@meta.active_sessions = false

@el.find('.js-chattingCustomers .js-info').popover(
trigger: 'hover'
html: true
animation: false
delay: 0
placement: 'bottom'
container: 'body'
title: ->
App.i18n.translateContent('Chatting Customers')
content: =>
@chatSessionList(@meta.running_chat_session_list)
)

@el.find('.js-activeAgents .js-info').popover(
trigger: 'hover'
html: true
animation: false
delay: 0
placement: 'bottom'
container: 'body'
title: ->
App.i18n.translateContent('Active Agents')
content: =>
users = []
for user_id in @meta.active_agent_ids
users.push App.User.find(user_id)
App.view('customer_chat/user_list')(
users: users
)
)

@updateNavMenu()

addChat: (session) ->
Expand Down Expand Up @@ -298,9 +343,10 @@ class App.CustomerChat extends App.Controller
for session_id, chat of @chatWindows
chat.trigger('layout-changed')

acceptChat: =>
acceptChat: (e) =>
return if @windowCount() >= @maxChatWindows
App.WebSocket.send(event:'chat_session_start')
chat_id = $(e.currentTarget).attr('data-chat-id')
App.WebSocket.send(event:'chat_session_start', chat_id: chat_id)
@idleTimeoutStop()

settings: (params = {}) ->
Expand Down Expand Up @@ -344,6 +390,7 @@ class ChatWindow extends App.Controller
'click .js-scrollHint': 'onScrollHintClick'
'click .js-info': 'toggleMeta'
'click .js-createTicket': 'ticketCreate'
'click .js-transferChat': 'transfer'
'submit .js-metaForm': 'sendMetaForm'

elements:
Expand Down Expand Up @@ -450,6 +497,7 @@ class ChatWindow extends App.Controller
@html App.view('customer_chat/chat_window')(
name: @name
session: @session
chats: App.Chat.all()
)

@el.one('transitionend', @onTransitionend)
Expand Down Expand Up @@ -766,6 +814,12 @@ class ChatWindow extends App.Controller
else if showHint
@showScrollHint()

transfer: (e) =>
e.preventDefault()
chat_id = $(e.currentTarget).attr('data-chat-id')
App.WebSocket.send(event:'chat_transfer', chat_id: chat_id, session_id: @session.id)
@close()

ticketCreate: (e) =>
e.preventDefault()

Expand Down
40 changes: 40 additions & 0 deletions app/assets/javascripts/app/views/customer_chat/chat_header.jst.eco
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<div class="status-fields">
<% if @chats.length > 1: %>
<div class="buttonDropdown dropdown">
<div class="status-field status-field--spacer js-acceptChat">
<span class="badge js-badgeWaitingCustomers"></span> <%- @T('Waiting Customers') %>
</div>
<div class="status-field status-field--arrow" data-toggle="dropdown">
<%- @Icon('arrow-down') %>
</div>
<ul class="dropdown-menu" role="menu">
<% for chat in @chats: %>
<li class="js-waitingCustomers js-acceptChat" disabled data-chat-id="<%= chat.id %>" role="menuitem">
<span class="badge js-badgeWaitingCustomers"></span> <%- @T('Waiting in %s', chat.name) %> <span class="flex-spacer"></span>
<div class="status-badge js-info">
<div class="info-badge"><%- @Icon('info') %></div>
</div>
<% end %>
</ul>
</div>
<% else: %>
<div class="status-field js-acceptChat js-waitingCustomers">
<span class="badge js-badgeWaitingCustomers"></span> <%- @T('Waiting Customers') %>
<div class="status-badge js-totalInfo">
<div class="info-badge"><%- @Icon('info') %></div>
</div>
</div>
<% end %>
<div class="status-field js-chattingCustomers">
<span class="badge js-badgeChattingCustomers"></span> <%- @T('Chatting Customers') %>
<div class="status-badge js-info">
<div class="info-badge"><%- @Icon('info') %></div>
</div>
</div>
<div class="status-field js-activeAgents">
<span class="badge js-badgeActiveAgents"></span> <%- @T('Active Agents') %>
<div class="status-badge js-info">
<div class="info-badge"><%- @Icon('info') %></div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
<div class="chat-body js-body"></div>
<div class="chat-body js-meta hidden">
<% if @session: %>
<%- @T('Transfer conversation to another chat:') %>
<ul>
<% for chat in @chats: %>
<% if @session.chat_id isnt chat.id: %>
<li><a data-chat-id="<%= chat.id %>" class="js-transferChat" href="#"><%- chat.name %></a>
<% end %>
<% end %>
</ul>
<hr>
<ul>
<li><%- @T('Created at') %>: <%- @Ttimestamp(@session.created_at) %></li>
<% if @session && @session.preferences: %>
Expand Down
23 changes: 1 addition & 22 deletions app/assets/javascripts/app/views/customer_chat/index.jst.eco
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,7 @@
<div class="page-header-title">
<h1><%- @T('Customer Chat') %></h1>
</div>
<div class="page-header-center">
<div class="status-fields">
<div class="status-field js-acceptChat js-waitingCustomers">
<span class="badge js-badgeWaitingCustomers"></span> <%- @T('Waiting Customers') %>
<div class="status-badge js-info">
<div class="info-badge"><%- @Icon('info') %></div>
</div>
</div>
<div class="status-field js-chattingCustomers">
<span class="badge js-badgeChattingCustomers"></span> <%- @T('Chatting Customers') %>
<div class="status-badge js-info">
<div class="info-badge"><%- @Icon('info') %></div>
</div>
</div>
<div class="status-field js-activeAgents">
<span class="badge js-badgeActiveAgents"></span> <%- @T('Active Agents') %>
<div class="status-badge js-info">
<div class="info-badge"><%- @Icon('info') %></div>
</div>
</div>
</div>
</div>
<div class="page-header-center js-header"></div>
<div class="page-header-meta">
<div class="btn btn--action js-settings"><%- @T('Settings') %></div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
<%- @Icon('arrow-down', 'dropdown-arrow') %>
</div>
</div>
<table class="settings-list">
<table class="settings-list settings-list--stretch">
<thead>
<tr>
<th><%- @T('Topic') %>
<th width="100%"><%- @T('Greeting') %> (<%- @T('Separate multiple values by ;') %>)
<th><%- @T('Greeting') %> (<%- @T('Separate multiple values by ;') %>)
<th><%- @T('Enabled') %>
</th></tr>
</thead>
Expand Down
Loading

0 comments on commit 133b570

Please sign in to comment.