From 6aac9f99d7fe400698e9f6ece5071c2511d5e1c0 Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Mon, 27 Apr 2015 16:10:36 -0700 Subject: [PATCH] Quicksand - get the dark console working properly with quicksand Summary: Fixes T7700. This ends up being kind of tricky because - the key for a given request is only correct at the time the dark console is rendered - the dark console itself should contain every request made, as opposed to being drawn from scratch - in the case of a quicksand request, the behavior gets invoked first with the correctly rendered console as part of the `quicksand-redraw` event and then again shortly after as an ajax request would, except this is incorrect relative to when the key should be calculated... So... - assume we can get away with concurrency between the `quicksand-redraw` event and ajax request invocation of the behavior - cache the right data as part of the `quicksand-redraw` event and then use it in the subsequent ajax call - make sure ajax config gets a 'quicksand' flag ...otherwise its somewhat standard make sure this behavior can be init'd a bunch stuff. Test Plan: visited '/', visited '/differential/', visited '/DXXX' - observed correctly populating dark console with all sorts of good data stuff. navigated backwards and observed dark console staying the same as expected. navigated by clicking links and console updated again Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T7700 Differential Revision: https://secure.phabricator.com/D12582 --- resources/celerity/map.php | 22 +-- src/aphront/response/AphrontAjaxResponse.php | 7 +- webroot/rsrc/js/core/behavior-dark-console.js | 131 ++++++++++++------ 3 files changed, 101 insertions(+), 59 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index e75bbaab5d..76e1d9fe8c 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'core.pkg.css' => '9a9b59ca', 'core.pkg.js' => '59d01bb7', - 'darkconsole.pkg.js' => '8ab24e01', + 'darkconsole.pkg.js' => '6d16ff19', 'differential.pkg.css' => '3500921f', 'differential.pkg.js' => '890046d3', 'diffusion.pkg.css' => '591664fa', @@ -460,7 +460,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' => '08883e8b', + 'rsrc/js/core/behavior-dark-console.js' => '87987821', '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', @@ -567,7 +567,7 @@ return array( 'javelin-behavior-conpherence-pontificate' => '21ba5861', 'javelin-behavior-conpherence-widget-pane' => '93568464', 'javelin-behavior-countdown-timer' => 'e4cc26b3', - 'javelin-behavior-dark-console' => '08883e8b', + 'javelin-behavior-dark-console' => '87987821', 'javelin-behavior-dashboard-async-panel' => '469c0d9e', 'javelin-behavior-dashboard-move-panels' => '82439934', 'javelin-behavior-dashboard-query-panel-select' => '453c5375', @@ -897,14 +897,6 @@ return array( 'javelin-uri', 'phabricator-file-upload', ), - '08883e8b' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-util', - 'javelin-dom', - 'javelin-request', - 'phabricator-keyboard-shortcut', - ), '0a3f3021' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1483,6 +1475,14 @@ 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', diff --git a/src/aphront/response/AphrontAjaxResponse.php b/src/aphront/response/AphrontAjaxResponse.php index c37fcb3de9..f44c4cb6c6 100644 --- a/src/aphront/response/AphrontAjaxResponse.php +++ b/src/aphront/response/AphrontAjaxResponse.php @@ -44,9 +44,10 @@ final class AphrontAjaxResponse extends AphrontResponse { Javelin::initBehavior( 'dark-console', array( - 'uri' => (string)$uri, - 'key' => $console->getKey($this->getRequest()), - 'color' => $console->getColor(), + 'uri' => (string)$uri, + 'key' => $console->getKey($this->getRequest()), + 'color' => $console->getColor(), + 'quicksand' => $this->getRequest()->isQuicksand(), )); } diff --git a/webroot/rsrc/js/core/behavior-dark-console.js b/webroot/rsrc/js/core/behavior-dark-console.js index 26c1fc84d7..203ea76de4 100644 --- a/webroot/rsrc/js/core/behavior-dark-console.js +++ b/webroot/rsrc/js/core/behavior-dark-console.js @@ -9,8 +9,60 @@ */ JX.behavior('dark-console', function(config, statics) { + // Do first-time setup. function setup_console() { + init_console(config.visible); + + statics.selected = config.selected; + + install_shortcut(); + + if (config.headers) { + // If the main page had profiling enabled, also enable it for any Ajax + // requests. + JX.Request.listen('open', function(r) { + for (var k in config.headers) { + r.getTransport().setRequestHeader(k, config.headers[k]); + } + }); + } + + // When the user clicks a tab, select it. + JX.Stratcom.listen('click', 'dark-console-tab', function(e) { + e.kill(); + select_tab(e.getNodeData('dark-console-tab')['class']); + }); + + JX.Stratcom.listen( + 'quicksand-redraw', + null, + function (e) { + e.kill(); + var data = e.getData(); + var new_console; + if (data.fromServer) { + new_console = JX.$('darkconsole'); + // The correct key has to be pulled from the rendered console + statics.quicksand_key = new_console.getAttribute('data-console-key'); + statics.quicksand_color = + new_console.getAttribute('data-console-color'); + } else { + // we need to add a console holder back in since we blew it away + new_console = JX.$N( + 'div', + { id : 'darkconsole', class : 'dark-console' }); + JX.DOM.prependContent( + JX.$('phabricator-standard-page-body'), + new_console); + } + JX.DOM.replace(new_console, statics.root); + }); + + return statics.root; + } + + function init_console(visible) { statics.root = JX.$('darkconsole'); statics.req = {all: {}, current: null}; statics.tab = {all: {}, current: null}; @@ -31,33 +83,11 @@ JX.behavior('dark-console', function(config, statics) { statics.cache = {}; - statics.visible = config.visible; - statics.selected = config.selected; - - install_shortcut(); - - if (config.headers) { - // If the main page had profiling enabled, also enable it for any Ajax - // requests. - JX.Request.listen('open', function(r) { - for (var k in config.headers) { - r.getTransport().setRequestHeader(k, config.headers[k]); - } - }); - } + statics.visible = visible; return statics.root; } - var root = statics.root || setup_console(); - - config.key = config.key || root.getAttribute('data-console-key'); - - if (!('color' in config)) { - config.color = root.getAttribute('data-console-color'); - } - - // Add a new request to the console (initial page load, or new Ajax response). function add_request(config) { @@ -78,12 +108,21 @@ JX.behavior('dark-console', function(config, statics) { statics.el.reqs.appendChild(link); statics.req.all[config.key] = link; + // When the user clicks a request, select it. + JX.DOM.listen( + link, + 'click', + 'dark-console-request', + function(e) { + e.kill(); + select_request(e.getNodeData('dark-console-request').key); + }); + if (!statics.req.current) { select_request(config.key); } } - function get_bullet(color) { if (!color) { return null; @@ -91,29 +130,25 @@ JX.behavior('dark-console', function(config, statics) { return JX.$N('span', {style: {color: color}}, '\u2022'); } - // Select a request (on load, or when the user clicks one). function select_request(key) { - var req = statics.req; - - if (req.current) { - JX.DOM.alterClass(req.all[req.current], 'dark-selected', false); + if (statics.req.current) { + JX.DOM.alterClass( + statics.req.all[statics.req.current], + 'dark-selected', + false); } statics.req.current = key; - JX.DOM.alterClass(req.all[req.current], 'dark-selected', true); + JX.DOM.alterClass( + statics.req.all[statics.req.current], + 'dark-selected', + true); if (statics.visible) { draw_request(key); } } - // When the user clicks a request, select it. - JX.Stratcom.listen('click', 'dark-console-request', function(e) { - e.kill(); - select_request(e.getNodeData('dark-console-request').key); - }); - - // After the user selects a request, draw its tabs. function draw_request(key) { var cache = statics.cache; @@ -205,12 +240,6 @@ JX.behavior('dark-console', function(config, statics) { draw_panel(); } - // When the user clicks a tab, select it. - JX.Stratcom.listen('click', 'dark-console-tab', function(e) { - e.kill(); - select_tab(e.getNodeData('dark-console-tab')['class']); - }); - function draw_panel() { var data = statics.cache[statics.req.current]; var tclass = JX.Stratcom.getData(statics.tab.current)['class']; @@ -227,12 +256,12 @@ JX.behavior('dark-console', function(config, statics) { statics.visible = !statics.visible; if (statics.visible) { - JX.DOM.show(root); + JX.DOM.show(statics.root); if (statics.req.current) { draw_request(statics.req.current); } } else { - JX.DOM.hide(root); + JX.DOM.hide(statics.root); } // Save user preference. @@ -246,5 +275,17 @@ JX.behavior('dark-console', function(config, statics) { .register(); } + statics.root = statics.root || setup_console(); + if (config.quicksand && statics.quicksand_key) { + config.key = statics.quicksand_key; + config.color = statics.quicksand_color; + statics.quicksand_key = null; + statics.quicksand_color = null; + } + config.key = config.key || statics.root.getAttribute('data-console-key'); + if (!('color' in config)) { + config.color = statics.root.getAttribute('data-console-color'); + } add_request(config); + });