| <!-- |
| This in an HTML Import-able file that contains the definition |
| of the following elements: |
| |
| <job-search-sk> |
| |
| To use this file import it: |
| |
| <link href="/res/imp/job-search-sk.html" rel="import" /> |
| |
| Usage: |
| |
| <job-search-sk></job-search-sk> |
| |
| Properties: |
| recent_repos: Array, optional list of repo URLs used for auto-completion. |
| recent_servers: Array, optional list of codereview servers used for auto-completion. |
| valid_statuses: Array, optional list of valid job statuses used for auto-completion. |
| |
| Methods: |
| None. |
| |
| Events: |
| None. |
| --> |
| |
| <link rel="import" href="/res/common/imp/autocomplete-input-sk.html"> |
| <link rel="import" href="/res/common/imp/date-time-picker-sk.html"> |
| <link rel="import" href="/res/common/imp/human-date-sk.html"> |
| <link rel="import" href="/res/common/imp/styles-sk.html"> |
| <link rel="import" href="/res/common/imp/url-params-sk.html"> |
| <link rel="import" href="/res/imp/bower_components/iron-collapse/iron-collapse.html"> |
| <link rel="import" href="/res/imp/bower_components/iron-flex-layout/iron-flex-layout-classes.html"> |
| <link rel="import" href="/res/imp/bower_components/iron-icons/iron-icons.html"> |
| <link rel="import" href="/res/imp/bower_components/paper-checkbox/paper-checkbox.html"> |
| <link rel="import" href="/res/imp/bower_components/paper-button/paper-button.html"> |
| <link rel="import" href="/res/imp/bower_components/paper-input/paper-input.html"> |
| <link rel="import" href="/res/imp/bower_components/paper-icon-button/paper-icon-button.html"> |
| |
| <dom-module id="job-search-sk"> |
| <template> |
| <style include="iron-flex iron-flex-alignment styles-sk"> |
| :host { |
| font-family: sans-serif; |
| } |
| .cancelButton { |
| color: #fff; |
| } |
| .controlColumn { |
| width: 50%; |
| max-width: 500px; |
| padding: 5px; |
| } |
| .searchButton { |
| color: #fff; |
| } |
| .timeSelect { |
| padding: 3px; |
| } |
| </style> |
| <url-param-sk name="repo" value="{{repo}}"></url-param-sk> |
| <url-param-sk name="revision" value="{{revision}}"></url-param-sk> |
| <url-param-sk name="server" value="{{server}}"></url-param-sk> |
| <url-param-sk name="issue" value="{{issue}}"></url-param-sk> |
| <url-param-sk name="patchset" value="{{patchset}}"></url-param-sk> |
| <url-param-sk name="buildbucket_build_id" value="{{buildbucket_build_id}}"></url-param-sk> |
| <url-param-sk name="isForce" value="{{isForce}}"></url-param-sk> |
| <url-param-sk name="name" value="{{name}}"></url-param-sk> |
| <url-param-sk name="status" value="{{status}}"></url-param-sk> |
| <url-param-sk name="time_start" value="{{_time_start}}"></url-param-sk> |
| <url-param-sk name="time_end" value="{{_time_end}}"></url-param-sk> |
| <div class="container"> |
| <div class="layout horizontal flex"> |
| <div class="flex"><h2>Job Search</h2></div> |
| <paper-icon-button id="expandButton" icon="icons:arrow-drop-up" on-tap="_toggleExpand"></paper-icon-button> |
| </div> |
| <iron-collapse id="controls" opened> |
| <div class="layout horizontal"> |
| <div class="controlColumn"> |
| <div class="timeSelect">Start: <date-time-picker-sk format="ISO" value="{{_time_start}}"></date-time-picker-sk></div> |
| <div class="timeSelect">End: <date-time-picker-sk format="ISO" value="{{_time_end}}"></date-time-picker-sk></div> |
| <autocomplete-input-sk value="{{repo}}" label="Repo" autocomplete="[[recent_repos]]"></autocomplete-input-sk> |
| <autocomplete-input-sk value="{{revision}}" label="Revision"></autocomplete-input-sk> |
| <autocomplete-input-sk value="{{server}}" label="Server" autocomplete="[[recent_servers]]"></autocomplete-input-sk> |
| <paper-input value="{{issue}}" label="Issue"></paper-input> |
| </div> |
| <div class="controlColumn"> |
| <autocomplete-input-sk value="{{patchset}}" label="Patchset"></autocomplete-input-sk> |
| <autocomplete-input-sk value="{{buildbucket_build_id}}" label="Buildbucket Build ID"></autocomplete-input-sk> |
| <div><paper-checkbox checked="{{isForce}}">Is Force</paper-input></div> |
| <autocomplete-input-sk value="{{name}}" label="Name"></autocomplete-input-sk> |
| <autocomplete-input-sk value="{{status}}" label="Status" autocomplete="[[valid_statuses]]"></autocomplete-input-sk> |
| <div class="searchButton layout vertical center"> |
| <paper-button on-tap="_search" class="searchButton bg-redorange" raised>Search</paper-button> |
| </div> |
| </div> |
| </div> |
| </iron-collapse> |
| </div> |
| <template is="dom-if" if="[[_showResults]]"> |
| <div class="container"> |
| <div class="table"> |
| <div class="tr"> |
| <div class="th">ID</div> |
| <div class="th">Name</div> |
| <div class="th">Repo</div> |
| <div class="th">Revision</div> |
| <div class="th">Codereview Link</div> |
| <div class="th">Status</div> |
| <div class="th">Manually Triggered</div> |
| <template is="dom-if" if="[[_editRights]]"> |
| <div class="th"> |
| <paper-button raised class="cancelButton bg-purple" on-tap="_cancelAll">Cancel All</paper-button> |
| </div> |
| </template> |
| </div> |
| <template is="dom-repeat" items="[[_results]]" as="job" initialCount="20"> |
| <div class="tr"> |
| <div class="td"><a href$="[[_jobLink(job)]]">[[job.id]]</a></div> |
| <div class="td">[[job.name]]</div> |
| <div class="td">[[job.repo]]</div> |
| <div class="td"><a href$="[[_revisionLink(job)]]" target="_blank">[[job.revision]]</a></div> |
| <div class="td"> |
| <template is="dom-if" if="[[_isTryJob(job)]]"> |
| <a href$="[[_codeReviewLink(job)]]" target="_blank">[[_codeReviewLink(job)]]</a> |
| </template> |
| </div> |
| <div class="td" style$="background-color:[[_statusColor(job)]]">[[_statusText(job)]]</div> |
| <div class="td">[[job.isForce]]</div> |
| <template is="dom-if" if="[[_editRights]]"> |
| <div class="td"> |
| <template is="dom-if" if="[[_showCancel(job)]]"> |
| <paper-button raised class="cancelButton bg-purple" on-tap="_cancelJob" data-id$="[[job.id]]">Cancel</paper-button> |
| </template> |
| </div> |
| </template> |
| </div> |
| </template> |
| </div> |
| </div> |
| </template> |
| </template> |
| <script> |
| (function(){ |
| var iconUp = "icons:arrow-drop-up"; |
| var iconDown = "icons:arrow-drop-down"; |
| var jobStatusToTextColor = { |
| "": ["in progress", "rgb(248, 230, 180)"], |
| "SUCCESS": ["succeeded", "rgb(209, 228, 188)"], |
| "FAILURE": ["failed", "rgb(217, 95, 2)"], |
| "MISHAP": ["mishap", "rgb(117, 112, 179)"], |
| "CANCELED": ["canceled", "rgb(117, 112, 179)"], |
| }; |
| |
| Polymer({ |
| is: "job-search-sk", |
| |
| properties: { |
| recent_repos: { |
| type: Array, |
| }, |
| recent_servers: { |
| type: Array, |
| }, |
| valid_statues: { |
| type: Array, |
| }, |
| |
| // Private. |
| _editRights: { |
| type: Boolean, |
| }, |
| _results: { |
| type: Array, |
| value: function() { return []; }, |
| }, |
| _showResults: { |
| type: Boolean, |
| }, |
| _dropdownButtonIcon: { |
| type: String, |
| }, |
| }, |
| |
| ready: function() { |
| sk.Login.then(function(status) { |
| var editRights = false; |
| var email = status["Email"]; |
| if (email && email.endsWith("@google.com")) { |
| editRights = true; |
| } |
| this.set("_editRights", editRights) |
| }.bind(this)); |
| |
| // Only perform the initial search if URL params were specified for at |
| // least one search term. |
| if (window.location.search) { |
| this._search(); |
| } |
| }, |
| |
| _search: function() { |
| var url = "/json/jobs/search" + window.location.search; |
| console.log("Searching Jobs from " + url); |
| this.set("_showResults", false); |
| this._toggleExpand(); |
| sk.get(url).then(JSON.parse).then(function(json) { |
| this.set("_results", json); |
| this.set("_showResults", true); |
| }.bind(this)).catch(sk.errorMessage); |
| }, |
| |
| _toggleExpand: function() { |
| if (this.$.expandButton.icon === iconUp) { |
| this.$.expandButton.icon = iconDown; |
| } else { |
| this.$.expandButton.icon = iconUp; |
| } |
| this.$.controls.toggle(); |
| }, |
| |
| _showCancel: function(job) { |
| return job.status === ""; |
| }, |
| |
| _cancel: function(jobId) { |
| var url = "/json/job/" + jobId + "/cancel"; |
| console.log("Canceling Job: " + url); |
| sk.post(url).then(JSON.parse).then(function(json) { |
| var idx = this._results.findIndex(function (job) { |
| return job.id === jobId; |
| }); |
| if (idx != -1) { |
| this.splice("_results", idx, 1, json); |
| } |
| }.bind(this)).catch(sk.errorMessage); |
| }, |
| |
| _cancelJob: function(e) { |
| this._cancel(e.target.dataset.id); |
| }, |
| |
| _cancelAll: function() { |
| var toCancel = this._results.filter(function(job) { |
| return job.status === ""; |
| }); |
| if (!toCancel.length) { |
| sk.errorMessage("No unfinished jobs to cancel!"); |
| return; |
| } |
| for (var i = 0; i < toCancel.length; i++) { |
| this._cancel(toCancel[i].id); |
| } |
| }, |
| |
| _codeReviewLink: function(job) { |
| return job.server + "/c/" + job.issue + "/" + job.patchset; |
| }, |
| |
| _isTryJob: function(job) { |
| return job.server != "" && job.issue != "" && job.patchset != ""; |
| }, |
| |
| _jobLink: function(job) { |
| return "/job/" + job.id; |
| }, |
| |
| _revisionLink: function(job) { |
| // This assumes we use Gitiles, but that's a safe assumption for now. |
| return job.repo + "/+/" + job.revision; |
| }, |
| |
| _statusText: function(job) { |
| if (!job || job.status === undefined || job.status === null) { |
| return "unknown"; |
| } |
| var textColor = jobStatusToTextColor[job.status]; |
| if (!textColor || textColor.length != 2) { |
| return "unknown"; |
| } |
| return textColor[0]; |
| }, |
| |
| _statusColor: function(job) { |
| if (!job || job.status === undefined || job.status === null) { |
| return "rgb(255, 255, 255)"; |
| } |
| var textColor = jobStatusToTextColor[job.status]; |
| if (!textColor || textColor.length != 2) { |
| return "rgb(255, 255, 255)"; |
| } |
| return textColor[1]; |
| }, |
| }); |
| })(); |
| </script> |
| </dom-module> |