@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix some of the most egregious errors in Harbormaster log paging

Summary:
Depends on D19141. Ref T13088. Some of the fundamental log behaviors like "loading the correct rows" are now a bit better behaved.

The UI is a little less garbage, too.

Test Plan: Viewed some logs and loaded more context by clicking the buttons.

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13088

Differential Revision: https://secure.phabricator.com/D19142

+220 -58
+7 -7
resources/celerity/map.php
··· 78 78 'rsrc/css/application/feed/feed.css' => 'ecd4ec57', 79 79 'rsrc/css/application/files/global-drag-and-drop.css' => 'b556a948', 80 80 'rsrc/css/application/flag/flag.css' => 'bba8f811', 81 - 'rsrc/css/application/harbormaster/harbormaster.css' => 'fecac64f', 81 + 'rsrc/css/application/harbormaster/harbormaster.css' => 'c7e29d9e', 82 82 'rsrc/css/application/herald/herald-test.css' => 'a52e323e', 83 83 'rsrc/css/application/herald/herald.css' => 'cd8d0134', 84 84 'rsrc/css/application/maniphest/report.css' => '9b9580b7', ··· 416 416 'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef', 417 417 'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab', 418 418 'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888', 419 - 'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '0844f3c1', 419 + 'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => 'be6974cc', 420 420 'rsrc/js/application/herald/HeraldRuleEditor.js' => 'dca75c0e', 421 421 'rsrc/js/application/herald/PathTypeahead.js' => 'f7fc67ec', 422 422 'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3', ··· 579 579 'font-fontawesome' => 'e838e088', 580 580 'font-lato' => 'c7ccd872', 581 581 'global-drag-and-drop-css' => 'b556a948', 582 - 'harbormaster-css' => 'fecac64f', 582 + 'harbormaster-css' => 'c7e29d9e', 583 583 'herald-css' => 'cd8d0134', 584 584 'herald-rule-editor' => 'dca75c0e', 585 585 'herald-test-css' => 'a52e323e', ··· 636 636 'javelin-behavior-event-all-day' => 'b41537c9', 637 637 'javelin-behavior-fancy-datepicker' => 'ecf4e799', 638 638 'javelin-behavior-global-drag-and-drop' => '960f6a39', 639 - 'javelin-behavior-harbormaster-log' => '0844f3c1', 639 + 'javelin-behavior-harbormaster-log' => 'be6974cc', 640 640 'javelin-behavior-herald-rule-editor' => '7ebaeed3', 641 641 'javelin-behavior-high-security-warning' => 'a464fe03', 642 642 'javelin-behavior-history-install' => '7ee2b591', ··· 961 961 'javelin-dom', 962 962 'javelin-stratcom', 963 963 'javelin-workflow', 964 - ), 965 - '0844f3c1' => array( 966 - 'javelin-behavior', 967 964 ), 968 965 '08f4ccc3' => array( 969 966 'phui-oi-list-view-css', ··· 1891 1888 'javelin-dom', 1892 1889 'javelin-util', 1893 1890 'javelin-request', 1891 + ), 1892 + 'be6974cc' => array( 1893 + 'javelin-behavior', 1894 1894 ), 1895 1895 'bea6e7f4' => array( 1896 1896 'javelin-install',
+151 -45
src/applications/harbormaster/controller/HarbormasterBuildLogRenderController.php
··· 61 61 'offset' => $head_offset, 62 62 'lines' => $head_lines, 63 63 'direction' => 1, 64 + 'limit' => $tail_offset, 64 65 ); 65 66 } 66 67 ··· 69 70 'offset' => $tail_offset, 70 71 'lines' => $tail_lines, 71 72 'direction' => -1, 73 + 'limit' => $head_offset, 72 74 ); 73 75 } 74 76 ··· 128 130 foreach ($views as $view_key => $view) { 129 131 $anchor_byte = $view['offset']; 130 132 133 + if ($view['direction'] < 0) { 134 + $anchor_byte = $anchor_byte - 1; 135 + } 136 + 131 137 $data_key = null; 132 138 foreach ($reads as $read_key => $read) { 133 139 $s = $read['fetchOffset']; ··· 148 154 foreach ($reads[$data_key]['lines'] as $line_key => $line) { 149 155 $s = $line['offset']; 150 156 $e = $s + $line['length']; 151 - if (($s <= $anchor_byte) && ($e >= $anchor_byte)) { 157 + 158 + if (($s <= $anchor_byte) && ($e > $anchor_byte)) { 152 159 $anchor_key = $line_key; 153 160 break; 154 161 } ··· 161 168 } 162 169 163 170 if ($direction > 0) { 164 - $slice_offset = $line_key; 171 + $slice_offset = $anchor_key; 165 172 } else { 166 - $slice_offset = max(0, $line_key - ($view['lines'] - 1)); 173 + $slice_offset = max(0, $anchor_key - ($view['lines'] - 1)); 167 174 } 168 175 $slice_length = $view['lines']; 169 176 ··· 200 207 $trim = ($view_offset - $data_offset); 201 208 $view_length -= $trim; 202 209 } 210 + 211 + $limit = $view['limit']; 212 + if ($limit < ($view_offset + $view_length)) { 213 + $view_length = ($limit - $view_offset); 214 + } 203 215 } else { 204 216 $view_offset = $data_offset; 205 217 $view_length = $data_length; 206 218 if ($data_offset + $data_length > $view['offset']) { 207 219 $view_length -= (($data_offset + $data_length) - $view['offset']); 220 + } 221 + 222 + $limit = $view['limit']; 223 + if ($limit > $view_offset) { 224 + $view_length -= ($limit - $view_offset); 225 + $view_offset = $limit; 208 226 } 209 227 } 210 228 ··· 232 250 } 233 251 234 252 $trim = ($view_offset - $line_offset); 235 - $line_data = substr($line['data'], $trim); 236 - if (!strlen($line_data)) { 253 + if ($trim && ($trim >= strlen($line['data']))) { 237 254 unset($lines[$line_key]); 238 255 continue; 239 256 } 240 257 258 + $line_data = substr($line['data'], $trim); 241 259 $lines[$line_key]['data'] = $line_data; 242 260 $lines[$line_key]['length'] = strlen($line_data); 243 261 $lines[$line_key]['offset'] += $trim; ··· 248 266 foreach ($lines as $line_key => $line) { 249 267 $line_end = $line['offset'] + $line['length']; 250 268 if ($line_end <= $view_end) { 251 - break; 269 + continue; 252 270 } 253 271 254 272 $trim = ($line_end - $view_end); 255 - $line_data = substr($line['data'], -$trim); 256 - if (!strlen($line_data)) { 273 + if ($trim && ($trim >= strlen($line['data']))) { 257 274 unset($lines[$line_key]); 258 275 continue; 259 276 } 260 277 278 + $line_data = substr($line['data'], -$trim); 261 279 $lines[$line_key]['data'] = $line_data; 262 280 $lines[$line_key]['length'] = strlen($line_data); 263 281 } ··· 267 285 268 286 $spacer = null; 269 287 $render = array(); 288 + 289 + $head_view = head($views); 290 + if ($head_view['viewOffset'] > $head_offset) { 291 + $render[] = array( 292 + 'spacer' => true, 293 + 'head' => $head_offset, 294 + 'tail' => $head_view['viewOffset'], 295 + ); 296 + } 297 + 298 + 270 299 foreach ($views as $view) { 271 300 if ($spacer) { 272 301 $spacer['tail'] = $view['viewOffset']; ··· 281 310 ); 282 311 } 283 312 313 + $tail_view = last($views); 314 + if ($tail_view['viewOffset'] + $tail_view['viewLength'] < $tail_offset) { 315 + $render[] = array( 316 + 'spacer' => true, 317 + 'head' => $tail_view['viewOffset'] + $tail_view['viewLength'], 318 + 'tail' => $tail_offset, 319 + ); 320 + } 321 + 284 322 $uri = $log->getURI(); 285 323 $highlight_range = $request->getURIData('lines'); 286 324 287 325 $rows = array(); 288 326 foreach ($render as $range) { 289 327 if (isset($range['spacer'])) { 290 - $rows[] = phutil_tag( 291 - 'tr', 292 - array(), 293 - array( 294 - phutil_tag( 295 - 'th', 296 - array(), 297 - null), 298 - phutil_tag( 299 - 'td', 300 - array(), 301 - array( 302 - javelin_tag( 303 - 'a', 304 - array( 305 - 'sigil' => 'harbormaster-log-expand', 306 - 'meta' => array( 307 - 'headOffset' => $range['head'], 308 - 'tailOffset' => $range['tail'], 309 - 'head' => 4, 310 - ), 311 - ), 312 - 'Show Up ^^^^'), 313 - '... '.($range['tail'] - $range['head']).' bytes ...', 314 - javelin_tag( 315 - 'a', 316 - array( 317 - 'sigil' => 'harbormaster-log-expand', 318 - 'meta' => array( 319 - 'headOffset' => $range['head'], 320 - 'tailOffset' => $range['tail'], 321 - 'tail' => 4, 322 - ), 323 - ), 324 - 'Show Down VVVV'), 325 - )), 326 - )); 328 + $rows[] = $this->renderExpandRow($range); 327 329 continue; 328 330 } 329 331 ··· 557 559 } 558 560 559 561 return $views; 562 + } 563 + 564 + private function renderExpandRow($range) { 565 + 566 + $icon_up = id(new PHUIIconView()) 567 + ->setIcon('fa-chevron-up'); 568 + 569 + $icon_down = id(new PHUIIconView()) 570 + ->setIcon('fa-chevron-down'); 571 + 572 + $up_text = array( 573 + pht('Show More Above'), 574 + ' ', 575 + $icon_up, 576 + ); 577 + 578 + $expand_up = javelin_tag( 579 + 'a', 580 + array( 581 + 'sigil' => 'harbormaster-log-expand', 582 + 'meta' => array( 583 + 'headOffset' => $range['head'], 584 + 'tailOffset' => $range['tail'], 585 + 'head' => 4, 586 + 'tail' => 0, 587 + ), 588 + ), 589 + $up_text); 590 + 591 + $mid_text = pht( 592 + 'Show More (%s bytes Hidden)', 593 + new PhutilNumber($range['tail'] - $range['head'])); 594 + 595 + $expand_mid = javelin_tag( 596 + 'a', 597 + array( 598 + 'sigil' => 'harbormaster-log-expand', 599 + 'meta' => array( 600 + 'headOffset' => $range['head'], 601 + 'tailOffset' => $range['tail'], 602 + 'head' => 2, 603 + 'tail' => 2, 604 + ), 605 + ), 606 + $mid_text); 607 + 608 + $down_text = array( 609 + $icon_down, 610 + ' ', 611 + pht('Show More Below'), 612 + ); 613 + 614 + $expand_down = javelin_tag( 615 + 'a', 616 + array( 617 + 'sigil' => 'harbormaster-log-expand', 618 + 'meta' => array( 619 + 'headOffset' => $range['head'], 620 + 'tailOffset' => $range['tail'], 621 + 'head' => 0, 622 + 'tail' => 4, 623 + ), 624 + ), 625 + $down_text); 626 + 627 + $expand_cells = array( 628 + phutil_tag( 629 + 'td', 630 + array( 631 + 'class' => 'harbormaster-log-expand-up', 632 + ), 633 + $expand_up), 634 + phutil_tag( 635 + 'td', 636 + array( 637 + 'class' => 'harbormaster-log-expand-mid', 638 + ), 639 + $expand_mid), 640 + phutil_tag( 641 + 'td', 642 + array( 643 + 'class' => 'harbormaster-log-expand-down', 644 + ), 645 + $expand_down), 646 + ); 647 + $expand_row = phutil_tag('tr', array(), $expand_cells); 648 + $expand_table = phutil_tag( 649 + 'table', 650 + array( 651 + 'class' => 'harbormaster-log-expand-table', 652 + ), 653 + $expand_row); 654 + 655 + $cells = array( 656 + phutil_tag('th', array()), 657 + phutil_tag( 658 + 'td', 659 + array( 660 + 'class' => 'harbormaster-log-expand-cell', 661 + ), 662 + $expand_table), 663 + ); 664 + 665 + return phutil_tag('tr', array(), $cells); 560 666 } 561 667 562 668 }
+59 -5
webroot/rsrc/css/application/harbormaster/harbormaster.css
··· 37 37 color: {$lightgreytext}; 38 38 } 39 39 40 - .harbormaster-log-table th { 40 + .harbormaster-log-table > tbody > tr > th { 41 41 background-color: {$paste.highlight}; 42 42 border-right: 1px solid {$paste.border}; 43 43 ··· 48 48 user-select: none; 49 49 } 50 50 51 - .harbormaster-log-table th a { 51 + .harbormaster-log-table > tbody > tr > th a { 52 52 display: block; 53 53 color: {$darkbluetext}; 54 54 text-align: right; 55 55 padding: 2px 6px 1px 12px; 56 56 } 57 57 58 - .harbormaster-log-table th a:hover { 58 + .harbormaster-log-table > tbody > tr > th a:hover { 59 59 background: {$paste.border}; 60 60 } 61 61 62 - .harbormaster-log-table td { 62 + .harbormaster-log-table > tbody > tr > td { 63 63 white-space: pre-wrap; 64 64 padding: 2px 8px 1px; 65 65 width: 100%; 66 66 } 67 67 68 - .harbormaster-log-table tr.harbormaster-log-highlighted td { 68 + .harbormaster-log-table > tbody > tr > td.harbormaster-log-expand-cell { 69 + padding: 4px 0; 70 + } 71 + 72 + .harbormaster-log-table tr.harbormaster-log-highlighted > td { 69 73 background: {$paste.highlight}; 70 74 } 75 + 76 + .harbormaster-log-expand-table { 77 + width: 100%; 78 + background: {$paste.highlight}; 79 + border-top: 1px solid {$paste.border}; 80 + border-bottom: 1px solid {$paste.border}; 81 + } 82 + 83 + .harbormaster-log-expand-table a { 84 + display: block; 85 + padding: 6px 16px; 86 + color: {$darkbluetext}; 87 + } 88 + 89 + .device-desktop .harbormaster-log-expand-table a:hover { 90 + background: {$paste.border}; 91 + text-decoration: none; 92 + } 93 + 94 + .harbormaster-log-expand-table td { 95 + vertical-align: middle; 96 + font: 13px 'Segoe UI', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Lato', 97 + 'Helvetica Neue', Helvetica, Arial, sans-serif; 98 + } 99 + 100 + 101 + .harbormaster-log-expand-up { 102 + text-align: right; 103 + width: 50%; 104 + } 105 + 106 + .harbormaster-log-expand-up .phui-icon-view { 107 + margin: 0 0 0px 4px; 108 + } 109 + 110 + .harbormaster-log-expand-mid { 111 + text-align: center; 112 + white-space: nowrap; 113 + border-left: 1px solid {$paste.border}; 114 + border-right: 1px solid {$paste.border}; 115 + } 116 + 117 + .harbormaster-log-expand-down { 118 + text-align: left; 119 + width: 50%; 120 + } 121 + 122 + .harbormaster-log-expand-down .phui-icon-view { 123 + margin: 0 4px 0 0; 124 + }
+3 -1
webroot/rsrc/js/application/harbormaster/behavior-harbormaster-log.js
··· 14 14 e.kill(); 15 15 16 16 var row = e.getNode('tag:tr'); 17 + row = JX.DOM.findAbove(row, 'tr'); 18 + 17 19 var data = e.getNodeData('harbormaster-log-expand'); 18 20 19 21 var uri = new JX.URI(config.renderURI) ··· 21 23 22 24 var request = new JX.Request(uri, function(r) { 23 25 var result = JX.$H(r.markup).getNode(); 24 - var rows = JX.DOM.scry(result, 'tr'); 26 + var rows = [].slice.apply(result.firstChild.childNodes); 25 27 26 28 JX.DOM.replace(row, rows); 27 29 });