Commit a6f5aa3a authored by Axel García's avatar Axel García

Hide child epics icon on Roadmap if not available

This checks the group features for sub epics support, if available the
allowSubEpics flag is propagated with the store and used in the epic
details component to hide/show the child epics icon.

This also adds the store to parent components specs that use
@vue/test-utils/mount.
parent 15c7001e
<script>
import { mapState } from 'vuex';
import { GlButton, GlIcon, GlLoadingIcon, GlTooltip } from '@gitlab/ui';
import { __, n__ } from '~/locale';
import eventHub from '../event_hub';
......@@ -43,6 +44,7 @@ export default {
},
},
computed: {
...mapState(['allowSubEpics']),
itemId() {
return this.epic.id;
},
......@@ -154,14 +156,16 @@ export default {
<p class="epic-timeframe" :title="timeframeString">{{ timeframeString }}</p>
</div>
</div>
<div ref="childEpicsCount" class="d-flex text-secondary text-nowrap">
<gl-icon name="epic" class="align-text-bottom mr-1" aria-hidden="true" />
<p class="m-0" :aria-label="childEpicsCountText">{{ childEpicsCount }}</p>
</div>
<gl-tooltip :target="() => $refs.childEpicsCount">
<span :class="{ bold: hasFiltersApplied }">{{ childEpicsCountText }}</span>
<span v-if="hasFiltersApplied" class="d-block">{{ childEpicsSearchText }}</span>
</gl-tooltip>
<template v-if="allowSubEpics">
<div ref="childEpicsCount" class="d-flex text-secondary text-nowrap">
<gl-icon name="epic" class="align-text-bottom mr-1" aria-hidden="true" />
<p class="m-0" :aria-label="childEpicsCountText">{{ childEpicsCount }}</p>
</div>
<gl-tooltip :target="() => $refs.childEpicsCount">
<span :class="{ bold: hasFiltersApplied }">{{ childEpicsCountText }}</span>
<span v-if="hasFiltersApplied" class="d-block">{{ childEpicsSearchText }}</span>
</gl-tooltip>
</template>
</div>
</div>
</template>
......@@ -78,6 +78,7 @@ export default () => {
return {
emptyStateIllustrationPath: dataset.emptyStateIllustration,
hasFiltersApplied: parseBoolean(dataset.hasFiltersApplied),
allowSubEpics: parseBoolean(dataset.allowSubEpics),
defaultInnerHeight: Number(dataset.innerHeight),
isChildEpics: parseBoolean(dataset.childEpics),
currentGroupId: parseInt(dataset.groupId, 0),
......@@ -109,6 +110,7 @@ export default () => {
initialEpicsPath: this.initialEpicsPath,
defaultInnerHeight: this.defaultInnerHeight,
isChildEpics: this.isChildEpics,
allowSubEpics: this.allowSubEpics,
});
},
methods: {
......
......@@ -33,4 +33,5 @@ export default () => ({
milestonesFetchInProgress: false,
milestonesFetchFailure: false,
milestonesFetchResultEmpty: false,
allowSubEpics: false,
});
......@@ -6,6 +6,8 @@
- @content_class = "group-epics-roadmap"
- breadcrumb_title _("Epics Roadmap")
- epics_limit_feature = 'epics_limit_warning_dismissed'
- sub_epics_feature_available = @group.feature_available?(:subepics)
- allow_sub_epics = sub_epics_feature_available ? 'true' : 'false'
- has_filters_applied = params[:label_name].present? || params[:author_username].present? || params[:search].present?
......@@ -21,7 +23,7 @@
%a.btn.btn-outline-warning#js-learn-more{ "href" => "https://docs.gitlab.com/ee/user/group/roadmap/" }
= _("Learn more")
#js-roadmap{ data: { epics_path: group_epics_path(@group, format: :json), group_id: @group.id, full_path: @group.full_path, empty_state_illustration: image_path('illustrations/epics/roadmap.svg'), has_filters_applied: "#{has_filters_applied}", new_epic_endpoint: group_epics_path(@group), preset_type: roadmap_layout, epics_state: @epics_state, sorted_by: @sort } }
#js-roadmap{ data: { epics_path: group_epics_path(@group, format: :json), group_id: @group.id, full_path: @group.full_path, empty_state_illustration: image_path('illustrations/epics/roadmap.svg'), has_filters_applied: "#{has_filters_applied}", new_epic_endpoint: group_epics_path(@group), preset_type: roadmap_layout, epics_state: @epics_state, sorted_by: @sort, allow_sub_epics: allow_sub_epics } }
- else
= render 'shared/empty_states/roadmap'
---
title: Hide child epic icon on Roadmap for accounts without child epics support
merge_request: 31250
author:
type: fixed
import { mount } from '@vue/test-utils';
import createStore from 'ee/roadmap/store';
import EpicItem from 'ee/roadmap/components/epic_item.vue';
import EpicItemContainer from 'ee/roadmap/components/epic_item_container.vue';
......@@ -13,6 +14,8 @@ import {
mockFormattedChildEpic1,
} from 'ee_jest/roadmap/mock_data';
let store;
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const createComponent = ({
......@@ -26,6 +29,7 @@ const createComponent = ({
hasFiltersApplied = false,
} = {}) => {
return mount(EpicItemContainer, {
store,
stubs: {
'epic-item': EpicItem,
},
......@@ -46,6 +50,7 @@ describe('EpicItemContainer', () => {
let wrapper;
beforeEach(() => {
store = createStore();
wrapper = createComponent();
});
......
import { GlButton, GlIcon, GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import createStore from 'ee/roadmap/store';
import EpicItemDetails from 'ee/roadmap/components/epic_item_details.vue';
import eventHub from 'ee/roadmap/event_hub';
import {
......@@ -9,6 +10,8 @@ import {
mockFormattedChildEpic1,
} from 'ee_jest/roadmap/mock_data';
let store;
const createComponent = ({
epic = mockFormattedEpic,
currentGroupId = mockGroupId,
......@@ -19,6 +22,7 @@ const createComponent = ({
isChildrenEmpty = false,
} = {}) => {
return shallowMount(EpicItemDetails, {
store,
propsData: {
epic,
currentGroupId,
......@@ -43,6 +47,7 @@ describe('EpicItemDetails', () => {
let wrapper;
beforeEach(() => {
store = createStore();
wrapper = createComponent();
});
......@@ -131,6 +136,10 @@ describe('EpicItemDetails', () => {
});
describe('epic', () => {
beforeEach(() => {
store.state.allowSubEpics = true;
});
describe('expand icon', () => {
it('is hidden when epic has no child epics', () => {
const epic = {
......@@ -325,6 +334,12 @@ describe('EpicItemDetails', () => {
'1 child epic Some child epics may be hidden due to applied filters',
);
});
it('does not render if the user license does not support child epics', () => {
store.state.allowSubEpics = false;
wrapper = createComponent();
expect(getChildEpicsCount(wrapper).exists()).toBe(false);
});
});
});
});
......@@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils';
import { delay } from 'lodash';
import createStore from 'ee/roadmap/store';
import EpicItemComponent from 'ee/roadmap/components/epic_item.vue';
import EpicItemContainer from 'ee/roadmap/components/epic_item_container.vue';
......@@ -24,6 +25,8 @@ jest.mock('lodash/delay', () =>
}),
);
let store;
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const createComponent = ({
......@@ -37,6 +40,7 @@ const createComponent = ({
hasFiltersApplied = false,
}) => {
return mount(EpicItemComponent, {
store,
stubs: {
'epic-item-container': EpicItemContainer,
'epic-item': EpicItemComponent,
......@@ -58,6 +62,7 @@ describe('EpicItemComponent', () => {
let wrapper;
beforeEach(() => {
store = createStore();
wrapper = createComponent({});
});
......
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