chat: add waiting screen, outsource agent view, add basic socket communication
This commit is contained in:
parent
d67bae2005
commit
806ffb70c7
9 changed files with 489 additions and 98 deletions
|
@ -5,10 +5,11 @@ do($ = window.jQuery, window) ->
|
||||||
|
|
||||||
defaults:
|
defaults:
|
||||||
invitationPhrase: '<strong>Chat</strong> with us!'
|
invitationPhrase: '<strong>Chat</strong> with us!'
|
||||||
agentPhrase: '%%agent%% is helping you'
|
agentPhrase: ' is helping you'
|
||||||
show: true
|
show: true
|
||||||
target: $('body')
|
target: $('body')
|
||||||
|
|
||||||
|
_messageCount: 0
|
||||||
isOpen: false
|
isOpen: false
|
||||||
blinkOnlineInterval: null
|
blinkOnlineInterval: null
|
||||||
stopBlinOnlineStateTimeout: null
|
stopBlinOnlineStateTimeout: null
|
||||||
|
@ -25,15 +26,20 @@ do($ = window.jQuery, window) ->
|
||||||
'Connection re-established': 'Connection re-established'
|
'Connection re-established': 'Connection re-established'
|
||||||
'Today': 'Today'
|
'Today': 'Today'
|
||||||
|
|
||||||
T: (string) ->
|
T: (string) =>
|
||||||
return @strings[string]
|
return @strings[string]
|
||||||
|
|
||||||
view: (name) ->
|
view: (name) =>
|
||||||
return window.zammadChatTemplates[name]
|
return (options) =>
|
||||||
|
if !options
|
||||||
|
options = {}
|
||||||
|
|
||||||
|
options.T = @T
|
||||||
|
return window.zammadChatTemplates[name](options)
|
||||||
|
|
||||||
constructor: (el, options) ->
|
constructor: (el, options) ->
|
||||||
@options = $.extend {}, @defaults, options
|
@options = $.extend {}, @defaults, options
|
||||||
@el = $(@view('chat')())
|
@el = $(@view('chat')(@options))
|
||||||
@options.target.append @el
|
@options.target.append @el
|
||||||
|
|
||||||
@setAgentOnlineState @isOnline
|
@setAgentOnlineState @isOnline
|
||||||
|
@ -46,19 +52,18 @@ do($ = window.jQuery, window) ->
|
||||||
).autoGrow { extraLine: false }
|
).autoGrow { extraLine: false }
|
||||||
|
|
||||||
if !window.WebSocket
|
if !window.WebSocket
|
||||||
console.log('no websockets available')
|
console.log('Zammad Chat: Browser not supported')
|
||||||
return
|
return
|
||||||
|
|
||||||
zammad_host = 'ws://localhost:6042'
|
zammad_host = 'ws://localhost:6042'
|
||||||
@ws = new window.WebSocket(zammad_host)
|
@ws = new window.WebSocket(zammad_host)
|
||||||
console.log("connecting ws #{zammad_host}")
|
console.log("Connecting to #{zammad_host}")
|
||||||
|
|
||||||
@ws.onopen = =>
|
@ws.onopen = =>
|
||||||
console.log('ws connected')
|
console.log('ws connected')
|
||||||
|
@send "chat_status"
|
||||||
|
|
||||||
@ws.onmessage = (e) =>
|
@ws.onmessage = @onWebSocketMessage
|
||||||
pipe = JSON.parse( e.data )
|
|
||||||
console.log 'debug', 'ws:onmessage', pipe
|
|
||||||
|
|
||||||
@ws.onclose = (e) =>
|
@ws.onclose = (e) =>
|
||||||
console.log 'debug', 'close websocket connection'
|
console.log 'debug', 'close websocket connection'
|
||||||
|
@ -71,6 +76,44 @@ do($ = window.jQuery, window) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@sendMessage()
|
@sendMessage()
|
||||||
|
|
||||||
|
send: (action, data) =>
|
||||||
|
pipe = JSON.stringify
|
||||||
|
action: action
|
||||||
|
data: data
|
||||||
|
|
||||||
|
@ws.send pipe
|
||||||
|
|
||||||
|
onWebSocketMessage: (e) =>
|
||||||
|
pipe = JSON.parse( e.data )
|
||||||
|
console.log 'debug', 'ws:onmessage', pipe
|
||||||
|
|
||||||
|
switch pipe.action
|
||||||
|
when 'message'
|
||||||
|
@receiveMessage pipe.data
|
||||||
|
when 'typing_start'
|
||||||
|
@onAgentTypingStart()
|
||||||
|
when 'typing_end'
|
||||||
|
@onAgentTypingEnd()
|
||||||
|
when 'chat_init'
|
||||||
|
switch pipe.data.state
|
||||||
|
when 'ok'
|
||||||
|
@onConnectionEstablished pipe.data.agent
|
||||||
|
when 'queue'
|
||||||
|
@onQueue pipe.data.position
|
||||||
|
when 'chat_status'
|
||||||
|
switch pipe.data.state
|
||||||
|
when 'ok'
|
||||||
|
@onReady()
|
||||||
|
when 'offline'
|
||||||
|
console.log 'Zammad Chat: No agent online'
|
||||||
|
when 'chat_disabled'
|
||||||
|
console.log 'Zammad Chat: Chat is disabled'
|
||||||
|
when 'no_seats_available'
|
||||||
|
console.log 'Zammad Chat: Too many clients in queue. Clients in queue: ', pipe.data.queue
|
||||||
|
|
||||||
|
onReady: =>
|
||||||
|
@show() if @options.show
|
||||||
|
|
||||||
onInput: =>
|
onInput: =>
|
||||||
# remove unread-state from messages
|
# remove unread-state from messages
|
||||||
@el.find('.zammad-chat-message--unread')
|
@el.find('.zammad-chat-message--unread')
|
||||||
|
@ -86,10 +129,12 @@ do($ = window.jQuery, window) ->
|
||||||
onTypingStart: ->
|
onTypingStart: ->
|
||||||
# send typing start event
|
# send typing start event
|
||||||
@isTyping = true
|
@isTyping = true
|
||||||
|
@send 'typing_start'
|
||||||
|
|
||||||
onTypingEnd: =>
|
onTypingEnd: =>
|
||||||
# send typing end event
|
# send typing end event
|
||||||
@isTyping = false
|
@isTyping = false
|
||||||
|
@send 'typing_end'
|
||||||
|
|
||||||
onSubmit: (event) =>
|
onSubmit: (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -98,28 +143,35 @@ do($ = window.jQuery, window) ->
|
||||||
sendMessage: ->
|
sendMessage: ->
|
||||||
message = @el.find('.zammad-chat-input').val()
|
message = @el.find('.zammad-chat-input').val()
|
||||||
|
|
||||||
if message
|
if !message
|
||||||
messageElement = @view('message')
|
return
|
||||||
message: message
|
|
||||||
from: 'customer'
|
|
||||||
|
|
||||||
@maybeAddTimestamp()
|
messageElement = @view('message')
|
||||||
|
message: message
|
||||||
|
from: 'customer'
|
||||||
|
id: @_messageCount++
|
||||||
|
|
||||||
# add message before message typing loader
|
@maybeAddTimestamp()
|
||||||
if @el.find('.zammad-chat-message--typing').size()
|
|
||||||
@lastAddedType = 'typing-placeholder'
|
|
||||||
@el.find('.zammad-chat-message--typing').before messageElement
|
|
||||||
else
|
|
||||||
@lastAddedType = 'message--customer'
|
|
||||||
@el.find('.zammad-chat-body').append messageElement
|
|
||||||
|
|
||||||
@el.find('.zammad-chat-input').val('')
|
# add message before message typing loader
|
||||||
@scrollToBottom()
|
if @el.find('.zammad-chat-message--typing').size()
|
||||||
|
@lastAddedType = 'typing-placeholder'
|
||||||
|
@el.find('.zammad-chat-message--typing').before messageElement
|
||||||
|
else
|
||||||
|
@lastAddedType = 'message--customer'
|
||||||
|
@el.find('.zammad-chat-body').append messageElement
|
||||||
|
|
||||||
@isTyping = false
|
@el.find('.zammad-chat-input').val('')
|
||||||
# send message event
|
@scrollToBottom()
|
||||||
|
|
||||||
receiveMessage: (message) =>
|
@isTyping = false
|
||||||
|
|
||||||
|
# send message event
|
||||||
|
@send 'message',
|
||||||
|
body: message
|
||||||
|
id: @_messageCount
|
||||||
|
|
||||||
|
receiveMessage: (data) =>
|
||||||
# hide writing indicator
|
# hide writing indicator
|
||||||
@onAgentTypingEnd()
|
@onAgentTypingEnd()
|
||||||
|
|
||||||
|
@ -128,7 +180,8 @@ do($ = window.jQuery, window) ->
|
||||||
@lastAddedType = 'message--agent'
|
@lastAddedType = 'message--agent'
|
||||||
unread = document.hidden ? " zammad-chat-message--unread" : ""
|
unread = document.hidden ? " zammad-chat-message--unread" : ""
|
||||||
@el.find('.zammad-chat-body').append @view('message')
|
@el.find('.zammad-chat-body').append @view('message')
|
||||||
message: message
|
message: data.body
|
||||||
|
id: data.id
|
||||||
from: 'agent'
|
from: 'agent'
|
||||||
@scrollToBottom()
|
@scrollToBottom()
|
||||||
|
|
||||||
|
@ -136,15 +189,18 @@ do($ = window.jQuery, window) ->
|
||||||
if @isOpen then @close() else @open()
|
if @isOpen then @close() else @open()
|
||||||
|
|
||||||
open: ->
|
open: ->
|
||||||
|
@showLoader()
|
||||||
|
|
||||||
@el
|
@el
|
||||||
.addClass('zammad-chat-is-open')
|
.addClass('zammad-chat-is-open')
|
||||||
.animate { bottom: 0 }, 500, @onOpenAnimationEnd
|
.animate { bottom: 0 }, 500, @onOpenAnimationEnd
|
||||||
|
|
||||||
onOpenAnimationEnd: =>
|
onOpenAnimationEnd: =>
|
||||||
@isOpen = true
|
@isOpen = true
|
||||||
setTimeout @onConnectionEstablished, 1180
|
#setTimeout @onQueue, 1180
|
||||||
setTimeout @onAgentTypingStart, 2000
|
# setTimeout @onConnectionEstablished, 1180
|
||||||
setTimeout @receiveMessage, 5000, "Hello! How can I help you?"
|
# setTimeout @onAgentTypingStart, 2000
|
||||||
|
# setTimeout @receiveMessage, 5000, "Hello! How can I help you?"
|
||||||
@connect()
|
@connect()
|
||||||
|
|
||||||
close: ->
|
close: ->
|
||||||
|
@ -166,8 +222,15 @@ do($ = window.jQuery, window) ->
|
||||||
|
|
||||||
@el.css 'bottom', -remainerHeight
|
@el.css 'bottom', -remainerHeight
|
||||||
|
|
||||||
|
onQueue: (position) =>
|
||||||
|
console.log "onQueue", position
|
||||||
|
@inQueue = true
|
||||||
|
|
||||||
|
@el.find('.zammad-chat-body').html @view('waiting')
|
||||||
|
position: position
|
||||||
|
|
||||||
onAgentTypingStart: =>
|
onAgentTypingStart: =>
|
||||||
# never display two loaders
|
# never display two typing indicators
|
||||||
return if @el.find('.zammad-chat-message--typing').size()
|
return if @el.find('.zammad-chat-message--typing').size()
|
||||||
|
|
||||||
@maybeAddTimestamp()
|
@maybeAddTimestamp()
|
||||||
|
@ -212,7 +275,7 @@ do($ = window.jQuery, window) ->
|
||||||
@el.find('.zammad-chat-body').scrollTop($('.zammad-chat-body').prop('scrollHeight'))
|
@el.find('.zammad-chat-body').scrollTop($('.zammad-chat-body').prop('scrollHeight'))
|
||||||
|
|
||||||
connect: ->
|
connect: ->
|
||||||
|
@send('chat_init')
|
||||||
|
|
||||||
reconnect: =>
|
reconnect: =>
|
||||||
# set status to connecting
|
# set status to connecting
|
||||||
|
@ -227,17 +290,26 @@ do($ = window.jQuery, window) ->
|
||||||
@addStatus @T('Connection re-established')
|
@addStatus @T('Connection re-established')
|
||||||
|
|
||||||
disconnect: ->
|
disconnect: ->
|
||||||
@el.find('.zammad-chat-loader').removeClass('zammad-chat-is-hidden');
|
@showLoader()
|
||||||
@el.find('.zammad-chat-welcome').removeClass('zammad-chat-is-hidden');
|
@el.find('.zammad-chat-welcome').removeClass('zammad-chat-is-hidden')
|
||||||
@el.find('.zammad-chat-agent').addClass('zammad-chat-is-hidden');
|
@el.find('.zammad-chat-agent').addClass('zammad-chat-is-hidden')
|
||||||
@el.find('.zammad-chat-agent-status').addClass('zammad-chat-is-hidden');
|
@el.find('.zammad-chat-agent-status').addClass('zammad-chat-is-hidden')
|
||||||
|
|
||||||
onConnectionEstablished: =>
|
onConnectionEstablished: (agent) =>
|
||||||
@el.find('.zammad-chat-loader').addClass('zammad-chat-is-hidden');
|
@inQueue = false
|
||||||
@el.find('.zammad-chat-welcome').addClass('zammad-chat-is-hidden');
|
@agent = agent
|
||||||
@el.find('.zammad-chat-agent').removeClass('zammad-chat-is-hidden');
|
|
||||||
@el.find('.zammad-chat-agent-status').removeClass('zammad-chat-is-hidden');
|
@el.find('.zammad-chat-agent').html @view('agent')
|
||||||
@el.find('.zammad-chat-input').focus();
|
agent: agent
|
||||||
|
|
||||||
|
@el.find('.zammad-chat-body').empty()
|
||||||
|
@el.find('.zammad-chat-welcome').addClass('zammad-chat-is-hidden')
|
||||||
|
@el.find('.zammad-chat-agent').removeClass('zammad-chat-is-hidden')
|
||||||
|
@el.find('.zammad-chat-agent-status').removeClass('zammad-chat-is-hidden')
|
||||||
|
@el.find('.zammad-chat-input').focus()
|
||||||
|
|
||||||
|
showLoader: ->
|
||||||
|
@el.find('.zammad-chat-body').html @view('loader')()
|
||||||
|
|
||||||
setAgentOnlineState: (state) =>
|
setAgentOnlineState: (state) =>
|
||||||
@isOnline = state
|
@isOnline = state
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
if (!window.zammadChatTemplates) {
|
if (!window.zammadChatTemplates) {
|
||||||
window.zammadChatTemplates = {};
|
window.zammadChatTemplates = {};
|
||||||
}
|
}
|
||||||
window.zammadChatTemplates["chat"] = function (__obj) {
|
window.zammadChatTemplates["agent"] = function (__obj) {
|
||||||
if (!__obj) __obj = {};
|
if (!__obj) __obj = {};
|
||||||
var __out = [], __capture = function(callback) {
|
var __out = [], __capture = function(callback) {
|
||||||
var out = __out, result;
|
var out = __out, result;
|
||||||
|
@ -40,7 +40,19 @@ window.zammadChatTemplates["chat"] = function (__obj) {
|
||||||
}
|
}
|
||||||
(function() {
|
(function() {
|
||||||
(function() {
|
(function() {
|
||||||
__out.push('<div class="zammad-chat">\n <div class="zammad-chat-header">\n <div class="zammad-chat-header-controls">\n <span class="zammad-chat-agent-status zammad-chat-is-hidden" data-status="online">Online</span>\n <span class="zammad-chat-toggle">\n <svg class="zammad-chat-toggle-icon-open" viewBox="0 0 13 7"><path d="M10.807 7l1.4-1.428-5-4.9L6.5-.02l-.7.7-4.9 4.9 1.414 1.413L6.5 2.886 10.807 7z" fill-rule="evenodd"/></svg>\n <svg class="zammad-chat-toggle-icon-close" viewBox="0 0 13 7"><path d="M6.554 4.214L2.246 0l-1.4 1.428 5 4.9.708.693.7-.7 4.9-4.9L10.74.008 6.553 4.214z" fill-rule="evenodd"/></svg>\n </span>\n </div>\n <div class="zammad-chat-agent zammad-chat-is-hidden">\n <img class="zammad-chat-agent-avatar" src="https://s3.amazonaws.com/uifaces/faces/twitter/joshaustin/128.jpg">\n <span class="zammad-chat-agent-sentence">\n <span class="zammad-chat-agent-name">Adam</span> is helping you.\n </span>\n </div>\n <div class="zammad-chat-welcome">\n <svg class="zammad-chat-icon" viewBox="0 0 24 24"><path d="M2 5C2 4 3 3 4 3h16c1 0 2 1 2 2v10C22 16 21 17 20 17H4C3 17 2 16 2 15V5zM12 17l6 4v-4h-6z" fill-rule="evenodd"/></svg>\n <span class="zammad-chat-welcome-text"><strong>Chat</strong> with us!</span>\n </div>\n </div>\n <div class="zammad-chat-loader">\n <span class="zammad-chat-loading-animation">\n <span class="zammad-chat-loading-circle"></span>\n <span class="zammad-chat-loading-circle"></span>\n <span class="zammad-chat-loading-circle"></span>\n </span>\n <span class="zammad-chat-loader-text">Connecting</span>\n </div>\n <div class="zammad-chat-body"></div>\n <form class="zammad-chat-controls">\n <textarea class="zammad-chat-input" rows="1" placeholder="Compose your message..."></textarea>\n <button type="submit" class="zammad-chat-send">Send</button>\n </form>\n</div>');
|
__out.push('<img class="zammad-chat-agent-avatar" src="');
|
||||||
|
|
||||||
|
__out.push(__sanitize(this.agent.avatar));
|
||||||
|
|
||||||
|
__out.push('">\n<span class="zammad-chat-agent-sentence">\n <span class="zammad-chat-agent-name">');
|
||||||
|
|
||||||
|
__out.push(__sanitize(this.agent.name));
|
||||||
|
|
||||||
|
__out.push('</span> ');
|
||||||
|
|
||||||
|
__out.push(this.agentPhrase);
|
||||||
|
|
||||||
|
__out.push('\n</span>');
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
||||||
|
@ -56,11 +68,13 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
ZammadChat = (function() {
|
ZammadChat = (function() {
|
||||||
ZammadChat.prototype.defaults = {
|
ZammadChat.prototype.defaults = {
|
||||||
invitationPhrase: '<strong>Chat</strong> with us!',
|
invitationPhrase: '<strong>Chat</strong> with us!',
|
||||||
agentPhrase: '%%agent%% is helping you',
|
agentPhrase: ' is helping you',
|
||||||
show: true,
|
show: true,
|
||||||
target: $('body')
|
target: $('body')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ZammadChat.prototype._messageCount = 0;
|
||||||
|
|
||||||
ZammadChat.prototype.isOpen = false;
|
ZammadChat.prototype.isOpen = false;
|
||||||
|
|
||||||
ZammadChat.prototype.blinkOnlineInterval = null;
|
ZammadChat.prototype.blinkOnlineInterval = null;
|
||||||
|
@ -92,7 +106,15 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.view = function(name) {
|
ZammadChat.prototype.view = function(name) {
|
||||||
return window.zammadChatTemplates[name];
|
return (function(_this) {
|
||||||
|
return function(options) {
|
||||||
|
if (!options) {
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
options.T = _this.T;
|
||||||
|
return window.zammadChatTemplates[name](options);
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
function ZammadChat(el, options) {
|
function ZammadChat(el, options) {
|
||||||
|
@ -102,6 +124,7 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
this.reconnect = bind(this.reconnect, this);
|
this.reconnect = bind(this.reconnect, this);
|
||||||
this.onAgentTypingEnd = bind(this.onAgentTypingEnd, this);
|
this.onAgentTypingEnd = bind(this.onAgentTypingEnd, this);
|
||||||
this.onAgentTypingStart = bind(this.onAgentTypingStart, this);
|
this.onAgentTypingStart = bind(this.onAgentTypingStart, this);
|
||||||
|
this.onQueue = bind(this.onQueue, this);
|
||||||
this.onCloseAnimationEnd = bind(this.onCloseAnimationEnd, this);
|
this.onCloseAnimationEnd = bind(this.onCloseAnimationEnd, this);
|
||||||
this.onOpenAnimationEnd = bind(this.onOpenAnimationEnd, this);
|
this.onOpenAnimationEnd = bind(this.onOpenAnimationEnd, this);
|
||||||
this.toggle = bind(this.toggle, this);
|
this.toggle = bind(this.toggle, this);
|
||||||
|
@ -109,9 +132,15 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
this.onSubmit = bind(this.onSubmit, this);
|
this.onSubmit = bind(this.onSubmit, this);
|
||||||
this.onTypingEnd = bind(this.onTypingEnd, this);
|
this.onTypingEnd = bind(this.onTypingEnd, this);
|
||||||
this.onInput = bind(this.onInput, this);
|
this.onInput = bind(this.onInput, this);
|
||||||
|
this.onReady = bind(this.onReady, this);
|
||||||
|
this.onWebSocketMessage = bind(this.onWebSocketMessage, this);
|
||||||
|
this.send = bind(this.send, this);
|
||||||
this.checkForEnter = bind(this.checkForEnter, this);
|
this.checkForEnter = bind(this.checkForEnter, this);
|
||||||
|
this.view = bind(this.view, this);
|
||||||
|
this.T = bind(this.T, this);
|
||||||
|
var zammad_host;
|
||||||
this.options = $.extend({}, this.defaults, options);
|
this.options = $.extend({}, this.defaults, options);
|
||||||
this.el = $(this.view('chat')());
|
this.el = $(this.view('chat')(this.options));
|
||||||
this.options.target.append(this.el);
|
this.options.target.append(this.el);
|
||||||
this.setAgentOnlineState(this.isOnline);
|
this.setAgentOnlineState(this.isOnline);
|
||||||
this.el.find('.zammad-chat-header').click(this.toggle);
|
this.el.find('.zammad-chat-header').click(this.toggle);
|
||||||
|
@ -122,6 +151,30 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
}).autoGrow({
|
}).autoGrow({
|
||||||
extraLine: false
|
extraLine: false
|
||||||
});
|
});
|
||||||
|
if (!window.WebSocket) {
|
||||||
|
console.log('Zammad Chat: Browser not supported');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
zammad_host = 'ws://localhost:6042';
|
||||||
|
this.ws = new window.WebSocket(zammad_host);
|
||||||
|
console.log("Connecting to " + zammad_host);
|
||||||
|
this.ws.onopen = (function(_this) {
|
||||||
|
return function() {
|
||||||
|
console.log('ws connected');
|
||||||
|
return _this.send("chat_status");
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
this.ws.onmessage = this.onWebSocketMessage;
|
||||||
|
this.ws.onclose = (function(_this) {
|
||||||
|
return function(e) {
|
||||||
|
return console.log('debug', 'close websocket connection');
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
|
this.ws.onerror = (function(_this) {
|
||||||
|
return function(e) {
|
||||||
|
return console.log('debug', 'ws:onerror', e);
|
||||||
|
};
|
||||||
|
})(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZammadChat.prototype.checkForEnter = function(event) {
|
ZammadChat.prototype.checkForEnter = function(event) {
|
||||||
|
@ -131,6 +184,54 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ZammadChat.prototype.send = function(action, data) {
|
||||||
|
var pipe;
|
||||||
|
pipe = JSON.stringify({
|
||||||
|
action: action,
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
return this.ws.send(pipe);
|
||||||
|
};
|
||||||
|
|
||||||
|
ZammadChat.prototype.onWebSocketMessage = function(e) {
|
||||||
|
var pipe;
|
||||||
|
pipe = JSON.parse(e.data);
|
||||||
|
console.log('debug', 'ws:onmessage', pipe);
|
||||||
|
switch (pipe.action) {
|
||||||
|
case 'message':
|
||||||
|
return this.receiveMessage(pipe.data);
|
||||||
|
case 'typing_start':
|
||||||
|
return this.onAgentTypingStart();
|
||||||
|
case 'typing_end':
|
||||||
|
return this.onAgentTypingEnd();
|
||||||
|
case 'chat_init':
|
||||||
|
switch (pipe.data.state) {
|
||||||
|
case 'ok':
|
||||||
|
return this.onConnectionEstablished(pipe.data.agent);
|
||||||
|
case 'queue':
|
||||||
|
return this.onQueue(pipe.data.position);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'chat_status':
|
||||||
|
switch (pipe.data.state) {
|
||||||
|
case 'ok':
|
||||||
|
return this.onReady();
|
||||||
|
case 'offline':
|
||||||
|
return console.log('Zammad Chat: No agent online');
|
||||||
|
case 'chat_disabled':
|
||||||
|
return console.log('Zammad Chat: Chat is disabled');
|
||||||
|
case 'no_seats_available':
|
||||||
|
return console.log('Zammad Chat: Too many clients in queue. Clients in queue: ', pipe.data.queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ZammadChat.prototype.onReady = function() {
|
||||||
|
if (this.options.show) {
|
||||||
|
return this.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.onInput = function() {
|
ZammadChat.prototype.onInput = function() {
|
||||||
this.el.find('.zammad-chat-message--unread').removeClass('zammad-chat-message--unread');
|
this.el.find('.zammad-chat-message--unread').removeClass('zammad-chat-message--unread');
|
||||||
if (this.inputTimeout) {
|
if (this.inputTimeout) {
|
||||||
|
@ -143,11 +244,13 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.onTypingStart = function() {
|
ZammadChat.prototype.onTypingStart = function() {
|
||||||
return this.isTyping = true;
|
this.isTyping = true;
|
||||||
|
return this.send('typing_start');
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.onTypingEnd = function() {
|
ZammadChat.prototype.onTypingEnd = function() {
|
||||||
return this.isTyping = false;
|
this.isTyping = false;
|
||||||
|
return this.send('typing_end');
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.onSubmit = function(event) {
|
ZammadChat.prototype.onSubmit = function(event) {
|
||||||
|
@ -158,26 +261,32 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
ZammadChat.prototype.sendMessage = function() {
|
ZammadChat.prototype.sendMessage = function() {
|
||||||
var message, messageElement;
|
var message, messageElement;
|
||||||
message = this.el.find('.zammad-chat-input').val();
|
message = this.el.find('.zammad-chat-input').val();
|
||||||
if (message) {
|
if (!message) {
|
||||||
messageElement = this.view('message')({
|
return;
|
||||||
message: message,
|
|
||||||
from: 'customer'
|
|
||||||
});
|
|
||||||
this.maybeAddTimestamp();
|
|
||||||
if (this.el.find('.zammad-chat-message--typing').size()) {
|
|
||||||
this.lastAddedType = 'typing-placeholder';
|
|
||||||
this.el.find('.zammad-chat-message--typing').before(messageElement);
|
|
||||||
} else {
|
|
||||||
this.lastAddedType = 'message--customer';
|
|
||||||
this.el.find('.zammad-chat-body').append(messageElement);
|
|
||||||
}
|
|
||||||
this.el.find('.zammad-chat-input').val('');
|
|
||||||
this.scrollToBottom();
|
|
||||||
return this.isTyping = false;
|
|
||||||
}
|
}
|
||||||
|
messageElement = this.view('message')({
|
||||||
|
message: message,
|
||||||
|
from: 'customer',
|
||||||
|
id: this._messageCount++
|
||||||
|
});
|
||||||
|
this.maybeAddTimestamp();
|
||||||
|
if (this.el.find('.zammad-chat-message--typing').size()) {
|
||||||
|
this.lastAddedType = 'typing-placeholder';
|
||||||
|
this.el.find('.zammad-chat-message--typing').before(messageElement);
|
||||||
|
} else {
|
||||||
|
this.lastAddedType = 'message--customer';
|
||||||
|
this.el.find('.zammad-chat-body').append(messageElement);
|
||||||
|
}
|
||||||
|
this.el.find('.zammad-chat-input').val('');
|
||||||
|
this.scrollToBottom();
|
||||||
|
this.isTyping = false;
|
||||||
|
return this.send('message', {
|
||||||
|
body: message,
|
||||||
|
id: this._messageCount
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.receiveMessage = function(message) {
|
ZammadChat.prototype.receiveMessage = function(data) {
|
||||||
var ref, unread;
|
var ref, unread;
|
||||||
this.onAgentTypingEnd();
|
this.onAgentTypingEnd();
|
||||||
this.maybeAddTimestamp();
|
this.maybeAddTimestamp();
|
||||||
|
@ -186,7 +295,8 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
" zammad-chat-message--unread": ""
|
" zammad-chat-message--unread": ""
|
||||||
};
|
};
|
||||||
this.el.find('.zammad-chat-body').append(this.view('message')({
|
this.el.find('.zammad-chat-body').append(this.view('message')({
|
||||||
message: message,
|
message: data.body,
|
||||||
|
id: data.id,
|
||||||
from: 'agent'
|
from: 'agent'
|
||||||
}));
|
}));
|
||||||
return this.scrollToBottom();
|
return this.scrollToBottom();
|
||||||
|
@ -201,6 +311,7 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.open = function() {
|
ZammadChat.prototype.open = function() {
|
||||||
|
this.showLoader();
|
||||||
return this.el.addClass('zammad-chat-is-open').animate({
|
return this.el.addClass('zammad-chat-is-open').animate({
|
||||||
bottom: 0
|
bottom: 0
|
||||||
}, 500, this.onOpenAnimationEnd);
|
}, 500, this.onOpenAnimationEnd);
|
||||||
|
@ -208,9 +319,6 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
|
|
||||||
ZammadChat.prototype.onOpenAnimationEnd = function() {
|
ZammadChat.prototype.onOpenAnimationEnd = function() {
|
||||||
this.isOpen = true;
|
this.isOpen = true;
|
||||||
setTimeout(this.onConnectionEstablished, 1180);
|
|
||||||
setTimeout(this.onAgentTypingStart, 2000);
|
|
||||||
setTimeout(this.receiveMessage, 5000, "Hello! How can I help you?");
|
|
||||||
return this.connect();
|
return this.connect();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -239,6 +347,14 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
return this.el.css('bottom', -remainerHeight);
|
return this.el.css('bottom', -remainerHeight);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ZammadChat.prototype.onQueue = function(position) {
|
||||||
|
console.log("onQueue", position);
|
||||||
|
this.inQueue = true;
|
||||||
|
return this.el.find('.zammad-chat-body').html(this.view('waiting')({
|
||||||
|
position: position
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.onAgentTypingStart = function() {
|
ZammadChat.prototype.onAgentTypingStart = function() {
|
||||||
if (this.el.find('.zammad-chat-message--typing').size()) {
|
if (this.el.find('.zammad-chat-message--typing').size()) {
|
||||||
return;
|
return;
|
||||||
|
@ -287,7 +403,9 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
return this.el.find('.zammad-chat-body').scrollTop($('.zammad-chat-body').prop('scrollHeight'));
|
return this.el.find('.zammad-chat-body').scrollTop($('.zammad-chat-body').prop('scrollHeight'));
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.connect = function() {};
|
ZammadChat.prototype.connect = function() {
|
||||||
|
return this.send('chat_init');
|
||||||
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.reconnect = function() {
|
ZammadChat.prototype.reconnect = function() {
|
||||||
this.lastAddedType = 'status';
|
this.lastAddedType = 'status';
|
||||||
|
@ -302,20 +420,29 @@ var bind = function(fn, me){ return function(){ return fn.apply(me, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.disconnect = function() {
|
ZammadChat.prototype.disconnect = function() {
|
||||||
this.el.find('.zammad-chat-loader').removeClass('zammad-chat-is-hidden');
|
this.showLoader();
|
||||||
this.el.find('.zammad-chat-welcome').removeClass('zammad-chat-is-hidden');
|
this.el.find('.zammad-chat-welcome').removeClass('zammad-chat-is-hidden');
|
||||||
this.el.find('.zammad-chat-agent').addClass('zammad-chat-is-hidden');
|
this.el.find('.zammad-chat-agent').addClass('zammad-chat-is-hidden');
|
||||||
return this.el.find('.zammad-chat-agent-status').addClass('zammad-chat-is-hidden');
|
return this.el.find('.zammad-chat-agent-status').addClass('zammad-chat-is-hidden');
|
||||||
};
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.onConnectionEstablished = function() {
|
ZammadChat.prototype.onConnectionEstablished = function(agent) {
|
||||||
this.el.find('.zammad-chat-loader').addClass('zammad-chat-is-hidden');
|
this.inQueue = false;
|
||||||
|
this.agent = agent;
|
||||||
|
this.el.find('.zammad-chat-agent').html(this.view('agent')({
|
||||||
|
agent: agent
|
||||||
|
}));
|
||||||
|
this.el.find('.zammad-chat-body').empty();
|
||||||
this.el.find('.zammad-chat-welcome').addClass('zammad-chat-is-hidden');
|
this.el.find('.zammad-chat-welcome').addClass('zammad-chat-is-hidden');
|
||||||
this.el.find('.zammad-chat-agent').removeClass('zammad-chat-is-hidden');
|
this.el.find('.zammad-chat-agent').removeClass('zammad-chat-is-hidden');
|
||||||
this.el.find('.zammad-chat-agent-status').removeClass('zammad-chat-is-hidden');
|
this.el.find('.zammad-chat-agent-status').removeClass('zammad-chat-is-hidden');
|
||||||
return this.el.find('.zammad-chat-input').focus();
|
return this.el.find('.zammad-chat-input').focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ZammadChat.prototype.showLoader = function() {
|
||||||
|
return this.el.find('.zammad-chat-body').html(this.view('loader')());
|
||||||
|
};
|
||||||
|
|
||||||
ZammadChat.prototype.setAgentOnlineState = function(state) {
|
ZammadChat.prototype.setAgentOnlineState = function(state) {
|
||||||
this.isOnline = state;
|
this.isOnline = state;
|
||||||
return this.el.find('.zammad-chat-agent-status').toggleClass('zammad-chat-is-online', state).text(state ? this.T('Online') : this.T('Offline'));
|
return this.el.find('.zammad-chat-agent-status').toggleClass('zammad-chat-is-online', state).text(state ? this.T('Online') : this.T('Offline'));
|
||||||
|
@ -406,6 +533,116 @@ jQuery.fn.autoGrow = function(options) {
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
if (!window.zammadChatTemplates) {
|
||||||
|
window.zammadChatTemplates = {};
|
||||||
|
}
|
||||||
|
window.zammadChatTemplates["chat"] = function (__obj) {
|
||||||
|
if (!__obj) __obj = {};
|
||||||
|
var __out = [], __capture = function(callback) {
|
||||||
|
var out = __out, result;
|
||||||
|
__out = [];
|
||||||
|
callback.call(this);
|
||||||
|
result = __out.join('');
|
||||||
|
__out = out;
|
||||||
|
return __safe(result);
|
||||||
|
}, __sanitize = function(value) {
|
||||||
|
if (value && value.ecoSafe) {
|
||||||
|
return value;
|
||||||
|
} else if (typeof value !== 'undefined' && value != null) {
|
||||||
|
return __escape(value);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
|
||||||
|
__safe = __obj.safe = function(value) {
|
||||||
|
if (value && value.ecoSafe) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
if (!(typeof value !== 'undefined' && value != null)) value = '';
|
||||||
|
var result = new String(value);
|
||||||
|
result.ecoSafe = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!__escape) {
|
||||||
|
__escape = __obj.escape = function(value) {
|
||||||
|
return ('' + value)
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
__out.push('<div class="zammad-chat">\n <div class="zammad-chat-header">\n <div class="zammad-chat-header-controls">\n <span class="zammad-chat-agent-status zammad-chat-is-hidden" data-status="online">Online</span>\n <span class="zammad-chat-toggle">\n <svg class="zammad-chat-toggle-icon-open" viewBox="0 0 13 7"><path d="M10.807 7l1.4-1.428-5-4.9L6.5-.02l-.7.7-4.9 4.9 1.414 1.413L6.5 2.886 10.807 7z" fill-rule="evenodd"/></svg>\n <svg class="zammad-chat-toggle-icon-close" viewBox="0 0 13 7"><path d="M6.554 4.214L2.246 0l-1.4 1.428 5 4.9.708.693.7-.7 4.9-4.9L10.74.008 6.553 4.214z" fill-rule="evenodd"/></svg>\n </span>\n </div>\n <div class="zammad-chat-agent zammad-chat-is-hidden">\n \n </div>\n <div class="zammad-chat-welcome">\n <svg class="zammad-chat-icon" viewBox="0 0 24 24"><path d="M2 5C2 4 3 3 4 3h16c1 0 2 1 2 2v10C22 16 21 17 20 17H4C3 17 2 16 2 15V5zM12 17l6 4v-4h-6z" fill-rule="evenodd"/></svg>\n <span class="zammad-chat-welcome-text">');
|
||||||
|
|
||||||
|
__out.push(this.invitationPhrase);
|
||||||
|
|
||||||
|
__out.push('</span>\n </div>\n </div>\n <div class="zammad-chat-body"></div>\n <form class="zammad-chat-controls">\n <textarea class="zammad-chat-input" rows="1" placeholder="Compose your message..."></textarea>\n <button type="submit" class="zammad-chat-send">Send</button>\n </form>\n</div>');
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|
||||||
|
}).call(__obj);
|
||||||
|
__obj.safe = __objSafe, __obj.escape = __escape;
|
||||||
|
return __out.join('');
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.zammadChatTemplates) {
|
||||||
|
window.zammadChatTemplates = {};
|
||||||
|
}
|
||||||
|
window.zammadChatTemplates["loader"] = function (__obj) {
|
||||||
|
if (!__obj) __obj = {};
|
||||||
|
var __out = [], __capture = function(callback) {
|
||||||
|
var out = __out, result;
|
||||||
|
__out = [];
|
||||||
|
callback.call(this);
|
||||||
|
result = __out.join('');
|
||||||
|
__out = out;
|
||||||
|
return __safe(result);
|
||||||
|
}, __sanitize = function(value) {
|
||||||
|
if (value && value.ecoSafe) {
|
||||||
|
return value;
|
||||||
|
} else if (typeof value !== 'undefined' && value != null) {
|
||||||
|
return __escape(value);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
|
||||||
|
__safe = __obj.safe = function(value) {
|
||||||
|
if (value && value.ecoSafe) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
if (!(typeof value !== 'undefined' && value != null)) value = '';
|
||||||
|
var result = new String(value);
|
||||||
|
result.ecoSafe = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!__escape) {
|
||||||
|
__escape = __obj.escape = function(value) {
|
||||||
|
return ('' + value)
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
__out.push('<div class="zammad-chat-modal">\n <span class="zammad-chat-loading-animation">\n <span class="zammad-chat-loading-circle"></span>\n <span class="zammad-chat-loading-circle"></span>\n <span class="zammad-chat-loading-circle"></span>\n </span>\n <span class="zammad-chat-modal-text">');
|
||||||
|
|
||||||
|
__out.push(__sanitize(this.T('Connecting')));
|
||||||
|
|
||||||
|
__out.push('</span>\n</div>');
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|
||||||
|
}).call(__obj);
|
||||||
|
__obj.safe = __objSafe, __obj.escape = __escape;
|
||||||
|
return __out.join('');
|
||||||
|
};
|
||||||
|
|
||||||
if (!window.zammadChatTemplates) {
|
if (!window.zammadChatTemplates) {
|
||||||
window.zammadChatTemplates = {};
|
window.zammadChatTemplates = {};
|
||||||
}
|
}
|
||||||
|
@ -574,3 +811,58 @@ window.zammadChatTemplates["typingIndicator"] = function (__obj) {
|
||||||
__obj.safe = __objSafe, __obj.escape = __escape;
|
__obj.safe = __objSafe, __obj.escape = __escape;
|
||||||
return __out.join('');
|
return __out.join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!window.zammadChatTemplates) {
|
||||||
|
window.zammadChatTemplates = {};
|
||||||
|
}
|
||||||
|
window.zammadChatTemplates["waiting"] = function (__obj) {
|
||||||
|
if (!__obj) __obj = {};
|
||||||
|
var __out = [], __capture = function(callback) {
|
||||||
|
var out = __out, result;
|
||||||
|
__out = [];
|
||||||
|
callback.call(this);
|
||||||
|
result = __out.join('');
|
||||||
|
__out = out;
|
||||||
|
return __safe(result);
|
||||||
|
}, __sanitize = function(value) {
|
||||||
|
if (value && value.ecoSafe) {
|
||||||
|
return value;
|
||||||
|
} else if (typeof value !== 'undefined' && value != null) {
|
||||||
|
return __escape(value);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}, __safe, __objSafe = __obj.safe, __escape = __obj.escape;
|
||||||
|
__safe = __obj.safe = function(value) {
|
||||||
|
if (value && value.ecoSafe) {
|
||||||
|
return value;
|
||||||
|
} else {
|
||||||
|
if (!(typeof value !== 'undefined' && value != null)) value = '';
|
||||||
|
var result = new String(value);
|
||||||
|
result.ecoSafe = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!__escape) {
|
||||||
|
__escape = __obj.escape = function(value) {
|
||||||
|
return ('' + value)
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
__out.push('<div class="zammad-chat-modal">\n <div class="zammad-chat-modal-text">\n <span class="zammad-chat-loading-animation">\n <span class="zammad-chat-loading-circle"></span>\n <span class="zammad-chat-loading-circle"></span>\n <span class="zammad-chat-loading-circle"></span>\n </span>\n Leider sind gerade alle Mitarbeiter belegt.<br>\n Warteliste-Position: <strong>');
|
||||||
|
|
||||||
|
__out.push(__sanitize(this.position));
|
||||||
|
|
||||||
|
__out.push('</strong>\n </div>\n</div>');
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|
||||||
|
}).call(__obj);
|
||||||
|
__obj.safe = __objSafe, __obj.escape = __escape;
|
||||||
|
return __out.join('');
|
||||||
|
};
|
||||||
|
|
2
public/assets/chat/chat.min.js
vendored
2
public/assets/chat/chat.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -123,7 +123,7 @@
|
||||||
-webkit-transform: scale(1);
|
-webkit-transform: scale(1);
|
||||||
transform: scale(1); } }
|
transform: scale(1); } }
|
||||||
|
|
||||||
.zammad-chat-loader {
|
.zammad-chat-modal {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -144,12 +144,15 @@
|
||||||
-ms-flex-pack: center;
|
-ms-flex-pack: center;
|
||||||
justify-content: center; }
|
justify-content: center; }
|
||||||
|
|
||||||
.zammad-chat-loader-text {
|
.zammad-chat-modal-text {
|
||||||
font-size: 1.3em; }
|
font-size: 1.3em;
|
||||||
|
line-height: 1.45; }
|
||||||
|
.zammad-chat-modal-text .zammad-chat-loading-animation {
|
||||||
|
font-size: 0.7em; }
|
||||||
|
|
||||||
.zammad-chat-loader .zammad-chat-loading-animation {
|
.zammad-chat-modal .zammad-chat-loading-animation {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
margin-left: -19px; }
|
vertical-align: middle; }
|
||||||
|
|
||||||
.zammad-chat-body {
|
.zammad-chat-body {
|
||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
|
@ -192,6 +195,9 @@
|
||||||
.zammad-chat-message--typing .zammad-chat-message-body {
|
.zammad-chat-message--typing .zammad-chat-message-body {
|
||||||
white-space: normal; }
|
white-space: normal; }
|
||||||
|
|
||||||
|
.zammad-chat-loading-animation {
|
||||||
|
display: inline-block; }
|
||||||
|
|
||||||
.zammad-chat-loading-circle {
|
.zammad-chat-loading-circle {
|
||||||
background: #c5dded;
|
background: #c5dded;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
|
|
|
@ -154,7 +154,7 @@ $baseTextColor: if($luminance < 0.2, white, black);
|
||||||
to { opacity: 1; transform: scale(1); }
|
to { opacity: 1; transform: scale(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-chat-loader {
|
.zammad-chat-modal {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -170,13 +170,18 @@ $baseTextColor: if($luminance < 0.2, white, black);
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-chat-loader-text {
|
.zammad-chat-modal-text {
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
|
line-height: 1.45;
|
||||||
|
|
||||||
|
.zammad-chat-loading-animation {
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-chat-loader .zammad-chat-loading-animation {
|
.zammad-chat-modal .zammad-chat-loading-animation {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
margin-left: -19px;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-chat-body {
|
.zammad-chat-body {
|
||||||
|
@ -232,6 +237,10 @@ $baseTextColor: if($luminance < 0.2, white, black);
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.zammad-chat-loading-animation {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.zammad-chat-loading-circle {
|
.zammad-chat-loading-circle {
|
||||||
background: desaturate(lightenMax($themeColor, 50%, 85%), 15%);
|
background: desaturate(lightenMax($themeColor, 50%, 85%), 15%);
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
|
|
4
public/assets/chat/views/agent.eco
Normal file
4
public/assets/chat/views/agent.eco
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<img class="zammad-chat-agent-avatar" src="<%= @agent.avatar %>">
|
||||||
|
<span class="zammad-chat-agent-sentence">
|
||||||
|
<span class="zammad-chat-agent-name"><%= @agent.name %></span> <%- @agentPhrase %>
|
||||||
|
</span>
|
|
@ -8,24 +8,13 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="zammad-chat-agent zammad-chat-is-hidden">
|
<div class="zammad-chat-agent zammad-chat-is-hidden">
|
||||||
<img class="zammad-chat-agent-avatar" src="https://s3.amazonaws.com/uifaces/faces/twitter/joshaustin/128.jpg">
|
|
||||||
<span class="zammad-chat-agent-sentence">
|
|
||||||
<span class="zammad-chat-agent-name">Adam</span> is helping you.
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="zammad-chat-welcome">
|
<div class="zammad-chat-welcome">
|
||||||
<svg class="zammad-chat-icon" viewBox="0 0 24 24"><path d="M2 5C2 4 3 3 4 3h16c1 0 2 1 2 2v10C22 16 21 17 20 17H4C3 17 2 16 2 15V5zM12 17l6 4v-4h-6z" fill-rule="evenodd"/></svg>
|
<svg class="zammad-chat-icon" viewBox="0 0 24 24"><path d="M2 5C2 4 3 3 4 3h16c1 0 2 1 2 2v10C22 16 21 17 20 17H4C3 17 2 16 2 15V5zM12 17l6 4v-4h-6z" fill-rule="evenodd"/></svg>
|
||||||
<span class="zammad-chat-welcome-text"><strong>Chat</strong> with us!</span>
|
<span class="zammad-chat-welcome-text"><%- @invitationPhrase %></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="zammad-chat-loader">
|
|
||||||
<span class="zammad-chat-loading-animation">
|
|
||||||
<span class="zammad-chat-loading-circle"></span>
|
|
||||||
<span class="zammad-chat-loading-circle"></span>
|
|
||||||
<span class="zammad-chat-loading-circle"></span>
|
|
||||||
</span>
|
|
||||||
<span class="zammad-chat-loader-text">Connecting</span>
|
|
||||||
</div>
|
|
||||||
<div class="zammad-chat-body"></div>
|
<div class="zammad-chat-body"></div>
|
||||||
<form class="zammad-chat-controls">
|
<form class="zammad-chat-controls">
|
||||||
<textarea class="zammad-chat-input" rows="1" placeholder="Compose your message..."></textarea>
|
<textarea class="zammad-chat-input" rows="1" placeholder="Compose your message..."></textarea>
|
||||||
|
|
8
public/assets/chat/views/loader.eco
Normal file
8
public/assets/chat/views/loader.eco
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<div class="zammad-chat-modal">
|
||||||
|
<span class="zammad-chat-loading-animation">
|
||||||
|
<span class="zammad-chat-loading-circle"></span>
|
||||||
|
<span class="zammad-chat-loading-circle"></span>
|
||||||
|
<span class="zammad-chat-loading-circle"></span>
|
||||||
|
</span>
|
||||||
|
<span class="zammad-chat-modal-text"><%= @T('Connecting') %></span>
|
||||||
|
</div>
|
11
public/assets/chat/views/waiting.eco
Normal file
11
public/assets/chat/views/waiting.eco
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="zammad-chat-modal">
|
||||||
|
<div class="zammad-chat-modal-text">
|
||||||
|
<span class="zammad-chat-loading-animation">
|
||||||
|
<span class="zammad-chat-loading-circle"></span>
|
||||||
|
<span class="zammad-chat-loading-circle"></span>
|
||||||
|
<span class="zammad-chat-loading-circle"></span>
|
||||||
|
</span>
|
||||||
|
Leider sind gerade alle Mitarbeiter belegt.<br>
|
||||||
|
Warteliste-Position: <strong><%= @position %></strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in a new issue