customer chat
|
@ -15,5 +15,5 @@ App.Config.set( 'Admin', { prio: 9000, parent: '', name: 'Admin', translate: tru
|
||||||
App.Config.set( 'New', { prio: 20000, parent: '', name: 'New', translate: true, target: '#new', class: 'add' }, 'NavBarRight' )
|
App.Config.set( 'New', { prio: 20000, parent: '', name: 'New', translate: true, target: '#new', class: 'add' }, 'NavBarRight' )
|
||||||
|
|
||||||
App.Config.set( 'Misc', { prio: 90000, parent: '', name: 'Tools', translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar' )
|
App.Config.set( 'Misc', { prio: 90000, parent: '', name: 'Tools', translate: true, target: '#tools', child: true, class: 'tools' }, 'NavBar' )
|
||||||
#App.Config.set( 'Misc1', { prio: 1600, parent: '#tools', name: 'Test 1', target: '#test1', role: [ 'Admin' ] }, 'NavBar' )
|
App.Config.set( 'Misc1', { prio: 1600, parent: '#tools', name: 'Test 1', target: '#test1', role: [ 'Admin' ] }, 'NavBar' )
|
||||||
#App.Config.set( 'Misc2', { prio: 1700, parent: '#tools', name: 'Test 2', target: '#test2', role: [ 'Admin' ] }, 'NavBar' )
|
App.Config.set( 'Misc2', { prio: 1700, parent: '#tools', name: 'Test 2', target: '#test2', role: [ 'Admin' ] }, 'NavBar' )
|
||||||
|
|
|
@ -1657,4 +1657,370 @@ class PrimaryEmailRef extends App.ControllerContent
|
||||||
App.Config.set( 'layout_ref/primary_email', PrimaryEmailRef, 'Routes' )
|
App.Config.set( 'layout_ref/primary_email', PrimaryEmailRef, 'Routes' )
|
||||||
|
|
||||||
|
|
||||||
|
class App.CustomerChatRef extends App.ControllerContent
|
||||||
|
@extend Spine.Events
|
||||||
|
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
question: "Der dümmste Bauer hat die dicksten ..?"
|
||||||
|
answers: ["Kartoffeln"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Welchen Wein besang einst Udo Jürgens?"
|
||||||
|
answers: ["griechisch"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Was behandelt ein Logopäde?"
|
||||||
|
answers: ["Sprachstörung"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "In welcher Stadt ist das Porsche Stammwerk?"
|
||||||
|
answers: ["Stuttgart"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Wer erfand den legendären C64-Computer?"
|
||||||
|
answers: ["Commodore"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Im Englischen steht "Lost And Found" für ..?'
|
||||||
|
answers: ["Fundbüro"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Welches Möbelstück ist und war besonders in Sigmund Freuds Arbeitszimmer bekannt?'
|
||||||
|
answers: ["Couch"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Wenn es einem gut geht, lebt man "wie die Made im .."?'
|
||||||
|
answers: ["Speck"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Von welcher Sportart handelt der US-amerikanische Film "Rocky"?'
|
||||||
|
answers: ["Boxen"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Wo soll man hingehen, wenn man sich weit entfernen soll? Dahin wo ..?'
|
||||||
|
answers: ["Pfeffer", "wächst"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Welches internationale Autokennzeichen hat Spanien?'
|
||||||
|
answers: ["ES"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Wenn man sich ärgert sagt man "Verdammt und .."?'
|
||||||
|
answers: ["zugenäht"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Bei welchem Spiel muss man ohne zu zittern Stäbchen sammeln?'
|
||||||
|
answers: ["Mikado"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: 'Wann wurde Znuny gegründet?'
|
||||||
|
answers: ["2012"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
@i = 0
|
||||||
|
@chatWindows = []
|
||||||
|
@totalQuestions = 7
|
||||||
|
@answered = 0
|
||||||
|
@correct = 0
|
||||||
|
@wrong = 0
|
||||||
|
@maxChats = 4;
|
||||||
|
|
||||||
|
@render()
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
@html App.view('layout_ref/customer_chat')()
|
||||||
|
|
||||||
|
@addChat()
|
||||||
|
|
||||||
|
# @testChat @chatWindows[0], 100
|
||||||
|
@initQuiz()
|
||||||
|
|
||||||
|
testChat: (chat, count) ->
|
||||||
|
for i in [0..count]
|
||||||
|
text = @questions[Math.floor(Math.random() * @questions.length)].question
|
||||||
|
chat.addMessage text, if i % 2 then 'customer' else 'agent'
|
||||||
|
|
||||||
|
addChat: ->
|
||||||
|
chat = new chatWindowRef
|
||||||
|
name: "Quizmaster-#{ ++@i }"
|
||||||
|
|
||||||
|
@on 'layout-has-changed', @propagateLayoutChange
|
||||||
|
|
||||||
|
@$('.chat-workspace').append(chat.el)
|
||||||
|
@chatWindows.push chat
|
||||||
|
|
||||||
|
propagateLayoutChange: (event) =>
|
||||||
|
# adjust scroll position on layoutChange
|
||||||
|
console.log "propagateLayoutChange", event
|
||||||
|
|
||||||
|
for chat in @chatWindows
|
||||||
|
chat.trigger 'layout-changed'
|
||||||
|
|
||||||
|
initQuiz: ->
|
||||||
|
@chatWindows[0].addStatusMessage('To start the quiz type <strong>Start</strong>')
|
||||||
|
@chatWindows[0].bind "answer", @startQuiz
|
||||||
|
|
||||||
|
startQuiz: (answer) =>
|
||||||
|
return false unless answer is "Start"
|
||||||
|
|
||||||
|
@chatWindows[0].unbind "answer"
|
||||||
|
|
||||||
|
@nextQuestion()
|
||||||
|
|
||||||
|
nextQuestion: ->
|
||||||
|
if not @questions.length
|
||||||
|
@currentChat.addStatusMessage("Du hast #{ @correct } von #{ @totalQuestions } Fragen richtig beantwortet!")
|
||||||
|
for chat in @chatWindows
|
||||||
|
chat.unbind "answer"
|
||||||
|
if chat is not @currentChat
|
||||||
|
chat.goOffline()
|
||||||
|
return
|
||||||
|
|
||||||
|
if @chatWindows.length < @maxChats and Math.random() < 0.2
|
||||||
|
@addChat()
|
||||||
|
randomWindowId = @chatWindows.length-1
|
||||||
|
else
|
||||||
|
# maybe take a chat offline
|
||||||
|
if @chatWindows.length > 1 and Math.random() > 0.85
|
||||||
|
randomWindowId = Math.floor(Math.random()*@chatWindows.length)
|
||||||
|
[killedChat] = @chatWindows.splice randomWindowId, 1
|
||||||
|
killedChat.goOffline()
|
||||||
|
|
||||||
|
randomWindowId = Math.floor(Math.random()*@chatWindows.length)
|
||||||
|
|
||||||
|
randomQuestionId = Math.floor(Math.random()*@questions.length)
|
||||||
|
|
||||||
|
@currentQuestion = @questions.splice(randomQuestionId, 1)[0]
|
||||||
|
|
||||||
|
newChat = @chatWindows[randomWindowId]
|
||||||
|
|
||||||
|
messageDelay = 500
|
||||||
|
|
||||||
|
if newChat != @currentChat
|
||||||
|
@currentChat.unbind("answer") if @currentChat
|
||||||
|
@currentChat = newChat
|
||||||
|
@currentChat.bind "answer", @onQuestionAnswer
|
||||||
|
messageDelay = 1500
|
||||||
|
|
||||||
|
@currentChat.showWritingLoader()
|
||||||
|
|
||||||
|
setTimeout @currentChat.receiveMessage, messageDelay + Math.random() * 1000, @currentQuestion.question
|
||||||
|
|
||||||
|
onQuestionAnswer: (answer) =>
|
||||||
|
match = false
|
||||||
|
|
||||||
|
for text in @currentQuestion.answers
|
||||||
|
if answer.match( new RegExp(text,'i') )
|
||||||
|
match = true
|
||||||
|
|
||||||
|
@answered++
|
||||||
|
|
||||||
|
if match
|
||||||
|
@correct++
|
||||||
|
@currentChat.receiveMessage _.shuffle(['😀','😃','😊','😍','😎','😏','👍','😌','😇','👌'])[0]
|
||||||
|
else
|
||||||
|
@wrong++
|
||||||
|
@currentChat.receiveMessage _.shuffle(['👎','💩','😰','😩','😦','😧','😟','😠','😡','😞','😢','😒','😕'])[0]
|
||||||
|
|
||||||
|
if @answerd is @totalQuestions
|
||||||
|
@finishQuiz()
|
||||||
|
else
|
||||||
|
@nextQuestion()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
App.Config.set( 'layout_ref/customer_chat', App.CustomerChatRef, 'Routes' )
|
||||||
|
|
||||||
|
App.Config.set( 'Chat', { prio: 300, parent: '', name: 'Customer Chat', target: '#layout_ref/customer_chat', switch: true, counter: true, role: ['Agent'], class: 'chat' }, 'NavBar' )
|
||||||
|
# App.Config.set( 'Chat', { controller: 'CustomerChatRef', authentication: true }, 'permanentTask' )
|
||||||
|
|
||||||
|
|
||||||
|
class chatWindowRef extends Spine.Controller
|
||||||
|
@extend Spine.Events
|
||||||
|
|
||||||
|
className: 'chat-window'
|
||||||
|
|
||||||
|
events:
|
||||||
|
'keydown .js-customerChatInput': 'onKeydown'
|
||||||
|
'focus .js-customerChatInput': 'clearUnread'
|
||||||
|
'click': 'clearUnread'
|
||||||
|
'click .js-send': 'sendMessage'
|
||||||
|
'click .js-close': 'close'
|
||||||
|
|
||||||
|
elements:
|
||||||
|
'.js-customerChatInput': 'input'
|
||||||
|
'.js-status': 'status'
|
||||||
|
'.js-body': 'body'
|
||||||
|
'.js-scrollHolder': 'scrollHolder'
|
||||||
|
|
||||||
|
sound:
|
||||||
|
message: new Audio('assets/sounds/chat_message.mp3')
|
||||||
|
window: new Audio('assets/sounds/chat_new.mp3')
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
|
||||||
|
@showTimeEveryXMinutes = 1
|
||||||
|
@lastTimestamp
|
||||||
|
@lastAddedType
|
||||||
|
@render()
|
||||||
|
@sound.window.play()
|
||||||
|
|
||||||
|
@on 'layout-change', @scrollToBottom
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
@html App.view('layout_ref/customer_chat_window')
|
||||||
|
name: @options.name
|
||||||
|
|
||||||
|
@el.one 'transitionend', @onTransitionend
|
||||||
|
|
||||||
|
# make sure animation will run
|
||||||
|
setTimeout (=> @el.addClass('is-open')), 0
|
||||||
|
|
||||||
|
# @addMessage 'Hello. My name is Roger, how can I help you?', 'agent'
|
||||||
|
|
||||||
|
onTransitionend: (event) =>
|
||||||
|
# chat window is done with animation - adjust scroll-bars
|
||||||
|
# of sibling chat windows
|
||||||
|
@trigger 'layout-has-changed'
|
||||||
|
|
||||||
|
if event.data and event.data.callback
|
||||||
|
event.data.callback()
|
||||||
|
|
||||||
|
close: =>
|
||||||
|
@el.one 'transitionend', { callback: @release }, @onTransitionend
|
||||||
|
@el.removeClass('is-open')
|
||||||
|
|
||||||
|
release: =>
|
||||||
|
@trigger 'closed'
|
||||||
|
super
|
||||||
|
|
||||||
|
clearUnread: =>
|
||||||
|
@$('.chat-message--new').removeClass('chat-message--new')
|
||||||
|
@updateModified(false)
|
||||||
|
|
||||||
|
onKeydown: (event) =>
|
||||||
|
TABKEY = 9;
|
||||||
|
ENTERKEY = 13;
|
||||||
|
|
||||||
|
switch event.keyCode
|
||||||
|
when TABKEY
|
||||||
|
allChatInputs = $('.js-customerChatInput').not('[disabled="disabled"]')
|
||||||
|
chatCount = allChatInputs.size()
|
||||||
|
index = allChatInputs.index(@input)
|
||||||
|
|
||||||
|
if chatCount > 1
|
||||||
|
switch index
|
||||||
|
when chatCount-1
|
||||||
|
if !event.shiftKey
|
||||||
|
# State: tab without shift on last input
|
||||||
|
# Jump to first input
|
||||||
|
event.preventDefault()
|
||||||
|
allChatInputs.eq(0).focus()
|
||||||
|
when 0
|
||||||
|
if event.shiftKey
|
||||||
|
# State: tab with shift on first input
|
||||||
|
# Jump to last input
|
||||||
|
event.preventDefault()
|
||||||
|
allChatInputs.eq(chatCount-1).focus()
|
||||||
|
|
||||||
|
when ENTERKEY
|
||||||
|
if !event.shiftKey
|
||||||
|
event.preventDefault()
|
||||||
|
@sendMessage()
|
||||||
|
|
||||||
|
sendMessage: =>
|
||||||
|
return if !@input.html()
|
||||||
|
|
||||||
|
@addMessage @input.html(), 'agent'
|
||||||
|
|
||||||
|
@trigger "answer", @input.html()
|
||||||
|
|
||||||
|
@input.html('')
|
||||||
|
|
||||||
|
updateModified: (state) =>
|
||||||
|
@status.toggleClass('is-modified', state)
|
||||||
|
|
||||||
|
receiveMessage: (message) =>
|
||||||
|
isFocused = @input.is(':focus')
|
||||||
|
|
||||||
|
@removeWritingLoader()
|
||||||
|
@addMessage(message, 'customer', !isFocused)
|
||||||
|
|
||||||
|
if !isFocused
|
||||||
|
@updateModified(true)
|
||||||
|
@sound.message.play()
|
||||||
|
|
||||||
|
addMessage: (message, sender, isNew) =>
|
||||||
|
@maybeAddTimestamp()
|
||||||
|
|
||||||
|
@lastAddedType = sender
|
||||||
|
|
||||||
|
@body.append App.view('layout_ref/customer_chat_message')
|
||||||
|
message: message
|
||||||
|
sender: sender
|
||||||
|
isNew: isNew
|
||||||
|
timestamp: Date.now()
|
||||||
|
|
||||||
|
@scrollToBottom()
|
||||||
|
|
||||||
|
showWritingLoader: =>
|
||||||
|
@maybeAddTimestamp()
|
||||||
|
@body.append App.view('layout_ref/customer_chat_loader')()
|
||||||
|
|
||||||
|
@scrollToBottom()
|
||||||
|
|
||||||
|
removeWritingLoader: =>
|
||||||
|
@$('.js-loader').remove()
|
||||||
|
|
||||||
|
goOffline: =>
|
||||||
|
@addStatusMessage("<strong>#{ @options.name }</strong>'s connection got closed")
|
||||||
|
@status.attr('data-status', 'offline')
|
||||||
|
@el.addClass('is-offline')
|
||||||
|
@input.attr('disabled', true)
|
||||||
|
|
||||||
|
maybeAddTimestamp: ->
|
||||||
|
timestamp = Date.now()
|
||||||
|
|
||||||
|
if !@lastTimestamp or timestamp - @lastTimestamp > @showTimeEveryXMinutes * 60000
|
||||||
|
label = 'Today'
|
||||||
|
time = new Date().toTimeString().substr(0,5)
|
||||||
|
if @lastAddedType is 'timestamp'
|
||||||
|
# update last time
|
||||||
|
@updateLastTimestamp label, time
|
||||||
|
@lastTimestamp = timestamp
|
||||||
|
else
|
||||||
|
@addTimestamp label, time
|
||||||
|
@lastTimestamp = timestamp
|
||||||
|
@lastAddedType = 'timestamp'
|
||||||
|
|
||||||
|
addTimestamp: (label, time) =>
|
||||||
|
@body.append App.view('layout_ref/customer_chat_timestamp')
|
||||||
|
label: label
|
||||||
|
time: time
|
||||||
|
|
||||||
|
updateLastTimestamp: (label, time) ->
|
||||||
|
@body
|
||||||
|
.find('.js-timestamp')
|
||||||
|
.last()
|
||||||
|
.replaceWith App.view('layout_ref/customer_chat_timestamp')
|
||||||
|
label: label
|
||||||
|
time: time
|
||||||
|
|
||||||
|
addStatusMessage: (message) ->
|
||||||
|
@body.append App.view('layout_ref/customer_chat_status_message')
|
||||||
|
message: message
|
||||||
|
|
||||||
|
@scrollToBottom()
|
||||||
|
|
||||||
|
scrollToBottom: ->
|
||||||
|
@scrollHolder.scrollTop(@scrollHolder.prop('scrollHeight'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
App.Config.set( 'LayoutRef', { prio: 1700, parent: '#current_user', name: 'Layout Reference', translate: true, target: '#layout_ref', role: [ 'Admin' ] }, 'NavBarRight' )
|
App.Config.set( 'LayoutRef', { prio: 1700, parent: '#current_user', name: 'Layout Reference', translate: true, target: '#layout_ref', role: [ 'Admin' ] }, 'NavBarRight' )
|
|
@ -4,7 +4,7 @@
|
||||||
<li <% if item.active: %>class="active"<% end %>>
|
<li <% if item.active: %>class="active"<% end %>>
|
||||||
<a class="horizontal center" href="<%= item.target %>">
|
<a class="horizontal center" href="<%= item.target %>">
|
||||||
<span class="local u-textTruncate"><%- @T(item.name) %></span>
|
<span class="local u-textTruncate"><%- @T(item.name) %></span>
|
||||||
<span class="badge"><%= item.count %></span>
|
<span class="badge badge--text"><%= item.count %></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<div class="chat main">
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="page-header-title">
|
||||||
|
<h1>Customer Chat</h1>
|
||||||
|
</div>
|
||||||
|
<div class="page-header-center">
|
||||||
|
<div class="status-fields">
|
||||||
|
<div class="status-field">
|
||||||
|
<span class="badge">0</span> Waiting Customers
|
||||||
|
</div>
|
||||||
|
<div class="status-field">
|
||||||
|
<span class="badge">15</span> Chatting Customers
|
||||||
|
</div>
|
||||||
|
<div class="status-field">
|
||||||
|
<span class="badge">5</span> Active Agents
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="page-header-meta">
|
||||||
|
<div class="btn btn--action" data-type="settings"><%= @T('Settings') %></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chat-workspace"></div>
|
||||||
|
</div>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="chat-message chat-message--customer chat-message--loader js-loader">
|
||||||
|
<div class="chat-loader">
|
||||||
|
<%- @Icon('loading') %>
|
||||||
|
<%- @Icon('loading') %>
|
||||||
|
<%- @Icon('loading') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="chat-message chat-message--<%= @sender %><%= ' chat-message--new' if @isNew %>"><%- @message %></div>
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="chat-status-message"><%- @message %></div>
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="chat-timestamp js-timestamp"><span class="chat-timestamp-label"><%= @label %></span> <%= @time %></div>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<div class="chat-header">
|
||||||
|
<div class="chat-status js-status" data-status="online">
|
||||||
|
<div class="chat-status-holder">
|
||||||
|
<%- @Icon('status') %>
|
||||||
|
<%- @Icon('status-modified-outer-circle') %>
|
||||||
|
<%- @Icon('status-modified-inner-circle') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chat-name"><%- @name %></div>
|
||||||
|
<div class="chat-close js-close">
|
||||||
|
<%- @Icon('diagonal-cross') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chat-body-holder js-scrollHolder">
|
||||||
|
<div class="chat-body js-body"></div>
|
||||||
|
</div>
|
||||||
|
<div class="chat-controls">
|
||||||
|
<div class="chat-input form-control form-control--small form-control--multiline js-customerChatInput" contenteditable="true"></div>
|
||||||
|
<div class="btn btn--primary btn--slim btn--small js-send"><%= @T('Send') %></div>
|
||||||
|
</div>
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><a href="#layout_ref/customer_chat">Customer Chat</a></li>
|
||||||
<li><a href="#layout_ref/ticket_zoom">Ticket Zoom</a></li>
|
<li><a href="#layout_ref/ticket_zoom">Ticket Zoom</a></li>
|
||||||
<li><a href="#layout_ref/primary_email">Primary Email (New/Edit User)</a></li>
|
<li><a href="#layout_ref/primary_email">Primary Email (New/Edit User)</a></li>
|
||||||
<li><a href="#layout_ref/merge_customer">Merge Customer</a></li>
|
<li><a href="#layout_ref/merge_customer">Merge Customer</a></li>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<% for item in @items: %>
|
<% for item in @items: %>
|
||||||
<% if item.child: %>
|
<% if item.child: %>
|
||||||
<li class="dropdown <%= item.class %> <% if @open_tab[item.target] : %>open<% end %>">
|
<li class="dropdown <% if @open_tab[item.target] : %>open<% end %>">
|
||||||
<a href="<%= item.target %>" class="dropdown-toggle" data-toggle="dropdown">
|
<a href="<%= item.target %>" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
<%- @Icon(item.class, 'nav-icon') %>
|
<%- @Icon(item.class, 'nav-icon') %>
|
||||||
<span class="nav-item-name flex">
|
<span class="nav-item-name flex">
|
||||||
|
@ -16,17 +16,26 @@
|
||||||
<% if item.navheader: %>
|
<% if item.navheader: %>
|
||||||
<li class="dropdown-header"><%- @T( item.navheader ) %></li>
|
<li class="dropdown-header"><%- @T( item.navheader ) %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<li class="<% if @active_tab[item.target] : %>active<% end %>"><a href="<%= item.target %>"><%- @T( item.name ) %><% if item['count'] isnt undefined: %><span class="badge count"><%= item['count'] %></span><% end %></a></li>
|
<li class="<% if @active_tab[item.target] : %>active<% end %>"><a href="<%= item.target %>"><%- @T( item.name ) %><% if item['count'] isnt undefined: %><span class="badge badge--text count"><%= item['count'] %></span><% end %></a></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<% else: %>
|
<% else: %>
|
||||||
<li class="<%= item.class %> <% if @active_tab[item.target] : %>active<% end %>">
|
<li<% ' class="active"' if @active_tab[item.target] %>>
|
||||||
<a class="horizontal center" href="<%= item.target %>">
|
<a class="horizontal center" href="<%= item.target %>">
|
||||||
<%- @Icon(item.class, 'nav-icon') %>
|
<%- @Icon(item.class, 'nav-icon') %>
|
||||||
<span class="nav-item-name">
|
<span class="nav-item-name">
|
||||||
<%- @T(item.name) %>
|
<%- @T(item.name) %>
|
||||||
</span>
|
</span>
|
||||||
|
<% if item.counter: %>
|
||||||
|
<span class="counter badge badge--big"></span>
|
||||||
|
<% end %>
|
||||||
|
<% if item.switch: %>
|
||||||
|
<div class="zammad-switch zammad-switch--dark zammad-switch--small">
|
||||||
|
<input type="checkbox" id="<%- item.class %>-switch">
|
||||||
|
<label for="<%- item.class %>-switch"></label>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<li class="<% if @active_tab[item.target] : %>active<% end %>">
|
<li class="<% if @active_tab[item.target] : %>active<% end %>">
|
||||||
<a href="<%= item.target %>" class="horizontal center">
|
<a href="<%= item.target %>" class="horizontal center">
|
||||||
<span class="flex u-textTruncate"><% if item.translate: %><%- @T( item.name ) %><% else: %><%= item.name %><% end %></span>
|
<span class="flex u-textTruncate"><% if item.translate: %><%- @T( item.name ) %><% else: %><%= item.name %><% end %></span>
|
||||||
<% if item['count'] isnt undefined: %><span class="badge count"><%= item['count'] %></span><% end %>
|
<% if item['count'] isnt undefined: %><span class="badge badge--text count"><%= item['count'] %></span><% end %>
|
||||||
<% if item.iconClass: %><%- @Icon(item.iconClass) %><% end %>
|
<% if item.iconClass: %><%- @Icon(item.iconClass) %><% end %>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
45
app/assets/stylesheets/bootstrap.css
vendored
|
@ -3513,51 +3513,6 @@ a.label:focus {
|
||||||
.label-danger[href]:focus {
|
.label-danger[href]:focus {
|
||||||
background-color: #c9302c;
|
background-color: #c9302c;
|
||||||
}
|
}
|
||||||
.badge {
|
|
||||||
display: inline-block;
|
|
||||||
min-width: 10px;
|
|
||||||
padding: 3px 7px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
line-height: 1;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: baseline;
|
|
||||||
background-color: #777;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
.badge:empty {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.btn .badge {
|
|
||||||
position: relative;
|
|
||||||
top: -1px;
|
|
||||||
}
|
|
||||||
.btn-xs .badge {
|
|
||||||
top: 0;
|
|
||||||
padding: 1px 5px;
|
|
||||||
}
|
|
||||||
a.badge:hover,
|
|
||||||
a.badge:focus {
|
|
||||||
color: #fff;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.list-group-item.active > .badge,
|
|
||||||
.nav-pills > .active > a > .badge {
|
|
||||||
color: #337ab7;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
.list-group-item > .badge {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
.list-group-item > .badge + .badge {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
.nav-pills > li > a > .badge {
|
|
||||||
margin-left: 3px;
|
|
||||||
}
|
|
||||||
.jumbotron {
|
.jumbotron {
|
||||||
padding: 30px 15px;
|
padding: 30px 15px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Fira Sans';
|
font-family: 'Fira Sans';
|
||||||
src: url('fonts/FiraSans-Regular.eot');
|
src: url('fonts/FiraSans-Regular.eot');
|
||||||
|
@ -21,8 +18,15 @@
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Fira Sans';
|
||||||
|
src: url('fonts/FiraSans-Medium.eot');
|
||||||
|
src: url('fonts/FiraSans-Medium.woff2') format('woff2'),
|
||||||
|
url('fonts/FiraSans-Medium.woff') format('woff'),
|
||||||
|
url('fonts/FiraSans-Medium.ttf') format('truetype');
|
||||||
|
font-weight: 500;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Fira Sans';
|
font-family: 'Fira Sans';
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
.icon-arrow-left { width: 7px; height: 13px; }
|
.icon-arrow-left { width: 7px; height: 13px; }
|
||||||
.icon-arrow-right { width: 7px; height: 13px; }
|
.icon-arrow-right { width: 7px; height: 13px; }
|
||||||
.icon-arrow-up { width: 13px; height: 7px; }
|
.icon-arrow-up { width: 13px; height: 7px; }
|
||||||
|
.icon-chat { width: 24px; height: 24px; }
|
||||||
.icon-checkbox-checked { width: 11px; height: 11px; }
|
.icon-checkbox-checked { width: 11px; height: 11px; }
|
||||||
.icon-checkbox { width: 11px; height: 11px; }
|
.icon-checkbox { width: 11px; height: 11px; }
|
||||||
.icon-checkmark { width: 16px; height: 14px; }
|
.icon-checkmark { width: 16px; height: 14px; }
|
||||||
|
@ -55,9 +56,6 @@
|
||||||
.icon-phone { width: 17px; height: 17px; }
|
.icon-phone { width: 17px; height: 17px; }
|
||||||
.icon-plus-small { width: 16px; height: 16px; }
|
.icon-plus-small { width: 16px; height: 16px; }
|
||||||
.icon-plus { width: 20px; height: 20px; }
|
.icon-plus { width: 20px; height: 20px; }
|
||||||
.icon-priority-modified-inner-circle { width: 16px; height: 16px; }
|
|
||||||
.icon-priority-modified-outer-circle { width: 16px; height: 16px; }
|
|
||||||
.icon-priority { width: 16px; height: 16px; }
|
|
||||||
.icon-radio-checked { width: 11px; height: 11px; }
|
.icon-radio-checked { width: 11px; height: 11px; }
|
||||||
.icon-radio { width: 11px; height: 11px; }
|
.icon-radio { width: 11px; height: 11px; }
|
||||||
.icon-received-calls { width: 17px; height: 17px; }
|
.icon-received-calls { width: 17px; height: 17px; }
|
||||||
|
@ -67,11 +65,11 @@
|
||||||
.icon-reply { width: 16px; height: 16px; }
|
.icon-reply { width: 16px; height: 16px; }
|
||||||
.icon-signout { width: 15px; height: 19px; }
|
.icon-signout { width: 15px; height: 19px; }
|
||||||
.icon-split { width: 16px; height: 16px; }
|
.icon-split { width: 16px; height: 16px; }
|
||||||
|
.icon-status-modified-inner-circle { width: 16px; height: 16px; }
|
||||||
|
.icon-status-modified-outer-circle { width: 16px; height: 16px; }
|
||||||
.icon-status { width: 16px; height: 16px; }
|
.icon-status { width: 16px; height: 16px; }
|
||||||
.icon-stopwatch { width: 77px; height: 83px; }
|
.icon-stopwatch { width: 77px; height: 83px; }
|
||||||
.icon-switchView { width: 19px; height: 18px; }
|
.icon-switchView { width: 19px; height: 18px; }
|
||||||
.icon-task-state-modified-inner-circle { width: 16px; height: 16px; }
|
|
||||||
.icon-task-state-modified-outer-circle { width: 16px; height: 16px; }
|
|
||||||
.icon-task-state { width: 16px; height: 16px; }
|
.icon-task-state { width: 16px; height: 16px; }
|
||||||
.icon-team { width: 16px; height: 16px; }
|
.icon-team { width: 16px; height: 16px; }
|
||||||
.icon-templates { width: 24px; height: 24px; }
|
.icon-templates { width: 24px; height: 24px; }
|
||||||
|
|
|
@ -46,6 +46,10 @@ p {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.text-muted {
|
.text-muted {
|
||||||
color: hsl(60,1%,74%);
|
color: hsl(60,1%,74%);
|
||||||
}
|
}
|
||||||
|
@ -320,6 +324,11 @@ span[data-tooltip]:hover:before {
|
||||||
box-shadow: 0 0 0 3px hsl(201,62%,90%);
|
box-shadow: 0 0 0 3px hsl(201,62%,90%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.btn--small {
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
&.btn--slim {
|
&.btn--slim {
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
|
@ -356,7 +365,7 @@ span[data-tooltip]:hover:before {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
height: 31px;
|
height: 31px;
|
||||||
padding: 6px 11px !important;
|
padding: 2px 11px 0 !important;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@ -589,6 +598,78 @@ span[data-tooltip]:hover:before {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-fields {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-field {
|
||||||
|
background: hsl(210,7%,95%);
|
||||||
|
color: hsl(0,0%,66%);
|
||||||
|
padding: 8px 10px 6px;
|
||||||
|
border: 1px solid hsl(0,0%,91%);
|
||||||
|
box-shadow: 0 1px rgba(0,0,0,.02) inset;
|
||||||
|
|
||||||
|
&:not(:last-child):not(:only-child) {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:only-child {
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
background: hsl(210,5%,77%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 18px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: top;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: hsl(198,18%,86%);
|
||||||
|
margin-right: 3px;
|
||||||
|
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.badge--big {
|
||||||
|
min-width: 22px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 11px;
|
||||||
|
padding: 5px 7px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.badge--text {
|
||||||
|
min-width: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin-right: 5px;
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: left;
|
||||||
|
color: #d0d2d3;
|
||||||
|
background: none;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
table {
|
table {
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
|
@ -864,6 +945,7 @@ label,
|
||||||
|
|
||||||
/* circumventing the label:not(.inline-label) selector because it's too strong */
|
/* circumventing the label:not(.inline-label) selector because it's too strong */
|
||||||
.inline-label,
|
.inline-label,
|
||||||
|
.label.label-success,
|
||||||
.label.label-warning,
|
.label.label-warning,
|
||||||
.label.label-danger {
|
.label.label-danger {
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
|
@ -882,11 +964,16 @@ label,
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.label.label-success,
|
||||||
.label.label-warning,
|
.label.label-warning,
|
||||||
.label.label-danger {
|
.label.label-danger {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.label.label-success {
|
||||||
|
color: $supergood-color;
|
||||||
|
}
|
||||||
|
|
||||||
.label.label-warning {
|
.label.label-warning {
|
||||||
color: $ok-color;
|
color: $ok-color;
|
||||||
}
|
}
|
||||||
|
@ -1130,12 +1217,12 @@ textarea,
|
||||||
.form-control,
|
.form-control,
|
||||||
.checkbox.form-group .checkbox {
|
.checkbox.form-group .checkbox {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 6px 12px;
|
padding: 7px 12px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 41px;
|
height: 41px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
line-height: 27px;
|
line-height: 25px;
|
||||||
color: #555;
|
color: #555;
|
||||||
background: white;
|
background: white;
|
||||||
border: 1px solid hsl(0, 0%, 90%);
|
border: 1px solid hsl(0, 0%, 90%);
|
||||||
|
@ -1146,15 +1233,19 @@ textarea,
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
|
||||||
&.form-control--small {
|
&.form-control--small {
|
||||||
padding: 0 8px;
|
padding: 5px 8px 4px;
|
||||||
height: 31px;
|
height: 31px;
|
||||||
line-height: 29px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.form-control--inline {
|
&.form-control--inline {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.form-control--multiline {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=url] {
|
input[type=url] {
|
||||||
|
@ -1575,6 +1666,17 @@ kbd {
|
||||||
|
|
||||||
.page-header-title h1 {
|
.page-header-title h1 {
|
||||||
margin-top: 9px;
|
margin-top: 9px;
|
||||||
|
margin-bottom: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header-center {
|
||||||
|
justify-self: center;
|
||||||
|
padding-left: 9px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
& + .page-header-meta {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header-meta {
|
.page-header-meta {
|
||||||
|
@ -1991,6 +2093,21 @@ ol.tabs li {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-status-modified-inner-circle {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
will-change: opacity;
|
||||||
|
transform: translateZ(0);
|
||||||
|
animation: fade 1.8s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade {
|
||||||
|
54% { opacity: 1 }
|
||||||
|
90% { opacity: 0 }
|
||||||
|
to { opacity: 1 }
|
||||||
|
}
|
||||||
|
|
||||||
.icon-checkbox,
|
.icon-checkbox,
|
||||||
.icon-checkbox-checked {
|
.icon-checkbox-checked {
|
||||||
fill: white;
|
fill: white;
|
||||||
|
@ -2164,6 +2281,16 @@ footer {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.main-navigation .badge {
|
||||||
|
background: $ok-color;
|
||||||
|
color: hsl(233,10%,16%);
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-navigation .zammad-switch {
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
.main-navigation > li > a {
|
.main-navigation > li > a {
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
|
@ -2326,21 +2453,6 @@ footer {
|
||||||
height: 12px;
|
height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-tab-icon .modified-inner-circle {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
will-change: opacity;
|
|
||||||
transform: translateZ(0);
|
|
||||||
animation: fade 1.8s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade {
|
|
||||||
54% { opacity: 1 }
|
|
||||||
90% { opacity: 0 }
|
|
||||||
to { opacity: 1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-tab-icon .icon.icon-loading {
|
.nav-tab-icon .icon.icon-loading {
|
||||||
animation: rotateplane 1.2s infinite ease-in-out;
|
animation: rotateplane 1.2s infinite ease-in-out;
|
||||||
fill: $supergood-color;
|
fill: $supergood-color;
|
||||||
|
@ -2866,18 +2978,6 @@ footer {
|
||||||
border-top: none;
|
border-top: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
|
||||||
min-width: 0;
|
|
||||||
padding: 0;
|
|
||||||
margin-right: 5px;
|
|
||||||
font-size: inherit;
|
|
||||||
font-weight: normal;
|
|
||||||
text-align: left;
|
|
||||||
color: #d0d2d3;
|
|
||||||
background: none;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-pills > li > a > .badge {
|
.nav-pills > li > a > .badge {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
@ -3162,7 +3262,7 @@ footer {
|
||||||
}
|
}
|
||||||
|
|
||||||
.time.stat-widget .stat-amount {
|
.time.stat-widget .stat-amount {
|
||||||
margin-top: 8px;
|
margin-top: 12px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -5843,11 +5943,36 @@ output {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-switch label {
|
.zammad-switch {
|
||||||
position: relative;
|
width: 50px;
|
||||||
width: 48px;
|
|
||||||
height: 30px;
|
height: 30px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&.zammad-switch--small {
|
||||||
|
width: 40px;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.zammad-switch--dark {
|
||||||
|
label {
|
||||||
|
background: hsl(234,10%,5%);
|
||||||
|
}
|
||||||
|
label:before {
|
||||||
|
background: hsl(233,10%,10%);
|
||||||
|
}
|
||||||
|
label:after {
|
||||||
|
background: hsl(234,10%,19%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.zammad-switch label {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: inherit;
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: hsl(0,0%,90%);
|
background: hsl(0,0%,90%);
|
||||||
|
@ -5859,7 +5984,7 @@ output {
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-switch input:checked + label {
|
.zammad-switch input:checked + label {
|
||||||
background: hsl(200,71%,59%);
|
background: $supergood-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-switch input:focus + label {
|
.zammad-switch input:focus + label {
|
||||||
|
@ -5876,8 +6001,8 @@ output {
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-switch label:before {
|
.zammad-switch label:before {
|
||||||
width: 46px;
|
width: calc(100% - 2px);
|
||||||
height: 28px;
|
height: calc(100% - 2px);
|
||||||
left: 1px;
|
left: 1px;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
border-radius: inherit;
|
border-radius: inherit;
|
||||||
|
@ -5891,9 +6016,9 @@ output {
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-switch label:after {
|
.zammad-switch label:after {
|
||||||
width: 28px;
|
width: calc(60% - 2px);
|
||||||
height: 28px;
|
height: calc(100% - 2px);
|
||||||
border-radius: 100%;
|
border-radius: inherit;
|
||||||
left: 1px;
|
left: 1px;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
|
@ -5903,7 +6028,7 @@ output {
|
||||||
}
|
}
|
||||||
|
|
||||||
.zammad-switch input:checked + label:after {
|
.zammad-switch input:checked + label:after {
|
||||||
transform: translateX(18px);
|
transform: translateX(70%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.horizontal-filter-text {
|
.horizontal-filter-text {
|
||||||
|
@ -6545,6 +6670,222 @@ output {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat {
|
||||||
|
background: white;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
margin: 15px 6px 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-workspace {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0 0 10px;
|
||||||
|
margin: 0 -4px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-window {
|
||||||
|
flex: 0 1 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
color: hsl(0,0%,33%);
|
||||||
|
transition: all 500ms;
|
||||||
|
transform: scale(0);
|
||||||
|
|
||||||
|
&.is-open {
|
||||||
|
flex: 1 0 25%;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-offline {
|
||||||
|
.chat-body-holder,
|
||||||
|
.chat-controls {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-header {
|
||||||
|
padding: 12px 40px;
|
||||||
|
background: hsl(210,8%,95%);
|
||||||
|
border: 1px solid hsl(0,0%,91%);
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
position: relative;
|
||||||
|
line-height: 13px;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-status,
|
||||||
|
.chat-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
padding-top: inherit;
|
||||||
|
padding-bottom: inherit;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-status {
|
||||||
|
left: 0;
|
||||||
|
top: -1px;
|
||||||
|
|
||||||
|
&[data-status='online'] .icon {
|
||||||
|
fill: $supergood-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-status='offline'] .icon {
|
||||||
|
fill: $superbad-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-status-modified-inner-circle,
|
||||||
|
.icon-status-modified-outer-circle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-modified {
|
||||||
|
.icon-status {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-status-modified-inner-circle,
|
||||||
|
.icon-status-modified-outer-circle {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-status-holder {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-close {
|
||||||
|
right: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: hsl(197,19%,78%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: hsl(197,18%,96%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-body-holder {
|
||||||
|
flex: 1;
|
||||||
|
background: hsl(210,17%,98%);
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
overflow: auto;
|
||||||
|
border-right: 1px solid hsl(0,0%,91%);
|
||||||
|
border-left: 1px solid hsl(0,0%,91%);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-body {
|
||||||
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-timestamp {
|
||||||
|
font-size: 12px;
|
||||||
|
color: hsl(10,5%,78%);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-timestamp-label {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message {
|
||||||
|
max-width: 90%;
|
||||||
|
background: white;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 16px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message--customer.chat-message--new {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message--agent {
|
||||||
|
margin-left: auto;
|
||||||
|
background: hsl(199,44%,93%);
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-message--agent + .chat-message--customer,
|
||||||
|
.chat-message--customer + .chat-message--agent {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-status-message {
|
||||||
|
align-self: center;
|
||||||
|
background: hsl(197,18%,92%);
|
||||||
|
padding: 6px 12px;
|
||||||
|
margin: 4px 0 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-loader {
|
||||||
|
margin-right: -4px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
fill: hsl(0,0%,90%);
|
||||||
|
margin-left: -4px;
|
||||||
|
vertical-align: middle;
|
||||||
|
animation: fadeInDown 300ms both;
|
||||||
|
animation: ease-in-out load-fade 600ms infinite alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon + .icon {
|
||||||
|
animation-delay: .13s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon + .icon + .icon {
|
||||||
|
animation-delay: .26s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes load-fade {
|
||||||
|
from { opacity: .5; transform: scale(0.6); }
|
||||||
|
67% { opacity: 1; transform: scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid hsl(0,0%,91%);
|
||||||
|
border-radius: 0 0 3px 3px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input {
|
||||||
|
margin-right: 10px;
|
||||||
|
max-height: 50vh;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
|
|
BIN
public/assets/fonts/FiraSans-Medium.eot
Normal file
BIN
public/assets/fonts/FiraSans-Medium.ttf
Normal file
BIN
public/assets/fonts/FiraSans-Medium.woff
Normal file
BIN
public/assets/fonts/FiraSans-Medium.woff2
Normal file
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 50 KiB |
12
public/assets/images/icons/chat.svg
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||||
|
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>chat</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||||
|
<g id="chat" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
||||||
|
<path d="M2,5.00585866 C2,3.89805351 2.89821238,3 3.99079514,3 L20.0092049,3 C21.1086907,3 22,3.89706013 22,5.00585866 L22,14.9941413 C22,16.1019465 21.1017876,17 20.0092049,17 L3.99079514,17 C2.89130934,17 2,16.1029399 2,14.9941413 L2,5.00585866 Z M12,17 L18,21 L18,17 L12,17 Z" id="Chat" sketch:type="MSShapeGroup"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 955 B |
|
@ -6,7 +6,7 @@
|
||||||
<defs></defs>
|
<defs></defs>
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||||
<g id="dashboard" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
<g id="dashboard" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
||||||
<path d="M11.9671579,2 C6.44426901,2 1.9671579,6.47711111 1.9671579,12 C1.9671579,17.5228889 6.44426901,22 11.9671579,22 C17.490269,22 21.9671579,17.5228889 21.9671579,12 C21.9671579,6.47711111 17.490269,2 11.9671579,2 L11.9671579,2 L11.9671579,2 Z M11.9671579,20.1248889 C10.5864912,20.1248889 9.4671579,19.0055556 9.4671579,17.6248889 C9.4671579,17.52 11.9671579,9.18755556 11.9671579,9.18755556 C11.9671579,9.18755556 14.4671579,17.52 14.4671579,17.6248889 C14.4671579,19.0055556 13.3478246,20.1248889 11.9671579,20.1248889 L11.9671579,20.1248889 L11.9671579,20.1248889 Z M18.3391579,15.9544444 C19.0533801,14.8064444 19.4671579,13.452 19.4671579,12 C19.4671579,7.85777778 16.1096023,4.5 11.9671579,4.5 C7.82493568,4.5 4.4671579,7.85777778 4.4671579,12 C4.4671579,13.452 4.88093568,14.8064444 5.59493568,15.9544444 L4.57871346,16.6853333 C3.71804679,15.3302222 3.2171579,13.7242222 3.2171579,12 C3.2171579,7.16755556 7.13471346,3.25 11.9671579,3.25 C16.7998246,3.25 20.7171579,7.16755556 20.7171579,12 C20.7171579,13.7242222 20.2160468,15.3302222 19.3553801,16.6853333 L18.3391579,15.9544444 L18.3391579,15.9544444 Z" sketch:type="MSShapeGroup"></path>
|
<path d="M11.9671579,2 C6.44426901,2 1.9671579,6.47711111 1.9671579,12 C1.9671579,17.5228889 6.44426901,22 11.9671579,22 C17.490269,22 21.9671579,17.5228889 21.9671579,12 C21.9671579,6.47711111 17.490269,2 11.9671579,2 L11.9671579,2 L11.9671579,2 Z M9.82400492,11.1709229 C9.89058924,11.0792774 17.3644383,5.38592124 17.3644383,5.38592124 C17.3644383,5.38592124 14.2592811,14.2533179 14.1926968,14.3449633 C13.3162384,15.5513048 11.6276721,15.8187474 10.4213306,14.942289 C9.21498916,14.0658307 8.94754654,12.3772644 9.82400492,11.1709229 Z M19.4671579,12 C19.4671579,7.85777778 16.1096023,4.5 11.9671579,4.5 C7.82493568,4.5 4.4671579,7.85777778 4.4671579,12 C4.4671579,13.452 4.88093568,14.8064444 5.59493568,15.9544444 L4.57871346,16.6853333 C3.71804679,15.3302222 3.2171579,13.7242222 3.2171579,12 C3.2171579,7.16755556 7.13471346,3.25 11.9671579,3.25 C16.7998246,3.25 20.7171579,7.16755556 20.7171579,12 C20.7171579,13.7242222 20.2160468,15.3302222 19.3553801,16.6853333 L18.3391579,15.9544444 C19.0533801,14.8064444 19.4671579,13.452 19.4671579,12 Z" sketch:type="MSShapeGroup"></path>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
|
||||||
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
|
||||||
<title>priority</title>
|
|
||||||
<desc>Created with Sketch.</desc>
|
|
||||||
<defs></defs>
|
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
|
||||||
<g id="priority" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
|
||||||
<path d="M8.00000001,13.5 C11.0375661,13.5 13.5,11.0375661 13.5,8.00000001 C13.5,4.96243388 11.0375661,2.50000001 8.00000001,2.50000001 C4.96243388,2.50000001 2.50000001,4.96243388 2.50000001,8.00000001 C2.50000001,11.0375661 4.96243388,13.5 8.00000001,13.5 Z M8.00000001,11.0833333 C9.70287799,11.0833333 11.0833333,9.70287799 11.0833333,8.00000001 C11.0833333,6.29712203 9.70287799,4.91666667 8.00000001,4.91666667 C6.29712203,4.91666667 4.91666667,6.29712203 4.91666667,8.00000001 C4.91666667,9.70287799 6.29712203,11.0833333 8.00000001,11.0833333 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1.2 KiB |
|
@ -1,11 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||||
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
||||||
<title>priority-modified-inner-circle</title>
|
<title>status-modified-inner-circle</title>
|
||||||
<desc>Created with Sketch.</desc>
|
<desc>Created with Sketch.</desc>
|
||||||
<defs></defs>
|
<defs></defs>
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||||
<g id="priority-modified-inner-circle" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
<g id="status-modified-inner-circle" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
||||||
<circle id="Oval-2" sketch:type="MSShapeGroup" cx="8" cy="8" r="3"></circle>
|
<circle id="Oval-2" sketch:type="MSShapeGroup" cx="8" cy="8" r="3"></circle>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 755 B |
|
@ -1,11 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||||
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
||||||
<title>priority-modified-outer-circle</title>
|
<title>status-modified-outer-circle</title>
|
||||||
<desc>Created with Sketch.</desc>
|
<desc>Created with Sketch.</desc>
|
||||||
<defs></defs>
|
<defs></defs>
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||||
<g id="priority-modified-outer-circle" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
<g id="status-modified-outer-circle" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
||||||
<path d="M8,14 C11.3137085,14 14,11.3137085 14,8 C14,4.6862915 11.3137085,2 8,2 C4.6862915,2 2,4.6862915 2,8 C2,11.3137085 4.6862915,14 8,14 Z M8,13 C10.7614237,13 13,10.7614237 13,8 C13,5.23857625 10.7614237,3 8,3 C5.23857625,3 3,5.23857625 3,8 C3,10.7614237 5.23857625,13 8,13 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>
|
<path d="M8,14 C11.3137085,14 14,11.3137085 14,8 C14,4.6862915 11.3137085,2 8,2 C4.6862915,2 2,4.6862915 2,8 C2,11.3137085 4.6862915,14 8,14 Z M8,13 C10.7614237,13 13,10.7614237 13,8 C13,5.23857625 10.7614237,3 8,3 C5.23857625,3 3,5.23857625 3,8 C3,10.7614237 5.23857625,13 8,13 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
Before Width: | Height: | Size: 1,011 B After Width: | Height: | Size: 1,007 B |
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
|
||||||
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
|
||||||
<title>task-state-modified-inner-circle</title>
|
|
||||||
<desc>Created with Sketch.</desc>
|
|
||||||
<defs></defs>
|
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
|
||||||
<g id="task-state-modified-inner-circle" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
|
||||||
<circle id="Oval-2" sketch:type="MSShapeGroup" cx="8" cy="8" r="3"></circle>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 763 B |
|
@ -1,12 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
|
||||||
<!-- Generator: Sketch 3.3.3 (12072) - http://www.bohemiancoding.com/sketch -->
|
|
||||||
<title>task-state-modified-outer-circle</title>
|
|
||||||
<desc>Created with Sketch.</desc>
|
|
||||||
<defs></defs>
|
|
||||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
|
||||||
<g id="task-state-modified-outer-circle" sketch:type="MSArtboardGroup" fill="#50E3C2">
|
|
||||||
<path d="M8,14 C11.3137085,14 14,11.3137085 14,8 C14,4.6862915 11.3137085,2 8,2 C4.6862915,2 2,4.6862915 2,8 C2,11.3137085 4.6862915,14 8,14 Z M8,13 C10.7614237,13 13,10.7614237 13,8 C13,5.23857625 10.7614237,3 8,3 C5.23857625,3 3,5.23857625 3,8 C3,10.7614237 5.23857625,13 8,13 Z" id="Oval-2" sketch:type="MSShapeGroup"></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1,015 B |