Commit c3c6f145 authored by Martin Wortschack's avatar Martin Wortschack

Merge branch...

Merge branch '271250-fe-devops-report-adding-preparing-state-and-tooltips-in-segment-table-4' into 'master'

DevOps Report: Add segments button tooltip

See merge request gitlab-org/gitlab!49691
parents 1fadd6f1 8734a62d
<script> <script>
import dateformat from 'dateformat'; import dateformat from 'dateformat';
import { GlLoadingIcon, GlButton, GlSprintf, GlAlert, GlModalDirective } from '@gitlab/ui'; import {
GlLoadingIcon,
GlButton,
GlSprintf,
GlAlert,
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
import * as Sentry from '~/sentry/wrapper'; import * as Sentry from '~/sentry/wrapper';
import getGroupsQuery from '../graphql/queries/get_groups.query.graphql'; import getGroupsQuery from '../graphql/queries/get_groups.query.graphql';
import devopsAdoptionSegmentsQuery from '../graphql/queries/devops_adoption_segments.query.graphql'; import devopsAdoptionSegmentsQuery from '../graphql/queries/devops_adoption_segments.query.graphql';
...@@ -11,6 +18,7 @@ import { ...@@ -11,6 +18,7 @@ import {
DEVOPS_ADOPTION_STRINGS, DEVOPS_ADOPTION_STRINGS,
DEVOPS_ADOPTION_ERROR_KEYS, DEVOPS_ADOPTION_ERROR_KEYS,
MAX_REQUEST_COUNT, MAX_REQUEST_COUNT,
MAX_SEGMENTS,
DATE_TIME_FORMAT, DATE_TIME_FORMAT,
DEVOPS_ADOPTION_SEGMENT_MODAL_ID, DEVOPS_ADOPTION_SEGMENT_MODAL_ID,
} from '../constants'; } from '../constants';
...@@ -28,10 +36,12 @@ export default { ...@@ -28,10 +36,12 @@ export default {
}, },
directives: { directives: {
GlModal: GlModalDirective, GlModal: GlModalDirective,
GlTooltip: GlTooltipDirective,
}, },
i18n: { i18n: {
...DEVOPS_ADOPTION_STRINGS.app, ...DEVOPS_ADOPTION_STRINGS.app,
}, },
maxSegments: MAX_SEGMENTS,
devopsSegmentModalId: DEVOPS_ADOPTION_SEGMENT_MODAL_ID, devopsSegmentModalId: DEVOPS_ADOPTION_SEGMENT_MODAL_ID,
data() { data() {
return { return {
...@@ -78,6 +88,12 @@ export default { ...@@ -78,6 +88,12 @@ export default {
modalKey() { modalKey() {
return this.selectedSegment?.id; return this.selectedSegment?.id;
}, },
segmentLimitReached() {
return this.devopsAdoptionSegments.nodes?.length > this.$options.maxSegments;
},
addSegmentButtonTooltipText() {
return this.segmentLimitReached ? this.$options.i18n.tableHeader.buttonTooltip : false;
},
}, },
created() { created() {
this.fetchGroups(); this.fetchGroups();
...@@ -149,9 +165,14 @@ export default { ...@@ -149,9 +165,14 @@ export default {
<template #timestamp>{{ timestamp }}</template> <template #timestamp>{{ timestamp }}</template>
</gl-sprintf> </gl-sprintf>
</span> </span>
<gl-button v-gl-modal="$options.devopsSegmentModalId" @click="clearSelectedSegment">{{ <span v-gl-tooltip.hover="addSegmentButtonTooltipText" data-testid="segmentButtonWrapper">
$options.i18n.tableHeader.button <gl-button
}}</gl-button> v-gl-modal="$options.devopsSegmentModalId"
:disabled="segmentLimitReached"
@click="clearSelectedSegment"
>{{ $options.i18n.tableHeader.button }}</gl-button
></span
>
</div> </div>
<devops-adoption-table <devops-adoption-table
:segments="devopsAdoptionSegments.nodes" :segments="devopsAdoptionSegments.nodes"
......
import { s__, __ } from '~/locale'; import { s__, __, sprintf } from '~/locale';
export const MAX_SEGMENTS = 30;
export const MAX_REQUEST_COUNT = 10; export const MAX_REQUEST_COUNT = 10;
...@@ -26,6 +28,9 @@ export const DEVOPS_ADOPTION_STRINGS = { ...@@ -26,6 +28,9 @@ export const DEVOPS_ADOPTION_STRINGS = {
'DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}.', 'DevopsAdoption|Feature adoption is based on usage in the last calendar month. Last updated: %{timestamp}.',
), ),
button: s__('DevopsAdoption|Add new segment'), button: s__('DevopsAdoption|Add new segment'),
buttonTooltip: sprintf(s__('DevopsAdoption|Maximum %{maxSegments} segments allowed'), {
maxSegments: MAX_SEGMENTS,
}),
}, },
}, },
emptyState: { emptyState: {
......
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlAlert, GlButton, GlLoadingIcon, GlSprintf } from '@gitlab/ui'; import { GlAlert, GlButton, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { getByText } from '@testing-library/dom'; import { getByText } from '@testing-library/dom';
...@@ -14,6 +15,7 @@ import DevopsAdoptionSegmentModal from 'ee/admin/dev_ops_report/components/devop ...@@ -14,6 +15,7 @@ import DevopsAdoptionSegmentModal from 'ee/admin/dev_ops_report/components/devop
import { import {
DEVOPS_ADOPTION_STRINGS, DEVOPS_ADOPTION_STRINGS,
DEVOPS_ADOPTION_SEGMENT_MODAL_ID, DEVOPS_ADOPTION_SEGMENT_MODAL_ID,
MAX_SEGMENTS,
} from 'ee/admin/dev_ops_report/constants'; } from 'ee/admin/dev_ops_report/constants';
import * as Sentry from '~/sentry/wrapper'; import * as Sentry from '~/sentry/wrapper';
import { import {
...@@ -68,6 +70,9 @@ describe('DevopsAdoptionApp', () => { ...@@ -68,6 +70,9 @@ describe('DevopsAdoptionApp', () => {
stubs: { stubs: {
GlSprintf, GlSprintf,
}, },
directives: {
GlTooltip: createMockDirective(),
},
data() { data() {
return data; return data;
}, },
...@@ -354,9 +359,11 @@ describe('DevopsAdoptionApp', () => { ...@@ -354,9 +359,11 @@ describe('DevopsAdoptionApp', () => {
describe('segment modal button', () => { describe('segment modal button', () => {
let segmentButton; let segmentButton;
let segmentButtonWrapper;
beforeEach(() => { beforeEach(() => {
segmentButton = tableHeader.find(GlButton); segmentButton = tableHeader.find(GlButton);
segmentButtonWrapper = wrapper.find("[data-testid='segmentButtonWrapper']");
}); });
afterEach(() => { afterEach(() => {
...@@ -375,6 +382,33 @@ describe('DevopsAdoptionApp', () => { ...@@ -375,6 +382,33 @@ describe('DevopsAdoptionApp', () => {
expect(rootEmit.mock.calls[0][0]).toContain('show'); expect(rootEmit.mock.calls[0][0]).toContain('show');
expect(rootEmit.mock.calls[0][1]).toBe(DEVOPS_ADOPTION_SEGMENT_MODAL_ID); expect(rootEmit.mock.calls[0][1]).toBe(DEVOPS_ADOPTION_SEGMENT_MODAL_ID);
}); });
it('does not have a tooltip', () => {
const tooltip = getBinding(segmentButtonWrapper.element, 'gl-tooltip');
// Setting a directive's value to false tells it not to render
expect(tooltip.value).toBe(false);
});
describe('when there are more than the max number of segments', () => {
beforeEach(() => {
const data = {
nodes: Array(MAX_SEGMENTS + 1).fill(devopsAdoptionSegmentsData.nodes[0]),
};
wrapper.setData({ devopsAdoptionSegments: data });
});
it('disables the button', () => {
expect(segmentButton.props('disabled')).toBe(true);
});
it('has a tooltip', () => {
const tooltip = getBinding(segmentButtonWrapper.element, 'gl-tooltip');
expect(tooltip).toBeDefined();
expect(tooltip.value).toBe('Maximum 30 segments allowed');
});
});
}); });
}); });
}); });
......
...@@ -9676,6 +9676,9 @@ msgstr "" ...@@ -9676,6 +9676,9 @@ msgstr ""
msgid "DevopsAdoption|MRs" msgid "DevopsAdoption|MRs"
msgstr "" msgstr ""
msgid "DevopsAdoption|Maximum %{maxSegments} segments allowed"
msgstr ""
msgid "DevopsAdoption|My segment" msgid "DevopsAdoption|My segment"
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