/** * @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 */ 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, }, }; } 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); })();