From 7ac8042b3fe06cf898a3ec51b37f09933cf30b01 Mon Sep 17 00:00:00 2001 From: Felix Niklas Date: Fri, 10 Feb 2017 00:26:54 +0100 Subject: [PATCH] Batch action groups --- .../app/controllers/ticket_overview.coffee | 120 +++++++++++++++--- .../batch_overlay_user_group.jst.eco | 26 ++-- .../app/views/ticket_overview/index.jst.eco | 8 +- app/assets/stylesheets/zammad.scss | 38 +++++- 4 files changed, 155 insertions(+), 37 deletions(-) diff --git a/app/assets/javascripts/app/controllers/ticket_overview.coffee b/app/assets/javascripts/app/controllers/ticket_overview.coffee index 6f2ea235b..3ab920d7c 100644 --- a/app/assets/javascripts/app/controllers/ticket_overview.coffee +++ b/app/assets/javascripts/app/controllers/ticket_overview.coffee @@ -4,15 +4,20 @@ class App.TicketOverview extends App.Controller mouse: x: null y: null + batchAnimationPaused: false elements: - '.js-batch-overlay': 'batchOverlay' - '.js-batch-overlay-backdrop': 'batchOverlayBackdrop' - '.js-batch-cancel': 'batchCancel' - '.js-batch-macro-circle': 'batchMacroCircle' - '.js-batch-assign-circle': 'batchAssignCircle' - '.js-batch-assign': 'batchAssign' - '.js-batch-macro': 'batchMacro' + '.js-batch-overlay': 'batchOverlay' + '.js-batch-overlay-backdrop': 'batchOverlayBackdrop' + '.js-batch-cancel': 'batchCancel' + '.js-batch-macro-circle': 'batchMacroCircle' + '.js-batch-assign-circle': 'batchAssignCircle' + '.js-batch-assign': 'batchAssign' + '.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: 'mousedown .item': 'startDragItem' @@ -85,7 +90,7 @@ class App.TicketOverview extends App.Controller $.Velocity.hook item, 'translateX', "#{dx}px" $.Velocity.hook item, 'translateY', "#{dy}px" - @moveDraggedItems(-dir) + @alignDraggedItems(-dir) @mouseY = event.pageY @showBatchOverlay() @@ -151,7 +156,7 @@ class App.TicketOverview extends App.Controller @el.find('[name="bulk"]:checked').prop('checked', false) @el.find('[name="bulk_all"]').prop('checked', false) - moveDraggedItems: (dir) -> + alignDraggedItems: (dir) -> @draggedItems.velocity properties: translateX: 0 @@ -227,7 +232,10 @@ class App.TicketOverview extends App.Controller showBatchOverlay: -> @batchOverlay.show() + $('html').css('overflow', 'hidden') @batchOverlayBackdrop.velocity { opacity: [1, 0] }, { duration: 500 } + @batchMacroOffset = @batchMacro.offset().top + @batchMacro.outerHeight() + @batchAssignOffset = @batchAssign.offset().top @batchOverlayShown = true $(document).on 'mousemove.batchoverlay', @controlBatchOverlay @@ -238,21 +246,33 @@ class App.TicketOverview extends App.Controller @hideBatchCircles => @batchOverlay.hide() + $('html').css('overflow', '') + if @batchAssignShown @hideBatchAssign() if @batchMacroShown @hideBatchMacro() + if @batchAssignGroupShown + @hideBatchAssignGroup() + controlBatchOverlay: (event) => + return if @batchAnimationPaused # store to detect if the mouse is hovering a drag-action entry # after an animation ended -> @highlightBatchEntryAtMousePosition @mouse.x = event.pageX @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' - else if event.pageY > window.innerHeight/5*2 && event.pageY <= window.innerHeight/5*3 + else if @mouse.y > @batchMacroOffset && @mouse.y <= @batchAssignOffset mouseInArea = 'middle' else mouseInArea = 'bottom' @@ -262,7 +282,7 @@ class App.TicketOverview extends App.Controller if !@batchMacroShown @hideBatchCircles() @showBatchMacro() - @moveDraggedItems(1) + @alignDraggedItems(1) when 'middle' if @batchAssignShown @@ -278,7 +298,7 @@ class App.TicketOverview extends App.Controller if !@batchAssignShown @hideBatchCircles() @showBatchAssign() - @moveDraggedItems(-1) + @alignDraggedItems(-1) showBatchCircles: -> @batchCirclesShown = true @@ -338,7 +358,6 @@ class App.TicketOverview extends App.Controller duration: 500 visibility: 'visible' complete: @highlightBatchEntryAtMousePosition - delay: if @batchCirclesShown then 0 else 200 @batchCancel.css top: 0 @@ -352,7 +371,6 @@ class App.TicketOverview extends App.Controller easing: [1,-.55,.2,1.37] duration: 500 visibility: 'visible' - delay: if @batchCirclesShown then 0 else 200 hideBatchAssign: -> @batchAssign.velocity @@ -363,6 +381,8 @@ class App.TicketOverview extends App.Controller duration: 300 visibility: 'hidden' queue: false + complete: => + $.Velocity.hook @batchAssign, 'translateY', '0%' @batchCancel.velocity properties: @@ -375,6 +395,53 @@ class App.TicketOverview extends App.Controller @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: -> return if !@batchOverlayShown # user might have dropped the item already @batchMacroShown = true @@ -388,7 +455,6 @@ class App.TicketOverview extends App.Controller duration: 500 visibility: 'visible' complete: @highlightBatchEntryAtMousePosition - delay: if @batchCirclesShown then 0 else 200 @batchCancel.css top: 'auto' @@ -401,7 +467,6 @@ class App.TicketOverview extends App.Controller easing: [1,-.55,.2,1.37] duration: 500 visibility: 'visible' - delay: if @batchCirclesShown then 0 else 200 hideBatchMacro: -> @batchMacro.velocity @@ -412,6 +477,8 @@ class App.TicketOverview extends App.Controller duration: 300 visibility: 'hidden' queue: false + complete: => + $.Velocity.hook @batchMacro, 'translateY', '0%' @batchCancel.velocity properties: @@ -432,10 +499,27 @@ class App.TicketOverview extends App.Controller highlightBatchEntry: (event) -> @hoveredBatchEntry = $(event.currentTarget).addClass('is-hovered') + if @hoveredBatchEntry.attr('data-action') is 'group_assign' + @batchAssignGroupHintTimeout = setTimeout @blinkBatchEntry, 800 + @batchAssignGroupTimeout = setTimeout @showBatchAssignGroup, 900 + unhighlightBatchEntry: (event) -> + if @hoveredBatchEntry.attr('data-action') is 'group_assign' + if @batchAssignGroupTimeout + clearTimeout @batchAssignGroupTimeout + if @batchAssignGroupHintTimeout + clearTimeout @batchAssignGroupHintTimeout + @hoveredBatchEntry = null $(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: -> 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 groups: groups )) diff --git a/app/assets/javascripts/app/views/ticket_overview/batch_overlay_user_group.jst.eco b/app/assets/javascripts/app/views/ticket_overview/batch_overlay_user_group.jst.eco index 602addf12..956b89425 100644 --- a/app/assets/javascripts/app/views/ticket_overview/batch_overlay_user_group.jst.eco +++ b/app/assets/javascripts/app/views/ticket_overview/batch_overlay_user_group.jst.eco @@ -1,17 +1,15 @@ -
<% for user in @users: %> -
- <%- user.avatar(80) %> -
<%- user.displayName() %>
-
+
+ <%- user.avatar(80) %> +
<%- user.displayName() %>
+
<% end %> <% for group in @groups: %> -
- - <%- @Icon('organization') %> - -
<%- group.displayName() %>
-
<%- @T('%s people', group.user_ids.length) %>
-
-<% end %> -
\ No newline at end of file +
+ + <%- @Icon('organization') %> + +
<%- group.displayName() %>
+
<%- @T('%s people', group.user_ids.length) %>
+
+<% end %> \ No newline at end of file diff --git a/app/assets/javascripts/app/views/ticket_overview/index.jst.eco b/app/assets/javascripts/app/views/ticket_overview/index.jst.eco index f7151e764..6ab46f034 100644 --- a/app/assets/javascripts/app/views/ticket_overview/index.jst.eco +++ b/app/assets/javascripts/app/views/ticket_overview/index.jst.eco @@ -16,6 +16,12 @@ <%- @Icon('arrow-down') %>
<%- @T('assign tickets') %>
-
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/app/assets/stylesheets/zammad.scss b/app/assets/stylesheets/zammad.scss index 0594f3d1f..0f468ba6e 100644 --- a/app/assets/stylesheets/zammad.scss +++ b/app/assets/stylesheets/zammad.scss @@ -8478,7 +8478,7 @@ output { margin: 37px 25px; display: flex; flex-wrap: wrap; - justify-content: space-between; + justify-content: center; overflow: hidden; } } @@ -8488,17 +8488,37 @@ output { bottom: -50px; // extra space for bounce animation .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 { padding: 13px; width: 116px; - height: 159px; + height: 155px; &.is-hovered { .avatar { @@ -8512,6 +8532,11 @@ output { margin-bottom: 10px; box-sizing: content-box; transition: transform 120ms; + cursor: inherit; + + &--organization { + background: hsl(191,68%,47%); + } } &-name { @@ -8536,6 +8561,11 @@ output { .batch-overlay-box-inner { max-height: 146px; + margin: 24px 12px; + + @media screen and (min-height: 800px) { + max-height: 292px; + } } &-entry {