Imperative named Slots
The idea is to instead of imperatively appending slotted comments to
threadGroupEls (which results in them being removed from the light DOM
of the gr-diff element and thus causing all kinds of tracking
difficulties), to slot them into a named slot in the appropriate line.
Change-Id: I17e99b236240baab581f8c266bed3d400a302408
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
index d2731a2..6f5a8d3 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-binary.js
@@ -20,10 +20,8 @@
// Prevent redefinition.
if (window.GrDiffBuilderBinary) { return; }
- function GrDiffBuilderBinary(diff, commentThreadEls, prefs,
- outputEl) {
- GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
- outputEl);
+ function GrDiffBuilderBinary(diff, prefs, outputEl) {
+ GrDiffBuilder.call(this, diff, prefs, outputEl);
}
GrDiffBuilderBinary.prototype = Object.create(GrDiffBuilder.prototype);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
index f05f4f0..bf543e5 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
@@ -22,10 +22,8 @@
const IMAGE_MIME_PATTERN = /^image\/(bmp|gif|jpeg|jpg|png|tiff|webp)$/;
- function GrDiffBuilderImage(diff, commentThreadEls, prefs,
- outputEl, baseImage, revisionImage) {
- GrDiffBuilderSideBySide.call(this, diff, commentThreadEls,
- prefs, outputEl, []);
+ function GrDiffBuilderImage(diff, prefs, outputEl, baseImage, revisionImage) {
+ GrDiffBuilderSideBySide.call(this, diff, prefs, outputEl, []);
this._baseImage = baseImage;
this._revisionImage = revisionImage;
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
index 81cbabb..2cf9782 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-side-by-side.js
@@ -20,10 +20,8 @@
// Prevent redefinition.
if (window.GrDiffBuilderSideBySide) { return; }
- function GrDiffBuilderSideBySide(diff, commentThreadEls,
- prefs, outputEl, layers) {
- GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
- outputEl, layers);
+ function GrDiffBuilderSideBySide(diff, prefs, outputEl, layers) {
+ GrDiffBuilder.call(this, diff, prefs, outputEl, layers);
}
GrDiffBuilderSideBySide.prototype = Object.create(GrDiffBuilder.prototype);
GrDiffBuilderSideBySide.prototype.constructor = GrDiffBuilderSideBySide;
@@ -99,10 +97,6 @@
row.appendChild(action);
} else {
const textEl = this._createTextEl(line, side);
- const threadGroupEl = this._commentThreadGroupForLine(line, side);
- if (threadGroupEl) {
- textEl.appendChild(threadGroupEl);
- }
row.appendChild(textEl);
}
};
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
index 2dcdee4..6020e19 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-unified.js
@@ -20,10 +20,8 @@
// Prevent redefinition.
if (window.GrDiffBuilderUnified) { return; }
- function GrDiffBuilderUnified(diff, commentThreadEls, prefs,
- outputEl, layers) {
- GrDiffBuilder.call(this, diff, commentThreadEls, prefs,
- outputEl, layers);
+ function GrDiffBuilderUnified(diff, prefs, outputEl, layers) {
+ GrDiffBuilder.call(this, diff, prefs, outputEl, layers);
}
GrDiffBuilderUnified.prototype = Object.create(GrDiffBuilder.prototype);
GrDiffBuilderUnified.prototype.constructor = GrDiffBuilderUnified;
@@ -88,10 +86,6 @@
row.appendChild(action);
} else {
const textEl = this._createTextEl(line);
- const threadGroupEl = this._commentThreadGroupForLine(line);
- if (threadGroupEl) {
- textEl.appendChild(threadGroupEl);
- }
row.appendChild(textEl);
}
return row;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
index 6aea35b..c19d23f 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html
@@ -121,10 +121,6 @@
return this.queryEffectiveChildren('#diffTable');
},
- get _commentThreadElements() {
- return this.queryAllEffectiveChildren('.comment-thread');
- },
-
observers: [
'_groupsChanged(_groups.splices)',
],
@@ -292,20 +288,16 @@
let builder = null;
if (this.isImageDiff) {
- builder = new GrDiffBuilderImage(diff,
- this._commentThreadElements, prefs, this.diffElement,
+ builder = new GrDiffBuilderImage(diff, prefs, this.diffElement,
this.baseImage, this.revisionImage);
} else if (diff.binary) {
// If the diff is binary, but not an image.
- return new GrDiffBuilderBinary(diff,
- this._commentThreadElements, prefs, this.diffElement);
+ return new GrDiffBuilderBinary(diff, prefs, this.diffElement);
} else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) {
- builder = new GrDiffBuilderSideBySide(diff,
- this._commentThreadElements, prefs, this.diffElement,
+ builder = new GrDiffBuilderSideBySide(diff, prefs, this.diffElement,
this._layers);
} else if (this.viewMode === DiffViewMode.UNIFIED) {
- builder = new GrDiffBuilderUnified(diff,
- this._commentThreadElements, prefs, this.diffElement,
+ builder = new GrDiffBuilderUnified(diff, prefs, this.diffElement,
this._layers);
}
if (!builder) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
index d428f68..e892605 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
@@ -20,60 +20,6 @@
// Prevent redefinition.
if (window.GrDiffBuilder) { return; }
- /** @enum {string} */
- Gerrit.DiffSide = {
- LEFT: 'left',
- RIGHT: 'right',
- BOTH: 'both',
- };
-
- /**
- * @param {!Array<!HTMLElement>} threadEls
- * @param {!{beforeNumber: (number|string|undefined),
- * afterNumber: (number|string|undefined)}}
- * lineInfo
- * @param {!Gerrit.DiffSide=} side The side (LEFT, RIGHT, BOTH) for
- * which to return the threads (default: BOTH).
- * @return {!Array<!HTMLElement>} The thread elements matching the given
- * location.
- */
- Gerrit.filterThreadElsForLocation = function(
- threadEls, lineInfo, side = Gerrit.DiffSide.BOTH) {
- function matchesLeftLine(threadEl) {
- return threadEl.getAttribute('comment-side') ==
- Gerrit.DiffSide.LEFT &&
- threadEl.getAttribute('line-num') == lineInfo.beforeNumber;
- }
- function matchesRightLine(threadEl) {
- return threadEl.getAttribute('comment-side') ==
- Gerrit.DiffSide.RIGHT &&
- threadEl.getAttribute('line-num') == lineInfo.afterNumber;
- }
- function matchesFileComment(threadEl) {
- return (side === Gerrit.DiffSide.BOTH ||
- threadEl.getAttribute('comment-side') == side) &&
- // line/range comments have 1-based line set, if line is falsy it's
- // a file comment
- !threadEl.getAttribute('line-num');
- }
-
- // Select the appropriate matchers for the desired side and line
- // If side is BOTH, we want both the left and right matcher.
- const matchers = [];
- if (side !== Gerrit.DiffSide.RIGHT) {
- matchers.push(matchesLeftLine);
- }
- if (side !== Gerrit.DiffSide.LEFT) {
- matchers.push(matchesRightLine);
- }
- if (lineInfo.afterNumber === 'FILE' ||
- lineInfo.beforeNumber === 'FILE') {
- matchers.push(matchesFileComment);
- }
- return threadEls.filter(threadEl =>
- matchers.some(matcher => matcher(threadEl)));
- };
-
/**
* In JS, unicode code points above 0xFFFF occupy two elements of a string.
* For example '𐀏'.length is 2. An occurence of such a code point is called a
@@ -96,8 +42,7 @@
*/
const REGEX_TAB_OR_SURROGATE_PAIR = /\t|[\uD800-\uDBFF][\uDC00-\uDFFF]/;
- function GrDiffBuilder(diff, commentThreadEls, prefs,
- outputEl, layers) {
+ function GrDiffBuilder(diff, prefs, outputEl, layers) {
this._diff = diff;
this._prefs = prefs;
this._outputEl = outputEl;
@@ -119,8 +64,6 @@
layer.addListener(this._handleLayerUpdate.bind(this));
}
}
-
- this._threadEls = commentThreadEls;
}
GrDiffBuilder.GroupType = {
@@ -373,31 +316,6 @@
return button;
};
- /**
- * @param {!GrDiffLine} line
- * @param {!GrDiffBuilder.Side=} side The side (LEFT, RIGHT, BOTH) for which
- * to return the thread group (default: BOTH).
- * @return {!Object}
- */
- GrDiffBuilder.prototype._commentThreadGroupForLine = function(
- line, commentSide = GrDiffBuilder.Side.BOTH) {
- const threadElsForGroup =
- Gerrit.filterThreadElsForLocation(this._threadEls, line, commentSide);
- if (!threadElsForGroup || threadElsForGroup.length === 0) {
- return null;
- }
-
- const threadGroupEl = document.createElement('div');
- threadGroupEl.className = 'thread-group';
- for (const threadEl of threadElsForGroup) {
- Polymer.dom(threadGroupEl).appendChild(threadEl);
- }
- if (commentSide) {
- threadGroupEl.setAttribute('data-side', commentSide);
- }
- return threadGroupEl;
- };
-
GrDiffBuilder.prototype._createLineEl = function(
line, number, type, opt_class) {
const td = this._createElement('td');
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
index c7a1140..1b0ba04 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
@@ -75,70 +75,11 @@
show_tabs: true,
tab_size: 4,
};
- builder = new GrDiffBuilder({content: []}, [], prefs);
+ builder = new GrDiffBuilder({content: []}, prefs);
});
teardown(() => { sandbox.restore(); });
- test('filterThreadElsForLocation with no threads', () => {
- const line = {beforeNumber: 3, afterNumber: 5};
-
- const threads = [];
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threads, line), []);
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threads, line,
- Gerrit.DiffSide.LEFT), []);
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threads, line,
- Gerrit.DiffSide.RIGHT), []);
- });
-
- test('filterThreadElsForLocation for line comments', () => {
- const line = {beforeNumber: 3, afterNumber: 5};
-
- const l3 = document.createElement('div');
- l3.setAttribute('line-num', 3);
- l3.setAttribute('comment-side', 'left');
-
- const l5 = document.createElement('div');
- l5.setAttribute('line-num', 5);
- l5.setAttribute('comment-side', 'left');
-
- const r3 = document.createElement('div');
- r3.setAttribute('line-num', 3);
- r3.setAttribute('comment-side', 'right');
-
- const r5 = document.createElement('div');
- r5.setAttribute('line-num', 5);
- r5.setAttribute('comment-side', 'right');
-
- const threadEls = [l3, l5, r3, r5];
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line),
- [l3, r5]);
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
- Gerrit.DiffSide.LEFT), [l3]);
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
- Gerrit.DiffSide.RIGHT), [r5]);
- });
-
- test('filterThreadElsForLocation for file comments', () => {
- const line = {beforeNumber: 'FILE', afterNumber: 'FILE'};
-
- const l = document.createElement('div');
- l.setAttribute('comment-side', 'left');
-
- const r = document.createElement('div');
- r.setAttribute('comment-side', 'right');
-
- const threadEls = [l, r];
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line),
- [l, r]);
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
- Gerrit.DiffSide.BOTH), [l, r]);
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
- Gerrit.DiffSide.LEFT), [l]);
- assert.deepEqual(Gerrit.filterThreadElsForLocation(threadEls, line,
- Gerrit.DiffSide.RIGHT), [r]);
- });
-
test('_createElement classStr applies all classes', () => {
const node = builder._createElement('div', 'test classes');
assert.isTrue(node.classList.contains('gr-diff'));
@@ -312,73 +253,6 @@
}
});
- test('comment thread group creation', () => {
- const l3 = document.createElement('div');
- l3.className = 'comment-thread';
- l3.setAttribute('comment-side', 'left');
- l3.setAttribute('line-num', 3);
-
- const l5 = document.createElement('div');
- l5.className = 'comment-thread';
- l5.setAttribute('comment-side', 'left');
- l5.setAttribute('line-num', 5);
-
- const r5 = document.createElement('div');
- r5.className = 'comment-thread';
- r5.setAttribute('comment-side', 'right');
- r5.setAttribute('line-num', 5);
-
- builder = new GrDiffBuilder({content: []}, [l3, l5, r5], prefs);
-
- function checkThreadGroupProps(threadGroupEl,
- expectedThreadEls) {
- const threadEls = Polymer.dom(threadGroupEl).queryDistributedElements(
- '.comment-thread');
- assert.equal(threadEls.length, expectedThreadEls.length);
- for (let i=0; i<expectedThreadEls.length; i++) {
- assert.equal(threadEls[i], expectedThreadEls[i]);
- }
- }
-
- let line = new GrDiffLine(GrDiffLine.Type.BOTH);
- line.beforeNumber = 5;
- line.afterNumber = 5;
- let threadGroupEl = builder._commentThreadGroupForLine(line);
- checkThreadGroupProps(threadGroupEl, [l5, r5]);
-
- threadGroupEl =
- builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.RIGHT);
- checkThreadGroupProps(threadGroupEl, [r5]);
-
- threadGroupEl =
- builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.LEFT);
- checkThreadGroupProps(threadGroupEl, [l5]);
-
- threadGroupEl = builder._commentThreadGroupForLine(line);
- checkThreadGroupProps(threadGroupEl, [l5, r5]);
-
- threadEl =
- builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.LEFT);
- checkThreadGroupProps(threadEl, [l5]);
-
- threadGroupEl =
- builder._commentThreadGroupForLine(line, GrDiffBuilder.Side.RIGHT);
- checkThreadGroupProps(threadGroupEl, [r5]);
-
- line = new GrDiffLine(GrDiffLine.Type.REMOVE);
- line.beforeNumber = 5;
- line.afterNumber = 5;
- threadGroupEl = builder._commentThreadGroupForLine(line);
- checkThreadGroupProps(threadGroupEl, [l5, r5]);
-
- line = new GrDiffLine(GrDiffLine.Type.ADD);
- line.beforeNumber = 3;
- line.afterNumber = 5;
- threadGroupEl = builder._commentThreadGroupForLine(line);
- checkThreadGroupProps(threadGroupEl, [l3, r5]);
- });
-
-
test('_handlePreferenceError called with invalid preference', () => {
sandbox.stub(element, '_handlePreferenceError');
const prefs = {tab_size: 0};
@@ -913,7 +787,7 @@
outputEl = element.queryEffectiveChildren('#diffTable');
keyLocations = {left: {}, right: {}};
sandbox.stub(element, '_getDiffBuilder', () => {
- const builder = new GrDiffBuilder({content}, [], prefs, outputEl);
+ const builder = new GrDiffBuilder({content}, prefs, outputEl);
sandbox.stub(builder, 'addColumns');
builder.buildSectionElement = function(group) {
const section = document.createElement('stub');
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
index 75a2b15..1646583 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight.js
@@ -74,8 +74,16 @@
this.debounce('selectionChange', this._handleSelection, 200);
},
+ _getThreadEl(e) {
+ const path = Polymer.dom(e).path || [];
+ for (const pathEl of path) {
+ if (pathEl.classList.contains('comment-thread')) return pathEl;
+ }
+ return null;
+ },
+
_handleCommentThreadMouseenter(e) {
- const threadEl = Polymer.dom(e).localTarget;
+ const threadEl = this._getThreadEl(e);
const index = this._indexForThreadEl(threadEl);
if (index !== undefined) {
@@ -84,7 +92,7 @@
},
_handleCommentThreadMouseleave(e) {
- const threadEl = Polymer.dom(e).localTarget;
+ const threadEl = this._getThreadEl(e);
const index = this._indexForThreadEl(threadEl);
if (index !== undefined) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
index 8c30afa..6f6cbc4 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.html
@@ -199,6 +199,7 @@
test('comment-thread-mouseenter from line comments is ignored', () => {
const threadEl = document.createElement('div');
+ threadEl.className = 'comment-thread';
threadEl.setAttribute('comment-side', 'right');
threadEl.setAttribute('line-num', 3);
element.appendChild(threadEl);
@@ -212,6 +213,7 @@
test('comment-thread-mouseenter from ranged comment causes set', () => {
const threadEl = document.createElement('div');
+ threadEl.className = 'comment-thread';
threadEl.setAttribute('comment-side', 'right');
threadEl.setAttribute('line-num', 3);
threadEl.setAttribute('range', JSON.stringify({
@@ -239,6 +241,7 @@
test('comment-thread-mouseleave from line comments is ignored', () => {
const threadEl = document.createElement('div');
+ threadEl.className = 'comment-thread';
threadEl.setAttribute('comment-side', 'right');
threadEl.setAttribute('line-num', 3);
element.appendChild(threadEl);
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 5839141..0611a12 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
@@ -63,6 +63,12 @@
a.end_character === b.end_character;
}
+ /** @enum {string} */
+ Gerrit.DiffSide = {
+ LEFT: 'left',
+ RIGHT: 'right',
+ };
+
/**
* Wrapper around gr-diff.
*
@@ -196,11 +202,6 @@
type: Number,
computed: '_computeParentIndex(patchRange.*)',
},
-
- _threadEls: {
- type: Array,
- value: () => [],
- },
},
behaviors: [
@@ -344,7 +345,7 @@
* @return {!Array<!HTMLElement>}
*/
getThreadEls() {
- return this._threadEls;
+ return Polymer.dom(this.$.diff).querySelectorAll('.comment-thread');
},
/** @param {HTMLElement} el */
@@ -471,7 +472,6 @@
return isImageDiff(diff);
},
-
_commentsChanged(newComments) {
const allComments = [];
for (const side of [GrDiffBuilder.Side.LEFT, GrDiffBuilder.Side.RIGHT]) {
@@ -590,21 +590,20 @@
},
_attachThreadElement(threadEl) {
- this._threadEls.push(threadEl);
Polymer.dom(this.$.diff).appendChild(threadEl);
},
_clearThreads() {
- for (const threadEl of this._threadEls) {
+ for (const threadEl of this.getThreadEls()) {
const parent = Polymer.dom(threadEl).parentNode;
Polymer.dom(parent).removeChild(threadEl);
}
- this._threadEls = [];
},
_createThreadElement(thread) {
const threadEl = document.createElement('gr-diff-comment-thread');
threadEl.className = 'comment-thread';
+ threadEl.slot = `${thread.commentSide}-${thread.lineNum}`;
threadEl.comments = thread.comments;
threadEl.commentSide = thread.commentSide;
threadEl.isOnParent = !!thread.isOnParent;
@@ -625,10 +624,6 @@
const parent = Polymer.dom(threadEl).parentNode;
Polymer.dom(parent).removeChild(threadEl);
- const i = this._threadEls.findIndex(
- threadEl => threadEl.rootId == e.detail.rootId);
- this._threadEls.splice(i, 1);
-
threadEl.removeEventListener('root-id-changed', rootIdChangedListener);
threadEl.removeEventListener('thread-discard', threadDiscardListener);
};
@@ -660,12 +655,57 @@
return rangesEqual(threadRange, range);
}
- const filteredThreadEls = Gerrit.filterThreadElsForLocation(
- this._threadEls, line, commentSide).filter(matchesRange);
+ const filteredThreadEls = this._filterThreadElsForLocation(
+ this.getThreadEls(), line, commentSide).filter(matchesRange);
return filteredThreadEls.length ? filteredThreadEls[0] : null;
},
/**
+ * @param {!Array<!HTMLElement>} threadEls
+ * @param {!{beforeNumber: (number|string|undefined|null),
+ * afterNumber: (number|string|undefined|null)}}
+ * lineInfo
+ * @param {!Gerrit.DiffSide=} side The side (LEFT, RIGHT) for
+ * which to return the threads.
+ * @return {!Array<!HTMLElement>} The thread elements matching the given
+ * location.
+ */
+ _filterThreadElsForLocation(threadEls, lineInfo, side) {
+ function matchesLeftLine(threadEl) {
+ return threadEl.getAttribute('comment-side') ==
+ Gerrit.DiffSide.LEFT &&
+ threadEl.getAttribute('line-num') == lineInfo.beforeNumber;
+ }
+ function matchesRightLine(threadEl) {
+ return threadEl.getAttribute('comment-side') ==
+ Gerrit.DiffSide.RIGHT &&
+ threadEl.getAttribute('line-num') == lineInfo.afterNumber;
+ }
+ function matchesFileComment(threadEl) {
+ return threadEl.getAttribute('comment-side') == side &&
+ // line/range comments have 1-based line set, if line is falsy it's
+ // a file comment
+ !threadEl.getAttribute('line-num');
+ }
+
+ // Select the appropriate matchers for the desired side and line
+ // If side is BOTH, we want both the left and right matcher.
+ const matchers = [];
+ if (side !== Gerrit.DiffSide.RIGHT) {
+ matchers.push(matchesLeftLine);
+ }
+ if (side !== Gerrit.DiffSide.LEFT) {
+ matchers.push(matchesRightLine);
+ }
+ if (lineInfo.afterNumber === 'FILE' ||
+ lineInfo.beforeNumber === 'FILE') {
+ matchers.push(matchesFileComment);
+ }
+ return threadEls.filter(threadEl =>
+ matchers.some(matcher => matcher(threadEl)));
+ },
+
+ /**
* Take a diff that was loaded with a ignore-whitespace other than
* IGNORE_NONE, and convert delta chunks labeled as common into shared
* chunks.
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 5344256..53a60d7 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
@@ -769,10 +769,11 @@
});
});
- test('getThreadEls() returns _threadEls', () => {
- const returnValue = [document.createElement('b')];
- element._threadEls = returnValue;
- assert.equal(element.getThreadEls(), returnValue);
+ test('getThreadEls() returns .comment-threads', () => {
+ const threadEl = document.createElement('div');
+ threadEl.className = 'comment-thread';
+ Polymer.dom(element.$.diff).appendChild(threadEl);
+ assert.deepEqual(element.getThreadEls(), [threadEl]);
});
test('delegates addDraftAtLine(el)', () => {
@@ -1159,6 +1160,65 @@
assert.equal(threads[1].patchNum, 3);
});
+ test('_filterThreadElsForLocation with no threads', () => {
+ const line = {beforeNumber: 3, afterNumber: 5};
+
+ const threads = [];
+ assert.deepEqual(element._filterThreadElsForLocation(threads, line), []);
+ assert.deepEqual(element._filterThreadElsForLocation(threads, line,
+ Gerrit.DiffSide.LEFT), []);
+ assert.deepEqual(element._filterThreadElsForLocation(threads, line,
+ Gerrit.DiffSide.RIGHT), []);
+ });
+
+ test('_filterThreadElsForLocation for line comments', () => {
+ const line = {beforeNumber: 3, afterNumber: 5};
+
+ const l3 = document.createElement('div');
+ l3.setAttribute('line-num', 3);
+ l3.setAttribute('comment-side', 'left');
+
+ const l5 = document.createElement('div');
+ l5.setAttribute('line-num', 5);
+ l5.setAttribute('comment-side', 'left');
+
+ const r3 = document.createElement('div');
+ r3.setAttribute('line-num', 3);
+ r3.setAttribute('comment-side', 'right');
+
+ const r5 = document.createElement('div');
+ r5.setAttribute('line-num', 5);
+ r5.setAttribute('comment-side', 'right');
+
+ const threadEls = [l3, l5, r3, r5];
+ assert.deepEqual(element._filterThreadElsForLocation(threadEls, line),
+ [l3, r5]);
+ assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+ Gerrit.DiffSide.LEFT), [l3]);
+ assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+ Gerrit.DiffSide.RIGHT), [r5]);
+ });
+
+ test('_filterThreadElsForLocation for file comments', () => {
+ const line = {beforeNumber: 'FILE', afterNumber: 'FILE'};
+
+ const l = document.createElement('div');
+ l.setAttribute('comment-side', 'left');
+
+ const r = document.createElement('div');
+ r.setAttribute('comment-side', 'right');
+
+ const threadEls = [l, r];
+ assert.deepEqual(element._filterThreadElsForLocation(threadEls, line),
+ [l, r]);
+ assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+ Gerrit.DiffSide.BOTH), [l, r]);
+ assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+ Gerrit.DiffSide.LEFT), [l]);
+ assert.deepEqual(element._filterThreadElsForLocation(threadEls, line,
+ Gerrit.DiffSide.RIGHT), [r]);
+ });
+
suite('_translateChunksToIgnore', () => {
let content;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index e587953..4ccdf96 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -294,7 +294,6 @@
is-image-diff="[[isImageDiff]]"
base-image="[[baseImage]]"
revision-image="[[revisionImage]]">
- <slot></slot>
<table
id="diffTable"
class$="[[_diffTableClass]]"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index 8b5c6d6..996d484 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -60,6 +60,20 @@
node.classList.contains('comment-thread');
}
+ /**
+ * Turn a slot element into the corresponding content element.
+ * Slots are only fully supported in Polymer 2 - in Polymer 1, they are
+ * replaced with content elements during template parsing. This conversion is
+ * not applied for imperatively created slot elements, so this method
+ * implements the same behavior as the template parsing for imperative slots.
+ */
+ Gerrit.slotToContent = function(slot) {
+ const content = document.createElement('content');
+ content.name = slot.name;
+ content.setAttribute('select', `[slot='${slot.name}']`);
+ return content;
+ };
+
Polymer({
is: 'gr-diff',
@@ -455,14 +469,16 @@
* Gets or creates a comment thread group for a specific line and side on a
* diff.
* @param {!Object} contentEl
+ * @param {!Gerrit.DiffSide} commentSide
* @return {!Node}
*/
- _getOrCreateThreadGroup(contentEl) {
+ _getOrCreateThreadGroup(contentEl, commentSide) {
// Check if thread group exists.
let threadGroupEl = this._getThreadGroupForLine(contentEl);
if (!threadGroupEl) {
threadGroupEl = document.createElement('div');
threadGroupEl.className = 'thread-group';
+ threadGroupEl.setAttribute('data-side', commentSide);
contentEl.appendChild(threadGroupEl);
}
return threadGroupEl;
@@ -624,8 +640,17 @@
lineNumString, commentSide);
const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
const contentEl = contentText.parentElement;
- const threadGroupEl = this._getOrCreateThreadGroup(contentEl);
- Polymer.dom(threadGroupEl).appendChild(threadEl);
+ const threadGroupEl = this._getOrCreateThreadGroup(
+ contentEl, commentSide);
+ // Create a slot for the thread and attach it to the thread group.
+ // The Polyfill has some bugs and this only works if the slot is
+ // attached to the group after the group is attached to the DOM.
+ // The thread group may already have a slot with the right name, but
+ // that is okay because the first matching slot is used and the rest
+ // are ignored.
+ const slot = document.createElement('slot');
+ slot.name = threadEl.slot;
+ Polymer.dom(threadGroupEl).appendChild(Gerrit.slotToContent(slot));
}
});
},