diff --git a/ee/app/assets/javascripts/related_items_tree/components/epic_health_status.vue b/ee/app/assets/javascripts/related_items_tree/components/epic_health_status.vue index b1b2b04f67be95f9b120cefdee73728c7a6f1d82..f615328c21c26147c2aa3e5611038b09ddbbd34c 100644 --- a/ee/app/assets/javascripts/related_items_tree/components/epic_health_status.vue +++ b/ee/app/assets/javascripts/related_items_tree/components/epic_health_status.vue @@ -1,9 +1,12 @@ <script> -import { GlTooltip } from '@gitlab/ui'; +import { GlAlert, GlPopover } from '@gitlab/ui'; + +import { i18n } from '../constants'; export default { components: { - GlTooltip, + GlAlert, + GlPopover, }, props: { healthStatus: { @@ -19,6 +22,7 @@ export default { return totalHealthStatuses > 0; }, }, + i18n, }; </script> @@ -28,7 +32,7 @@ export default { ref="healthStatus" class="health-status d-inline-flex align-items-center" > - <gl-tooltip :target="() => $refs.healthStatus" placement="top"> + <gl-popover :target="() => $refs.healthStatus" placement="top"> <span ><strong>{{ healthStatus.issuesOnTrack }}</strong > <span>{{ __('issues on track') }}</span @@ -43,7 +47,10 @@ export default { ><strong>{{ healthStatus.issuesAtRisk }}</strong > <span>{{ __('issues at risk') }}</span></span > - </gl-tooltip> + <gl-alert :dismissible="false" class="gl-max-w-26 gl-mt-3"> + {{ $options.i18n.permissionAlert }} + </gl-alert> + </gl-popover> <span class="gl-label gl-label-text-dark gl-label-sm status-on-track gl-mr-2"> <span class="gl-label-text"> diff --git a/ee/app/assets/javascripts/related_items_tree/components/related_items_tree_header.vue b/ee/app/assets/javascripts/related_items_tree/components/related_items_tree_header.vue index 086748b186a39b0fffceee268a99cd9263a7e092..50d9474fc066f95cb79f66141fffcaef7ff7822b 100644 --- a/ee/app/assets/javascripts/related_items_tree/components/related_items_tree_header.vue +++ b/ee/app/assets/javascripts/related_items_tree/components/related_items_tree_header.vue @@ -1,14 +1,16 @@ <script> -import { GlTooltip, GlIcon } from '@gitlab/ui'; +import { GlAlert, GlPopover, GlIcon } from '@gitlab/ui'; import { mapState, mapActions } from 'vuex'; import { issuableTypesMap } from '~/related_issues/constants'; +import { i18n } from '../constants'; import EpicHealthStatus from './epic_health_status.vue'; import EpicActionsSplitButton from './epic_issue_actions_split_button.vue'; export default { components: { - GlTooltip, + GlAlert, + GlPopover, GlIcon, EpicHealthStatus, EpicActionsSplitButton, @@ -28,6 +30,9 @@ export default { totalIssuesCount() { return this.descendantCounts.openedIssues + this.descendantCounts.closedIssues; }, + totalChildrenCount() { + return this.totalEpicsCount + this.totalIssuesCount; + }, showHealthStatus() { return this.healthStatus && this.allowIssuableHealthStatus; }, @@ -66,6 +71,7 @@ export default { }); }, }, + i18n, }; </script> @@ -81,7 +87,7 @@ export default { {{ allowSubEpics ? __('Child issues and epics') : __('Issues') }} </h3> <div class="gl-display-inline-flex lh-100 gl-vertical-align-middle gl-ml-5 gl-flex-wrap"> - <gl-tooltip :target="() => $refs.countBadge"> + <gl-popover :target="() => $refs.countBadge"> <p v-if="allowSubEpics" class="gl-font-weight-bold gl-m-0"> {{ __('Epics') }} • <span class="gl-font-weight-normal" @@ -108,7 +114,14 @@ export default { {{ __('Total weight') }} • <span class="gl-font-weight-normal">{{ totalWeight }} </span> </p> - </gl-tooltip> + <gl-alert + v-if="totalChildrenCount > 0" + :dismissible="false" + class="gl-max-w-26 gl-mt-3" + > + {{ $options.i18n.permissionAlert }} + </gl-alert> + </gl-popover> <div ref="countBadge" class="issue-count-badge gl-display-inline-flex gl-text-secondary gl-p-0 gl-pr-5" diff --git a/ee/app/assets/javascripts/related_items_tree/constants.js b/ee/app/assets/javascripts/related_items_tree/constants.js index d2e23aa8de0295109a27838c83e7c5ec16a393e2..8532ab78930c0ce8e76246ef50ede24c18ee5716 100644 --- a/ee/app/assets/javascripts/related_items_tree/constants.js +++ b/ee/app/assets/javascripts/related_items_tree/constants.js @@ -71,3 +71,7 @@ export const ITEM_TABS = { TREE: 'tree', ROADMAP: 'roadmap', }; + +export const i18n = { + permissionAlert: __('Counts reflect children you may not have access to.'), +}; diff --git a/ee/spec/frontend/related_items_tree/components/epic_health_status_spec.js b/ee/spec/frontend/related_items_tree/components/epic_health_status_spec.js index a6cbafebeb11ac02a22c69b4efce6940c07fd216..80e2a51b0df60c793512d5228f9da7e345e07afb 100644 --- a/ee/spec/frontend/related_items_tree/components/epic_health_status_spec.js +++ b/ee/spec/frontend/related_items_tree/components/epic_health_status_spec.js @@ -1,4 +1,4 @@ -import { GlTooltip } from '@gitlab/ui'; +import { GlPopover, GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import EpicHealthStatus from 'ee/related_items_tree/components/epic_health_status.vue'; @@ -48,10 +48,10 @@ describe('EpicHealthStatus', () => { }); }); - it('renders tooltip', () => { - const tooltip = wrapper.findComponent(GlTooltip); + it('renders popover', () => { + const popover = wrapper.findComponent(GlPopover); - expect(tooltip.exists()).toBe(true); + expect(popover.exists()).toBe(true); }); it('hasHealthStatus computed property returns false', () => { @@ -81,5 +81,11 @@ describe('EpicHealthStatus', () => { expect(shortLabelWrapper.text()).toEqual(expectedShortLabels[index]); }); }); + + it('displays warning', () => { + expect(wrapper.findComponent(GlAlert).text()).toBe( + 'Counts reflect children you may not have access to.', + ); + }); }); }); diff --git a/ee/spec/frontend/related_items_tree/components/related_items_tree_header_spec.js b/ee/spec/frontend/related_items_tree/components/related_items_tree_header_spec.js index 2f31adf88210e6acf6897d4ef10b70ef62f49e02..72af828fa5a040b06eddb5d4c2da9595a4def9a6 100644 --- a/ee/spec/frontend/related_items_tree/components/related_items_tree_header_spec.js +++ b/ee/spec/frontend/related_items_tree/components/related_items_tree_header_spec.js @@ -1,4 +1,4 @@ -import { GlTooltip, GlIcon } from '@gitlab/ui'; +import { GlPopover, GlIcon, GlAlert } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; @@ -51,20 +51,26 @@ describe('RelatedItemsTree', () => { wrapper.destroy(); }); - describe('badgeTooltip', () => { + describe('Count popover', () => { beforeEach(() => { wrapper = createComponent(); }); it('returns string containing epic count based on available direct children within state', () => { - expect(wrapper.findComponent(GlTooltip).text()).toContain(`Epics • + expect(wrapper.findComponent(GlPopover).text()).toContain(`Epics • 1 open, 1 closed`); }); it('returns string containing issue count based on available direct children within state', () => { - expect(wrapper.findComponent(GlTooltip).text()).toContain(`Issues • + expect(wrapper.findComponent(GlPopover).text()).toContain(`Issues • 2 open, 1 closed`); }); + + it('displays warning', () => { + expect(wrapper.findComponent(GlAlert).text()).toBe( + 'Counts reflect children you may not have access to.', + ); + }); }); describe('totalWeight', () => { diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f53f37787af56d0e3b6e77f35970b63c1a419746..cce867f937228c392b8f29ec9df60ef5fff46de3 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -10907,6 +10907,9 @@ msgstr "" msgid "Country" msgstr "" +msgid "Counts reflect children you may not have access to." +msgstr "" + msgid "Coverage" msgstr ""