Added support to search for chat sessions. Added set name and tags for chats.
This commit is contained in:
parent
69ccf09906
commit
9c54b3382d
13 changed files with 417 additions and 87 deletions
|
@ -35,7 +35,7 @@ class App.CustomerChat extends App.Controller
|
|||
active_agent_ids: []
|
||||
|
||||
@render()
|
||||
@on 'layout-has-changed', @propagateLayoutChange
|
||||
@on('layout-has-changed', @propagateLayoutChange)
|
||||
|
||||
# update navbar on new status
|
||||
@bind('chat_status_agent', (data) =>
|
||||
|
@ -163,6 +163,11 @@ class App.CustomerChat extends App.Controller
|
|||
@title 'Customer Chat', true
|
||||
@navupdate '#customer_chat'
|
||||
|
||||
if params.session_id && App.ChatSession.exists(params.session_id)
|
||||
session = App.ChatSession.find(params.session_id)
|
||||
@addChat(session)
|
||||
@navigate '#customer_chat'
|
||||
|
||||
active: (state) =>
|
||||
return @shown if state is undefined
|
||||
@shown = state
|
||||
|
@ -264,10 +269,11 @@ class App.CustomerChat extends App.Controller
|
|||
|
||||
addChat: (session) ->
|
||||
return if @chatWindows[session.session_id]
|
||||
chat = new ChatWindow
|
||||
chat = new ChatWindow(
|
||||
session: session
|
||||
removeCallback: @removeChat
|
||||
messageCallback: @updateNavMenu
|
||||
)
|
||||
|
||||
@workspace.append chat.el
|
||||
chat.render()
|
||||
|
@ -289,7 +295,7 @@ class App.CustomerChat extends App.Controller
|
|||
propagateLayoutChange: (event) =>
|
||||
# adjust scroll position on layoutChange
|
||||
for session_id, chat of @chatWindows
|
||||
chat.trigger 'layout-changed'
|
||||
chat.trigger('layout-changed')
|
||||
|
||||
acceptChat: =>
|
||||
return if @windowCount() >= @maxChatWindows
|
||||
|
@ -324,19 +330,6 @@ class App.CustomerChat extends App.Controller
|
|||
currentPosition: =>
|
||||
@$('.main').scrollTop()
|
||||
|
||||
class CustomerChatRouter extends App.ControllerPermanent
|
||||
requiredPermission: 'chat.agent'
|
||||
constructor: (params) ->
|
||||
super
|
||||
|
||||
App.TaskManager.execute(
|
||||
key: 'CustomerChat'
|
||||
controller: 'CustomerChat'
|
||||
params: {}
|
||||
show: true
|
||||
persistent: true
|
||||
)
|
||||
|
||||
class ChatWindow extends App.Controller
|
||||
className: 'chat-window'
|
||||
|
||||
|
@ -348,6 +341,8 @@ class ChatWindow extends App.Controller
|
|||
'click .js-close': 'close'
|
||||
'click .js-disconnect': 'disconnect'
|
||||
'click .js-scrollHint': 'onScrollHintClick'
|
||||
'click .js-info': 'toggleMeta'
|
||||
'submit .js-metaForm': 'sendMetaForm'
|
||||
|
||||
elements:
|
||||
'.js-customerChatInput': 'input'
|
||||
|
@ -355,8 +350,11 @@ class ChatWindow extends App.Controller
|
|||
'.js-close': 'closeButton'
|
||||
'.js-disconnect': 'disconnectButton'
|
||||
'.js-body': 'body'
|
||||
'.js-meta': 'meta'
|
||||
'.js-name': 'metaName'
|
||||
'.js-scrollHolder': 'scrollHolder'
|
||||
'.js-scrollHint': 'scrollHint'
|
||||
'.js-metaForm': 'metaForm'
|
||||
|
||||
sounds:
|
||||
message: new Audio('assets/sounds/chat_message.mp3')
|
||||
|
@ -374,9 +372,11 @@ class ChatWindow extends App.Controller
|
|||
@scrollSnapTolerance = 10 # pixels
|
||||
|
||||
@chat = App.Chat.find(@session.chat_id)
|
||||
@name = "#{@chat.displayName()} ##{@session.id}"
|
||||
@name = @chat.displayName()
|
||||
if @session && !_.isEmpty(@session.name)
|
||||
@name = @session.name
|
||||
|
||||
@on 'layout-change', @onLayoutChange
|
||||
@on('layout-change', @onLayoutChange)
|
||||
|
||||
@bind('chat_session_typing', (data) =>
|
||||
return if data.session_id isnt @session.session_id
|
||||
|
@ -413,12 +413,44 @@ class ChatWindow extends App.Controller
|
|||
onLayoutChange: =>
|
||||
@scrollToBottom()
|
||||
|
||||
render: ->
|
||||
@html App.view('customer_chat/chat_window')
|
||||
name: @name
|
||||
toggleMeta: =>
|
||||
if @meta.hasClass('hidden')
|
||||
@showMeta()
|
||||
else
|
||||
@hideMeta()
|
||||
|
||||
@el.one 'transitionend', @onTransitionend
|
||||
@scrollHolder.scroll @detectScrolledtoBottom
|
||||
hideMeta: =>
|
||||
@body.removeClass('hidden')
|
||||
@meta.addClass('hidden')
|
||||
@sendMetaForm()
|
||||
|
||||
showMeta: =>
|
||||
@body.addClass('hidden')
|
||||
@meta.removeClass('hidden')
|
||||
|
||||
sendMetaForm: (e) =>
|
||||
if e
|
||||
e.preventDefault()
|
||||
params = @formParam(@metaForm)
|
||||
|
||||
App.WebSocket.send(
|
||||
event:'chat_session_update'
|
||||
data:
|
||||
session_id: @session.session_id
|
||||
name: params.name
|
||||
tags: params.tags
|
||||
)
|
||||
|
||||
@metaName.text(params.name)
|
||||
|
||||
render: ->
|
||||
@html App.view('customer_chat/chat_window')(
|
||||
name: @name
|
||||
session: @session
|
||||
)
|
||||
|
||||
@el.one('transitionend', @onTransitionend)
|
||||
@scrollHolder.scroll(@detectScrolledtoBottom)
|
||||
|
||||
# force repaint
|
||||
@el.prop('offsetHeight')
|
||||
|
@ -426,18 +458,24 @@ class ChatWindow extends App.Controller
|
|||
|
||||
# @addMessage 'Hello. My name is Roger, how can I help you?', 'agent'
|
||||
if @session
|
||||
|
||||
# set chat to offline if state is already closed
|
||||
activeChat = true
|
||||
if @session.state is 'closed'
|
||||
activeChat = false
|
||||
|
||||
if @session && @session.preferences && @session.preferences.url
|
||||
@addNoticeMessage(@session.preferences.url)
|
||||
@addNoticeMessage(@session.preferences.url, undefined, activeChat)
|
||||
|
||||
if @session.messages
|
||||
for message in @session.messages
|
||||
if message.created_by_id
|
||||
@addMessage message.content, 'agent'
|
||||
@addMessage(message.content, 'agent', false, activeChat)
|
||||
else
|
||||
@addMessage message.content, 'customer'
|
||||
@addMessage(message.content, 'customer', false, activeChat)
|
||||
|
||||
# send init reply
|
||||
if !@session.messages || _.isEmpty(@session.messages)
|
||||
if activeChat && _.isEmpty(@session.messages)
|
||||
preferences = @Session.get('preferences')
|
||||
if preferences.chat && preferences.chat.phrase
|
||||
phrases = preferences.chat.phrase[@session.chat_id]
|
||||
|
@ -447,20 +485,9 @@ class ChatWindow extends App.Controller
|
|||
@input.html(phrase)
|
||||
@sendMessage(1600)
|
||||
|
||||
@$('.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('Details')
|
||||
content: =>
|
||||
App.view('customer_chat/chat_window_info')(
|
||||
session: @session
|
||||
)
|
||||
)
|
||||
# set chat to offline if state is already closed
|
||||
if !activeChat
|
||||
@goOffline()
|
||||
|
||||
# show text module UI
|
||||
new App.WidgetTextModule(
|
||||
|
@ -470,6 +497,18 @@ class ChatWindow extends App.Controller
|
|||
config: App.Config.all()
|
||||
)
|
||||
|
||||
configureAttributesOutbound = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', null: true, },
|
||||
{ name: 'tags', display: 'Tags', tag: 'tag', null: true, },
|
||||
]
|
||||
new App.ControllerForm(
|
||||
el: @$('.js-metaForm')
|
||||
model:
|
||||
configure_attributes: configureAttributesOutbound
|
||||
className: ''
|
||||
params: @session
|
||||
)
|
||||
|
||||
focus: =>
|
||||
@input.focus()
|
||||
|
||||
|
@ -498,7 +537,8 @@ class ChatWindow extends App.Controller
|
|||
@goOffline()
|
||||
|
||||
close: =>
|
||||
@el.one 'transitionend', { callback: @release }, @onTransitionend
|
||||
@sendMetaForm()
|
||||
@el.one('transitionend', { callback: @release }, @onTransitionend)
|
||||
@el.removeClass('is-open')
|
||||
if @removeCallback
|
||||
@removeCallback(@session.session_id)
|
||||
|
@ -577,7 +617,8 @@ class ChatWindow extends App.Controller
|
|||
)
|
||||
@delay(send, delay)
|
||||
|
||||
@addMessage content, 'agent'
|
||||
@hideMeta()
|
||||
@addMessage(content, 'agent')
|
||||
@input.html('')
|
||||
|
||||
updateModified: (state) =>
|
||||
|
@ -614,18 +655,19 @@ class ChatWindow extends App.Controller
|
|||
@messageCallback(@session.session_id)
|
||||
@unreadMessagesCounter = 0
|
||||
|
||||
addMessage: (message, sender, isNew) =>
|
||||
@maybeAddTimestamp()
|
||||
addMessage: (message, sender, isNew, useMaybeAddTimestamp = true) =>
|
||||
@maybeAddTimestamp() if useMaybeAddTimestamp
|
||||
|
||||
@lastAddedType = sender
|
||||
|
||||
@body.append App.view('customer_chat/chat_message')
|
||||
@body.append App.view('customer_chat/chat_message')(
|
||||
message: message
|
||||
sender: sender
|
||||
isNew: isNew
|
||||
timestamp: Date.now()
|
||||
)
|
||||
|
||||
@scrollToBottom showHint: true
|
||||
@scrollToBottom(showHint: true)
|
||||
|
||||
showWritingLoader: =>
|
||||
if !@isTyping
|
||||
|
@ -667,33 +709,37 @@ class ChatWindow extends App.Controller
|
|||
@lastAddedType = 'timestamp'
|
||||
|
||||
addTimestamp: (label, time) =>
|
||||
@body.append App.view('customer_chat/chat_timestamp')
|
||||
@body.append App.view('customer_chat/chat_timestamp')(
|
||||
label: label
|
||||
time: time
|
||||
)
|
||||
|
||||
updateLastTimestamp: (label, time) ->
|
||||
@body
|
||||
.find('.js-timestamp')
|
||||
.last()
|
||||
.replaceWith App.view('customer_chat/chat_timestamp')
|
||||
.replaceWith App.view('customer_chat/chat_timestamp')(
|
||||
label: label
|
||||
time: time
|
||||
)
|
||||
|
||||
addStatusMessage: (message, args) ->
|
||||
@maybeAddTimestamp()
|
||||
addStatusMessage: (message, args, useMaybeAddTimestamp = true) ->
|
||||
@maybeAddTimestamp() if useMaybeAddTimestamp
|
||||
|
||||
@body.append App.view('customer_chat/chat_status_message')
|
||||
@body.append App.view('customer_chat/chat_status_message')(
|
||||
message: message
|
||||
args: args
|
||||
)
|
||||
|
||||
@scrollToBottom()
|
||||
|
||||
addNoticeMessage: (message, args) ->
|
||||
@maybeAddTimestamp()
|
||||
addNoticeMessage: (message, args, useMaybeAddTimestamp = true) ->
|
||||
@maybeAddTimestamp() if useMaybeAddTimestamp
|
||||
|
||||
@body.append App.view('customer_chat/chat_notice_message')
|
||||
@body.append App.view('customer_chat/chat_notice_message')(
|
||||
message: message
|
||||
args: args
|
||||
)
|
||||
|
||||
@scrollToBottom()
|
||||
|
||||
|
@ -784,6 +830,24 @@ class Setting extends App.ControllerModal
|
|||
msg: App.i18n.translateContent(data.message)
|
||||
)
|
||||
|
||||
class CustomerChatRouter extends App.ControllerPermanent
|
||||
requiredPermission: 'chat.agent'
|
||||
constructor: (params) ->
|
||||
super
|
||||
|
||||
# cleanup params
|
||||
clean_params =
|
||||
session_id: params.session_id
|
||||
|
||||
App.TaskManager.execute(
|
||||
key: 'CustomerChat'
|
||||
controller: 'CustomerChat'
|
||||
params: clean_params
|
||||
show: true
|
||||
persistent: true
|
||||
)
|
||||
|
||||
App.Config.set('customer_chat', CustomerChatRouter, 'Routes')
|
||||
App.Config.set('customer_chat/session/:session_id', CustomerChatRouter, 'Routes')
|
||||
App.Config.set('CustomerChat', { controller: 'CustomerChat', permission: ['chat.agent'] }, 'permanentTask')
|
||||
App.Config.set('CustomerChat', { prio: 1200, parent: '', name: 'Customer Chat', target: '#customer_chat', key: 'CustomerChat', shown: false, permission: ['chat.agent'], class: 'chat' }, 'NavBar')
|
||||
|
|
|
@ -79,6 +79,7 @@ class App.Search extends App.Controller
|
|||
|
||||
@tabs = []
|
||||
for model in App.Config.get('models_searchable')
|
||||
model = model.replace(/::/, '')
|
||||
tab =
|
||||
name: model
|
||||
model: model
|
||||
|
|
32
app/assets/javascripts/app/models/chat_sessions.coffee
Normal file
32
app/assets/javascripts/app/models/chat_sessions.coffee
Normal file
|
@ -0,0 +1,32 @@
|
|||
class App.ChatSession extends App.Model
|
||||
@configure 'ChatSession', 'name', 'note'
|
||||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/chat_sessions'
|
||||
|
||||
@configure_attributes = [
|
||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, 'null': false }
|
||||
{ name: 'state', display: 'State', readonly: 1 }
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 }
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 }
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 }
|
||||
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 }
|
||||
]
|
||||
|
||||
@configure_overview = [
|
||||
'name',
|
||||
'state',
|
||||
'created_at',
|
||||
]
|
||||
|
||||
uiUrl: ->
|
||||
"#customer_chat/session/#{@id}"
|
||||
|
||||
searchResultAttributes: ->
|
||||
displayName = ''
|
||||
if !_.isEmpty(@name)
|
||||
displayName = @displayName()
|
||||
display: "##{@id} #{displayName}"
|
||||
id: @id
|
||||
class: 'chat_session chat_session-popover'
|
||||
url: @uiUrl()
|
||||
icon: 'chat'
|
|
@ -7,9 +7,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="chat-name">
|
||||
<%= @name %> <div class="status-badge js-info">
|
||||
<div class="info-badge"><%- @Icon('info') %></div>
|
||||
</div>
|
||||
<span class="js-name js-info u-clickable"><%= @name %><span> #<%= @session.id %>
|
||||
</div>
|
||||
<div class="chat-disconnect js-disconnect">
|
||||
<div class="btn btn--action btn--small"><%- @T('disconnect') %></div>
|
||||
|
@ -24,6 +22,25 @@
|
|||
</div>
|
||||
<div class="chat-body-holder js-scrollHolder">
|
||||
<div class="chat-body js-body"></div>
|
||||
<div class="chat-body js-meta hidden">
|
||||
<% if @session: %>
|
||||
<ul>
|
||||
<li><%- @T('Created at') %>: <%- @Ttimestamp(@session.created_at) %></li>
|
||||
<% if @session && @session.preferences: %>
|
||||
<% if @session.preferences.geo_ip: %>
|
||||
<li>GeoIP: <%= @session.preferences.geo_ip.country_name %> <%= @session.preferences.geo_ip.city_name %></li>
|
||||
<% end %>
|
||||
<% if @session.preferences.remote_ip: %>
|
||||
<li>IP: <%= @session.preferences.remote_ip %></li>
|
||||
<% end %>
|
||||
<% if @session.preferences.dns_name: %>
|
||||
<li>DNS: <%= @session.preferences.dns_name %></li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
<form class="js-metaForm" style="max-width: 200px; width: 100%;"></form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-controls">
|
||||
<div class="chat-input">
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<hr>
|
||||
<ul>
|
||||
<% if @session: %>
|
||||
<li><%- @T('Created at') %>: <%- @Ttimestamp(@session.created_at) %>
|
||||
<% end %>
|
||||
<% if @session && @session.preferences: %>
|
||||
<% if @session.preferences.geo_ip: %>
|
||||
<li>GeoIP: <%= @session.preferences.geo_ip.country_name %> <%= @session.preferences.geo_ip.city_name %>
|
||||
<% end %>
|
||||
<% if @session.preferences.remote_ip: %>
|
||||
<li>IP: <%= @session.preferences.remote_ip %>
|
||||
<% end %>
|
||||
<% if @session.preferences.dns_name: %>
|
||||
<li>DNS: <%= @session.preferences.dns_name %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</ul>
|
|
@ -33,9 +33,10 @@ class SearchController < ApplicationController
|
|||
objects_in_order = []
|
||||
objects_in_order_hash = {}
|
||||
objects.each do |object|
|
||||
preferences = object.constantize.search_preferences(current_user)
|
||||
local_class = object.constantize
|
||||
preferences = local_class.search_preferences(current_user)
|
||||
next if !preferences
|
||||
objects_in_order_hash[preferences[:prio]] = object
|
||||
objects_in_order_hash[preferences[:prio]] = local_class
|
||||
end
|
||||
objects_in_order_hash.keys.sort.reverse_each do |prio|
|
||||
objects_in_order.push objects_in_order_hash[prio]
|
||||
|
@ -64,16 +65,18 @@ class SearchController < ApplicationController
|
|||
items = SearchIndexBackend.search(query, limit, objects_with_direct_search_index)
|
||||
items.each do |item|
|
||||
require item[:type].to_filename
|
||||
record = Kernel.const_get(item[:type]).lookup(id: item[:id])
|
||||
local_class = Kernel.const_get(item[:type])
|
||||
record = local_class.lookup(id: item[:id])
|
||||
next if !record
|
||||
assets = record.assets(assets)
|
||||
item[:type] = local_class.to_app_model.to_s
|
||||
result.push item
|
||||
end
|
||||
end
|
||||
|
||||
# e. g. do ticket query by Ticket class to handle ticket permissions
|
||||
objects_without_direct_search_index.each do |object|
|
||||
object_result = search_generic_backend(object, query, limit, current_user, assets)
|
||||
object_result = search_generic_backend(object.constantize, query, limit, current_user, assets)
|
||||
if object_result.present?
|
||||
result = result.concat(object_result)
|
||||
end
|
||||
|
@ -83,7 +86,7 @@ class SearchController < ApplicationController
|
|||
result_in_order = []
|
||||
objects_in_order.each do |object|
|
||||
result.each do |item|
|
||||
next if item[:type] != object
|
||||
next if item[:type] != object.to_app_model.to_s
|
||||
item[:id] = item[:id].to_i
|
||||
result_in_order.push item
|
||||
end
|
||||
|
@ -110,7 +113,7 @@ class SearchController < ApplicationController
|
|||
private
|
||||
|
||||
def search_generic_backend(object, query, limit, current_user, assets)
|
||||
found_objects = object.constantize.search(
|
||||
found_objects = object.search(
|
||||
query: query,
|
||||
limit: limit,
|
||||
current_user: current_user,
|
||||
|
@ -119,7 +122,7 @@ class SearchController < ApplicationController
|
|||
found_objects.each do |found_object|
|
||||
item = {
|
||||
id: found_object.id,
|
||||
type: found_object.class.to_s
|
||||
type: found_object.class.to_app_model.to_s
|
||||
}
|
||||
result.push item
|
||||
assets = found_object.assets(assets)
|
||||
|
|
|
@ -1,4 +1,15 @@
|
|||
class Chat::Session < ApplicationModel
|
||||
include HasSearchIndexBackend
|
||||
include HasTags
|
||||
|
||||
extend Chat::Session::Search
|
||||
load 'chat/session/search_index.rb'
|
||||
include Chat::Session::SearchIndex
|
||||
load 'chat/session/assets.rb'
|
||||
include Chat::Session::Assets
|
||||
|
||||
has_many :messages, class_name: 'Chat::Message', foreign_key: 'chat_session_id'
|
||||
|
||||
before_create :generate_session_id
|
||||
store :preferences
|
||||
|
||||
|
|
56
app/models/chat/session/assets.rb
Normal file
56
app/models/chat/session/assets.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||||
module Chat::Session::Assets
|
||||
|
||||
=begin
|
||||
|
||||
get all assets / related models for this chat
|
||||
|
||||
chat = Chat::Session.find(123)
|
||||
result = Chat::Session.assets(assets_if_exists)
|
||||
|
||||
returns
|
||||
|
||||
result = {
|
||||
users: {
|
||||
123: user_model_123,
|
||||
1234: user_model_1234,
|
||||
},
|
||||
chat_sessions: [ chat_session_model1 ]
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def assets(data)
|
||||
|
||||
app_model_chat_session = Chat::Session.to_app_model
|
||||
app_model_chat = Chat.to_app_model
|
||||
app_model_user = User.to_app_model
|
||||
|
||||
data[ app_model_chat_session ] ||= {}
|
||||
|
||||
if !data[ app_model_chat_session ][ id ]
|
||||
data[ app_model_chat_session ][ id ] = attributes_with_association_ids
|
||||
data[ app_model_chat_session ][ id ]['messages'] = []
|
||||
messages.each do |message|
|
||||
data[ app_model_chat_session ][ id ]['messages'].push message.attributes
|
||||
end
|
||||
data[ app_model_chat_session ][ id ]['tags'] = tag_list
|
||||
end
|
||||
|
||||
if !data[ app_model_chat ] || !data[ app_model_chat ][ chat_id ]
|
||||
chat = Chat.lookup(id: chat_id)
|
||||
if chat
|
||||
data = chat.assets(data)
|
||||
end
|
||||
end
|
||||
|
||||
%w[created_by_id updated_by_id].each do |local_user_id|
|
||||
next if !self[ local_user_id ]
|
||||
next if data[ app_model_user ] && data[ app_model_user ][ self[ local_user_id ] ]
|
||||
user = User.lookup(id: self[ local_user_id ])
|
||||
next if !user
|
||||
data = user.assets(data)
|
||||
end
|
||||
data
|
||||
end
|
||||
end
|
80
app/models/chat/session/search.rb
Normal file
80
app/models/chat/session/search.rb
Normal file
|
@ -0,0 +1,80 @@
|
|||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Chat::Session
|
||||
module Search
|
||||
|
||||
=begin
|
||||
|
||||
search organizations preferences
|
||||
|
||||
result = Chat::Session.search_preferences(user_model)
|
||||
|
||||
returns if user has permissions to search
|
||||
|
||||
result = {
|
||||
prio: 1000,
|
||||
direct_search_index: true
|
||||
}
|
||||
|
||||
returns if user has no permissions to search
|
||||
|
||||
result = false
|
||||
|
||||
=end
|
||||
|
||||
def search_preferences(current_user)
|
||||
return false if Setting.get('chat') != true || !current_user.permissions?('chat.agent')
|
||||
{
|
||||
prio: 900,
|
||||
direct_search_index: true,
|
||||
}
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
search organizations
|
||||
|
||||
result = Chat::Session.search(
|
||||
current_user: User.find(123),
|
||||
query: 'search something',
|
||||
limit: 15,
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
result = [organization_model1, organization_model2]
|
||||
|
||||
=end
|
||||
|
||||
def search(params)
|
||||
|
||||
# get params
|
||||
query = params[:query]
|
||||
limit = params[:limit] || 10
|
||||
current_user = params[:current_user]
|
||||
|
||||
# enable search only for agents and admins
|
||||
return [] if !search_preferences(current_user)
|
||||
|
||||
# try search index backend
|
||||
if SearchIndexBackend.enabled?
|
||||
items = SearchIndexBackend.search(query, limit, 'Chat::Session')
|
||||
chat_sessions = []
|
||||
items.each do |item|
|
||||
chat_session = Chat::Session.lookup(id: item[:id])
|
||||
next if !chat_session
|
||||
chat_sessions.push chat_session
|
||||
end
|
||||
return chat_sessions
|
||||
end
|
||||
|
||||
# fallback do sql query
|
||||
# - stip out * we already search for *query* -
|
||||
query.delete! '*'
|
||||
chat_sessions = Chat::Session.where(
|
||||
'name LIKE ?', "%#{query}%"
|
||||
).order('name').limit(limit).to_a
|
||||
chat_sessions
|
||||
end
|
||||
end
|
||||
end
|
36
app/models/chat/session/search_index.rb
Normal file
36
app/models/chat/session/search_index.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
||||
module Chat::Session::SearchIndex
|
||||
|
||||
=begin
|
||||
|
||||
lookup name of ref. objects
|
||||
|
||||
chat_session = Chat::Session.find(123)
|
||||
result = chat_session.search_index_attribute_lookup
|
||||
|
||||
returns
|
||||
|
||||
attributes # object with lookup data
|
||||
|
||||
=end
|
||||
|
||||
def search_index_attribute_lookup
|
||||
attributes = super
|
||||
return if !attributes
|
||||
|
||||
attributes[:tag] = tag_list
|
||||
|
||||
messages = Chat::Message.where(chat_session_id: id)
|
||||
attributes['messages'] = []
|
||||
messages.each do |message|
|
||||
|
||||
# lookup attributes of ref. objects (normally name and note)
|
||||
message_attributes = message.search_index_attribute_lookup
|
||||
|
||||
attributes['messages'].push message_attributes
|
||||
end
|
||||
|
||||
attributes
|
||||
end
|
||||
|
||||
end
|
|
@ -49,7 +49,7 @@ class Sessions::Event::Base
|
|||
true
|
||||
end
|
||||
|
||||
def permission_check(key, event)
|
||||
def current_user_id
|
||||
if !@session
|
||||
error = {
|
||||
event: "#{event}_error",
|
||||
|
@ -60,7 +60,7 @@ class Sessions::Event::Base
|
|||
Sessions.send(@client_id, error)
|
||||
return
|
||||
end
|
||||
if !@session['id']
|
||||
if @session['id'].blank?
|
||||
error = {
|
||||
event: "#{event}_error",
|
||||
data: {
|
||||
|
@ -70,7 +70,13 @@ class Sessions::Event::Base
|
|||
Sessions.send(@client_id, error)
|
||||
return
|
||||
end
|
||||
user = User.lookup(id: @session['id'])
|
||||
@session['id']
|
||||
end
|
||||
|
||||
def current_user
|
||||
user_id = current_user_id
|
||||
return if !user_id
|
||||
user = User.find_by(id: user_id)
|
||||
if !user
|
||||
error = {
|
||||
event: "#{event}_error",
|
||||
|
@ -81,6 +87,12 @@ class Sessions::Event::Base
|
|||
Sessions.send(@client_id, error)
|
||||
return
|
||||
end
|
||||
user
|
||||
end
|
||||
|
||||
def permission_check(key, event)
|
||||
user = current_user
|
||||
return if !user
|
||||
if !user.permissions?(key)
|
||||
error = {
|
||||
event: "#{event}_error",
|
||||
|
|
35
lib/sessions/event/chat_session_update.rb
Normal file
35
lib/sessions/event/chat_session_update.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
class Sessions::Event::ChatSessionUpdate < Sessions::Event::ChatBase
|
||||
|
||||
def run
|
||||
return super if super
|
||||
return if !check_chat_session_exists
|
||||
return if !permission_check('chat.agent', 'chat')
|
||||
chat_session = current_chat_session
|
||||
|
||||
if @payload['data']['name'] != chat_session.name
|
||||
chat_session.name = @payload['data']['name']
|
||||
chat_session.save!
|
||||
end
|
||||
|
||||
if @payload['data']['tags']
|
||||
new_tags = @payload['data']['tags'].split(',')
|
||||
|
||||
new_tags.each(&:strip!)
|
||||
|
||||
tags = chat_session.tag_list
|
||||
new_tags.each do |new_tag|
|
||||
next if new_tag.blank?
|
||||
next if tags.include?(new_tag)
|
||||
chat_session.tag_add(new_tag, current_user_id)
|
||||
end
|
||||
|
||||
tags.each do |tag|
|
||||
next if new_tags.include?(tag)
|
||||
chat_session.tag_remove(tag, current_user_id)
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
|
@ -243,8 +243,8 @@ class ModelTest < ActiveSupport::TestCase
|
|||
assert(searchable.include?(Ticket))
|
||||
assert(searchable.include?(User))
|
||||
assert(searchable.include?(Organization))
|
||||
assert_equal(3, searchable.count)
|
||||
|
||||
assert(searchable.include?(Chat::Session))
|
||||
assert_equal(4, searchable.count)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue