Implement Jump behavior for Changes tab

This commit is contained in:
Douwe Maan 2016-08-04 18:01:32 -07:00
parent 9b115ce4d3
commit ffbba55bc8
6 changed files with 132 additions and 32 deletions

View File

@ -43,39 +43,139 @@
}, },
methods: { methods: {
jumpToNextUnresolvedDiscussion: function () { jumpToNextUnresolvedDiscussion: function () {
let unresolvedIds = CommentsStore.unresolvedDiscussionIds(), let discussionsSelector,
nextUnresolvedDiscussionId; discussionIdsInScope,
const activePage = $('.merge-request-tabs .active a').attr('data-action'), firstUnresolvedDiscussionId,
$diffDiscussions = $('.discussion').filter(function () { nextUnresolvedDiscussionId,
return unresolvedIds.indexOf($(this).attr('data-discussion-id')) !== -1; activeTab = window.mrTabs.currentAction,
}); hasDiscussionsToJumpTo = true,
jumpToFirstDiscussion = !this.discussionId;
unresolvedIds = unresolvedIds.sort(function (a, b) { const discussionIdsForElements = function(elements) {
return $diffDiscussions.index(`[data-discussion-id="${b}"]`) > $diffDiscussions.index(`[data-discussion-id="${a}"]`); return elements.map(function() {
}); return $(this).attr('data-discussion-id');
}).toArray();
};
unresolvedIds.forEach(function (discussionId, i) { const discussions = this.discussions;
if (this.discussionId && discussionId === this.discussionId) {
nextUnresolvedDiscussionId = unresolvedIds[i + 1]; if (activeTab === 'diffs') {
discussionsSelector = '.diffs .notes[data-discussion-id]';
discussionIdsInScope = discussionIdsForElements($(discussionsSelector));
let unresolvedDiscussionCount = 0;
for (const discussionId of discussionIdsInScope) {
const discussion = discussions[discussionId];
if (discussion && !discussion.isResolved()) {
unresolvedDiscussionCount++;
}
}
if (this.discussionId && !this.discussion.isResolved()) {
// If this is the last unresolved discussion on the diffs tab,
// there are no discussions to jump to.
if (unresolvedDiscussionCount === 1) {
hasDiscussionsToJumpTo = false;
}
} else {
// If there are no unresolved discussions on the diffs tab at all,
// there are no discussions to jump to.
if (unresolvedDiscussionCount === 0) {
hasDiscussionsToJumpTo = false;
}
}
} else if (activeTab !== 'notes') {
// If we are on the commits or builds tabs,
// there are no discussions to jump to.
hasDiscussionsToJumpTo = false;
}
if (!hasDiscussionsToJumpTo) {
// If there are no discussions to jump to on the current page,
// switch to the notes tab and jump to the first disucssion there.
window.mrTabs.activateTab('notes');
activeTab = 'notes';
jumpToFirstDiscussion = true;
}
if (activeTab === 'notes') {
discussionsSelector = '.discussion[data-discussion-id]';
discussionIdsInScope = discussionIdsForElements($(discussionsSelector));
}
let currentDiscussionFound = false;
for (const discussionId of discussionIdsInScope) {
const discussion = discussions[discussionId];
if (!discussion) {
// Discussions for comments on commits in this MR don't have a resolved status.
continue;
}
if (!firstUnresolvedDiscussionId && !discussion.isResolved()) {
firstUnresolvedDiscussionId = discussionId;
if (jumpToFirstDiscussion) {
break;
}
}
if (!jumpToFirstDiscussion) {
if (currentDiscussionFound) {
if (!discussion.isResolved()) {
nextUnresolvedDiscussionId = discussionId;
break;
}
else {
continue;
}
}
if (discussionId === this.discussionId) {
currentDiscussionFound = true;
}
}
}
nextUnresolvedDiscussionId = nextUnresolvedDiscussionId || firstUnresolvedDiscussionId;
if (!nextUnresolvedDiscussionId) {
return; return;
} }
}.bind(this));
nextUnresolvedDiscussionId = nextUnresolvedDiscussionId || unresolvedIds[0]; let $target = $(`${discussionsSelector}[data-discussion-id="${nextUnresolvedDiscussionId}"]`);
if (nextUnresolvedDiscussionId) { if (activeTab === 'notes') {
let selector = '.discussion'; $target = $target.closest('.note-discussion');
} else if (activeTab === 'diffs') {
// Resolved discussions are hidden in the diffs tab by default.
// If they are marked unresolved on the notes tab, they will still be hidden on the diffs tab.
// When jumping between unresolved discussions on the diffs tab, we show them.
$target.closest(".content").show();
if (activePage === 'diffs' && $(`${selector}[data-discussion-id="${nextUnresolvedDiscussionId}"]`).length) { $target = $target.closest("tr.notes_holder");
selector = '.diffs .notes'; $target.show();
// If we are on the diffs tab, we don't scroll to the discussion itself, but to
// 4 diff lines above it: the line the discussion was in response to + 3 context
let prevEl;
for (let i = 0; i < 4; i++) {
prevEl = $target.prev();
// If the discussion doesn't have 4 lines above it, we'll have to do with fewer.
if (!prevEl.hasClass("line_holder")) {
break;
} }
$.scrollTo(`${selector}[data-discussion-id="${nextUnresolvedDiscussionId}"]`, { $target = prevEl;
}
}
$.scrollTo($target, {
offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight()) offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight())
}); });
} }
} }
}
}); });
Vue.component('jump-to-discussion', JumpToDiscussion); Vue.component('jump-to-discussion', JumpToDiscussion);

View File

@ -11,7 +11,7 @@
}, },
computed: { computed: {
allResolved: function () { allResolved: function () {
return this.resolved === this.discussionCount; return this.resolvedDiscussionCount === this.discussionCount;
} }
} }
}); });

View File

@ -4,7 +4,7 @@
discussionCount: function () { discussionCount: function () {
return Object.keys(this.discussions).length; return Object.keys(this.discussions).length;
}, },
resolved: function () { resolvedDiscussionCount: function () {
let resolvedCount = 0; let resolvedCount = 0;
for (const discussionId in this.discussions) { for (const discussionId in this.discussions) {
@ -19,6 +19,7 @@
}, },
unresolvedDiscussionCount: function () { unresolvedDiscussionCount: function () {
let unresolvedCount = 0; let unresolvedCount = 0;
for (const discussionId in this.discussions) { for (const discussionId in this.discussions) {
const discussion = this.discussions[discussionId]; const discussion = this.discussions[discussionId];

View File

@ -11,10 +11,8 @@
prepareRequest(namespace) { prepareRequest(namespace) {
this.setCSRF(); this.setCSRF();
if (Vue.http.options.root !== `/${namespace}`) {
Vue.http.options.root = `/${namespace}`; Vue.http.options.root = `/${namespace}`;
} }
}
resolve(namespace, noteId) { resolve(namespace, noteId) {
this.prepareRequest(namespace); this.prepareRequest(namespace);

View File

@ -81,6 +81,7 @@
if (action === 'show') { if (action === 'show') {
action = 'notes'; action = 'notes';
} }
this.currentAction = action;
new_state = this._location.pathname.replace(/\/(commits|diffs|builds)(\.html)?\/?$/, ''); new_state = this._location.pathname.replace(/\/(commits|diffs|builds)(\.html)?\/?$/, '');
if (action !== 'notes') { if (action !== 'notes') {
new_state += "/" + action; new_state += "/" + action;

View File

@ -66,12 +66,12 @@
%li#resolve-count-app.line-resolve-all-container.pull-right.prepend-top-10.hidden-xs{ "v-cloak" => true } %li#resolve-count-app.line-resolve-all-container.pull-right.prepend-top-10.hidden-xs{ "v-cloak" => true }
%resolve-count{ "inline-template" => true, ":logged-out" => "#{current_user.nil?}" } %resolve-count{ "inline-template" => true, ":logged-out" => "#{current_user.nil?}" }
.line-resolve-all{ "v-show" => "discussionCount > 0", .line-resolve-all{ "v-show" => "discussionCount > 0",
":class" => "{ 'has-next-btn': !loggedOut && resolved !== discussionCount }" } ":class" => "{ 'has-next-btn': !loggedOut && resolvedDiscussionCount !== discussionCount }" }
%span.line-resolve-btn.is-disabled{ type: "button", %span.line-resolve-btn.is-disabled{ type: "button",
":class" => "{ 'is-active': resolved === discussionCount }" } ":class" => "{ 'is-active': resolvedDiscussionCount === discussionCount }" }
= icon("check") = icon("check")
%span.line-resolve-text %span.line-resolve-text
{{ resolved }}/{{ discussionCount }} {{ discussionCount | pluralize 'discussion' }} resolved {{ resolvedDiscussionCount }}/{{ discussionCount }} {{ discussionCount | pluralize 'discussion' }} resolved
= render "discussions/jump_to_next" = render "discussions/jump_to_next"
.tab-content#diff-notes-app .tab-content#diff-notes-app