| <!-- |
| This in an HTML Import-able file that contains the definitions |
| for the following elements: |
| |
| <cluster-summary-sk> |
| |
| Properties: |
| fade - A boolean, fade out an issue if its status isn't New. |
| mailbox - The name of the sk.Mailbox that contains a serialized |
| tiling.TileGUI. |
| |
| Methods: |
| setSummary() - A serialized types.ClusterSummary. |
| If the summary.ID == -1 then the triaging dialog is not displayed. |
| |
| Events: |
| None. |
| |
| --> |
| <link rel="import" href="/res/imp/bower_components/iron-flex-layout/iron-flex-layout-classes.html"> |
| <link rel="import" href="/res/imp/bower_components/paper-material/paper-material.html"> |
| <link rel="import" href="/res/imp/bower_components/paper-radio-button/paper-radio-button.html"> |
| <link rel="import" href="/res/imp/bower_components/paper-radio-group/paper-radio-group.html"> |
| |
| <link rel="stylesheet" href="/res/common/css/md.css"> |
| |
| <link rel="import" href="/res/common/imp/login.html"> |
| <link rel="import" href="/res/common/imp/toggle.html"> |
| <link rel="import" href="/res/common/imp/word-cloud.html"> |
| <link rel="import" href="plot.html"> |
| |
| <dom-module id="cluster-summary-sk"> |
| <style include="iron-flex iron-flex-alignment"> |
| #status.disabled { |
| opacity: 0.5; |
| } |
| |
| .highlight .high { |
| background-color: #44AA99; |
| color: white; |
| border-radius: 6px; |
| padding: 3px 6px; |
| } |
| |
| .highlight .low { |
| background-color: #AA4499; |
| color: white; |
| border-radius: 6px; |
| padding: 3px 6px; |
| } |
| |
| @media (max-width: 600px) { |
| #graph { |
| display: none; |
| } |
| } |
| |
| .fade { |
| opacity: 0.3; |
| } |
| |
| word-cloud-sk { |
| display: none; |
| } |
| |
| word-cloud-sk.display { |
| display: block; |
| } |
| |
| .disabledMessage { |
| display: none; |
| } |
| |
| #status { |
| padding: 0.5em 2em; |
| } |
| |
| #status.disabled .disabledMessage { |
| display: block; |
| } |
| |
| plot-simple-sk { |
| margin: 1em; |
| } |
| |
| paper-material #status.hidden, |
| #clPermalink.hidden { |
| display: none; |
| } |
| |
| #choices paper-radio-button { |
| --default-primary-color: #1f78b4; |
| } |
| |
| input { |
| padding: 0.6em; |
| } |
| |
| .labelled { |
| display: inline-block; |
| margin-right: 2em; |
| } |
| </style> |
| <template> |
| <div id=container class$="layout horizontal {{faded(fade, summary.Status)}}"> |
| <plot-sk id=graph width=400 height=150></plot-sk> |
| <div class="clDetails highlight"> |
| <p class$="{{statusClass(summary.StepFit.Status)}}"> |
| Regression: <span class="clRegression">{{trunc(summary.StepFit.Regression)}}</span> |
| </p> |
| <p> |
| <button id="shortcut">View on dashboard</button> |
| <a id="clPermalink" class$="{{hiddenClass(summary.ID)}}" href$="{{permaLink(summary.ID)}}">Permlink</a> |
| </p> |
| <p id=metrics> |
| <div class=labelled>Cluster Size: <span class="clClusterSize">{{summary.Keys.length}}</span></div> |
| <div class=labelled>Least Squares Error: <span class="clLeastSquares">{{trunc(summary.StepFit.LeastSquares)}}</span></div> |
| <div class=labelled>Step Size: <span class="clStepSize">{{trunc(summary.StepFit.StepSize)}}</span></div> |
| <div class=labelled><span class="clBugs">Bugs:</span></div> |
| <div class=labelled>Commit: <a href$="{{commitLink(summary.Hash)}}">{{truncHash(summary.Hash)}}</a></div> |
| </p> |
| <template is="dom-repeat" items="{{summary.Bugs}}" as="b"> |
| <a class="clBug" href$="{{bugLink(b)}}">{{b}}</a> |
| </template> |
| |
| <paper-material elevation="1"> |
| <div id=status class$="{{hiddenClassDisabled(summary.ID)}}"> |
| <p class="disabledMessage">You must be logged in to change the status.</p> |
| <paper-radio-group id=choices class="layout horizontal" selected="{{cachedStatus}}"> |
| <b class="status">Status:</b> |
| <paper-radio-button name="New" label="New">New</paper-radio-button> |
| <paper-radio-button name="Ignore" label="Ignore">Ignore</paper-radio-button> |
| <paper-radio-button name="Bug" label="Bug">Bug</paper-radio-button> |
| </paper-radio-group> |
| <input value="{{summary.Message}}" label="Note" id="message"></input> |
| <button class="action layout self end" id=update>Update</button> |
| </div> |
| </paper-material> |
| <toggle-display-sk>Word Cloud</toggle-display-sk> |
| <word-cloud-sk id=wordcloud></word-cloud-sk> |
| </div> |
| </div> |
| </template> |
| <script> |
| Polymer({ |
| is: 'cluster-summary-sk', |
| |
| properties: { |
| fade: { |
| type: Boolean, |
| value: false, |
| }, |
| mailbox: { |
| type: String, |
| value: "tileinfo", |
| }, |
| }, |
| |
| ready: function () { |
| this.summary = {}; |
| this.tileinfo = {}; |
| this.$.update.addEventListener('click', this.updateClick.bind(this)); |
| this.$.shortcut.addEventListener('click', this.openShortcut.bind(this)); |
| this.cachedStatus = this.summary.Status || 'New'; |
| |
| sk.Login.then(function(status) { |
| this.$.status.classList.toggle('disabled', status['Email'] == ''); |
| }.bind(this)).catch(sk.errorMessage); |
| |
| sk.Mailbox.subscribe(this.mailbox, function(tileinfo) { |
| if (!tileinfo) { |
| return |
| } |
| this.tileinfo = tileinfo; |
| this.setGraphInfo(); |
| |
| }.bind(this)); |
| }, |
| |
| setGraphInfo: function() { |
| if (!this.summary["Hash"] || !this.tileinfo["commits"]) { |
| return |
| } |
| // this.$.graph.setBackgroundInfo(); |
| // this.$.graph.setStepIndex(); uses this.summary.Hash. |
| var skps = [0].concat(this.tileinfo.skps, [this.tileinfo.commits.length-1]); |
| var tickmap = {}; |
| for (var i = this.tileinfo.ticks.length - 1; i >= 0; i--) { |
| var t = this.tileinfo.ticks[i]; |
| tickmap[t[0]] = t[1]; |
| } |
| this.$.graph.setBackgroundInfo(tickmap, skps, this.lastCommitIndex(this.tileinfo.commits)); |
| |
| var index = -1; |
| for (var i = 0, len = this.tileinfo.commits.length; i < len; i++) { |
| if (this.tileinfo.commits[i].hash == this.summary.Hash) { |
| index = i; |
| break; |
| } |
| } |
| this.$.graph.setStepIndex(index); |
| }, |
| |
| lastCommitIndex: function(commits) { |
| for (var i = commits.length - 1; i >= 0; i--) { |
| if (commits[i].commit_time != 0) { |
| return i; |
| } |
| } |
| // We shouldn't get here. |
| return commits.length-1; |
| }, |
| |
| setSummary: function (summary) { |
| // Check for an empty summary object. |
| if (summary.ParamSummaries == undefined) { |
| return; |
| } |
| this.summary = summary; |
| this.cachedStatus = this.summary.Status || 'New'; |
| // Set the data- attributes used for sorting cluster summaries. |
| this.dataset.clustersize = this.summary.Keys.length; |
| this.dataset.steplse = this.summary.StepFit.LeastSquares; |
| this.dataset.stepsize = this.summary.StepFit.StepSize; |
| this.dataset.stepregression = this.summary.StepFit.Regression; |
| this.dataset.timestamp = this.summary.Timestamp; |
| this.summary.ParamSummaries.sort(function (a, b) { |
| return b[0].Weight - a[0].Weight; |
| }); |
| this.$.wordcloud.setItems(summary.ParamSummaries); |
| // We take in a ClusterSummary, but need to transform all that data |
| // into a format that plot-sk can handle. |
| |
| // Covert this.summary.Traces[0] into a traces that plot-sk wants. |
| var traces = [ |
| { |
| data: this.summary.Traces[0], |
| label: "0", |
| _params: {"id": "0"}, |
| }, |
| ]; |
| |
| this.$.graph.addTraces(traces); |
| this.$.graph.highlightGroup("id", "0"); |
| this.setGraphInfo(); |
| }, |
| |
| updateClick: function () { |
| var status = this.$.choices.selected; |
| var state = { |
| Id: this.summary.ID, |
| Status: status, |
| Message: this.$.message.value |
| }; |
| sk.post('/annotate/', JSON.stringify(state)).then(JSON.parse).then(function (json) { |
| this.set("summary.Status", status); |
| if (json.Bug) { |
| // Open the bug reporting page in a new window. |
| window.open(json.Bug, '_blank'); |
| } |
| }.bind(this)).catch(sk.errorMessage); |
| }, |
| |
| openShortcut: function (e) { |
| var keys = this.summary.Keys.slice(0, 50); |
| var state = { |
| scale: 0, |
| tiles: [-1], |
| hash: this.summary.Hash, |
| keys: keys, |
| }; |
| sk.post('/shortcuts/', JSON.stringify(state)).then(JSON.parse).then(function (json) { |
| window.open('/#' + json.id, '_blank'); |
| }); |
| e.preventDefault(); |
| }, |
| |
| // Below are filters used in template expansion: |
| hiddenClass: function (id) { |
| if (id == -1) { |
| return 'hidden'; |
| } |
| return ''; |
| }, |
| |
| hiddenClassDisabled: function (id) { |
| if (id == -1) { |
| return 'hidden'; |
| } |
| return ''; |
| }, |
| |
| permaLink: function (id) { |
| return '/cl/' + id; |
| }, |
| |
| faded: function (fade, status) { |
| if (fade && status != 'New') { |
| return 'fade'; |
| } |
| return ''; |
| }, |
| |
| statusClass: function (status) { |
| status = status || ""; |
| return status.toLowerCase(); |
| }, |
| |
| trunc: function (value) { |
| return (+value).toPrecision(3); |
| }, |
| |
| truncHash: function (value) { |
| if (value) { |
| return value.substring(0, 7); |
| } |
| }, |
| |
| commitLink: function (hash) { |
| return 'https://skia.googlesource.com/skia/+/' + hash; |
| }, |
| |
| bugLink: function (b) { |
| return 'https://bug.skia.org/' + b; |
| } |
| }); |
| </script> |
| </dom-module> |