Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(515)

Side by Side Diff: web/inc/logdog-stream-view/logdog-stream-view.html

Issue 2988993003: [logdog-view] Update UX, fix bugs. (Closed)
Patch Set: unfollow only on up scroll Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | web/inc/logdog-stream-view/model.ts » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <!-- 1 <!--
2 Copyright 2016 The LUCI Authors. All rights reserved. 2 Copyright 2016 The LUCI Authors. All rights reserved.
3 Use of this source code is governed under the Apache License, Version 2.0 3 Use of this source code is governed under the Apache License, Version 2.0
4 that can be found in the LICENSE file. 4 that can be found in the LICENSE file.
5 --> 5 -->
6 6
7 <link rel="import" href="../bower_components/polymer/polymer.html"> 7 <link rel="import" href="../bower_components/polymer/polymer.html">
8 <link rel="import" href="../bower_components/google-signin/google-signin-aware.h tml"> 8 <link rel="import" href="../bower_components/google-signin/google-signin-aware.h tml">
9 <link rel="import" href="../bower_components/iron-icons/iron-icons.html"> 9 <link rel="import" href="../bower_components/iron-icons/iron-icons.html">
10 <link rel="import" href="../bower_components/iron-icons/av-icons.html"> 10 <link rel="import" href="../bower_components/iron-icons/av-icons.html">
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 This must be after "rpc-client" so we get the signin event after it 172 This must be after "rpc-client" so we get the signin event after it
173 does. 173 does.
174 --> 174 -->
175 <google-signin-aware 175 <google-signin-aware
176 id="aware" 176 id="aware"
177 on-google-signin-aware-success="_onSignin"></google-signin-aware> 177 on-google-signin-aware-success="_onSignin"></google-signin-aware>
178 178
179 <!-- Stream view options. --> 179 <!-- Stream view options. -->
180 <div id="mainView"> 180 <div id="mainView">
181 <div id="buttons"> 181 <div id="buttons">
182 <!-- If we have exactly one stream, we will enable users to split. --> 182 <template is="dom-if" if="{{showPlayPause}}">
183 <template is="dom-if" if="{{showStreamingControls}}">
184 <paper-icon-button class="paper-icon-button-highlight" toggles
185 title="Stick to bottom." icon="icons:update"
186 active="{{follow}}">
187 </paper-icon-button>
188
189 <paper-icon-button class="paper-icon-button-highlight" toggles 183 <paper-icon-button class="paper-icon-button-highlight" toggles
190 title="Auto-Load" icon="{{playingIconName}}" 184 title="Auto-Load" icon="{{playingIconName}}"
191 active="{{playing}}"> 185 active="{{playing}}">
192 </paper-icon-button> 186 </paper-icon-button>
187 </template>
193 188
194 <template is="dom-if" if="{{canSplit}}"> 189 <template is="dom-if" if="{{showSplitButton}}">
195 <paper-icon-button 190 <paper-icon-button
196 title="Jump to latest." 191 title="Jump to latest."
197 icon="editor:vertical-align-bottom" 192 icon="editor:vertical-align-bottom"
198 on-tap="_splitClicked"> 193 on-tap="_splitClicked">
194 </paper-icon-button>
195 </template>
196
197 <template is="dom-if" if="{{showStreamControls}}">
198 <template is="dom-if" if="{{showSplitControls}}">
199 <paper-icon-button toggles
200 title="Load new logs, or backfill from top."
201 icon="{{backfillIconName}}"
202 active="{{backfill}}">
199 </paper-icon-button> 203 </paper-icon-button>
200 </template>
201 204
202 <template is="dom-if" if="{{isSplit}}">
203 <paper-icon-button title="Scroll to split" 205 <paper-icon-button title="Scroll to split"
204 icon="editor:vertical-align-center" on-tap="_scrollToSplit"> 206 icon="editor:vertical-align-center" on-tap="_scrollToSplit">
205 </paper-icon-button> 207 </paper-icon-button>
206 </template> 208 </template>
207 209
208 <template is="dom-if" if="{{isSplit}}">
209 <paper-icon-button toggles
210 title="Load new logs, or backfill from top."
211 icon="{{backfillIconName}}"
212 active="{{backfill}}">
213 </paper-icon-button>
214 </template>
215 </template>
216
217 <template is="dom-if" if="{{_not(playing)}}">
218 <paper-button class="paper-button-highlight" toggles raised 210 <paper-button class="paper-button-highlight" toggles raised
219 active="{{wrapLines}}"> 211 active="{{wrapLines}}">
220 Wrap 212 Wrap
221 </paper-button> 213 </paper-button>
222 214
223 <template is="dom-if" if="{{metadata}}"> 215 <template is="dom-if" if="{{metadata}}">
224 <paper-button class="paper-button-highlight" toggles raised 216 <paper-button class="paper-button-highlight" toggles raised
225 active="{{showMetadata}}"> 217 active="{{showMetadata}}">
226 Metadata 218 Metadata
227 </paper-button> 219 </paper-button>
228 </template> 220 </template>
229 </template> 221 </template>
230 </div> 222 </div>
231 223
232 <!-- Display current fetching status, if stream data is still loading. --> 224 <!-- Display current fetching status, if stream data is still loading. -->
233 <div id="streamStatus"> 225 <div id="streamStatus">
234 <template is="dom-if" if="{{streamStatus}}"> 226 <template is="dom-if" if="{{streamStatus}}">
235 <table> 227 <table>
236 <template is="dom-repeat" items="{{streamStatus}}"> 228 <template is="dom-repeat" items="{{streamStatus}}">
237 <tr> 229 <tr>
238 <td>{{item.name}}</td> 230 <td>{{item.name}}</td>
239 <td>{{item.desc}}</td> 231 <td>{{item.desc}}</td>
240 </tr> 232 </tr>
241 </template> 233 </template>
242 </table> 234 </table>
243 </template> 235 </template>
244 </div> 236 </div>
245 237
246 <!-- Muxed log content. --> 238 <!-- Muxed log content. -->
247 <div id="logContent" 239 <div id="logContent">
248 on-mousewheel="_handleMouseWheel">
249 <div id="logs"> 240 <div id="logs">
250 <!-- Content will be populated with JavaScript as logs are loaded. 241 <!-- Content will be populated with JavaScript as logs are loaded.
251 242
252 <div class="log-entry"> 243 <div class="log-entry">
253 <div class="log-entry-meta"> 244 <div class="log-entry-meta">
254 <div class="log-entry-meta-line">(Meta 0)</div> 245 <div class="log-entry-meta-line">(Meta 0)</div>
255 ... 246 ...
256 <div class="log-entry-meta-line">(Meta N)</div> 247 <div class="log-entry-meta-line">(Meta N)</div>
257 </div> 248 </div>
258 <div class="log-entry-content"> 249 <div class="log-entry-content">
259 LINE #0 250 LINE #0
260 ... 251 ...
261 LINE #N 252 LINE #N
262 </div> 253 </div>
263 </div> 254 </div>
264 ... 255 ...
265 256
266 257
267 Note that we can't use templating to show/hide the log dividers, 258 Note that we can't use templating to show/hide the log dividers,
268 since our positional log insertion requires them to be present and 259 since our positional log insertion requires them to be present and
269 move along with insertions as points of reference. 260 move along with insertions as points of reference.
270 --> 261 -->
271 262
272 <div id="logSplit" class="logFetchButtonContainer"> 263 <div id="logSplit" class="logFetchButtonContainer">
273 <!-- Insert point (prepend for head, append for tail). --> 264 <!-- Insert point (prepend for head, append for tail). -->
274 <paper-button id="logSplitUp" 265 <paper-button id="logSplitUp"
275 class="logFetchButton logSplitUpButton giant" 266 class="logFetchButton logSplitUpButton giant"
276 text="Load Above" 267 text="Load Above"
277 disabled="[[streamAnchorsNotClickable]]" 268 disabled="[[playing]]"
278 on-click="_handleUpClick"> 269 on-click="_handleUpClick">
279 <iron-icon icon="file-upload"></iron-icon> 270 <iron-icon icon="file-upload"></iron-icon>
280 </paper-button> 271 </paper-button>
281 <paper-button id="logSplitDown" 272 <paper-button id="logSplitDown"
282 class="logFetchButton logSplitDownButton giant" 273 class="logFetchButton logSplitDownButton giant"
283 text="Load Below" 274 text="Load Below"
284 disabled="[[streamAnchorsNotClickable]]" 275 disabled="[[playing]]"
285 on-click="_handleDownClick"> 276 on-click="_handleDownClick">
286 <iron-icon icon="file-download"></iron-icon> 277 <iron-icon icon="file-download"></iron-icon>
287 </paper-button> 278 </paper-button>
288 </div> 279 </div>
289 280
290 <div id="logBottom" class="logFetchButtonContainer"> 281 <div id="logBottom" class="logFetchButtonContainer">
291 <!-- 282 <!--
292 Bottom of the log stream (red bottom line). When tail is complete, 283 Bottom of the log stream (red bottom line). When tail is complete,
293 all future logs get prepended to this. 284 all future logs get prepended to this.
294 --> 285 -->
295 <paper-button id="logBottomButton" 286 <paper-button id="logBottomButton"
296 class="logFetchButton logBottomButton giant" 287 class="logFetchButton logBottomButton giant"
297 disabled="[[streamAnchorsNotClickable]]" 288 disabled="[[playing]]"
298 on-click="_handleBottomClick"> 289 on-click="_handleBottomClick">
299 <iron-icon icon="arrow-drop-down"></iron-icon> 290 <iron-icon icon="arrow-drop-down"></iron-icon>
300 </paper-button> 291 </paper-button>
301 </div> 292 </div>
302 <div id="logEnd"></div> 293 <div id="logEnd"></div>
303 </div> 294 </div>
304 </div> 295 </div>
305 296
306 </div> 297 </div>
307 298
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 * The smaller the value, the smoother the page will behave while logs are 347 * The smaller the value, the smoother the page will behave while logs are
357 * loading. However, the logs will also load slower because of forced 348 * loading. However, the logs will also load slower because of forced
358 * renders in between elements. 349 * renders in between elements.
359 */ 350 */
360 burst: { 351 burst: {
361 type: Number, 352 type: Number,
362 value: 1000, 353 value: 1000,
363 notify: true, 354 notify: true,
364 }, 355 },
365 356
357 /** If populated, the stream name at the top will link to this URL. */
358 streamLinkUrl: {
359 type: String,
360 value: null,
361 notify: true,
362 },
363
366 /** 364 /**
367 * If true, render metadata blocks alongside their log entries. 365 * If true, render metadata blocks alongside their log entries.
368 * 366 *
369 * This will cause significantly more HTML elements during rendering (so 367 * This will cause significantly more HTML elements during rendering (so
370 * that each metadata element can show up next to its row) and greatly 368 * that each metadata element can show up next to its row) and greatly
371 * slow the viewer down. 369 * slow the viewer down.
372 */ 370 */
373 metadata: { 371 metadata: {
374 type: Boolean, 372 type: Boolean,
375 value: false, 373 value: false,
376 }, 374 },
377 375
378 /** If true, show log metadata column. */ 376 /** If true, show log metadata column. */
379 showMetadata: { 377 showMetadata: {
380 type: Boolean, 378 type: Boolean,
381 value: false, 379 value: false,
382 observer: "_showMetadataChanged", 380 observer: "_showMetadataChanged",
383 }, 381 },
384 382
385 /** If true, wrap log lines to the screen. */ 383 /** If true, wrap log lines to the screen. */
386 wrapLines: { 384 wrapLines: {
387 type: Boolean, 385 type: Boolean,
388 value: false, 386 value: false,
389 observer: "_wrapLinesChanged", 387 observer: "_wrapLinesChanged",
390 }, 388 },
391 389
392 /** 390 /** Whether or not to show play/pause button. */
393 * If true, automatically scroll the page to the bottom of the logs 391 showPlayPause: {
394 * while they are streaming. 392 type: Boolean,
395 */ 393 value: true,
396 follow: { 394 readOnly: true,
395 },
396
397 /** Whether or not to show stream control buttons. */
398 showStreamControls: {
397 type: Boolean, 399 type: Boolean,
398 value: false, 400 value: false,
399 observer: "_followChanged", 401 readOnly: true,
400 }, 402 },
401 403
402 /** 404 /** Whether or not to show the "split streams" button. */
403 * True if the stream is capable of being split. 405 showSplitButton: {
404 * 406 type: Boolean,
405 * This is set by the viewer via "_updateControls". 407 value: false,
406 * 408 readOnly: true,
407 * A split is a visual break in the log continuity, where content above 409 },
408 * the split contains logs starting at the beginning of the stream, while 410
409 * content below the split contains data from the last log entry in the 411 /** Whether or not to show the split controls. */
410 * stream at the time of the split. 412 showSplitControls: {
411 */
412 canSplit: {
413 type: Boolean, 413 type: Boolean,
414 value: false, 414 value: false,
415 readOnly: true, 415 readOnly: true,
416 }, 416 },
417 417
418 /** 418 /**
419 * True if log streaming controls should be visible.
420 *
421 * This is set by the viewer via "_updateControls".
422 */
423 showStreamingControls: {
424 type: Boolean,
425 value: true,
426 readOnly: true,
427 },
428
429 /**
430 * True if the view is currently split.
431 *
432 * This is set by the viewer via "_updateControls".
433 */
434 isSplit: {
435 type: Boolean,
436 value: false,
437 readOnly: true,
438 },
439
440 /**
441 * True if the stream anchors (split bar buttons) can be clicked.
442 */
443 streamAnchorsNotClickable: {
444 type: Boolean,
445 computed:
446 '_computeAnchorsNotClickable(playing, showStreamingControls)',
447 },
448
449 /**
450 * True if the viewer should automatically load more logs after the 419 * True if the viewer should automatically load more logs after the
451 * previous batch has finished. 420 * previous batch has finished.
452 */ 421 */
453 playing: { 422 playing: {
454 type: Boolean, 423 type: Boolean,
455 value: false, 424 value: false,
456 observer: "_playingChanged", 425 observer: "_playingChanged",
457 }, 426 },
458 427
459 /** 428 /**
(...skipping 16 matching lines...) Expand all
476 }, 445 },
477 446
478 /** 447 /**
479 * (Computed) the iron-icon name of the backfill button icon. 448 * (Computed) the iron-icon name of the backfill button icon.
480 */ 449 */
481 backfillIconName: { 450 backfillIconName: {
482 type: String, 451 type: String,
483 computed: '_computeBackfillIconName(backfill)', 452 computed: '_computeBackfillIconName(backfill)',
484 }, 453 },
485 454
486 /** If populated, the stream name at the top will link to this URL. */
487 streamLinkUrl: {
488 type: String,
489 value: null,
490 notify: true,
491 },
492
493 /** 455 /**
494 * The current stream status. This is an Array of objects: 456 * The current stream status. This is an Array of objects:
495 * obj.name is the name of the stream. 457 * obj.name is the name of the stream.
496 * obj.desc is the status description of the stream. 458 * obj.desc is the status description of the stream.
497 */ 459 */
498 streamStatus: { 460 streamStatus: {
499 type: Array, 461 type: Array,
500 value: null, 462 value: null,
501 notify: true, 463 notify: true,
502 readOnly: true, 464 readOnly: true,
503 }, 465 },
504 466
505 /** 467 /**
506 * The text content of the status element at the bottom of the page. 468 * The text content of the status element at the bottom of the page.
507 */ 469 */
508 statusBar: { 470 statusBar: {
509 type: String, 471 type: String,
510 value: null, 472 value: null,
511 readOnly: true, 473 readOnly: true,
512 }, 474 },
513 }, 475 },
514 476
515 created: function() { 477 created: function() {
516 this._view = new LogDog.View(this); 478 this._view = new LogDog.View(this);
517 }, 479 },
518 480
519 attached: function() { 481 attached: function() {
520 this._view.reset(); 482 this._view.reset();
483 this.$.logContent.addEventListener('wheel',
484 this._handleMouseWheel.bind(this));
521 }, 485 },
522 486
523 detached: function() { 487 detached: function() {
524 this._view.detach(); 488 this._view.detach();
489 this.$.logContent.removeEventListener('wheel',
490 this._handleMouseWheel.bind(this));
525 }, 491 },
526 492
527 stop: function() { 493 stop: function() {
528 this._view.stop(); 494 this._view.stop();
529 }, 495 },
530 496
531 _polymerAppendChild: function(e) { 497 _polymerAppendChild: function(e) {
532 Polymer.dom(this.root).appendChild(e); 498 Polymer.dom(this.root).appendChild(e);
533 }, 499 },
534 500
535 _handleMouseWheel: function(e) { 501 _handleMouseWheel: function(e) {
536 this._view.handleMouseWheel(); 502 this._view.handleMouseWheel(e.deltaY >= 0);
537 }, 503 },
538 504
539 _handleDownClick: function(e) { 505 _handleDownClick: function(e) {
540 this._view.handleDownClick(); 506 this._view.handleDownClick();
541 }, 507 },
542 508
543 _handleUpClick: function(e) { 509 _handleUpClick: function(e) {
544 this._view.handleUpClick(); 510 this._view.handleUpClick();
545 }, 511 },
546 512
(...skipping 15 matching lines...) Expand all
562 }, 528 },
563 529
564 /** 530 /**
565 * Callback when "wrapLines" has changed. This adds/removes the 531 * Callback when "wrapLines" has changed. This adds/removes the
566 * "wrapLines" CSS class to the log data. 532 * "wrapLines" CSS class to the log data.
567 */ 533 */
568 _wrapLinesChanged: function(v) { 534 _wrapLinesChanged: function(v) {
569 this.toggleClass("wrapLines", v, this.$.logs); 535 this.toggleClass("wrapLines", v, this.$.logs);
570 }, 536 },
571 537
572 /** Callback when "follow" has changed. */ 538 /** Callback when "playing" has changed. */
573 _playingChanged: function(v) { 539 _playingChanged: function(v) {
574 this._view.handlePlayingChanged(v); 540 this._view.handlePlayPauseChanged(v);
575 }, 541 },
576 542
577 _computePlayingIconName: function(playing) { 543 _computePlayingIconName: function(playing) {
578 return ( (playing) ? 544 return ( (playing) ?
579 "av:pause-circle-outline" : "av:play-circle-outline" ); 545 "av:pause-circle-outline" : "av:play-circle-outline" );
580 }, 546 },
581 547
582 /** Callback when "follow" has changed. */ 548 /** Callback when "backfill" has changed. */
583 _backfillChanged: function(v) { 549 _backfillChanged: function(v) {
584 this._view.handleBackfillChanged(v); 550 this._view.handleBackfillChanged(v);
585 }, 551 },
586 552
587 _computeBackfillIconName: function(backfill) { 553 _computeBackfillIconName: function(backfill) {
588 return ( (backfill) ? 554 return ( (backfill) ?
589 "editor:border-bottom" : "editor:border-top" ); 555 "editor:border-bottom" : "editor:border-top" );
590 }, 556 },
591 557
592 /** Callback when "follow" has changed. */
593 _followChanged: function(v) {
594 this._view.handleFollowChanged(v);
595 },
596
597 /** Callback when "split" button has been clicked. */ 558 /** Callback when "split" button has been clicked. */
598 _splitClicked: function() { 559 _splitClicked: function() {
599 this._view.handleSplitClicked(); 560 this._view.handleSplitClicked();
600 }, 561 },
601 562
602 /** Callback when "split" button has been clicked. */ 563 /** Callback when "split" button has been clicked. */
603 _scrollToSplit: function() { 564 _scrollToSplit: function() {
604 this._view.handleScrollToSplitClicked(); 565 this._view.handleScrollToSplitClicked();
605 }, 566 },
606 567
607 _updateSplitVisible: function(v) { 568 _updateSplitVisible: function(v) {
608 this.toggleClass("logFetchButtonVisible", v, this.$.logSplit); 569 this.toggleClass("logFetchButtonVisible", v, this.$.logSplit);
609 },
610
611 _updateBottomVisible: function(v) {
612 this.toggleClass("logFetchButtonVisible", v, this.$.logBottom); 570 this.toggleClass("logFetchButtonVisible", v, this.$.logBottom);
613 }, 571 },
614 572
615 _computeAnchorsNotClickable: function(playing, showStreamingControls,
616 rendering) {
617 // Anchors are not clickable if we're playing or the controls are
618 // not visible.
619 return ( playing || (!showStreamingControls) || rendering );
620 },
621
622 /** Filter function to invert a value. */
623 _not: function(v) {
624 return (!v);
625 },
626
627 _onSignin: function() { 573 _onSignin: function() {
628 this._view.handleSignin(); 574 this._view.handleSignin();
629 }, 575 },
630 }); 576 });
631 </script> 577 </script>
OLDNEW
« no previous file with comments | « no previous file | web/inc/logdog-stream-view/model.ts » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698