Added keyboard support to online notifications. Added browser tests. Improved search keyboard support.
This commit is contained in:
parent
105b36c641
commit
532d562845
9 changed files with 244 additions and 70 deletions
|
@ -82,6 +82,11 @@ Copyright: @leChanteaux <santiago at mural.ly>
|
||||||
Mural.ly Dev Team <dev at mural.ly>
|
Mural.ly Dev Team <dev at mural.ly>
|
||||||
License: dfyw
|
License: dfyw
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
jquery.visible.js
|
||||||
|
Source: https://github.com/customd/jquery-visible
|
||||||
|
Copyright: 2012, Digital Fusion
|
||||||
|
License: MIT license
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
marked.js
|
marked.js
|
||||||
Source: https://github.com/chjj/marked
|
Source: https://github.com/chjj/marked
|
||||||
Copyright: 2011-2014, Christopher Jeffrey
|
Copyright: 2011-2014, Christopher Jeffrey
|
||||||
|
|
|
@ -128,32 +128,32 @@ class App.Controller extends Spine.Controller
|
||||||
return if !$('#navigation').is(':visible')
|
return if !$('#navigation').is(':visible')
|
||||||
$('#navigation').addClass('hide')
|
$('#navigation').addClass('hide')
|
||||||
|
|
||||||
scrollTo: ( x = 0, y = 0, delay = 0 ) ->
|
scrollTo: (x = 0, y = 0, delay = 0) ->
|
||||||
a = ->
|
a = ->
|
||||||
window.scrollTo( x, y )
|
window.scrollTo(x, y)
|
||||||
|
|
||||||
@delay( a, delay )
|
@delay(a, delay)
|
||||||
|
|
||||||
shake: (element) ->
|
shake: (element) ->
|
||||||
|
|
||||||
# this part is from wordpress 3, thanks to open source
|
# this part is from wordpress 3, thanks to open source
|
||||||
shakeMe = (element, position, positionEnd) ->
|
shakeMe = (element, position, positionEnd) ->
|
||||||
positionStart = position.shift()
|
positionStart = position.shift()
|
||||||
element.css( 'left', positionStart + 'px' )
|
element.css('left', positionStart + 'px')
|
||||||
if position.length > 0
|
if position.length > 0
|
||||||
setTimeout( ->
|
setTimeout(->
|
||||||
shakeMe( element, position, positionEnd )
|
shakeMe(element, position, positionEnd)
|
||||||
, positionEnd)
|
, positionEnd)
|
||||||
else
|
else
|
||||||
try
|
try
|
||||||
element.css( 'position', 'static' )
|
element.css('position', 'static')
|
||||||
catch e
|
catch e
|
||||||
console.log 'error', e
|
console.log 'error', e
|
||||||
|
|
||||||
position = [ 15, 30, 15, 0, -15, -30, -15, 0 ]
|
position = [ 15, 30, 15, 0, -15, -30, -15, 0 ]
|
||||||
position = position.concat( position.concat( position ) )
|
position = position.concat(position.concat(position))
|
||||||
element.css( 'position', 'relative' )
|
element.css('position', 'relative')
|
||||||
shakeMe( element, position, 20 )
|
shakeMe(element, position, 20)
|
||||||
|
|
||||||
isRole: (name) ->
|
isRole: (name) ->
|
||||||
roles = @Session.get('roles')
|
roles = @Session.get('roles')
|
||||||
|
@ -183,8 +183,8 @@ class App.Controller extends Spine.Controller
|
||||||
App.Utils.humanFileSize(size)
|
App.Utils.humanFileSize(size)
|
||||||
|
|
||||||
# human readable time
|
# human readable time
|
||||||
humanTime: ( time, escalation, long = true ) ->
|
humanTime: (time, escalation, long = true) ->
|
||||||
App.PrettyDate.humanTime( time, escalation, long )
|
App.PrettyDate.humanTime(time, escalation, long)
|
||||||
|
|
||||||
userInfo: (data) ->
|
userInfo: (data) ->
|
||||||
el = data.el || $('[data-id="customer_info"]')
|
el = data.el || $('[data-id="customer_info"]')
|
||||||
|
@ -206,7 +206,7 @@ class App.Controller extends Spine.Controller
|
||||||
if !checkOnly
|
if !checkOnly
|
||||||
location = window.location.hash
|
location = window.location.hash
|
||||||
if location isnt '#login' && location isnt '#logout' && location isnt '#keyboard_shortcuts'
|
if location isnt '#login' && location isnt '#logout' && location isnt '#keyboard_shortcuts'
|
||||||
@Config.set( 'requested_url', location)
|
@Config.set('requested_url', location)
|
||||||
|
|
||||||
return false if checkOnly
|
return false if checkOnly
|
||||||
|
|
||||||
|
@ -262,16 +262,16 @@ class App.Controller extends Spine.Controller
|
||||||
placement: position
|
placement: position
|
||||||
title: ->
|
title: ->
|
||||||
ticket_id = $(@).data('id')
|
ticket_id = $(@).data('id')
|
||||||
ticket = App.Ticket.fullLocal( ticket_id )
|
ticket = App.Ticket.fullLocal(ticket_id)
|
||||||
App.Utils.htmlEscape( ticket.title )
|
App.Utils.htmlEscape(ticket.title)
|
||||||
content: ->
|
content: ->
|
||||||
ticket_id = $(@).data('id')
|
ticket_id = $(@).data('id')
|
||||||
ticket = App.Ticket.fullLocal( ticket_id )
|
ticket = App.Ticket.fullLocal(ticket_id)
|
||||||
html = App.view('popover/ticket')(
|
html = App.view('popover/ticket')(
|
||||||
ticket: ticket
|
ticket: ticket
|
||||||
)
|
)
|
||||||
html = $(html)
|
html = $(html)
|
||||||
html.find('.humanTimeFromNow').each( ->
|
html.find('.humanTimeFromNow').each(->
|
||||||
item = $(@)
|
item = $(@)
|
||||||
ui.frontendTimeUpdateItem(item)
|
ui.frontendTimeUpdateItem(item)
|
||||||
)
|
)
|
||||||
|
@ -306,11 +306,11 @@ class App.Controller extends Spine.Controller
|
||||||
placement: "auto #{position}"
|
placement: "auto #{position}"
|
||||||
title: ->
|
title: ->
|
||||||
user_id = $(@).data('id')
|
user_id = $(@).data('id')
|
||||||
user = App.User.fullLocal( user_id )
|
user = App.User.fullLocal(user_id)
|
||||||
App.Utils.htmlEscape( user.displayName() )
|
App.Utils.htmlEscape(user.displayName())
|
||||||
content: ->
|
content: ->
|
||||||
user_id = $(@).data('id')
|
user_id = $(@).data('id')
|
||||||
user = App.User.fullLocal( user_id )
|
user = App.User.fullLocal(user_id)
|
||||||
|
|
||||||
# get display data
|
# get display data
|
||||||
userData = []
|
userData = []
|
||||||
|
@ -318,7 +318,7 @@ class App.Controller extends Spine.Controller
|
||||||
|
|
||||||
# check if value for _id exists
|
# check if value for _id exists
|
||||||
name = attributeName
|
name = attributeName
|
||||||
nameNew = name.substr( 0, name.length - 3 )
|
nameNew = name.substr(0, name.length - 3)
|
||||||
if nameNew of user
|
if nameNew of user
|
||||||
name = nameNew
|
name = nameNew
|
||||||
|
|
||||||
|
@ -364,11 +364,11 @@ class App.Controller extends Spine.Controller
|
||||||
placement: "auto #{position}"
|
placement: "auto #{position}"
|
||||||
title: ->
|
title: ->
|
||||||
organization_id = $(@).data('id')
|
organization_id = $(@).data('id')
|
||||||
organization = App.Organization.fullLocal( organization_id )
|
organization = App.Organization.fullLocal(organization_id)
|
||||||
App.Utils.htmlEscape( organization.name )
|
App.Utils.htmlEscape(organization.name)
|
||||||
content: ->
|
content: ->
|
||||||
organization_id = $(@).data('id')
|
organization_id = $(@).data('id')
|
||||||
organization = App.Organization.fullLocal( organization_id )
|
organization = App.Organization.fullLocal(organization_id)
|
||||||
|
|
||||||
# get display data
|
# get display data
|
||||||
organizationData = []
|
organizationData = []
|
||||||
|
@ -376,7 +376,7 @@ class App.Controller extends Spine.Controller
|
||||||
|
|
||||||
# check if value for _id exists
|
# check if value for _id exists
|
||||||
name = attributeName
|
name = attributeName
|
||||||
nameNew = name.substr( 0, name.length - 3 )
|
nameNew = name.substr(0, name.length - 3)
|
||||||
if nameNew of organization
|
if nameNew of organization
|
||||||
name = nameNew
|
name = nameNew
|
||||||
|
|
||||||
|
@ -424,13 +424,13 @@ class App.Controller extends Spine.Controller
|
||||||
tickets = []
|
tickets = []
|
||||||
if ticket_list[type]
|
if ticket_list[type]
|
||||||
for ticket_id in ticket_list[type]
|
for ticket_id in ticket_list[type]
|
||||||
tickets.push App.Ticket.fullLocal( ticket_id )
|
tickets.push App.Ticket.fullLocal(ticket_id)
|
||||||
|
|
||||||
# insert data
|
# insert data
|
||||||
html = App.view('popover/user_ticket_list')(
|
html = App.view('popover/user_ticket_list')(
|
||||||
tickets: tickets
|
tickets: tickets
|
||||||
)
|
)
|
||||||
html = $( html )
|
html = $(html )
|
||||||
html.find('.humanTimeFromNow').each( ->
|
html.find('.humanTimeFromNow').each( ->
|
||||||
item = $(@)
|
item = $(@)
|
||||||
ui.frontendTimeUpdateItem(item)
|
ui.frontendTimeUpdateItem(item)
|
||||||
|
@ -440,15 +440,14 @@ class App.Controller extends Spine.Controller
|
||||||
|
|
||||||
fetch = (params) =>
|
fetch = (params) =>
|
||||||
@ajax(
|
@ajax(
|
||||||
type: 'GET',
|
type: 'GET'
|
||||||
url: @Config.get('api_path') + '/ticket_customer',
|
url: @Config.get('api_path') + '/ticket_customer'
|
||||||
data: {
|
data:
|
||||||
customer_id: params.user_id,
|
customer_id: params.user_id
|
||||||
}
|
processData: true
|
||||||
processData: true,
|
|
||||||
success: (data, status, xhr) ->
|
success: (data, status, xhr) ->
|
||||||
App.Collection.loadAssets( data.assets )
|
App.Collection.loadAssets(data.assets)
|
||||||
show( params, { open: data.ticket_ids_open, closed: data.ticket_ids_closed } )
|
show(params, { open: data.ticket_ids_open, closed: data.ticket_ids_closed })
|
||||||
)
|
)
|
||||||
|
|
||||||
# get data
|
# get data
|
||||||
|
@ -514,10 +513,10 @@ class App.Controller extends Spine.Controller
|
||||||
item.default = params[item.name]
|
item.default = params[item.name]
|
||||||
#if !item.default
|
#if !item.default
|
||||||
# delete item['default']
|
# delete item['default']
|
||||||
newElement = ui.formGenItem( item, classname, form )
|
newElement = ui.formGenItem(item, classname, form)
|
||||||
|
|
||||||
# replace new option list
|
# replace new option list
|
||||||
form.find('[name="' + fieldNameToChange + '"]').closest('.form-group').replaceWith( newElement )
|
form.find('[name="' + fieldNameToChange + '"]').closest('.form-group').replaceWith(newElement)
|
||||||
|
|
||||||
stopPropagation: (e) ->
|
stopPropagation: (e) ->
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
@ -712,7 +711,6 @@ class App.ControllerModal extends App.Controller
|
||||||
'hide.bs.modal': @onClose
|
'hide.bs.modal': @onClose
|
||||||
'hidden.bs.modal': =>
|
'hidden.bs.modal': =>
|
||||||
@onClosed()
|
@onClosed()
|
||||||
# remove modal from dom
|
|
||||||
$('.modal').remove()
|
$('.modal').remove()
|
||||||
|
|
||||||
close: (e) =>
|
close: (e) =>
|
||||||
|
|
|
@ -195,7 +195,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
@$('form.search').on('submit', (e) ->
|
@$('form.search').on('submit', (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
)
|
)
|
||||||
@$('#global-search').on('keydown', @navigate)
|
@$('#global-search').on('keydown', @listNavigate)
|
||||||
|
|
||||||
# bind to empty search
|
# bind to empty search
|
||||||
@$('.empty-search').on('click', =>
|
@$('.empty-search').on('click', =>
|
||||||
|
@ -206,7 +206,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
el: @el
|
el: @el
|
||||||
)
|
)
|
||||||
|
|
||||||
navigate: (e) =>
|
listNavigate: (e) =>
|
||||||
if e.keyCode is 27 # close on esc
|
if e.keyCode is 27 # close on esc
|
||||||
@emptyAndClose()
|
@emptyAndClose()
|
||||||
return
|
return
|
||||||
|
@ -217,7 +217,7 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
@nudge(e, 1)
|
@nudge(e, 1)
|
||||||
return
|
return
|
||||||
else if e.keyCode is 13 # enter
|
else if e.keyCode is 13 # enter
|
||||||
href = @$('#global-search-result .nav-tab.is-active').attr('href')
|
href = @$('#global-search-result .nav-tab.is-hover').attr('href')
|
||||||
@locationExecute(href)
|
@locationExecute(href)
|
||||||
@emptyAndClose()
|
@emptyAndClose()
|
||||||
return
|
return
|
||||||
|
@ -229,21 +229,29 @@ class App.Navigation extends App.ControllerWidgetPermanent
|
||||||
|
|
||||||
# get current
|
# get current
|
||||||
navigationResult = @$('#global-search-result')
|
navigationResult = @$('#global-search-result')
|
||||||
current = navigationResult.find('.nav-tab.is-active')
|
current = navigationResult.find('.nav-tab.is-hover')
|
||||||
if !current.get(0)
|
if !current.get(0)
|
||||||
navigationResult.find('.nav-tab').first().addClass('is-active')
|
navigationResult.find('.nav-tab').first().addClass('is-hover')
|
||||||
return
|
return
|
||||||
|
|
||||||
if position is 1
|
if position is 1
|
||||||
next = current.closest('li').nextAll('li').not('.divider').first().find('.nav-tab')
|
next = current.closest('li').nextAll('li').not('.divider').first().find('.nav-tab')
|
||||||
if next.get(0)
|
if next.get(0)
|
||||||
current.removeClass('is-active').popover('hide')
|
current.removeClass('is-hover').popover('hide')
|
||||||
next.addClass('is-active').popover('show')
|
next.addClass('is-hover').popover('show')
|
||||||
else
|
else
|
||||||
prev = current.closest('li').prevAll('li').not('.divider').first().find('.nav-tab')
|
prev = current.closest('li').prevAll('li').not('.divider').first().find('.nav-tab')
|
||||||
if prev.get(0)
|
if prev.get(0)
|
||||||
current.removeClass('is-active').popover('hide')
|
current.removeClass('is-hover').popover('hide')
|
||||||
prev.addClass('is-active').popover('show')
|
prev.addClass('is-hover').popover('show')
|
||||||
|
|
||||||
|
if next
|
||||||
|
element = next.get(0)
|
||||||
|
if prev
|
||||||
|
element = prev.get(0)
|
||||||
|
return if !element
|
||||||
|
return if $(element).visible(true)
|
||||||
|
element.scrollIntoView()
|
||||||
|
|
||||||
emptyAndClose: =>
|
emptyAndClose: =>
|
||||||
@$('#global-search').val('').blur()
|
@$('#global-search').val('').blur()
|
||||||
|
|
|
@ -59,6 +59,7 @@ App.Config.set(
|
||||||
description: 'Dashboard'
|
description: 'Dashboard'
|
||||||
callback: (e) ->
|
callback: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
$('#global-search').blur()
|
||||||
App.Event.trigger('keyboard_shortcuts_close')
|
App.Event.trigger('keyboard_shortcuts_close')
|
||||||
window.location.hash = '#dashboard'
|
window.location.hash = '#dashboard'
|
||||||
}
|
}
|
||||||
|
@ -68,6 +69,7 @@ App.Config.set(
|
||||||
description: 'Overviews'
|
description: 'Overviews'
|
||||||
callback: (e) ->
|
callback: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
$('#global-search').blur()
|
||||||
App.Event.trigger('keyboard_shortcuts_close')
|
App.Event.trigger('keyboard_shortcuts_close')
|
||||||
window.location.hash = '#ticket/view'
|
window.location.hash = '#ticket/view'
|
||||||
}
|
}
|
||||||
|
@ -80,12 +82,23 @@ App.Config.set(
|
||||||
App.Event.trigger('keyboard_shortcuts_close')
|
App.Event.trigger('keyboard_shortcuts_close')
|
||||||
$('#global-search').focus()
|
$('#global-search').focus()
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
key: 'y'
|
||||||
|
hotkeys: true
|
||||||
|
description: 'Notifications'
|
||||||
|
callback: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
$('#global-search').blur()
|
||||||
|
App.Event.trigger('keyboard_shortcuts_close')
|
||||||
|
$('#navigation .js-toggleNotifications').click()
|
||||||
|
}
|
||||||
{
|
{
|
||||||
key: 'n'
|
key: 'n'
|
||||||
hotkeys: true
|
hotkeys: true
|
||||||
description: 'New Ticket'
|
description: 'New Ticket'
|
||||||
callback: (e) ->
|
callback: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
$('#global-search').blur()
|
||||||
App.Event.trigger('keyboard_shortcuts_close')
|
App.Event.trigger('keyboard_shortcuts_close')
|
||||||
window.location.hash = '#ticket/create'
|
window.location.hash = '#ticket/create'
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ class App.OnlineNotificationWidget extends App.Controller
|
||||||
release: ->
|
release: ->
|
||||||
@removeContainer()
|
@removeContainer()
|
||||||
$(window).off 'click.notifications'
|
$(window).off 'click.notifications'
|
||||||
|
$(window).off 'keydown.notifications'
|
||||||
App.OnlineNotification.unsubscribe(@subscribeId)
|
App.OnlineNotification.unsubscribe(@subscribeId)
|
||||||
|
|
||||||
access: ->
|
access: ->
|
||||||
|
@ -56,6 +57,48 @@ class App.OnlineNotificationWidget extends App.Controller
|
||||||
return true if @isRole('Admin')
|
return true if @isRole('Admin')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
listNavigate: (e) =>
|
||||||
|
|
||||||
|
if e.keyCode is 27 # close on esc
|
||||||
|
@hidePopover()
|
||||||
|
return
|
||||||
|
else if e.keyCode is 38 # up
|
||||||
|
@nudge(e, -1)
|
||||||
|
return
|
||||||
|
else if e.keyCode is 40 # down
|
||||||
|
@nudge(e, 1)
|
||||||
|
return
|
||||||
|
else if e.keyCode is 13 # enter
|
||||||
|
$('.js-notificationsContainer .popover-content .activity-entry.is-hover .js-locationVerify').click()
|
||||||
|
|
||||||
|
nudge: (e, position) ->
|
||||||
|
|
||||||
|
# get current
|
||||||
|
navigation = $('.js-notificationsContainer .popover-content')
|
||||||
|
current = navigation.find('.activity-entry.is-hover')
|
||||||
|
if !current.get(0)
|
||||||
|
navigation.find('.activity-entry').first().addClass('is-hover')
|
||||||
|
return
|
||||||
|
|
||||||
|
if position is 1
|
||||||
|
next = current.next('.activity-entry')
|
||||||
|
if next.get(0)
|
||||||
|
current.removeClass('is-hover')
|
||||||
|
next.addClass('is-hover')
|
||||||
|
else
|
||||||
|
prev = current.prev('.activity-entry')
|
||||||
|
if prev.get(0)
|
||||||
|
current.removeClass('is-hover')
|
||||||
|
prev.addClass('is-hover')
|
||||||
|
|
||||||
|
if next
|
||||||
|
element = next.get(0)
|
||||||
|
if prev
|
||||||
|
element = prev.get(0)
|
||||||
|
return if !element
|
||||||
|
return if $(element).visible(true)
|
||||||
|
element.scrollIntoView()
|
||||||
|
|
||||||
counterUpdate: (count) =>
|
counterUpdate: (count) =>
|
||||||
if !count
|
if !count
|
||||||
@el.find('.js-counter').text('')
|
@el.find('.js-counter').text('')
|
||||||
|
@ -100,9 +143,11 @@ class App.OnlineNotificationWidget extends App.Controller
|
||||||
|
|
||||||
notificationsContainer.on 'click', @stopPropagation
|
notificationsContainer.on 'click', @stopPropagation
|
||||||
$(window).on 'click.notifications', @hidePopover
|
$(window).on 'click.notifications', @hidePopover
|
||||||
|
$(window).on 'keydown.notifications', @listNavigate
|
||||||
|
|
||||||
onHide: ->
|
onHide: ->
|
||||||
$(window).off 'click.notifications'
|
$(window).off 'click.notifications'
|
||||||
|
$(window).off 'keydown.notifications'
|
||||||
|
|
||||||
hidePopover: =>
|
hidePopover: =>
|
||||||
@toggle.popover('hide')
|
@toggle.popover('hide')
|
||||||
|
|
68
app/assets/javascripts/app/lib/base/jquery.visible.js
Normal file
68
app/assets/javascripts/app/lib/base/jquery.visible.js
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
(function($){
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2012, Digital Fusion
|
||||||
|
* Licensed under the MIT license.
|
||||||
|
* http://teamdf.com/jquery-plugins/license/
|
||||||
|
*
|
||||||
|
* @author Sam Sehnert
|
||||||
|
* @desc A small plugin that checks whether elements are within
|
||||||
|
* the user visible viewport of a web browser.
|
||||||
|
* only accounts for vertical position, not horizontal.
|
||||||
|
*/
|
||||||
|
var $w = $(window);
|
||||||
|
$.fn.visible = function(partial,hidden,direction){
|
||||||
|
|
||||||
|
if (this.length < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var $t = this.length > 1 ? this.eq(0) : this,
|
||||||
|
t = $t.get(0),
|
||||||
|
vpWidth = $w.width(),
|
||||||
|
vpHeight = $w.height(),
|
||||||
|
direction = (direction) ? direction : 'both',
|
||||||
|
clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true;
|
||||||
|
|
||||||
|
if (typeof t.getBoundingClientRect === 'function'){
|
||||||
|
|
||||||
|
// Use this native browser method, if available.
|
||||||
|
var rec = t.getBoundingClientRect(),
|
||||||
|
tViz = rec.top >= 0 && rec.top < vpHeight,
|
||||||
|
bViz = rec.bottom > 0 && rec.bottom <= vpHeight,
|
||||||
|
lViz = rec.left >= 0 && rec.left < vpWidth,
|
||||||
|
rViz = rec.right > 0 && rec.right <= vpWidth,
|
||||||
|
vVisible = partial ? tViz || bViz : tViz && bViz,
|
||||||
|
hVisible = partial ? lViz || rViz : lViz && rViz;
|
||||||
|
|
||||||
|
if(direction === 'both')
|
||||||
|
return clientSize && vVisible && hVisible;
|
||||||
|
else if(direction === 'vertical')
|
||||||
|
return clientSize && vVisible;
|
||||||
|
else if(direction === 'horizontal')
|
||||||
|
return clientSize && hVisible;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
var viewTop = $w.scrollTop(),
|
||||||
|
viewBottom = viewTop + vpHeight,
|
||||||
|
viewLeft = $w.scrollLeft(),
|
||||||
|
viewRight = viewLeft + vpWidth,
|
||||||
|
offset = $t.offset(),
|
||||||
|
_top = offset.top,
|
||||||
|
_bottom = _top + $t.height(),
|
||||||
|
_left = offset.left,
|
||||||
|
_right = _left + $t.width(),
|
||||||
|
compareTop = partial === true ? _bottom : _top,
|
||||||
|
compareBottom = partial === true ? _top : _bottom,
|
||||||
|
compareLeft = partial === true ? _right : _left,
|
||||||
|
compareRight = partial === true ? _left : _right;
|
||||||
|
|
||||||
|
if(direction === 'both')
|
||||||
|
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
|
||||||
|
else if(direction === 'vertical')
|
||||||
|
return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop));
|
||||||
|
else if(direction === 'horizontal')
|
||||||
|
return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})(jQuery);
|
|
@ -2904,7 +2904,8 @@ footer {
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-tab.is-active,
|
.nav-tab.is-active,
|
||||||
.nav-tab.nav-tab--search:hover {
|
.nav-tab.nav-tab--search:hover,
|
||||||
|
.nav-tab.nav-tab--search.is-hover {
|
||||||
background: #389ed9;
|
background: #389ed9;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
|
@ -3893,6 +3894,10 @@ footer {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-hover {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
&.activity-entry--removeable {
|
&.activity-entry--removeable {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,6 +154,38 @@ class KeyboardShortcutsTest < TestCase
|
||||||
timeout: 6,
|
timeout: 6,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# open online notification
|
||||||
|
@browser_agent = browser_instance
|
||||||
|
login(
|
||||||
|
browser: @browser_agent,
|
||||||
|
username: 'agent1@example.com',
|
||||||
|
password: 'test',
|
||||||
|
url: browser_url,
|
||||||
|
)
|
||||||
|
ticket2 = ticket_create(
|
||||||
|
browser: @browser_agent,
|
||||||
|
data: {
|
||||||
|
customer: 'nico',
|
||||||
|
group: 'Users',
|
||||||
|
title: 'Test Ticket for Shortcuts II - ABC123',
|
||||||
|
body: 'Test Ticket Body for Shortcuts II - ABC123',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
sleep 5
|
||||||
|
shortcut(key: 'y')
|
||||||
|
watch_for(
|
||||||
|
css: '.js-notificationsContainer',
|
||||||
|
value: 'Test Ticket for Shortcuts II',
|
||||||
|
timeout: 10,
|
||||||
|
)
|
||||||
|
window_keys(value: :arrow_down)
|
||||||
|
window_keys(value: :enter)
|
||||||
|
watch_for(
|
||||||
|
css: '.active.content',
|
||||||
|
value: ticket2[:number],
|
||||||
|
timeout: 2,
|
||||||
|
)
|
||||||
|
|
||||||
shortcut(key: 'e')
|
shortcut(key: 'e')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: 'body',
|
css: 'body',
|
||||||
|
|
|
@ -9,8 +9,8 @@ class PreferencesTest < TestCase
|
||||||
password: 'test',
|
password: 'test',
|
||||||
url: browser_url,
|
url: browser_url,
|
||||||
)
|
)
|
||||||
click( css: 'a[href="#current_user"]' )
|
click(css: 'a[href="#current_user"]')
|
||||||
click( css: 'a[href="#profile"]' )
|
click(css: 'a[href="#profile"]')
|
||||||
match(
|
match(
|
||||||
css: '.content .NavBarProfile',
|
css: '.content .NavBarProfile',
|
||||||
value: 'Password',
|
value: 'Password',
|
||||||
|
@ -36,8 +36,8 @@ class PreferencesTest < TestCase
|
||||||
password: 'test',
|
password: 'test',
|
||||||
url: browser_url,
|
url: browser_url,
|
||||||
)
|
)
|
||||||
click( css: 'a[href="#current_user"]' )
|
click(css: 'a[href="#current_user"]')
|
||||||
click( css: 'a[href="#profile"]' )
|
click(css: 'a[href="#profile"]')
|
||||||
match(
|
match(
|
||||||
css: '.content .NavBarProfile',
|
css: '.content .NavBarProfile',
|
||||||
value: 'Password',
|
value: 'Password',
|
||||||
|
@ -96,14 +96,14 @@ class PreferencesTest < TestCase
|
||||||
value: 'Zammad Foundation',
|
value: 'Zammad Foundation',
|
||||||
)
|
)
|
||||||
|
|
||||||
click( css: 'a[href="#current_user"]' )
|
click(css: 'a[href="#current_user"]')
|
||||||
click( css: 'a[href="#profile"]' )
|
click(css: 'a[href="#profile"]')
|
||||||
click( css: 'a[href="#profile/language"]' )
|
click(css: 'a[href="#profile/language"]')
|
||||||
select(
|
select(
|
||||||
css: '.language_item [name="locale"]',
|
css: '.language_item [name="locale"]',
|
||||||
value: 'Deutsch',
|
value: 'Deutsch',
|
||||||
)
|
)
|
||||||
click( css: '.content button[type="submit"]' )
|
click(css: '.content button[type="submit"]')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: 'body',
|
css: 'body',
|
||||||
value: 'Sprache',
|
value: 'Sprache',
|
||||||
|
@ -116,14 +116,14 @@ class PreferencesTest < TestCase
|
||||||
)
|
)
|
||||||
|
|
||||||
# check language in dashboard
|
# check language in dashboard
|
||||||
click( css: '.js-menu a[href="#dashboard"]' )
|
click(css: '.js-menu a[href="#dashboard"]')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: '.content.active',
|
css: '.content.active',
|
||||||
value: 'Meine Statistik'
|
value: 'Meine Statistik'
|
||||||
)
|
)
|
||||||
|
|
||||||
# check language in overview
|
# check language in overview
|
||||||
click( css: '.js-menu a[href="#ticket/view"]' )
|
click(css: '.js-menu a[href="#ticket/view"]')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: '.content.active',
|
css: '.content.active',
|
||||||
value: 'Meine'
|
value: 'Meine'
|
||||||
|
@ -209,14 +209,14 @@ class PreferencesTest < TestCase
|
||||||
value: 'notiz'
|
value: 'notiz'
|
||||||
)
|
)
|
||||||
|
|
||||||
click( css: 'a[href="#current_user"]' )
|
click(css: 'a[href="#current_user"]')
|
||||||
click( css: 'a[href="#profile"]' )
|
click(css: 'a[href="#profile"]')
|
||||||
click( css: 'a[href="#profile/language"]' )
|
click(css: 'a[href="#profile/language"]')
|
||||||
select(
|
select(
|
||||||
css: '.language_item [name="locale"]',
|
css: '.language_item [name="locale"]',
|
||||||
value: 'English (United States)',
|
value: 'English (United States)',
|
||||||
)
|
)
|
||||||
click( css: '.content button[type="submit"]' )
|
click(css: '.content button[type="submit"]')
|
||||||
sleep 2
|
sleep 2
|
||||||
watch_for(
|
watch_for(
|
||||||
css: 'body',
|
css: 'body',
|
||||||
|
@ -230,14 +230,14 @@ class PreferencesTest < TestCase
|
||||||
)
|
)
|
||||||
|
|
||||||
# check language in dashboard
|
# check language in dashboard
|
||||||
click( css: '.js-menu a[href="#dashboard"]' )
|
click(css: '.js-menu a[href="#dashboard"]')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: '.content.active',
|
css: '.content.active',
|
||||||
value: 'My Stats'
|
value: 'My Stats'
|
||||||
)
|
)
|
||||||
|
|
||||||
# check language in overview
|
# check language in overview
|
||||||
click( css: '.js-menu a[href="#ticket/view"]' )
|
click(css: '.js-menu a[href="#ticket/view"]')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: '.content.active',
|
css: '.content.active',
|
||||||
value: 'My'
|
value: 'My'
|
||||||
|
@ -324,15 +324,15 @@ class PreferencesTest < TestCase
|
||||||
)
|
)
|
||||||
|
|
||||||
# switch to de again
|
# switch to de again
|
||||||
click( css: 'a[href="#current_user"]' )
|
click(css: 'a[href="#current_user"]')
|
||||||
click( css: 'a[href="#profile"]' )
|
click(css: 'a[href="#profile"]')
|
||||||
click( css: 'a[href="#profile/language"]' )
|
click(css: 'a[href="#profile/language"]')
|
||||||
sleep 4
|
sleep 4
|
||||||
select(
|
select(
|
||||||
css: '.language_item [name="locale"]',
|
css: '.language_item [name="locale"]',
|
||||||
value: 'Deutsch',
|
value: 'Deutsch',
|
||||||
)
|
)
|
||||||
click( css: '.content button[type="submit"]' )
|
click(css: '.content button[type="submit"]')
|
||||||
sleep 4
|
sleep 4
|
||||||
watch_for(
|
watch_for(
|
||||||
css: 'body',
|
css: 'body',
|
||||||
|
@ -356,14 +356,14 @@ class PreferencesTest < TestCase
|
||||||
)
|
)
|
||||||
|
|
||||||
# check language in dashboard
|
# check language in dashboard
|
||||||
click( css: '.js-menu a[href="#dashboard"]' )
|
click(css: '.js-menu a[href="#dashboard"]')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: '.content.active',
|
css: '.content.active',
|
||||||
value: 'Meine Statistik'
|
value: 'Meine Statistik'
|
||||||
)
|
)
|
||||||
|
|
||||||
# check language in overview
|
# check language in overview
|
||||||
click( css: '.js-menu a[href="#ticket/view"]' )
|
click(css: '.js-menu a[href="#ticket/view"]')
|
||||||
watch_for(
|
watch_for(
|
||||||
css: '.content.active',
|
css: '.content.active',
|
||||||
value: 'Meine'
|
value: 'Meine'
|
||||||
|
|
Loading…
Reference in a new issue