Commit e4375a34 authored by Angelo Gulina's avatar Angelo Gulina Committed by Vitaly Slobodin

Add message for user count overage

Notify the user of QSR process around user seats overage.

Changelog: changed
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/80149
EE: true
parent 43d680b3
......@@ -31,3 +31,5 @@ export const STEPS = [
];
export const TRACK_SUCCESS_MESSAGE = 'Success';
/* eslint-enable @gitlab/require-i18n-strings */
export const QSR_RECONCILIATION_PATH = 'subscriptions/quarterly_reconciliation.html';
<script>
import { GlFormGroup, GlFormSelect, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
import { GlAlert, GlFormGroup, GlFormSelect, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapState, mapGetters, mapActions } from 'vuex';
import { STEP_SUBSCRIPTION_DETAILS } from 'ee/subscriptions/constants';
import { QSR_RECONCILIATION_PATH, STEP_SUBSCRIPTION_DETAILS } from 'ee/subscriptions/constants';
import { NEW_GROUP } from 'ee/subscriptions/new/constants';
import Step from 'ee/vue_shared/purchase_flow/components/step.vue';
import { sprintf, s__ } from '~/locale';
import { sprintf, s__, __ } from '~/locale';
import autofocusonshow from '~/vue_shared/directives/autofocusonshow';
import Tracking from '~/tracking';
import { helpPagePath } from '~/helpers/help_page_helper';
export default {
components: {
GlAlert,
GlFormGroup,
GlFormSelect,
GlFormInput,
......@@ -170,8 +172,12 @@ export default {
selectedPlan: s__('Checkout|%{selectedPlanText} plan'),
group: s__('Checkout|Group'),
users: s__('Checkout|Users'),
qsrOverageMessage: __(
'You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}',
),
},
stepId: STEP_SUBSCRIPTION_DETAILS,
qsrReconciliationLink: helpPagePath(QSR_RECONCILIATION_PATH),
};
</script>
<template>
......@@ -215,7 +221,11 @@ export default {
<gl-form-input ref="organization-name" v-model="organizationNameModel" type="text" />
</gl-form-group>
<div class="combined d-flex">
<gl-form-group :label="$options.i18n.numberOfUsersLabel" label-size="sm" class="number">
<gl-form-group
:label="$options.i18n.numberOfUsersLabel"
label-size="sm"
class="number gl-mb-0"
>
<gl-form-input
ref="number-of-users"
v-model.number="numberOfUsersModel"
......@@ -237,6 +247,18 @@ export default {
</gl-sprintf>
</gl-form-group>
</div>
<gl-alert
class="gl-mt-5 gl-mb-6"
:dismissible="false"
variant="info"
data-testid="qsr-overage-message"
>
<gl-sprintf :message="$options.i18n.qsrOverageMessage">
<template #qsrOverageLink="{ content }">
<gl-link :href="$options.qsrReconciliationLink" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</template>
<template #summary>
<strong ref="summary-line-1">
......
import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import { GlLink } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
import { mockTracking } from 'helpers/tracking_helper';
import { STEPS } from 'ee/subscriptions/constants';
import { QSR_RECONCILIATION_PATH, STEPS } from 'ee/subscriptions/constants';
import Component from 'ee/subscriptions/new/components/checkout/subscription_details.vue';
import { NEW_GROUP } from 'ee/subscriptions/new/constants';
import createStore from 'ee/subscriptions/new/store';
import * as types from 'ee/subscriptions/new/store/mutation_types';
import Step from 'ee/vue_shared/purchase_flow/components/step.vue';
import { createMockApolloProvider } from 'ee_jest/vue_shared/purchase_flow/spec_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
const availablePlans = [
{ id: 'firstPlanId', code: 'bronze', price_per_year: 48, name: 'bronze' },
......@@ -38,7 +39,7 @@ describe('Subscription Details', () => {
function createComponent(options = {}) {
const { apolloProvider, store } = options;
return mount(Component, {
return mountExtended(Component, {
store,
apolloProvider,
stubs: {
......@@ -51,11 +52,34 @@ describe('Subscription Details', () => {
const groupSelect = () => wrapper.findComponent({ ref: 'group-select' });
const numberOfUsersInput = () => wrapper.findComponent({ ref: 'number-of-users' });
const companyLink = () => wrapper.findComponent({ ref: 'company-link' });
const findQsrOverageMessage = () => wrapper.findByTestId('qsr-overage-message');
afterEach(() => {
wrapper.destroy();
});
describe('when rendering', () => {
beforeEach(() => {
const mockApollo = createMockApolloProvider(STEPS);
const store = createStore(
createDefaultInitialStoreData({ newUser: 'true', setupForCompany: '' }),
);
wrapper = createComponent({ apolloProvider: mockApollo, store });
});
it('has an alert displaying a message related to QSR process', () => {
expect(findQsrOverageMessage().text()).toMatchInterpolatedText(
'You are billed if you exceed this number. How does billing work?',
);
});
it('has a link to QSR process help page', () => {
expect(findQsrOverageMessage().findComponent(GlLink).attributes('href')).toMatch(
QSR_RECONCILIATION_PATH,
);
});
});
describe('A new user for which we do not have setupForCompany info', () => {
beforeEach(() => {
const mockApollo = createMockApolloProvider(STEPS);
......
......@@ -41183,6 +41183,9 @@ msgstr ""
msgid "You are attempting to update a file that has changed since you started editing it."
msgstr ""
msgid "You are billed if you exceed this number. %{qsrOverageLinkStart}How does billing work?%{qsrOverageLinkEnd}"
msgstr ""
msgid "You are connected to the Prometheus server, but there is currently no data to display."
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