Allow porting comments to contribute to comment count string
Ported comments now contribute to the thread, unresolved and draft count shown on the file list and the diff view dropdown. For the file list count and the file dropdown in diff view, we have a path and patchset range already defined. We then figure out if the ported thread will be rendered or not and add it to the count accordingly. Also refactor to * Use getThreadsBySideForFile to calculate thread count which automatically includes ported comments since we are now calculating these numbers based on threads and not comments. * Merge comment string computed by gr-file-list and gr-diff-view and move it to gr-comment-api. Change-Id: Ibf6959abf5a0cf437a4964ef32e35f6304d0de86
This commit is contained in:
@@ -610,44 +610,16 @@ export class GrFileList extends KeyboardShortcutMixin(
|
|||||||
_computeCommentsString(
|
_computeCommentsString(
|
||||||
changeComments?: ChangeComments,
|
changeComments?: ChangeComments,
|
||||||
patchRange?: PatchRange,
|
patchRange?: PatchRange,
|
||||||
path?: string
|
file?: NormalizedFileInfo
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
changeComments === undefined ||
|
changeComments === undefined ||
|
||||||
patchRange === undefined ||
|
patchRange === undefined ||
|
||||||
path === undefined
|
file?.__path === undefined
|
||||||
) {
|
) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const unresolvedCount =
|
return changeComments.computeCommentsString(patchRange, file.__path, file);
|
||||||
changeComments.computeUnresolvedNum({
|
|
||||||
patchNum: patchRange.basePatchNum,
|
|
||||||
path,
|
|
||||||
}) +
|
|
||||||
changeComments.computeUnresolvedNum({
|
|
||||||
patchNum: patchRange.patchNum,
|
|
||||||
path,
|
|
||||||
});
|
|
||||||
const commentThreadCount =
|
|
||||||
changeComments.computeCommentThreadCount({
|
|
||||||
patchNum: patchRange.basePatchNum,
|
|
||||||
path,
|
|
||||||
}) +
|
|
||||||
changeComments.computeCommentThreadCount({
|
|
||||||
patchNum: patchRange.patchNum,
|
|
||||||
path,
|
|
||||||
});
|
|
||||||
const commentString = pluralize(commentThreadCount, 'comment');
|
|
||||||
const unresolvedString =
|
|
||||||
unresolvedCount === 0 ? '' : `${unresolvedCount} unresolved`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
commentString +
|
|
||||||
// Add a space if both comments and unresolved
|
|
||||||
(commentString && unresolvedString ? ' ' : '') +
|
|
||||||
// Add parentheses around unresolved if it exists.
|
|
||||||
(unresolvedString ? `(${unresolvedString})` : '')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -456,8 +456,7 @@ export const htmlTemplate = html`
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
><!--
|
><!--
|
||||||
-->[[_computeCommentsString(changeComments, patchRange,
|
-->[[_computeCommentsString(changeComments, patchRange, file)]]<!--
|
||||||
file.__path)]]<!--
|
|
||||||
--></span
|
--></span
|
||||||
>
|
>
|
||||||
<span class="noCommentsScreenReaderText">
|
<span class="noCommentsScreenReaderText">
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import {runA11yAudit} from '../../../test/a11y-test-utils.js';
|
|||||||
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
|
import {html} from '@polymer/polymer/lib/utils/html-tag.js';
|
||||||
import {TestKeyboardShortcutBinder} from '../../../test/test-utils.js';
|
import {TestKeyboardShortcutBinder} from '../../../test/test-utils.js';
|
||||||
import {Shortcut} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
|
import {Shortcut} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
|
||||||
import {ChangeComments} from '../../diff/gr-comment-api/gr-comment-api.js';
|
|
||||||
import {createCommentThreads} from '../../../utils/comment-util.js';
|
import {createCommentThreads} from '../../../utils/comment-util.js';
|
||||||
|
import {createChangeComments} from '../../../test/test-data-generators.js';
|
||||||
|
|
||||||
const commentApiMock = createCommentApiMockWithTemplateElement(
|
const commentApiMock = createCommentApiMockWithTemplateElement(
|
||||||
'gr-file-list-comment-api-mock', html`
|
'gr-file-list-comment-api-mock', html`
|
||||||
@@ -352,101 +352,7 @@ suite('gr-file-list tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('comment filtering', () => {
|
test('comment filtering', () => {
|
||||||
const comments = {
|
element.changeComments = createChangeComments();
|
||||||
'/COMMIT_MSG': [
|
|
||||||
{
|
|
||||||
patch_set: 1,
|
|
||||||
message: 'Done',
|
|
||||||
updated: '2017-02-08 16:40:49',
|
|
||||||
id: '1',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
patch_set: 1,
|
|
||||||
message: 'oh hay',
|
|
||||||
updated: '2017-02-09 16:40:49',
|
|
||||||
id: '2',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
patch_set: 2,
|
|
||||||
message: 'hello',
|
|
||||||
updated: '2017-02-10 16:40:49',
|
|
||||||
id: '3',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'myfile.txt': [
|
|
||||||
{
|
|
||||||
patch_set: 1,
|
|
||||||
message: 'good news!',
|
|
||||||
updated: '2017-02-08 16:40:49',
|
|
||||||
id: '4',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
patch_set: 2,
|
|
||||||
message: 'wat!?',
|
|
||||||
updated: '2017-02-09 16:40:49',
|
|
||||||
id: '5',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
patch_set: 2,
|
|
||||||
message: 'hi',
|
|
||||||
updated: '2017-02-10 16:40:49',
|
|
||||||
id: '6',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'unresolved.file': [
|
|
||||||
{
|
|
||||||
patch_set: 2,
|
|
||||||
message: 'wat!?',
|
|
||||||
updated: '2017-02-09 16:40:49',
|
|
||||||
id: '7',
|
|
||||||
unresolved: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
patch_set: 2,
|
|
||||||
message: 'hi',
|
|
||||||
updated: '2017-02-10 16:40:49',
|
|
||||||
id: '8',
|
|
||||||
in_reply_to: '7',
|
|
||||||
unresolved: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
patch_set: 2,
|
|
||||||
message: 'good news!',
|
|
||||||
updated: '2017-02-08 16:40:49',
|
|
||||||
id: '9',
|
|
||||||
unresolved: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const drafts = {
|
|
||||||
'/COMMIT_MSG': [
|
|
||||||
{
|
|
||||||
patch_set: 1,
|
|
||||||
message: 'hi',
|
|
||||||
updated: '2017-02-15 16:40:49',
|
|
||||||
id: '10',
|
|
||||||
unresolved: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
patch_set: 1,
|
|
||||||
message: 'fyi',
|
|
||||||
updated: '2017-02-15 16:40:49',
|
|
||||||
id: '11',
|
|
||||||
unresolved: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'unresolved.file': [
|
|
||||||
{
|
|
||||||
patch_set: 1,
|
|
||||||
message: 'hi',
|
|
||||||
updated: '2017-02-11 16:40:49',
|
|
||||||
id: '12',
|
|
||||||
unresolved: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
element.changeComments = new ChangeComments(comments, {}, drafts, 123);
|
|
||||||
|
|
||||||
const parentTo1 = {
|
const parentTo1 = {
|
||||||
basePatchNum: 'PARENT',
|
basePatchNum: 'PARENT',
|
||||||
patchNum: 1,
|
patchNum: 1,
|
||||||
@@ -462,12 +368,6 @@ suite('gr-file-list tests', () => {
|
|||||||
patchNum: 2,
|
patchNum: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, parentTo1,
|
|
||||||
'/COMMIT_MSG', 'comment'), '2 comments (1 unresolved)');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, _1To2,
|
|
||||||
'/COMMIT_MSG', 'comment'), '3 comments (1 unresolved)');
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeCommentsStringMobile(element.changeComments, parentTo1
|
element._computeCommentsStringMobile(element.changeComments, parentTo1
|
||||||
, '/COMMIT_MSG'), '2c');
|
, '/COMMIT_MSG'), '2c');
|
||||||
@@ -486,12 +386,6 @@ suite('gr-file-list tests', () => {
|
|||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
||||||
'unresolved.file'), '1d');
|
'unresolved.file'), '1d');
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, parentTo1,
|
|
||||||
'myfile.txt', 'comment'), '1 comment');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, _1To2,
|
|
||||||
'myfile.txt', 'comment'), '3 comments');
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeCommentsStringMobile(
|
element._computeCommentsStringMobile(
|
||||||
element.changeComments,
|
element.changeComments,
|
||||||
@@ -513,12 +407,6 @@ suite('gr-file-list tests', () => {
|
|||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
||||||
'myfile.txt'), '');
|
'myfile.txt'), '');
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, parentTo1,
|
|
||||||
'file_added_in_rev2.txt', 'comment'), '');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, _1To2,
|
|
||||||
'file_added_in_rev2.txt', 'comment'), '');
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeCommentsStringMobile(
|
element._computeCommentsStringMobile(
|
||||||
element.changeComments,
|
element.changeComments,
|
||||||
@@ -540,12 +428,6 @@ suite('gr-file-list tests', () => {
|
|||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
||||||
'file_added_in_rev2.txt'), '');
|
'file_added_in_rev2.txt'), '');
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, parentTo2,
|
|
||||||
'/COMMIT_MSG', 'comment'), '1 comment');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, _1To2,
|
|
||||||
'/COMMIT_MSG', 'comment'), '3 comments (1 unresolved)');
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeCommentsStringMobile(
|
element._computeCommentsStringMobile(
|
||||||
element.changeComments,
|
element.changeComments,
|
||||||
@@ -570,12 +452,6 @@ suite('gr-file-list tests', () => {
|
|||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
||||||
'/COMMIT_MSG'), '2d');
|
'/COMMIT_MSG'), '2d');
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, parentTo2,
|
|
||||||
'myfile.txt', 'comment'), '2 comments');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, _1To2,
|
|
||||||
'myfile.txt', 'comment'), '3 comments');
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeCommentsStringMobile(
|
element._computeCommentsStringMobile(
|
||||||
element.changeComments,
|
element.changeComments,
|
||||||
@@ -591,18 +467,6 @@ suite('gr-file-list tests', () => {
|
|||||||
assert.equal(
|
assert.equal(
|
||||||
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
element._computeDraftsStringMobile(element.changeComments, _1To2,
|
||||||
'myfile.txt'), '');
|
'myfile.txt'), '');
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, parentTo2,
|
|
||||||
'file_added_in_rev2.txt', 'comment'), '');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, _1To2,
|
|
||||||
'file_added_in_rev2.txt', 'comment'), '');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, parentTo2,
|
|
||||||
'unresolved.file', 'comment'), '2 comments (1 unresolved)');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentsString(element.changeComments, _1To2,
|
|
||||||
'unresolved.file', 'comment'), '2 comments (1 unresolved)');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_reviewedTitle', () => {
|
test('_reviewedTitle', () => {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
UrlEncodedCommentId,
|
UrlEncodedCommentId,
|
||||||
NumericChangeId,
|
NumericChangeId,
|
||||||
PathToCommentsInfoMap,
|
PathToCommentsInfoMap,
|
||||||
|
FileInfo,
|
||||||
} from '../../../types/common';
|
} from '../../../types/common';
|
||||||
import {hasOwnProperty} from '../../../utils/common-util';
|
import {hasOwnProperty} from '../../../utils/common-util';
|
||||||
import {
|
import {
|
||||||
@@ -51,6 +52,7 @@ import {PatchSetFile, PatchNumOnly, isPatchSetFile} from '../../../types/types';
|
|||||||
import {appContext} from '../../../services/app-context';
|
import {appContext} from '../../../services/app-context';
|
||||||
import {CommentSide, Side} from '../../../constants/constants';
|
import {CommentSide, Side} from '../../../constants/constants';
|
||||||
import {KnownExperimentId} from '../../../services/flags/flags';
|
import {KnownExperimentId} from '../../../services/flags/flags';
|
||||||
|
import {pluralize} from '../../../utils/string-util';
|
||||||
|
|
||||||
export type CommentIdToCommentThreadMap = {
|
export type CommentIdToCommentThreadMap = {
|
||||||
[urlEncodedCommentId: string]: CommentThread;
|
[urlEncodedCommentId: string]: CommentThread;
|
||||||
@@ -485,6 +487,45 @@ export class ChangeComments {
|
|||||||
return this._commentObjToArray(allDrafts).length;
|
return this._commentObjToArray(allDrafts).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param includeUnmodified Included unmodified status of the file in the
|
||||||
|
* comment string or not. For files we opt of chip instead of a string.
|
||||||
|
* @param filterPatchset Only count threads which belong to this patchset
|
||||||
|
*/
|
||||||
|
computeCommentsString(
|
||||||
|
patchRange?: PatchRange,
|
||||||
|
path?: string,
|
||||||
|
changeFileInfo?: FileInfo,
|
||||||
|
includeUnmodified?: boolean
|
||||||
|
) {
|
||||||
|
if (!path) return '';
|
||||||
|
if (!patchRange) return '';
|
||||||
|
|
||||||
|
const threads = this.getThreadsBySideForFile({path}, patchRange);
|
||||||
|
const commentThreadCount = threads.filter(thread => !isDraftThread(thread))
|
||||||
|
.length;
|
||||||
|
const unresolvedCount = threads.reduce((cnt, thread) => {
|
||||||
|
if (isUnresolved(thread)) cnt += 1;
|
||||||
|
return cnt;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const commentThreadString = pluralize(commentThreadCount, 'comment');
|
||||||
|
const unresolvedString =
|
||||||
|
unresolvedCount === 0 ? '' : `${unresolvedCount} unresolved`;
|
||||||
|
|
||||||
|
const unmodifiedString =
|
||||||
|
includeUnmodified && changeFileInfo?.status === 'U' ? 'no changes' : '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
commentThreadString +
|
||||||
|
// Add a space if both comments and unresolved
|
||||||
|
(commentThreadString && unresolvedString ? ' ' : '') +
|
||||||
|
// Add parentheses around unresolved if it exists.
|
||||||
|
(unresolvedString ? `(${unresolvedString})` : '') +
|
||||||
|
(unmodifiedString ? `(${unmodifiedString})` : '')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes a number of unresolved comment threads in a given file and path.
|
* Computes a number of unresolved comment threads in a given file and path.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import './gr-comment-api.js';
|
|||||||
import {ChangeComments} from './gr-comment-api.js';
|
import {ChangeComments} from './gr-comment-api.js';
|
||||||
import {CommentSide} from '../../../constants/constants.js';
|
import {CommentSide} from '../../../constants/constants.js';
|
||||||
import {isInRevisionOfPatchRange, isInBaseOfPatchRange, createCommentThreads, isDraftThread, isUnresolved} from '../../../utils/comment-util.js';
|
import {isInRevisionOfPatchRange, isInBaseOfPatchRange, createCommentThreads, isDraftThread, isUnresolved} from '../../../utils/comment-util.js';
|
||||||
import {createDraft, createComment} from '../../../test/test-data-generators.js';
|
import {createDraft, createComment, createChangeComments} from '../../../test/test-data-generators.js';
|
||||||
|
|
||||||
const basicFixture = fixtureFromElement('gr-comment-api');
|
const basicFixture = fixtureFromElement('gr-comment-api');
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ suite('gr-comment-api tests', () => {
|
|||||||
portedComments = {
|
portedComments = {
|
||||||
'karma.conf.js': [{
|
'karma.conf.js': [{
|
||||||
...comment1,
|
...comment1,
|
||||||
patchNum: 4,
|
patch_set: 4,
|
||||||
range: {
|
range: {
|
||||||
start_line: 136,
|
start_line: 136,
|
||||||
start_character: 16,
|
start_character: 16,
|
||||||
@@ -278,6 +278,17 @@ suite('gr-comment-api tests', () => {
|
|||||||
).length, 0);
|
).length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('ported comments contribute to comment count', () => {
|
||||||
|
assert.equal(changeComments.computeCommentsString(
|
||||||
|
{basePatchNum: 'PARENT', patchNum: 2}, 'karma.conf.js',
|
||||||
|
{__path: 'karma.conf.js'}), '2 comments (1 unresolved)');
|
||||||
|
|
||||||
|
// comment1 is ported over to patchset 4
|
||||||
|
assert.equal(changeComments.computeCommentsString(
|
||||||
|
{basePatchNum: 'PARENT', patchNum: 4}, 'karma.conf.js',
|
||||||
|
{__path: 'karma.conf.js'}), '1 comment (1 unresolved)');
|
||||||
|
});
|
||||||
|
|
||||||
test('drafts are ported over', () => {
|
test('drafts are ported over', () => {
|
||||||
changeComments = new ChangeComments(
|
changeComments = new ChangeComments(
|
||||||
{}/* comments */,
|
{}/* comments */,
|
||||||
@@ -612,6 +623,78 @@ suite('gr-comment-api tests', () => {
|
|||||||
element._changeComments.computeUnresolvedNum(1, 'path'), 0);
|
element._changeComments.computeUnresolvedNum(1, 'path'), 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('computeCommentsString', () => {
|
||||||
|
const changeComments = createChangeComments();
|
||||||
|
const parentTo1 = {
|
||||||
|
basePatchNum: 'PARENT',
|
||||||
|
patchNum: 1,
|
||||||
|
};
|
||||||
|
const parentTo2 = {
|
||||||
|
basePatchNum: 'PARENT',
|
||||||
|
patchNum: 2,
|
||||||
|
};
|
||||||
|
const _1To2 = {
|
||||||
|
basePatchNum: 1,
|
||||||
|
patchNum: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo1, '/COMMIT_MSG',
|
||||||
|
{__path: '/COMMIT_MSG'}), '2 comments (1 unresolved)');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo1, '/COMMIT_MSG',
|
||||||
|
{__path: '/COMMIT_MSG', status: 'U'}, true),
|
||||||
|
'2 comments (1 unresolved)(no changes)');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(_1To2, '/COMMIT_MSG',
|
||||||
|
{__path: '/COMMIT_MSG'}), '3 comments (1 unresolved)');
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo1, 'myfile.txt',
|
||||||
|
{__path: 'myfile.txt'}), '1 comment');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(_1To2, 'myfile.txt',
|
||||||
|
{__path: 'myfile.txt'}), '3 comments');
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo1,
|
||||||
|
'file_added_in_rev2.txt',
|
||||||
|
{__path: 'file_added_in_rev2.txt'}), '');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(_1To2,
|
||||||
|
'file_added_in_rev2.txt',
|
||||||
|
{__path: 'file_added_in_rev2.txt'}), '');
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo2, '/COMMIT_MSG',
|
||||||
|
{__path: '/COMMIT_MSG'}), '1 comment');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(_1To2, '/COMMIT_MSG',
|
||||||
|
{__path: '/COMMIT_MSG'}), '3 comments (1 unresolved)');
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo2, 'myfile.txt',
|
||||||
|
{__path: 'myfile.txt'}), '2 comments');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(_1To2, 'myfile.txt',
|
||||||
|
{__path: 'myfile.txt'}), '3 comments');
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo2,
|
||||||
|
'file_added_in_rev2.txt',
|
||||||
|
{__path: 'file_added_in_rev2.txt'}), '');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(_1To2,
|
||||||
|
'file_added_in_rev2.txt',
|
||||||
|
{__path: 'file_added_in_rev2.txt'}), '');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(parentTo2, 'unresolved.file',
|
||||||
|
{__path: 'unresolved.file'}), '2 comments (1 unresolved)');
|
||||||
|
assert.equal(
|
||||||
|
changeComments.computeCommentsString(_1To2, 'unresolved.file',
|
||||||
|
{__path: 'unresolved.file'}), '2 comments (1 unresolved)');
|
||||||
|
});
|
||||||
|
|
||||||
test('computeCommentThreadCount', () => {
|
test('computeCommentThreadCount', () => {
|
||||||
assert.equal(element._changeComments
|
assert.equal(element._changeComments
|
||||||
.computeCommentThreadCount({
|
.computeCommentThreadCount({
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import {
|
|||||||
KeyboardShortcutMixin,
|
KeyboardShortcutMixin,
|
||||||
Shortcut,
|
Shortcut,
|
||||||
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
|
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
|
||||||
import {pluralize} from '../../../utils/string-util';
|
|
||||||
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
|
import {GerritNav} from '../../core/gr-navigation/gr-navigation';
|
||||||
import {appContext} from '../../../services/app-context';
|
import {appContext} from '../../../services/app-context';
|
||||||
import {
|
import {
|
||||||
@@ -181,9 +180,7 @@ export class GrDiffView extends KeyboardShortcutMixin(
|
|||||||
|
|
||||||
@property({
|
@property({
|
||||||
type: Array,
|
type: Array,
|
||||||
computed:
|
computed: '_formatFilesForDropdown(_files, _patchRange, _changeComments)',
|
||||||
'_formatFilesForDropdown(_files, ' +
|
|
||||||
'_patchRange.patchNum, _changeComments)',
|
|
||||||
})
|
})
|
||||||
_formattedFiles?: DropdownItem[];
|
_formattedFiles?: DropdownItem[];
|
||||||
|
|
||||||
@@ -1306,11 +1303,11 @@ export class GrDiffView extends KeyboardShortcutMixin(
|
|||||||
|
|
||||||
_formatFilesForDropdown(
|
_formatFilesForDropdown(
|
||||||
files?: Files,
|
files?: Files,
|
||||||
patchNum?: PatchSetNum,
|
patchRange?: PatchRange,
|
||||||
changeComments?: ChangeComments
|
changeComments?: ChangeComments
|
||||||
): DropdownItem[] {
|
): DropdownItem[] {
|
||||||
if (!files) return [];
|
if (!files) return [];
|
||||||
if (!patchNum) return [];
|
if (!patchRange) return [];
|
||||||
if (!changeComments) return [];
|
if (!changeComments) return [];
|
||||||
|
|
||||||
const dropdownContent: DropdownItem[] = [];
|
const dropdownContent: DropdownItem[] = [];
|
||||||
@@ -1319,46 +1316,17 @@ export class GrDiffView extends KeyboardShortcutMixin(
|
|||||||
text: computeDisplayPath(path),
|
text: computeDisplayPath(path),
|
||||||
mobileText: computeTruncatedPath(path),
|
mobileText: computeTruncatedPath(path),
|
||||||
value: path,
|
value: path,
|
||||||
bottomText: this._computeCommentString(
|
bottomText: changeComments.computeCommentsString(
|
||||||
changeComments,
|
patchRange,
|
||||||
patchNum,
|
|
||||||
path,
|
path,
|
||||||
files.changeFilesByPath[path]
|
files.changeFilesByPath[path],
|
||||||
|
/* includeUnmodified= */ true
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return dropdownContent;
|
return dropdownContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeCommentString(
|
|
||||||
changeComments?: ChangeComments,
|
|
||||||
patchNum?: PatchSetNum,
|
|
||||||
path?: string,
|
|
||||||
changeFileInfo?: FileInfo
|
|
||||||
) {
|
|
||||||
if (!changeComments) return '';
|
|
||||||
if (!path) return '';
|
|
||||||
if (!changeFileInfo) return '';
|
|
||||||
|
|
||||||
const unresolvedCount = changeComments.computeUnresolvedNum({
|
|
||||||
patchNum,
|
|
||||||
path,
|
|
||||||
});
|
|
||||||
const commentThreadCount = changeComments.computeCommentThreadCount({
|
|
||||||
patchNum,
|
|
||||||
path,
|
|
||||||
});
|
|
||||||
const commentThreadString = pluralize(commentThreadCount, 'comment');
|
|
||||||
const unresolvedString =
|
|
||||||
unresolvedCount === 0 ? '' : `${unresolvedCount} unresolved`;
|
|
||||||
|
|
||||||
const unmodifiedString = changeFileInfo.status === 'U' ? 'no changes' : '';
|
|
||||||
|
|
||||||
return [unmodifiedString, commentThreadString, unresolvedString]
|
|
||||||
.filter(v => v && v.length > 0)
|
|
||||||
.join(', ');
|
|
||||||
}
|
|
||||||
|
|
||||||
_computePrefsButtonHidden(
|
_computePrefsButtonHidden(
|
||||||
prefs?: DiffPreferencesInfo,
|
prefs?: DiffPreferencesInfo,
|
||||||
prefsDisabled?: boolean
|
prefsDisabled?: boolean
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ suite('gr-diff-view tests', () => {
|
|||||||
},
|
},
|
||||||
]},
|
]},
|
||||||
computeCommentThreadCount: () => {},
|
computeCommentThreadCount: () => {},
|
||||||
|
computeCommentsString: () => '',
|
||||||
computeUnresolvedNum: () => {},
|
computeUnresolvedNum: () => {},
|
||||||
getPaths: () => {},
|
getPaths: () => {},
|
||||||
getThreadsBySideForFile: () => [],
|
getThreadsBySideForFile: () => [],
|
||||||
@@ -905,44 +906,6 @@ suite('gr-diff-view tests', () => {
|
|||||||
assert.isTrue(overlayOpenStub.called);
|
assert.isTrue(overlayOpenStub.called);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_computeCommentString', done => {
|
|
||||||
const path = '/test';
|
|
||||||
element.$.commentAPI.loadAll().then(comments => {
|
|
||||||
const commentThreadCountStub =
|
|
||||||
sinon.stub(comments, 'computeCommentThreadCount');
|
|
||||||
const unresolvedCountStub =
|
|
||||||
sinon.stub(comments, 'computeUnresolvedNum');
|
|
||||||
commentThreadCountStub.withArgs({patchNum: 1, path}).returns(0);
|
|
||||||
commentThreadCountStub.withArgs({patchNum: 2, path}).returns(1);
|
|
||||||
commentThreadCountStub.withArgs({patchNum: 3, path}).returns(2);
|
|
||||||
commentThreadCountStub.withArgs({patchNum: 4, path}).returns(0);
|
|
||||||
unresolvedCountStub.withArgs({patchNum: 1, path}).returns(1);
|
|
||||||
unresolvedCountStub.withArgs({patchNum: 2, path}).returns(0);
|
|
||||||
unresolvedCountStub.withArgs({patchNum: 3, path}).returns(2);
|
|
||||||
unresolvedCountStub.withArgs({patchNum: 4, path}).returns(0);
|
|
||||||
|
|
||||||
assert.equal(element._computeCommentString(comments, 1, path, {}),
|
|
||||||
'1 unresolved');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentString(comments, 2, path, {status: 'M'}),
|
|
||||||
'1 comment');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentString(comments, 2, path, {status: 'U'}),
|
|
||||||
'no changes, 1 comment');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentString(comments, 3, path, {status: 'A'}),
|
|
||||||
'2 comments, 2 unresolved');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentString(
|
|
||||||
comments, 4, path, {status: 'M'}
|
|
||||||
), '');
|
|
||||||
assert.equal(
|
|
||||||
element._computeCommentString(comments, 4, path, {status: 'U'}),
|
|
||||||
'no changes');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
suite('url params', () => {
|
suite('url params', () => {
|
||||||
setup(() => {
|
setup(() => {
|
||||||
sinon.stub(element, '_getFiles');
|
sinon.stub(element, '_getFiles');
|
||||||
@@ -962,9 +925,6 @@ suite('gr-diff-view tests', () => {
|
|||||||
basePatchNum: PARENT,
|
basePatchNum: PARENT,
|
||||||
patchNum: 10,
|
patchNum: 10,
|
||||||
};
|
};
|
||||||
// computeCommentThreadCount is an empty function hence stubbing
|
|
||||||
// function that depends on it's return value
|
|
||||||
sinon.stub(element, '_computeCommentString').returns('');
|
|
||||||
element._change = {_number: 42};
|
element._change = {_number: 42};
|
||||||
element._files = getFilesFromFileList(
|
element._files = getFilesFromFileList(
|
||||||
['chell.go', 'glados.txt', 'wheatley.md',
|
['chell.go', 'glados.txt', 'wheatley.md',
|
||||||
|
|||||||
@@ -367,6 +367,7 @@ export class GrPatchRangeSelect extends GestureEventListeners(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(dhruvsri): have ported comments contribute to this count
|
||||||
_computePatchSetCommentsString(
|
_computePatchSetCommentsString(
|
||||||
changeComments: ChangeComments,
|
changeComments: ChangeComments,
|
||||||
patchNum: PatchSetNum
|
patchNum: PatchSetNum
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ import {CommitInfoWithRequiredCommit} from '../elements/change/gr-change-metadat
|
|||||||
import {WebLinkInfo} from '../types/diff';
|
import {WebLinkInfo} from '../types/diff';
|
||||||
import {UIComment, UIDraft} from '../utils/comment-util';
|
import {UIComment, UIDraft} from '../utils/comment-util';
|
||||||
import {GerritView} from '../services/router/router-model';
|
import {GerritView} from '../services/router/router-model';
|
||||||
|
import {ChangeComments} from '../elements/diff/gr-comment-api/gr-comment-api';
|
||||||
|
|
||||||
export function dateToTimestamp(date: Date): Timestamp {
|
export function dateToTimestamp(date: Date): Timestamp {
|
||||||
const nanosecondSuffix = '.000000000';
|
const nanosecondSuffix = '.000000000';
|
||||||
@@ -465,3 +466,106 @@ export function createDraft(): UIDraft {
|
|||||||
__editing: false,
|
__editing: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createChangeComments(): ChangeComments {
|
||||||
|
const comments = {
|
||||||
|
'/COMMIT_MSG': [
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
message: 'Done',
|
||||||
|
updated: '2017-02-08 16:40:49' as Timestamp,
|
||||||
|
id: '1' as UrlEncodedCommentId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
message: 'oh hay',
|
||||||
|
updated: '2017-02-09 16:40:49' as Timestamp,
|
||||||
|
id: '2' as UrlEncodedCommentId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
patch_set: 2 as PatchSetNum,
|
||||||
|
message: 'hello',
|
||||||
|
updated: '2017-02-10 16:40:49' as Timestamp,
|
||||||
|
id: '3' as UrlEncodedCommentId,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'myfile.txt': [
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
message: 'good news!',
|
||||||
|
updated: '2017-02-08 16:40:49' as Timestamp,
|
||||||
|
id: '4' as UrlEncodedCommentId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
patch_set: 2 as PatchSetNum,
|
||||||
|
message: 'wat!?',
|
||||||
|
updated: '2017-02-09 16:40:49' as Timestamp,
|
||||||
|
id: '5' as UrlEncodedCommentId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
patch_set: 2 as PatchSetNum,
|
||||||
|
message: 'hi',
|
||||||
|
updated: '2017-02-10 16:40:49' as Timestamp,
|
||||||
|
id: '6' as UrlEncodedCommentId,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'unresolved.file': [
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
patch_set: 2 as PatchSetNum,
|
||||||
|
message: 'wat!?',
|
||||||
|
updated: '2017-02-09 16:40:49' as Timestamp,
|
||||||
|
id: '7' as UrlEncodedCommentId,
|
||||||
|
unresolved: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
patch_set: 2 as PatchSetNum,
|
||||||
|
message: 'hi',
|
||||||
|
updated: '2017-02-10 16:40:49' as Timestamp,
|
||||||
|
id: '8' as UrlEncodedCommentId,
|
||||||
|
in_reply_to: '7' as UrlEncodedCommentId,
|
||||||
|
unresolved: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...createComment(),
|
||||||
|
patch_set: 2 as PatchSetNum,
|
||||||
|
message: 'good news!',
|
||||||
|
updated: '2017-02-08 16:40:49' as Timestamp,
|
||||||
|
id: '9' as UrlEncodedCommentId,
|
||||||
|
unresolved: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const drafts = {
|
||||||
|
'/COMMIT_MSG': [
|
||||||
|
{
|
||||||
|
...createDraft(),
|
||||||
|
message: 'hi',
|
||||||
|
updated: '2017-02-15 16:40:49' as Timestamp,
|
||||||
|
id: '10' as UrlEncodedCommentId,
|
||||||
|
unresolved: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...createDraft(),
|
||||||
|
message: 'fyi',
|
||||||
|
updated: '2017-02-15 16:40:49' as Timestamp,
|
||||||
|
id: '11' as UrlEncodedCommentId,
|
||||||
|
unresolved: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'unresolved.file': [
|
||||||
|
{
|
||||||
|
...createDraft(),
|
||||||
|
message: 'hi',
|
||||||
|
updated: '2017-02-11 16:40:49' as Timestamp,
|
||||||
|
id: '12' as UrlEncodedCommentId,
|
||||||
|
unresolved: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
return new ChangeComments(comments, {}, drafts, {}, {});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user