Commit 866f71d0 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '345158-roadmap-settings-epics-state' into 'master'

Roadmap settings - Move epics state to sidebar

See merge request gitlab-org/gitlab!79302
parents cbe91312 ea85d05c
...@@ -115,12 +115,13 @@ export default { ...@@ -115,12 +115,13 @@ export default {
{{ dateRange.text }} {{ dateRange.text }}
</gl-dropdown-item> </gl-dropdown-item>
</gl-dropdown> </gl-dropdown>
<gl-form-group v-if="availablePresets.length"> <gl-form-group v-if="availablePresets.length" class="gl-mb-0">
<gl-form-radio-group <gl-form-radio-group
data-testid="daterange-presets"
:checked="presetType" :checked="presetType"
stacked stacked
:options="availablePresets" :options="availablePresets"
@change="handleRoadmapLayoutChange" @input="handleRoadmapLayoutChange"
/> />
</gl-form-group> </gl-form-group>
</div> </div>
......
<script>
import { GlFormGroup, GlFormRadioGroup } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
import { EPICS_STATES } from '../constants';
export default {
components: {
GlFormGroup,
GlFormRadioGroup,
},
computed: {
...mapState(['epicsState']),
availableStates() {
const all = { text: __('Show all epics'), value: EPICS_STATES.ALL };
const opened = { text: __('Show open epics'), value: EPICS_STATES.OPENED };
const closed = { text: __('Show closed epics'), value: EPICS_STATES.CLOSED };
return [all, opened, closed];
},
},
methods: {
...mapActions(['setEpicsState', 'fetchEpics']),
handleEpicStateChange(epicsState) {
if (epicsState !== this.epicsState) {
this.setEpicsState(epicsState);
this.fetchEpics();
}
},
},
i18n: {
header: __('Epics'),
},
};
</script>
<template>
<div>
<gl-form-group class="gl-mb-0" :label="$options.i18n.header" data-testid="roadmap-epics-state">
<gl-form-radio-group
:checked="epicsState"
stacked
:options="availableStates"
@change="handleEpicStateChange"
/>
</gl-form-group>
</div>
</template>
...@@ -206,6 +206,7 @@ export default { ...@@ -206,6 +206,7 @@ export default {
/> />
</gl-form-group> </gl-form-group>
<gl-dropdown <gl-dropdown
v-if="!glFeatures.roadmapSettings"
:text="selectedEpicStateTitle" :text="selectedEpicStateTitle"
class="gl-mr-0 gl-lg-mr-3 mb-sm-2 dropdown-epics-state" class="gl-mr-0 gl-lg-mr-3 mb-sm-2 dropdown-epics-state"
toggle-class="gl-rounded-base!" toggle-class="gl-rounded-base!"
......
<script> <script>
import { GlDrawer } from '@gitlab/ui'; import { GlDrawer } from '@gitlab/ui';
import RoadmapDaterange from './roadmap_daterange.vue'; import RoadmapDaterange from './roadmap_daterange.vue';
import RoadmapEpicsState from './roadmap_epics_state.vue';
export default { export default {
components: { components: {
GlDrawer, GlDrawer,
RoadmapDaterange, RoadmapDaterange,
RoadmapEpicsState,
}, },
props: { props: {
isOpen: { isOpen: {
...@@ -44,6 +46,7 @@ export default { ...@@ -44,6 +46,7 @@ export default {
</template> </template>
<template #default> <template #default>
<roadmap-daterange :timeframe-range-type="timeframeRangeType" /> <roadmap-daterange :timeframe-range-type="timeframeRangeType" />
<roadmap-epics-state />
</template> </template>
</gl-drawer> </gl-drawer>
</template> </template>
...@@ -10,7 +10,6 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -10,7 +10,6 @@ RSpec.describe 'group epic roadmap', :js do
let(:user_dev) { create(:user) } let(:user_dev) { create(:user) }
let(:group) { create(:group) } let(:group) { create(:group) }
let(:milestone) { create(:milestone, group: group) } let(:milestone) { create(:milestone, group: group) }
let(:state_dropdown) { find('.dropdown-epics-state') }
let!(:bug_label) { create(:group_label, group: group, title: 'Bug') } let!(:bug_label) { create(:group_label, group: group, title: 'Bug') }
let!(:critical_label) { create(:group_label, group: group, title: 'Critical') } let!(:critical_label) { create(:group_label, group: group, title: 'Critical') }
...@@ -50,6 +49,7 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -50,6 +49,7 @@ RSpec.describe 'group epic roadmap', :js do
let!(:epic_with_bug) { create(:labeled_epic, group: group, start_date: 10.days.ago, end_date: 1.day.ago, labels: [bug_label]) } let!(:epic_with_bug) { create(:labeled_epic, group: group, start_date: 10.days.ago, end_date: 1.day.ago, labels: [bug_label]) }
let!(:epic_with_critical) { create(:labeled_epic, group: group, start_date: 20.days.ago, end_date: 2.days.ago, labels: [critical_label]) } let!(:epic_with_critical) { create(:labeled_epic, group: group, start_date: 20.days.ago, end_date: 2.days.ago, labels: [critical_label]) }
let!(:closed_epic) { create(:epic, :closed, group: group, start_date: 20.days.ago, end_date: 2.days.ago) } let!(:closed_epic) { create(:epic, :closed, group: group, start_date: 20.days.ago, end_date: 2.days.ago) }
let(:state_dropdown) { find('.dropdown-epics-state') }
before do before do
stub_feature_flags(roadmap_settings: false) stub_feature_flags(roadmap_settings: false)
...@@ -95,6 +95,50 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -95,6 +95,50 @@ RSpec.describe 'group epic roadmap', :js do
end end
end end
end end
it 'renders the epics state dropdown' do
page.within('.content-wrapper .content .epics-filters') do
expect(page).to have_css('.dropdown-epics-state')
end
end
describe 'roadmap page with epics state filter' do
before do
state_dropdown.find('.dropdown-toggle').click
end
it 'renders open epics only' do
state_dropdown.find('button', text: 'Open epics').click
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 2)
end
end
it 'renders closed epics only' do
state_dropdown.find('button', text: 'Closed epics').click
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 1)
end
end
end
describe 'roadmap page with filter applied' do
before do
search_for_label(bug_label)
end
it 'keeps label filter when filtering by state' do
state_dropdown.find('.dropdown-toggle').click
state_dropdown.find('button', text: 'Open epics').click
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 1)
expect(page).to have_content(epic_with_bug.title)
end
end
end
end end
context 'when epics exist for the group' do context 'when epics exist for the group' do
...@@ -110,12 +154,12 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -110,12 +154,12 @@ RSpec.describe 'group epic roadmap', :js do
end end
describe 'roadmap page' do describe 'roadmap page' do
context 'roadmap daterange filtering' do
def open_settings_sidebar def open_settings_sidebar
click_button 'Settings' click_button 'Settings'
expect(page).to have_selector('[data-testid="roadmap-settings"]') expect(page).to have_selector('[data-testid="roadmap-settings"]')
end end
context 'roadmap daterange filtering' do
def select_date_range(range_type) def select_date_range(range_type)
open_settings_sidebar open_settings_sidebar
...@@ -132,7 +176,7 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -132,7 +176,7 @@ RSpec.describe 'group epic roadmap', :js do
page.within('[data-testid="roadmap-settings"]') do page.within('[data-testid="roadmap-settings"]') do
expect(page).to have_selector('[data-testid="daterange-dropdown"]') expect(page).to have_selector('[data-testid="daterange-dropdown"]')
expect(page).not_to have_selector('.gl-form-checkbox-group') expect(page).not_to have_selector('[data-testid="daterange-presets"]')
expect(page.find('[data-testid="daterange-dropdown"] button.dropdown-toggle')).to have_content('This quarter') expect(page.find('[data-testid="daterange-dropdown"] button.dropdown-toggle')).to have_content('This quarter')
end end
end end
...@@ -141,7 +185,7 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -141,7 +185,7 @@ RSpec.describe 'group epic roadmap', :js do
select_date_range('This year') select_date_range('This year')
page.within('[data-testid="roadmap-settings"]') do page.within('[data-testid="roadmap-settings"]') do
expect(page).to have_selector('.gl-form-checkbox-group') expect(page).to have_selector('[data-testid="daterange-presets"]')
expect(page).to have_selector('input[value="MONTHS"]') expect(page).to have_selector('input[value="MONTHS"]')
expect(page).to have_selector('input[value="WEEKS"]') expect(page).to have_selector('input[value="WEEKS"]')
end end
...@@ -151,7 +195,7 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -151,7 +195,7 @@ RSpec.describe 'group epic roadmap', :js do
select_date_range('Within 3 years') select_date_range('Within 3 years')
page.within('[data-testid="roadmap-settings"]') do page.within('[data-testid="roadmap-settings"]') do
expect(page).to have_selector('.gl-form-checkbox-group') expect(page).to have_selector('[data-testid="daterange-presets"]')
expect(page).to have_selector('input[value="QUARTERS"]') expect(page).to have_selector('input[value="QUARTERS"]')
expect(page).to have_selector('input[value="MONTHS"]') expect(page).to have_selector('input[value="MONTHS"]')
expect(page).to have_selector('input[value="WEEKS"]') expect(page).to have_selector('input[value="WEEKS"]')
...@@ -159,9 +203,43 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -159,9 +203,43 @@ RSpec.describe 'group epic roadmap', :js do
end end
end end
it 'renders the epics state dropdown' do describe 'roadmap page with epics state filter' do
page.within('.content-wrapper .content .epics-filters') do def select_state(state)
expect(page).to have_css('.dropdown-epics-state') page.within('[data-testid="roadmap-epics-state"]') do
choose state
end
end
before do
open_settings_sidebar
end
it 'renders open epics only' do
select_state('Show open epics')
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 2)
end
end
it 'renders closed epics only' do
select_state('Show closed epics')
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 1)
end
end
it 'saves last selected epic state', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341827' do
select_state('Show open epics')
wait_for_all_requests
visit group_roadmap_path(group)
wait_for_requests
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 2)
end
end end
end end
...@@ -209,41 +287,6 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -209,41 +287,6 @@ RSpec.describe 'group epic roadmap', :js do
end end
end end
describe 'roadmap page with epics state filter' do
before do
state_dropdown.find('.dropdown-toggle').click
end
it 'renders open epics only' do
state_dropdown.find('button', text: 'Open epics').click
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 2)
end
end
it 'renders closed epics only' do
state_dropdown.find('button', text: 'Closed epics').click
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 1)
end
end
it 'saves last selected epic state', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341827' do
state_dropdown.find('button', text: 'Open epics').click
wait_for_all_requests
visit group_roadmap_path(group)
wait_for_requests
expect(state_dropdown.find('.dropdown-toggle')).to have_text("Open epics")
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 2)
end
end
end
describe 'roadmap page with filter applied' do describe 'roadmap page with filter applied' do
before do before do
search_for_label(bug_label) search_for_label(bug_label)
...@@ -259,16 +302,6 @@ RSpec.describe 'group epic roadmap', :js do ...@@ -259,16 +302,6 @@ RSpec.describe 'group epic roadmap', :js do
expect(page).to have_content(epic_with_bug.title) expect(page).to have_content(epic_with_bug.title)
end end
end end
it 'keeps label filter when filtering by state' do
state_dropdown.find('.dropdown-toggle').click
state_dropdown.find('button', text: 'Open epics').click
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epics-list-item .epic-title', count: 1)
expect(page).to have_content(epic_with_bug.title)
end
end
end end
describe 'roadmap page with sort order applied' do describe 'roadmap page with sort order applied' do
......
import { GlFormGroup, GlFormRadioGroup } from '@gitlab/ui';
import { __ } from '~/locale';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createStore from 'ee/roadmap/store';
import RoadmapEpicsState from 'ee/roadmap/components/roadmap_epics_state.vue';
import { EPICS_STATES } from 'ee/roadmap/constants';
describe('RoadmapEpicsState', () => {
let wrapper;
const availableStates = [
{ text: __('Show all epics'), value: EPICS_STATES.ALL },
{ text: __('Show open epics'), value: EPICS_STATES.OPENED },
{ text: __('Show closed epics'), value: EPICS_STATES.CLOSED },
];
const createComponent = () => {
const store = createStore();
store.dispatch('setInitialData', {
epicsState: EPICS_STATES.All,
});
wrapper = shallowMountExtended(RoadmapEpicsState, {
store,
});
};
const findFormGroup = () => wrapper.findComponent(GlFormGroup);
const findFormRadioGroup = () => wrapper.findComponent(GlFormRadioGroup);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
describe('template', () => {
it('renders form group', () => {
expect(findFormGroup().exists()).toBe(true);
expect(findFormGroup().attributes('label')).toBe('Epics');
});
it('renders radio form group', () => {
expect(findFormRadioGroup().exists()).toBe(true);
expect(findFormRadioGroup().props('options')).toEqual(availableStates);
});
});
});
...@@ -2,6 +2,7 @@ import { GlDrawer } from '@gitlab/ui'; ...@@ -2,6 +2,7 @@ import { GlDrawer } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RoadmapSettings from 'ee/roadmap/components/roadmap_settings.vue'; import RoadmapSettings from 'ee/roadmap/components/roadmap_settings.vue';
import RoadmapDaterange from 'ee/roadmap/components/roadmap_daterange.vue'; import RoadmapDaterange from 'ee/roadmap/components/roadmap_daterange.vue';
import RoadmapEpicsState from 'ee/roadmap/components/roadmap_epics_state.vue';
describe('RoadmapSettings', () => { describe('RoadmapSettings', () => {
let wrapper; let wrapper;
...@@ -14,6 +15,7 @@ describe('RoadmapSettings', () => { ...@@ -14,6 +15,7 @@ describe('RoadmapSettings', () => {
const findSettingsDrawer = () => wrapper.findComponent(GlDrawer); const findSettingsDrawer = () => wrapper.findComponent(GlDrawer);
const findDaterange = () => wrapper.findComponent(RoadmapDaterange); const findDaterange = () => wrapper.findComponent(RoadmapDaterange);
const findEpicsSate = () => wrapper.findComponent(RoadmapEpicsState);
beforeEach(() => { beforeEach(() => {
createComponent(); createComponent();
...@@ -32,5 +34,9 @@ describe('RoadmapSettings', () => { ...@@ -32,5 +34,9 @@ describe('RoadmapSettings', () => {
it('renders roadmap daterange component', () => { it('renders roadmap daterange component', () => {
expect(findDaterange().exists()).toBe(true); expect(findDaterange().exists()).toBe(true);
}); });
it('renders roadmap epics state component', () => {
expect(findEpicsSate().exists()).toBe(true);
});
}); });
}); });
...@@ -33069,6 +33069,9 @@ msgstr "" ...@@ -33069,6 +33069,9 @@ msgstr ""
msgid "Show all breadcrumbs" msgid "Show all breadcrumbs"
msgstr "" msgstr ""
msgid "Show all epics"
msgstr ""
msgid "Show all issues." msgid "Show all issues."
msgstr "" msgstr ""
...@@ -33081,6 +33084,9 @@ msgstr "" ...@@ -33081,6 +33084,9 @@ msgstr ""
msgid "Show archived projects only" msgid "Show archived projects only"
msgstr "" msgstr ""
msgid "Show closed epics"
msgstr ""
msgid "Show command" msgid "Show command"
msgstr "" msgstr ""
...@@ -33117,6 +33123,9 @@ msgstr "" ...@@ -33117,6 +33123,9 @@ msgstr ""
msgid "Show one file at a time" msgid "Show one file at a time"
msgstr "" msgstr ""
msgid "Show open epics"
msgstr ""
msgid "Show the Closed list" msgid "Show the Closed list"
msgstr "" msgstr ""
......
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