Commit 1ed1fe07 authored by Florie Guibert's avatar Florie Guibert

Roadmap settings - Turn off progress tracking

Allow user to turn off progress tracking on roadmap
parent b4bdcd48
......@@ -57,7 +57,7 @@ export default {
},
},
computed: {
...mapState(['progressTracking']),
...mapState(['progressTracking', 'isProgressTrackingActive']),
timelineBarInnerStyle() {
return {
maxWidth: `${this.clientWidth - EPIC_DETAILS_CELL_WIDTH}px`,
......@@ -141,7 +141,10 @@ export default {
<div class="epic-bar-inner gl-px-3 gl-py-2" :style="timelineBarInnerStyle">
<p class="epic-bar-title gl-text-truncate gl-m-0">{{ timelineBarTitle }}</p>
<div v-if="!isTimelineBarSmall" class="gl-display-flex gl-align-items-center">
<div
v-if="!isTimelineBarSmall && isProgressTrackingActive"
class="gl-display-flex gl-align-items-center"
>
<gl-progress-bar
class="epic-bar-progress gl-flex-grow-1 gl-mr-2"
:value="epicPercentage"
......
......@@ -76,6 +76,7 @@ export default {
'epicsState',
'sortedBy',
'filterParams',
'isProgressTrackingActive',
'progressTracking',
'isShowingMilestones',
'milestonesType',
......
<script>
import { GlFormGroup, GlFormRadioGroup } from '@gitlab/ui';
import { GlFormGroup, GlFormRadioGroup, GlToggle } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
......@@ -9,12 +9,13 @@ export default {
components: {
GlFormGroup,
GlFormRadioGroup,
GlToggle,
},
computed: {
...mapState(['progressTracking']),
...mapState(['progressTracking', 'isProgressTrackingActive']),
},
methods: {
...mapActions(['setProgressTracking']),
...mapActions(['setProgressTracking', 'toggleProgressTrackingActive']),
handleProgressTrackingChange(option) {
if (option !== this.progressTracking) {
this.setProgressTracking(option);
......@@ -23,6 +24,7 @@ export default {
},
i18n: {
header: __('Progress tracking'),
toggleLabel: __('Display progress of child issues'),
},
PROGRESS_TRACKING_OPTIONS,
};
......@@ -35,10 +37,24 @@ export default {
:label="$options.i18n.header"
data-testid="roadmap-progress-tracking"
>
<label for="toggle-progress-tracking" class="gl-font-weight-normal">
{{ $options.i18n.toggleLabel }}
</label>
<gl-toggle
id="toggle-progress-tracking"
:value="isProgressTrackingActive"
:label="$options.i18n.toggleLabel"
label-position="hidden"
aria-describedby="toggleTrackingProgress"
data-testid="toggle-progress-tracking"
@change="toggleProgressTrackingActive"
/>
<gl-form-radio-group
v-if="isProgressTrackingActive"
:checked="progressTracking"
stacked
:options="$options.PROGRESS_TRACKING_OPTIONS"
class="gl-mt-3"
@change="handleProgressTrackingChange"
/>
</gl-form-group>
......
......@@ -53,6 +53,7 @@ export default {
'not[author_username]': notAuthorUsername,
'not[my_reaction_emoji]': notMyReactionEmoji,
'not[label_name][]': notLabelName,
showProgress: this.isProgressTrackingActive,
progress: this.progressTracking,
show_milestones: this.isShowingMilestones,
milestones_type: this.milestonesType,
......
......@@ -109,6 +109,10 @@ export default () => {
presetType,
timeframe,
progressTracking: rawFilterParams.progress || PROGRESS_WEIGHT,
isProgressTrackingActive:
rawFilterParams.showProgress === undefined
? true
: parseBoolean(rawFilterParams.showProgress),
isShowingMilestones:
rawFilterParams.show_milestones === undefined
? true
......@@ -132,6 +136,7 @@ export default () => {
isChildEpics: this.isChildEpics,
hasFiltersApplied: this.hasFiltersApplied,
allowSubEpics: this.allowSubEpics,
isProgressTrackingActive: this.isProgressTrackingActive,
progressTracking: this.progressTracking,
isShowingMilestones: this.isShowingMilestones,
milestonesType: this.milestonesType,
......
......@@ -330,6 +330,9 @@ export const setSortedBy = ({ commit }, sortedBy) => commit(types.SET_SORTED_BY,
export const setProgressTracking = ({ commit }, progressTracking) =>
commit(types.SET_PROGRESS_TRACKING, progressTracking);
export const toggleProgressTrackingActive = ({ commit }) =>
commit(types.TOGGLE_PROGRESS_TRACKING_ACTIVE);
export const setMilestonesType = ({ commit }, milestonesType) =>
commit(types.SET_MILESTONES_TYPE, milestonesType);
......
......@@ -33,5 +33,6 @@ export const SET_DATERANGE = 'SET_DATERANGE';
export const SET_FILTER_PARAMS = 'SET_FILTER_PARAMS';
export const SET_SORTED_BY = 'SET_SORTED_BY';
export const SET_PROGRESS_TRACKING = 'SET_PROGRESS_TRACKING';
export const TOGGLE_PROGRESS_TRACKING_ACTIVE = 'TOGGLE_PROGRESS_TRACKING_ACTIVE';
export const SET_MILESTONES_TYPE = 'SET_MILESTONES_TYPE';
export const TOGGLE_MILESTONES = 'TOGGLE_MILESTONES';
......@@ -145,6 +145,10 @@ export default {
state.progressTracking = progressTracking;
},
[types.TOGGLE_PROGRESS_TRACKING_ACTIVE](state) {
state.isProgressTrackingActive = !state.isProgressTrackingActive;
},
[types.SET_MILESTONES_TYPE](state, milestonesType) {
state.milestonesType = milestonesType;
},
......
......@@ -3,6 +3,7 @@ export default () => ({
basePath: '',
epicsState: '',
progressTracking: '',
isProgressTrackingActive: true,
filterParams: null,
isShowingMilestones: true,
milestonesType: '',
......
......@@ -247,6 +247,48 @@ RSpec.describe 'group epic roadmap', :js do
end
end
describe 'roadmap with epics progress tracking' do
def select_progress_tracking(tracking)
page.within('[data-testid="roadmap-progress-tracking"]') do
choose tracking
end
end
before do
open_settings_sidebar
end
it 'renders progress bar using weight' do
select_progress_tracking('Use issue weight')
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epic-bar-progress', count: 3)
expect(page).to have_selector('[data-testid="weight-icon"]', count: 3)
end
end
it 'renders progress bar issue count' do
select_progress_tracking('Use issue count')
page.within('.roadmap-container .epics-list-section') do
expect(page).to have_selector('.epic-bar-progress', count: 3)
expect(page).to have_selector('[data-testid="issue-closed-icon"]', count: 3)
end
end
it 'turns off progress tracking' do
page.within('[data-testid="roadmap-progress-tracking"]') do
find('[data-testid="toggle-progress-tracking"]').click
end
page.within('.roadmap-container .epics-list-section') do
expect(page).not_to have_selector('.epic-bar-progress')
expect(page).not_to have_selector('[data-testid="issue-closed-icon"]')
expect(page).not_to have_selector('[data-testid="weight-icon"]')
end
end
end
describe 'roadmap milestones settings' do
def select_milestones(milestones)
page.within('[data-testid="roadmap-milestones-settings"]') do
......
......@@ -23,11 +23,13 @@ const createComponent = ({
timeframeItem = mockTimeframeMonths[0],
timeframeString = '',
progressTracking = PROGRESS_WEIGHT,
isProgressTrackingActive = true,
} = {}) => {
const store = createStore();
store.dispatch('setInitialData', {
progressTracking,
isProgressTrackingActive,
});
return shallowMount(EpicItemTimeline, {
......@@ -75,6 +77,16 @@ describe('EpicItemTimelineComponent', () => {
expect(getEpicBar(wrapper).attributes('href')).toBe(mockFormattedEpic.webUrl);
});
it.each`
isProgressTrackingActive
${true}
${false}
`('displays tracking depending on isProgressTrackingActive', ({ isProgressTrackingActive }) => {
wrapper = createComponent({ isProgressTrackingActive });
expect(wrapper.findComponent(GlProgressBar).exists()).toBe(isProgressTrackingActive);
});
it.each`
progressTracking | icon
${PROGRESS_WEIGHT} | ${'weight'}
......
......@@ -61,6 +61,7 @@ const createComponent = ({
sortedBy,
filterParams,
timeframe,
isProgressTrackingActive: true,
progressTracking: PROGRESS_WEIGHT,
milestonesType: MILESTONES_ALL,
});
......@@ -124,7 +125,7 @@ describe('RoadmapFilters', () => {
await nextTick();
expect(global.window.location.href).toBe(
`${TEST_HOST}/?state=${EPICS_STATES.CLOSED}&sort=end_date_asc&layout=MONTHS&author_username=root&label_name%5B%5D=Bug&milestone_title=4.0&confidential=true&progress=WEIGHT&show_milestones=true&milestones_type=ALL`,
`${TEST_HOST}/?state=${EPICS_STATES.CLOSED}&sort=end_date_asc&layout=MONTHS&author_username=root&label_name%5B%5D=Bug&milestone_title=4.0&confidential=true&showProgress=true&progress=WEIGHT&show_milestones=true&milestones_type=ALL`,
);
});
});
......
......@@ -8,11 +8,12 @@ import { PROGRESS_WEIGHT, PROGRESS_TRACKING_OPTIONS } from 'ee/roadmap/constants
describe('RoadmapProgressTracking', () => {
let wrapper;
const createComponent = () => {
const createComponent = ({ isProgressTrackingActive = true } = {}) => {
const store = createStore();
store.dispatch('setInitialData', {
progressTracking: PROGRESS_WEIGHT,
isProgressTrackingActive,
});
wrapper = shallowMountExtended(RoadmapProgressTracking, {
......@@ -37,9 +38,20 @@ describe('RoadmapProgressTracking', () => {
expect(findFormGroup().attributes('label')).toBe('Progress tracking');
});
it('renders radio form group', () => {
expect(findFormRadioGroup().exists()).toBe(true);
expect(findFormRadioGroup().props('options')).toEqual(PROGRESS_TRACKING_OPTIONS);
});
it.each`
isProgressTrackingActive
${true}
${false}
`(
'displays radio form group depending on isProgressTrackingActive',
({ isProgressTrackingActive }) => {
createComponent({ isProgressTrackingActive });
expect(findFormRadioGroup().exists()).toBe(isProgressTrackingActive);
if (isProgressTrackingActive) {
expect(findFormRadioGroup().props('options')).toEqual(PROGRESS_TRACKING_OPTIONS);
}
},
);
});
});
......@@ -673,6 +673,18 @@ describe('Roadmap Vuex Actions', () => {
});
});
describe('toggleProgressTrackingActive', () => {
it('commit TOGGLE_PROGRESS_TRACKING_ACTIVE mutation', () => {
return testAction(
actions.toggleProgressTrackingActive,
undefined,
state,
[{ type: types.TOGGLE_PROGRESS_TRACKING_ACTIVE }],
[],
);
});
});
describe('setMilestonesType', () => {
it('should set milestonesType in store state', () => {
return testAction(
......
......@@ -347,7 +347,6 @@ describe('Roadmap Store Mutations', () => {
describe('SET_PROGRESS_TRACKING', () => {
it('Should set `progressTracking` to the state', () => {
const progressTracking = PROGRESS_COUNT;
setEpicMockData(state);
mutations[types.SET_PROGRESS_TRACKING](state, progressTracking);
......@@ -357,6 +356,20 @@ describe('Roadmap Store Mutations', () => {
});
});
describe('TOGGLE_PROGRESS_TRACKING_ACTIVE', () => {
it('Should toggle `progressTracking` on state', () => {
expect(state).toMatchObject({
isProgressTrackingActive: true,
});
mutations[types.TOGGLE_PROGRESS_TRACKING_ACTIVE](state);
expect(state).toMatchObject({
isProgressTrackingActive: false,
});
});
});
describe('SET_MILESTONES_TYPE', () => {
it('Should set `milestonesType` to the state', () => {
const milestonesType = MILESTONES_GROUP;
......
......@@ -12869,6 +12869,9 @@ msgstr ""
msgid "Display name"
msgstr ""
msgid "Display progress of child issues"
msgstr ""
msgid "Display rendered file"
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