|  | /** | 
|  | * @license | 
|  | * Copyright (C) 2016 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | * http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  | (function() { | 
|  | 'use strict'; | 
|  |  | 
|  | const CHANGE_SIZE = { | 
|  | XS: 10, | 
|  | SMALL: 50, | 
|  | MEDIUM: 250, | 
|  | LARGE: 1000, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @appliesMixin Gerrit.BaseUrlMixin | 
|  | * @appliesMixin Gerrit.ChangeTableMixin | 
|  | * @appliesMixin Gerrit.PathListMixin | 
|  | * @appliesMixin Gerrit.RESTClientMixin | 
|  | * @appliesMixin Gerrit.URLEncodingMixin | 
|  | * @extends Polymer.Element | 
|  | */ | 
|  | class GrChangeListItem extends Polymer.mixinBehaviors( [ | 
|  | Gerrit.BaseUrlBehavior, | 
|  | Gerrit.ChangeTableBehavior, | 
|  | Gerrit.PathListBehavior, | 
|  | Gerrit.RESTClientBehavior, | 
|  | Gerrit.URLEncodingBehavior, | 
|  | ], Polymer.GestureEventListeners( | 
|  | Polymer.LegacyElementMixin( | 
|  | Polymer.Element))) { | 
|  | static get is() { return 'gr-change-list-item'; } | 
|  |  | 
|  | static get properties() { | 
|  | return { | 
|  | visibleChangeTableColumns: Array, | 
|  | labelNames: { | 
|  | type: Array, | 
|  | }, | 
|  |  | 
|  | /** @type {?} */ | 
|  | change: Object, | 
|  | changeURL: { | 
|  | type: String, | 
|  | computed: '_computeChangeURL(change)', | 
|  | }, | 
|  | statuses: { | 
|  | type: Array, | 
|  | computed: 'changeStatuses(change)', | 
|  | }, | 
|  | showStar: { | 
|  | type: Boolean, | 
|  | value: false, | 
|  | }, | 
|  | showNumber: Boolean, | 
|  | _changeSize: { | 
|  | type: String, | 
|  | computed: '_computeChangeSize(change)', | 
|  | }, | 
|  | _dynamicCellEndpoints: { | 
|  | type: Array, | 
|  | }, | 
|  | }; | 
|  | } | 
|  |  | 
|  | /** @override */ | 
|  | attached() { | 
|  | super.attached(); | 
|  | Gerrit.awaitPluginsLoaded().then(() => { | 
|  | this._dynamicCellEndpoints = Gerrit._endpoints.getDynamicEndpoints( | 
|  | 'change-list-item-cell'); | 
|  | }); | 
|  | } | 
|  |  | 
|  | _computeChangeURL(change) { | 
|  | return Gerrit.Nav.getUrlForChange(change); | 
|  | } | 
|  |  | 
|  | _computeLabelTitle(change, labelName) { | 
|  | const label = change.labels[labelName]; | 
|  | if (!label) { return 'Label not applicable'; } | 
|  | const significantLabel = label.rejected || label.approved || | 
|  | label.disliked || label.recommended; | 
|  | if (significantLabel && significantLabel.name) { | 
|  | return labelName + '\nby ' + significantLabel.name; | 
|  | } | 
|  | return labelName; | 
|  | } | 
|  |  | 
|  | _computeLabelClass(change, labelName) { | 
|  | const label = change.labels[labelName]; | 
|  | // Mimic a Set. | 
|  | const classes = { | 
|  | cell: true, | 
|  | label: true, | 
|  | }; | 
|  | if (label) { | 
|  | if (label.approved) { | 
|  | classes['u-green'] = true; | 
|  | } | 
|  | if (label.value == 1) { | 
|  | classes['u-monospace'] = true; | 
|  | classes['u-green'] = true; | 
|  | } else if (label.value == -1) { | 
|  | classes['u-monospace'] = true; | 
|  | classes['u-red'] = true; | 
|  | } | 
|  | if (label.rejected) { | 
|  | classes['u-red'] = true; | 
|  | } | 
|  | } else { | 
|  | classes['u-gray-background'] = true; | 
|  | } | 
|  | return Object.keys(classes).sort() | 
|  | .join(' '); | 
|  | } | 
|  |  | 
|  | _computeLabelValue(change, labelName) { | 
|  | const label = change.labels[labelName]; | 
|  | if (!label) { return ''; } | 
|  | if (label.approved) { | 
|  | return '✓'; | 
|  | } | 
|  | if (label.rejected) { | 
|  | return '✕'; | 
|  | } | 
|  | if (label.value > 0) { | 
|  | return '+' + label.value; | 
|  | } | 
|  | if (label.value < 0) { | 
|  | return label.value; | 
|  | } | 
|  | return ''; | 
|  | } | 
|  |  | 
|  | _computeRepoUrl(change) { | 
|  | return Gerrit.Nav.getUrlForProjectChanges(change.project, true, | 
|  | change.internalHost); | 
|  | } | 
|  |  | 
|  | _computeRepoBranchURL(change) { | 
|  | return Gerrit.Nav.getUrlForBranch(change.branch, change.project, null, | 
|  | change.internalHost); | 
|  | } | 
|  |  | 
|  | _computeTopicURL(change) { | 
|  | if (!change.topic) { return ''; } | 
|  | return Gerrit.Nav.getUrlForTopic(change.topic, change.internalHost); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Computes the display string for the project column. If there is a host | 
|  | * specified in the change detail, the string will be prefixed with it. | 
|  | * | 
|  | * @param {!Object} change | 
|  | * @param {string=} truncate whether or not the project name should be | 
|  | *     truncated. If this value is truthy, the name will be truncated. | 
|  | * @return {string} | 
|  | */ | 
|  | _computeRepoDisplay(change, truncate) { | 
|  | if (!change || !change.project) { return ''; } | 
|  | let str = ''; | 
|  | if (change.internalHost) { str += change.internalHost + '/'; } | 
|  | str += truncate ? this.truncatePath(change.project, 2) : change.project; | 
|  | return str; | 
|  | } | 
|  |  | 
|  | _computeSizeTooltip(change) { | 
|  | if (change.insertions + change.deletions === 0 || | 
|  | isNaN(change.insertions + change.deletions)) { | 
|  | return 'Size unknown'; | 
|  | } else { | 
|  | return `+${change.insertions}, -${change.deletions}`; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * TShirt sizing is based on the following paper: | 
|  | * http://dirkriehle.com/wp-content/uploads/2008/09/hicss-42-csdistr-final-web.pdf | 
|  | */ | 
|  | _computeChangeSize(change) { | 
|  | const delta = change.insertions + change.deletions; | 
|  | if (isNaN(delta) || delta === 0) { | 
|  | return null; // Unknown | 
|  | } | 
|  | if (delta < CHANGE_SIZE.XS) { | 
|  | return 'XS'; | 
|  | } else if (delta < CHANGE_SIZE.SMALL) { | 
|  | return 'S'; | 
|  | } else if (delta < CHANGE_SIZE.MEDIUM) { | 
|  | return 'M'; | 
|  | } else if (delta < CHANGE_SIZE.LARGE) { | 
|  | return 'L'; | 
|  | } else { | 
|  | return 'XL'; | 
|  | } | 
|  | } | 
|  |  | 
|  | toggleReviewed() { | 
|  | const newVal = !this.change.reviewed; | 
|  | this.set('change.reviewed', newVal); | 
|  | this.dispatchEvent(new CustomEvent('toggle-reviewed', { | 
|  | bubbles: true, | 
|  | composed: true, | 
|  | detail: {change: this.change, reviewed: newVal}, | 
|  | })); | 
|  | } | 
|  | } | 
|  |  | 
|  | customElements.define(GrChangeListItem.is, GrChangeListItem); | 
|  | })(); |