| <!-- The <detail-table-sk> custom element declaration. |
| |
| Presents detailed information about the differences |
| between two images, or just one image if the bothcolumns |
| attribute is false. |
| |
| Attributes: |
| top - The top digest. |
| left - The left digest. |
| test - The name of the test the digests are from. |
| bothcolumns - A boolean, if present then display both top and left values, |
| otherwise only display the left. |
| Events: |
| triage - The change event e.detail has the form: |
| { |
| test: "testname1", |
| digest: "aabb112233", |
| status: "positive", |
| } |
| Methods: |
| --> |
| <polymer-element name="detail-table-sk" attributes="top left test bothcolumns"> |
| <template> |
| <style type="text/css" media="screen"> |
| #legend { |
| margin-top: 2em; |
| } |
| |
| #commits { |
| padding: 1em; |
| padding-left: 3em; |
| } |
| |
| dots-sk { |
| box-shadow: 5px 5px 10px 2px rgba(133,133,133,1); |
| } |
| |
| .perTrace { |
| width: 100%; |
| } |
| |
| th { |
| text-align: right; |
| } |
| |
| th, td { |
| text-align: left; |
| padding: 5px; |
| vertical-align: top; |
| } |
| |
| tri-sk { |
| min-width: 15em; |
| display: block; |
| } |
| |
| .sectionHeader { |
| padding-top: 2em; |
| text-decoration: underline; |
| } |
| |
| .openInNew { |
| position: relative; |
| } |
| |
| .openInNew a { |
| top: 5px; |
| position: absolute; |
| } |
| |
| table.singlecolumn .both { |
| display: none; |
| } |
| |
| .single { |
| display: none; |
| } |
| |
| table.singlecolumn .single { |
| display: table-row; |
| } |
| |
| img.small { |
| border: solid 1px lightgray; |
| max-width: 128px; |
| max-height: 128px; |
| width: auto; |
| height: auto; |
| } |
| |
| circle.status0 { |
| fill: #000000; |
| stroke: #000000; |
| } |
| circle.status1 { |
| fill: #ffffff; |
| stroke: #1B9E77; |
| } |
| circle.status2 { |
| fill: #ffffff; |
| stroke: #D95F02; |
| } |
| circle.status3 { |
| fill: #ffffff; |
| stroke: #7570B3; |
| } |
| circle.status4 { |
| fill: #ffffff; |
| stroke: #E7298A; |
| } |
| circle.status5 { |
| fill: #ffffff; |
| stroke: #66A61E; |
| } |
| circle.status6 { |
| fill: #ffffff; |
| stroke: #E6AB02; |
| } |
| circle.status7 { |
| fill: #ffffff; |
| stroke: #A6761D; |
| } |
| circle.status8 { |
| fill: #ffffff; |
| stroke: #999999; |
| } |
| .preview { |
| margin: 5px; |
| border: solid 2px lightgray; |
| display: block; |
| width: 132px; |
| height: 132px; |
| } |
| .preview img { |
| display: block; |
| max-width: 128px; |
| max-height: 128px; |
| width: auto; |
| height: auto; |
| } |
| .closestDetails div { |
| padding-bottom: 0.5em; |
| padding-left: 0.5em; |
| } |
| paper-spinner { |
| margin-left: 1em; |
| } |
| </style> |
| <table class="{{bothcolumns?'':'singlecolumn'}}"> |
| <tr class=both> |
| <th></th> |
| <th>Left</th> |
| <th class=both>Top</th> |
| </tr> |
| <tr> |
| <th>Status</th> |
| <td><tri-sk id=leftDetail value="{{details.leftStatus}}" title="{{left}}"></tri-sk> </td> |
| <td class=both><tri-sk id=topDetail value="{{details.topStatus}}" title="{{top}}"></tri-sk></td> |
| </tr> |
| <tr> |
| <th>Image</th> |
| <td class=openInNew><img class=small src="/img/images/{{left}}.png"> <a href="/img/images/{{left}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a></td> |
| <td class="openInNew both"><img class=small src="/img/images/{{top}}.png"> <a href="/img/images/{{top}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a></td> |
| </tr> |
| <tr class=single> |
| <th>Test</th> |
| <td><a href="/cmp/{{test}}">{{test}}</a></td> |
| <td class=both><a href="/cmp/{{test}}">{{test}}</a></td> |
| </tr> |
| <tr> |
| <th>Digest</th> |
| <td><a href="detail?test={{test}}&digest={{left}}">{{left}}</a></td> |
| <td class=both><a href="detail?test={{test}}&digest={{top}}">{{top}}</a></td> |
| </tr> |
| |
| <tr><th colspan=2 class=sectionHeader>Parameters <paper-spinner active="{{getInProgress}}"></paper-spinner></th></tr> |
| |
| <template repeat="{{p in details.params}}"> |
| <tr> |
| <th>{{p.name}}</th> |
| <td class=pval> |
| <template repeat="{{n in p.left}}"> |
| {{n}} |
| </template> |
| </td> |
| <td class="pval both"> |
| <template repeat="{{n in p.top}}"> |
| {{n}} |
| </template> |
| </td> |
| </tr> |
| </template> |
| |
| <template if="{{!bothcolumns}}"> |
| <tr><th colspan=2 class=sectionHeader>Graphs</th></tr> |
| <tr> |
| <th>Per Trace</th> |
| <td class=perTrace> |
| <div horizontal layout> |
| <div vertical layout> |
| <paper-input disabled value="" label="Highlighted Trace ID" id="tracename"></paper-input> |
| <dots-sk id=dots></dots-sk> |
| |
| <table id=legend> |
| <tr><th colspan=3>Legend</th></tr> |
| <tr> <td> <svg width=10 height=10 viewBox="-1 -1 2 2"> <circle cx=0 cy=0 r="0.3" class="status0"/> </svg> </td> <td><code>{{top}}</code></td> </tr> |
| <template repeat="{{digestInfo, i in details.otherDigests}}"> |
| <tr> |
| <td> |
| <svg width=10 height=10 viewBox="-1 -1 2 2"> |
| <circle cx=0 cy=0 r="0.3" class="status{{i+1}}"/> |
| </svg> |
| </td> |
| <td> |
| <template if="{{i<7}}"> |
| <code><a href="detail?test={{test}}&digest={{digestInfo.digest}}">{{digestInfo.digest}}</a></code> |
| </template> |
| <template if="{{i==7}}"> |
| One of many other digests. |
| </template> |
| </td> |
| <td> |
| <template if="{{i<7}}"> |
| <tricon-sk value="{{digestInfo.status}}"></tricon-sk> |
| </template> |
| </td> |
| <td> |
| <template if="{{i<7}}"> |
| <a href="diff?test={{test}}&left={{digestInfo.digest}}&top={{top}}">diff</a> |
| </template> |
| </td> |
| </tr> |
| </template> |
| </table> |
| </div> |
| <commits-sk id=commits></commits-sk> |
| </div> |
| </td> |
| <td class=both></td> |
| </tr> |
| <template if="{{details.topStatus!='positive'}}"> |
| <tr><th colspan=2 class=sectionHeader>Closest Postive Digest</th></tr> |
| <tr> |
| <td colspan=2> |
| <div vertical layout class=closestDetails> |
| <div> |
| <a href="detail?test={{test}}&digest={{details.posClosest.digest}}">{{details.posClosest.digest}}</a> |
| <a href="diff?test=blurs&left={{top}}&top={{details.posClosest.digest}}">Details</a> |
| </div> |
| <div><strong>Diff:</strong> {{details.posClosest.diff | fixedPercent}}%</div> |
| <div><strong>RGBA:</strong> {{details.posClosest.maxRGBA}}</div> |
| </div> |
| <div horizontal layout id=images> |
| <div class=preview> |
| <img src="/img/images/{{details.posClosest.digest}}.png" /> |
| </div> |
| <a href="/img/images/{{details.posClosest.digest}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a> |
| <div class=preview> |
| <img src="/img/diffs/{{details.posClosest.digest | diffTo}}.png" /> |
| </div> |
| <a href="/img/diffs/{{details.posClosest.digest | diffTo}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a> |
| <div class=preview> |
| <img src="/img/images/{{top}}.png" /> |
| </div> |
| <a href="/img/images/{{top}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a> |
| </div> |
| </td> |
| </tr> |
| </template> |
| <template if="{{details.topStatus!='negative'}}"> |
| <tr><th colspan=2 class=sectionHeader>Closest Negative Digest</th></tr> |
| <tr> |
| <td colspan=2> |
| <div vertical layout class=closestDetails> |
| <div> |
| <a href="detail?test={{test}}&digest={{details.negClosest.digest}}">{{details.negClosest.digest}}</a> |
| <a href="diff?test=blurs&left={{top}}&top={{details.negClosest.digest}}">Details</a> |
| </div> |
| <div><strong>Diff:</strong> {{details.negClosest.diff | fixedPercent}}%</div> |
| <div><strong>RGBA:</strong> {{details.negClosest.maxRGBA}}</div> |
| </div> |
| <div horizontal layout id=images> |
| <div class=preview> |
| <img src="/img/images/{{details.negClosest.digest}}.png" /> |
| </div> |
| <a href="/img/images/{{details.negClosest.digest}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a> |
| <div class=preview> |
| <img src="/img/diffs/{{details.negClosest.digest | diffTo}}.png" /> |
| </div> |
| <a href="/img/diffs/{{details.negClosest.digest | diffTo}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a> |
| <div class=preview> |
| <img src="/img/images/{{top}}.png" /> |
| </div> |
| <a href="/img/images/{{top}}.png" target=_blank><core-icon icon="open-in-new"></core-icon></a> |
| </div> |
| </td> |
| </tr> |
| </template> |
| </template> |
| </table> |
| </template> |
| <script> |
| (function(){ |
| // removeSecurityHeader drops the first 4 chars from JSON returned from |
| // the gitiles server to make it into valid JSON. |
| function removeSecurityHeader(s) { |
| return s.slice(4, s.length); |
| } |
| |
| Polymer({ |
| publish: { |
| top: { |
| value: "", |
| reflect: true, |
| }, |
| left: { |
| value: "", |
| reflect: true, |
| }, |
| test: { |
| value: "", |
| reflect: true, |
| }, |
| bothcolumns: { |
| value: false, |
| reflect: true, |
| } |
| }, |
| |
| ready: function() { |
| // A serialized PolyDetailsGUI which has the form: |
| // |
| // { |
| // topStatus: "positive", |
| // leftStatus: "negative", |
| // params: [ |
| // { |
| // name: "arch", |
| // top: ["Arm7"], |
| // left: ["Arm8", "x86"], |
| // } |
| // ... |
| // ], |
| // } |
| this.details = { |
| topStatus: "untriaged", |
| leftStatus: "untriaged", |
| }; |
| |
| this.getInProgress = false; |
| |
| var that = this; |
| this.$.topDetail.addEventListener('change', function(e) { |
| e.stopPropagation(); |
| var detail = { |
| test: that.test, |
| digest: [that.top], |
| status: e.detail, |
| }; |
| that.dispatchEvent(new CustomEvent('triage', {detail: detail})); |
| }); |
| this.$.leftDetail.addEventListener('change', function(e) { |
| e.stopPropagation(); |
| var detail = { |
| test: that.test, |
| digest: [that.left], |
| status: e.detail, |
| }; |
| that.dispatchEvent(new CustomEvent('triage', {detail: detail})); |
| }); |
| |
| this.hoverElement = null; |
| |
| if (this.$.dots) { |
| this.$.dots.addEventListener('hover', function(e) { |
| that.$.tracename.value = e.detail; |
| }); |
| |
| this.$.dots.addEventListener('commit-selected', function(e) { |
| that.$.commits.setCommitInfo(e.detail); |
| }); |
| } |
| }, |
| |
| changeImpl_: function() { |
| if (this.test == "" || this.top == "" || this.left == "" || this.getInProgress) { |
| return |
| } |
| this.getInProgress = true; |
| var that = this; |
| var q = "?test=" + this.test + "&top=" + this.top + "&left=" + this.left + "&graphs=" + !this.bothcolumns + "&closest=" + !this.bothcolumns; |
| sk.get('_/details'+q).then(JSON.parse).then(function(json) { |
| that.details = json; |
| that.getInProgress = false; |
| if (that.$.dots) { |
| that.$.dots.setValue(json); |
| that.$.dots.setCommits(json.commits); |
| } |
| |
| if (json.commits) { |
| // Now populate the commit messages. |
| var lastHash = json.commits[json.commits.length-1].hash; |
| var url = "https://skia.googlesource.com/skia/+log/" + lastHash + "~" + json.commits.length + ".." + lastHash + "?format=json"; |
| sk.get(url).then(removeSecurityHeader).then(JSON.parse).then(function(json) { |
| var len = that.details.commits.length; |
| for (var i=0; i<json.log.length; i++) { |
| that.details.commits[len-i-1].message = json.log[i].message.slice(0, 40); |
| } |
| }); |
| } |
| }); |
| }, |
| |
| // diffTo is a template filter that returns "d1-d2", where d1 and d2 |
| // are two digests, with d1 < d2, which makes it useful for |
| // referencing diff images. |
| diffTo: function(s) { |
| if (s<this.top) { |
| return s+"-"+this.top; |
| } else { |
| return this.top+"-"+s;; |
| } |
| }, |
| |
| fixedPercent: function(i) { |
| if (i) { |
| return i.toFixed(2); |
| } else { |
| return ''; |
| } |
| }, |
| |
| testChanged: function() { |
| this.changeImpl_(); |
| }, |
| |
| topChanged: function() { |
| this.changeImpl_(); |
| }, |
| |
| leftChanged: function() { |
| this.changeImpl_(); |
| }, |
| }); |
| })(); |
| </script> |
| </polymer-element> |