
These tags are preserved by the Closure compiler and vulcanize in order to serve the license notices embedded in the outputs. In a standalone Gerrit server, these license are also covered in the LICENSES.txt served with the documentation. When serving PG assets from a CDN, it's less obvious what the corresponding LICENSES.txt file is, since the CDN is not directly linked to a running Gerrit server. Safer to embed the licenses in the assets themselves. Change-Id: Id1add1451fad1baa7916882a6bda02c326ccc988
251 lines
8.4 KiB
JavaScript
251 lines
8.4 KiB
JavaScript
/**
|
|
* @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';
|
|
|
|
// Maximum length for patch set descriptions.
|
|
const PATCH_DESC_MAX_LENGTH = 500;
|
|
|
|
/**
|
|
* Fired when the patch range changes
|
|
*
|
|
* @event patch-range-change
|
|
*
|
|
* @property {string} patchNum
|
|
* @property {string} basePatchNum
|
|
*/
|
|
|
|
Polymer({
|
|
is: 'gr-patch-range-select',
|
|
|
|
properties: {
|
|
availablePatches: Array,
|
|
_baseDropdownContent: {
|
|
type: Object,
|
|
computed: '_computeBaseDropdownContent(availablePatches, patchNum,' +
|
|
'_sortedRevisions, changeComments, revisionInfo)',
|
|
},
|
|
_patchDropdownContent: {
|
|
type: Object,
|
|
computed: '_computePatchDropdownContent(availablePatches,' +
|
|
'basePatchNum, _sortedRevisions, changeComments)',
|
|
},
|
|
changeNum: String,
|
|
changeComments: Object,
|
|
/** @type {{ meta_a: !Array, meta_b: !Array}} */
|
|
filesWeblinks: Object,
|
|
patchNum: String,
|
|
basePatchNum: String,
|
|
revisions: Object,
|
|
revisionInfo: Object,
|
|
_sortedRevisions: Array,
|
|
},
|
|
|
|
observers: [
|
|
'_updateSortedRevisions(revisions.*)',
|
|
],
|
|
|
|
behaviors: [Gerrit.PatchSetBehavior],
|
|
|
|
_computeBaseDropdownContent(availablePatches, patchNum, _sortedRevisions,
|
|
changeComments, revisionInfo) {
|
|
const parentCounts = revisionInfo.getParentCountMap();
|
|
const currentParentCount = parentCounts.hasOwnProperty(patchNum) ?
|
|
parentCounts[patchNum] : 1;
|
|
const maxParents = revisionInfo.getMaxParents();
|
|
const isMerge = currentParentCount > 1;
|
|
|
|
const dropdownContent = [];
|
|
for (const basePatch of availablePatches) {
|
|
const basePatchNum = basePatch.num;
|
|
const entry = this._createDropdownEntry(basePatchNum, 'Patchset ',
|
|
_sortedRevisions, changeComments);
|
|
dropdownContent.push(Object.assign({}, entry, {
|
|
disabled: this._computeLeftDisabled(
|
|
basePatch.num, patchNum, _sortedRevisions),
|
|
}));
|
|
}
|
|
|
|
dropdownContent.push({
|
|
text: isMerge ? 'Auto Merge' : 'Base',
|
|
value: 'PARENT',
|
|
});
|
|
|
|
for (let idx = 0; isMerge && idx < maxParents; idx++) {
|
|
dropdownContent.push({
|
|
disabled: idx >= currentParentCount,
|
|
triggerText: `Parent ${idx + 1}`,
|
|
text: `Parent ${idx + 1}`,
|
|
mobileText: `Parent ${idx + 1}`,
|
|
value: -(idx + 1),
|
|
});
|
|
}
|
|
|
|
return dropdownContent;
|
|
},
|
|
|
|
_computeMobileText(patchNum, changeComments, revisions) {
|
|
return `${patchNum}` +
|
|
`${this._computePatchSetCommentsString(changeComments, patchNum)}` +
|
|
`${this._computePatchSetDescription(revisions, patchNum, true)}`;
|
|
},
|
|
|
|
_computePatchDropdownContent(availablePatches, basePatchNum,
|
|
_sortedRevisions, changeComments) {
|
|
const dropdownContent = [];
|
|
for (const patch of availablePatches) {
|
|
const patchNum = patch.num;
|
|
const entry = this._createDropdownEntry(
|
|
patchNum, patchNum === 'edit' ? '' : 'Patchset ', _sortedRevisions,
|
|
changeComments);
|
|
dropdownContent.push(Object.assign({}, entry, {
|
|
disabled: this._computeRightDisabled(basePatchNum, patchNum,
|
|
_sortedRevisions),
|
|
}));
|
|
}
|
|
return dropdownContent;
|
|
},
|
|
|
|
_createDropdownEntry(patchNum, prefix, sortedRevisions, changeComments) {
|
|
const entry = {
|
|
triggerText: `${prefix}${patchNum}`,
|
|
text: `${prefix}${patchNum}` +
|
|
`${this._computePatchSetCommentsString(
|
|
changeComments, patchNum)}`,
|
|
mobileText: this._computeMobileText(patchNum, changeComments,
|
|
sortedRevisions),
|
|
bottomText: `${this._computePatchSetDescription(
|
|
sortedRevisions, patchNum)}`,
|
|
value: patchNum,
|
|
};
|
|
const date = this._computePatchSetDate(sortedRevisions, patchNum);
|
|
if (date) {
|
|
entry['date'] = date;
|
|
}
|
|
return entry;
|
|
},
|
|
|
|
_updateSortedRevisions(revisionsRecord) {
|
|
const revisions = revisionsRecord.base;
|
|
this._sortedRevisions = this.sortRevisions(Object.values(revisions));
|
|
},
|
|
|
|
/**
|
|
* The basePatchNum should always be <= patchNum -- because sortedRevisions
|
|
* is sorted in reverse order (higher patchset nums first), invalid base
|
|
* patch nums have an index greater than the index of patchNum.
|
|
* @param {number|string} basePatchNum The possible base patch num.
|
|
* @param {number|string} patchNum The current selected patch num.
|
|
* @param {!Array} sortedRevisions
|
|
*/
|
|
_computeLeftDisabled(basePatchNum, patchNum, sortedRevisions) {
|
|
return this.findSortedIndex(basePatchNum, sortedRevisions) <=
|
|
this.findSortedIndex(patchNum, sortedRevisions);
|
|
},
|
|
|
|
/**
|
|
* The basePatchNum should always be <= patchNum -- because sortedRevisions
|
|
* is sorted in reverse order (higher patchset nums first), invalid patch
|
|
* nums have an index greater than the index of basePatchNum.
|
|
*
|
|
* In addition, if the current basePatchNum is 'PARENT', all patchNums are
|
|
* valid.
|
|
*
|
|
* If the curent basePatchNum is a parent index, then only patches that have
|
|
* at least that many parents are valid.
|
|
*
|
|
* @param {number|string} basePatchNum The current selected base patch num.
|
|
* @param {number|string} patchNum The possible patch num.
|
|
* @param {!Array} sortedRevisions
|
|
* @return {boolean}
|
|
*/
|
|
_computeRightDisabled(basePatchNum, patchNum, sortedRevisions) {
|
|
if (this.patchNumEquals(basePatchNum, 'PARENT')) { return false; }
|
|
|
|
if (this.isMergeParent(basePatchNum)) {
|
|
// Note: parent indices use 1-offset.
|
|
return this.revisionInfo.getParentCount(patchNum) <
|
|
this.getParentIndex(basePatchNum);
|
|
}
|
|
|
|
return this.findSortedIndex(basePatchNum, sortedRevisions) <=
|
|
this.findSortedIndex(patchNum, sortedRevisions);
|
|
},
|
|
|
|
|
|
_computePatchSetCommentsString(changeComments, patchNum) {
|
|
if (!changeComments) { return; }
|
|
|
|
const commentCount = changeComments.computeCommentCount(patchNum);
|
|
const commentString = GrCountStringFormatter.computePluralString(
|
|
commentCount, 'comment');
|
|
|
|
const unresolvedCount = changeComments.computeUnresolvedNum(patchNum);
|
|
const unresolvedString = GrCountStringFormatter.computeString(
|
|
unresolvedCount, 'unresolved');
|
|
|
|
if (!commentString.length && !unresolvedString.length) {
|
|
return '';
|
|
}
|
|
|
|
return ` (${commentString}` +
|
|
// Add a comma + space if both comments and unresolved
|
|
(commentString && unresolvedString ? ', ' : '') +
|
|
`${unresolvedString})`;
|
|
},
|
|
|
|
/**
|
|
* @param {!Array} revisions
|
|
* @param {number|string} patchNum
|
|
* @param {boolean=} opt_addFrontSpace
|
|
*/
|
|
_computePatchSetDescription(revisions, patchNum, opt_addFrontSpace) {
|
|
const rev = this.getRevisionByPatchNum(revisions, patchNum);
|
|
return (rev && rev.description) ?
|
|
(opt_addFrontSpace ? ' ' : '') +
|
|
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
|
},
|
|
|
|
/**
|
|
* @param {!Array} revisions
|
|
* @param {number|string} patchNum
|
|
*/
|
|
_computePatchSetDate(revisions, patchNum) {
|
|
const rev = this.getRevisionByPatchNum(revisions, patchNum);
|
|
return rev ? rev.created : undefined;
|
|
},
|
|
|
|
/**
|
|
* Catches value-change events from the patchset dropdowns and determines
|
|
* whether or not a patch change event should be fired.
|
|
*/
|
|
_handlePatchChange(e) {
|
|
const detail = {patchNum: this.patchNum, basePatchNum: this.basePatchNum};
|
|
const target = Polymer.dom(e).localTarget;
|
|
|
|
if (target === this.$.patchNumDropdown) {
|
|
detail.patchNum = e.detail.value;
|
|
} else {
|
|
detail.basePatchNum = e.detail.value;
|
|
}
|
|
|
|
this.dispatchEvent(
|
|
new CustomEvent('patch-range-change', {detail, bubbles: false}));
|
|
},
|
|
});
|
|
})();
|