Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
f9e0a822
Commit
f9e0a822
authored
Jan 30, 2020
by
Justin Boyson
Committed by
Mike Greiling
Jan 30, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor navigation logic into mixin
Move jump logic into mixin. Remove logic from consuming components.
parent
b4dbb874
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
76 additions
and
157 deletions
+76
-157
app/assets/javascripts/diff_notes/components/jump_to_discussion.js
...s/javascripts/diff_notes/components/jump_to_discussion.js
+2
-2
app/assets/javascripts/mr_notes/init_notes.js
app/assets/javascripts/mr_notes/init_notes.js
+1
-3
app/assets/javascripts/notes/components/discussion_actions.vue
...ssets/javascripts/notes/components/discussion_actions.vue
+1
-1
app/assets/javascripts/notes/components/discussion_counter.vue
...ssets/javascripts/notes/components/discussion_counter.vue
+3
-15
app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
...ripts/notes/components/discussion_jump_to_next_button.vue
+4
-2
app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue
...cripts/notes/components/discussion_keyboard_navigator.vue
+2
-37
app/assets/javascripts/notes/components/noteable_discussion.vue
...sets/javascripts/notes/components/noteable_discussion.vue
+1
-17
app/assets/javascripts/notes/mixins/discussion_navigation.js
app/assets/javascripts/notes/mixins/discussion_navigation.js
+29
-0
app/assets/javascripts/notes/stores/actions.js
app/assets/javascripts/notes/stores/actions.js
+3
-0
app/assets/javascripts/notes/stores/getters.js
app/assets/javascripts/notes/stores/getters.js
+0
-1
app/assets/javascripts/notes/stores/modules/index.js
app/assets/javascripts/notes/stores/modules/index.js
+1
-1
app/assets/javascripts/notes/stores/mutation_types.js
app/assets/javascripts/notes/stores/mutation_types.js
+1
-0
app/assets/javascripts/notes/stores/mutations.js
app/assets/javascripts/notes/stores/mutations.js
+4
-1
changelogs/unreleased/jdb-cycle-unresolved-threads.yml
changelogs/unreleased/jdb-cycle-unresolved-threads.yml
+5
-0
doc/user/discussions/index.md
doc/user/discussions/index.md
+1
-1
locale/gitlab.pot
locale/gitlab.pot
+3
-3
spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
.../user_resolves_diff_notes_and_discussions_resolve_spec.rb
+0
-10
spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
...__snapshots__/discussion_jump_to_next_button_spec.js.snap
+1
-1
spec/frontend/notes/components/discussion_actions_spec.js
spec/frontend/notes/components/discussion_actions_spec.js
+0
-9
spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
...d/notes/components/discussion_jump_to_next_button_spec.js
+0
-11
spec/frontend/notes/components/discussion_keyboard_navigator_spec.js
...nd/notes/components/discussion_keyboard_navigator_spec.js
+7
-5
spec/frontend/notes/stores/mutation_spec.js
spec/frontend/notes/stores/mutation_spec.js
+0
-2
spec/javascripts/notes/components/discussion_counter_spec.js
spec/javascripts/notes/components/discussion_counter_spec.js
+7
-4
spec/javascripts/notes/components/noteable_discussion_spec.js
.../javascripts/notes/components/noteable_discussion_spec.js
+0
-31
No files found.
app/assets/javascripts/diff_notes/components/jump_to_discussion.js
View file @
f9e0a822
...
@@ -24,9 +24,9 @@ const JumpToDiscussion = Vue.extend({
...
@@ -24,9 +24,9 @@ const JumpToDiscussion = Vue.extend({
computed
:
{
computed
:
{
buttonText
()
{
buttonText
()
{
if
(
this
.
discussionId
)
{
if
(
this
.
discussionId
)
{
return
__
(
'
Jump to next unresolved
discussion
'
);
return
__
(
'
Jump to next unresolved
thread
'
);
}
else
{
}
else
{
return
__
(
'
Jump to first unresolved
discussion
'
);
return
__
(
'
Jump to first unresolved
thread
'
);
}
}
},
},
allResolved
()
{
allResolved
()
{
...
...
app/assets/javascripts/mr_notes/init_notes.js
View file @
f9e0a822
...
@@ -69,13 +69,11 @@ export default () => {
...
@@ -69,13 +69,11 @@ export default () => {
},
},
},
},
render
(
createElement
)
{
render
(
createElement
)
{
const
isDiffView
=
this
.
activeTab
===
'
diffs
'
;
// NOTE: Even though `discussionKeyboardNavigator` is added to the `notes-app`,
// NOTE: Even though `discussionKeyboardNavigator` is added to the `notes-app`,
// it adds a global key listener so it works on the diffs tab as well.
// it adds a global key listener so it works on the diffs tab as well.
// If we create a single Vue app for all of the MR tabs, we should move this
// If we create a single Vue app for all of the MR tabs, we should move this
// up the tree, to the root.
// up the tree, to the root.
return
createElement
(
discussionKeyboardNavigator
,
{
props
:
{
isDiffView
}
},
[
return
createElement
(
discussionKeyboardNavigator
,
[
createElement
(
'
notes-app
'
,
{
createElement
(
'
notes-app
'
,
{
props
:
{
props
:
{
noteableData
:
this
.
noteableData
,
noteableData
:
this
.
noteableData
,
...
...
app/assets/javascripts/notes/components/discussion_actions.vue
View file @
f9e0a822
...
@@ -73,7 +73,7 @@ export default {
...
@@ -73,7 +73,7 @@ export default {
v-if=
"discussion.resolvable && shouldShowJumpToNextDiscussion"
v-if=
"discussion.resolvable && shouldShowJumpToNextDiscussion"
class=
"btn-group discussion-actions ml-sm-2"
class=
"btn-group discussion-actions ml-sm-2"
>
>
<jump-to-next-discussion-button
@
onClick=
"$emit('jumpToNextDiscussion')"
/>
<jump-to-next-discussion-button
/>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
app/assets/javascripts/notes/components/discussion_counter.vue
View file @
f9e0a822
<
script
>
<
script
>
import
{
map
Actions
,
map
Getters
}
from
'
vuex
'
;
import
{
mapGetters
}
from
'
vuex
'
;
import
{
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
{
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
discussionNavigation
from
'
../mixins/discussion_navigation
'
;
import
discussionNavigation
from
'
../mixins/discussion_navigation
'
;
...
@@ -17,9 +17,7 @@ export default {
...
@@ -17,9 +17,7 @@ export default {
'
getUserData
'
,
'
getUserData
'
,
'
getNoteableData
'
,
'
getNoteableData
'
,
'
resolvableDiscussionsCount
'
,
'
resolvableDiscussionsCount
'
,
'
firstUnresolvedDiscussionId
'
,
'
unresolvedDiscussionsCount
'
,
'
unresolvedDiscussionsCount
'
,
'
getDiscussion
'
,
]),
]),
isLoggedIn
()
{
isLoggedIn
()
{
return
this
.
getUserData
.
id
;
return
this
.
getUserData
.
id
;
...
@@ -37,16 +35,6 @@ export default {
...
@@ -37,16 +35,6 @@ export default {
return
this
.
resolvableDiscussionsCount
-
this
.
unresolvedDiscussionsCount
;
return
this
.
resolvableDiscussionsCount
-
this
.
unresolvedDiscussionsCount
;
},
},
},
},
methods
:
{
...
mapActions
([
'
expandDiscussion
'
]),
jumpToFirstUnresolvedDiscussion
()
{
const
diffTab
=
window
.
mrTabs
.
currentAction
===
'
diffs
'
;
const
discussionId
=
this
.
firstUnresolvedDiscussionId
(
diffTab
)
||
this
.
firstUnresolvedDiscussionId
();
const
firstDiscussion
=
this
.
getDiscussion
(
discussionId
);
this
.
jumpToDiscussion
(
firstDiscussion
);
},
},
};
};
</
script
>
</
script
>
...
@@ -83,9 +71,9 @@ export default {
...
@@ -83,9 +71,9 @@ export default {
<div
v-if=
"isLoggedIn && !allResolved"
class=
"btn-group btn-group-sm"
role=
"group"
>
<div
v-if=
"isLoggedIn && !allResolved"
class=
"btn-group btn-group-sm"
role=
"group"
>
<button
<button
v-gl-tooltip
v-gl-tooltip
title=
"Jump to
firs
t unresolved thread"
title=
"Jump to
nex
t unresolved thread"
class=
"btn btn-default discussion-next-btn"
class=
"btn btn-default discussion-next-btn"
@
click=
"jumpTo
FirstUnresolved
Discussion"
@
click=
"jumpTo
Next
Discussion"
>
>
<icon
name=
"comment-next"
/>
<icon
name=
"comment-next"
/>
</button>
</button>
...
...
app/assets/javascripts/notes/components/discussion_jump_to_next_button.vue
View file @
f9e0a822
<
script
>
<
script
>
import
{
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
{
GlTooltipDirective
}
from
'
@gitlab/ui
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
discussionNavigation
from
'
../mixins/discussion_navigation
'
;
export
default
{
export
default
{
name
:
'
JumpToNextDiscussionButton
'
,
name
:
'
JumpToNextDiscussionButton
'
,
...
@@ -10,6 +11,7 @@ export default {
...
@@ -10,6 +11,7 @@ export default {
directives
:
{
directives
:
{
GlTooltip
:
GlTooltipDirective
,
GlTooltip
:
GlTooltipDirective
,
},
},
mixins
:
[
discussionNavigation
],
};
};
</
script
>
</
script
>
...
@@ -19,8 +21,8 @@ export default {
...
@@ -19,8 +21,8 @@ export default {
ref=
"button"
ref=
"button"
v-gl-tooltip
v-gl-tooltip
class=
"btn btn-default discussion-next-btn"
class=
"btn btn-default discussion-next-btn"
:title=
"s__('MergeRequests|Jump to next unresolved
discussion
')"
:title=
"s__('MergeRequests|Jump to next unresolved
thread
')"
@
click=
"
$emit('onClick')
"
@
click=
"
jumpToNextDiscussion
"
>
>
<icon
name=
"comment-next"
/>
<icon
name=
"comment-next"
/>
</button>
</button>
...
...
app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue
View file @
f9e0a822
<
script
>
<
script
>
/* global Mousetrap */
/* global Mousetrap */
import
'
mousetrap
'
;
import
'
mousetrap
'
;
import
{
mapGetters
,
mapActions
}
from
'
vuex
'
;
import
discussionNavigation
from
'
~/notes/mixins/discussion_navigation
'
;
import
discussionNavigation
from
'
~/notes/mixins/discussion_navigation
'
;
export
default
{
export
default
{
mixins
:
[
discussionNavigation
],
mixins
:
[
discussionNavigation
],
props
:
{
isDiffView
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
data
()
{
return
{
currentDiscussionId
:
null
,
};
},
computed
:
{
...
mapGetters
([
'
nextUnresolvedDiscussionId
'
,
'
previousUnresolvedDiscussionId
'
,
'
getDiscussion
'
,
]),
},
mounted
()
{
mounted
()
{
Mousetrap
.
bind
(
'
n
'
,
()
=>
this
.
jumpToNextDiscussion
()
);
Mousetrap
.
bind
(
'
n
'
,
this
.
jumpToNextDiscussion
);
Mousetrap
.
bind
(
'
p
'
,
()
=>
this
.
jumpToPreviousDiscussion
()
);
Mousetrap
.
bind
(
'
p
'
,
this
.
jumpToPreviousDiscussion
);
},
},
beforeDestroy
()
{
beforeDestroy
()
{
Mousetrap
.
unbind
(
'
n
'
);
Mousetrap
.
unbind
(
'
n
'
);
Mousetrap
.
unbind
(
'
p
'
);
Mousetrap
.
unbind
(
'
p
'
);
},
},
methods
:
{
...
mapActions
([
'
expandDiscussion
'
]),
jumpToNextDiscussion
()
{
const
nextId
=
this
.
nextUnresolvedDiscussionId
(
this
.
currentDiscussionId
,
this
.
isDiffView
);
const
nextDiscussion
=
this
.
getDiscussion
(
nextId
);
this
.
jumpToDiscussion
(
nextDiscussion
);
this
.
currentDiscussionId
=
nextId
;
},
jumpToPreviousDiscussion
()
{
const
prevId
=
this
.
previousUnresolvedDiscussionId
(
this
.
currentDiscussionId
,
this
.
isDiffView
);
const
prevDiscussion
=
this
.
getDiscussion
(
prevId
);
this
.
jumpToDiscussion
(
prevDiscussion
);
this
.
currentDiscussionId
=
prevId
;
},
},
render
()
{
render
()
{
return
this
.
$slots
.
default
;
return
this
.
$slots
.
default
;
},
},
...
...
app/assets/javascripts/notes/components/noteable_discussion.vue
View file @
f9e0a822
...
@@ -14,7 +14,6 @@ import noteForm from './note_form.vue';
...
@@ -14,7 +14,6 @@ import noteForm from './note_form.vue';
import
diffWithNote
from
'
./diff_with_note.vue
'
;
import
diffWithNote
from
'
./diff_with_note.vue
'
;
import
noteable
from
'
../mixins/noteable
'
;
import
noteable
from
'
../mixins/noteable
'
;
import
resolvable
from
'
../mixins/resolvable
'
;
import
resolvable
from
'
../mixins/resolvable
'
;
import
discussionNavigation
from
'
../mixins/discussion_navigation
'
;
import
eventHub
from
'
../event_hub
'
;
import
eventHub
from
'
../event_hub
'
;
import
DiscussionNotes
from
'
./discussion_notes.vue
'
;
import
DiscussionNotes
from
'
./discussion_notes.vue
'
;
import
DiscussionActions
from
'
./discussion_actions.vue
'
;
import
DiscussionActions
from
'
./discussion_actions.vue
'
;
...
@@ -35,7 +34,7 @@ export default {
...
@@ -35,7 +34,7 @@ export default {
directives
:
{
directives
:
{
GlTooltip
:
GlTooltipDirective
,
GlTooltip
:
GlTooltipDirective
,
},
},
mixins
:
[
noteable
,
resolvable
,
di
scussionNavigation
,
di
ffLineNoteFormMixin
],
mixins
:
[
noteable
,
resolvable
,
diffLineNoteFormMixin
],
props
:
{
props
:
{
discussion
:
{
discussion
:
{
type
:
Object
,
type
:
Object
,
...
@@ -79,12 +78,8 @@ export default {
...
@@ -79,12 +78,8 @@ export default {
'
convertedDisscussionIds
'
,
'
convertedDisscussionIds
'
,
'
getNoteableData
'
,
'
getNoteableData
'
,
'
userCanReply
'
,
'
userCanReply
'
,
'
nextUnresolvedDiscussionId
'
,
'
unresolvedDiscussionsCount
'
,
'
hasUnresolvedDiscussions
'
,
'
showJumpToNextDiscussion
'
,
'
showJumpToNextDiscussion
'
,
'
getUserData
'
,
'
getUserData
'
,
'
getDiscussion
'
,
]),
]),
currentUser
()
{
currentUser
()
{
return
this
.
getUserData
;
return
this
.
getUserData
;
...
@@ -152,7 +147,6 @@ export default {
...
@@ -152,7 +147,6 @@ export default {
'
saveNote
'
,
'
saveNote
'
,
'
removePlaceholderNotes
'
,
'
removePlaceholderNotes
'
,
'
toggleResolveNote
'
,
'
toggleResolveNote
'
,
'
expandDiscussion
'
,
'
removeConvertedDiscussion
'
,
'
removeConvertedDiscussion
'
,
]),
]),
showReplyForm
()
{
showReplyForm
()
{
...
@@ -219,15 +213,6 @@ export default {
...
@@ -219,15 +213,6 @@ export default {
callback
(
err
);
callback
(
err
);
});
});
},
},
jumpToNextDiscussion
()
{
const
nextId
=
this
.
nextUnresolvedDiscussionId
(
this
.
discussion
.
id
,
this
.
discussionsByDiffOrder
,
);
const
nextDiscussion
=
this
.
getDiscussion
(
nextId
);
this
.
jumpToDiscussion
(
nextDiscussion
);
},
deleteNoteHandler
(
note
)
{
deleteNoteHandler
(
note
)
{
this
.
$emit
(
'
noteDeleted
'
,
this
.
discussion
,
note
);
this
.
$emit
(
'
noteDeleted
'
,
this
.
discussion
,
note
);
},
},
...
@@ -294,7 +279,6 @@ export default {
...
@@ -294,7 +279,6 @@ export default {
:should-show-jump-to-next-discussion=
"shouldShowJumpToNextDiscussion"
:should-show-jump-to-next-discussion=
"shouldShowJumpToNextDiscussion"
@
showReplyForm=
"showReplyForm"
@
showReplyForm=
"showReplyForm"
@
resolve=
"resolveHandler"
@
resolve=
"resolveHandler"
@
jumpToNextDiscussion=
"jumpToNextDiscussion"
/>
/>
<div
v-if=
"isReplying"
class=
"avatar-note-form-holder"
>
<div
v-if=
"isReplying"
class=
"avatar-note-form-holder"
>
<user-avatar-link
<user-avatar-link
...
...
app/assets/javascripts/notes/mixins/discussion_navigation.js
View file @
f9e0a822
import
{
mapGetters
,
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
scrollToElement
}
from
'
~/lib/utils/common_utils
'
;
import
{
scrollToElement
}
from
'
~/lib/utils/common_utils
'
;
import
eventHub
from
'
../../notes/event_hub
'
;
import
eventHub
from
'
../../notes/event_hub
'
;
export
default
{
export
default
{
computed
:
{
...
mapGetters
([
'
nextUnresolvedDiscussionId
'
,
'
previousUnresolvedDiscussionId
'
,
'
getDiscussion
'
,
]),
...
mapState
({
currentDiscussionId
:
state
=>
state
.
notes
.
currentDiscussionId
,
}),
},
methods
:
{
methods
:
{
...
mapActions
([
'
expandDiscussion
'
,
'
setCurrentDiscussionId
'
]),
diffsJump
(
id
)
{
diffsJump
(
id
)
{
const
selector
=
`ul.notes[data-discussion-id="
${
id
}
"]`
;
const
selector
=
`ul.notes[data-discussion-id="
${
id
}
"]`
;
...
@@ -58,5 +71,21 @@ export default {
...
@@ -58,5 +71,21 @@ export default {
}
}
}
}
},
},
jumpToNextDiscussion
()
{
this
.
handleDiscussionJump
(
this
.
nextUnresolvedDiscussionId
);
},
jumpToPreviousDiscussion
()
{
this
.
handleDiscussionJump
(
this
.
previousUnresolvedDiscussionId
);
},
handleDiscussionJump
(
fn
)
{
const
isDiffView
=
window
.
mrTabs
.
currentAction
===
'
diffs
'
;
const
targetId
=
fn
(
this
.
currentDiscussionId
,
isDiffView
);
const
discussion
=
this
.
getDiscussion
(
targetId
);
this
.
jumpToDiscussion
(
discussion
);
this
.
setCurrentDiscussionId
(
targetId
);
},
},
},
};
};
app/assets/javascripts/notes/stores/actions.js
View file @
f9e0a822
...
@@ -506,5 +506,8 @@ export const fetchDescriptionVersion = (_, { endpoint, startingVersion }) => {
...
@@ -506,5 +506,8 @@ export const fetchDescriptionVersion = (_, { endpoint, startingVersion }) => {
});
});
};
};
export
const
setCurrentDiscussionId
=
({
commit
},
discussionId
)
=>
commit
(
types
.
SET_CURRENT_DISCUSSION_ID
,
discussionId
);
// prevent babel-plugin-rewire from generating an invalid default during karma tests
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export
default
()
=>
{};
export
default
()
=>
{};
app/assets/javascripts/notes/stores/getters.js
View file @
f9e0a822
...
@@ -59,7 +59,6 @@ export const getDiscussionLastNote = state => discussion =>
...
@@ -59,7 +59,6 @@ export const getDiscussionLastNote = state => discussion =>
export
const
unresolvedDiscussionsCount
=
state
=>
state
.
unresolvedDiscussionsCount
;
export
const
unresolvedDiscussionsCount
=
state
=>
state
.
unresolvedDiscussionsCount
;
export
const
resolvableDiscussionsCount
=
state
=>
state
.
resolvableDiscussionsCount
;
export
const
resolvableDiscussionsCount
=
state
=>
state
.
resolvableDiscussionsCount
;
export
const
hasUnresolvedDiscussions
=
state
=>
state
.
hasUnresolvedDiscussions
;
export
const
showJumpToNextDiscussion
=
(
state
,
getters
)
=>
(
mode
=
'
discussion
'
)
=>
{
export
const
showJumpToNextDiscussion
=
(
state
,
getters
)
=>
(
mode
=
'
discussion
'
)
=>
{
const
orderedDiffs
=
const
orderedDiffs
=
...
...
app/assets/javascripts/notes/stores/modules/index.js
View file @
f9e0a822
...
@@ -8,6 +8,7 @@ export default () => ({
...
@@ -8,6 +8,7 @@ export default () => ({
convertedDisscussionIds
:
[],
convertedDisscussionIds
:
[],
targetNoteHash
:
null
,
targetNoteHash
:
null
,
lastFetchedAt
:
null
,
lastFetchedAt
:
null
,
currentDiscussionId
:
null
,
// View layer
// View layer
isToggleStateButtonLoading
:
false
,
isToggleStateButtonLoading
:
false
,
...
@@ -26,7 +27,6 @@ export default () => ({
...
@@ -26,7 +27,6 @@ export default () => ({
commentsDisabled
:
false
,
commentsDisabled
:
false
,
resolvableDiscussionsCount
:
0
,
resolvableDiscussionsCount
:
0
,
unresolvedDiscussionsCount
:
0
,
unresolvedDiscussionsCount
:
0
,
hasUnresolvedDiscussions
:
false
,
},
},
actions
,
actions
,
getters
,
getters
,
...
...
app/assets/javascripts/notes/stores/mutation_types.js
View file @
f9e0a822
...
@@ -25,6 +25,7 @@ export const COLLAPSE_DISCUSSION = 'COLLAPSE_DISCUSSION';
...
@@ -25,6 +25,7 @@ export const COLLAPSE_DISCUSSION = 'COLLAPSE_DISCUSSION';
export
const
EXPAND_DISCUSSION
=
'
EXPAND_DISCUSSION
'
;
export
const
EXPAND_DISCUSSION
=
'
EXPAND_DISCUSSION
'
;
export
const
TOGGLE_DISCUSSION
=
'
TOGGLE_DISCUSSION
'
;
export
const
TOGGLE_DISCUSSION
=
'
TOGGLE_DISCUSSION
'
;
export
const
UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS
=
'
UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS
'
;
export
const
UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS
=
'
UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS
'
;
export
const
SET_CURRENT_DISCUSSION_ID
=
'
SET_CURRENT_DISCUSSION_ID
'
;
// Issue
// Issue
export
const
CLOSE_ISSUE
=
'
CLOSE_ISSUE
'
;
export
const
CLOSE_ISSUE
=
'
CLOSE_ISSUE
'
;
...
...
app/assets/javascripts/notes/stores/mutations.js
View file @
f9e0a822
...
@@ -267,7 +267,6 @@ export default {
...
@@ -267,7 +267,6 @@ export default {
discussion
.
resolvable
&&
discussion
.
resolvable
&&
discussion
.
notes
.
some
(
note
=>
note
.
resolvable
&&
!
note
.
resolved
),
discussion
.
notes
.
some
(
note
=>
note
.
resolvable
&&
!
note
.
resolved
),
).
length
;
).
length
;
state
.
hasUnresolvedDiscussions
=
state
.
unresolvedDiscussionsCount
>
1
;
},
},
[
types
.
CONVERT_TO_DISCUSSION
](
state
,
discussionId
)
{
[
types
.
CONVERT_TO_DISCUSSION
](
state
,
discussionId
)
{
...
@@ -281,4 +280,8 @@ export default {
...
@@ -281,4 +280,8 @@ export default {
convertedDisscussionIds
.
splice
(
convertedDisscussionIds
.
indexOf
(
discussionId
),
1
);
convertedDisscussionIds
.
splice
(
convertedDisscussionIds
.
indexOf
(
discussionId
),
1
);
Object
.
assign
(
state
,
{
convertedDisscussionIds
});
Object
.
assign
(
state
,
{
convertedDisscussionIds
});
},
},
[
types
.
SET_CURRENT_DISCUSSION_ID
](
state
,
discussionId
)
{
state
.
currentDiscussionId
=
discussionId
;
},
};
};
changelogs/unreleased/jdb-cycle-unresolved-threads.yml
0 → 100644
View file @
f9e0a822
---
title
:
Cycle unresolved threads
merge_request
:
23123
author
:
type
:
changed
doc/user/discussions/index.md
View file @
f9e0a822
...
@@ -89,7 +89,7 @@ When a merge request has a large number of comments it can be difficult to track
...
@@ -89,7 +89,7 @@ When a merge request has a large number of comments it can be difficult to track
what remains unresolved. You can jump between unresolved threads with the
what remains unresolved. You can jump between unresolved threads with the
Jump button next to the Reply field on a thread.
Jump button next to the Reply field on a thread.
You can also jump to the
firs
t unresolved thread from the button next to the
You can also jump to the
nex
t unresolved thread from the button next to the
resolved threads tracker.
resolved threads tracker.
You can also use keyboard shortcuts to navigate among threads:
You can also use keyboard shortcuts to navigate among threads:
...
...
locale/gitlab.pot
View file @
f9e0a822
...
@@ -10770,10 +10770,10 @@ msgstr ""
...
@@ -10770,10 +10770,10 @@ msgstr ""
msgid "July"
msgid "July"
msgstr ""
msgstr ""
msgid "Jump to first unresolved
discussion
"
msgid "Jump to first unresolved
thread
"
msgstr ""
msgstr ""
msgid "Jump to next unresolved
discussion
"
msgid "Jump to next unresolved
thread
"
msgstr ""
msgstr ""
msgid "Jun"
msgid "Jun"
...
@@ -11787,7 +11787,7 @@ msgstr ""
...
@@ -11787,7 +11787,7 @@ msgstr ""
msgid "MergeRequests|Failed to squash. Should be done manually."
msgid "MergeRequests|Failed to squash. Should be done manually."
msgstr ""
msgstr ""
msgid "MergeRequests|Jump to next unresolved
discussion
"
msgid "MergeRequests|Jump to next unresolved
thread
"
msgstr ""
msgstr ""
msgid "MergeRequests|Reply..."
msgid "MergeRequests|Reply..."
...
...
spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
View file @
f9e0a822
...
@@ -368,16 +368,6 @@ describe 'Merge request > User resolves diff notes and threads', :js do
...
@@ -368,16 +368,6 @@ describe 'Merge request > User resolves diff notes and threads', :js do
end
end
end
end
it
'shows jump to next discussion button on all discussions'
do
wait_for_requests
all_discussion_replies
=
page
.
all
(
'.discussion-reply-holder'
)
expect
(
all_discussion_replies
.
count
).
to
eq
(
2
)
expect
(
all_discussion_replies
.
first
.
all
(
'.discussion-next-btn'
).
count
).
to
eq
(
1
)
expect
(
all_discussion_replies
.
last
.
all
(
'.discussion-next-btn'
).
count
).
to
eq
(
1
)
end
it
'displays next thread even if hidden'
do
it
'displays next thread even if hidden'
do
page
.
all
(
'.note-discussion'
,
count:
2
).
each
do
|
discussion
|
page
.
all
(
'.note-discussion'
,
count:
2
).
each
do
|
discussion
|
page
.
within
discussion
do
page
.
within
discussion
do
...
...
spec/frontend/notes/components/__snapshots__/discussion_jump_to_next_button_spec.js.snap
View file @
f9e0a822
...
@@ -7,7 +7,7 @@ exports[`JumpToNextDiscussionButton matches the snapshot 1`] = `
...
@@ -7,7 +7,7 @@ exports[`JumpToNextDiscussionButton matches the snapshot 1`] = `
>
>
<button
<button
class="btn btn-default discussion-next-btn"
class="btn btn-default discussion-next-btn"
title="Jump to next unresolved
discussion
"
title="Jump to next unresolved
thread
"
>
>
<icon-stub
<icon-stub
name="comment-next"
name="comment-next"
...
...
spec/frontend/notes/components/discussion_actions_spec.js
View file @
f9e0a822
...
@@ -120,14 +120,5 @@ describe('DiscussionActions', () => {
...
@@ -120,14 +120,5 @@ describe('DiscussionActions', () => {
.
trigger
(
'
click
'
);
.
trigger
(
'
click
'
);
expect
(
wrapper
.
vm
.
$emit
).
toHaveBeenCalledWith
(
'
resolve
'
);
expect
(
wrapper
.
vm
.
$emit
).
toHaveBeenCalledWith
(
'
resolve
'
);
});
});
it
(
'
emits jumpToNextDiscussion event when clicking on jump to next discussion button
'
,
()
=>
{
jest
.
spyOn
(
wrapper
.
vm
,
'
$emit
'
);
wrapper
.
find
(
JumpToNextDiscussionButton
)
.
find
(
'
button
'
)
.
trigger
(
'
click
'
);
expect
(
wrapper
.
vm
.
$emit
).
toHaveBeenCalledWith
(
'
jumpToNextDiscussion
'
);
});
});
});
});
});
spec/frontend/notes/components/discussion_jump_to_next_button_spec.js
View file @
f9e0a822
...
@@ -15,15 +15,4 @@ describe('JumpToNextDiscussionButton', () => {
...
@@ -15,15 +15,4 @@ describe('JumpToNextDiscussionButton', () => {
it
(
'
matches the snapshot
'
,
()
=>
{
it
(
'
matches the snapshot
'
,
()
=>
{
expect
(
wrapper
.
vm
.
$el
).
toMatchSnapshot
();
expect
(
wrapper
.
vm
.
$el
).
toMatchSnapshot
();
});
});
it
(
'
emits onClick event on button click
'
,
()
=>
{
const
button
=
wrapper
.
find
({
ref
:
'
button
'
});
button
.
trigger
(
'
click
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
wrapper
.
emitted
().
onClick
).
toBeTruthy
();
expect
(
wrapper
.
emitted
().
onClick
.
length
).
toBe
(
1
);
});
});
});
});
spec/frontend/notes/components/discussion_keyboard_navigator_spec.js
View file @
f9e0a822
...
@@ -53,13 +53,15 @@ describe('notes/components/discussion_keyboard_navigator', () => {
...
@@ -53,13 +53,15 @@ describe('notes/components/discussion_keyboard_navigator', () => {
});
});
describe
.
each
`
describe
.
each
`
isDiffView
| expectedNextId | expectedPrevId
currentAction
| expectedNextId | expectedPrevId
${
true
}
|
${
NEXT_DIFF_ID
}
|
${
PREV_DIFF_ID
}
${
'
diffs
'
}
|
${
NEXT_DIFF_ID
}
|
${
PREV_DIFF_ID
}
${
false
}
|
${
NEXT_ID
}
|
${
PREV_ID
}
${
'
show
'
}
|
${
NEXT_ID
}
|
${
PREV_ID
}
`
(
'
when isDiffView is $isDiffView
'
,
({
isDiffView
,
expectedNextId
,
expectedPrevId
})
=>
{
`
(
'
when isDiffView is $isDiffView
'
,
({
currentAction
,
expectedNextId
,
expectedPrevId
})
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
createComponent
({
propsData
:
{
isDiffView
}
});
window
.
mrTabs
=
{
currentAction
};
createComponent
();
});
});
afterEach
(()
=>
delete
window
.
mrTabs
);
it
(
'
calls jumpToNextDiscussion when pressing `n`
'
,
()
=>
{
it
(
'
calls jumpToNextDiscussion when pressing `n`
'
,
()
=>
{
Mousetrap
.
trigger
(
'
n
'
);
Mousetrap
.
trigger
(
'
n
'
);
...
...
spec/frontend/notes/stores/mutation_spec.js
View file @
f9e0a822
...
@@ -501,7 +501,6 @@ describe('Notes Store mutations', () => {
...
@@ -501,7 +501,6 @@ describe('Notes Store mutations', () => {
expect
.
objectContaining
({
expect
.
objectContaining
({
resolvableDiscussionsCount
:
1
,
resolvableDiscussionsCount
:
1
,
unresolvedDiscussionsCount
:
1
,
unresolvedDiscussionsCount
:
1
,
hasUnresolvedDiscussions
:
false
,
}),
}),
);
);
});
});
...
@@ -538,7 +537,6 @@ describe('Notes Store mutations', () => {
...
@@ -538,7 +537,6 @@ describe('Notes Store mutations', () => {
expect
.
objectContaining
({
expect
.
objectContaining
({
resolvableDiscussionsCount
:
4
,
resolvableDiscussionsCount
:
4
,
unresolvedDiscussionsCount
:
2
,
unresolvedDiscussionsCount
:
2
,
hasUnresolvedDiscussions
:
true
,
}),
}),
);
);
});
});
...
...
spec/javascripts/notes/components/discussion_counter_spec.js
View file @
f9e0a822
...
@@ -7,6 +7,7 @@ import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
...
@@ -7,6 +7,7 @@ import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
describe
(
'
DiscussionCounter component
'
,
()
=>
{
describe
(
'
DiscussionCounter component
'
,
()
=>
{
let
store
;
let
store
;
let
vm
;
let
vm
;
const
notes
=
{
currentDiscussionId
:
null
};
beforeEach
(()
=>
{
beforeEach
(()
=>
{
window
.
mrTabs
=
{};
window
.
mrTabs
=
{};
...
@@ -25,7 +26,7 @@ describe('DiscussionCounter component', () => {
...
@@ -25,7 +26,7 @@ describe('DiscussionCounter component', () => {
});
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
methods
'
,
()
=>
{
describe
(
'
jumpTo
FirstUnresolved
Discussion
'
,
()
=>
{
describe
(
'
jumpTo
Next
Discussion
'
,
()
=>
{
it
(
'
expands unresolved discussion
'
,
()
=>
{
it
(
'
expands unresolved discussion
'
,
()
=>
{
window
.
mrTabs
.
currentAction
=
'
show
'
;
window
.
mrTabs
.
currentAction
=
'
show
'
;
...
@@ -48,13 +49,14 @@ describe('DiscussionCounter component', () => {
...
@@ -48,13 +49,14 @@ describe('DiscussionCounter component', () => {
store
.
replaceState
({
store
.
replaceState
({
...
store
.
state
,
...
store
.
state
,
discussions
,
discussions
,
notes
,
});
});
vm
.
jumpTo
FirstUnresolved
Discussion
();
vm
.
jumpTo
Next
Discussion
();
expect
(
vm
.
expandDiscussion
).
toHaveBeenCalledWith
({
discussionId
:
firstDiscussionId
});
expect
(
vm
.
expandDiscussion
).
toHaveBeenCalledWith
({
discussionId
:
firstDiscussionId
});
});
});
it
(
'
jumps to
firs
t unresolved discussion from diff tab if all diff discussions are resolved
'
,
()
=>
{
it
(
'
jumps to
nex
t unresolved discussion from diff tab if all diff discussions are resolved
'
,
()
=>
{
window
.
mrTabs
.
currentAction
=
'
diff
'
;
window
.
mrTabs
.
currentAction
=
'
diff
'
;
spyOn
(
vm
,
'
switchToDiscussionsTabAndJumpTo
'
).
and
.
stub
();
spyOn
(
vm
,
'
switchToDiscussionsTabAndJumpTo
'
).
and
.
stub
();
...
@@ -77,8 +79,9 @@ describe('DiscussionCounter component', () => {
...
@@ -77,8 +79,9 @@ describe('DiscussionCounter component', () => {
store
.
replaceState
({
store
.
replaceState
({
...
store
.
state
,
...
store
.
state
,
discussions
,
discussions
,
notes
,
});
});
vm
.
jumpTo
FirstUnresolved
Discussion
();
vm
.
jumpTo
Next
Discussion
();
expect
(
vm
.
switchToDiscussionsTabAndJumpTo
).
toHaveBeenCalledWith
(
unresolvedId
);
expect
(
vm
.
switchToDiscussionsTabAndJumpTo
).
toHaveBeenCalledWith
(
unresolvedId
);
});
});
...
...
spec/javascripts/notes/components/noteable_discussion_spec.js
View file @
f9e0a822
...
@@ -101,37 +101,6 @@ describe('noteable_discussion component', () => {
...
@@ -101,37 +101,6 @@ describe('noteable_discussion component', () => {
});
});
});
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
jumpToNextDiscussion
'
,
()
=>
{
it
(
'
expands next unresolved thread
'
,
done
=>
{
const
discussion2
=
getJSONFixture
(
discussionWithTwoUnresolvedNotes
)[
0
];
discussion2
.
resolved
=
false
;
discussion2
.
active
=
true
;
discussion2
.
id
=
'
next
'
;
// prepare this for being identified as next one (to be jumped to)
store
.
dispatch
(
'
setInitialNotes
'
,
[
discussionMock
,
discussion2
]);
window
.
mrTabs
.
currentAction
=
'
show
'
;
wrapper
.
vm
.
$nextTick
()
.
then
(()
=>
{
spyOn
(
wrapper
.
vm
,
'
expandDiscussion
'
).
and
.
stub
();
const
nextDiscussionId
=
discussion2
.
id
;
setFixtures
(
`<div class="discussion" data-discussion-id="
${
nextDiscussionId
}
"></div>`
);
wrapper
.
vm
.
jumpToNextDiscussion
();
expect
(
wrapper
.
vm
.
expandDiscussion
).
toHaveBeenCalledWith
({
discussionId
:
nextDiscussionId
,
});
})
.
then
(
done
)
.
catch
(
done
.
fail
);
});
});
});
describe
(
'
for resolved thread
'
,
()
=>
{
describe
(
'
for resolved thread
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
const
discussion
=
getJSONFixture
(
discussionWithTwoUnresolvedNotes
)[
0
];
const
discussion
=
getJSONFixture
(
discussionWithTwoUnresolvedNotes
)[
0
];
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment