summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/notes/components
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/notes/components')
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue15
-rw-r--r--app/assets/javascripts/notes/components/diff_discussion_header.vue7
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue105
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue81
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue5
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue3
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue13
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue5
-rw-r--r--app/assets/javascripts/notes/components/sort_discussion.vue53
-rw-r--r--app/assets/javascripts/notes/components/timeline_toggle.vue60
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue10
12 files changed, 211 insertions, 148 deletions
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 54fcf41ca50..cfdadbceaf6 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -371,6 +371,7 @@ export default {
:markdown-docs-path="markdownDocsPath"
:quick-actions-docs-path="quickActionsDocsPath"
:add-spacing-classes="false"
+ :textarea-value="note"
>
<textarea
id="note-body"
@@ -380,7 +381,8 @@ export default {
dir="auto"
:disabled="isSubmitting"
name="note[note]"
- class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area qa-comment-input"
+ class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area"
+ data-qa-selector="comment_field"
data-supports-quick-actions="true"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@@ -425,7 +427,8 @@ export default {
>
<gl-button
:disabled="isSubmitButtonDisabled"
- class="js-comment-button js-comment-submit-button qa-comment-button"
+ class="js-comment-button js-comment-submit-button"
+ data-qa-selector="comment_button"
type="submit"
category="primary"
variant="success"
@@ -439,7 +442,8 @@ export default {
name="button"
category="primary"
variant="success"
- class="note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown"
+ class="note-type-toggle js-note-new-discussion dropdown-toggle"
+ data-qa-selector="note_dropdown"
data-display="static"
data-toggle="dropdown"
icon="chevron-down"
@@ -468,7 +472,10 @@ export default {
</li>
<li class="divider droplab-item-ignore"></li>
<li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
- <button class="qa-discussion-option" @click.prevent="setNoteType('discussion')">
+ <button
+ data-qa-selector="discussion_menu_item"
+ @click.prevent="setNoteType('discussion')"
+ >
<i aria-hidden="true" class="fa fa-check icon"></i>
<div class="description">
<strong>{{ __('Start thread') }}</strong>
diff --git a/app/assets/javascripts/notes/components/diff_discussion_header.vue b/app/assets/javascripts/notes/components/diff_discussion_header.vue
index 8e6c01ba63f..ee39a529345 100644
--- a/app/assets/javascripts/notes/components/diff_discussion_header.vue
+++ b/app/assets/javascripts/notes/components/diff_discussion_header.vue
@@ -1,7 +1,7 @@
<script>
-/* eslint-disable vue/no-v-html */
import { mapActions } from 'vuex';
import { escape } from 'lodash';
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import { truncateSha } from '~/lib/utils/text_utility';
@@ -17,6 +17,9 @@ export default {
noteEditedText,
noteHeader,
},
+ directives: {
+ SafeHtml,
+ },
props: {
discussion: {
type: Object,
@@ -113,7 +116,7 @@ export default {
:expanded="discussion.expanded"
@toggleHandler="toggleDiscussionHandler"
>
- <span v-html="headerText"></span>
+ <span v-safe-html="headerText"></span>
</note-header>
<note-edited-text
v-if="discussion.resolved"
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index c01cd8f8037..a4271852563 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -76,7 +76,7 @@ export default {
:discussion-path="discussion.discussion_path"
:diff-file="discussion.diff_file"
:can-current-user-fork="false"
- :expanded="!discussion.diff_file.viewer.collapsed"
+ :expanded="!discussion.diff_file.viewer.automaticallyCollapsed"
/>
<div v-if="isTextFile" class="diff-content">
<table class="code js-syntax-highlight" :class="$options.userColorSchemeClass">
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index c6fab271376..2427a3f98ad 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -1,6 +1,7 @@
<script>
import { mapGetters, mapActions } from 'vuex';
-import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlButton, GlButtonGroup } from '@gitlab/ui';
+import { __ } from '~/locale';
import discussionNavigation from '../mixins/discussion_navigation';
export default {
@@ -9,6 +10,8 @@ export default {
},
components: {
GlIcon,
+ GlButton,
+ GlButtonGroup,
},
mixins: [discussionNavigation],
computed: {
@@ -34,6 +37,12 @@ export default {
allExpanded() {
return this.toggeableDiscussions.every(discussion => discussion.expanded);
},
+ lineResolveClass() {
+ return this.allResolved ? 'line-resolve-btn is-active' : 'line-resolve-text';
+ },
+ toggleThreadsLabel() {
+ return this.allExpanded ? __('Collapse all threads') : __('Expand all threads');
+ },
},
methods: {
...mapActions(['setExpandDiscussions']),
@@ -51,59 +60,49 @@ export default {
<div
v-if="resolvableDiscussionsCount > 0"
ref="discussionCounter"
- class="line-resolve-all-container full-width-mobile"
+ class="line-resolve-all-container full-width-mobile gl-display-flex d-sm-flex"
>
- <div class="full-width-mobile d-flex d-sm-flex">
- <div class="line-resolve-all">
- <span
- :class="{ 'line-resolve-btn is-active': allResolved, 'line-resolve-text': !allResolved }"
- >
- <template v-if="allResolved">
- <gl-icon name="check-circle-filled" />
- {{ __('All threads resolved') }}
- </template>
- <template v-else>
- {{ n__('%d unresolved thread', '%d unresolved threads', unresolvedDiscussionsCount) }}
- </template>
- </span>
- </div>
- <div
- v-if="resolveAllDiscussionsIssuePath && !allResolved"
- class="btn-group btn-group-sm"
- role="group"
- >
- <a
- v-gl-tooltip
- :href="resolveAllDiscussionsIssuePath"
- :title="s__('Resolve all threads in new issue')"
- class="new-issue-for-discussion btn btn-default discussion-create-issue-btn"
- >
- <gl-icon name="issue-new" />
- </a>
- </div>
- <div v-if="isLoggedIn && !allResolved" class="btn-group btn-group-sm" role="group">
- <button
- v-gl-tooltip
- :title="__('Jump to next unresolved thread')"
- class="btn btn-default discussion-next-btn"
- data-track-event="click_button"
- data-track-label="mr_next_unresolved_thread"
- data-track-property="click_next_unresolved_thread_top"
- @click="jumpToNextDiscussion"
- >
- <gl-icon name="comment-next" />
- </button>
- </div>
- <div class="btn-group btn-group-sm" role="group">
- <button
- v-gl-tooltip
- :title="__('Toggle all threads')"
- class="btn btn-default toggle-all-discussions-btn"
- @click="handleExpandDiscussions"
- >
- <gl-icon :name="allExpanded ? 'angle-up' : 'angle-down'" />
- </button>
- </div>
+ <div class="line-resolve-all">
+ <span :class="lineResolveClass">
+ <template v-if="allResolved">
+ <gl-icon name="check-circle-filled" />
+ {{ __('All threads resolved') }}
+ </template>
+ <template v-else>
+ {{ n__('%d unresolved thread', '%d unresolved threads', unresolvedDiscussionsCount) }}
+ </template>
+ </span>
</div>
+ <gl-button-group>
+ <gl-button
+ v-if="resolveAllDiscussionsIssuePath && !allResolved"
+ v-gl-tooltip
+ :href="resolveAllDiscussionsIssuePath"
+ :title="s__('Resolve all threads in new issue')"
+ :aria-label="s__('Resolve all threads in new issue')"
+ class="new-issue-for-discussion discussion-create-issue-btn"
+ icon="issue-new"
+ />
+ <gl-button
+ v-if="isLoggedIn && !allResolved"
+ v-gl-tooltip
+ :title="__('Jump to next unresolved thread')"
+ :aria-label="__('Jump to next unresolved thread')"
+ class="discussion-next-btn"
+ data-track-event="click_button"
+ data-track-label="mr_next_unresolved_thread"
+ data-track-property="click_next_unresolved_thread_top"
+ icon="comment-next"
+ @click="jumpToNextDiscussion"
+ />
+ <gl-button
+ v-gl-tooltip
+ :title="toggleThreadsLabel"
+ :aria-label="toggleThreadsLabel"
+ class="toggle-all-discussions-btn"
+ :icon="allExpanded ? 'angle-up' : 'angle-down'"
+ @click="handleExpandDiscussions"
+ />
+ </gl-button-group>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 989ce9ff144..e4b191b55a7 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -1,11 +1,11 @@
<script>
-import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
-import { GlIcon } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlDropdownDivider } from '@gitlab/ui';
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
import {
DISCUSSION_FILTERS_DEFAULT_VALUE,
HISTORY_ONLY_FILTER_VALUE,
+ COMMENTS_ONLY_FILTER_VALUE,
DISCUSSION_TAB_LABEL,
DISCUSSION_FILTER_TYPES,
NOTE_UNDERSCORE,
@@ -14,7 +14,9 @@ import notesEventHub from '../event_hub';
export default {
components: {
- GlIcon,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
},
props: {
filters: {
@@ -37,7 +39,7 @@ export default {
};
},
computed: {
- ...mapGetters(['getNotesDataByProp']),
+ ...mapGetters(['getNotesDataByProp', 'timelineEnabled']),
currentFilter() {
if (!this.currentValue) return this.filters[0];
return this.filters.find(filter => filter.value === this.currentValue);
@@ -62,14 +64,20 @@ export default {
window.removeEventListener('hashchange', this.handleLocationHash);
},
methods: {
- ...mapActions(['filterDiscussion', 'setCommentsDisabled', 'setTargetNoteHash']),
+ ...mapActions([
+ 'filterDiscussion',
+ 'setCommentsDisabled',
+ 'setTargetNoteHash',
+ 'setTimelineView',
+ ]),
selectFilter(value, persistFilter = true) {
const filter = parseInt(value, 10);
- // close dropdown
- this.toggleDropdown();
-
if (filter === this.currentValue) return;
+
+ if (this.timelineEnabled && filter !== COMMENTS_ONLY_FILTER_VALUE) {
+ this.setTimelineView(false);
+ }
this.currentValue = filter;
this.filterDiscussion({
path: this.getNotesDataByProp('discussionsPath'),
@@ -78,9 +86,6 @@ export default {
});
this.toggleCommentsForm();
},
- toggleDropdown() {
- $(this.$refs.dropdownToggle).dropdown('toggle');
- },
toggleCommentsForm() {
this.setCommentsDisabled(this.currentValue === HISTORY_ONLY_FILTER_VALUE);
},
@@ -92,7 +97,6 @@ export default {
if (/^note_/.test(hash) && this.currentValue !== DISCUSSION_FILTERS_DEFAULT_VALUE) {
this.selectFilter(this.defaultValue, false);
- this.toggleDropdown(); // close dropdown
this.setTargetNoteHash(hash);
}
},
@@ -109,43 +113,24 @@ export default {
</script>
<template>
- <div
+ <gl-dropdown
v-if="displayFilters"
- class="discussion-filter-container js-discussion-filter-container d-inline-block align-bottom full-width-mobile"
+ id="discussion-filter-dropdown"
+ class="gl-mr-3 full-width-mobile discussion-filter-container js-discussion-filter-container qa-discussion-filter"
+ :text="currentFilter.title"
>
- <button
- id="discussion-filter-dropdown"
- ref="dropdownToggle"
- class="btn btn-sm qa-discussion-filter"
- data-toggle="dropdown"
- aria-expanded="false"
- >
- {{ currentFilter.title }} <gl-icon name="chevron-down" />
- </button>
- <div
- ref="dropdownMenu"
- class="dropdown-menu dropdown-menu-selectable dropdown-menu-right"
- aria-labelledby="discussion-filter-dropdown"
- >
- <div class="dropdown-content">
- <ul>
- <li
- v-for="filter in filters"
- :key="filter.value"
- :data-filter-type="filterType(filter.value)"
- >
- <button
- :class="{ 'is-active': filter.value === currentValue }"
- class="qa-filter-options"
- type="button"
- @click="selectFilter(filter.value)"
- >
- {{ filter.title }}
- </button>
- <div v-if="filter.value === defaultValue" class="dropdown-divider"></div>
- </li>
- </ul>
- </div>
+ <div v-for="filter in filters" :key="filter.value" class="dropdown-item-wrapper">
+ <gl-dropdown-item
+ :is-check-item="true"
+ :is-checked="filter.value === currentValue"
+ :class="{ 'is-active': filter.value === currentValue }"
+ :data-filter-type="filterType(filter.value)"
+ class="qa-filter-options"
+ @click.prevent="selectFilter(filter.value)"
+ >
+ {{ filter.title }}
+ </gl-dropdown-item>
+ <gl-dropdown-divider v-if="filter.value === defaultValue" />
</div>
- </div>
+ </gl-dropdown>
</template>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index a8057276f1a..c2f40b2d21a 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -160,7 +160,7 @@ export default {
});
},
displayMemberBadgeText() {
- return sprintf(__('This user is a %{access} of the %{name} project.'), {
+ return sprintf(__('This user has the %{access} role in the %{name} project.'), {
access: this.accessLevel.toLowerCase(),
name: this.projectName,
});
@@ -275,7 +275,8 @@ export default {
v-gl-tooltip
type="button"
title="Edit comment"
- class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
+ class="note-action-button js-note-edit btn btn-transparent"
+ data-qa-selector="note_edit_button"
@click="onEdit"
>
<gl-icon name="pencil" class="link-highlight" />
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 314fa762768..65b89b94eaa 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -45,7 +45,7 @@ export default {
},
},
computed: {
- ...mapGetters(['getDiscussion']),
+ ...mapGetters(['getDiscussion', 'suggestionsCount']),
discussion() {
if (!this.note.isDraft) return {};
@@ -125,6 +125,7 @@ export default {
<suggestions
v-if="hasSuggestion && !isEditing"
:suggestions="note.suggestions"
+ :suggestions-count="suggestionsCount"
:batch-suggestions-info="batchSuggestionsInfo"
:note-html="note.note_html"
:line-type="lineType"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 88b4461cf38..4b3f23e742d 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -328,6 +328,7 @@ export default {
:add-spacing-classes="false"
:help-page-path="helpPagePath"
:show-suggest-popover="showSuggestPopover"
+ :textarea-value="updatedNoteBody"
@handleSuggestDismissed="() => $emit('handleSuggestDismissed')"
>
<textarea
@@ -337,7 +338,8 @@ export default {
v-model="updatedNoteBody"
:data-supports-quick-actions="!isEditing"
name="note[note]"
- class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form qa-reply-input"
+ class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form"
+ data-qa-selector="reply_field"
dir="auto"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@@ -376,7 +378,8 @@ export default {
<button
:disabled="isDisabled"
type="button"
- class="btn btn-success qa-start-review"
+ class="btn btn-success"
+ data-qa-selector="start_review_button"
@click="handleAddToReview"
>
<template v-if="hasDrafts">{{ __('Add to review') }}</template>
@@ -385,7 +388,8 @@ export default {
<button
:disabled="isDisabled"
type="button"
- class="btn qa-comment-now js-comment-button"
+ class="btn js-comment-button"
+ data-qa-selector="comment_now_button"
@click="handleUpdate()"
>
{{ __('Add comment now') }}
@@ -404,7 +408,8 @@ export default {
<button
:disabled="isDisabled"
type="button"
- class="js-vue-issue-save btn btn-success js-comment-button qa-reply-comment-button"
+ class="js-vue-issue-save btn btn-success js-comment-button"
+ data-qa-selector="reply_comment_button"
@click="handleUpdate()"
>
{{ saveButtonTitle }}
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index fb18be9386e..9eaa4e422d5 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -73,6 +73,7 @@ export default {
'userCanReply',
'discussionTabCounter',
'sortDirection',
+ 'timelineEnabled',
]),
sortDirDesc() {
return this.sortDirection === constants.DESC;
@@ -95,7 +96,7 @@ export default {
return this.discussions;
},
canReply() {
- return this.userCanReply && !this.commentsDisabled;
+ return this.userCanReply && !this.commentsDisabled && !this.timelineEnabled;
},
slotKeys() {
return this.sortDirDesc ? ['form', 'comments'] : ['comments', 'form'];
@@ -252,7 +253,7 @@ export default {
<ordered-layout :slot-keys="slotKeys">
<template #form>
<comment-form
- v-if="!commentsDisabled"
+ v-if="!(commentsDisabled || timelineEnabled)"
class="js-comment-form"
:noteable-type="noteableType"
/>
diff --git a/app/assets/javascripts/notes/components/sort_discussion.vue b/app/assets/javascripts/notes/components/sort_discussion.vue
index 60b531d7597..c279a7107c7 100644
--- a/app/assets/javascripts/notes/components/sort_discussion.vue
+++ b/app/assets/javascripts/notes/components/sort_discussion.vue
@@ -1,6 +1,5 @@
-gs
<script>
-import { GlIcon } from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
import { __ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
@@ -15,12 +14,13 @@ const SORT_OPTIONS = [
export default {
SORT_OPTIONS,
components: {
- GlIcon,
+ GlDropdown,
+ GlDropdownItem,
LocalStorageSync,
},
mixins: [Tracking.mixin()],
computed: {
- ...mapGetters(['sortDirection', 'noteableType']),
+ ...mapGetters(['sortDirection', 'persistSortOrder', 'noteableType']),
selectedOption() {
return SORT_OPTIONS.find(({ key }) => this.sortDirection === key);
},
@@ -38,7 +38,7 @@ export default {
return;
}
- this.setDiscussionSortDirection(direction);
+ this.setDiscussionSortDirection({ direction });
this.track('change_discussion_sort_direction', { property: direction });
},
isDropdownItemActive(sortDir) {
@@ -49,33 +49,28 @@ export default {
</script>
<template>
- <div
- data-testid="sort-discussion-filter"
- class="gl-mr-2 gl-display-inline-block gl-vertical-align-bottom full-width-mobile"
- >
+ <div class="gl-mr-3 gl-display-inline-block gl-vertical-align-bottom full-width-mobile">
<local-storage-sync
:value="sortDirection"
:storage-key="storageKey"
- @input="setDiscussionSortDirection"
+ :persist="persistSortOrder"
+ @input="setDiscussionSortDirection({ direction: $event })"
/>
- <button class="btn btn-sm js-dropdown-text" data-toggle="dropdown" aria-expanded="false">
- {{ dropdownText }}
- <gl-icon name="chevron-down" />
- </button>
- <div ref="dropdownMenu" class="dropdown-menu dropdown-menu-selectable dropdown-menu-right">
- <div class="dropdown-content">
- <ul>
- <li v-for="{ text, key, cls } in $options.SORT_OPTIONS" :key="key">
- <button
- :class="[cls, { 'is-active': isDropdownItemActive(key) }]"
- type="button"
- @click="fetchSortedDiscussions(key)"
- >
- {{ text }}
- </button>
- </li>
- </ul>
- </div>
- </div>
+ <gl-dropdown
+ :text="dropdownText"
+ data-testid="sort-discussion-filter"
+ class="js-dropdown-text full-width-mobile"
+ >
+ <gl-dropdown-item
+ v-for="{ text, key, cls } in $options.SORT_OPTIONS"
+ :key="key"
+ :class="cls"
+ :is-check-item="true"
+ :is-checked="isDropdownItemActive(key)"
+ @click="fetchSortedDiscussions(key)"
+ >
+ {{ text }}
+ </gl-dropdown-item>
+ </gl-dropdown>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/timeline_toggle.vue b/app/assets/javascripts/notes/components/timeline_toggle.vue
new file mode 100644
index 00000000000..d1ffe0a3601
--- /dev/null
+++ b/app/assets/javascripts/notes/components/timeline_toggle.vue
@@ -0,0 +1,60 @@
+<script>
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { mapActions, mapGetters } from 'vuex';
+import { s__ } from '~/locale';
+import { COMMENTS_ONLY_FILTER_VALUE, DESC } from '../constants';
+import notesEventHub from '../event_hub';
+import TrackEventDirective from '~/vue_shared/directives/track_event';
+import { trackToggleTimelineView } from '../utils';
+
+export const timelineEnabledTooltip = s__('Timeline|Turn timeline view off');
+export const timelineDisabledTooltip = s__('Timeline|Turn timeline view on');
+
+export default {
+ components: {
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ TrackEvent: TrackEventDirective,
+ },
+ computed: {
+ ...mapGetters(['timelineEnabled', 'sortDirection']),
+ tooltip() {
+ return this.timelineEnabled ? timelineEnabledTooltip : timelineDisabledTooltip;
+ },
+ },
+ methods: {
+ ...mapActions(['setTimelineView', 'setDiscussionSortDirection']),
+ trackToggleTimelineView,
+ setSort() {
+ if (this.timelineEnabled && this.sortDirection !== DESC) {
+ this.setDiscussionSortDirection({ direction: DESC, persist: false });
+ }
+ },
+ setFilter() {
+ notesEventHub.$emit('dropdownSelect', COMMENTS_ONLY_FILTER_VALUE, false);
+ },
+ toggleTimeline(event) {
+ event.currentTarget.blur();
+ this.setTimelineView(!this.timelineEnabled);
+ this.setSort();
+ this.setFilter();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-button
+ v-gl-tooltip
+ v-track-event="trackToggleTimelineView(timelineEnabled)"
+ icon="comments"
+ size="small"
+ :selected="timelineEnabled"
+ :title="tooltip"
+ :aria-label="tooltip"
+ class="gl-mr-3"
+ @click="toggleTimeline"
+ />
+</template>
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index bddac60647d..f49fd2c3fa3 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -57,7 +57,12 @@ export default {
tooltip-placement="bottom"
/>
</div>
- <button class="btn btn-link js-replies-text qa-expand-replies" type="button" @click="toggle">
+ <button
+ class="btn btn-link js-replies-text"
+ data-qa-selector="expand_replies_button"
+ type="button"
+ @click="toggle"
+ >
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
</button>
{{ __('Last reply by') }}
@@ -68,7 +73,8 @@ export default {
</template>
<span
v-else
- class="collapse-replies-btn js-collapse-replies qa-collapse-replies"
+ class="collapse-replies-btn js-collapse-replies"
+ data-qa-selector="collapse_replies_button"
@click="toggle"
>
<gl-icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}