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
|
||||
|
||||
@tabs = [
|
||||
{
|
||||
name: 'Chat Channels',
|
||||
target: 'channels',
|
||||
controller: App.ChannelChatOverview
|
||||
},
|
||||
{
|
||||
name: 'Settings',
|
||||
target: 'setting',
|
||||
|
@ -15,28 +20,125 @@ class App.ChannelChat extends App.ControllerTabs
|
|||
|
||||
@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
|
||||
# sales - en / authentication needed
|
||||
# sales - de / authentication needed
|
||||
load: =>
|
||||
@startLoading()
|
||||
@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
|
||||
# channes I'm work for
|
||||
@html App.view('channel/chat_overview')(
|
||||
chats: chats
|
||||
)
|
||||
|
||||
# x sales - de / greeting
|
||||
# o sales - en / greeting
|
||||
new: (e) =>
|
||||
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
|
||||
# name, email, location/ip, age
|
||||
delete: (e) =>
|
||||
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' )
|
||||
|
|
|
@ -81,6 +81,9 @@ class App.CustomerChat extends App.Controller
|
|||
|
||||
# play on changes
|
||||
if @lastWaitingChatCount isnt counter
|
||||
|
||||
# do not play sound on initial load
|
||||
if counter > 0 && @lastWaitingChatCount isnt undefined
|
||||
@sounds.chat_new.play()
|
||||
@lastWaitingChatCount = counter
|
||||
|
||||
|
|
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,7 +1,6 @@
|
|||
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
class Chat < ApplicationModel
|
||||
has_many :chat_topics
|
||||
validates :name, presence: true
|
||||
|
||||
def customer_state(session_id = nil)
|
||||
|
@ -68,6 +67,7 @@ class Chat < ApplicationModel
|
|||
waiting_chat_count: waiting_chat_count,
|
||||
running_chat_count: running_chat_count,
|
||||
active_sessions: Chat::Session.active_chats_by_user_id(user_id),
|
||||
active_agents: active_agents,
|
||||
seads_available: seads_available,
|
||||
seads_total: seads_total,
|
||||
active: Chat::Agent.state(user_id)
|
||||
|
@ -94,6 +94,10 @@ class Chat < ApplicationModel
|
|||
agents
|
||||
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)
|
||||
total = 0
|
||||
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