diff --git a/app/assets/javascripts/app/controllers/chat.coffee b/app/assets/javascripts/app/controllers/chat.coffee
index 2966e3b4c..8eb974089 100644
--- a/app/assets/javascripts/app/controllers/chat.coffee
+++ b/app/assets/javascripts/app/controllers/chat.coffee
@@ -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')
diff --git a/app/assets/javascripts/app/controllers/search.coffee b/app/assets/javascripts/app/controllers/search.coffee
index 9a6f45052..67e9c009a 100644
--- a/app/assets/javascripts/app/controllers/search.coffee
+++ b/app/assets/javascripts/app/controllers/search.coffee
@@ -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
diff --git a/app/assets/javascripts/app/models/chat_sessions.coffee b/app/assets/javascripts/app/models/chat_sessions.coffee
new file mode 100644
index 000000000..d32fccd18
--- /dev/null
+++ b/app/assets/javascripts/app/models/chat_sessions.coffee
@@ -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'
diff --git a/app/assets/javascripts/app/views/customer_chat/chat_window.jst.eco b/app/assets/javascripts/app/views/customer_chat/chat_window.jst.eco
index 1fef2ed9b..de2f271da 100644
--- a/app/assets/javascripts/app/views/customer_chat/chat_window.jst.eco
+++ b/app/assets/javascripts/app/views/customer_chat/chat_window.jst.eco
@@ -7,9 +7,7 @@
- <%= @name %>
+
<%= @name %> #<%= @session.id %>
<%- @T('disconnect') %>
@@ -24,6 +22,25 @@
+
+ <% if @session: %>
+
+ - <%- @T('Created at') %>: <%- @Ttimestamp(@session.created_at) %>
+ <% if @session && @session.preferences: %>
+ <% if @session.preferences.geo_ip: %>
+ - GeoIP: <%= @session.preferences.geo_ip.country_name %> <%= @session.preferences.geo_ip.city_name %>
+ <% end %>
+ <% if @session.preferences.remote_ip: %>
+ - IP: <%= @session.preferences.remote_ip %>
+ <% end %>
+ <% if @session.preferences.dns_name: %>
+ - DNS: <%= @session.preferences.dns_name %>
+ <% end %>
+ <% end %>
+
+ <% end %>
+
+
diff --git a/app/assets/javascripts/app/views/customer_chat/chat_window_info.jst.eco b/app/assets/javascripts/app/views/customer_chat/chat_window_info.jst.eco
deleted file mode 100644
index a7c3b1ff3..000000000
--- a/app/assets/javascripts/app/views/customer_chat/chat_window_info.jst.eco
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-<% if @session: %>
-- <%- @T('Created at') %>: <%- @Ttimestamp(@session.created_at) %>
-<% end %>
-<% if @session && @session.preferences: %>
- <% if @session.preferences.geo_ip: %>
-
- GeoIP: <%= @session.preferences.geo_ip.country_name %> <%= @session.preferences.geo_ip.city_name %>
- <% end %>
- <% if @session.preferences.remote_ip: %>
-
- IP: <%= @session.preferences.remote_ip %>
- <% end %>
- <% if @session.preferences.dns_name: %>
-
- DNS: <%= @session.preferences.dns_name %>
- <% end %>
-<% end %>
-
\ No newline at end of file
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 1ec9c76f8..fad61f23c 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -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)
diff --git a/app/models/chat/session.rb b/app/models/chat/session.rb
index 70cd0d818..cf83beea4 100644
--- a/app/models/chat/session.rb
+++ b/app/models/chat/session.rb
@@ -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
diff --git a/app/models/chat/session/assets.rb b/app/models/chat/session/assets.rb
new file mode 100644
index 000000000..6410e2692
--- /dev/null
+++ b/app/models/chat/session/assets.rb
@@ -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
diff --git a/app/models/chat/session/search.rb b/app/models/chat/session/search.rb
new file mode 100644
index 000000000..87d12f1c9
--- /dev/null
+++ b/app/models/chat/session/search.rb
@@ -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
diff --git a/app/models/chat/session/search_index.rb b/app/models/chat/session/search_index.rb
new file mode 100644
index 000000000..b81196722
--- /dev/null
+++ b/app/models/chat/session/search_index.rb
@@ -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
diff --git a/lib/sessions/event/base.rb b/lib/sessions/event/base.rb
index 5c1b659f2..1b02e6bfe 100644
--- a/lib/sessions/event/base.rb
+++ b/lib/sessions/event/base.rb
@@ -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",
diff --git a/lib/sessions/event/chat_session_update.rb b/lib/sessions/event/chat_session_update.rb
new file mode 100644
index 000000000..0f93dfc31
--- /dev/null
+++ b/lib/sessions/event/chat_session_update.rb
@@ -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
diff --git a/test/unit/model_test.rb b/test/unit/model_test.rb
index 9c5431539..d31e69fbb 100644
--- a/test/unit/model_test.rb
+++ b/test/unit/model_test.rb
@@ -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