From 00f864b359305c54ddebd3f722232335f1a9ddbe Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Tue, 28 Apr 2015 14:51:49 -0700 Subject: [PATCH] Quicksand - fix project board page and quicksand Summary: Fixes T7913. Collapse the separate board dropdown into the board projects behavior; we always need that anyway and now we can install the listener more granularly. Test Plan: - visted project board - invoked create task, cancelled dialog - visited project feed - visited project board - invoked create task, cancelled dialog (FAILED pre patch...!) Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T7913 Differential Revision: https://secure.phabricator.com/D12599 --- resources/celerity/map.php | 62 +++--- .../base/controller/PhabricatorController.php | 13 +- .../PhabricatorProjectBoardViewController.php | 20 +- src/view/page/PhabricatorStandardPageView.php | 5 +- .../rsrc/externals/javelin/lib/Quicksand.js | 6 + .../projects/behavior-boards-dropdown.js | 35 --- .../projects/behavior-project-boards.js | 201 ++++++++++++------ webroot/rsrc/js/core/behavior-dark-console.js | 1 - 8 files changed, 188 insertions(+), 155 deletions(-) delete mode 100644 webroot/rsrc/js/application/projects/behavior-boards-dropdown.js diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 878bce2556..d4c3c4980c 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'core.pkg.css' => '5e324506', 'core.pkg.js' => '59d01bb7', - 'darkconsole.pkg.js' => '6d16ff19', + 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '3500921f', 'differential.pkg.js' => '890046d3', 'diffusion.pkg.css' => '591664fa', @@ -205,7 +205,7 @@ return array( 'rsrc/externals/javelin/lib/JSON.js' => '69adf288', 'rsrc/externals/javelin/lib/Leader.js' => '331b1611', 'rsrc/externals/javelin/lib/Mask.js' => '8a41885b', - 'rsrc/externals/javelin/lib/Quicksand.js' => '517545ab', + 'rsrc/externals/javelin/lib/Quicksand.js' => '51aeb01d', 'rsrc/externals/javelin/lib/Request.js' => '94b750d2', 'rsrc/externals/javelin/lib/Resource.js' => '44959b73', 'rsrc/externals/javelin/lib/Routable.js' => 'b3e7d692', @@ -413,8 +413,7 @@ return array( 'rsrc/js/application/policy/behavior-policy-control.js' => '1ed33505', 'rsrc/js/application/policy/behavior-policy-rule-editor.js' => '5e9f347c', 'rsrc/js/application/ponder/behavior-votebox.js' => '4e9b766b', - 'rsrc/js/application/projects/behavior-boards-dropdown.js' => '0ec56e1d', - 'rsrc/js/application/projects/behavior-project-boards.js' => '87cb6b51', + 'rsrc/js/application/projects/behavior-project-boards.js' => '60292820', 'rsrc/js/application/projects/behavior-project-create.js' => '065227cc', 'rsrc/js/application/projects/behavior-reorder-columns.js' => 'e1d25dfb', 'rsrc/js/application/releeph/releeph-preview-branch.js' => 'b2b4fbaf', @@ -460,7 +459,7 @@ return array( 'rsrc/js/core/behavior-autofocus.js' => '7319e029', 'rsrc/js/core/behavior-choose-control.js' => '6153c708', 'rsrc/js/core/behavior-crop.js' => 'fa0f4fc2', - 'rsrc/js/core/behavior-dark-console.js' => '87987821', + 'rsrc/js/core/behavior-dark-console.js' => 'f411b6ae', 'rsrc/js/core/behavior-device.js' => 'a205cf28', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '6d49590e', 'rsrc/js/core/behavior-error-log.js' => '6882e80a', @@ -560,14 +559,13 @@ return array( 'javelin-behavior-aphront-more' => 'a80d0378', 'javelin-behavior-audio-source' => '59b251eb', 'javelin-behavior-audit-preview' => 'd835b03a', - 'javelin-behavior-boards-dropdown' => '0ec56e1d', 'javelin-behavior-choose-control' => '6153c708', 'javelin-behavior-config-reorder-fields' => '14a827de', 'javelin-behavior-conpherence-menu' => '077a1dab', 'javelin-behavior-conpherence-pontificate' => '21ba5861', 'javelin-behavior-conpherence-widget-pane' => '93568464', 'javelin-behavior-countdown-timer' => 'e4cc26b3', - 'javelin-behavior-dark-console' => '87987821', + 'javelin-behavior-dark-console' => 'f411b6ae', 'javelin-behavior-dashboard-async-panel' => '469c0d9e', 'javelin-behavior-dashboard-move-panels' => '82439934', 'javelin-behavior-dashboard-query-panel-select' => '453c5375', @@ -642,7 +640,7 @@ return array( 'javelin-behavior-policy-control' => '1ed33505', 'javelin-behavior-policy-rule-editor' => '5e9f347c', 'javelin-behavior-ponder-votebox' => '4e9b766b', - 'javelin-behavior-project-boards' => '87cb6b51', + 'javelin-behavior-project-boards' => '60292820', 'javelin-behavior-project-create' => '065227cc', 'javelin-behavior-quicksand-blacklist' => '7927a7d3', 'javelin-behavior-refresh-csrf' => '7814b593', @@ -677,7 +675,7 @@ return array( 'javelin-leader' => '331b1611', 'javelin-magical-init' => '3010e992', 'javelin-mask' => '8a41885b', - 'javelin-quicksand' => '517545ab', + 'javelin-quicksand' => '51aeb01d', 'javelin-reactor' => '2b8de964', 'javelin-reactor-dom' => 'c90a04fc', 'javelin-reactor-node-calmer' => '76f4ebed', @@ -921,12 +919,6 @@ return array( 'javelin-util', 'phabricator-notification-css', ), - '0ec56e1d' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-stratcom', - 'phuix-dropdown-menu', - ), '0f764c35' => array( 'javelin-install', 'javelin-util', @@ -1193,14 +1185,14 @@ return array( 'javelin-typeahead-source', 'javelin-util', ), - '517545ab' => array( - 'javelin-install', - ), '519705ea' => array( 'javelin-install', 'javelin-dom', 'javelin-reactor-dom', ), + '51aeb01d' => array( + 'javelin-install', + ), '54b612ba' => array( 'javelin-color', 'javelin-install', @@ -1274,6 +1266,15 @@ return array( 'javelin-workflow', 'javelin-stratcom', ), + 60292820 => array( + 'javelin-behavior', + 'javelin-dom', + 'javelin-util', + 'javelin-vector', + 'javelin-stratcom', + 'javelin-workflow', + 'phabricator-draggable-list', + ), 60479091 => array( 'phabricator-busy', 'javelin-behavior', @@ -1472,23 +1473,6 @@ return array( 'aphront-typeahead-control-css', 'phui-tag-view-css', ), - 87987821 => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-util', - 'javelin-dom', - 'javelin-request', - 'phabricator-keyboard-shortcut', - ), - '87cb6b51' => array( - 'javelin-behavior', - 'javelin-dom', - 'javelin-util', - 'javelin-vector', - 'javelin-stratcom', - 'javelin-workflow', - 'phabricator-draggable-list', - ), '88236f00' => array( 'javelin-behavior', 'phabricator-keyboard-shortcut', @@ -1970,6 +1954,14 @@ return array( 'javelin-vector', 'phabricator-hovercard', ), + 'f411b6ae' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-util', + 'javelin-dom', + 'javelin-request', + 'phabricator-keyboard-shortcut', + ), 'f5d1233b' => array( 'javelin-behavior', 'javelin-dom', diff --git a/src/applications/base/controller/PhabricatorController.php b/src/applications/base/controller/PhabricatorController.php index 09bc69ad91..e2b899ab6e 100644 --- a/src/applications/base/controller/PhabricatorController.php +++ b/src/applications/base/controller/PhabricatorController.php @@ -3,6 +3,7 @@ abstract class PhabricatorController extends AphrontController { private $handles; + private $extraQuicksandConfig = array(); public function shouldRequireLogin() { return true; @@ -61,6 +62,15 @@ abstract class PhabricatorController extends AphrontController { return false; } + public function addExtraQuicksandConfig($config) { + $this->extraQuicksandConfig += $config; + return $this; + } + + private function getExtraQuicksandConfig() { + return $this->extraQuicksandConfig; + } + public function willBeginExecution() { $request = $this->getRequest(); @@ -294,7 +304,8 @@ abstract class PhabricatorController extends AphrontController { private function buildPageResponse($page) { if ($this->getRequest()->isQuicksand()) { $response = id(new AphrontAjaxResponse()) - ->setContent($page->renderForQuicksand()); + ->setContent($page->renderForQuicksand( + $this->getExtraQuicksandConfig())); } else { $response = id(new AphrontWebpageResponse()) ->setContent($page->render()); diff --git a/src/applications/project/controller/PhabricatorProjectBoardViewController.php b/src/applications/project/controller/PhabricatorProjectBoardViewController.php index 27e16ce56c..031427d058 100644 --- a/src/applications/project/controller/PhabricatorProjectBoardViewController.php +++ b/src/applications/project/controller/PhabricatorProjectBoardViewController.php @@ -265,15 +265,17 @@ final class PhabricatorProjectBoardViewController ->setUser($viewer) ->setID($board_id); + $behavior_config = array( + 'boardID' => $board_id, + 'projectPHID' => $project->getPHID(), + 'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'), + 'createURI' => '/maniphest/task/create/', + 'order' => $this->sortKey, + ); $this->initBehavior( 'project-boards', - array( - 'boardID' => $board_id, - 'projectPHID' => $project->getPHID(), - 'moveURI' => $this->getApplicationURI('move/'.$project->getID().'/'), - 'createURI' => '/maniphest/task/create/', - 'order' => $this->sortKey, - )); + $behavior_config); + $this->addExtraQuickSandConfig(array('boardConfig' => $behavior_config)); $this->handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks); @@ -340,10 +342,6 @@ final class PhabricatorProjectBoardViewController $board->addPanel($panel); } - Javelin::initBehavior( - 'boards-dropdown', - array()); - $sort_menu = $this->buildSortMenu( $viewer, $sort_key); diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php index 55744995c0..7e7bb4fae0 100644 --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -601,14 +601,15 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView { $foot); } - public function renderForQuicksand() { + public function renderForQuicksand(array $extra_config) { parent::willRenderPage(); $response = $this->renderPageBodyContent(); $response = $this->willSendResponse($response); return array( 'content' => hsprintf('%s', $response), - ) + $this->buildQuicksandConfig(); + ) + $this->buildQuicksandConfig() + + $extra_config; } private function buildQuicksandConfig() { diff --git a/webroot/rsrc/externals/javelin/lib/Quicksand.js b/webroot/rsrc/externals/javelin/lib/Quicksand.js index f2ca8d6b36..0d6be34487 100644 --- a/webroot/rsrc/externals/javelin/lib/Quicksand.js +++ b/webroot/rsrc/externals/javelin/lib/Quicksand.js @@ -68,6 +68,10 @@ JX.install('Quicksand', { }, + getCurrentPageID: function() { + return JX.Quicksand._id; + }, + /** * Respond to the user clicking a link. * @@ -234,7 +238,9 @@ JX.install('Quicksand', { null, { newResponse: self._responses[self._current], + newResponseID: self._current, oldResponse: self._responses[self._onpage], + oldResponseID: self._onpage, fromServer: from_server }); self._onpage = self._current; diff --git a/webroot/rsrc/js/application/projects/behavior-boards-dropdown.js b/webroot/rsrc/js/application/projects/behavior-boards-dropdown.js deleted file mode 100644 index 92f61024c9..0000000000 --- a/webroot/rsrc/js/application/projects/behavior-boards-dropdown.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @provides javelin-behavior-boards-dropdown - * @requires javelin-behavior - * javelin-dom - * javelin-stratcom - * phuix-dropdown-menu - */ - -JX.behavior('boards-dropdown', function() { - - JX.Stratcom.listen('click', 'boards-dropdown-menu', function(e) { - var data = e.getNodeData('boards-dropdown-menu'); - if (data.menu) { - return; - } - - e.kill(); - - var list = JX.$H(data.items).getFragment().firstChild; - - var button = e.getNode('boards-dropdown-menu'); - data.menu = new JX.PHUIXDropdownMenu(button); - data.menu.setContent(list); - data.menu.open(); - - JX.DOM.listen(list, 'click', 'tag:a', function(e) { - if (!e.isNormalClick()) { - return; - } - data.menu.close(); - }); - }); - - -}); diff --git a/webroot/rsrc/js/application/projects/behavior-project-boards.js b/webroot/rsrc/js/application/projects/behavior-project-boards.js index 3455b2fac1..20a78d0963 100644 --- a/webroot/rsrc/js/application/projects/behavior-project-boards.js +++ b/webroot/rsrc/js/application/projects/behavior-project-boards.js @@ -9,7 +9,7 @@ * phabricator-draggable-list */ -JX.behavior('project-boards', function(config) { +JX.behavior('project-boards', function(config, statics) { function finditems(col) { return JX.DOM.scry(col, 'li', 'project-card'); @@ -69,7 +69,7 @@ JX.behavior('project-boards', function(config) { } function getcolumns() { - return JX.DOM.scry(JX.$(config.boardID), 'ul', 'project-column'); + return JX.DOM.scry(JX.$(statics.boardID), 'ul', 'project-column'); } function colsort(u, v) { @@ -91,7 +91,7 @@ JX.behavior('project-boards', function(config) { function getcontainer() { return JX.DOM.find( - JX.$(config.boardID), + JX.$(statics.boardID), 'div', 'aphront-multi-column-view'); } @@ -164,9 +164,9 @@ JX.behavior('project-boards', function(config) { data.beforePHID = before_phid; } - data.order = config.order; + data.order = statics.order; - var workflow = new JX.Workflow(config.moveURI, data) + var workflow = new JX.Workflow(statics.moveURI, data) .setHandler(function(response) { onresponse(response, item, list); }); @@ -174,32 +174,7 @@ JX.behavior('project-boards', function(config) { workflow.start(); } - var lists = []; - var ii; - var cols = getcolumns(); - - for (ii = 0; ii < cols.length; ii++) { - var list = new JX.DraggableList('project-card', cols[ii]) - .setFindItemsHandler(JX.bind(null, finditems, cols[ii])); - - list.listen('didSend', JX.bind(list, onupdate, cols[ii])); - list.listen('didReceive', JX.bind(list, onupdate, cols[ii])); - - list.listen('didDrop', JX.bind(null, ondrop, list)); - - list.listen('didBeginDrag', JX.bind(null, onbegindrag)); - list.listen('didEndDrag', JX.bind(null, onenddrag)); - - lists.push(list); - - onupdate(cols[ii]); - } - - for (ii = 0; ii < lists.length; ii++) { - lists[ii].setGroup(lists); - } - - var onedit = function(column, r) { + function onedit(column, r) { var new_card = JX.$H(r.tasks).getNode(); var new_data = JX.Stratcom.getData(new_card); var items = finditems(column); @@ -241,50 +216,136 @@ JX.behavior('project-boards', function(config) { onupdate(column); }; - JX.Stratcom.listen( - 'click', - ['edit-project-card'], - function(e) { - e.kill(); - var column = e.getNode('project-column'); - var request_data = { - responseType: 'card', - columnPHID: JX.Stratcom.getData(column).columnPHID, - order: config.order - }; - new JX.Workflow(e.getNode('tag:a').href, request_data) - .setHandler(JX.bind(null, onedit, column)) - .start(); - }); + function update_statics(update_config) { + statics.boardID = update_config.boardID; + statics.projectPHID = update_config.projectPHID; + statics.order = update_config.order; + statics.moveURI = update_config.moveURI; + statics.createURI = update_config.createURI; + } - JX.Stratcom.listen( - 'click', - ['column-add-task'], - function (e) { + function init_board() { + var lists = []; + var ii; + var cols = getcolumns(); - // We want the 'boards-dropdown-menu' behavior to see this event and - // close the dropdown, but don't want to follow the link. - e.prevent(); + for (ii = 0; ii < cols.length; ii++) { + var list = new JX.DraggableList('project-card', cols[ii]) + .setFindItemsHandler(JX.bind(null, finditems, cols[ii])); - var column_phid = e.getNodeData('column-add-task').columnPHID; - var request_data = { - responseType: 'card', - columnPHID: column_phid, - projects: config.projectPHID, - order: config.order - }; - var cols = getcolumns(); - var ii; - var column; - for (ii = 0; ii < cols.length; ii++) { - if (JX.Stratcom.getData(cols[ii]).columnPHID == column_phid) { - column = cols[ii]; - break; + list.listen('didSend', JX.bind(list, onupdate, cols[ii])); + list.listen('didReceive', JX.bind(list, onupdate, cols[ii])); + + list.listen('didDrop', JX.bind(null, ondrop, list)); + + list.listen('didBeginDrag', JX.bind(null, onbegindrag)); + list.listen('didEndDrag', JX.bind(null, onenddrag)); + + lists.push(list); + + onupdate(cols[ii]); + } + + for (ii = 0; ii < lists.length; ii++) { + lists[ii].setGroup(lists); + } + + JX.Stratcom.listen( + 'click', + ['edit-project-card'], + function(e) { + e.kill(); + var column = e.getNode('project-column'); + var request_data = { + responseType: 'card', + columnPHID: JX.Stratcom.getData(column).columnPHID, + order: statics.order + }; + new JX.Workflow(e.getNode('tag:a').href, request_data) + .setHandler(JX.bind(null, onedit, column)) + .start(); + }); + + JX.Stratcom.listen( + 'click', + ['column-add-task'], + function (e) { + + // We want the 'boards-dropdown-menu' behavior to see this event and + // close the dropdown, but don't want to follow the link. + e.prevent(); + + var column_phid = e.getNodeData('column-add-task').columnPHID; + var request_data = { + responseType: 'card', + columnPHID: column_phid, + projects: statics.projectPHID, + order: statics.order + }; + var cols = getcolumns(); + var ii; + var column; + for (ii = 0; ii < cols.length; ii++) { + if (JX.Stratcom.getData(cols[ii]).columnPHID == column_phid) { + column = cols[ii]; + break; + } } + new JX.Workflow(statics.createURI, request_data) + .setHandler(JX.bind(null, onedit, column)) + .start(); + }); + + JX.Stratcom.listen('click', 'boards-dropdown-menu', function(e) { + var data = e.getNodeData('boards-dropdown-menu'); + if (data.menu) { + return; } - new JX.Workflow(config.createURI, request_data) - .setHandler(JX.bind(null, onedit, column)) - .start(); + + e.kill(); + + var list = JX.$H(data.items).getFragment().firstChild; + + var button = e.getNode('boards-dropdown-menu'); + data.menu = new JX.PHUIXDropdownMenu(button); + data.menu.setContent(list); + data.menu.open(); + + JX.DOM.listen(list, 'click', 'tag:a', function(e) { + if (!e.isNormalClick()) { + return; + } + data.menu.close(); + }); }); + JX.Stratcom.listen( + 'quicksand-redraw', + null, + function (e) { + var data = e.getData(); + if (!data.newResponse.boardConfig) { + return; + } + var new_config; + if (data.fromServer) { + new_config = data.newResponse.boardConfig; + statics.boardConfigCache[data.newResponseID] = new_config; + } else { + new_config = statics.boardConfigCache[data.newResponseID]; + statics.boardID = new_config.boardID; + } + update_statics(new_config); + }); + return true; + } + + if (!statics.setup) { + update_statics(config); + var current_page_id = JX.Quicksand.getCurrentPageID(); + statics.boardConfigCache = {}; + statics.boardConfigCache[current_page_id] = config; + statics.setup = init_board(); + } + }); diff --git a/webroot/rsrc/js/core/behavior-dark-console.js b/webroot/rsrc/js/core/behavior-dark-console.js index 203ea76de4..3322d31227 100644 --- a/webroot/rsrc/js/core/behavior-dark-console.js +++ b/webroot/rsrc/js/core/behavior-dark-console.js @@ -38,7 +38,6 @@ JX.behavior('dark-console', function(config, statics) { 'quicksand-redraw', null, function (e) { - e.kill(); var data = e.getData(); var new_console; if (data.fromServer) {