Commit 84e1fbdd authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch...

Merge branch '229325-migrate-bootstrap-button-to-gitlab-ui-glbutton-in-app-assets-javascripts-notes-components' into 'master'

Migrate MR threads toolbar to GitLab UI

See merge request gitlab-org/gitlab!41658
parents 8af21fd3 f1f16e0e
<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>
......@@ -858,68 +858,28 @@ $note-form-margin-left: 72px;
}
.line-resolve-all-container {
margin: $gl-padding-4;
> div {
white-space: nowrap;
}
.discussion-next-btn {
border-radius: 0;
}
.toggle-all-discussions-btn {
.btn-group .btn:first-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.btn {
line-height: $gl-line-height;
svg {
fill: $gray-500;
}
&.discussion-create-issue-btn {
border-radius: 0;
border-right: 0;
a {
padding: 0;
line-height: 0;
&:hover {
text-decoration: none;
border: 0;
}
}
}
&.discussion-next-btn {
border-right: 0;
}
}
}
.line-resolve-all {
vertical-align: middle;
display: inline-block;
padding: $gl-padding-4 10px;
padding: $gl-padding-8 $gl-padding-12;
background-color: $gray-light;
border: 1px solid $border-color;
border-right: 0;
border-radius: $border-radius-default;
font-size: $gl-btn-small-font-size;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right: 0;
.line-resolve-btn {
color: $gray-500;
svg {
vertical-align: text-top;
}
}
font-size: $gl-font-size;
line-height: 1rem;
@include media-breakpoint-down(xs) {
flex: 1;
......
......@@ -6382,6 +6382,9 @@ msgstr ""
msgid "Collapse"
msgstr ""
msgid "Collapse all threads"
msgstr ""
msgid "Collapse approvers"
msgstr ""
......@@ -10458,6 +10461,9 @@ msgstr ""
msgid "Expand all files"
msgstr ""
msgid "Expand all threads"
msgstr ""
msgid "Expand approvers"
msgstr ""
......@@ -26807,9 +26813,6 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
msgid "Toggle all threads"
msgstr ""
msgid "Toggle backtrace"
msgstr ""
......
import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { GlIcon } from '@gitlab/ui';
import { GlButton } from '@gitlab/ui';
import notesModule from '~/notes/stores/modules';
import DiscussionCounter from '~/notes/components/discussion_counter.vue';
import { noteableDataMock, discussionMock, notesDataMock, userDataMock } from '../mock_data';
......@@ -9,6 +9,7 @@ import * as types from '~/notes/stores/mutation_types';
describe('DiscussionCounter component', () => {
let store;
let wrapper;
let setExpandDiscussionsFn;
const localVue = createLocalVue();
localVue.use(Vuex);
......@@ -16,6 +17,7 @@ describe('DiscussionCounter component', () => {
beforeEach(() => {
window.mrTabs = {};
const { state, getters, mutations, actions } = notesModule();
setExpandDiscussionsFn = jest.fn().mockImplementation(actions.setExpandDiscussions);
store = new Vuex.Store({
state: {
......@@ -24,7 +26,10 @@ describe('DiscussionCounter component', () => {
},
getters,
mutations,
actions,
actions: {
...actions,
setExpandDiscussions: setExpandDiscussionsFn,
},
});
store.dispatch('setNoteableData', {
...noteableDataMock,
......@@ -84,7 +89,7 @@ describe('DiscussionCounter component', () => {
wrapper = shallowMount(DiscussionCounter, { store, localVue });
expect(wrapper.find(`.is-active`).exists()).toBe(isActive);
expect(wrapper.findAll('[role="group"').length).toBe(groupLength);
expect(wrapper.findAll(GlButton)).toHaveLength(groupLength);
});
});
......@@ -103,23 +108,22 @@ describe('DiscussionCounter component', () => {
it('calls button handler when clicked', () => {
updateStoreWithExpanded(true);
wrapper.setMethods({ handleExpandDiscussions: jest.fn() });
toggleAllButton.trigger('click');
toggleAllButton.vm.$emit('click');
expect(wrapper.vm.handleExpandDiscussions).toHaveBeenCalledTimes(1);
expect(setExpandDiscussionsFn).toHaveBeenCalledTimes(1);
});
it('collapses all discussions if expanded', () => {
updateStoreWithExpanded(true);
expect(wrapper.vm.allExpanded).toBe(true);
expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-up');
expect(toggleAllButton.props('icon')).toBe('angle-up');
toggleAllButton.trigger('click');
toggleAllButton.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.allExpanded).toBe(false);
expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-down');
expect(toggleAllButton.props('icon')).toBe('angle-down');
});
});
......@@ -127,13 +131,13 @@ describe('DiscussionCounter component', () => {
updateStoreWithExpanded(false);
expect(wrapper.vm.allExpanded).toBe(false);
expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-down');
expect(toggleAllButton.props('icon')).toBe('angle-down');
toggleAllButton.trigger('click');
toggleAllButton.vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.allExpanded).toBe(true);
expect(toggleAllButton.find(GlIcon).props().name).toBe('angle-up');
expect(toggleAllButton.props('icon')).toBe('angle-up');
});
});
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment