Move comment change handling to gr-diff-host
These three events are just used to sync the model to reflect the changes. As
nothing in gr-diff and descendents needs the comment model anymore, we can
remove that property and instead do the updating in gr-diff-host, where we
still need the comments model property to be kept in sync.
This change removes the last dependency on the comment model from gr-diff and
descendents, so they can now be reused indepedently of Gerrit's comment model.
Change-Id: I9549ea640688006c099493c2156170d706a1c65c
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html
index d335e7a..3eb7b37 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.html
@@ -37,7 +37,6 @@
commit-range="[[commitRange]]"
hidden$="[[hidden]]"
no-render-on-prefs-change="[[noRenderOnPrefsChange]]"
- comments="[[comments]]"
line-wrapping="[[lineWrapping]]"
view-mode="[[viewMode]]"
line-of-interest="[[lineOfInterest]]"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
index 8a2f2cd..5839141 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.js
@@ -208,7 +208,16 @@
],
listeners: {
+ // These are named inconsistently for a reason:
+ // The create-comment event is fired to indicate that we should
+ // create a comment.
+ // The comment-* events are just notifying that the comments did already
+ // change in some way, and that we should update any models we may want
+ // to keep in sync.
'create-comment': '_handleCreateComment',
+ 'comment-discard': '_handleCommentDiscard',
+ 'comment-update': '_handleCommentUpdate',
+ 'comment-save': '_handleCommentSave',
},
observers: [
@@ -723,5 +732,76 @@
this.getParentIndex(patchRangeRecord.base.basePatchNum) : null;
},
+ _handleCommentSave(e) {
+ const comment = e.detail.comment;
+ const side = e.detail.comment.__commentSide;
+ const idx = this._findDraftIndex(comment, side);
+ this.set(['comments', side, idx], comment);
+ this._handleCommentSaveOrDiscard();
+ },
+
+ _handleCommentDiscard(e) {
+ const comment = e.detail.comment;
+ this._removeComment(comment);
+ this._handleCommentSaveOrDiscard();
+ },
+
+ /**
+ * Closure annotation for Polymer.prototype.push is off. Submitted PR:
+ * https://github.com/Polymer/polymer/pull/4776
+ * but for not supressing annotations.
+ *
+ * @suppress {checkTypes}
+ */
+ _handleCommentUpdate(e) {
+ const comment = e.detail.comment;
+ const side = e.detail.comment.__commentSide;
+ let idx = this._findCommentIndex(comment, side);
+ if (idx === -1) {
+ idx = this._findDraftIndex(comment, side);
+ }
+ if (idx !== -1) { // Update draft or comment.
+ this.set(['comments', side, idx], comment);
+ } else { // Create new draft.
+ this.push(['comments', side], comment);
+ }
+ },
+
+ _handleCommentSaveOrDiscard() {
+ this.dispatchEvent(new CustomEvent('diff-comments-modified',
+ {bubbles: true}));
+ },
+
+ _removeComment(comment) {
+ const side = comment.__commentSide;
+ this._removeCommentFromSide(comment, side);
+ },
+
+ _removeCommentFromSide(comment, side) {
+ let idx = this._findCommentIndex(comment, side);
+ if (idx === -1) {
+ idx = this._findDraftIndex(comment, side);
+ }
+ if (idx !== -1) {
+ this.splice('comments.' + side, idx, 1);
+ }
+ },
+
+ /** @return {number} */
+ _findCommentIndex(comment, side) {
+ if (!comment.id || !this.comments[side]) {
+ return -1;
+ }
+ return this.comments[side].findIndex(item => item.id === comment.id);
+ },
+
+ /** @return {number} */
+ _findDraftIndex(comment, side) {
+ if (!comment.__draftID || !this.comments[side]) {
+ return -1;
+ }
+ return this.comments[side].findIndex(
+ item => item.__draftID === comment.__draftID);
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
index 88d7ab6..5344256 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.html
@@ -52,6 +52,189 @@
sandbox.restore();
});
+ suite('handle comment-update', () => {
+ setup(() => {
+ sandbox.stub(element, '_commentsChanged');
+ element.comments = {
+ meta: {
+ changeNum: '42',
+ patchRange: {
+ basePatchNum: 'PARENT',
+ patchNum: 3,
+ },
+ path: '/path/to/foo',
+ projectConfig: {foo: 'bar'},
+ },
+ left: [
+ {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ ],
+ right: [
+ {id: 'c1', __commentSide: 'right'},
+ {id: 'c2', __commentSide: 'right'},
+ {id: 'd1', __draft: true, __commentSide: 'right'},
+ {id: 'd2', __draft: true, __commentSide: 'right'},
+ ],
+ };
+ });
+
+ test('creating a draft', () => {
+ const comment = {__draft: true, __draftID: 'tempID', side: 'PARENT',
+ __commentSide: 'left'};
+ element.fire('comment-update', {comment});
+ assert.include(element.comments.left, comment);
+ });
+
+ test('discarding a draft', () => {
+ const draftID = 'tempID';
+ const id = 'savedID';
+ const comment = {
+ __draft: true,
+ __draftID: draftID,
+ side: 'PARENT',
+ __commentSide: 'left',
+ };
+ const diffCommentsModifiedStub = sandbox.stub();
+ element.addEventListener('diff-comments-modified',
+ diffCommentsModifiedStub);
+ element.comments.left.push(comment);
+ comment.id = id;
+ element.fire('comment-discard', {comment});
+ const drafts = element.comments.left.filter(item => {
+ return item.__draftID === draftID;
+ });
+ assert.equal(drafts.length, 0);
+ assert.isTrue(diffCommentsModifiedStub.called);
+ });
+
+ test('saving a draft', () => {
+ const draftID = 'tempID';
+ const id = 'savedID';
+ const comment = {
+ __draft: true,
+ __draftID: draftID,
+ side: 'PARENT',
+ __commentSide: 'left',
+ };
+ const diffCommentsModifiedStub = sandbox.stub();
+ element.addEventListener('diff-comments-modified',
+ diffCommentsModifiedStub);
+ element.comments.left.push(comment);
+ comment.id = id;
+ element.fire('comment-save', {comment});
+ const drafts = element.comments.left.filter(item => {
+ return item.__draftID === draftID;
+ });
+ assert.equal(drafts.length, 1);
+ assert.equal(drafts[0].id, id);
+ assert.isTrue(diffCommentsModifiedStub.called);
+ });
+ });
+
+ test('remove comment', () => {
+ sandbox.stub(element, '_commentsChanged');
+ element.comments = {
+ meta: {
+ changeNum: '42',
+ patchRange: {
+ basePatchNum: 'PARENT',
+ patchNum: 3,
+ },
+ path: '/path/to/foo',
+ projectConfig: {foo: 'bar'},
+ },
+ left: [
+ {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ ],
+ right: [
+ {id: 'c1', __commentSide: 'right'},
+ {id: 'c2', __commentSide: 'right'},
+ {id: 'd1', __draft: true, __commentSide: 'right'},
+ {id: 'd2', __draft: true, __commentSide: 'right'},
+ ],
+ };
+
+ element._removeComment({});
+ // Using JSON.stringify because Safari 9.1 (11601.5.17.1) doesn’t seem
+ // to believe that one object deepEquals another even when they do :-/.
+ assert.equal(JSON.stringify(element.comments), JSON.stringify({
+ meta: {
+ changeNum: '42',
+ patchRange: {
+ basePatchNum: 'PARENT',
+ patchNum: 3,
+ },
+ path: '/path/to/foo',
+ projectConfig: {foo: 'bar'},
+ },
+ left: [
+ {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bc2', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ ],
+ right: [
+ {id: 'c1', __commentSide: 'right'},
+ {id: 'c2', __commentSide: 'right'},
+ {id: 'd1', __draft: true, __commentSide: 'right'},
+ {id: 'd2', __draft: true, __commentSide: 'right'},
+ ],
+ }));
+
+ element._removeComment({id: 'bc2', side: 'PARENT',
+ __commentSide: 'left'});
+ assert.deepEqual(element.comments, {
+ meta: {
+ changeNum: '42',
+ patchRange: {
+ basePatchNum: 'PARENT',
+ patchNum: 3,
+ },
+ path: '/path/to/foo',
+ projectConfig: {foo: 'bar'},
+ },
+ left: [
+ {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ ],
+ right: [
+ {id: 'c1', __commentSide: 'right'},
+ {id: 'c2', __commentSide: 'right'},
+ {id: 'd1', __draft: true, __commentSide: 'right'},
+ {id: 'd2', __draft: true, __commentSide: 'right'},
+ ],
+ });
+
+ element._removeComment({id: 'd2', __commentSide: 'right'});
+ assert.deepEqual(element.comments, {
+ meta: {
+ changeNum: '42',
+ patchRange: {
+ basePatchNum: 'PARENT',
+ patchNum: 3,
+ },
+ path: '/path/to/foo',
+ projectConfig: {foo: 'bar'},
+ },
+ left: [
+ {id: 'bc1', side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd1', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ {id: 'bd2', __draft: true, side: 'PARENT', __commentSide: 'left'},
+ ],
+ right: [
+ {id: 'c1', __commentSide: 'right'},
+ {id: 'c2', __commentSide: 'right'},
+ {id: 'd1', __draft: true, __commentSide: 'right'},
+ ],
+ });
+ });
+
test('thread-discard handling', () => {
const threads = [
{comments: [{id: 4711}]},
@@ -682,12 +865,6 @@
assert.equal(element.$.diff.noRenderOnPrefsChange, value);
});
- test('passes in comments', () => {
- const value = {left: [], right: []};
- element.comments = value;
- assert.equal(element.$.diff.comments, value);
- });
-
test('passes in lineWrapping', () => {
const value = true;
element.lineWrapping = value;