From 39b37e048b5bdaeb2ec65fa6e79381e66a18f2ef Mon Sep 17 00:00:00 2001
From: Martin Edenhofer
Date: Wed, 25 Nov 2015 10:33:39 +0100
Subject: [PATCH] Added chat settings. Improved chat event backends.
---
.../javascripts/app/controllers/chat.coffee | 115 ++++++++++++++++--
app/assets/javascripts/app/models/chat.coffee | 4 +-
.../app/views/channel/chat.jst.eco | 16 +--
.../app/views/customer_chat/index.jst.eco | 2 +-
.../app/views/customer_chat/setting.jst.eco | 34 ++++++
app/controllers/users_controller.rb | 5 +-
app/models/chat.rb | 11 +-
lib/sessions/event/chat_agent_state.rb | 14 +--
lib/sessions/event/chat_base.rb | 88 ++++++++++++++
lib/sessions/event/chat_session_close.rb | 20 +--
lib/sessions/event/chat_session_init.rb | 14 +--
lib/sessions/event/chat_session_message.rb | 21 +---
lib/sessions/event/chat_session_start.rb | 2 +
lib/sessions/event/chat_session_typing.rb | 21 +---
lib/sessions/event/chat_status_agent.rb | 1 +
lib/sessions/event/chat_status_customer.rb | 14 +--
16 files changed, 262 insertions(+), 120 deletions(-)
create mode 100644 app/assets/javascripts/app/views/customer_chat/setting.jst.eco
diff --git a/app/assets/javascripts/app/controllers/chat.coffee b/app/assets/javascripts/app/controllers/chat.coffee
index b9db911ef..d61525233 100644
--- a/app/assets/javascripts/app/controllers/chat.coffee
+++ b/app/assets/javascripts/app/controllers/chat.coffee
@@ -3,6 +3,7 @@ class App.CustomerChat extends App.Controller
events:
'click .js-acceptChat': 'acceptChat'
+ 'click .js-settings': 'settings'
sounds:
chat_new: new Audio('assets/sounds/chat_new.mp3')
@@ -19,7 +20,11 @@ class App.CustomerChat extends App.Controller
return
@chatWindows = {}
- @maxChats = 4
+ @maxChatWindows = 4
+ preferences = @Session.get('preferences')
+ if preferences && preferences.chat && preferences.chat.max_windows
+ @maxChatWindows = parseInt(preferences.chat.max_windows)
+
@pushStateStarted = false
@messageCounter = 0
@meta =
@@ -33,6 +38,8 @@ class App.CustomerChat extends App.Controller
# update navbar on new status
@bind('chat_status_agent', (data) =>
+ if data.assets
+ App.Collection.loadAssets(data.assets)
@meta = data
@updateMeta()
if !@pushStateStarted
@@ -42,6 +49,7 @@ class App.CustomerChat extends App.Controller
# add new chat window
@bind('chat_session_start', (data) =>
+ console.log('chat_session_start', data)
if data.session
@addChat(data.session)
)
@@ -103,6 +111,16 @@ class App.CustomerChat extends App.Controller
if state is undefined
return @meta.active
+ # check if min one chat is active
+ if state
+ preferences = @Session.get('preferences')
+ if !preferences || !preferences.chat || !preferences.chat.active || _.isEmpty(preferences.chat.active)
+ @notify(
+ type: 'error'
+ msg: App.i18n.translateContent('To be able to chat you need to select min. one chat topic in settings!')
+ )
+ return
+
@meta.active = state
# write state
@@ -118,7 +136,7 @@ class App.CustomerChat extends App.Controller
@delay(delay, 200, 'updateNavMenu')
updateMeta: =>
- if @meta.waiting_chat_count && @maxChats > @windowCount()
+ if @meta.waiting_chat_count && @maxChatWindows > @windowCount()
@$('.js-acceptChat').addClass('is-clickable is-blinking')
else
@$('.js-acceptChat').removeClass('is-clickable is-blinking')
@@ -130,6 +148,7 @@ class App.CustomerChat extends App.Controller
if @meta.active_sessions
for session in @meta.active_sessions
@addChat(session)
+ console.log('updateMeta aC', session)
@meta.active_sessions = false
@updateNavMenu()
@@ -165,9 +184,14 @@ class App.CustomerChat extends App.Controller
chat.trigger 'layout-changed'
acceptChat: =>
- return if @windowCount() >= @maxChats
+ return if @windowCount() >= @maxChatWindows
App.WebSocket.send(event:'chat_session_start')
+ settings: ->
+ new Setting(
+ maxChatWindows: @maxChatWindows
+ )
+
class CustomerChatRouter extends App.ControllerPermanent
constructor: (params) ->
super
@@ -243,12 +267,21 @@ class ChatWindow extends App.Controller
@el.addClass('is-open')
# @addMessage 'Hello. My name is Roger, how can I help you?', 'agent'
- if @session && @session.messages
- for message in @session.messages
- if message.created_by_id
- @addMessage message.content, 'agent'
- else
- @addMessage message.content, 'customer'
+ if @session
+ if @session.messages
+ for message in @session.messages
+ if message.created_by_id
+ @addMessage message.content, 'agent'
+ else
+ @addMessage message.content, 'customer'
+
+ # send init reply
+ if !@session.messages || _.isEmpty(@session.messages)
+ preferences = @Session.get('preferences')
+ if preferences.chat && preferences.chat.phrase
+ phrases = preferences.chat.phrase[@session.chat_id]
+ if phrases
+ @sendMessage phrases
focus: =>
@input.focus()
@@ -319,11 +352,12 @@ class ChatWindow extends App.Controller
event.preventDefault()
@sendMessage()
- sendMessage: =>
- content = @input.html()
+ sendMessage: (content) =>
+ if !content
+ content = @input.html()
return if !content
- #@trigger "answer", @input.html()
+ console.log('send', content, @session.session_id)
App.WebSocket.send(
event:'chat_session_message'
data:
@@ -431,6 +465,63 @@ class ChatWindow extends App.Controller
scrollToBottom: ->
@scrollHolder.scrollTop(@scrollHolder.prop('scrollHeight'))
+class Setting extends App.ControllerModalNice
+ buttonClose: true
+ buttonCancel: true
+ buttonSubmit: true
+ head: 'Settings'
+
+ content: =>
+
+ preferences = @Session.get('preferences')
+ if !preferences
+ preferences = {}
+ if !preferences.chat
+ preferences.chat = {}
+ if !preferences.chat.active
+ preferences.chat.active = {}
+ if !preferences.chat.phrase
+ preferences.chat.phrase = {}
+ if !preferences.chat.max_windows
+ preferences.chat.max_windows = @maxChatWindows
+
+ App.view('customer_chat/setting')(
+ chats: App.Chat.all()
+ preferences: preferences
+ )
+
+ submit: (e) =>
+ e.preventDefault()
+ params = @formParam(e.target)
+
+ @formDisable(e)
+
+ # get data
+ @ajax(
+ id: 'preferences'
+ type: 'PUT'
+ url: "#{@apiPath}/users/preferences"
+ data: JSON.stringify({user:params})
+ processData: true
+ success: @success
+ error: @error
+ )
+
+ success: (data, status, xhr) =>
+ App.User.full(
+ App.Session.get('id'),
+ =>
+ @close()
+ ,
+ true
+ )
+
+ error: (xhr, status, error) =>
+ data = JSON.parse(xhr.responseText)
+ @notify(
+ type: 'error'
+ msg: App.i18n.translateContent(data.message)
+ )
App.Config.set( 'customer_chat', CustomerChatRouter, 'Routes' )
App.Config.set( 'CustomerChat', { controller: 'CustomerChat', authentication: true }, 'permanentTask' )
diff --git a/app/assets/javascripts/app/models/chat.coffee b/app/assets/javascripts/app/models/chat.coffee
index b80361ce0..4a93284bb 100644
--- a/app/assets/javascripts/app/models/chat.coffee
+++ b/app/assets/javascripts/app/models/chat.coffee
@@ -6,8 +6,8 @@ class App.Chat extends App.Model
@configure_attributes = [
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false },
{ name: 'note', display: 'Note', tag: 'textarea', limit: 250, null: true },
- { name: 'public', display: 'Public', tag: 'boolean', default: true },
- { name: 'max_queue', display: 'Max. Queue', tag: 'input', default: 5 },
+ #{ name: 'public', display: 'Public', tag: 'boolean', default: true },
+ { name: 'max_queue', display: 'Max. clients in waitlist', tag: 'input', default: 2 },
{ name: 'active', display: 'Active', tag: 'active', default: true },
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
diff --git a/app/assets/javascripts/app/views/channel/chat.jst.eco b/app/assets/javascripts/app/views/channel/chat.jst.eco
index 06c78c7ee..8081932e9 100644
--- a/app/assets/javascripts/app/views/channel/chat.jst.eco
+++ b/app/assets/javascripts/app/views/channel/chat.jst.eco
@@ -1,19 +1,19 @@
<%- @T('You can create chat widgets for your webpages to allow visitors to chat with you.') %>
-
<%- @T('Channels') %>
-
<%- @T('You can create multiple chat channels.') %>
+
<%- @T('Topics') %>
+
<%- @T('You can create multiple chat topics.') %>
<%- @T('Name') %>
<%- @T('Note') %>
- <%- @T('Max Queue') %>
+ <%- @T('Max. clients in waitlist') %>
<%- @T('Delete') %>
@@ -41,7 +41,7 @@
<% end %>
- <%- @Icon('plus-small') %> Add Channel
+ <%- @Icon('plus-small') %> <%- @T('Add') %>
@@ -57,7 +57,7 @@
-
+
<%- @T('Preview') %>
@@ -222,7 +222,7 @@ $(function() {
<%- marked(@T('When you turn on debugging by setting the option `debug` to `true` the reason gets printed to the javascript console.')) %>
-
+
<%- @T('Options') %>
diff --git a/app/assets/javascripts/app/views/customer_chat/index.jst.eco b/app/assets/javascripts/app/views/customer_chat/index.jst.eco
index 894a4c92f..ec09e5379 100644
--- a/app/assets/javascripts/app/views/customer_chat/index.jst.eco
+++ b/app/assets/javascripts/app/views/customer_chat/index.jst.eco
@@ -17,7 +17,7 @@
diff --git a/app/assets/javascripts/app/views/customer_chat/setting.jst.eco b/app/assets/javascripts/app/views/customer_chat/setting.jst.eco
new file mode 100644
index 000000000..396e42e01
--- /dev/null
+++ b/app/assets/javascripts/app/views/customer_chat/setting.jst.eco
@@ -0,0 +1,34 @@
+
\ No newline at end of file
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 9a7cb331a..dd0ac8d9d 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -572,10 +572,11 @@ curl http://localhost/api/v1/users/preferences.json -v -u #{login}:#{password} -
return
end
if params[:user]
+ user = User.find(current_user.id)
params[:user].each {|key, value|
- current_user.preferences[key.to_sym] = value
+ user.preferences[key.to_sym] = value
}
- current_user.save
+ user.save
end
render json: { message: 'ok' }, status: :ok
end
diff --git a/app/models/chat.rb b/app/models/chat.rb
index 356da3aa0..2a013e880 100644
--- a/app/models/chat.rb
+++ b/app/models/chat.rb
@@ -51,10 +51,10 @@ class Chat < ApplicationModel
end
# if all seads are used
- if Chat.active_chat_count >= max_queue
+ if Chat.waiting_chat_count >= max_queue
return {
state: 'no_seats_available',
- queue: Chat.seads_available,
+ queue: Chat.waiting_chat_count,
}
end
@@ -64,6 +64,10 @@ class Chat < ApplicationModel
def self.agent_state(user_id)
return { state: 'chat_disabled' } if !Setting.get('chat')
+ assets = {}
+ Chat.where(active: true).each {|chat|
+ assets = chat.assets(assets)
+ }
{
waiting_chat_count: waiting_chat_count,
running_chat_count: running_chat_count,
@@ -71,7 +75,8 @@ class Chat < ApplicationModel
active_agents: active_agents,
seads_available: seads_available,
seads_total: seads_total,
- active: Chat::Agent.state(user_id)
+ active: Chat::Agent.state(user_id),
+ assets: assets,
}
end
diff --git a/lib/sessions/event/chat_agent_state.rb b/lib/sessions/event/chat_agent_state.rb
index 4edc40b61..f89a517bc 100644
--- a/lib/sessions/event/chat_agent_state.rb
+++ b/lib/sessions/event/chat_agent_state.rb
@@ -2,18 +2,8 @@ class Sessions::Event::ChatAgentState < Sessions::Event::ChatBase
def run
- # only agents can do this
- chat_id = 1
- chat = Chat.find_by(id: chat_id)
- if !@session['id']
- return {
- event: 'chat_agent_state',
- data: {
- state: 'failed',
- message: 'No such user_id.'
- },
- }
- end
+ # check if user has permissions
+ return if !agent_permission_check
Chat::Agent.state(@session['id'], @data['data']['active'])
diff --git a/lib/sessions/event/chat_base.rb b/lib/sessions/event/chat_base.rb
index f630fa893..92a5ef153 100644
--- a/lib/sessions/event/chat_base.rb
+++ b/lib/sessions/event/chat_base.rb
@@ -53,4 +53,92 @@ class Sessions::Event::ChatBase
}
end
+ def agent_permission_check
+ if !@session
+ error = {
+ event: 'chat_error',
+ data: {
+ state: 'no_session',
+ },
+ }
+ Sessions.send(@client_id, error)
+ return
+ end
+ if !@session['id']
+ error = {
+ event: 'chat_error',
+ data: {
+ state: 'no_session_user_id',
+ },
+ }
+ Sessions.send(@client_id, error)
+ return
+ end
+ user = User.lookup(id: @session['id'])
+ if !user
+ error = {
+ event: 'chat_error',
+ data: {
+ state: 'no_such_user',
+ },
+ }
+ Sessions.send(@client_id, error)
+ return
+ end
+ if !user.role?('Agent')
+ error = {
+ event: 'chat_error',
+ data: {
+ state: 'no_permission',
+ },
+ }
+ Sessions.send(@client_id, error)
+ return
+ end
+ true
+ end
+
+ def current_chat_session
+ Chat::Session.find_by(session_id: @data['data']['session_id'])
+ end
+
+ def check_chat_session_exists
+ if !@data['data'] || !@data['data']['session_id']
+ error = {
+ event: 'chat_error',
+ data: {
+ state: 'Need session_id.',
+ },
+ }
+ Sessions.send(@client_id, error)
+ return
+ end
+ return true if current_chat_session
+ error = {
+ event: 'chat_error',
+ data: {
+ state: "No such session id #{@data['data']['session_id']}",
+ },
+ }
+ Sessions.send(@client_id, error)
+ false
+ end
+
+ def current_chat
+ Chat.find_by(id: @data['data']['chat_id'])
+ end
+
+ def check_chat_exists
+ chat = current_chat
+ return true if chat
+ error = {
+ event: 'chat_error',
+ data: {
+ state: 'no_such_chat',
+ },
+ }
+ Sessions.send(@client_id, error)
+ false
+ end
+
end
diff --git a/lib/sessions/event/chat_session_close.rb b/lib/sessions/event/chat_session_close.rb
index 306e2c282..c5e945432 100644
--- a/lib/sessions/event/chat_session_close.rb
+++ b/lib/sessions/event/chat_session_close.rb
@@ -2,24 +2,7 @@ class Sessions::Event::ChatSessionClose < Sessions::Event::ChatBase
def run
- if !@data['data'] || !@data['data']['session_id']
- return {
- event: 'chat_status_close',
- data: {
- state: 'Need session_id.',
- },
- }
- end
-
- chat_session = Chat::Session.find_by(session_id: @data['data']['session_id'])
- if !chat_session
- return {
- event: 'chat_status_close',
- data: {
- state: "No such session id #{@data['data']['session_id']}",
- },
- }
- end
+ return if !check_chat_session_exists
realname = 'Anonymous'
if @session && @session['id']
@@ -28,6 +11,7 @@ class Sessions::Event::ChatSessionClose < Sessions::Event::ChatBase
# check count of participents
participents_count = 0
+ chat_session = current_chat_session
if chat_session.preferences[:participents]
participents_count = chat_session.preferences[:participents].count
end
diff --git a/lib/sessions/event/chat_session_init.rb b/lib/sessions/event/chat_session_init.rb
index 853173fbb..4edac5151 100644
--- a/lib/sessions/event/chat_session_init.rb
+++ b/lib/sessions/event/chat_session_init.rb
@@ -1,21 +1,11 @@
class Sessions::Event::ChatSessionInit < Sessions::Event::ChatBase
def run
-
- chat_id = 1
- chat = Chat.find_by(id: chat_id)
- if !chat
- return {
- event: 'chat_session_init',
- data: {
- state: 'no_such_chat',
- },
- }
- end
+ return if !check_chat_exists
# create chat session
chat_session = Chat::Session.create(
- chat_id: chat_id,
+ chat_id: @data['data']['chat_id'],
name: '',
state: 'waiting',
preferences: {
diff --git a/lib/sessions/event/chat_session_message.rb b/lib/sessions/event/chat_session_message.rb
index b454f7e17..46e317bbf 100644
--- a/lib/sessions/event/chat_session_message.rb
+++ b/lib/sessions/event/chat_session_message.rb
@@ -1,25 +1,8 @@
class Sessions::Event::ChatSessionMessage < Sessions::Event::ChatBase
def run
-
- if !@data['data'] || !@data['data']['session_id']
- return {
- event: 'chat_session_message',
- data: {
- state: 'Need session_id.',
- },
- }
- end
-
- chat_session = Chat::Session.find_by(session_id: @data['data']['session_id'])
- if !chat_session
- return {
- event: 'chat_session_message',
- data: {
- state: "No such session id #{@data['data']['session_id']}",
- },
- }
- end
+ return if !check_chat_session_exists
+ chat_session = current_chat_session
user_id = nil
if @session
diff --git a/lib/sessions/event/chat_session_start.rb b/lib/sessions/event/chat_session_start.rb
index 0480c6259..0b5a7bbf5 100644
--- a/lib/sessions/event/chat_session_start.rb
+++ b/lib/sessions/event/chat_session_start.rb
@@ -1,6 +1,7 @@
class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase
def run
+ agent_permission_check
# find first in waiting list
chat_session = Chat::Session.where(state: 'waiting').order('created_at ASC').first
@@ -34,6 +35,7 @@ class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase
state: 'ok',
agent: user,
session_id: chat_session.session_id,
+ chat_id: chat_session.chat_id,
},
}
chat_session.send_to_recipients(data)
diff --git a/lib/sessions/event/chat_session_typing.rb b/lib/sessions/event/chat_session_typing.rb
index c7180ce00..9ab4b109e 100644
--- a/lib/sessions/event/chat_session_typing.rb
+++ b/lib/sessions/event/chat_session_typing.rb
@@ -1,25 +1,8 @@
class Sessions::Event::ChatSessionTyping < Sessions::Event::ChatBase
def run
-
- if !@data['data'] || !@data['data']['session_id']
- return {
- event: 'chat_session_typing',
- data: {
- state: 'Need session_id.',
- },
- }
- end
-
- chat_session = Chat::Session.find_by(session_id: @data['data']['session_id'])
- if !chat_session
- return {
- event: 'chat_session_typing',
- data: {
- state: "No such session id #{@data['data']['session_id']}",
- },
- }
- end
+ return if !check_chat_session_exists
+ chat_session = current_chat_session
user_id = nil
if @session
diff --git a/lib/sessions/event/chat_status_agent.rb b/lib/sessions/event/chat_status_agent.rb
index 7e723a118..9f0801d8d 100644
--- a/lib/sessions/event/chat_status_agent.rb
+++ b/lib/sessions/event/chat_status_agent.rb
@@ -3,6 +3,7 @@ class Sessions::Event::ChatStatusAgent < Sessions::Event::ChatBase
def run
# check if user has permissions
+ return if !agent_permission_check
# renew timestamps
state = Chat::Agent.state(@session['id'])
diff --git a/lib/sessions/event/chat_status_customer.rb b/lib/sessions/event/chat_status_customer.rb
index 5fa937e22..7dbeeeec6 100644
--- a/lib/sessions/event/chat_status_customer.rb
+++ b/lib/sessions/event/chat_status_customer.rb
@@ -1,17 +1,7 @@
class Sessions::Event::ChatStatusCustomer < Sessions::Event::ChatBase
def run
-
- chat_id = 1
- chat = Chat.find_by(id: chat_id)
- if !chat
- return {
- event: 'chat_status_customer',
- data: {
- state: 'no_such_chat',
- },
- }
- end
+ return if !check_chat_exists
# check if it's a chat sessin reconnect
session_id = nil
@@ -24,7 +14,7 @@ class Sessions::Event::ChatStatusCustomer < Sessions::Event::ChatBase
end
{
event: 'chat_status_customer',
- data: chat.customer_state(session_id),
+ data: current_chat.customer_state(session_id),
}
end
end