Merge branch 'develop' of github.com:martini/zammad into develop
This commit is contained in:
commit
d970c08306
9 changed files with 307 additions and 16 deletions
|
@ -6,6 +6,11 @@ class App.ChannelChat extends App.ControllerTabs
|
||||||
@title 'Chat', true
|
@title 'Chat', true
|
||||||
|
|
||||||
@tabs = [
|
@tabs = [
|
||||||
|
{
|
||||||
|
name: 'Chat Channels',
|
||||||
|
target: 'channels',
|
||||||
|
controller: App.ChannelChatOverview
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
target: 'setting',
|
target: 'setting',
|
||||||
|
@ -15,28 +20,125 @@ class App.ChannelChat extends App.ControllerTabs
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
# enable/disable
|
class App.ChannelChatOverview extends App.Controller
|
||||||
|
events:
|
||||||
|
'click .js-new': 'new'
|
||||||
|
'click .js-edit': 'edit'
|
||||||
|
'click .js-delete': 'delete'
|
||||||
|
'click .js-widget': 'widget'
|
||||||
|
|
||||||
# show also if nobody is online / leave a message
|
constructor: ->
|
||||||
|
super
|
||||||
|
@interval(@load, 30000)
|
||||||
|
#@load()
|
||||||
|
|
||||||
# channels
|
load: =>
|
||||||
# sales - en / authentication needed
|
@startLoading()
|
||||||
# sales - de / authentication needed
|
@ajax(
|
||||||
|
id: 'chat_index'
|
||||||
|
type: 'GET'
|
||||||
|
url: @apiPath + '/chats'
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
App.Collection.loadAssets(data.assets)
|
||||||
|
@stopLoading()
|
||||||
|
@render(data)
|
||||||
|
)
|
||||||
|
|
||||||
|
render: (data = {}) =>
|
||||||
|
|
||||||
|
chats = []
|
||||||
|
for chat_id in data.chat_ids
|
||||||
|
chats.push App.Chat.find(chat_id)
|
||||||
|
|
||||||
# agent
|
@html App.view('channel/chat_overview')(
|
||||||
# channes I'm work for
|
chats: chats
|
||||||
|
)
|
||||||
|
|
||||||
# x sales - de / greeting
|
new: (e) =>
|
||||||
# o sales - en / greeting
|
new App.ControllerGenericNew(
|
||||||
|
pageData:
|
||||||
|
title: 'Chats'
|
||||||
|
object: 'Chat'
|
||||||
|
objects: 'Chats'
|
||||||
|
genericObject: 'Chat'
|
||||||
|
callback: @load
|
||||||
|
container: @el.closest('.content')
|
||||||
|
large: true
|
||||||
|
)
|
||||||
|
|
||||||
# concurent chats
|
edit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
id = $(e.target).closest('.action').data('id')
|
||||||
|
new App.ControllerGenericEdit(
|
||||||
|
id: id
|
||||||
|
genericObject: 'Chat'
|
||||||
|
pageData:
|
||||||
|
object: 'Chat'
|
||||||
|
container: @el.closest('.content')
|
||||||
|
callback: @load
|
||||||
|
)
|
||||||
|
|
||||||
# active chats
|
delete: (e) =>
|
||||||
# name, email, location/ip, age
|
e.preventDefault()
|
||||||
|
id = $(e.target).closest('.action').data('id')
|
||||||
|
item = App.Chat.find(id)
|
||||||
|
new App.ControllerGenericDestroyConfirm(
|
||||||
|
item: item
|
||||||
|
container: @el.closest('.content')
|
||||||
|
callback: @load
|
||||||
|
)
|
||||||
|
|
||||||
|
widget: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
id = $(e.target).closest('.action').data('id')
|
||||||
|
new Widget(
|
||||||
|
permanent:
|
||||||
|
id: id
|
||||||
|
)
|
||||||
|
|
||||||
# chat history
|
class Widget extends App.ControllerModal
|
||||||
|
events:
|
||||||
|
'change .js-params': 'updateParams'
|
||||||
|
'keyup .js-params': 'updateParams'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@head = 'Widget'
|
||||||
|
@close = true
|
||||||
|
@render()
|
||||||
|
@show()
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
@content = $( App.view('channel/chat_js_widget')(
|
||||||
|
baseurl: window.location.origin
|
||||||
|
))
|
||||||
|
|
||||||
|
onShown: =>
|
||||||
|
@updateParams()
|
||||||
|
|
||||||
|
updateParams: =>
|
||||||
|
console.log('id', @id)
|
||||||
|
|
||||||
|
quote = (value) ->
|
||||||
|
if value.replace
|
||||||
|
value = value.replace('\'', '\\\'')
|
||||||
|
.replace(/\</g, '<')
|
||||||
|
.replace(/\>/g, '>')
|
||||||
|
value
|
||||||
|
params = @formParam(@$('.js-params'))
|
||||||
|
if @permanent
|
||||||
|
for key, value of @permanent
|
||||||
|
params[key] = value
|
||||||
|
paramString = ''
|
||||||
|
for key, value of params
|
||||||
|
if value != ''
|
||||||
|
if paramString != ''
|
||||||
|
paramString += ",\n"
|
||||||
|
if value == 'true' || value == 'false' || _.isNumber(value)
|
||||||
|
paramString += " #{key}: #{value}"
|
||||||
|
else
|
||||||
|
paramString += " #{key}: '#{quote(value)}'"
|
||||||
|
@$('.js-modal-params').html(paramString)
|
||||||
|
|
||||||
App.Config.set( 'Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: App.ChannelChat, role: ['Admin'] }, 'NavBarAdmin' )
|
App.Config.set( 'Chat', { prio: 4000, name: 'Chat', parent: '#channels', target: '#channels/chat', controller: App.ChannelChat, role: ['Admin'] }, 'NavBarAdmin' )
|
||||||
|
|
|
@ -81,7 +81,10 @@ class App.CustomerChat extends App.Controller
|
||||||
|
|
||||||
# play on changes
|
# play on changes
|
||||||
if @lastWaitingChatCount isnt counter
|
if @lastWaitingChatCount isnt counter
|
||||||
@sounds.chat_new.play()
|
|
||||||
|
# do not play sound on initial load
|
||||||
|
if counter > 0 && @lastWaitingChatCount isnt undefined
|
||||||
|
@sounds.chat_new.play()
|
||||||
@lastWaitingChatCount = counter
|
@lastWaitingChatCount = counter
|
||||||
|
|
||||||
# collect chat window messages
|
# collect chat window messages
|
||||||
|
|
16
app/assets/javascripts/app/models/chat.coffee
Normal file
16
app/assets/javascripts/app/models/chat.coffee
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
class App.Chat extends App.Model
|
||||||
|
@configure 'Chat', 'name', 'active', 'public', 'max_queue', 'note'
|
||||||
|
@extend Spine.Model.Ajax
|
||||||
|
@url: @apiPath + '/chats'
|
||||||
|
|
||||||
|
@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: '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 },
|
||||||
|
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||||
|
{ name: 'updated_at', display: 'Updated', tag: 'datetime', readonly: 1 },
|
||||||
|
]
|
|
@ -0,0 +1,66 @@
|
||||||
|
<div class="js-params">
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<div class="input form-group">
|
||||||
|
<div class="formGroup-label">
|
||||||
|
<label for="form-chat-title"><%- @T('Title of the Chat') %></label>
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="form-chat-title" name="title" value="<strong>Chat</strong> with us!">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="input form-group">
|
||||||
|
<div class="formGroup-label">
|
||||||
|
<label for="form-chat-background"><%- @T('Background color') %></label>
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" id="form-chat-background" name="background" value="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<table class="settings-list">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="white-space: nowrap;"><%- @T('Option') %></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="inline-label">
|
||||||
|
<span class="checkbox-replacement checkbox-replacement--inline">
|
||||||
|
<input type="checkbox" name="debug" value="true">
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</span>
|
||||||
|
<%- @T('Enable debugging for implementation.') %>
|
||||||
|
</label>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="inline-label">
|
||||||
|
<span class="checkbox-replacement checkbox-replacement--inline">
|
||||||
|
<input type="checkbox" name="flat" value="true">
|
||||||
|
<%- @Icon('checkbox', 'icon-unchecked') %>
|
||||||
|
<%- @Icon('checkbox-checked', 'icon-checked') %>
|
||||||
|
</span>
|
||||||
|
<%- @T('Flat design.') %>
|
||||||
|
</label>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><%- @T('You need to add the following Java Script code snipped to your web page') %>:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<script id="zammad_form_script" src="<%= @baseurl %>/assets/chat/chat.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
new ZammadChat({({
|
||||||
|
<span class="js-modal-params"></span>
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script></pre>
|
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
<h2><%- @T('Channels') %></h2>
|
||||||
|
|
||||||
|
<% if _.isEmpty(@chats): %>
|
||||||
|
<p><%- @T('You have no configured chat\'s right now.') %></p>
|
||||||
|
<% else: %>
|
||||||
|
<% for chat in @chats: %>
|
||||||
|
<div class="action" data-id="<%- chat.id %>">
|
||||||
|
|
||||||
|
<div class="action-flow action-flow--row">
|
||||||
|
<div class="action-row">
|
||||||
|
<h2><%= chat.name %></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-block action-block--flex">
|
||||||
|
<div class="label"><%- @T('Note') %></div>
|
||||||
|
<%= chat.note %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-block action-block--flex">
|
||||||
|
<div class="label"><%- @T('At a glance') %></div>
|
||||||
|
<%- @T('Sessions last 24 h') %><%= chat.last_24_h %><br>
|
||||||
|
<%- @T('Sessions last week') %><%= chat.last_week %><br>
|
||||||
|
<%- @T('Sessions last month') %><%= chat.last_month %><br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-block action-block--flex">
|
||||||
|
<div class="label"><%- @T('Public') %></div>
|
||||||
|
<%= chat.public %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-controls">
|
||||||
|
<div class="btn btn--danger btn--secondary js-delete"><%- @T('Delete') %></div>
|
||||||
|
<div class="btn js-edit"><%- @T('Edit') %></div>
|
||||||
|
<% if chat.public: %><div class="btn js-widget"><%- @T('Design Widget') %></div><% end %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<a class="btn btn--success js-new"><%- @T('New') %></a>
|
39
app/controllers/chats_controller.rb
Normal file
39
app/controllers/chats_controller.rb
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
class ChatsController < ApplicationController
|
||||||
|
before_action :authentication_check
|
||||||
|
|
||||||
|
def index
|
||||||
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
chat_ids = []
|
||||||
|
assets = {}
|
||||||
|
Chat.order(:id).each {|chat|
|
||||||
|
chat_ids.push chat.id
|
||||||
|
assets = chat.assets(assets)
|
||||||
|
}
|
||||||
|
render json: {
|
||||||
|
chat_ids: chat_ids,
|
||||||
|
assets: assets,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
model_show_render(Chat, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
model_create_render(Chat, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
model_update_render(Chat, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
model_destory_render(Chat, params)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,8 +1,7 @@
|
||||||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
class Chat < ApplicationModel
|
class Chat < ApplicationModel
|
||||||
has_many :chat_topics
|
validates :name, presence: true
|
||||||
validates :name, presence: true
|
|
||||||
|
|
||||||
def customer_state(session_id = nil)
|
def customer_state(session_id = nil)
|
||||||
return { state: 'chat_disabled' } if !Setting.get('chat')
|
return { state: 'chat_disabled' } if !Setting.get('chat')
|
||||||
|
@ -68,6 +67,7 @@ class Chat < ApplicationModel
|
||||||
waiting_chat_count: waiting_chat_count,
|
waiting_chat_count: waiting_chat_count,
|
||||||
running_chat_count: running_chat_count,
|
running_chat_count: running_chat_count,
|
||||||
active_sessions: Chat::Session.active_chats_by_user_id(user_id),
|
active_sessions: Chat::Session.active_chats_by_user_id(user_id),
|
||||||
|
active_agents: active_agents,
|
||||||
seads_available: seads_available,
|
seads_available: seads_available,
|
||||||
seads_total: seads_total,
|
seads_total: seads_total,
|
||||||
active: Chat::Agent.state(user_id)
|
active: Chat::Agent.state(user_id)
|
||||||
|
@ -94,6 +94,10 @@ class Chat < ApplicationModel
|
||||||
agents
|
agents
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.active_agents(diff = 2.minutes)
|
||||||
|
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).count
|
||||||
|
end
|
||||||
|
|
||||||
def self.seads_total(diff = 2.minutes)
|
def self.seads_total(diff = 2.minutes)
|
||||||
total = 0
|
total = 0
|
||||||
available_agents(diff).each {|_user_id, concurrent|
|
available_agents(diff).each {|_user_id, concurrent|
|
||||||
|
|
11
config/routes/chat.rb
Normal file
11
config/routes/chat.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
Zammad::Application.routes.draw do
|
||||||
|
api_path = Rails.configuration.api_path
|
||||||
|
|
||||||
|
# groups
|
||||||
|
match api_path + '/chats', to: 'chats#index', via: :get
|
||||||
|
match api_path + '/chats/:id', to: 'chats#show', via: :get
|
||||||
|
match api_path + '/chats', to: 'chats#create', via: :post
|
||||||
|
match api_path + '/chats/:id', to: 'chats#update', via: :put
|
||||||
|
match api_path + '/chats/:id', to: 'chats#destroy', via: :delete
|
||||||
|
|
||||||
|
end
|
6
db/migrate/20151115000001_update2_chat.rb
Normal file
6
db/migrate/20151115000001_update2_chat.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class Update2Chat < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
add_column :chats, :public, :boolean, null: false, default: false
|
||||||
|
drop_table :chat_topics
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue