Browse Source

Fix drag and drop issues when re-enter board

Andrés Manelli 7 years ago
parent
commit
5b0f7f8aef

+ 82 - 21
client/components/boards/boardBody.js

@@ -1,12 +1,8 @@
 const subManager = new SubsManager();
+const { calculateIndex } = Utils;
 
 BlazeComponent.extendComponent({
-  openNewListForm() {
-    this.childComponents('addListForm')[0].open();
-  },
   onCreated() {
-    this.draggingActive = new ReactiveVar(false);
-    this.showOverlay = new ReactiveVar(false);
     this.isBoardReady = new ReactiveVar(false);
 
     // The pattern we use to manually handle data loading is described here:
@@ -24,30 +20,70 @@ BlazeComponent.extendComponent({
         });
       });
     });
+  },
 
-    this._isDragging = false;
-    this._lastDragPositionX = 0;
+  onlyShowCurrentCard() {
+    return Utils.isMiniScreen() && Session.get('currentCard');
+  },
+
+}).register('board');
 
+BlazeComponent.extendComponent({
+  onCreated() {
+    this.showOverlay = new ReactiveVar(false);
+    this.draggingActive = new ReactiveVar(false);
+    this._isDragging = false;
     // Used to set the overlay
     this.mouseHasEnterCardDetails = false;
   },
+  onRendered() {
+    const boardComponent = this;
+    const $swimlanesDom = boardComponent.$('.js-swimlanes');
 
-  // XXX Flow components allow us to avoid creating these two setter methods by
-  // exposing a public API to modify the component state. We need to investigate
-  // best practices here.
-  setIsDragging(bool) {
-    this.draggingActive.set(bool);
-  },
+    $swimlanesDom.sortable({
+      tolerance: 'pointer',
+      appendTo: '.board-canvas',
+      helper: 'clone',
+      handle: '.js-swimlane-header',
+      items: '.js-swimlane:not(.placeholder)',
+      placeholder: 'swimlane placeholder',
+      distance: 7,
+      start(evt, ui) {
+        ui.placeholder.height(ui.helper.height());
+        EscapeActions.executeUpTo('popup-close');
+        boardComponent.setIsDragging(true);
+      },
+      stop(evt, ui) {
+        // To attribute the new index number, we need to get the DOM element
+        // of the previous and the following card -- if any.
+        const prevSwimlaneDom = ui.item.prev('.js-swimlane').get(0);
+        const nextSwimlaneDom = ui.item.next('.js-swimlane').get(0);
+        const sortIndex = calculateIndex(prevSwimlaneDom, nextSwimlaneDom, 1);
 
-  scrollLeft(position = 0) {
-    const lists = this.$('.js-lists');
-    lists && lists.animate({
-      scrollLeft: position,
+        $swimlanesDom.sortable('cancel');
+        const swimlaneDomElement = ui.item.get(0);
+        const swimlane = Blaze.getData(swimlaneDomElement);
+
+        Swimlanes.update(swimlane._id, {
+          $set: {
+            sort: sortIndex.base,
+          },
+        });
+
+        boardComponent.setIsDragging(false);
+      },
     });
-  },
 
-  onlyShowCurrentCard() {
-    return Utils.isMiniScreen() && Session.get('currentCard');
+    function userIsMember() {
+      return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
+    }
+
+    // If there is no data in the board (ie, no lists) we autofocus the list
+    // creation form by clicking on the corresponding element.
+    const currentBoard = Boards.findOne(Session.get('currentBoard'));
+    if (userIsMember() && currentBoard.lists().count() === 0) {
+      boardComponent.openNewListForm();
+    }
   },
 
   isViewSwimlanes() {
@@ -62,6 +98,16 @@ BlazeComponent.extendComponent({
     return (board.view === 'board-view-lists');
   },
 
+  openNewListForm() {
+    if (this.isViewSwimlanes()) {
+      this.childComponents('swimlane')[0]
+        .childComponents('addListAndSwimlaneForm')[0].open();
+    } else if (this.isViewLists()) {
+      this.childComponents('listsGroup')[0]
+        .childComponents('addListForm')[0].open();
+    }
+  },
+
   events() {
     return [{
       // XXX The board-overlay div should probably be moved to the parent
@@ -78,4 +124,19 @@ BlazeComponent.extendComponent({
       },
     }];
   },
-}).register('board');
+
+  // XXX Flow components allow us to avoid creating these two setter methods by
+  // exposing a public API to modify the component state. We need to investigate
+  // best practices here.
+  setIsDragging(bool) {
+    this.draggingActive.set(bool);
+  },
+
+  scrollLeft(position = 0) {
+    const lists = this.$('.js-lists');
+    lists && lists.animate({
+      scrollLeft: position,
+    });
+  },
+
+}).register('boardBody');

+ 0 - 74
client/components/lists/list.js

@@ -19,85 +19,11 @@ BlazeComponent.extendComponent({
   // comment below provides further details.
   onRendered() {
     const boardComponent = this.parentComponent().parentComponent();
-    const $listsDom = boardComponent.$('.js-lists');
-
-    if (!Session.get('currentCard')) {
-      boardComponent.scrollLeft();
-    }
-
-    // We want to animate the card details window closing. We rely on CSS
-    // transition for the actual animation.
-    $listsDom._uihooks = {
-      removeElement(node) {
-        const removeNode = _.once(() => {
-          node.parentNode.removeChild(node);
-        });
-        if ($(node).hasClass('js-card-details')) {
-          $(node).css({
-            flexBasis: 0,
-            padding: 0,
-          });
-          $listsDom.one(CSSEvents.transitionend, removeNode);
-        } else {
-          removeNode();
-        }
-      },
-    };
-
-    $listsDom.sortable({
-      tolerance: 'pointer',
-      helper: 'clone',
-      handle: '.js-list-header',
-      items: '.js-list:not(.js-list-composer)',
-      placeholder: 'list placeholder',
-      distance: 7,
-      start(evt, ui) {
-        ui.placeholder.height(ui.helper.height());
-        EscapeActions.executeUpTo('popup-close');
-        boardComponent.setIsDragging(true);
-      },
-      stop(evt, ui) {
-        // To attribute the new index number, we need to get the DOM element
-        // of the previous and the following card -- if any.
-        const prevListDom = ui.item.prev('.js-list').get(0);
-        const nextListDom = ui.item.next('.js-list').get(0);
-        const sortIndex = calculateIndex(prevListDom, nextListDom, 1);
-
-        $listsDom.sortable('cancel');
-        const listDomElement = ui.item.get(0);
-        const list = Blaze.getData(listDomElement);
-
-        Lists.update(list._id, {
-          $set: {
-            sort: sortIndex.base,
-          },
-        });
-
-        boardComponent.setIsDragging(false);
-      },
-    });
 
     function userIsMember() {
       return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
     }
 
-    // Disable drag-dropping while in multi-selection mode, or if the current user
-    // is not a board member
-    boardComponent.autorun(() => {
-      const $listDom = $listsDom;
-      if ($listDom.data('sortable')) {
-        $listsDom.sortable('option', 'disabled',
-          MultiSelection.isActive() || !userIsMember());
-      }
-    });
-
-    // If there is no data in the board (ie, no lists) we autofocus the list
-    // creation form by clicking on the corresponding element.
-    const currentBoard = Boards.findOne(Session.get('currentBoard'));
-    if (userIsMember() && currentBoard.lists().count() === 0) {
-      boardComponent.openNewListForm();
-    }
-
     const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
     const $cards = this.$('.js-minicards');
     $cards.sortable({

+ 49 - 27
client/components/swimlanes/swimlanes.js

@@ -3,15 +3,37 @@ const { calculateIndex } = Utils;
 BlazeComponent.extendComponent({
   onRendered() {
     const boardComponent = this.parentComponent();
-    const $swimlanesDom = boardComponent.$('.js-swimlanes');
+    const $listsDom = this.$('.js-lists');
+
+    if (!Session.get('currentCard')) {
+      boardComponent.scrollLeft();
+    }
+
+    // We want to animate the card details window closing. We rely on CSS
+    // transition for the actual animation.
+    $listsDom._uihooks = {
+      removeElement(node) {
+        const removeNode = _.once(() => {
+          node.parentNode.removeChild(node);
+        });
+        if ($(node).hasClass('js-card-details')) {
+          $(node).css({
+            flexBasis: 0,
+            padding: 0,
+          });
+          $listsDom.one(CSSEvents.transitionend, removeNode);
+        } else {
+          removeNode();
+        }
+      },
+    };
 
-    $swimlanesDom.sortable({
+    $listsDom.sortable({
       tolerance: 'pointer',
-      appendTo: '.board-canvas',
       helper: 'clone',
-      handle: '.js-swimlane-header',
-      items: '.js-swimlane:not(.placeholder)',
-      placeholder: 'swimlane placeholder',
+      handle: '.js-list-header',
+      items: '.js-list:not(.js-list-composer)',
+      placeholder: 'list placeholder',
       distance: 7,
       start(evt, ui) {
         ui.placeholder.height(ui.helper.height());
@@ -21,15 +43,15 @@ BlazeComponent.extendComponent({
       stop(evt, ui) {
         // To attribute the new index number, we need to get the DOM element
         // of the previous and the following card -- if any.
-        const prevSwimlaneDom = ui.item.prev('.js-swimlane').get(0);
-        const nextSwimlaneDom = ui.item.next('.js-swimlane').get(0);
-        const sortIndex = calculateIndex(prevSwimlaneDom, nextSwimlaneDom, 1);
+        const prevListDom = ui.item.prev('.js-list').get(0);
+        const nextListDom = ui.item.next('.js-list').get(0);
+        const sortIndex = calculateIndex(prevListDom, nextListDom, 1);
 
-        $swimlanesDom.sortable('cancel');
-        const swimlaneDomElement = ui.item.get(0);
-        const swimlane = Blaze.getData(swimlaneDomElement);
+        $listsDom.sortable('cancel');
+        const listDomElement = ui.item.get(0);
+        const list = Blaze.getData(listDomElement);
 
-        Swimlanes.update(swimlane._id, {
+        Lists.update(list._id, {
           $set: {
             sort: sortIndex.base,
           },
@@ -38,6 +60,20 @@ BlazeComponent.extendComponent({
         boardComponent.setIsDragging(false);
       },
     });
+
+    function userIsMember() {
+      return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
+    }
+
+    // Disable drag-dropping while in multi-selection mode, or if the current user
+    // is not a board member
+    boardComponent.autorun(() => {
+      const $listDom = $listsDom;
+      if ($listDom.data('sortable')) {
+        $listsDom.sortable('option', 'disabled',
+          MultiSelection.isActive() || !userIsMember());
+      }
+    });
   },
   onCreated() {
     this.draggingActive = new ReactiveVar(false);
@@ -50,20 +86,6 @@ BlazeComponent.extendComponent({
     return this._id;
   },
 
-  // XXX Flow components allow us to avoid creating these two setter methods by
-  // exposing a public API to modify the component state. We need to investigate
-  // best practices here.
-  setIsDragging(bool) {
-    this.draggingActive.set(bool);
-  },
-
-  scrollLeft(position = 0) {
-    const lists = this.$('.js-lists');
-    lists && lists.animate({
-      scrollLeft: position,
-    });
-  },
-
   currentCardIsInThisList(listId, swimlaneId) {
     const currentCard = Cards.findOne(Session.get('currentCard'));
     const currentBoardId = Session.get('currentBoard');