| <!-- |
| The <patch-sk> custom element declaration. Allows entering a CL in the form of |
| https://codereview.chromium.org/1344993003 (or just the CL number) to retrieve a patch from that |
| CL. Alternatively, allows entering a patch manually in an expanding text area. |
| |
| Attributes: |
| patchType: Specifies the project for the patch. Must be set. Supported values include |
| "chromium" and "skia". See also encodeCLData in |
| ct/go/ctfe/chromium_perf/chromium_perf.go. |
| cl: Raw value of the CL input. Does not notify. |
| clDescription: Human-readable description of the CL. Notifies. |
| patch: The patch, either retrieved from the CL or manually entered/modified. Notifies. |
| |
| Events: |
| None. |
| |
| Methods: |
| validate(): Checks that patch is valid based on cl. If not, shows an error toast and returns |
| false. Otherwise returns true. |
| --> |
| |
| <dom-module id="patch-sk"> |
| <style> |
| paper-input { |
| width: 25em; |
| } |
| |
| .long-field { |
| width: 40em; |
| } |
| |
| td.cl-label { |
| vertical-align: middle; |
| } |
| |
| .cl-detail-container { |
| position: relative; |
| text-align: center; |
| height: 100px; |
| min-width: 200px; |
| max-width: 300px; |
| } |
| |
| .loading-cl-spinner { |
| margin: auto; |
| vertical-align: middle; |
| } |
| |
| .cl-detail { |
| position: absolute; |
| top: 0px; |
| left: 0px; |
| text-align: start; |
| } |
| |
| .cl-error { |
| color: red; |
| } |
| </style> |
| <template> |
| <table> |
| <tr> |
| <td class="cl-label">CL:</td> |
| <td> |
| <paper-input value="{{cl}}" label="Please paste a complete Gerrit URL" no-label-float></paper-input> |
| <a href="javascript:void(0);" id="patch_expander"> |
| <iron-icon icon="{{patchExpanderIcon(patchOpened)}}"></iron-icon> |
| Specify patch manually</a> |
| </td> |
| <td> |
| <div class="cl-detail-container"> |
| <div class="loading-cl-spinner"> |
| <paper-spinner active="{{loadingClDetail}}" |
| alt="Loading CL details"></paper-spinner> |
| </div> |
| <div class="cl-detail"> |
| <a href$="{{clUrl(clData)}}" target="_blank">{{formatClData(clData)}}</a> |
| <span class="cl-error">{{formatClError(clData)}}</span> |
| </div> |
| </td> |
| </tr> |
| <tr> |
| <td colspan="3"> |
| <div class="long-field"> |
| <iron-collapse id="patch_collapse" opened="{{patchOpened}}"> |
| <iron-autogrow-textarea class="long-field" rows=5 max-rows=20 bind-value="{{patch}}"> |
| </iron-autogrow-textarea> |
| </iron-collapse> |
| </div> |
| </td> |
| </tr> |
| </table> |
| </template> |
| <script> |
| Polymer({ |
| is: "patch-sk", |
| properties: { |
| patchType: String, |
| cl: { |
| type: String, |
| value: "", |
| observer: "clChanged", |
| }, |
| clData: Object, |
| loadingClDetail: { |
| type: Boolean, |
| value: false, |
| }, |
| clDescription: { |
| type: String, |
| computed: "formatClDescription(clData)", |
| notify: true, |
| }, |
| patchOpened: { |
| type: Boolean, |
| value: false, |
| }, |
| patch: { |
| type: String, |
| notify: true, |
| }, |
| }, |
| |
| ready: function() { |
| var that = this; |
| this.$.patch_expander.addEventListener('click', function(e) { |
| that.$.patch_collapse.toggle(); |
| }); |
| }, |
| |
| clChanged: function(newValue) { |
| if (!newValue || newValue.length < 3) { |
| this.clData = null; |
| this.loadingClDetail = false; |
| return; |
| } |
| this.loadingClDetail = true; |
| var params = {cl: newValue}; |
| sk.post("/_/cl_data?" + sk.query.fromObject(params)).then(JSON.parse).then(function (json) { |
| if (this.cl == newValue) { |
| if (json.cl) { |
| this.clData = json; |
| var patch = this.clData[this.patchType + "_patch"]; |
| if (!patch) { |
| this.clData = {error: {response: "This is not a " + this.patchType + " CL."}}; |
| } else { |
| this.patch = patch; |
| } |
| } else { |
| this.clData = null; |
| } |
| this.loadingClDetail = false; |
| } |
| }.bind(this)).catch(function (err) { |
| if (this.cl == newValue) { |
| this.clData = {error: err}; |
| this.loadingClDetail = false; |
| } |
| }.bind(this)); |
| }, |
| |
| clUrl: function(clData) { |
| if (clData && !clData.error) { |
| return clData.url; |
| } |
| return "javascript:void(0);" |
| }, |
| |
| formatClData: function(clData) { |
| if (clData && !clData.error) { |
| return clData.subject + |
| " (modified " + ctfe.getFormattedTimestamp(clData.modified) + ")"; |
| } |
| return ""; |
| }, |
| |
| formatClError: function(clData) { |
| if (clData && clData.error) { |
| return clData.error.response; |
| } |
| return ""; |
| }, |
| |
| formatClDescription: function(clData) { |
| if (clData && !clData.error) { |
| return this.clUrl(clData) + " (" + clData.subject + ")"; |
| } |
| return "" |
| }, |
| |
| patchExpanderIcon: function(patchOpened) { |
| if (patchOpened) { |
| return "expand-less"; |
| } else { |
| return "expand-more"; |
| } |
| }, |
| |
| validate: function() { |
| if (this.cl && !this.clData) { |
| sk.errorMessage("Unable to load " + this.patchType + " CL " + this.cl + |
| ". Please specify patches manually."); |
| return false; |
| } |
| if (this.cl && !this.patch) { |
| sk.errorMessage("Unable to fetch " + this.patchType + " patch from CL " + this.cl + |
| ". Please specify patches manually."); |
| return false; |
| } |
| return true; |
| }, |
| }); |
| </script> |
| |
| </dom-module> |