[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/webroot/rsrc/js/application/projects/ -> behavior-project-boards.js (source)

   1  /**
   2   * @provides javelin-behavior-project-boards
   3   * @requires javelin-behavior
   4   *           javelin-dom
   5   *           javelin-util
   6   *           javelin-vector
   7   *           javelin-stratcom
   8   *           javelin-workflow
   9   *           phabricator-draggable-list
  10   */
  11  
  12  JX.behavior('project-boards', function(config) {
  13  
  14    function finditems(col) {
  15      return JX.DOM.scry(col, 'li', 'project-card');
  16    }
  17  
  18    function onupdate(col) {
  19      var data = JX.Stratcom.getData(col);
  20      var cards = finditems(col);
  21  
  22      // Update the count of tasks in the column header.
  23      if (!data.countTagNode) {
  24        data.countTagNode = JX.$(data.countTagID);
  25        JX.DOM.show(data.countTagNode);
  26      }
  27  
  28      var sum = 0;
  29      for (var ii = 0; ii < cards.length; ii++) {
  30        // TODO: Allow this to be computed in some more clever way.
  31        sum += 1;
  32      }
  33  
  34      // TODO: This is a little bit hacky, but we don't have a PHUIX version of
  35      // this element yet.
  36  
  37      var over_limit = (data.pointLimit && (sum > data.pointLimit));
  38  
  39      var display_value = sum;
  40      if (data.pointLimit) {
  41        display_value = sum + ' / ' + data.pointLimit;
  42      }
  43      JX.DOM.setContent(JX.$(data.countTagContentID), display_value);
  44  
  45  
  46      var panel_map = {
  47        'project-panel-empty': !cards.length,
  48        'project-panel-over-limit': over_limit
  49      };
  50      var panel = JX.DOM.findAbove(col, 'div', 'workpanel');
  51      for (var k in panel_map) {
  52        JX.DOM.alterClass(panel, k, !!panel_map[k]);
  53      }
  54  
  55      var color_map = {
  56        'phui-tag-shade-disabled': (sum === 0),
  57        'phui-tag-shade-blue': (sum > 0 && !over_limit),
  58        'phui-tag-shade-red': (over_limit)
  59      };
  60      for (var k in color_map) {
  61        JX.DOM.alterClass(data.countTagNode, k, !!color_map[k]);
  62      }
  63    }
  64  
  65    function onresponse(response, item, list) {
  66      list.unlock();
  67      JX.DOM.alterClass(item, 'drag-sending', false);
  68      JX.DOM.replace(item, JX.$H(response.task));
  69    }
  70  
  71    function getcolumns() {
  72      return JX.DOM.scry(JX.$(config.boardID), 'ul', 'project-column');
  73    }
  74  
  75    function colsort(u, v) {
  76      var ud = JX.Stratcom.getData(u).sort || [];
  77      var vd = JX.Stratcom.getData(v).sort || [];
  78  
  79      for (var ii = 0; ii < ud.length; ii++) {
  80  
  81        if (parseInt(ud[ii]) < parseInt(vd[ii])) {
  82          return 1;
  83        }
  84        if (parseInt(ud[ii]) > parseInt(vd[ii])) {
  85          return -1;
  86        }
  87      }
  88  
  89      return 0;
  90    }
  91  
  92    function getcontainer() {
  93      return JX.DOM.find(
  94        JX.$(config.boardID),
  95        'div',
  96        'aphront-multi-column-view');
  97    }
  98  
  99    function onbegindrag(item) {
 100      // If the longest column on the board is taller than the window, the board
 101      // will scroll vertically. Dragging an item to the longest column may
 102      // make it longer, by the total height of the board, plus the height of
 103      // the drop target.
 104  
 105      // If this happens, the scrollbar will jump around and the scroll position
 106      // can be adjusted in a disorienting way. To reproduce this, drag a task
 107      // to the bottom of the longest column on a scrolling board and wave the
 108      // task in and out of the column. The scroll bar will jump around and
 109      // it will be hard to lock onto a target.
 110  
 111      // To fix this, set the minimum board height to the current board height
 112      // plus the size of the drop target (which is the size of the item plus
 113      // a bit of margin). This makes sure the scroll bar never needs to
 114      // recalculate.
 115  
 116      var item_size = JX.Vector.getDim(item);
 117      var container = getcontainer();
 118      var container_size = JX.Vector.getDim(container);
 119  
 120      container.style.minHeight = (item_size.y + container_size.y + 12) + 'px';
 121    }
 122  
 123    function onenddrag() {
 124      getcontainer().style.minHeight = '';
 125    }
 126  
 127    function ondrop(list, item, after) {
 128      list.lock();
 129      JX.DOM.alterClass(item, 'drag-sending', true);
 130  
 131      var item_phid = JX.Stratcom.getData(item).objectPHID;
 132      var data = {
 133        objectPHID: item_phid,
 134        columnPHID: JX.Stratcom.getData(list.getRootNode()).columnPHID
 135      };
 136  
 137      var after_phid = null;
 138      var items = finditems(list.getRootNode());
 139      if (after) {
 140        after_phid = JX.Stratcom.getData(after).objectPHID;
 141        data.afterPHID = after_phid;
 142      }
 143      var ii;
 144      var ii_item;
 145      var ii_item_phid;
 146      var ii_prev_item_phid = null;
 147      var before_phid = null;
 148      for (ii = 0; ii < items.length; ii++) {
 149        ii_item = items[ii];
 150        ii_item_phid = JX.Stratcom.getData(ii_item).objectPHID;
 151        if (ii_item_phid == item_phid) {
 152          // skip the item we just dropped
 153          continue;
 154        }
 155        // note this handles when there is no after phid - we are at the top of
 156        // the list - quite nicely
 157        if (ii_prev_item_phid == after_phid) {
 158          before_phid = ii_item_phid;
 159          break;
 160        }
 161        ii_prev_item_phid = ii_item_phid;
 162      }
 163      if (before_phid) {
 164        data.beforePHID = before_phid;
 165      }
 166  
 167      data.order = config.order;
 168  
 169      var workflow = new JX.Workflow(config.moveURI, data)
 170        .setHandler(function(response) {
 171          onresponse(response, item, list);
 172        });
 173  
 174      workflow.start();
 175    }
 176  
 177    var lists = [];
 178    var ii;
 179    var cols = getcolumns();
 180  
 181    for (ii = 0; ii < cols.length; ii++) {
 182      var list = new JX.DraggableList('project-card', cols[ii])
 183        .setFindItemsHandler(JX.bind(null, finditems, cols[ii]));
 184  
 185      list.listen('didSend', JX.bind(list, onupdate, cols[ii]));
 186      list.listen('didReceive', JX.bind(list, onupdate, cols[ii]));
 187  
 188      list.listen('didDrop', JX.bind(null, ondrop, list));
 189  
 190      list.listen('didBeginDrag', JX.bind(null, onbegindrag));
 191      list.listen('didEndDrag', JX.bind(null, onenddrag));
 192  
 193      lists.push(list);
 194  
 195      onupdate(cols[ii]);
 196    }
 197  
 198    for (ii = 0; ii < lists.length; ii++) {
 199      lists[ii].setGroup(lists);
 200    }
 201  
 202    var onedit = function(column, r) {
 203      var new_card = JX.$H(r.tasks).getNode();
 204      var new_data = JX.Stratcom.getData(new_card);
 205      var items = finditems(column);
 206      var edited = false;
 207  
 208      for (var ii = 0; ii < items.length; ii++) {
 209        var item = items[ii];
 210  
 211        var data = JX.Stratcom.getData(item);
 212        var phid = data.objectPHID;
 213  
 214        if (phid == new_data.objectPHID) {
 215          items[ii] = new_card;
 216          data = new_data;
 217          edited = true;
 218        }
 219  
 220        data.sort = r.data.sortMap[data.objectPHID] || data.sort;
 221      }
 222  
 223      // this is an add then...!
 224      if (!edited) {
 225        items[items.length + 1] = new_card;
 226        new_data.sort = r.data.sortMap[new_data.objectPHID] || new_data.sort;
 227      }
 228  
 229      items.sort(colsort);
 230  
 231      JX.DOM.setContent(column, items);
 232  
 233      onupdate(column);
 234    };
 235  
 236    JX.Stratcom.listen(
 237      'click',
 238      ['edit-project-card'],
 239      function(e) {
 240        e.kill();
 241        var column = e.getNode('project-column');
 242        var request_data = {
 243          responseType: 'card',
 244          columnPHID: JX.Stratcom.getData(column).columnPHID,
 245          order: config.order
 246        };
 247        new JX.Workflow(e.getNode('tag:a').href, request_data)
 248          .setHandler(JX.bind(null, onedit, column))
 249          .start();
 250      });
 251  
 252    JX.Stratcom.listen(
 253      'click',
 254      ['column-add-task'],
 255      function (e) {
 256  
 257        // We want the 'boards-dropdown-menu' behavior to see this event and
 258        // close the dropdown, but don't want to follow the link.
 259        e.prevent();
 260  
 261        var column_phid = e.getNodeData('column-add-task').columnPHID;
 262        var request_data = {
 263          responseType: 'card',
 264          columnPHID: column_phid,
 265          projects: config.projectPHID,
 266          order: config.order
 267        };
 268        var cols = getcolumns();
 269        var ii;
 270        var column;
 271        for (ii = 0; ii < cols.length; ii++) {
 272          if (JX.Stratcom.getData(cols[ii]).columnPHID == column_phid) {
 273            column = cols[ii];
 274            break;
 275          }
 276        }
 277        new JX.Workflow(config.createURI, request_data)
 278          .setHandler(JX.bind(null, onedit, column))
 279          .start();
 280      });
 281  
 282  });


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1