| OLD | NEW |
| 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 Loading... |
| 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> |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 Note that we can't use templating to show/hide the log dividers, | 259 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 | 260 since our positional log insertion requires them to be present and |
| 269 move along with insertions as points of reference. | 261 move along with insertions as points of reference. |
| 270 --> | 262 --> |
| 271 | 263 |
| 272 <div id="logSplit" class="logFetchButtonContainer"> | 264 <div id="logSplit" class="logFetchButtonContainer"> |
| 273 <!-- Insert point (prepend for head, append for tail). --> | 265 <!-- Insert point (prepend for head, append for tail). --> |
| 274 <paper-button id="logSplitUp" | 266 <paper-button id="logSplitUp" |
| 275 class="logFetchButton logSplitUpButton giant" | 267 class="logFetchButton logSplitUpButton giant" |
| 276 text="Load Above" | 268 text="Load Above" |
| 277 disabled="[[streamAnchorsNotClickable]]" | 269 disabled="[[playing]]" |
| 278 on-click="_handleUpClick"> | 270 on-click="_handleUpClick"> |
| 279 <iron-icon icon="file-upload"></iron-icon> | 271 <iron-icon icon="file-upload"></iron-icon> |
| 280 </paper-button> | 272 </paper-button> |
| 281 <paper-button id="logSplitDown" | 273 <paper-button id="logSplitDown" |
| 282 class="logFetchButton logSplitDownButton giant" | 274 class="logFetchButton logSplitDownButton giant" |
| 283 text="Load Below" | 275 text="Load Below" |
| 284 disabled="[[streamAnchorsNotClickable]]" | 276 disabled="[[playing]]" |
| 285 on-click="_handleDownClick"> | 277 on-click="_handleDownClick"> |
| 286 <iron-icon icon="file-download"></iron-icon> | 278 <iron-icon icon="file-download"></iron-icon> |
| 287 </paper-button> | 279 </paper-button> |
| 288 </div> | 280 </div> |
| 289 | 281 |
| 290 <div id="logBottom" class="logFetchButtonContainer"> | 282 <div id="logBottom" class="logFetchButtonContainer"> |
| 291 <!-- | 283 <!-- |
| 292 Bottom of the log stream (red bottom line). When tail is complete, | 284 Bottom of the log stream (red bottom line). When tail is complete, |
| 293 all future logs get prepended to this. | 285 all future logs get prepended to this. |
| 294 --> | 286 --> |
| 295 <paper-button id="logBottomButton" | 287 <paper-button id="logBottomButton" |
| 296 class="logFetchButton logBottomButton giant" | 288 class="logFetchButton logBottomButton giant" |
| 297 disabled="[[streamAnchorsNotClickable]]" | 289 disabled="[[playing]]" |
| 298 on-click="_handleBottomClick"> | 290 on-click="_handleBottomClick"> |
| 299 <iron-icon icon="arrow-drop-down"></iron-icon> | 291 <iron-icon icon="arrow-drop-down"></iron-icon> |
| 300 </paper-button> | 292 </paper-button> |
| 301 </div> | 293 </div> |
| 302 <div id="logEnd"></div> | 294 <div id="logEnd"></div> |
| 303 </div> | 295 </div> |
| 304 </div> | 296 </div> |
| 305 | 297 |
| 306 </div> | 298 </div> |
| 307 | 299 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 * The smaller the value, the smoother the page will behave while logs are | 348 * 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 | 349 * loading. However, the logs will also load slower because of forced |
| 358 * renders in between elements. | 350 * renders in between elements. |
| 359 */ | 351 */ |
| 360 burst: { | 352 burst: { |
| 361 type: Number, | 353 type: Number, |
| 362 value: 1000, | 354 value: 1000, |
| 363 notify: true, | 355 notify: true, |
| 364 }, | 356 }, |
| 365 | 357 |
| 358 /** If populated, the stream name at the top will link to this URL. */ |
| 359 streamLinkUrl: { |
| 360 type: String, |
| 361 value: null, |
| 362 notify: true, |
| 363 }, |
| 364 |
| 366 /** | 365 /** |
| 367 * If true, render metadata blocks alongside their log entries. | 366 * If true, render metadata blocks alongside their log entries. |
| 368 * | 367 * |
| 369 * This will cause significantly more HTML elements during rendering (so | 368 * This will cause significantly more HTML elements during rendering (so |
| 370 * that each metadata element can show up next to its row) and greatly | 369 * that each metadata element can show up next to its row) and greatly |
| 371 * slow the viewer down. | 370 * slow the viewer down. |
| 372 */ | 371 */ |
| 373 metadata: { | 372 metadata: { |
| 374 type: Boolean, | 373 type: Boolean, |
| 375 value: false, | 374 value: false, |
| 376 }, | 375 }, |
| 377 | 376 |
| 378 /** If true, show log metadata column. */ | 377 /** If true, show log metadata column. */ |
| 379 showMetadata: { | 378 showMetadata: { |
| 380 type: Boolean, | 379 type: Boolean, |
| 381 value: false, | 380 value: false, |
| 382 observer: "_showMetadataChanged", | 381 observer: "_showMetadataChanged", |
| 383 }, | 382 }, |
| 384 | 383 |
| 385 /** If true, wrap log lines to the screen. */ | 384 /** If true, wrap log lines to the screen. */ |
| 386 wrapLines: { | 385 wrapLines: { |
| 387 type: Boolean, | 386 type: Boolean, |
| 388 value: false, | 387 value: false, |
| 389 observer: "_wrapLinesChanged", | 388 observer: "_wrapLinesChanged", |
| 390 }, | 389 }, |
| 391 | 390 |
| 392 /** | 391 /** Whether or not to show play/pause button. */ |
| 393 * If true, automatically scroll the page to the bottom of the logs | 392 showPlayPause: { |
| 394 * while they are streaming. | 393 type: Boolean, |
| 395 */ | 394 value: true, |
| 396 follow: { | 395 readOnly: true, |
| 396 }, |
| 397 |
| 398 /** Whether or not to show stream control buttons. */ |
| 399 showStreamControls: { |
| 397 type: Boolean, | 400 type: Boolean, |
| 398 value: false, | 401 value: false, |
| 399 observer: "_followChanged", | 402 readOnly: true, |
| 400 }, | 403 }, |
| 401 | 404 |
| 402 /** | 405 /** Whether or not to show the "split streams" button. */ |
| 403 * True if the stream is capable of being split. | 406 showSplitButton: { |
| 404 * | 407 type: Boolean, |
| 405 * This is set by the viewer via "_updateControls". | 408 value: false, |
| 406 * | 409 readOnly: true, |
| 407 * A split is a visual break in the log continuity, where content above | 410 }, |
| 408 * the split contains logs starting at the beginning of the stream, while | 411 |
| 409 * content below the split contains data from the last log entry in the | 412 /** Whether or not to show the split controls. */ |
| 410 * stream at the time of the split. | 413 showSplitControls: { |
| 411 */ | |
| 412 canSplit: { | |
| 413 type: Boolean, | 414 type: Boolean, |
| 414 value: false, | 415 value: false, |
| 415 readOnly: true, | 416 readOnly: true, |
| 416 }, | 417 }, |
| 417 | 418 |
| 418 /** | 419 /** |
| 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 | 420 * True if the viewer should automatically load more logs after the |
| 451 * previous batch has finished. | 421 * previous batch has finished. |
| 452 */ | 422 */ |
| 453 playing: { | 423 playing: { |
| 454 type: Boolean, | 424 type: Boolean, |
| 455 value: false, | 425 value: false, |
| 456 observer: "_playingChanged", | 426 observer: "_playingChanged", |
| 457 }, | 427 }, |
| 458 | 428 |
| 459 /** | 429 /** |
| (...skipping 16 matching lines...) Expand all Loading... |
| 476 }, | 446 }, |
| 477 | 447 |
| 478 /** | 448 /** |
| 479 * (Computed) the iron-icon name of the backfill button icon. | 449 * (Computed) the iron-icon name of the backfill button icon. |
| 480 */ | 450 */ |
| 481 backfillIconName: { | 451 backfillIconName: { |
| 482 type: String, | 452 type: String, |
| 483 computed: '_computeBackfillIconName(backfill)', | 453 computed: '_computeBackfillIconName(backfill)', |
| 484 }, | 454 }, |
| 485 | 455 |
| 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 /** | 456 /** |
| 494 * The current stream status. This is an Array of objects: | 457 * The current stream status. This is an Array of objects: |
| 495 * obj.name is the name of the stream. | 458 * obj.name is the name of the stream. |
| 496 * obj.desc is the status description of the stream. | 459 * obj.desc is the status description of the stream. |
| 497 */ | 460 */ |
| 498 streamStatus: { | 461 streamStatus: { |
| 499 type: Array, | 462 type: Array, |
| 500 value: null, | 463 value: null, |
| 501 notify: true, | 464 notify: true, |
| 502 readOnly: true, | 465 readOnly: true, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 }, | 525 }, |
| 563 | 526 |
| 564 /** | 527 /** |
| 565 * Callback when "wrapLines" has changed. This adds/removes the | 528 * Callback when "wrapLines" has changed. This adds/removes the |
| 566 * "wrapLines" CSS class to the log data. | 529 * "wrapLines" CSS class to the log data. |
| 567 */ | 530 */ |
| 568 _wrapLinesChanged: function(v) { | 531 _wrapLinesChanged: function(v) { |
| 569 this.toggleClass("wrapLines", v, this.$.logs); | 532 this.toggleClass("wrapLines", v, this.$.logs); |
| 570 }, | 533 }, |
| 571 | 534 |
| 572 /** Callback when "follow" has changed. */ | 535 /** Callback when "playing" has changed. */ |
| 573 _playingChanged: function(v) { | 536 _playingChanged: function(v) { |
| 574 this._view.handlePlayingChanged(v); | 537 this._view.handlePlayPauseChanged(v); |
| 575 }, | 538 }, |
| 576 | 539 |
| 577 _computePlayingIconName: function(playing) { | 540 _computePlayingIconName: function(playing) { |
| 578 return ( (playing) ? | 541 return ( (playing) ? |
| 579 "av:pause-circle-outline" : "av:play-circle-outline" ); | 542 "av:pause-circle-outline" : "av:play-circle-outline" ); |
| 580 }, | 543 }, |
| 581 | 544 |
| 582 /** Callback when "follow" has changed. */ | 545 /** Callback when "backfill" has changed. */ |
| 583 _backfillChanged: function(v) { | 546 _backfillChanged: function(v) { |
| 584 this._view.handleBackfillChanged(v); | 547 this._view.handleBackfillChanged(v); |
| 585 }, | 548 }, |
| 586 | 549 |
| 587 _computeBackfillIconName: function(backfill) { | 550 _computeBackfillIconName: function(backfill) { |
| 588 return ( (backfill) ? | 551 return ( (backfill) ? |
| 589 "editor:border-bottom" : "editor:border-top" ); | 552 "editor:border-bottom" : "editor:border-top" ); |
| 590 }, | 553 }, |
| 591 | 554 |
| 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. */ | 555 /** Callback when "split" button has been clicked. */ |
| 598 _splitClicked: function() { | 556 _splitClicked: function() { |
| 599 this._view.handleSplitClicked(); | 557 this._view.handleSplitClicked(); |
| 600 }, | 558 }, |
| 601 | 559 |
| 602 /** Callback when "split" button has been clicked. */ | 560 /** Callback when "split" button has been clicked. */ |
| 603 _scrollToSplit: function() { | 561 _scrollToSplit: function() { |
| 604 this._view.handleScrollToSplitClicked(); | 562 this._view.handleScrollToSplitClicked(); |
| 605 }, | 563 }, |
| 606 | 564 |
| 607 _updateSplitVisible: function(v) { | 565 _updateSplitVisible: function(v) { |
| 608 this.toggleClass("logFetchButtonVisible", v, this.$.logSplit); | 566 this.toggleClass("logFetchButtonVisible", v, this.$.logSplit); |
| 609 }, | |
| 610 | |
| 611 _updateBottomVisible: function(v) { | |
| 612 this.toggleClass("logFetchButtonVisible", v, this.$.logBottom); | 567 this.toggleClass("logFetchButtonVisible", v, this.$.logBottom); |
| 613 }, | 568 }, |
| 614 | 569 |
| 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() { | 570 _onSignin: function() { |
| 628 this._view.handleSignin(); | 571 this._view.handleSignin(); |
| 629 }, | 572 }, |
| 630 }); | 573 }); |
| 631 </script> | 574 </script> |
| OLD | NEW |