Merge branch 'develop' of github.com:martini/zammad into develop

This commit is contained in:
Felix Niklas 2015-11-16 11:46:53 +01:00
commit d970c08306
9 changed files with 307 additions and 16 deletions

View file

@ -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, '&lt;')
.replace(/\>/g, '&gt;')
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' )

View file

@ -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

View 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 },
]

View file

@ -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="&lt;strong&gt;Chat&lt;/strong&gt; 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>
&lt;script id="zammad_form_script" src="<%= @baseurl %>/assets/chat/chat.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
$(function() {
new ZammadChat({({
<span class="js-modal-params"></span>
});
});
&lt;/script&gt;</pre>

View file

@ -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>

View 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

View file

@ -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
View 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

View 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