Change filtering of messages in experimental ChangeLog
Example:
All entries: https://imgur.com/a/2jhhwRc
New default view: https://imgur.com/a/GCbKVll
Old default view: https://imgur.com/a/vdRuv2c
Bug: Issue 11774, Issue 8164
Change-Id: I74b36f956fc44bc24d48c7eea1bb2eac7b6b1a86
diff --git a/polygerrit-ui/app/constants/constants.js b/polygerrit-ui/app/constants/constants.js
index cab50f6..36e0b86 100644
--- a/polygerrit-ui/app/constants/constants.js
+++ b/polygerrit-ui/app/constants/constants.js
@@ -33,3 +33,13 @@
COMMENT_THREADS: '_commentThreads',
};
+/**
+ * @enum
+ * @desc Tag names of change log messages.
+ */
+export const MessageTags = {
+ TAG_DELETE_REVIEWER: 'autogenerated:gerrit:deleteReviewer',
+ TAG_NEW_PATCHSET: 'autogenerated:gerrit:newPatchSet',
+ TAG_NEW_WIP_PATCHSET: 'autogenerated:gerrit:newWipPatchSet',
+ TAG_REVIEWER_UPDATE: 'autogenerated:gerrit:reviewerUpdate',
+};
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
index 9b221ac..15dc03b 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
@@ -29,6 +29,7 @@
import {htmlTemplate} from './gr-messages-list-experimental_html.js';
import {KeyboardShortcutBehavior} from '../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.js';
import {util} from '../../../scripts/util.js';
+import {MessageTags} from '../../../constants/constants.js';
/**
* The content of the enum is also used in the UI for the button text.
@@ -40,6 +41,39 @@
COLLAPSE_ALL: 'Collapse All',
};
+function isNewPatchSet(message) {
+ if (!message || !message.tag) return false;
+ return message.tag.includes(MessageTags.TAG_NEW_PATCHSET)
+ || message.tag.includes(MessageTags.TAG_NEW_WIP_PATCHSET);
+}
+
+function hasHigherRevisionNumber(m, message) {
+ return m._revision_number && m._revision_number > message._revision_number;
+}
+
+function isNewerReviewerUpdate(m, message) {
+ if (!message || !message.tag || !m || !m.tag) return false;
+ if (m.tag != MessageTags.TAG_REVIEWER_UPDATE) return false;
+ return m.date > message.date;
+}
+
+function isImportant(message, allMessages) {
+ // Human messages don't have a tag. They are always important.
+ if (!message.tag) return true;
+
+ // Autogenerated messages are only important, if there is not a newer message
+ // with the same tag.
+ const tag = message.tag;
+ const sameTag = m =>
+ m.tag === tag || (isNewPatchSet(m) && isNewPatchSet(message));
+ return !allMessages.filter(sameTag).some(m =>
+ hasHigherRevisionNumber(m, message) || isNewerReviewerUpdate(m, message));
+}
+
+export const TEST_ONLY = {
+ isImportant,
+};
+
/**
* @extends Polymer.Element
*/
@@ -141,14 +175,6 @@
this._highlightEl(el);
}
- _isAutomated(message) {
- const isReviewerUpdate =
- !!(message.reviewer || message.type === 'REVIEWER_UPDATE');
- const isAutoGenerated =
- !!(message.tag && message.tag.startsWith('autogenerated'));
- return isReviewerUpdate || isAutoGenerated;
- }
-
_observeShowAllActivity(showAllActivity) {
// We have to call render() such that the dom-repeat filter picks up the
// change.
@@ -159,7 +185,8 @@
* Filter for the dom-repeat of combinedMessages.
*/
_isMessageVisible(message) {
- return this._showAllActivity || !this._isAutomated(message);
+ const allMessages = this._combinedMessages;
+ return this._showAllActivity || isImportant(message, allMessages);
}
/**
@@ -260,7 +287,7 @@
_isVisibleShowAllActivityToggle(messages) {
messages = messages || [];
- return messages.some(m => this._isAutomated(m));
+ return messages.some(m => !isImportant(m, messages));
}
/**
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
index 6bf4e47..225b902 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
@@ -59,7 +59,7 @@
<span
id="showAllActivityToggleContainer"
class="container"
- hidden$="[[!_isVisibleShowAllActivityToggle(messages)]]"
+ hidden$="[[!_isVisibleShowAllActivityToggle(_combinedMessages)]]"
>
<paper-toggle-button
id="showAllActivityToggle"
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.html b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.html
index 58e1180..6a8b34c 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.html
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_test.html
@@ -47,6 +47,9 @@
import './gr-messages-list-experimental.js';
import '../../diff/gr-comment-api/gr-comment-api-mock_test.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {TEST_ONLY} from './gr-messages-list-experimental.js';
+import {MessageTags} from '../../../constants/constants.js';
+
const randomMessage = function(opt_params) {
const params = opt_params || {};
const author1 = {
@@ -60,14 +63,10 @@
message: params.message || Math.random().toString(),
_revision_number: params._revision_number || 1,
author: params.author || author1,
+ tag: params.tag,
};
};
-const randomAutomated = function(opt_params) {
- return Object.assign({tag: 'autogenerated:gerrit:replace'},
- randomMessage(opt_params));
-};
-
suite('gr-messages-list-experimental tests', () => {
let element;
let messages;
@@ -88,61 +87,53 @@
email: 'marvin@sirius.org',
};
+ const createComment = function() {
+ return {
+ id: '1a2b3c4d',
+ message: 'some random test text',
+ change_message_id: '8a7b6c5d',
+ updated: '2016-01-01 01:02:03.000000000',
+ line: 1,
+ patch_set: 1,
+ author,
+ };
+ };
+
const comments = {
file1: [
{
- message: 'message text',
+ ...createComment(),
change_message_id: MESSAGE_ID_0,
- updated: '2016-09-27 00:18:03.000000000',
in_reply_to: '6505d749_f0bec0aa',
- line: 62,
- id: '6505d749_10ed44b2',
- patch_set: 2,
author: {
email: 'some@email.com',
_account_id: 123,
},
},
{
- message: 'message text',
+ ...createComment(),
+ id: '2b3c4d5e',
change_message_id: MESSAGE_ID_1,
- updated: '2016-09-27 00:18:03.000000000',
in_reply_to: 'c5912363_6b820105',
- line: 42,
- id: '450a935e_0f1c05db',
- patch_set: 2,
- author,
},
{
- message: 'message text',
+ ...createComment(),
+ id: '2b3c4d5e',
change_message_id: MESSAGE_ID_1,
- updated: '2016-09-27 00:18:03.000000000',
in_reply_to: '6505d749_f0bec0aa',
- line: 62,
- id: '6505d749_10ed44b2',
- patch_set: 2,
- author,
},
{
- message: 'message text',
- change_message_id: MESSAGE_ID_2,
- updated: '2016-09-27 00:18:03.000000000',
- line: 64,
+ ...createComment(),
id: '34ed05d749_10ed44b2',
- patch_set: 2,
- author,
+ change_message_id: MESSAGE_ID_2,
},
],
file2: [
{
- message: 'message text',
+ ...createComment(),
change_message_id: MESSAGE_ID_1,
- updated: '2016-09-27 00:18:03.000000000',
in_reply_to: 'c5912363_4b7d450a',
- line: 132,
id: '450a935e_4f260d25',
- patch_set: 2,
- author,
},
],
};
@@ -214,7 +205,7 @@
assert.isTrue([...getMessages()].filter(m => m._expanded).length == 0);
});
- test('hide messages does not appear when no automated messages', () => {
+ test('showAllActivity does not appear when all msgs are important', () => {
assert.isOk(element.shadowRoot
.querySelector('#showAllActivityToggleContainer[hidden]'));
});
@@ -264,7 +255,7 @@
._expanded);
});
- test('messages', () => {
+ test('associating messages with comments', () => {
const messages = [].concat(
randomMessage(),
{
@@ -306,6 +297,70 @@
assert.isUndefined(messageElements[2].comments.file2);
});
+ test('isImportant human message', () => {
+ const m = randomMessage();
+ assert.isTrue(TEST_ONLY.isImportant(m, []));
+ assert.isTrue(TEST_ONLY.isImportant(m, [m]));
+ });
+
+ test('isImportant even with a tag', () => {
+ const m1 = randomMessage();
+ const m2 = randomMessage({tag: 'autogenerated:gerrit1'});
+ const m3 = randomMessage({tag: 'autogenerated:gerrit2'});
+ assert.isTrue(TEST_ONLY.isImportant(m2, []));
+ assert.isTrue(TEST_ONLY.isImportant(m1, [m1, m2, m3]));
+ assert.isTrue(TEST_ONLY.isImportant(m2, [m1, m2, m3]));
+ assert.isTrue(TEST_ONLY.isImportant(m3, [m1, m2, m3]));
+ });
+
+ test('isImportant filters same tag and older revision', () => {
+ const m1 = randomMessage({tag: 'auto', _revision_number: 2});
+ const m2 = randomMessage({tag: 'auto', _revision_number: 1});
+ const m3 = randomMessage({tag: 'auto'});
+ assert.isTrue(TEST_ONLY.isImportant(m1, [m1]));
+ assert.isTrue(TEST_ONLY.isImportant(m2, [m2]));
+ assert.isTrue(TEST_ONLY.isImportant(m1, [m1, m2]));
+ assert.isFalse(TEST_ONLY.isImportant(m2, [m1, m2]));
+ assert.isTrue(TEST_ONLY.isImportant(m1, [m1, m3]));
+ assert.isFalse(TEST_ONLY.isImportant(m3, [m1, m3]));
+ assert.isTrue(TEST_ONLY.isImportant(m1, [m1, m2, m3]));
+ assert.isFalse(TEST_ONLY.isImportant(m2, [m1, m2, m3]));
+ assert.isFalse(TEST_ONLY.isImportant(m3, [m1, m2, m3]));
+ });
+
+ test('isImportant filters newPatchSet also for wip', () => {
+ const m1 = randomMessage(
+ {tag: MessageTags.TAG_NEW_PATCHSET, _revision_number: 3});
+ const m2 = randomMessage(
+ {tag: MessageTags.TAG_NEW_PATCHSET, _revision_number: 2});
+ const m3 = randomMessage(
+ {tag: MessageTags.TAG_NEW_WIP_PATCHSET, _revision_number: 1});
+ assert.isTrue(TEST_ONLY.isImportant(m1, [m1, m2, m3]));
+ assert.isFalse(TEST_ONLY.isImportant(m2, [m1, m2, m3]));
+ assert.isFalse(TEST_ONLY.isImportant(m3, [m1, m2, m3]));
+ });
+
+ test('isImportant filters older reviewer updates', () => {
+ const m1 = randomMessage(
+ {
+ tag: MessageTags.TAG_REVIEWER_UPDATE,
+ date: '2020-04-24 10:11:02.000000000',
+ });
+ const m2 = randomMessage(
+ {
+ tag: MessageTags.TAG_REVIEWER_UPDATE,
+ date: '2020-04-25 10:11:02.000000000',
+ });
+ const m3 = randomMessage(
+ {
+ tag: MessageTags.TAG_REVIEWER_UPDATE,
+ date: '2020-04-25 10:13:02.000000000',
+ });
+ assert.isFalse(TEST_ONLY.isImportant(m1, [m1, m2, m3]));
+ assert.isFalse(TEST_ONLY.isImportant(m2, [m1, m2, m3]));
+ assert.isTrue(TEST_ONLY.isImportant(m3, [m1, m2, m3]));
+ });
+
test('messages without author do not throw', () => {
const messages = [{
_index: 5,
@@ -328,18 +383,6 @@
let sandbox;
let commentApiWrapper;
- const getMessages = function() {
- return dom(element.root).querySelectorAll('gr-message');
- };
- const getHiddenMessages = function() {
- return dom(element.root).querySelectorAll('gr-message[hidden]');
- };
-
- const randomMessageReviewer = {
- reviewer: {},
- date: '2016-01-13 20:30:33.038000',
- };
-
setup(() => {
stub('gr-rest-api-interface', {
getConfig() { return Promise.resolve({}); },
@@ -350,8 +393,11 @@
});
sandbox = sinon.sandbox.create();
- messages = _.times(2, randomAutomated);
- messages.push(randomMessageReviewer);
+ messages = [
+ randomMessage(),
+ randomMessage({tag: 'auto', _revision_number: 2}),
+ randomMessage({tag: 'auto', _revision_number: 3}),
+ ];
// Element must be wrapped in an element with direct access to the
// comment API.
@@ -374,37 +420,26 @@
.querySelector('#showAllActivityToggle[hidden]'));
});
- test('autogenerated messages are not hidden initially', () => {
- const allHiddenMessageEls = getHiddenMessages();
-
- // There are no hidden messages.
- assert.isFalse(!!allHiddenMessageEls.length);
+ test('one unimportant message is hidden initially', () => {
+ const displayedMsgs = dom(element.root).querySelectorAll('gr-message');
+ assert.equal(displayedMsgs.length, 2);
});
- test('autogenerated messages hidden after comments only toggle', () => {
- let allHiddenMessageEls = getHiddenMessages();
-
+ test('unimportant messages hidden after toggle', () => {
element._showAllActivity = true;
MockInteractions.tap(element.$.showAllActivityToggle);
flushAsynchronousOperations();
- const allMessageEls = getMessages();
- allHiddenMessageEls = getHiddenMessages();
-
- // Autogenerated messages are now hidden.
- assert.equal(allHiddenMessageEls.length, allMessageEls.length);
+ const displayedMsgs = dom(element.root).querySelectorAll('gr-message');
+ assert.equal(displayedMsgs.length, 2);
});
- test('autogenerated messages not hidden after comments only toggle',
- () => {
- let allHiddenMessageEls = getHiddenMessages();
-
- element._showAllActivity = false;
- MockInteractions.tap(element.$.showAllActivityToggle);
- allHiddenMessageEls = getHiddenMessages();
-
- // Autogenerated messages are now hidden.
- assert.isFalse(!!allHiddenMessageEls.length);
- });
+ test('unimportant messages shown after toggle', () => {
+ element._showAllActivity = false;
+ MockInteractions.tap(element.$.showAllActivityToggle);
+ flushAsynchronousOperations();
+ const displayedMsgs = dom(element.root).querySelectorAll('gr-message');
+ assert.equal(displayedMsgs.length, 3);
+ });
test('_computeLabelExtremes', () => {
const computeSpy = sandbox.spy(element, '_computeLabelExtremes');
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.js
index 3d1ce05..224eb5f 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser.js
@@ -16,6 +16,7 @@
*/
import {util} from '../../../scripts/util.js';
+import {MessageTags} from '../../../constants/constants.js';
/** @constructor */
export function GrReviewerUpdatesParser(change) {
@@ -52,9 +53,7 @@
*/
GrReviewerUpdatesParser.prototype._filterRemovedMessages = function() {
this.result.messages = this.result.messages
- .filter(
- message => message.tag !== 'autogenerated:gerrit:deleteReviewer'
- );
+ .filter(message => message.tag !== MessageTags.TAG_DELETE_REVIEWER);
};
/**
@@ -68,6 +67,7 @@
author: update.updated_by,
date: update.updated,
type: 'REVIEWER_UPDATE',
+ tag: MessageTags.TAG_REVIEWER_UPDATE,
};
};