Show placeholder if no activity stream is shown.
This commit is contained in:
parent
aaf57357cc
commit
d534d43ad0
3 changed files with 327 additions and 0 deletions
|
@ -38,6 +38,10 @@ class App.DashboardActivityStream extends App.Controller
|
|||
@render(items)
|
||||
|
||||
render: (items) ->
|
||||
if _.isEmpty(items)
|
||||
@$('.activity-description').removeClass('hidden')
|
||||
return
|
||||
|
||||
items = @prepareForObjectList(items)
|
||||
|
||||
html = $('<div></div>')
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
class App.FirstStepsClues extends App.Controller
|
||||
clues: [
|
||||
{
|
||||
container: '.search-holder'
|
||||
headline: 'Suche'
|
||||
text: 'Um alles zu finden nutze den <kbd>*</kbd>-Platzhalter'
|
||||
}
|
||||
{
|
||||
container: '.user-menu'
|
||||
headline: 'Erstellen'
|
||||
text: 'Hier kannst du Tickets, Kunden und Organisationen anlegen.'
|
||||
actions: [
|
||||
'click .add .js-action',
|
||||
'hover .add'
|
||||
]
|
||||
}
|
||||
{
|
||||
container: '.user-menu'
|
||||
headline: 'Persönliches Menü'
|
||||
text: 'Hier findest du den Logout, den Weg zu deinen Einstellungen und deinen Verlauf.'
|
||||
actions: [
|
||||
'click .user .js-action',
|
||||
'hover .user'
|
||||
]
|
||||
}
|
||||
{
|
||||
container: '.main-navigation .overviews'
|
||||
headline: 'Übersichten'
|
||||
text: 'Hier findest du eine Liste aller Tickets.'
|
||||
actions: [
|
||||
'hover'
|
||||
]
|
||||
}
|
||||
{
|
||||
container: '.main-navigation .dashboard'
|
||||
headline: 'Dashboard'
|
||||
text: 'Hier siehst du auf einem Blick ob sich alle Agenten an die Spielregeln halten.'
|
||||
actions: [
|
||||
'hover'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
elements:
|
||||
'.js-positionOrigin': 'modalWindow'
|
||||
'.js-backdrop': 'backdrop'
|
||||
|
||||
events:
|
||||
'click': 'stopPropagation'
|
||||
'click .js-next': 'next'
|
||||
'click .js-previous': 'previous'
|
||||
'click .js-close': 'close'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
###
|
||||
|
||||
options
|
||||
clues: list of clues
|
||||
onComplete: a callback for when the user is done
|
||||
|
||||
###
|
||||
@el = $('body')
|
||||
@options.onComplete = -> null
|
||||
@position = 0
|
||||
@render()
|
||||
|
||||
stopPropagation: (event) ->
|
||||
event.stopPropagation()
|
||||
|
||||
next: (event) =>
|
||||
event.stopPropagation()
|
||||
@navigate 1
|
||||
|
||||
previous: (event) =>
|
||||
event.stopPropagation()
|
||||
@navigate -1
|
||||
|
||||
close: =>
|
||||
@cleanUp()
|
||||
@options.onComplete()
|
||||
@remove()
|
||||
|
||||
remove: ->
|
||||
@$('.modal').remove()
|
||||
|
||||
navigate: (direction) ->
|
||||
@cleanUp =>
|
||||
@position += direction
|
||||
|
||||
if @position < @clues.length
|
||||
@showClue()
|
||||
else
|
||||
@options.onComplete()
|
||||
@remove()
|
||||
|
||||
cleanUp: (callback) ->
|
||||
@hideWindow =>
|
||||
clue = @clues[@position]
|
||||
container = $(clue.container)
|
||||
container.removeClass('selected-clue')
|
||||
|
||||
# undo click perform by doing it again
|
||||
if clue.actions
|
||||
@perform clue.actions, container
|
||||
|
||||
callback()
|
||||
|
||||
render: =>
|
||||
html = App.view('layout_ref/clues')
|
||||
console.log('HH', html)
|
||||
@el.append(html)
|
||||
#@modalWindow = $('.js-positionOrigin')
|
||||
#@backdrop = $('.js-backdrop')
|
||||
@backdrop.velocity
|
||||
properties:
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
duration: 300
|
||||
complete: @showClue
|
||||
|
||||
showClue: =>
|
||||
clue = @clues[@position]
|
||||
container = $(clue.container)
|
||||
container.addClass('selected-clue')
|
||||
console.log('showClue', clue, clue.container)
|
||||
if clue.actions
|
||||
@perform clue.actions, container
|
||||
|
||||
# calculate bounding box after actions
|
||||
# to take toggled child nodes into account
|
||||
boundingBox = @getVisibleBoundingBox(container.get(0))
|
||||
|
||||
center =
|
||||
x: boundingBox.left + boundingBox.width/2
|
||||
y: boundingBox.top + boundingBox.height/2
|
||||
|
||||
@modalWindow.html App.view('layout_ref/clue_content')
|
||||
headline: clue.headline
|
||||
text: clue.text
|
||||
position: @position
|
||||
max: @clues.length
|
||||
|
||||
@placeWindow(boundingBox)
|
||||
|
||||
@backdrop.velocity
|
||||
properties:
|
||||
translateX: center.x
|
||||
translateY: center.y
|
||||
translateZ: 0
|
||||
options:
|
||||
duration: 300
|
||||
complete: @showWindow
|
||||
|
||||
showWindow: =>
|
||||
@modalWindow.velocity
|
||||
properties:
|
||||
scale: [1, 0.2]
|
||||
opacity: [1, 0]
|
||||
options:
|
||||
duration: 300
|
||||
easing: [0.34,1.61,0.7,1]
|
||||
|
||||
hideWindow: (callback) =>
|
||||
@modalWindow.velocity
|
||||
properties:
|
||||
scale: [0.2, 1]
|
||||
opacity: 0
|
||||
options:
|
||||
duration: 200
|
||||
complete: callback
|
||||
|
||||
|
||||
placeWindow: (target) ->
|
||||
# reset scale in order to get correct measurements
|
||||
$.Velocity.hook(@modalWindow, 'scale', 1)
|
||||
|
||||
modal = @modalWindow.get(0).getBoundingClientRect()
|
||||
position = ''
|
||||
left = 0
|
||||
top = 0
|
||||
maxWidth = $(window).width()
|
||||
maxHeight = $(window).height()
|
||||
|
||||
# try to place it parallel to the larger side
|
||||
if target.height > target.width
|
||||
# try to place it aside
|
||||
# prefer right
|
||||
if target.right + modal.width <= maxWidth
|
||||
left = target.right
|
||||
position = 'right'
|
||||
else
|
||||
# place left
|
||||
left = target.left - modal.width
|
||||
position = 'left'
|
||||
|
||||
if position
|
||||
top = target.top + target.height/2 - modal.height/2
|
||||
else if target.height <= target.width or !position
|
||||
# try to place it above or below
|
||||
# prefer above
|
||||
if target.top - modal.height >= 0
|
||||
top = target.top - modal.height
|
||||
position = 'above'
|
||||
else
|
||||
top = target.bottom
|
||||
position = 'below'
|
||||
|
||||
if position
|
||||
left = target.left + target.width/2 - modal.width/2
|
||||
|
||||
# keep it inside the window
|
||||
# horizontal
|
||||
if left < 0
|
||||
moveArrow = modal.width/2 + left
|
||||
left = 0
|
||||
else if left + modal.width > maxWidth
|
||||
moveArrow = modal.width/2 + maxWidth - (left + modal.width)
|
||||
left = maxWidth - modal.width
|
||||
|
||||
if top < 0
|
||||
moveArrow = modal.height/2 + height
|
||||
top = 0
|
||||
else if top + modal.height > maxHeight
|
||||
moveArrow = modal.height/2 + maxHeight - (top + modal.height)
|
||||
top = maxHeight - modal.height
|
||||
|
||||
transformOrigin = @getTransformOrigin(modal, position)
|
||||
|
||||
if moveArrow
|
||||
parameter = if position is 'above' or position is 'below' then 'left' else 'top'
|
||||
# move arrow
|
||||
@modalWindow.find('.js-arrow').css(parameter, moveArrow)
|
||||
|
||||
# adjust transform origin
|
||||
if position is 'above' or position is 'below'
|
||||
transformOrigin.x = moveArrow
|
||||
else
|
||||
transformOrigin.y = moveArrow
|
||||
|
||||
# place window
|
||||
@modalWindow
|
||||
.attr 'data-position', position
|
||||
.css
|
||||
left: left
|
||||
top: top
|
||||
transformOrigin: "#{transformOrigin.x}px #{transformOrigin.y}px"
|
||||
|
||||
getTransformOrigin: (modal, position) ->
|
||||
positionDictionary =
|
||||
above:
|
||||
x: modal.width/2
|
||||
y: modal.height
|
||||
below:
|
||||
x: modal.width/2
|
||||
y: 0
|
||||
left:
|
||||
x: modal.width + @transformOriginPadding
|
||||
y: modal.height/2
|
||||
right:
|
||||
x: -@transformOriginPadding
|
||||
y: modal.height/2
|
||||
|
||||
return positionDictionary[position]
|
||||
|
||||
getVisibleBoundingBox: (el) ->
|
||||
###
|
||||
|
||||
getBoundingClientRect doesn't take
|
||||
absolute-positioned child nodes into account
|
||||
|
||||
###
|
||||
children = el.querySelectorAll('*')
|
||||
bb = el.getBoundingClientRect()
|
||||
dimensions =
|
||||
left: bb.left,
|
||||
right: bb.right,
|
||||
top: bb.top,
|
||||
bottom: bb.bottom
|
||||
|
||||
for child in children
|
||||
|
||||
continue if getComputedStyle(child).position is not 'absolute'
|
||||
|
||||
bb = child.getBoundingClientRect()
|
||||
|
||||
continue if bb.width is 0 or bb.height is 0
|
||||
|
||||
if bb.left < dimensions.left
|
||||
dimensions.left = bb.left
|
||||
if bb.top < dimensions.top
|
||||
dimensions.top = bb.top
|
||||
if bb.right > dimensions.right
|
||||
dimensions.right = bb.right
|
||||
if bb.bottom > dimensions.bottom
|
||||
dimensions.bottom = bb.bottom
|
||||
|
||||
dimensions.width = dimensions.right - dimensions.left
|
||||
dimensions.height = dimensions.bottom - dimensions.top
|
||||
|
||||
dimensions
|
||||
|
||||
perform: (actions, container) ->
|
||||
for action in actions
|
||||
if action.indexOf(" ") < 0
|
||||
# 'click'
|
||||
eventName = action
|
||||
target = container
|
||||
else
|
||||
# 'click .target'
|
||||
eventName = action.substr 0, action.indexOf(' ')
|
||||
target = container.find( action.substr action.indexOf(' ') + 1 )
|
||||
|
||||
switch eventName
|
||||
when 'click' then target.trigger('click')
|
||||
when 'hover' then target.toggleClass('is-hovered')
|
|
@ -1,6 +1,7 @@
|
|||
class App.Dashboard extends App.Controller
|
||||
events:
|
||||
'click .tabs .tab': 'toggle'
|
||||
'click .intro': 'clues'
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
@ -29,6 +30,11 @@ class App.Dashboard extends App.Controller
|
|||
|
||||
@renderWidgetClockFace 25
|
||||
|
||||
clues: =>
|
||||
new App.FirstStepsClues(
|
||||
el: @el
|
||||
)
|
||||
|
||||
renderWidgetClockFace: (time) =>
|
||||
canvas = @el.find 'canvas'
|
||||
ctx = canvas.get(0).getContext '2d'
|
||||
|
|
Loading…
Reference in a new issue