blob: 225d8b3a9be432e747edc6aefd77e73dd3424ff9 [file] [log] [blame]
// 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';
var COMMIT_MESSAGE_PATH = '/COMMIT_MSG';
Polymer({
is: 'gr-file-list',
properties: {
patchRange: Object,
patchNum: String,
changeNum: String,
comments: Object,
drafts: Object,
revisions: Object,
projectConfig: Object,
topMargin: Number,
selectedIndex: {
type: Number,
notify: true,
},
keyEventTarget: {
type: Object,
value: function() { return document.body; },
},
change: Object,
_files: {
type: Array,
observer: '_filesChanged',
},
_loggedIn: {
type: Boolean,
value: false,
},
_reviewed: {
type: Array,
value: function() { return []; },
},
_diffPrefs: Object,
_userPrefs: Object,
_localPrefs: Object,
_showInlineDiffs: Boolean,
},
behaviors: [
Gerrit.KeyboardShortcutBehavior,
],
reload: function() {
if (!this.changeNum || !this.patchRange.patchNum) {
return Promise.resolve();
}
this._collapseAllDiffs();
var promises = [];
var _this = this;
promises.push(this._getFiles().then(function(files) {
_this._files = files;
}));
promises.push(this._getLoggedIn().then(function(loggedIn) {
return _this._loggedIn = loggedIn;
}).then(function(loggedIn) {
if (!loggedIn) { return; }
return _this._getReviewedFiles().then(function(reviewed) {
_this._reviewed = reviewed;
});
}));
this._localPrefs = this.$.storage.getPreferences();
promises.push(this._getDiffPreferences().then(function(prefs) {
this._diffPrefs = prefs;
}.bind(this)));
promises.push(this._getPreferences().then(function(prefs) {
this._userPrefs = prefs;
}.bind(this)));
},
get diffs() {
return Polymer.dom(this.root).querySelectorAll('gr-diff');
},
_getDiffPreferences: function() {
return this.$.restAPI.getDiffPreferences();
},
_getPreferences: function() {
return this.$.restAPI.getPreferences();
},
_computePatchSets: function(revisions) {
var patchNums = [];
for (var commit in revisions) {
patchNums.push(revisions[commit]._number);
}
return patchNums.sort(function(a, b) { return a - b; });
},
_computePatchSetDisabled: function(patchNum, currentPatchNum) {
return parseInt(patchNum, 10) >= parseInt(currentPatchNum, 10);
},
_computePatchSetSelected: function(patchNum, basePatchNum) {
return parseInt(patchNum, 10) === parseInt(basePatchNum, 10);
},
_handlePatchChange: function(e) {
this.set('patchRange.basePatchNum', Polymer.dom(e).rootTarget.value);
page.show('/c/' + encodeURIComponent(this.changeNum) + '/' +
encodeURIComponent(this._patchRangeStr(this.patchRange)));
},
_forEachDiff: function(fn) {
var diffs = this.diffs;
for (var i = 0; i < diffs.length; i++) {
fn(diffs[i]);
}
},
_expandAllDiffs: function(e) {
this._showInlineDiffs = true;
this._forEachDiff(function(diff) {
diff.hidden = false;
diff.reload();
});
if (e && e.target) {
e.target.blur();
}
},
_collapseAllDiffs: function(e) {
this._showInlineDiffs = false;
this._forEachDiff(function(diff) {
diff.hidden = true;
});
this.$.cursor.handleDiffUpdate();
if (e && e.target) {
e.target.blur();
}
},
_computeCommentsString: function(comments, patchNum, path) {
return this._computeCountString(comments, patchNum, path, 'comment');
},
_computeDraftsString: function(drafts, patchNum, path) {
return this._computeCountString(drafts, patchNum, path, 'draft');
},
_computeCountString: function(comments, patchNum, path, noun) {
if (!comments) { return ''; }
var patchComments = (comments[path] || []).filter(function(c) {
return parseInt(c.patch_set, 10) === parseInt(patchNum, 10);
});
var num = patchComments.length;
if (num === 0) { return ''; }
return num + ' ' + noun + (num > 1 ? 's' : '');
},
_computeReviewed: function(file, _reviewed) {
return _reviewed.indexOf(file.__path) !== -1;
},
_handleReviewedChange: function(e) {
var path = Polymer.dom(e).rootTarget.getAttribute('data-path');
var index = this._reviewed.indexOf(path);
var reviewed = index !== -1;
if (reviewed) {
this.splice('_reviewed', index, 1);
} else {
this.push('_reviewed', path);
}
this._saveReviewedState(path, !reviewed).catch(function(err) {
alert('Couldn’t change file review status. Check the console ' +
'and contact the PolyGerrit team for assistance.');
throw err;
}.bind(this));
},
_saveReviewedState: function(path, reviewed) {
return this.$.restAPI.saveFileReviewed(this.changeNum,
this.patchRange.patchNum, path, reviewed);
},
_getLoggedIn: function() {
return this.$.restAPI.getLoggedIn();
},
_getReviewedFiles: function() {
return this.$.restAPI.getReviewedFiles(this.changeNum,
this.patchRange.patchNum);
},
_getFiles: function() {
return this.$.restAPI.getChangeFilesAsSpeciallySortedArray(
this.changeNum, this.patchRange);
},
_handleKey: function(e) {
if (this.shouldSupressKeyboardShortcut(e)) { return; }
switch (e.keyCode) {
case 37: // left
if (e.shiftKey && this._showInlineDiffs) {
e.preventDefault();
this.$.cursor.moveLeft();
}
break;
case 39: // right
if (e.shiftKey && this._showInlineDiffs) {
e.preventDefault();
this.$.cursor.moveRight();
}
break;
case 73: // 'i'
if (!e.shiftKey) { return; }
e.preventDefault();
this._toggleInlineDiffs();
break;
case 40: // down
case 74: // 'j'
e.preventDefault();
if (this._showInlineDiffs) {
this.$.cursor.moveDown();
} else {
this.selectedIndex =
Math.min(this._files.length - 1, this.selectedIndex + 1);
this._scrollToSelectedFile();
}
break;
case 38: // up
case 75: // 'k'
e.preventDefault();
if (this._showInlineDiffs) {
this.$.cursor.moveUp();
} else {
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
this._scrollToSelectedFile();
}
break;
case 67: // 'c'
var isRangeSelected = this.diffs.some(function(diff) {
return diff.isRangeSelected();
}, this);
if (this._showInlineDiffs && !isRangeSelected) {
e.preventDefault();
this._addDraftAtTarget();
}
break;
case 219: // '['
e.preventDefault();
this._openSelectedFile(this._files.length - 1);
break;
case 221: // ']'
e.preventDefault();
this._openSelectedFile(0);
break;
case 13: // <enter>
case 79: // 'o'
e.preventDefault();
if (this._showInlineDiffs) {
this._openCursorFile();
} else {
this._openSelectedFile();
}
break;
case 78: // 'n'
if (this._showInlineDiffs) {
e.preventDefault();
if (e.shiftKey) {
this.$.cursor.moveToNextCommentThread();
} else {
this.$.cursor.moveToNextChunk();
}
}
break;
case 80: // 'p'
if (this._showInlineDiffs) {
e.preventDefault();
if (e.shiftKey) {
this.$.cursor.moveToPreviousCommentThread();
} else {
this.$.cursor.moveToPreviousChunk();
}
}
break;
case 65: // 'a'
if (e.shiftKey) { // Hide left diff.
e.preventDefault();
this._forEachDiff(function(diff) {
diff.toggleLeftDiff();
});
}
break;
}
},
_toggleInlineDiffs: function() {
if (this._showInlineDiffs) {
this._collapseAllDiffs();
} else {
this._expandAllDiffs();
}
},
_openCursorFile: function() {
var diff = this.$.cursor.getTargetDiffElement();
page.show(this._computeDiffURL(diff.changeNum, diff.patchRange,
diff.path));
},
_openSelectedFile: function(opt_index) {
if (opt_index != null) {
this.selectedIndex = opt_index;
}
page.show(this._computeDiffURL(this.changeNum, this.patchRange,
this._files[this.selectedIndex].__path));
},
_addDraftAtTarget: function() {
var diff = this.$.cursor.getTargetDiffElement();
var target = this.$.cursor.getTargetLineElement();
if (diff && target) {
diff.addDraftAtLine(target);
}
},
_scrollToSelectedFile: function() {
var el = this.$$('.row[selected]');
var top = 0;
for (var node = el; node; node = node.offsetParent) {
top += node.offsetTop;
}
// Don't scroll if it's already in view.
if (top > window.pageYOffset + this.topMargin &&
top < window.pageYOffset + window.innerHeight - el.clientHeight) {
return;
}
window.scrollTo(0, top - document.body.clientHeight / 2);
},
_computeFileSelected: function(index, selectedIndex) {
return index === selectedIndex;
},
_computeFileStatus: function(status) {
return status || 'M';
},
_computeDiffURL: function(changeNum, patchRange, path) {
return '/c/' +
encodeURIComponent(changeNum) +
'/' +
encodeURIComponent(this._patchRangeStr(patchRange)) +
'/' +
path;
},
_patchRangeStr: function(patchRange) {
return patchRange.basePatchNum !== 'PARENT' ?
patchRange.basePatchNum + '..' + patchRange.patchNum :
patchRange.patchNum + '';
},
_computeFileDisplayName: function(path) {
return path === COMMIT_MESSAGE_PATH ? 'Commit message' : path;
},
_computeClass: function(baseClass, path) {
var classes = [baseClass];
if (path === COMMIT_MESSAGE_PATH) {
classes.push('invisible');
}
return classes.join(' ');
},
_filesChanged: function() {
this.async(function() {
var diffElements = Polymer.dom(this.root).querySelectorAll('gr-diff');
// Overwrite the cursor's list of diffs:
this.$.cursor.splice.apply(this.$.cursor,
['diffs', 0, this.$.cursor.diffs.length].concat(diffElements));
}.bind(this), 1);
},
});
})();