diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -11,7 +11,7 @@ 'conpherence.pkg.js' => '281b1a73', 'core.pkg.css' => 'b2ad82f4', 'core.pkg.js' => 'deabcef7', - 'darkconsole.pkg.js' => 'e7393ebb', + 'darkconsole.pkg.js' => '12813435', 'differential.pkg.css' => '90b30783', 'differential.pkg.js' => 'ddfeb49b', 'diffusion.pkg.css' => '91c5d3a6', @@ -20,7 +20,7 @@ 'maniphest.pkg.css' => '4845691a', 'maniphest.pkg.js' => '5ab2753f', 'rsrc/css/aphront/aphront-bars.css' => '231ac33c', - 'rsrc/css/aphront/dark-console.css' => 'f54bf286', + 'rsrc/css/aphront/dark-console.css' => '07dd8d38', 'rsrc/css/aphront/dialog-view.css' => '685c7e2d', 'rsrc/css/aphront/list-filter-view.css' => '5d6f0526', 'rsrc/css/aphront/multi-column.css' => '84cc6640', @@ -482,7 +482,6 @@ 'rsrc/js/core/behavior-autofocus.js' => '7319e029', 'rsrc/js/core/behavior-badge-view.js' => '8ff5e24c', 'rsrc/js/core/behavior-choose-control.js' => '327a00d1', - 'rsrc/js/core/behavior-dark-console.js' => 'f411b6ae', 'rsrc/js/core/behavior-detect-timezone.js' => '4c193c96', 'rsrc/js/core/behavior-device.js' => 'bb1dd507', 'rsrc/js/core/behavior-drag-and-drop-textarea.js' => '484a6e22', @@ -521,6 +520,10 @@ 'rsrc/js/core/behavior-user-menu.js' => '31420f77', 'rsrc/js/core/behavior-watch-anchor.js' => '9f36c42d', 'rsrc/js/core/behavior-workflow.js' => '0a3f3021', + 'rsrc/js/core/darkconsole/DarkLog.js' => 'c8e1ffe3', + 'rsrc/js/core/darkconsole/DarkMessage.js' => 'c48cccdd', + 'rsrc/js/core/darkconsole/behavior-dark-console-realtime.js' => '1e601b1d', + 'rsrc/js/core/darkconsole/behavior-dark-console.js' => 'fdd14f6a', 'rsrc/js/core/phtize.js' => 'd254d646', 'rsrc/js/phui/behavior-phui-dropdown-menu.js' => 'b95d6f7d', 'rsrc/js/phui/behavior-phui-file-upload.js' => 'b003d4fb', @@ -536,7 +539,7 @@ 'symbols' => array( 'almanac-css' => 'dbb9b3af', 'aphront-bars' => '231ac33c', - 'aphront-dark-console-css' => 'f54bf286', + 'aphront-dark-console-css' => '07dd8d38', 'aphront-dialog-view-css' => '685c7e2d', 'aphront-list-filter-view-css' => '5d6f0526', 'aphront-multi-column-view-css' => '84cc6640', @@ -603,7 +606,8 @@ 'javelin-behavior-conpherence-pontificate' => '55616e04', 'javelin-behavior-conpherence-search' => '9bbf3762', 'javelin-behavior-countdown-timer' => 'e4cc26b3', - 'javelin-behavior-dark-console' => 'f411b6ae', + 'javelin-behavior-dark-console' => 'fdd14f6a', + 'javelin-behavior-dark-console-realtime' => '1e601b1d', 'javelin-behavior-dashboard-async-panel' => '469c0d9e', 'javelin-behavior-dashboard-move-panels' => '408bf173', 'javelin-behavior-dashboard-query-panel-select' => '453c5375', @@ -774,6 +778,8 @@ 'phabricator-content-source-view-css' => '4b8b05d4', 'phabricator-core-css' => '9f4cb463', 'phabricator-countdown-css' => '16c52f5c', + 'phabricator-darklog' => 'c8e1ffe3', + 'phabricator-darkmessage' => 'c48cccdd', 'phabricator-dashboard-css' => 'fe5b1869', 'phabricator-drag-and-drop-file-upload' => '58dea2fa', 'phabricator-draggable-list' => 'bea6e7f4', @@ -1041,6 +1047,13 @@ 'javelin-dom', 'javelin-reactor-dom', ), + '1e601b1d' => array( + 'javelin-behavior', + 'javelin-dom', + 'phabricator-darklog', + 'phabricator-darkmessage', + 'javelin-leader', + ), '1e911d0f' => array( 'javelin-stratcom', 'javelin-request', @@ -2173,14 +2186,6 @@ 'f12cbc9f' => array( 'phui-oi-list-view-css', ), - 'f411b6ae' => array( - 'javelin-behavior', - 'javelin-stratcom', - 'javelin-util', - 'javelin-dom', - 'javelin-request', - 'phabricator-keyboard-shortcut', - ), 'f50152ad' => array( 'phui-timeline-view-css', ), @@ -2236,6 +2241,14 @@ 'javelin-dom', 'phortune-credit-card-form', ), + 'fdd14f6a' => array( + 'javelin-behavior', + 'javelin-stratcom', + 'javelin-util', + 'javelin-dom', + 'javelin-request', + 'phabricator-keyboard-shortcut', + ), 'fe287620' => array( 'javelin-install', 'javelin-dom', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -349,6 +349,7 @@ 'DarkConsoleEventPlugin' => 'applications/console/plugin/DarkConsoleEventPlugin.php', 'DarkConsoleEventPluginAPI' => 'applications/console/plugin/event/DarkConsoleEventPluginAPI.php', 'DarkConsolePlugin' => 'applications/console/plugin/DarkConsolePlugin.php', + 'DarkConsoleRealtimePlugin' => 'applications/console/plugin/DarkConsoleRealtimePlugin.php', 'DarkConsoleRequestPlugin' => 'applications/console/plugin/DarkConsoleRequestPlugin.php', 'DarkConsoleServicesPlugin' => 'applications/console/plugin/DarkConsoleServicesPlugin.php', 'DarkConsoleStartupPlugin' => 'applications/console/plugin/DarkConsoleStartupPlugin.php', @@ -5144,6 +5145,7 @@ 'DarkConsoleEventPlugin' => 'DarkConsolePlugin', 'DarkConsoleEventPluginAPI' => 'PhabricatorEventListener', 'DarkConsolePlugin' => 'Phobject', + 'DarkConsoleRealtimePlugin' => 'DarkConsolePlugin', 'DarkConsoleRequestPlugin' => 'DarkConsolePlugin', 'DarkConsoleServicesPlugin' => 'DarkConsolePlugin', 'DarkConsoleStartupPlugin' => 'DarkConsolePlugin', diff --git a/src/applications/console/plugin/DarkConsoleRealtimePlugin.php b/src/applications/console/plugin/DarkConsoleRealtimePlugin.php new file mode 100644 --- /dev/null +++ b/src/applications/console/plugin/DarkConsoleRealtimePlugin.php @@ -0,0 +1,34 @@ + $node_id, + )); + + return phutil_tag( + 'div', + array( + 'id' => $node_id, + 'class' => 'dark-console-log-frame', + )); + } + +} diff --git a/webroot/rsrc/css/aphront/dark-console.css b/webroot/rsrc/css/aphront/dark-console.css --- a/webroot/rsrc/css/aphront/dark-console.css +++ b/webroot/rsrc/css/aphront/dark-console.css @@ -217,3 +217,17 @@ .dark-console-panel-error-details { display: none; } + +.dark-console-log-frame { + height: 500px; + overflow: auto; + background: #303030; + border: 1px solid #202020; + margin: 4px; +} + +.dark-console-log-message { + background: #404040; + padding: 8px; + margin: 2px; +} diff --git a/webroot/rsrc/js/core/darkconsole/DarkLog.js b/webroot/rsrc/js/core/darkconsole/DarkLog.js new file mode 100644 --- /dev/null +++ b/webroot/rsrc/js/core/darkconsole/DarkLog.js @@ -0,0 +1,47 @@ +/** + * @provides phabricator-darklog + * @javelin + */ + +JX.install('DarkLog', { + + construct: function() { + this._messages = []; + }, + + members: { + _node: null, + _messages: null, + + addMessage: function(message) { + var node = message.getNode(); + + this._messages.push(message); + if (this._node) { + this._append([node]); + } + + return this; + }, + + setNode: function(node) { + var nodes = []; + for (var ii = 0; ii < this._messages.length; ii++) { + nodes.push(this._messages[ii].getNode()); + } + + this._node = node; + this._append(nodes); + + return this; + }, + + _append: function(nodes) { + for (var ii = 0; ii < nodes.length; ii++) { + this._node.appendChild(nodes[ii]); + } + } + + } + +}); diff --git a/webroot/rsrc/js/core/darkconsole/DarkMessage.js b/webroot/rsrc/js/core/darkconsole/DarkMessage.js new file mode 100644 --- /dev/null +++ b/webroot/rsrc/js/core/darkconsole/DarkMessage.js @@ -0,0 +1,37 @@ +/** + * @provides phabricator-darkmessage + * @javelin + */ + +JX.install('DarkMessage', { + + construct: function() { + + }, + + members: { + _node: null, + _message: null, + + setMessage: function(message) { + this._message = message; + + JX.DOM.setContent(this.getNode(), message); + + return this; + }, + + getNode: function() { + if (!this._node) { + this._node = JX.$N( + 'div', + { + className: 'dark-console-log-message' + }); + } + + return this._node; + } + } + +}); diff --git a/webroot/rsrc/js/core/darkconsole/behavior-dark-console-realtime.js b/webroot/rsrc/js/core/darkconsole/behavior-dark-console-realtime.js new file mode 100644 --- /dev/null +++ b/webroot/rsrc/js/core/darkconsole/behavior-dark-console-realtime.js @@ -0,0 +1,72 @@ +/** + * @provides javelin-behavior-dark-console-realtime + * @requires javelin-behavior + * javelin-dom + * phabricator-darklog + * phabricator-darkmessage + * javelin-leader + * @javelin + */ + +JX.behavior('dark-console-realtime', function(config, statics) { + if (statics.setup) { + return; + } + statics.setup = true; + + var log = new JX.DarkLog(); + + JX.Stratcom.listen('darkconsole.draw', null, function(e) { + var data = e.getData(); + if (data.panel != 'DarkConsoleRealtimePlugin') { + return; + } + + var node = JX.$(config.nodeID); + log.setNode(node); + }); + + // If the panel is initially visible, try rendering. + try { + var node = JX.$(config.nodeID); + log.setNode(node); + } catch (exception) { + // Ignore. + } + + var leader_log = function(event_name, type, is_leader, details) { + var parts = []; + if (is_leader === true) { + parts.push('+'); + } else if (is_leader === false) { + parts.push('-'); + } + + parts.push('[Leader/' + event_name + ']'); + + if (type) { + parts.push('(' + type + ')'); + } + + if (details) { + parts.push(details); + } + + parts = parts.join(' '); + + var message = new JX.DarkMessage() + .setMessage(parts); + + log.addMessage(message); + }; + + JX.Leader.listen('onReceiveBroadcast', function(message, is_leader) { + var json = JX.JSON.stringify(message.data); + leader_log('onReceiveBroadcast', message.type, is_leader, json); + }); + + JX.Leader.listen('onBecomeLeader', function() { + leader_log('onBecomeLeader'); + }); + +}); diff --git a/webroot/rsrc/js/core/behavior-dark-console.js b/webroot/rsrc/js/core/darkconsole/behavior-dark-console.js rename from webroot/rsrc/js/core/behavior-dark-console.js rename to webroot/rsrc/js/core/darkconsole/behavior-dark-console.js --- a/webroot/rsrc/js/core/behavior-dark-console.js +++ b/webroot/rsrc/js/core/darkconsole/behavior-dark-console.js @@ -246,6 +246,12 @@ var div = JX.$N('div', {className: 'dark-console-panel-core'}, JX.$H(html)); JX.DOM.setContent(statics.el.panel, div); + + var params = { + panel: tclass + }; + + JX.Stratcom.invoke('darkconsole.draw', null, params); } function install_shortcut() {