Merge branch 'winh-reply-button-focus' into 'master'

Focus reply field when clicking "reply to comment" button

See merge request gitlab-org/gitlab-ce!24867
This commit is contained in:
Phil Hughes 2019-02-18 09:43:13 +00:00
commit e49ff61571
6 changed files with 37 additions and 49 deletions

View file

@ -23,11 +23,6 @@ export default {
type: [String, Number],
required: true,
},
discussionId: {
type: String,
required: false,
default: '',
},
noteUrl: {
type: String,
required: false,
@ -176,7 +171,7 @@ export default {
v-if="showReplyButton"
ref="replyButton"
class="js-reply-button"
:note-id="discussionId"
@startReplying="$emit('startReplying')"
/>
<div v-if="canEdit" class="note-actions-item">
<button

View file

@ -1,5 +1,4 @@
<script>
import { mapActions } from 'vuex';
import { GlTooltipDirective, GlButton } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
@ -12,15 +11,6 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
noteId: {
type: String,
required: true,
},
},
methods: {
...mapActions(['convertToDiscussion']),
},
};
</script>
@ -32,7 +22,7 @@ export default {
class="note-action-button"
variant="transparent"
:title="__('Reply to comment')"
@click="convertToDiscussion(noteId)"
@click="$emit('startReplying')"
>
<icon name="comment" css-classes="link-highlight" />
</gl-button>

View file

@ -26,6 +26,7 @@ import resolvable from '../mixins/resolvable';
import discussionNavigation from '../mixins/discussion_navigation';
import ReplyPlaceholder from './discussion_reply_placeholder.vue';
import jumpToNextDiscussionButton from './discussion_jump_to_next_button.vue';
import eventHub from '../event_hub';
export default {
name: 'NoteableDiscussion',
@ -246,6 +247,12 @@ export default {
}
},
},
created() {
eventHub.$on('startReplying', this.onStartReplying);
},
beforeDestroy() {
eventHub.$off('startReplying', this.onStartReplying);
},
methods: {
...mapActions([
'saveNote',
@ -350,6 +357,11 @@ Please check your network connection and try again.`;
deleteNoteHandler(note) {
this.$emit('noteDeleted', this.discussion, note);
},
onStartReplying(discussionId) {
if (this.discussion.id === discussionId) {
this.showReplyForm();
}
},
},
};
</script>
@ -412,6 +424,7 @@ Please check your network connection and try again.`;
:help-page-path="helpPagePath"
:show-reply-button="canReply"
@handleDeleteNote="deleteNoteHandler"
@startReplying="showReplyForm"
>
<note-edited-text
v-if="discussion.resolved"

View file

@ -29,11 +29,6 @@ export default {
type: Object,
required: true,
},
discussion: {
type: Object,
required: false,
default: null,
},
line: {
type: Object,
required: false,
@ -49,6 +44,11 @@ export default {
required: false,
default: () => null,
},
showReplyButton: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
@ -91,13 +91,6 @@ export default {
}
return '';
},
showReplyButton() {
if (!this.discussion || !this.getNoteableData.current_user.can_create_note) {
return false;
}
return this.discussion.individual_note && !this.commentsDisabled;
},
actionText() {
if (!this.commit) {
return '';
@ -260,10 +253,10 @@ export default {
:is-resolved="note.resolved"
:is-resolving="isResolving"
:resolved-by="note.resolved_by"
:discussion-id="discussionId"
@handleEdit="editHandler"
@handleDelete="deleteHandler"
@handleResolve="resolveHandler"
@startReplying="$emit('startReplying')"
/>
</div>
<div class="timeline-discussion-body">

View file

@ -64,6 +64,7 @@ export default {
'getNotesDataByProp',
'isLoading',
'commentsDisabled',
'getNoteableData',
]),
noteableType() {
return this.noteableData.noteableType;
@ -79,6 +80,9 @@ export default {
return this.discussions;
},
canReply() {
return this.getNoteableData.current_user.can_create_note && !this.commentsDisabled;
},
},
watch: {
shouldShow() {
@ -129,6 +133,7 @@ export default {
'setNotesFetchedState',
'expandDiscussion',
'startTaskList',
'convertToDiscussion',
]),
fetchNotes() {
if (this.isFetching) return null;
@ -176,6 +181,11 @@ export default {
}
}
},
startReplying(discussionId) {
return this.convertToDiscussion(discussionId)
.then(() => this.$nextTick())
.then(() => eventHub.$emit('startReplying', discussionId));
},
},
systemNote: constants.SYSTEM_NOTE,
};
@ -206,7 +216,8 @@ export default {
v-else
:key="discussion.id"
:note="discussion.notes[0]"
:discussion="discussion"
:show-reply-button="canReply"
@startReplying="startReplying(discussion.id)"
/>
</template>
<noteable-discussion

View file

@ -3,27 +3,14 @@ import { createLocalVue, mount } from '@vue/test-utils';
import ReplyButton from '~/notes/components/note_actions/reply_button.vue';
describe('ReplyButton', () => {
const noteId = 'dummy-note-id';
let wrapper;
let convertToDiscussion;
beforeEach(() => {
const localVue = createLocalVue();
convertToDiscussion = jasmine.createSpy('convertToDiscussion');
localVue.use(Vuex);
const store = new Vuex.Store({
actions: {
convertToDiscussion,
},
});
wrapper = mount(ReplyButton, {
propsData: {
noteId,
},
store,
sync: false,
localVue,
});
@ -33,14 +20,13 @@ describe('ReplyButton', () => {
wrapper.destroy();
});
it('dispatches convertToDiscussion with note ID on click', () => {
it('emits startReplying on click', () => {
const button = wrapper.find({ ref: 'button' });
button.trigger('click');
expect(convertToDiscussion).toHaveBeenCalledTimes(1);
const [, payload] = convertToDiscussion.calls.argsFor(0);
expect(payload).toBe(noteId);
expect(wrapper.emitted()).toEqual({
startReplying: [[]],
});
});
});