Batch action groups
This commit is contained in:
parent
8d8a462057
commit
7ac8042b3f
4 changed files with 155 additions and 37 deletions
|
@ -4,15 +4,20 @@ class App.TicketOverview extends App.Controller
|
||||||
mouse:
|
mouse:
|
||||||
x: null
|
x: null
|
||||||
y: null
|
y: null
|
||||||
|
batchAnimationPaused: false
|
||||||
|
|
||||||
elements:
|
elements:
|
||||||
'.js-batch-overlay': 'batchOverlay'
|
'.js-batch-overlay': 'batchOverlay'
|
||||||
'.js-batch-overlay-backdrop': 'batchOverlayBackdrop'
|
'.js-batch-overlay-backdrop': 'batchOverlayBackdrop'
|
||||||
'.js-batch-cancel': 'batchCancel'
|
'.js-batch-cancel': 'batchCancel'
|
||||||
'.js-batch-macro-circle': 'batchMacroCircle'
|
'.js-batch-macro-circle': 'batchMacroCircle'
|
||||||
'.js-batch-assign-circle': 'batchAssignCircle'
|
'.js-batch-assign-circle': 'batchAssignCircle'
|
||||||
'.js-batch-assign': 'batchAssign'
|
'.js-batch-assign': 'batchAssign'
|
||||||
'.js-batch-macro': 'batchMacro'
|
'.js-batch-assign-inner': 'batchAssignInner'
|
||||||
|
'.js-batch-assign-group': 'batchAssignGroup'
|
||||||
|
'.js-batch-assign-group-name': 'batchAssignGroupName'
|
||||||
|
'.js-batch-assign-group-inner': 'batchAssignGroupInner'
|
||||||
|
'.js-batch-macro': 'batchMacro'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'mousedown .item': 'startDragItem'
|
'mousedown .item': 'startDragItem'
|
||||||
|
@ -85,7 +90,7 @@ class App.TicketOverview extends App.Controller
|
||||||
$.Velocity.hook item, 'translateX', "#{dx}px"
|
$.Velocity.hook item, 'translateX', "#{dx}px"
|
||||||
$.Velocity.hook item, 'translateY', "#{dy}px"
|
$.Velocity.hook item, 'translateY', "#{dy}px"
|
||||||
|
|
||||||
@moveDraggedItems(-dir)
|
@alignDraggedItems(-dir)
|
||||||
|
|
||||||
@mouseY = event.pageY
|
@mouseY = event.pageY
|
||||||
@showBatchOverlay()
|
@showBatchOverlay()
|
||||||
|
@ -151,7 +156,7 @@ class App.TicketOverview extends App.Controller
|
||||||
@el.find('[name="bulk"]:checked').prop('checked', false)
|
@el.find('[name="bulk"]:checked').prop('checked', false)
|
||||||
@el.find('[name="bulk_all"]').prop('checked', false)
|
@el.find('[name="bulk_all"]').prop('checked', false)
|
||||||
|
|
||||||
moveDraggedItems: (dir) ->
|
alignDraggedItems: (dir) ->
|
||||||
@draggedItems.velocity
|
@draggedItems.velocity
|
||||||
properties:
|
properties:
|
||||||
translateX: 0
|
translateX: 0
|
||||||
|
@ -227,7 +232,10 @@ class App.TicketOverview extends App.Controller
|
||||||
|
|
||||||
showBatchOverlay: ->
|
showBatchOverlay: ->
|
||||||
@batchOverlay.show()
|
@batchOverlay.show()
|
||||||
|
$('html').css('overflow', 'hidden')
|
||||||
@batchOverlayBackdrop.velocity { opacity: [1, 0] }, { duration: 500 }
|
@batchOverlayBackdrop.velocity { opacity: [1, 0] }, { duration: 500 }
|
||||||
|
@batchMacroOffset = @batchMacro.offset().top + @batchMacro.outerHeight()
|
||||||
|
@batchAssignOffset = @batchAssign.offset().top
|
||||||
@batchOverlayShown = true
|
@batchOverlayShown = true
|
||||||
$(document).on 'mousemove.batchoverlay', @controlBatchOverlay
|
$(document).on 'mousemove.batchoverlay', @controlBatchOverlay
|
||||||
|
|
||||||
|
@ -238,21 +246,33 @@ class App.TicketOverview extends App.Controller
|
||||||
@hideBatchCircles =>
|
@hideBatchCircles =>
|
||||||
@batchOverlay.hide()
|
@batchOverlay.hide()
|
||||||
|
|
||||||
|
$('html').css('overflow', '')
|
||||||
|
|
||||||
if @batchAssignShown
|
if @batchAssignShown
|
||||||
@hideBatchAssign()
|
@hideBatchAssign()
|
||||||
|
|
||||||
if @batchMacroShown
|
if @batchMacroShown
|
||||||
@hideBatchMacro()
|
@hideBatchMacro()
|
||||||
|
|
||||||
|
if @batchAssignGroupShown
|
||||||
|
@hideBatchAssignGroup()
|
||||||
|
|
||||||
controlBatchOverlay: (event) =>
|
controlBatchOverlay: (event) =>
|
||||||
|
return if @batchAnimationPaused
|
||||||
# store to detect if the mouse is hovering a drag-action entry
|
# store to detect if the mouse is hovering a drag-action entry
|
||||||
# after an animation ended -> @highlightBatchEntryAtMousePosition
|
# after an animation ended -> @highlightBatchEntryAtMousePosition
|
||||||
@mouse.x = event.pageX
|
@mouse.x = event.pageX
|
||||||
@mouse.y = event.pageY
|
@mouse.y = event.pageY
|
||||||
|
|
||||||
if event.pageY <= window.innerHeight/5*2
|
if @batchAssignGroupShown && @batchAssignGroupOffset != undefined
|
||||||
|
if @mouse.y < @batchAssignGroupOffset
|
||||||
|
@hideBatchAssignGroup()
|
||||||
|
@batchAnimationPaused = true
|
||||||
|
return
|
||||||
|
|
||||||
|
if @mouse.y <= @batchMacroOffset
|
||||||
mouseInArea = 'top'
|
mouseInArea = 'top'
|
||||||
else if event.pageY > window.innerHeight/5*2 && event.pageY <= window.innerHeight/5*3
|
else if @mouse.y > @batchMacroOffset && @mouse.y <= @batchAssignOffset
|
||||||
mouseInArea = 'middle'
|
mouseInArea = 'middle'
|
||||||
else
|
else
|
||||||
mouseInArea = 'bottom'
|
mouseInArea = 'bottom'
|
||||||
|
@ -262,7 +282,7 @@ class App.TicketOverview extends App.Controller
|
||||||
if !@batchMacroShown
|
if !@batchMacroShown
|
||||||
@hideBatchCircles()
|
@hideBatchCircles()
|
||||||
@showBatchMacro()
|
@showBatchMacro()
|
||||||
@moveDraggedItems(1)
|
@alignDraggedItems(1)
|
||||||
|
|
||||||
when 'middle'
|
when 'middle'
|
||||||
if @batchAssignShown
|
if @batchAssignShown
|
||||||
|
@ -278,7 +298,7 @@ class App.TicketOverview extends App.Controller
|
||||||
if !@batchAssignShown
|
if !@batchAssignShown
|
||||||
@hideBatchCircles()
|
@hideBatchCircles()
|
||||||
@showBatchAssign()
|
@showBatchAssign()
|
||||||
@moveDraggedItems(-1)
|
@alignDraggedItems(-1)
|
||||||
|
|
||||||
showBatchCircles: ->
|
showBatchCircles: ->
|
||||||
@batchCirclesShown = true
|
@batchCirclesShown = true
|
||||||
|
@ -338,7 +358,6 @@ class App.TicketOverview extends App.Controller
|
||||||
duration: 500
|
duration: 500
|
||||||
visibility: 'visible'
|
visibility: 'visible'
|
||||||
complete: @highlightBatchEntryAtMousePosition
|
complete: @highlightBatchEntryAtMousePosition
|
||||||
delay: if @batchCirclesShown then 0 else 200
|
|
||||||
|
|
||||||
@batchCancel.css
|
@batchCancel.css
|
||||||
top: 0
|
top: 0
|
||||||
|
@ -352,7 +371,6 @@ class App.TicketOverview extends App.Controller
|
||||||
easing: [1,-.55,.2,1.37]
|
easing: [1,-.55,.2,1.37]
|
||||||
duration: 500
|
duration: 500
|
||||||
visibility: 'visible'
|
visibility: 'visible'
|
||||||
delay: if @batchCirclesShown then 0 else 200
|
|
||||||
|
|
||||||
hideBatchAssign: ->
|
hideBatchAssign: ->
|
||||||
@batchAssign.velocity
|
@batchAssign.velocity
|
||||||
|
@ -363,6 +381,8 @@ class App.TicketOverview extends App.Controller
|
||||||
duration: 300
|
duration: 300
|
||||||
visibility: 'hidden'
|
visibility: 'hidden'
|
||||||
queue: false
|
queue: false
|
||||||
|
complete: =>
|
||||||
|
$.Velocity.hook @batchAssign, 'translateY', '0%'
|
||||||
|
|
||||||
@batchCancel.velocity
|
@batchCancel.velocity
|
||||||
properties:
|
properties:
|
||||||
|
@ -375,6 +395,53 @@ class App.TicketOverview extends App.Controller
|
||||||
|
|
||||||
@batchAssignShown = false
|
@batchAssignShown = false
|
||||||
|
|
||||||
|
showBatchAssignGroup: =>
|
||||||
|
return if !@batchOverlayShown # user might have dropped the item already
|
||||||
|
@batchAssignGroupShown = true
|
||||||
|
|
||||||
|
groupId = @hoveredBatchEntry.attr('data-id')
|
||||||
|
group = App.Group.find(groupId)
|
||||||
|
users = []
|
||||||
|
|
||||||
|
users.push App.User.find(i) for i in group.user_ids
|
||||||
|
|
||||||
|
@batchAssignGroupName.text group.displayName()
|
||||||
|
@batchAssignGroupInner.html $(App.view('ticket_overview/batch_overlay_user_group')(
|
||||||
|
users: users
|
||||||
|
groups: []
|
||||||
|
))
|
||||||
|
|
||||||
|
# then adjust the size of the group that it almost overlaps the batch-assign box
|
||||||
|
@batchAssignGroupInner.height(@batchAssignInner.height())
|
||||||
|
|
||||||
|
@batchAssignGroup.velocity
|
||||||
|
properties:
|
||||||
|
translateY: [0, '100%']
|
||||||
|
opacity: [1, 0]
|
||||||
|
options:
|
||||||
|
easing: [1,-.55,.2,1.37]
|
||||||
|
duration: 700
|
||||||
|
visibility: 'visible'
|
||||||
|
complete: =>
|
||||||
|
@highlightBatchEntryAtMousePosition()
|
||||||
|
@batchAssignGroupOffset = @batchAssignGroup.offset().top
|
||||||
|
|
||||||
|
hideBatchAssignGroup: ->
|
||||||
|
@batchAssignGroup.velocity
|
||||||
|
properties:
|
||||||
|
translateY: ['100%', 0]
|
||||||
|
opacity: [0, 1]
|
||||||
|
options:
|
||||||
|
duration: 300
|
||||||
|
visibility: 'hidden'
|
||||||
|
queue: false
|
||||||
|
complete: =>
|
||||||
|
@batchAssignGroupShown = false
|
||||||
|
@batchAssignGroupHovered = false
|
||||||
|
setTimeout (=> @batchAnimationPaused = false), 1000
|
||||||
|
|
||||||
|
@batchAssignGroupOffset = undefined
|
||||||
|
|
||||||
showBatchMacro: ->
|
showBatchMacro: ->
|
||||||
return if !@batchOverlayShown # user might have dropped the item already
|
return if !@batchOverlayShown # user might have dropped the item already
|
||||||
@batchMacroShown = true
|
@batchMacroShown = true
|
||||||
|
@ -388,7 +455,6 @@ class App.TicketOverview extends App.Controller
|
||||||
duration: 500
|
duration: 500
|
||||||
visibility: 'visible'
|
visibility: 'visible'
|
||||||
complete: @highlightBatchEntryAtMousePosition
|
complete: @highlightBatchEntryAtMousePosition
|
||||||
delay: if @batchCirclesShown then 0 else 200
|
|
||||||
|
|
||||||
@batchCancel.css
|
@batchCancel.css
|
||||||
top: 'auto'
|
top: 'auto'
|
||||||
|
@ -401,7 +467,6 @@ class App.TicketOverview extends App.Controller
|
||||||
easing: [1,-.55,.2,1.37]
|
easing: [1,-.55,.2,1.37]
|
||||||
duration: 500
|
duration: 500
|
||||||
visibility: 'visible'
|
visibility: 'visible'
|
||||||
delay: if @batchCirclesShown then 0 else 200
|
|
||||||
|
|
||||||
hideBatchMacro: ->
|
hideBatchMacro: ->
|
||||||
@batchMacro.velocity
|
@batchMacro.velocity
|
||||||
|
@ -412,6 +477,8 @@ class App.TicketOverview extends App.Controller
|
||||||
duration: 300
|
duration: 300
|
||||||
visibility: 'hidden'
|
visibility: 'hidden'
|
||||||
queue: false
|
queue: false
|
||||||
|
complete: =>
|
||||||
|
$.Velocity.hook @batchMacro, 'translateY', '0%'
|
||||||
|
|
||||||
@batchCancel.velocity
|
@batchCancel.velocity
|
||||||
properties:
|
properties:
|
||||||
|
@ -432,10 +499,27 @@ class App.TicketOverview extends App.Controller
|
||||||
highlightBatchEntry: (event) ->
|
highlightBatchEntry: (event) ->
|
||||||
@hoveredBatchEntry = $(event.currentTarget).addClass('is-hovered')
|
@hoveredBatchEntry = $(event.currentTarget).addClass('is-hovered')
|
||||||
|
|
||||||
|
if @hoveredBatchEntry.attr('data-action') is 'group_assign'
|
||||||
|
@batchAssignGroupHintTimeout = setTimeout @blinkBatchEntry, 800
|
||||||
|
@batchAssignGroupTimeout = setTimeout @showBatchAssignGroup, 900
|
||||||
|
|
||||||
unhighlightBatchEntry: (event) ->
|
unhighlightBatchEntry: (event) ->
|
||||||
|
if @hoveredBatchEntry.attr('data-action') is 'group_assign'
|
||||||
|
if @batchAssignGroupTimeout
|
||||||
|
clearTimeout @batchAssignGroupTimeout
|
||||||
|
if @batchAssignGroupHintTimeout
|
||||||
|
clearTimeout @batchAssignGroupHintTimeout
|
||||||
|
|
||||||
@hoveredBatchEntry = null
|
@hoveredBatchEntry = null
|
||||||
$(event.currentTarget).removeClass('is-hovered')
|
$(event.currentTarget).removeClass('is-hovered')
|
||||||
|
|
||||||
|
blinkBatchEntry: =>
|
||||||
|
@hoveredBatchEntry
|
||||||
|
.velocity({ opacity: [0.5, 1] }, { duration: 120 })
|
||||||
|
.velocity({ opacity: [1, 0.5] }, { duration: 60, delay: 40 })
|
||||||
|
.velocity({ opacity: [0.5, 1] }, { duration: 120 })
|
||||||
|
.velocity({ opacity: [1, 0.5] }, { duration: 60, delay: 40 })
|
||||||
|
|
||||||
render: ->
|
render: ->
|
||||||
elLocal = $(App.view('ticket_overview/index')())
|
elLocal = $(App.view('ticket_overview/index')())
|
||||||
|
|
||||||
|
@ -541,7 +625,7 @@ class App.TicketOverview extends App.Controller
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
###
|
###
|
||||||
@batchAssign.html $(App.view('ticket_overview/batch_overlay_user_group')(
|
@batchAssignInner.html $(App.view('ticket_overview/batch_overlay_user_group')(
|
||||||
users: users
|
users: users
|
||||||
groups: groups
|
groups: groups
|
||||||
))
|
))
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
<div class="batch-overlay-box-inner">
|
|
||||||
<% for user in @users: %>
|
<% for user in @users: %>
|
||||||
<div class="batch-overlay-assign-entry js-batch-overlay-entry" data-action="user_assign" data-id="<%= user.id %>">
|
<div class="batch-overlay-assign-entry js-batch-overlay-entry" data-action="user_assign" data-id="<%= user.id %>">
|
||||||
<%- user.avatar(80) %>
|
<%- user.avatar(80) %>
|
||||||
<div class="batch-overlay-assign-entry-name"><%- user.displayName() %></div>
|
<div class="batch-overlay-assign-entry-name"><%- user.displayName() %></div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% for group in @groups: %>
|
<% for group in @groups: %>
|
||||||
<div class="batch-overlay-assign-entry js-batch-overlay-entry" data-action="group_assign" data-id="<%= group.id %>">
|
<div class="batch-overlay-assign-entry js-batch-overlay-entry" data-action="group_assign" data-id="<%= group.id %>">
|
||||||
<span class="avatar avatar--organization size-80 avatar--unique" style="background-position: -200px -60px;">
|
<span class="avatar avatar--organization size-80">
|
||||||
<%- @Icon('organization') %>
|
<%- @Icon('organization') %>
|
||||||
</span>
|
</span>
|
||||||
<div class="batch-overlay-assign-entry-name"><%- group.displayName() %></div>
|
<div class="batch-overlay-assign-entry-name"><%- group.displayName() %></div>
|
||||||
<div class="batch-overlay-assign-entry-detail"><%- @T('%s people', group.user_ids.length) %></div>
|
<div class="batch-overlay-assign-entry-detail"><%- @T('%s people', group.user_ids.length) %></div>
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
</div>
|
||||||
|
<% end %>
|
|
@ -16,6 +16,12 @@
|
||||||
<%- @Icon('arrow-down') %>
|
<%- @Icon('arrow-down') %>
|
||||||
<div class="batch-overlay-circle-label"><%- @T('assign tickets') %></div>
|
<div class="batch-overlay-circle-label"><%- @T('assign tickets') %></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="batch-overlay-assign batch-overlay-box js-batch-assign"></div>
|
<div class="batch-overlay-assign batch-overlay-box js-batch-assign">
|
||||||
|
<div class="batch-overlay-box-inner js-batch-assign-inner"></div>
|
||||||
|
</div>
|
||||||
<div class="batch-overlay-macro batch-overlay-box js-batch-macro"></div>
|
<div class="batch-overlay-macro batch-overlay-box js-batch-macro"></div>
|
||||||
|
<div class="batch-overlay-assign batch-overlay-assign-group batch-overlay-box js-batch-assign-group">
|
||||||
|
<div class="batch-overlay-assign-group-name js-batch-assign-group-name"></div>
|
||||||
|
<div class="batch-overlay-box-inner js-batch-assign-group-inner"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -8478,7 +8478,7 @@ output {
|
||||||
margin: 37px 25px;
|
margin: 37px 25px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8488,17 +8488,37 @@ output {
|
||||||
bottom: -50px; // extra space for bounce animation
|
bottom: -50px; // extra space for bounce animation
|
||||||
|
|
||||||
.batch-overlay-box-inner {
|
.batch-overlay-box-inner {
|
||||||
max-height: 318px;
|
max-height: 310px;
|
||||||
|
|
||||||
@media screen and (min-height: 800px) {
|
@media screen and (min-height: 1000px) {
|
||||||
|
max-height: 465px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-group {
|
||||||
|
box-shadow: 0 0 35px hsla(0,0%,0%,.5);
|
||||||
|
|
||||||
|
.batch-overlay-box-inner {
|
||||||
|
margin-top: 42px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-name {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
padding: 11px 13px 8px;
|
||||||
|
line-height: 1;
|
||||||
|
position: absolute;
|
||||||
|
background: hsl(233,10%,15%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-entry {
|
&-entry {
|
||||||
padding: 13px;
|
padding: 13px;
|
||||||
width: 116px;
|
width: 116px;
|
||||||
height: 159px;
|
height: 155px;
|
||||||
|
|
||||||
&.is-hovered {
|
&.is-hovered {
|
||||||
.avatar {
|
.avatar {
|
||||||
|
@ -8512,6 +8532,11 @@ output {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
transition: transform 120ms;
|
transition: transform 120ms;
|
||||||
|
cursor: inherit;
|
||||||
|
|
||||||
|
&--organization {
|
||||||
|
background: hsl(191,68%,47%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-name {
|
&-name {
|
||||||
|
@ -8536,6 +8561,11 @@ output {
|
||||||
|
|
||||||
.batch-overlay-box-inner {
|
.batch-overlay-box-inner {
|
||||||
max-height: 146px;
|
max-height: 146px;
|
||||||
|
margin: 24px 12px;
|
||||||
|
|
||||||
|
@media screen and (min-height: 800px) {
|
||||||
|
max-height: 292px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-entry {
|
&-entry {
|
||||||
|
|
Loading…
Reference in a new issue