| OLD | NEW |
| 1 <link rel="import" href="/res/imp/polymer/polymer.html" /> | 1 <link rel="import" href="/res/imp/polymer/polymer.html" /> |
| 2 <link rel="import" href="/res/imp/core-ajax/core-ajax.html" /> | 2 <link rel="import" href="/res/imp/core-ajax/core-ajax.html" /> |
| 3 <link rel="import" href="/res/imp/core-icon-button/core-icon-button.html" /> | 3 <link rel="import" href="/res/imp/core-icon-button/core-icon-button.html" /> |
| 4 <link rel="import" href="/res/imp/core-input/core-input.html" /> | 4 <link rel="import" href="/res/imp/core-input/core-input.html" /> |
| 5 | 5 |
| 6 <script type="text/javascript" src="/res/js/common.js"></script> | 6 <script type="text/javascript" src="/res/js/common.js"></script> |
| 7 | 7 |
| 8 <polymer-element name="commits-sk"> | 8 <polymer-element name="commits-sk"> |
| 9 <template> | 9 <template> |
| 10 <style> | 10 <style> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 background-color: #FFFFFF; | 31 background-color: #FFFFFF; |
| 32 } | 32 } |
| 33 tr.commit > td { | 33 tr.commit > td { |
| 34 padding: 0px 5px; | 34 padding: 0px 5px; |
| 35 margin: 0px; | 35 margin: 0px; |
| 36 white-space: nowrap; | 36 white-space: nowrap; |
| 37 } | 37 } |
| 38 a { | 38 a { |
| 39 color: inherit; | 39 color: inherit; |
| 40 } | 40 } |
| 41 #moreButton { |
| 42 width: 40px; |
| 43 height: 40px; |
| 44 } |
| 41 </style> | 45 </style> |
| 42 <div vertical layout flex> | 46 <div vertical layout flex> |
| 43 <div horizontal layout center id="loadstatus"> | 47 <div horizontal layout center id="loadstatus"> |
| 44 <div> | 48 <div> |
| 45 Reload (s): | 49 Reload (s): |
| 46 <core-input type="number" value="{{reload}}" preventInvalidInput style
="width: 50px;"></core-input> | 50 <core-input type="number" value="{{reload}}" preventInvalidInput style
="width: 50px;"></core-input> |
| 47 </div> | 51 </div> |
| 48 <div flex></div> | 52 <div flex></div> |
| 49 <div>Last loaded at {{lastLoaded}}</div> | 53 <div>Last loaded at {{lastLoaded}}</div> |
| 50 </div> | 54 </div> |
| 51 <div horizontal layout> | 55 <div horizontal layout> |
| 52 <div id="canvasContainer"></div> | 56 <div id="canvasContainer"></div> |
| 53 <canvas id="commitCanvas"></canvas> | 57 <canvas id="commitCanvas"></canvas> |
| 54 <div flex> | 58 <div flex> |
| 55 <table class="commitList"> | 59 <table class="commitList"> |
| 56 <template repeat="{{commit in commits}}"> | 60 <template repeat="{{commit in commits}}"> |
| 57 <tr class="commit" style="color: {{getCommitColor(displayCommits[c
ommit.hash])}}"> | 61 <tr class="commit" style="color: {{getCommitColor(displayCommits[c
ommit.hash])}}"> |
| 58 <td><a href="https://skia.googlesource.com/skiabot-test/+/{{comm
it.hash}}" target="_blank">{{commit.hash|shortCommit}}</a></td> | 62 <td><a href="https://skia.googlesource.com/skia/+/{{commit.hash}
}" target="_blank">{{commit.hash|shortCommit}}</a></td> |
| 59 <td>{{commit.author|shortAuthor}}</td> | 63 <td>{{commit.author|shortAuthor}}</td> |
| 60 <td>{{commit.subject|shortSubject}}</td> | 64 <td>{{commit.subject|shortSubject}}</td> |
| 61 </tr> | 65 </tr> |
| 62 </template> | 66 </template> |
| 63 </table> | 67 </table> |
| 64 </div> | 68 </div> |
| 65 </div> | 69 </div> |
| 70 <!-- TODO(borenet): Automatically loadMore when the user scrolls to the bo
ttom? --> |
| 71 <core-icon-button id="moreButton" icon="add" on-click="{{loadMore}}"></cor
e-icon-button> |
| 66 </div> | 72 </div> |
| 67 </template> | 73 </template> |
| 68 <script> | 74 <script> |
| 69 (function() { | 75 (function() { |
| 70 var commitY = 20; // Vertical pixels used by each commit. | 76 var defaultCommitsToLoad = 35; // Default number of commits to load. |
| 71 var paddingX = 10; // Left-side padding pixels. | 77 var commitY = 20; // Vertical pixels used by each commit. |
| 72 var paddingY = 20; // Top padding pixels. | 78 var paddingX = 10; // Left-side padding pixels. |
| 73 var radius = 3; // Radius of commit dots. | 79 var paddingY = 20; // Top padding pixels. |
| 74 var columnWidth = commitY; // Pixel width of per-branch colums. | 80 var radius = 3; // Radius of commit dots. |
| 81 var columnWidth = commitY; // Pixel width of per-branch colums. |
| 75 // Colors used for the branches. Obtained from | 82 // Colors used for the branches. Obtained from |
| 76 // http://blog.mollietaylor.com/2012/10/color-blindness-and-palette-choice.h
tml | 83 // http://blog.mollietaylor.com/2012/10/color-blindness-and-palette-choice.h
tml |
| 77 var palette = [ | 84 var palette = [ |
| 78 "#1B9E77", | 85 "#1B9E77", |
| 79 "#D95F02", | 86 "#D95F02", |
| 80 "#7570B3", | 87 "#7570B3", |
| 81 "#E7298A", | 88 "#E7298A", |
| 82 "#66A61E", | 89 "#66A61E", |
| 83 "#E6AB02", | 90 "#E6AB02", |
| 84 "#A6761D", | 91 "#A6761D", |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 if (b != masterIdx && branch.name != "HEAD") { | 282 if (b != masterIdx && branch.name != "HEAD") { |
| 276 branches.push(branch); | 283 branches.push(branch); |
| 277 } | 284 } |
| 278 } | 285 } |
| 279 | 286 |
| 280 // Trace each branch, placing commits on that branch in an associated colu
mn. | 287 // Trace each branch, placing commits on that branch in an associated colu
mn. |
| 281 var column = 0; | 288 var column = 0; |
| 282 for (var b = 0; b < branches.length; b++) { | 289 for (var b = 0; b < branches.length; b++) { |
| 283 // Add a label to commits at branch heads. | 290 // Add a label to commits at branch heads. |
| 284 var hash = branches[b].head | 291 var hash = branches[b].head |
| 285 displayCommits[branches[b].head].label.push(branches[b].name); | 292 // The branch might have scrolled out of the time window. If so, just |
| 293 // skip it. |
| 294 if (!displayCommits[hash]) { |
| 295 continue |
| 296 } |
| 297 displayCommits[hash].label.push(branches[b].name); |
| 286 if (traceCommits(displayCommits, commits, remaining, hash, column)) { | 298 if (traceCommits(displayCommits, commits, remaining, hash, column)) { |
| 287 column++; | 299 column++; |
| 288 } | 300 } |
| 289 } | 301 } |
| 290 | 302 |
| 291 // Add the remaining commits to their own columns. | 303 // Add the remaining commits to their own columns. |
| 292 for (var hash in remaining) { | 304 for (var hash in remaining) { |
| 293 if (traceCommits(displayCommits, commits, remaining, hash, column)) { | 305 if (traceCommits(displayCommits, commits, remaining, hash, column)) { |
| 294 column++; | 306 column++; |
| 295 } | 307 } |
| 296 } | 308 } |
| 297 | 309 |
| 298 return [displayCommits, column]; | 310 return [displayCommits, column]; |
| 299 } | 311 } |
| 300 | 312 |
| 301 Polymer({ | 313 Polymer({ |
| 302 publish: { | 314 publish: { |
| 303 commits: { | 315 commits: { |
| 304 value: null, | 316 value: null, |
| 305 reflect: true, | 317 reflect: true, |
| 306 }, | 318 }, |
| 307 branchHeads: { | 319 branchHeads: { |
| 308 value: null, | 320 value: null, |
| 309 reflect: true, | 321 reflect: true, |
| 310 }, | 322 }, |
| 311 dispayCommits: { | 323 displayCommits: { |
| 312 value: null, | 324 value: null, |
| 313 reflect: true, | 325 reflect: true, |
| 314 }, | 326 }, |
| 315 reload: { | 327 reload: { |
| 316 value: 60, | 328 value: 60, |
| 317 reflect: true, | 329 reflect: true, |
| 318 }, | 330 }, |
| 319 timeout: { | 331 timeout: { |
| 320 value: null, | 332 value: null, |
| 321 reflect: false, | 333 reflect: false, |
| 322 }, | 334 }, |
| 323 lastLoaded: { | 335 lastLoaded: { |
| 324 value: "(not yet loaded)", | 336 value: "(not yet loaded)", |
| 325 reflect: false, | 337 reflect: false, |
| 326 }, | 338 }, |
| 327 }, | 339 }, |
| 328 | 340 |
| 329 created: function() { | 341 created: function() { |
| 330 this.commits = []; | 342 this.commits = []; |
| 331 this.branchHeads = []; | 343 this.branchHeads = []; |
| 344 this.startIdx = null; |
| 345 this.endIdx = null; |
| 332 this.reloadCommits(); | 346 this.reloadCommits(); |
| 333 var that = this; | 347 var that = this; |
| 334 window.addEventListener("resize", function() { | 348 window.addEventListener("resize", function() { |
| 335 that.draw(); | 349 that.draw(that.commits, that.branchHeads); |
| 336 }, true); | 350 }, true); |
| 337 }, | 351 }, |
| 338 | 352 |
| 339 // shortCommit returns the first 12 characters of a commit hash. | 353 // shortCommit returns the first 12 characters of a commit hash. |
| 340 shortCommit: function(commit) { | 354 shortCommit: function(commit) { |
| 341 return commit.substring(0, 12); | 355 return commit.substring(0, 12); |
| 342 }, | 356 }, |
| 343 | 357 |
| 344 // shortAuthor shortens the commit author field by returning the | 358 // shortAuthor shortens the commit author field by returning the |
| 345 // parenthesized email address if it exists. If it does not exist, the | 359 // parenthesized email address if it exists. If it does not exist, the |
| (...skipping 23 matching lines...) Expand all Loading... |
| 369 reloadChanged: function() { | 383 reloadChanged: function() { |
| 370 this.resetTimeout(); | 384 this.resetTimeout(); |
| 371 }, | 385 }, |
| 372 | 386 |
| 373 resetTimeout: function() { | 387 resetTimeout: function() { |
| 374 if (this.timeout) { | 388 if (this.timeout) { |
| 375 window.clearTimeout(this.timeout); | 389 window.clearTimeout(this.timeout); |
| 376 } | 390 } |
| 377 if (this.reload > 0) { | 391 if (this.reload > 0) { |
| 378 var that = this; | 392 var that = this; |
| 379 this.timeout = window.setTimeout(function() { that.reloadCommits(); },
this.reload * 1000); | 393 this.timeout = window.setTimeout(function() { |
| 394 that.reloadCommits(that.endIdx); |
| 395 }, this.reload * 1000); |
| 380 } | 396 } |
| 381 }, | 397 }, |
| 382 | 398 |
| 383 reloadCommits: function() { | 399 loadMore: function() { |
| 400 this.reloadCommits(this.startIdx - defaultCommitsToLoad, this.startIdx); |
| 401 }, |
| 402 |
| 403 // Reload the commits. If the startIdx and endIdx parameters are given, |
| 404 // loads the commits in that range. If not, load the most recent N |
| 405 // commits, where N is the default number returned by the server. |
| 406 reloadCommits: function(startIdx, endIdx) { |
| 384 console.log("Loading commits."); | 407 console.log("Loading commits."); |
| 408 if (this.$) { |
| 409 this.$.moreButton.disabled = true; |
| 410 } |
| 411 var url = "/json/commits"; |
| 412 if (startIdx) { |
| 413 url += "?start=" + startIdx; |
| 414 if (endIdx) { |
| 415 url += "&end=" + endIdx; |
| 416 } |
| 417 } |
| 418 console.log("GET " + url); |
| 385 var that = this; | 419 var that = this; |
| 386 sk.get("/json/commits").then(JSON.parse).then(function(json) { | 420 sk.get(url).then(JSON.parse).then(function(json) { |
| 387 that.commits = json.commits; | 421 try { |
| 388 that.commits.reverse(); | 422 json.commits.reverse(); |
| 389 that.branchHeads = json.branch_heads; | 423 that.lastLoaded = new Date().toLocaleTimeString(); |
| 390 that.lastLoaded = new Date().toLocaleTimeString(); | 424 |
| 391 that.resetTimeout(); | 425 // Merge the new commits into the existing set. |
| 392 console.log("Done loading commits."); | 426 // Ensure that the new commits line up exactly with the existing one
s. |
| 393 that.draw(); | 427 if (json.endIdx - json.startIdx != json.commits.length) { |
| 428 console.error("Server returned invalid number of commits."); |
| 429 return; |
| 430 } |
| 431 var commits = null; |
| 432 // Case 1: Loading initial set of commits. |
| 433 if (!that.startIdx || !that.endIdx) { |
| 434 commits = json.commits; |
| 435 that.startIdx = json.startIdx; |
| 436 that.endIdx = json.endIdx; |
| 437 } |
| 438 // Case 2: Loading earlier commits. |
| 439 else if (json.startIdx < that.startIdx) { |
| 440 if (json.endIdx != that.startIdx) { |
| 441 console.error("Server returned invalid set of commits."); |
| 442 return; |
| 443 } |
| 444 commits = that.commits.concat(json.commits); |
| 445 that.startIdx = json.startIdx; |
| 446 } |
| 447 // Case 3: Loading newer commits. |
| 448 else if (json.endIdx >= that.endIdx) { |
| 449 if (json.startIdx != that.endIdx) { |
| 450 console.error("Server returned invalid set of commits."); |
| 451 return; |
| 452 } |
| 453 if (json.commits.length == 0) { |
| 454 console.log("No new commits. Skipping draw."); |
| 455 return; |
| 456 } |
| 457 commits = json.commits.concat(that.commits); |
| 458 that.endIdx = json.endIdx; |
| 459 } |
| 460 // ??? |
| 461 else { |
| 462 console.error("Server returned invalid data."); |
| 463 return; |
| 464 } |
| 465 // Actually draw the commits. |
| 466 that.draw(commits, json.branch_heads); |
| 467 that.commits = commits; |
| 468 that.branchHeads = json.branch_heads; |
| 469 } catch(e) { |
| 470 console.error(e.stack); |
| 471 return; |
| 472 } finally { |
| 473 that.resetTimeout(); |
| 474 if (that.$) { |
| 475 that.$.moreButton.disabled = false; |
| 476 } |
| 477 } |
| 394 }); | 478 }); |
| 395 }, | 479 }, |
| 396 | 480 |
| 397 draw: function() { | 481 draw: function(commits, branchHeads) { |
| 398 console.log("Drawing."); | 482 console.log("Drawing."); |
| 399 // Initialize all commits. | 483 // Initialize all commits. |
| 400 var prep = prepareCommitsForDisplay(this.commits, this.branchHeads); | 484 var prep = prepareCommitsForDisplay(commits, branchHeads); |
| 401 this.displayCommits = prep[0]; | 485 this.displayCommits = prep[0]; |
| 402 var numColumns = prep[1]; | 486 var numColumns = prep[1]; |
| 403 | 487 |
| 404 // Calculate the required canvas width based on the commit columns and | 488 // Calculate the required canvas width based on the commit columns and |
| 405 // labels. | 489 // labels. |
| 406 // TODO(borenet): Further minimize this width by reordering the columns | 490 // TODO(borenet): Further minimize this width by reordering the columns |
| 407 // based on which has the longest label. | 491 // based on which has the longest label. |
| 408 var dummyCtx = document.createElement("canvas").getContext("2d"); | 492 var dummyCtx = document.createElement("canvas").getContext("2d"); |
| 409 dummyCtx.font = font; | 493 dummyCtx.font = font; |
| 410 var longestWidth = 0; | 494 var longestWidth = 0; |
| 411 for (var i = 0; i < this.commits.length; i++) { | 495 for (var i = 0; i < commits.length; i++) { |
| 412 var c = this.displayCommits[this.commits[i].hash]; | 496 var c = this.displayCommits[commits[i].hash]; |
| 413 var w = c.labelWidth(dummyCtx); | 497 var w = c.labelWidth(dummyCtx); |
| 414 w += commitY * (c.column + 1); | 498 w += commitY * (c.column + 1); |
| 415 if (w > longestWidth) { | 499 if (w > longestWidth) { |
| 416 longestWidth = w; | 500 longestWidth = w; |
| 417 } | 501 } |
| 418 } | 502 } |
| 419 | 503 |
| 420 // Redraw the canvas. | 504 // Redraw the canvas. |
| 421 var scale = window.devicePixelRatio || 1.0; | 505 var scale = window.devicePixelRatio || 1.0; |
| 422 var parent = this.shadowRoot.getElementById("canvasContainer"); | 506 var parent = this.shadowRoot.getElementById("canvasContainer"); |
| 423 var canvas = this.shadowRoot.getElementById("commitCanvas"); | 507 var canvas = this.shadowRoot.getElementById("commitCanvas"); |
| 424 var w = longestWidth + paddingX; | 508 var w = longestWidth + paddingX; |
| 425 var h = commitY * this.commits.length; | 509 var h = commitY * commits.length; |
| 426 canvas.style.width = w + "px"; | 510 canvas.style.width = w + "px"; |
| 427 canvas.style.height = h + "px"; | 511 canvas.style.height = h + "px"; |
| 428 canvas.width = w * scale; | 512 canvas.width = w * scale; |
| 429 canvas.height = h * scale; | 513 canvas.height = h * scale; |
| 430 var ctx = canvas.getContext("2d"); | 514 var ctx = canvas.getContext("2d"); |
| 431 ctx.clearRect(0, 0, canvas.width, canvas.height); | 515 ctx.clearRect(0, 0, canvas.width, canvas.height); |
| 432 ctx.setTransform(scale, 0, 0, scale, 0, 0); | 516 ctx.setTransform(scale, 0, 0, scale, 0, 0); |
| 433 ctx.font = font; | 517 ctx.font = font; |
| 434 | 518 |
| 435 // Shade an alternating background. | 519 // Shade an alternating background. |
| 436 for (var i = 0; i < this.commits.length; i++) { | 520 for (var i = 0; i < commits.length; i++) { |
| 437 this.displayCommits[this.commits[i].hash].drawBackground(ctx); | 521 this.displayCommits[commits[i].hash].drawBackground(ctx); |
| 438 } | 522 } |
| 439 | 523 |
| 440 // Draw the commits. | 524 // Draw the commits. |
| 441 for (var i = 0; i < this.commits.length; i++) { | 525 for (var i = 0; i < commits.length; i++) { |
| 442 this.displayCommits[this.commits[i].hash].draw(ctx, this.displayCommit
s); | 526 this.displayCommits[commits[i].hash].draw(ctx, this.displayCommits); |
| 443 } | 527 } |
| 444 }, | 528 }, |
| 445 }); | 529 }); |
| 446 })(); | 530 })(); |
| 447 </script> | 531 </script> |
| 448 </polymer-element> | 532 </polymer-element> |
| OLD | NEW |