1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 00:32:42 +01:00

Improve live Harbormaster log follow behaviors

Summary:
Depends on D19166. Ref T13088. When the user scrolls away from a followed log, break the focus lock.

Let users stop following a live log.

Show when lines are added more clearly.

Don't refresh quite as quickly give users a better shot at clicking the stop button.

These behaviors can probably be refined but are at least more plausible and less actively user-hostile than the first version of this behavior was.

Test Plan: Used `write-log --rate` to write a large log slowly. Clicked "Follow Log", followed for a bit. Scrolled away, still got live updates but no more scroll lock. Clicked stop, no more updates.

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13088

Differential Revision: https://secure.phabricator.com/D19167
This commit is contained in:
epriestley 2018-03-01 10:43:28 -08:00
parent 4e91ad276d
commit 1f40e50f7e
4 changed files with 93 additions and 18 deletions

View file

@ -78,7 +78,7 @@ return array(
'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 'rsrc/css/application/feed/feed.css' => 'ecd4ec57',
'rsrc/css/application/files/global-drag-and-drop.css' => 'b556a948', 'rsrc/css/application/files/global-drag-and-drop.css' => 'b556a948',
'rsrc/css/application/flag/flag.css' => 'bba8f811', 'rsrc/css/application/flag/flag.css' => 'bba8f811',
'rsrc/css/application/harbormaster/harbormaster.css' => 'cd73d427', 'rsrc/css/application/harbormaster/harbormaster.css' => '730a4a3c',
'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 'rsrc/css/application/herald/herald-test.css' => 'a52e323e',
'rsrc/css/application/herald/herald.css' => 'cd8d0134', 'rsrc/css/application/herald/herald.css' => 'cd8d0134',
'rsrc/css/application/maniphest/report.css' => '9b9580b7', 'rsrc/css/application/maniphest/report.css' => '9b9580b7',
@ -416,7 +416,7 @@ return array(
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef', 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab', 'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => 'ab1173d1', 'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '191b4909',
'rsrc/js/application/herald/HeraldRuleEditor.js' => 'dca75c0e', 'rsrc/js/application/herald/HeraldRuleEditor.js' => 'dca75c0e',
'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec', 'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec',
'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3', 'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3',
@ -579,7 +579,7 @@ return array(
'font-fontawesome' => 'e838e088', 'font-fontawesome' => 'e838e088',
'font-lato' => 'c7ccd872', 'font-lato' => 'c7ccd872',
'global-drag-and-drop-css' => 'b556a948', 'global-drag-and-drop-css' => 'b556a948',
'harbormaster-css' => 'cd73d427', 'harbormaster-css' => '730a4a3c',
'herald-css' => 'cd8d0134', 'herald-css' => 'cd8d0134',
'herald-rule-editor' => 'dca75c0e', 'herald-rule-editor' => 'dca75c0e',
'herald-test-css' => 'a52e323e', 'herald-test-css' => 'a52e323e',
@ -636,7 +636,7 @@ return array(
'javelin-behavior-event-all-day' => 'b41537c9', 'javelin-behavior-event-all-day' => 'b41537c9',
'javelin-behavior-fancy-datepicker' => 'ecf4e799', 'javelin-behavior-fancy-datepicker' => 'ecf4e799',
'javelin-behavior-global-drag-and-drop' => '960f6a39', 'javelin-behavior-global-drag-and-drop' => '960f6a39',
'javelin-behavior-harbormaster-log' => 'ab1173d1', 'javelin-behavior-harbormaster-log' => '191b4909',
'javelin-behavior-herald-rule-editor' => '7ebaeed3', 'javelin-behavior-herald-rule-editor' => '7ebaeed3',
'javelin-behavior-high-security-warning' => 'a464fe03', 'javelin-behavior-high-security-warning' => 'a464fe03',
'javelin-behavior-history-install' => '7ee2b591', 'javelin-behavior-history-install' => '7ee2b591',
@ -1022,6 +1022,9 @@ return array(
'185bbd53' => array( '185bbd53' => array(
'javelin-install', 'javelin-install',
), ),
'191b4909' => array(
'javelin-behavior',
),
'1ad0a787' => array( '1ad0a787' => array(
'javelin-install', 'javelin-install',
'javelin-reactor', 'javelin-reactor',
@ -1765,9 +1768,6 @@ return array(
'javelin-util', 'javelin-util',
'phabricator-prefab', 'phabricator-prefab',
), ),
'ab1173d1' => array(
'javelin-behavior',
),
'ab2f381b' => array( 'ab2f381b' => array(
'javelin-request', 'javelin-request',
'javelin-behavior', 'javelin-behavior',

View file

@ -720,12 +720,16 @@ final class HarbormasterBuildLogRenderController
private function renderLiveRow($log_size) { private function renderLiveRow($log_size) {
$icon_down = id(new PHUIIconView()) $icon_down = id(new PHUIIconView())
->setIcon('fa-chevron-down'); ->setIcon('fa-angle-double-down');
$icon_pause = id(new PHUIIconView())
->setIcon('fa-pause');
$follow = javelin_tag( $follow = javelin_tag(
'a', 'a',
array( array(
'sigil' => 'harbormaster-log-expand harbormaster-log-live', 'sigil' => 'harbormaster-log-expand harbormaster-log-live',
'class' => 'harbormaster-log-follow-start',
'meta' => array( 'meta' => array(
'headOffset' => $log_size, 'headOffset' => $log_size,
'head' => 0, 'head' => 0,
@ -737,8 +741,21 @@ final class HarbormasterBuildLogRenderController
$icon_down, $icon_down,
' ', ' ',
pht('Follow Log'), pht('Follow Log'),
));
$stop_following = javelin_tag(
'a',
array(
'sigil' => 'harbormaster-log-expand',
'class' => 'harbormaster-log-follow-stop',
'meta' => array(
'stop' => true,
),
),
array(
$icon_pause,
' ', ' ',
$icon_down, pht('Stop Following Log'),
)); ));
$expand_cells = array( $expand_cells = array(
@ -747,7 +764,10 @@ final class HarbormasterBuildLogRenderController
array( array(
'class' => 'harbormaster-log-follow', 'class' => 'harbormaster-log-follow',
), ),
$follow), array(
$follow,
$stop_following,
)),
); );
return $this->renderActionTable($expand_cells); return $this->renderActionTable($expand_cells);

View file

@ -139,3 +139,31 @@
.harbormaster-log-expand-down .phui-icon-view { .harbormaster-log-expand-down .phui-icon-view {
margin: 0 4px 0 0; margin: 0 4px 0 0;
} }
.harbormaster-log-following .harbormaster-log-table
.harbormaster-log-follow-start {
display: none;
}
.harbormaster-log-table .harbormaster-log-follow-stop {
display: none;
}
.harbormaster-log-following .harbormaster-log-table
.harbormaster-log-follow-stop {
display: block;
}
.harbormaster-log-appear > td {
animation: harbormaster-fade-in 1s linear;
}
@keyframes harbormaster-fade-in {
0% {
opacity: 0.5;
}
100% {
opacity: 1.0;
}
}

View file

@ -5,7 +5,9 @@
JX.behavior('harbormaster-log', function(config) { JX.behavior('harbormaster-log', function(config) {
var contentNode = JX.$(config.contentNodeID); var contentNode = JX.$(config.contentNodeID);
var following = false; var following = false;
var autoscroll = false;
JX.DOM.listen(contentNode, 'click', 'harbormaster-log-expand', function(e) { JX.DOM.listen(contentNode, 'click', 'harbormaster-log-expand', function(e) {
if (!e.isNormalClick()) { if (!e.isNormalClick()) {
@ -14,20 +16,29 @@ JX.behavior('harbormaster-log', function(config) {
e.kill(); e.kill();
expand(e.getTarget()); expand(e.getTarget(), true);
}); });
function expand(node) { function expand(node, is_action) {
var row = JX.DOM.findAbove(node, 'tr'); var row = JX.DOM.findAbove(node, 'tr');
row = JX.DOM.findAbove(row, 'tr'); row = JX.DOM.findAbove(row, 'tr');
var data = JX.Stratcom.getData(node); var data = JX.Stratcom.getData(node);
if (data.stop) {
following = false;
autoscroll = false;
JX.DOM.alterClass(contentNode, 'harbormaster-log-following', false);
return;
}
var uri = new JX.URI(config.renderURI) var uri = new JX.URI(config.renderURI)
.addQueryParams(data); .addQueryParams(data);
if (data.live) { if (data.live && is_action) {
following = true; following = true;
autoscroll = true;
JX.DOM.alterClass(contentNode, 'harbormaster-log-following', true);
} }
var request = new JX.Request(uri, function(r) { var request = new JX.Request(uri, function(r) {
@ -46,18 +57,34 @@ JX.behavior('harbormaster-log', function(config) {
if (data.live) { if (data.live) {
// If this was a live follow, scroll the new data into view. This is // If this was a live follow, scroll the new data into view. This is
// probably intensely annoying in practice but seems cool for now. // probably intensely annoying in practice but seems cool for now.
if (autoscroll) {
var last_row = rows[rows.length - 1]; var last_row = rows[rows.length - 1];
var tail_pos = JX.$V(last_row).y + JX.Vector.getDim(last_row).y; var tail_pos = JX.$V(last_row).y + JX.Vector.getDim(last_row).y;
var view_y = JX.Vector.getViewport().y; var view_y = JX.Vector.getViewport().y;
JX.DOM.scrollToPosition(null, (tail_pos - view_y) + 32); JX.DOM.scrollToPosition(null, (tail_pos - view_y) + 32);
setTimeout(follow, 500); // This will fire a scroll event, but we want to keep autoscroll
// enabled until we see an explicit scroll event by the user.
setTimeout(function() { autoscroll = true; }, 0);
}
setTimeout(follow, 2000);
for (var ii = 1; ii < (rows.length - 1); ii++) {
JX.DOM.alterClass(rows[ii], 'harbormaster-log-appear', true);
}
} }
}); });
request.send(); request.send();
} }
// If the user explicitly scrolls while following a log, keep live updating
// it but stop following it with the scrollbar.
JX.Stratcom.listen('scroll', null, function() {
autoscroll = false;
});
function follow() { function follow() {
if (!following) { if (!following) {
return; return;