Merge changes I488afd17,I053f3ee4
* changes: Enable prefer-object-spread rule Move GrReviewerUpdatesParser to class
This commit is contained in:
@@ -109,6 +109,7 @@ module.exports = {
|
||||
"prefer-const": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-object-spread": "error",
|
||||
"quote-props": ["error", "consistent-as-needed"],
|
||||
"semi": ["error", "always"],
|
||||
"template-curly-spacing": "error",
|
||||
|
||||
@@ -68,7 +68,7 @@ suite('gr-group tests', () => {
|
||||
});
|
||||
|
||||
test('default values with external group', done => {
|
||||
const groupExternal = Object.assign({}, group);
|
||||
const groupExternal = {...group};
|
||||
groupExternal.id = 'external-group-id';
|
||||
groupStub.restore();
|
||||
groupStub = sinon.stub(
|
||||
|
||||
@@ -182,10 +182,10 @@ class GrRepoAccess extends GestureEventListeners(
|
||||
// Keep a copy of the original inherit from values separate from
|
||||
// the ones data bound to gr-autocomplete, so the original value
|
||||
// can be restored if the user cancels.
|
||||
this._inheritsFrom = res.inherits_from ? Object.assign({},
|
||||
res.inherits_from) : null;
|
||||
this._originalInheritsFrom = res.inherits_from ? Object.assign({},
|
||||
res.inherits_from) : null;
|
||||
this._inheritsFrom = res.inherits_from ? ({
|
||||
...res.inherits_from}) : null;
|
||||
this._originalInheritsFrom = res.inherits_from ? ({
|
||||
...res.inherits_from}) : null;
|
||||
// Initialize the filter value so when the user clicks edit, the
|
||||
// current value appears. If there is no parent repo, it is
|
||||
// initialized as an empty string.
|
||||
@@ -282,7 +282,7 @@ class GrRepoAccess extends GestureEventListeners(
|
||||
}
|
||||
// Restore inheritFrom.
|
||||
if (this._inheritsFrom) {
|
||||
this._inheritsFrom = Object.assign({}, this._originalInheritsFrom);
|
||||
this._inheritsFrom = {...this._originalInheritsFrom};
|
||||
this._inheritFromFilter = this._inheritsFrom.name;
|
||||
}
|
||||
for (const key of Object.keys(this._local)) {
|
||||
|
||||
@@ -259,7 +259,7 @@ class GrRuleEditor extends GestureEventListeners(
|
||||
// gr-permission will take care of removing rules that were added but
|
||||
// unsaved. We need to keep the added bit for the filter.
|
||||
if (this.rule.value.added) { return; }
|
||||
this.set('rule.value', Object.assign({}, this._originalRuleValues));
|
||||
this.set('rule.value', {...this._originalRuleValues});
|
||||
this._deleted = false;
|
||||
delete this.rule.value.deleted;
|
||||
delete this.rule.value.modified;
|
||||
@@ -274,7 +274,7 @@ class GrRuleEditor extends GestureEventListeners(
|
||||
}
|
||||
|
||||
_setOriginalRuleValues(value) {
|
||||
this._originalRuleValues = Object.assign({}, value);
|
||||
this._originalRuleValues = {...value};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -858,7 +858,7 @@ class GrChangeActions extends GestureEventListeners(
|
||||
if (!approval) {
|
||||
return null;
|
||||
}
|
||||
const action = Object.assign({}, QUICK_APPROVE_ACTION);
|
||||
const action = {...QUICK_APPROVE_ACTION};
|
||||
action.label = approval.label + approval.score;
|
||||
const review = {
|
||||
drafts: 'PUBLISH_ALL_REVISIONS',
|
||||
@@ -899,7 +899,7 @@ class GrChangeActions extends GestureEventListeners(
|
||||
actions[a].label = this._getActionLabel(actions[a]);
|
||||
|
||||
// Triggers a re-render by ensuring object inequality.
|
||||
result.push(Object.assign({}, actions[a]));
|
||||
result.push({...actions[a]});
|
||||
});
|
||||
|
||||
let additionalActions = (additionalActionsChangeRecord &&
|
||||
@@ -909,7 +909,7 @@ class GrChangeActions extends GestureEventListeners(
|
||||
.map(a => {
|
||||
a.__primary = primaryActionKeys.includes(a.__key);
|
||||
// Triggers a re-render by ensuring object inequality.
|
||||
return Object.assign({}, a);
|
||||
return {...a};
|
||||
});
|
||||
return result.concat(additionalActions).concat(pluginActions);
|
||||
}
|
||||
|
||||
@@ -175,9 +175,10 @@ suite('gr-change-actions tests', () => {
|
||||
});
|
||||
|
||||
test('getActionDetails', () => {
|
||||
element.revisionActions = Object.assign({
|
||||
element.revisionActions = {
|
||||
'plugin~action': {},
|
||||
}, element.revisionActions);
|
||||
...element.revisionActions,
|
||||
};
|
||||
assert.isUndefined(element.getActionDetails('rubbish'));
|
||||
assert.strictEqual(element.revisionActions['plugin~action'],
|
||||
element.getActionDetails('plugin~action'));
|
||||
|
||||
@@ -173,7 +173,7 @@ class GrChangeMetadata extends GestureEventListeners(
|
||||
}
|
||||
|
||||
_labelsChanged(labels) {
|
||||
this.labels = Object.assign({}, labels) || null;
|
||||
this.labels = ({...labels}) || null;
|
||||
}
|
||||
|
||||
_changeChanged(change) {
|
||||
|
||||
@@ -869,7 +869,7 @@ class GrChangeView extends KeyboardShortcutMixin(
|
||||
// because the paths could contain dots in them. A new object must be
|
||||
// created to satisfy Polymer’s dirty checking.
|
||||
// https://github.com/Polymer/polymer/issues/3127
|
||||
const diffDrafts = Object.assign({}, this._diffDrafts);
|
||||
const diffDrafts = {...this._diffDrafts};
|
||||
if (!diffDrafts[draft.path]) {
|
||||
diffDrafts[draft.path] = [draft];
|
||||
this._diffDrafts = diffDrafts;
|
||||
@@ -917,7 +917,7 @@ class GrChangeView extends KeyboardShortcutMixin(
|
||||
// because the paths could contain dots in them. A new object must be
|
||||
// created to satisfy Polymer’s dirty checking.
|
||||
// https://github.com/Polymer/polymer/issues/3127
|
||||
const diffDrafts = Object.assign({}, this._diffDrafts);
|
||||
const diffDrafts = {...this._diffDrafts};
|
||||
diffDrafts[draft.path].splice(index, 1);
|
||||
if (diffDrafts[draft.path].length === 0) {
|
||||
delete diffDrafts[draft.path];
|
||||
|
||||
@@ -457,11 +457,9 @@ suite('gr-change-view tests', () => {
|
||||
const queryMap = new Map();
|
||||
queryMap.set('tab', PrimaryTab.FINDINGS);
|
||||
// view is required
|
||||
element.params = Object.assign(
|
||||
{
|
||||
view: GerritNav.View.CHANGE,
|
||||
},
|
||||
element.params, {queryMap});
|
||||
element.params = {
|
||||
view: GerritNav.View.CHANGE,
|
||||
...element.params, queryMap};
|
||||
flush(() => {
|
||||
assert.equal(element._activeTabs[0], PrimaryTab.FINDINGS);
|
||||
done();
|
||||
@@ -473,11 +471,9 @@ suite('gr-change-view tests', () => {
|
||||
const queryMap = new Map();
|
||||
queryMap.set('tab', 'random');
|
||||
// view is required
|
||||
element.params = Object.assign(
|
||||
{
|
||||
view: GerritNav.View.CHANGE,
|
||||
},
|
||||
element.params, {queryMap});
|
||||
element.params = {
|
||||
view: GerritNav.View.CHANGE,
|
||||
...element.params, queryMap};
|
||||
flush(() => {
|
||||
assert.equal(element._activeTabs[0], PrimaryTab.FILES);
|
||||
done();
|
||||
|
||||
@@ -133,7 +133,7 @@ class GrConfirmCherrypickDialog extends GestureEventListeners(
|
||||
}
|
||||
|
||||
updateStatus(change, status) {
|
||||
this._statuses = Object.assign({}, this._statuses, {[change.id]: status});
|
||||
this._statuses = {...this._statuses, [change.id]: status};
|
||||
}
|
||||
|
||||
_computeStatus(change, statuses) {
|
||||
|
||||
@@ -1073,7 +1073,7 @@ class GrFileList extends KeyboardShortcutMixin(
|
||||
if (loading || !changeComments) { return; }
|
||||
|
||||
const commentedPaths = changeComments.getPaths(patchRange);
|
||||
const files = Object.assign({}, filesByPath);
|
||||
const files = {...filesByPath};
|
||||
addUnmodifiedFiles(files, commentedPaths);
|
||||
const reviewedSet = new Set(reviewed || []);
|
||||
for (const filePath in files) {
|
||||
|
||||
@@ -73,8 +73,8 @@ suite('gr-upload-help-dialog tests', () => {
|
||||
assert.isUndefined(
|
||||
element._computeFetchCommand(testRev, '', 'badscheme'));
|
||||
|
||||
const rev = Object.assign({}, testRev);
|
||||
rev.fetch = Object.assign({}, testRev.fetch, {nocmds: {commands: {}}});
|
||||
const rev = {...testRev};
|
||||
rev.fetch = {...testRev.fetch, nocmds: {commands: {}}};
|
||||
assert.isUndefined(
|
||||
element._computeFetchCommand(rev, '', 'nocmds'));
|
||||
|
||||
|
||||
@@ -758,10 +758,10 @@ export const GerritNav = {
|
||||
.filter(section => (attentionEnabled || !section.attentionSetOnly))
|
||||
.filter(section => (assigneeEnabled || !section.assigneeOnly))
|
||||
.filter(section => (user === 'self' || !section.selfOnly))
|
||||
.map(section => Object.assign({}, section, {
|
||||
name: section.name,
|
||||
query: section.query.replace(USER_PLACEHOLDER_PATTERN, user),
|
||||
}));
|
||||
.map(section => {
|
||||
return {...section, name: section.name,
|
||||
query: section.query.replace(USER_PLACEHOLDER_PATTERN, user)};
|
||||
});
|
||||
return {title, sections};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -141,7 +141,7 @@ class GrApplyFixDialog extends GestureEventListeners(
|
||||
|
||||
overridePartialPrefs(prefs) {
|
||||
// generate a smaller gr-diff than fullscreen for dialog
|
||||
return Object.assign({}, prefs, {line_length: 50});
|
||||
return {...prefs, line_length: 50};
|
||||
}
|
||||
|
||||
onCancel(e) {
|
||||
|
||||
@@ -380,7 +380,7 @@ class ChangeComments {
|
||||
for (const file of Object.keys(comments)) {
|
||||
const commentsForFile = [];
|
||||
for (const comment of comments[file]) {
|
||||
commentsForFile.push(Object.assign({__path: file}, comment));
|
||||
commentsForFile.push({__path: file, ...comment});
|
||||
}
|
||||
commentArr = commentArr.concat(commentsForFile);
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ class GrDiffBuilderElement extends GestureEventListeners(
|
||||
return;
|
||||
}
|
||||
|
||||
const localPrefs = Object.assign({}, prefs);
|
||||
const localPrefs = {...prefs};
|
||||
if (this.path === COMMIT_MSG_PATH) {
|
||||
// override line_length for commit msg the same way as
|
||||
// in gr-diff
|
||||
|
||||
@@ -729,7 +729,7 @@ class GrDiffHost extends GestureEventListeners(
|
||||
isOnParent: comment.side === 'PARENT',
|
||||
};
|
||||
if (comment.range) {
|
||||
newThread.range = Object.assign({}, comment.range);
|
||||
newThread.range = {...comment.range};
|
||||
}
|
||||
threads.push(newThread);
|
||||
}
|
||||
|
||||
@@ -509,14 +509,20 @@ class GrDiffProcessor extends GestureEventListeners(
|
||||
|
||||
if (chunk.ab) {
|
||||
result.push(...this._splitAtChunkEnds(chunk.ab, chunkEnds)
|
||||
.map(({lines, keyLocation}) =>
|
||||
Object.assign({}, chunk, {ab: lines, keyLocation})));
|
||||
.map(({lines, keyLocation}) => {
|
||||
return {
|
||||
...chunk,
|
||||
ab: lines,
|
||||
keyLocation,
|
||||
};
|
||||
}));
|
||||
} else if (chunk.common) {
|
||||
const aChunks = this._splitAtChunkEnds(chunk.a, chunkEnds);
|
||||
const bChunks = this._splitAtChunkEnds(chunk.b, chunkEnds);
|
||||
result.push(...aChunks.map(({lines, keyLocation}, i) =>
|
||||
Object.assign(
|
||||
{}, chunk, {a: lines, b: bChunks[i].lines, keyLocation})));
|
||||
result.push(...aChunks.map(({lines, keyLocation}, i) => {
|
||||
return {
|
||||
...chunk, a: lines, b: bChunks[i].lines, keyLocation};
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -390,7 +390,7 @@ class GrDiffView extends KeyboardShortcutMixin(
|
||||
changeNum, patchRange).then(changeFiles => {
|
||||
if (!changeFiles) return;
|
||||
const commentedPaths = changeComments.getPaths(patchRange);
|
||||
const files = Object.assign({}, changeFiles);
|
||||
const files = {...changeFiles};
|
||||
addUnmodifiedFiles(files, commentedPaths);
|
||||
this._files = {
|
||||
sortedFileList: Object.keys(files).sort(specialFilePathCompare),
|
||||
|
||||
@@ -880,7 +880,7 @@ class GrDiff extends GestureEventListeners(
|
||||
*/
|
||||
_getBypassPrefs() {
|
||||
if (this._safetyBypass !== null) {
|
||||
return Object.assign({}, this.prefs, {context: this._safetyBypass});
|
||||
return {...this.prefs, context: this._safetyBypass};
|
||||
}
|
||||
return this.prefs;
|
||||
}
|
||||
|
||||
@@ -76,14 +76,14 @@ suite('gr-diff tests', () => {
|
||||
|
||||
test('line limit with line_wrapping', () => {
|
||||
element = basicFixture.instantiate();
|
||||
element.prefs = Object.assign({}, MINIMAL_PREFS, {line_wrapping: true});
|
||||
element.prefs = {...MINIMAL_PREFS, line_wrapping: true};
|
||||
flushAsynchronousOperations();
|
||||
assert.equal(getComputedStyleValue('--line-limit', element), '80ch');
|
||||
});
|
||||
|
||||
test('line limit without line_wrapping', () => {
|
||||
element = basicFixture.instantiate();
|
||||
element.prefs = Object.assign({}, MINIMAL_PREFS, {line_wrapping: false});
|
||||
element.prefs = {...MINIMAL_PREFS, line_wrapping: false};
|
||||
flushAsynchronousOperations();
|
||||
assert.isNotOk(getComputedStyleValue('--line-limit', element));
|
||||
});
|
||||
@@ -225,7 +225,7 @@ suite('gr-diff tests', () => {
|
||||
element.path = 'file.txt';
|
||||
|
||||
element.$.diffBuilder._builder = element.$.diffBuilder._getDiffBuilder(
|
||||
getMockDiffResponse(), Object.assign({}, MINIMAL_PREFS));
|
||||
getMockDiffResponse(), {...MINIMAL_PREFS});
|
||||
|
||||
// No thread groups.
|
||||
assert.isNotOk(element._getThreadGroupForLine(contentEl));
|
||||
@@ -693,22 +693,22 @@ suite('gr-diff tests', () => {
|
||||
|
||||
test('change in preferences re-renders diff', () => {
|
||||
sinon.stub(element, '_renderDiffTable');
|
||||
element.prefs = Object.assign(
|
||||
{}, MINIMAL_PREFS, {time_format: 'HHMM_12'});
|
||||
element.prefs = {
|
||||
...MINIMAL_PREFS, time_format: 'HHMM_12'};
|
||||
element.flushDebouncer('renderDiffTable');
|
||||
assert.isTrue(element._renderDiffTable.called);
|
||||
});
|
||||
|
||||
test('adding/removing property in preferences re-renders diff', () => {
|
||||
const stub = sinon.stub(element, '_renderDiffTable');
|
||||
const newPrefs1 = Object.assign({}, MINIMAL_PREFS,
|
||||
{line_wrapping: true});
|
||||
const newPrefs1 = {...MINIMAL_PREFS,
|
||||
line_wrapping: true};
|
||||
element.prefs = newPrefs1;
|
||||
element.flushDebouncer('renderDiffTable');
|
||||
assert.isTrue(element._renderDiffTable.called);
|
||||
stub.reset();
|
||||
|
||||
const newPrefs2 = Object.assign({}, newPrefs1);
|
||||
const newPrefs2 = {...newPrefs1};
|
||||
delete newPrefs2.line_wrapping;
|
||||
element.prefs = newPrefs2;
|
||||
element.flushDebouncer('renderDiffTable');
|
||||
@@ -719,8 +719,8 @@ suite('gr-diff tests', () => {
|
||||
'noRenderOnPrefsChange', () => {
|
||||
sinon.stub(element, '_renderDiffTable');
|
||||
element.noRenderOnPrefsChange = true;
|
||||
element.prefs = Object.assign(
|
||||
{}, MINIMAL_PREFS, {time_format: 'HHMM_12'});
|
||||
element.prefs = {
|
||||
...MINIMAL_PREFS, time_format: 'HHMM_12'};
|
||||
element.flushDebouncer('renderDiffTable');
|
||||
assert.isFalse(element._renderDiffTable.called);
|
||||
});
|
||||
@@ -787,7 +787,7 @@ suite('gr-diff tests', () => {
|
||||
});
|
||||
|
||||
test('large render w/ context = 10', done => {
|
||||
element.prefs = Object.assign({}, MINIMAL_PREFS, {context: 10});
|
||||
element.prefs = {...MINIMAL_PREFS, context: 10};
|
||||
function rendered() {
|
||||
assert.isTrue(renderStub.called);
|
||||
assert.isFalse(element._showWarning);
|
||||
@@ -799,7 +799,7 @@ suite('gr-diff tests', () => {
|
||||
});
|
||||
|
||||
test('large render w/ whole file and bypass', done => {
|
||||
element.prefs = Object.assign({}, MINIMAL_PREFS, {context: -1});
|
||||
element.prefs = {...MINIMAL_PREFS, context: -1};
|
||||
element._safetyBypass = 10;
|
||||
function rendered() {
|
||||
assert.isTrue(renderStub.called);
|
||||
@@ -812,7 +812,7 @@ suite('gr-diff tests', () => {
|
||||
});
|
||||
|
||||
test('large render w/ whole file and no bypass', done => {
|
||||
element.prefs = Object.assign({}, MINIMAL_PREFS, {context: -1});
|
||||
element.prefs = {...MINIMAL_PREFS, context: -1};
|
||||
function rendered() {
|
||||
assert.isFalse(renderStub.called);
|
||||
assert.isTrue(element._showWarning);
|
||||
@@ -1028,7 +1028,7 @@ suite('gr-diff tests', () => {
|
||||
}
|
||||
setupSampleDiff({content});
|
||||
assertDiffTableWithContent();
|
||||
element.diff = Object.assign({}, element.diff);
|
||||
element.diff = {...element.diff};
|
||||
// immediately cleaned up
|
||||
assert.equal(element.$.diffTable.innerHTML, '');
|
||||
element._renderDiffTable();
|
||||
|
||||
@@ -115,10 +115,8 @@ class GrPatchRangeSelect extends GestureEventListeners(
|
||||
const basePatchNum = basePatch.num;
|
||||
const entry = this._createDropdownEntry(basePatchNum, 'Patchset ',
|
||||
_sortedRevisions, changeComments, this._getShaForPatch(basePatch));
|
||||
dropdownContent.push(Object.assign({}, entry, {
|
||||
disabled: this._computeLeftDisabled(
|
||||
basePatch.num, patchNum, _sortedRevisions),
|
||||
}));
|
||||
dropdownContent.push({...entry, disabled: this._computeLeftDisabled(
|
||||
basePatch.num, patchNum, _sortedRevisions)});
|
||||
}
|
||||
|
||||
dropdownContent.push({
|
||||
@@ -163,10 +161,11 @@ class GrPatchRangeSelect extends GestureEventListeners(
|
||||
const entry = this._createDropdownEntry(
|
||||
patchNum, patchNum === 'edit' ? '' : 'Patchset ', _sortedRevisions,
|
||||
changeComments, this._getShaForPatch(patch));
|
||||
dropdownContent.push(Object.assign({}, entry, {
|
||||
disabled: this._computeRightDisabled(basePatchNum, patchNum,
|
||||
_sortedRevisions),
|
||||
}));
|
||||
dropdownContent.push({
|
||||
...entry,
|
||||
disabled: this._computeRightDisabled(
|
||||
basePatchNum, patchNum, _sortedRevisions),
|
||||
});
|
||||
}
|
||||
return dropdownContent;
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ class GrRangedCommentLayer extends GestureEventListeners(
|
||||
.map(range => {
|
||||
// Make a copy, so that the normalization below does not mess with
|
||||
// our map.
|
||||
range = Object.assign({}, range);
|
||||
range = {...range};
|
||||
range.end = range.end === -1 ? line.text.length : range.end;
|
||||
|
||||
// Normalize invalid ranges where the start is after the end but the
|
||||
|
||||
@@ -51,7 +51,7 @@ suite('gr-editor-view tests', () => {
|
||||
suite('_paramsChanged', () => {
|
||||
test('incorrect view returns immediately', () => {
|
||||
element._paramsChanged(
|
||||
Object.assign({}, mockParams, {view: GerritNav.View.DIFF}));
|
||||
{...mockParams, view: GerritNav.View.DIFF});
|
||||
assert.notOk(element._changeNum);
|
||||
});
|
||||
|
||||
@@ -64,7 +64,7 @@ suite('gr-editor-view tests', () => {
|
||||
});
|
||||
|
||||
const promises = element._paramsChanged(
|
||||
Object.assign({}, mockParams, {view: GerritNav.View.EDIT}));
|
||||
{...mockParams, view: GerritNav.View.EDIT});
|
||||
|
||||
flushAsynchronousOperations();
|
||||
assert.equal(element._changeNum, mockParams.changeNum);
|
||||
|
||||
@@ -86,7 +86,7 @@ class GrRegistrationDialog extends GestureEventListeners(
|
||||
// Using Object.assign here allows preservation of the default values
|
||||
// supplied in the value generating function of this._account, unless
|
||||
// they are overridden by properties in the account from the response.
|
||||
this._account = Object.assign({}, this._account, account);
|
||||
this._account = {...this._account, ...account};
|
||||
});
|
||||
|
||||
const loadConfig = this.$.restAPI.getConfig().then(config => {
|
||||
|
||||
@@ -168,7 +168,7 @@ class GrAccountList extends GestureEventListeners(
|
||||
let itemTypeAdded = 'unknown';
|
||||
if (item.account) {
|
||||
const account =
|
||||
Object.assign({}, item.account, {_pendingAdd: true});
|
||||
{...item.account, _pendingAdd: true};
|
||||
this.push('accounts', account);
|
||||
itemTypeAdded = 'account';
|
||||
} else if (item.group) {
|
||||
@@ -176,8 +176,8 @@ class GrAccountList extends GestureEventListeners(
|
||||
this.pendingConfirmation = item;
|
||||
return;
|
||||
}
|
||||
const group = Object.assign({}, item.group,
|
||||
{_pendingAdd: true, _group: true});
|
||||
const group = {...item.group,
|
||||
_pendingAdd: true, _group: true};
|
||||
this.push('accounts', group);
|
||||
itemTypeAdded = 'group';
|
||||
} else if (this.allowAnyInput) {
|
||||
@@ -204,8 +204,8 @@ class GrAccountList extends GestureEventListeners(
|
||||
}
|
||||
|
||||
confirmGroup(group) {
|
||||
group = Object.assign(
|
||||
{}, group, {confirmed: true, _pendingAdd: true, _group: true});
|
||||
group = {
|
||||
...group, confirmed: true, _pendingAdd: true, _group: true};
|
||||
this.push('accounts', group);
|
||||
this.pendingConfirmation = null;
|
||||
}
|
||||
|
||||
@@ -453,10 +453,8 @@ class GrComment extends KeyboardShortcutMixin(GestureEventListeners(
|
||||
* @return {!Object}
|
||||
*/
|
||||
_getEventPayload(opt_mixin) {
|
||||
return Object.assign({}, opt_mixin, {
|
||||
comment: this.comment,
|
||||
patchNum: this.patchNum,
|
||||
});
|
||||
return {...opt_mixin, comment: this.comment,
|
||||
patchNum: this.patchNum};
|
||||
}
|
||||
|
||||
_fireSave() {
|
||||
|
||||
@@ -590,13 +590,11 @@ suite('gr-comment tests', () => {
|
||||
});
|
||||
|
||||
test('robot comment layout', done => {
|
||||
const comment = Object.assign({
|
||||
robot_id: 'happy_robot_id',
|
||||
const comment = {robot_id: 'happy_robot_id',
|
||||
url: '/robot/comment',
|
||||
author: {
|
||||
name: 'Happy Robot',
|
||||
},
|
||||
}, element.comment);
|
||||
}, ...element.comment};
|
||||
element.comment = comment;
|
||||
element.collapsed = false;
|
||||
flush(() => {
|
||||
@@ -627,12 +625,10 @@ suite('gr-comment tests', () => {
|
||||
});
|
||||
|
||||
test('author name fallback to email', done => {
|
||||
const comment = Object.assign({
|
||||
url: '/robot/comment',
|
||||
const comment = {url: '/robot/comment',
|
||||
author: {
|
||||
email: 'test@test.com',
|
||||
},
|
||||
}, element.comment);
|
||||
}, ...element.comment};
|
||||
element.comment = comment;
|
||||
element.collapsed = false;
|
||||
flush(() => {
|
||||
|
||||
@@ -39,7 +39,7 @@ suite('gr-hovercard-account tests', () => {
|
||||
new Promise(resolve => { '2'; })
|
||||
);
|
||||
|
||||
element.account = Object.assign({}, ACCOUNT);
|
||||
element.account = {...ACCOUNT};
|
||||
element._config = {
|
||||
change: {enable_attention_set: true},
|
||||
};
|
||||
@@ -95,7 +95,7 @@ suite('gr-hovercard-account tests', () => {
|
||||
});
|
||||
|
||||
test('account status is displayed', () => {
|
||||
element.account = Object.assign({status: 'OOO'}, ACCOUNT);
|
||||
element.account = {status: 'OOO', ...ACCOUNT};
|
||||
flushAsynchronousOperations();
|
||||
assert.equal(element.shadowRoot.querySelector('.status .value').innerText,
|
||||
'OOO');
|
||||
|
||||
@@ -155,13 +155,11 @@ class GrJsApiInterface extends GestureEventListeners(
|
||||
//
|
||||
// assign on getter with existing property will report error
|
||||
// see Issue: 12286
|
||||
const change = Object.assign({}, detail.change, {
|
||||
get mergeable() {
|
||||
console.warn('Accessing change.mergeable from SHOW_CHANGE is ' +
|
||||
const change = {...detail.change, get mergeable() {
|
||||
console.warn('Accessing change.mergeable from SHOW_CHANGE is ' +
|
||||
'deprecated! Use info.mergeable instead.');
|
||||
return detail.info && detail.info.mergeable;
|
||||
},
|
||||
});
|
||||
return detail.info && detail.info.mergeable;
|
||||
}};
|
||||
const patchNum = detail.patchNum;
|
||||
const info = detail.info;
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ suite('gr-js-api-interface tests', () => {
|
||||
_number: 42,
|
||||
revisions: {def: {_number: 2}, abc: {_number: 1}},
|
||||
};
|
||||
const expectedChange = Object.assign({mergeable: false}, testChange);
|
||||
const expectedChange = {mergeable: false, ...testChange};
|
||||
plugin.on(element.EventType.SHOW_CHANGE, throwErrFn);
|
||||
plugin.on(element.EventType.SHOW_CHANGE, (change, revision, info) => {
|
||||
assert.deepEqual(change, expectedChange);
|
||||
|
||||
@@ -38,7 +38,7 @@ GrEtagDecorator.prototype.getOptions = function(url, opt_options) {
|
||||
if (!etag) {
|
||||
return opt_options;
|
||||
}
|
||||
const options = Object.assign({}, opt_options);
|
||||
const options = {...opt_options};
|
||||
options.headers = options.headers || new Headers();
|
||||
options.headers.set('If-None-Match', this._etags.get(url));
|
||||
return options;
|
||||
|
||||
@@ -748,7 +748,7 @@ class GrRestApiInterface extends GestureEventListeners(
|
||||
if (cachedAccount) {
|
||||
// Replace object in cache with new object to force UI updates.
|
||||
this._cache.set('/accounts/self/detail',
|
||||
Object.assign({}, cachedAccount, obj));
|
||||
{...cachedAccount, ...obj});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,212 +18,220 @@
|
||||
import {parseDate} from '../../../utils/date-util.js';
|
||||
import {MessageTag} from '../../../constants/constants.js';
|
||||
|
||||
/** @constructor */
|
||||
export function GrReviewerUpdatesParser(change) {
|
||||
this.result = Object.assign({}, change);
|
||||
this._lastState = {};
|
||||
}
|
||||
const MESSAGE_REVIEWERS_THRESHOLD_MILLIS = 500;
|
||||
const REVIEWER_UPDATE_THRESHOLD_MILLIS = 6000;
|
||||
|
||||
GrReviewerUpdatesParser.parse = function(change) {
|
||||
if (!change ||
|
||||
!change.messages ||
|
||||
!change.reviewer_updates ||
|
||||
!change.reviewer_updates.length) {
|
||||
return change;
|
||||
export class GrReviewerUpdatesParser {
|
||||
constructor(change) {
|
||||
this.result = {...change};
|
||||
this._lastState = {};
|
||||
this._batch = null;
|
||||
this._updateItems = null;
|
||||
}
|
||||
const parser = new GrReviewerUpdatesParser(change);
|
||||
parser._filterRemovedMessages();
|
||||
parser._groupUpdates();
|
||||
parser._formatUpdates();
|
||||
parser._advanceUpdates();
|
||||
return parser.result;
|
||||
};
|
||||
|
||||
GrReviewerUpdatesParser.MESSAGE_REVIEWERS_THRESHOLD_MILLIS = 500;
|
||||
GrReviewerUpdatesParser.REVIEWER_UPDATE_THRESHOLD_MILLIS = 6000;
|
||||
|
||||
GrReviewerUpdatesParser.prototype.result = null;
|
||||
GrReviewerUpdatesParser.prototype._batch = null;
|
||||
GrReviewerUpdatesParser.prototype._updateItems = null;
|
||||
GrReviewerUpdatesParser.prototype._lastState = null;
|
||||
|
||||
/**
|
||||
* Removes messages that describe removed reviewers, since reviewer_updates
|
||||
* are used.
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._filterRemovedMessages = function() {
|
||||
this.result.messages = this.result.messages
|
||||
.filter(message => message.tag !== MessageTag.TAG_DELETE_REVIEWER);
|
||||
};
|
||||
|
||||
/**
|
||||
* Is a part of _groupUpdates(). Creates a new batch of updates.
|
||||
*
|
||||
* @param {Object} update instance of ReviewerUpdateInfo
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._startBatch = function(update) {
|
||||
this._updateItems = [];
|
||||
return {
|
||||
author: update.updated_by,
|
||||
date: update.updated,
|
||||
type: 'REVIEWER_UPDATE',
|
||||
tag: MessageTag.TAG_REVIEWER_UPDATE,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Is a part of _groupUpdates(). Validates current batch:
|
||||
* - filters out updates that don't change reviewer state.
|
||||
* - updates current reviewer state.
|
||||
*
|
||||
* @param {Object} update instance of ReviewerUpdateInfo
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._completeBatch = function(update) {
|
||||
const items = [];
|
||||
for (const accountId in this._updateItems) {
|
||||
if (!this._updateItems.hasOwnProperty(accountId)) continue;
|
||||
const updateItem = this._updateItems[accountId];
|
||||
if (this._lastState[accountId] !== updateItem.state) {
|
||||
this._lastState[accountId] = updateItem.state;
|
||||
items.push(updateItem);
|
||||
}
|
||||
/**
|
||||
* Removes messages that describe removed reviewers, since reviewer_updates
|
||||
* are used.
|
||||
*/
|
||||
_filterRemovedMessages() {
|
||||
this.result.messages = this.result.messages.filter(
|
||||
message => message.tag !== MessageTag.TAG_DELETE_REVIEWER
|
||||
);
|
||||
}
|
||||
if (items.length) {
|
||||
this._batch.updates = items;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Groups reviewer updates. Sequential updates are grouped if:
|
||||
* - They were performed within short timeframe (6 seconds)
|
||||
* - Made by the same person
|
||||
* - Non-change updates are discarded within a group
|
||||
* - Groups with no-change updates are discarded (eg CC -> CC)
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._groupUpdates = function() {
|
||||
const updates = this.result.reviewer_updates;
|
||||
const newUpdates = updates.reduce((newUpdates, update) => {
|
||||
if (!this._batch) {
|
||||
this._batch = this._startBatch(update);
|
||||
}
|
||||
const updateDate = parseDate(update.updated).getTime();
|
||||
const batchUpdateDate = parseDate(this._batch.date).getTime();
|
||||
const reviewerId = update.reviewer._account_id.toString();
|
||||
if (updateDate - batchUpdateDate >
|
||||
GrReviewerUpdatesParser.REVIEWER_UPDATE_THRESHOLD_MILLIS ||
|
||||
update.updated_by._account_id !== this._batch.author._account_id) {
|
||||
// Next sequential update should form new group.
|
||||
this._completeBatch();
|
||||
if (this._batch.updates && this._batch.updates.length) {
|
||||
newUpdates.push(this._batch);
|
||||
}
|
||||
this._batch = this._startBatch(update);
|
||||
}
|
||||
this._updateItems[reviewerId] = {
|
||||
reviewer: update.reviewer,
|
||||
state: update.state,
|
||||
/**
|
||||
* Is a part of _groupUpdates(). Creates a new batch of updates.
|
||||
*
|
||||
* @param {Object} update instance of ReviewerUpdateInfo
|
||||
*/
|
||||
_startBatch(update) {
|
||||
this._updateItems = [];
|
||||
return {
|
||||
author: update.updated_by,
|
||||
date: update.updated,
|
||||
type: 'REVIEWER_UPDATE',
|
||||
tag: MessageTag.TAG_REVIEWER_UPDATE,
|
||||
};
|
||||
if (this._lastState[reviewerId]) {
|
||||
this._updateItems[reviewerId].prev_state = this._lastState[reviewerId];
|
||||
}
|
||||
return newUpdates;
|
||||
}, []);
|
||||
this._completeBatch();
|
||||
if (this._batch.updates && this._batch.updates.length) {
|
||||
newUpdates.push(this._batch);
|
||||
}
|
||||
this.result.reviewer_updates = newUpdates;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates update message for reviewer state change.
|
||||
*
|
||||
* @param {string} prev previous reviewer state.
|
||||
* @param {string} state current reviewer state.
|
||||
* @return {string}
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._getUpdateMessage = function(prev, state) {
|
||||
if (prev === 'REMOVED' || !prev) {
|
||||
return 'Added to ' + state.toLowerCase() + ': ';
|
||||
} else if (state === 'REMOVED') {
|
||||
if (prev) {
|
||||
return 'Removed from ' + prev.toLowerCase() + ': ';
|
||||
/**
|
||||
* Is a part of _groupUpdates(). Validates current batch:
|
||||
* - filters out updates that don't change reviewer state.
|
||||
* - updates current reviewer state.
|
||||
*
|
||||
* @param {Object} update instance of ReviewerUpdateInfo
|
||||
*/
|
||||
_completeBatch(update) {
|
||||
const items = [];
|
||||
for (const accountId in this._updateItems) {
|
||||
if (!this._updateItems.hasOwnProperty(accountId)) continue;
|
||||
const updateItem = this._updateItems[accountId];
|
||||
if (this._lastState[accountId] !== updateItem.state) {
|
||||
this._lastState[accountId] = updateItem.state;
|
||||
items.push(updateItem);
|
||||
}
|
||||
}
|
||||
if (items.length) {
|
||||
this._batch.updates = items;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups reviewer updates. Sequential updates are grouped if:
|
||||
* - They were performed within short timeframe (6 seconds)
|
||||
* - Made by the same person
|
||||
* - Non-change updates are discarded within a group
|
||||
* - Groups with no-change updates are discarded (eg CC -> CC)
|
||||
*/
|
||||
_groupUpdates() {
|
||||
const updates = this.result.reviewer_updates;
|
||||
const newUpdates = updates.reduce((newUpdates, update) => {
|
||||
if (!this._batch) {
|
||||
this._batch = this._startBatch(update);
|
||||
}
|
||||
const updateDate = parseDate(update.updated).getTime();
|
||||
const batchUpdateDate = parseDate(this._batch.date).getTime();
|
||||
const reviewerId = update.reviewer._account_id.toString();
|
||||
if (
|
||||
updateDate - batchUpdateDate >
|
||||
REVIEWER_UPDATE_THRESHOLD_MILLIS ||
|
||||
update.updated_by._account_id !== this._batch.author._account_id
|
||||
) {
|
||||
// Next sequential update should form new group.
|
||||
this._completeBatch();
|
||||
if (this._batch.updates && this._batch.updates.length) {
|
||||
newUpdates.push(this._batch);
|
||||
}
|
||||
this._batch = this._startBatch(update);
|
||||
}
|
||||
this._updateItems[reviewerId] = {
|
||||
reviewer: update.reviewer,
|
||||
state: update.state,
|
||||
};
|
||||
if (this._lastState[reviewerId]) {
|
||||
this._updateItems[reviewerId].prev_state = this._lastState[reviewerId];
|
||||
}
|
||||
return newUpdates;
|
||||
}, []);
|
||||
this._completeBatch();
|
||||
if (this._batch.updates && this._batch.updates.length) {
|
||||
newUpdates.push(this._batch);
|
||||
}
|
||||
this.result.reviewer_updates = newUpdates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates update message for reviewer state change.
|
||||
*
|
||||
* @param {string} prev previous reviewer state.
|
||||
* @param {string} state current reviewer state.
|
||||
* @return {string}
|
||||
*/
|
||||
_getUpdateMessage(prev, state) {
|
||||
if (prev === 'REMOVED' || !prev) {
|
||||
return 'Added to ' + state.toLowerCase() + ': ';
|
||||
} else if (state === 'REMOVED') {
|
||||
if (prev) {
|
||||
return 'Removed from ' + prev.toLowerCase() + ': ';
|
||||
} else {
|
||||
return 'Removed : ';
|
||||
}
|
||||
} else {
|
||||
return 'Removed : ';
|
||||
return (
|
||||
'Moved from ' + prev.toLowerCase() + ' to ' + state.toLowerCase() + ': '
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return 'Moved from ' + prev.toLowerCase() + ' to ' + state.toLowerCase() +
|
||||
': ';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Groups updates for same category (eg CC->CC) into a hash arrays of
|
||||
* reviewers.
|
||||
*
|
||||
* @param {!Array<!Object>} updates Array of ReviewerUpdateItemInfo.
|
||||
* @return {!Object} Hash of arrays of AccountInfo, message as key.
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._groupUpdatesByMessage = function(updates) {
|
||||
return updates.reduce((result, item) => {
|
||||
const message = this._getUpdateMessage(item.prev_state, item.state);
|
||||
if (!result[message]) {
|
||||
result[message] = [];
|
||||
}
|
||||
result[message].push(item.reviewer);
|
||||
return result;
|
||||
}, {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates text messages for grouped reviewer updates.
|
||||
* Formats reviewer updates to a (not yet implemented) EventInfo instance.
|
||||
*
|
||||
* @see https://gerrit-review.googlesource.com/c/94490/
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._formatUpdates = function() {
|
||||
for (const update of this.result.reviewer_updates) {
|
||||
const grouppedReviewers = this._groupUpdatesByMessage(update.updates);
|
||||
const newUpdates = [];
|
||||
for (const message in grouppedReviewers) {
|
||||
if (grouppedReviewers.hasOwnProperty(message)) {
|
||||
newUpdates.push({
|
||||
message,
|
||||
reviewers: grouppedReviewers[message],
|
||||
});
|
||||
/**
|
||||
* Groups updates for same category (eg CC->CC) into a hash arrays of
|
||||
* reviewers.
|
||||
*
|
||||
* @param {!Array<!Object>} updates Array of ReviewerUpdateItemInfo.
|
||||
* @return {!Object} Hash of arrays of AccountInfo, message as key.
|
||||
*/
|
||||
_groupUpdatesByMessage(updates) {
|
||||
return updates.reduce((result, item) => {
|
||||
const message = this._getUpdateMessage(item.prev_state, item.state);
|
||||
if (!result[message]) {
|
||||
result[message] = [];
|
||||
}
|
||||
}
|
||||
update.updates = newUpdates;
|
||||
result[message].push(item.reviewer);
|
||||
return result;
|
||||
}, {});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves reviewer updates that are within short time frame of change messages
|
||||
* back in time so they would come before change messages.
|
||||
* TODO(viktard): Remove when server-side serves reviewer updates like so.
|
||||
*/
|
||||
GrReviewerUpdatesParser.prototype._advanceUpdates = function() {
|
||||
const updates = this.result.reviewer_updates;
|
||||
const messages = this.result.messages;
|
||||
messages.forEach((message, index) => {
|
||||
const messageDate = parseDate(message.date).getTime();
|
||||
const nextMessageDate = index === messages.length - 1 ? null :
|
||||
parseDate(messages[index + 1].date).getTime();
|
||||
for (const update of updates) {
|
||||
const date = parseDate(update.date).getTime();
|
||||
if (date >= messageDate &&
|
||||
(!nextMessageDate || date < nextMessageDate)) {
|
||||
const timestamp = parseDate(update.date).getTime() -
|
||||
GrReviewerUpdatesParser.MESSAGE_REVIEWERS_THRESHOLD_MILLIS;
|
||||
update.date = new Date(timestamp)
|
||||
.toISOString()
|
||||
.replace('T', ' ')
|
||||
.replace('Z', '000000');
|
||||
}
|
||||
if (nextMessageDate && date > nextMessageDate) {
|
||||
break;
|
||||
/**
|
||||
* Generates text messages for grouped reviewer updates.
|
||||
* Formats reviewer updates to a (not yet implemented) EventInfo instance.
|
||||
*
|
||||
* @see https://gerrit-review.googlesource.com/c/94490/
|
||||
*/
|
||||
_formatUpdates() {
|
||||
for (const update of this.result.reviewer_updates) {
|
||||
const grouppedReviewers = this._groupUpdatesByMessage(update.updates);
|
||||
const newUpdates = [];
|
||||
for (const message in grouppedReviewers) {
|
||||
if (grouppedReviewers.hasOwnProperty(message)) {
|
||||
newUpdates.push({
|
||||
message,
|
||||
reviewers: grouppedReviewers[message],
|
||||
});
|
||||
}
|
||||
}
|
||||
update.updates = newUpdates;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves reviewer updates that are within short time frame of change messages
|
||||
* back in time so they would come before change messages.
|
||||
* TODO(viktard): Remove when server-side serves reviewer updates like so.
|
||||
*/
|
||||
_advanceUpdates() {
|
||||
const updates = this.result.reviewer_updates;
|
||||
const messages = this.result.messages;
|
||||
messages.forEach((message, index) => {
|
||||
const messageDate = parseDate(message.date).getTime();
|
||||
const nextMessageDate =
|
||||
index === messages.length - 1
|
||||
? null
|
||||
: parseDate(messages[index + 1].date).getTime();
|
||||
for (const update of updates) {
|
||||
const date = parseDate(update.date).getTime();
|
||||
if (
|
||||
date >= messageDate &&
|
||||
(!nextMessageDate || date < nextMessageDate)
|
||||
) {
|
||||
const timestamp =
|
||||
parseDate(update.date).getTime() -
|
||||
MESSAGE_REVIEWERS_THRESHOLD_MILLIS;
|
||||
update.date = new Date(timestamp)
|
||||
.toISOString()
|
||||
.replace('T', ' ')
|
||||
.replace('Z', '000000');
|
||||
}
|
||||
if (nextMessageDate && date > nextMessageDate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static parse(change) {
|
||||
if (
|
||||
!change ||
|
||||
!change.messages ||
|
||||
!change.reviewer_updates ||
|
||||
!change.reviewer_updates.length
|
||||
) {
|
||||
return change;
|
||||
}
|
||||
const parser = new GrReviewerUpdatesParser(change);
|
||||
parser._filterRemovedMessages();
|
||||
parser._groupUpdates();
|
||||
parser._formatUpdates();
|
||||
parser._advanceUpdates();
|
||||
return parser.result;
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,6 @@ import {parseDate} from '../../../utils/date-util.js';
|
||||
suite('gr-reviewer-updates-parser tests', () => {
|
||||
let instance;
|
||||
|
||||
setup(() => {
|
||||
|
||||
});
|
||||
|
||||
test('ignores changes without messages', () => {
|
||||
const change = {};
|
||||
sinon.stub(
|
||||
|
||||
@@ -25,7 +25,7 @@ export class GrGroupSuggestionsProvider {
|
||||
.then(groups => {
|
||||
if (!groups) { return []; }
|
||||
const keys = Object.keys(groups);
|
||||
return keys.map(key => Object.assign({}, groups[key], {name: key}));
|
||||
return keys.map(key => { return {...groups[key], name: key}; });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -134,9 +134,11 @@ export class Auth {
|
||||
* @return {!Promise<!Response>}
|
||||
*/
|
||||
fetch(url, opt_options) {
|
||||
const options = Object.assign({
|
||||
const options = {
|
||||
headers: new Headers(),
|
||||
}, this._defaultOptions, opt_options);
|
||||
...this._defaultOptions,
|
||||
...opt_options,
|
||||
};
|
||||
if (this._type === Auth.TYPE.ACCESS_TOKEN) {
|
||||
return this._getAccessToken().then(
|
||||
accessToken =>
|
||||
|
||||
@@ -651,4 +651,4 @@ export class GrReporting {
|
||||
}
|
||||
}
|
||||
|
||||
export const DEFAULT_STARTUP_TIMERS = Object.assign({}, STARTUP_TIMERS);
|
||||
export const DEFAULT_STARTUP_TIMERS = {...STARTUP_TIMERS};
|
||||
|
||||
@@ -29,7 +29,7 @@ suite('gr-reporting tests', () => {
|
||||
setup(() => {
|
||||
clock = sinon.useFakeTimers(NOW_TIME);
|
||||
service = new GrReporting(appContext.flagsService);
|
||||
service._baselines = Object.assign({}, DEFAULT_STARTUP_TIMERS);
|
||||
service._baselines = {...DEFAULT_STARTUP_TIMERS};
|
||||
sinon.stub(service, 'reporter');
|
||||
});
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ function _filterLinks(filterFn, getAdminMenuLinks, opt_options) {
|
||||
// set in addition to the subsection that should be displayed if it
|
||||
// exists.
|
||||
for (const link of links) {
|
||||
const linkCopy = Object.assign({}, link);
|
||||
const linkCopy = {...link};
|
||||
if (linkCopy.name === 'Repositories' && repoName) {
|
||||
linkCopy.subsection = getRepoSubsections(repoName);
|
||||
expandedSection = linkCopy.subsection;
|
||||
|
||||
@@ -143,7 +143,7 @@ export function computeAllPatchSets(change) {
|
||||
let patchNums = [];
|
||||
if (change.revisions && Object.keys(change.revisions).length) {
|
||||
const revisions = Object.keys(change.revisions)
|
||||
.map(sha => Object.assign({sha}, change.revisions[sha]));
|
||||
.map(sha => { return {sha, ...change.revisions[sha]}; });
|
||||
patchNums = sortRevisions(revisions)
|
||||
.map(e => {
|
||||
// TODO(kaspern): Mark which patchset an edit was made on, if an
|
||||
|
||||
Reference in New Issue
Block a user