Commit c15d0373 authored by Scott Hampton's avatar Scott Hampton

Merge branch '325739-add-additional-blocks' into 'master'

Add trial and subscription blocks to Subscription Activation Form

See merge request gitlab-org/gitlab!59215
parents 88a98073 2ec48653
...@@ -7,12 +7,16 @@ import { ...@@ -7,12 +7,16 @@ import {
} from '../constants'; } from '../constants';
import CloudLicenseSubscriptionActivationForm from './subscription_activation_form.vue'; import CloudLicenseSubscriptionActivationForm from './subscription_activation_form.vue';
import SubscriptionBreakdown from './subscription_breakdown.vue'; import SubscriptionBreakdown from './subscription_breakdown.vue';
import SubscriptionPurchaseCard from './subscription_purchase_card.vue';
import SubscriptionTrialCard from './subscription_trial_card.vue';
export default { export default {
name: 'CloudLicenseApp', name: 'CloudLicenseApp',
components: { components: {
SubscriptionBreakdown, SubscriptionBreakdown,
CloudLicenseSubscriptionActivationForm, CloudLicenseSubscriptionActivationForm,
SubscriptionTrialCard,
SubscriptionPurchaseCard,
}, },
i18n: { i18n: {
subscriptionActivationTitle, subscriptionActivationTitle,
...@@ -72,6 +76,14 @@ export default { ...@@ -72,6 +76,14 @@ export default {
{{ $options.i18n.subscriptionActivationTitle }} {{ $options.i18n.subscriptionActivationTitle }}
</h3> </h3>
<cloud-license-subscription-activation-form @subscription-activation="handleActivation" /> <cloud-license-subscription-activation-form @subscription-activation="handleActivation" />
<div class="row gl-mt-7">
<div class="col-lg-6">
<subscription-trial-card />
</div>
<div class="col-lg-6">
<subscription-purchase-card />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -9,11 +9,19 @@ import { ...@@ -9,11 +9,19 @@ import {
GlLink, GlLink,
GlSprintf, GlSprintf,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { subscriptionQueries } from '../constants'; import { subscriptionActivationForm, subscriptionQueries } from '../constants';
export const SUBSCRIPTION_ACTIVATION_EVENT = 'subscription-activation'; export const SUBSCRIPTION_ACTIVATION_EVENT = 'subscription-activation';
export default { export default {
i18n: {
title: subscriptionActivationForm.title,
howToActivateSubscription: subscriptionActivationForm.howToActivateSubscription,
activationCode: subscriptionActivationForm.activationCode,
pasteActivationCode: subscriptionActivationForm.pasteActivationCode,
acceptTerms: subscriptionActivationForm.acceptTerms,
activateLabel: subscriptionActivationForm.activateLabel,
},
name: 'CloudLicenseSubscriptionActivationForm', name: 'CloudLicenseSubscriptionActivationForm',
components: { components: {
GlButton, GlButton,
...@@ -74,15 +82,11 @@ export default { ...@@ -74,15 +82,11 @@ export default {
<template> <template>
<gl-card> <gl-card>
<template #header> <template #header>
<h5 class="gl-my-0 gl-font-weight-bold">{{ s__('CloudLicense|Activate subscription') }}</h5> <h5 class="gl-my-0 gl-font-weight-bold">{{ $options.i18n.title }}</h5>
</template> </template>
<p> <p>
<gl-sprintf <gl-sprintf :message="$options.i18n.howToActivateSubscription">
:message="
s__('CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}.')
"
>
<template #link="{ content }"> <template #link="{ content }">
<gl-link href="" target="_blank">{{ content }}</gl-link> <gl-link href="" target="_blank">{{ content }}</gl-link>
</template> </template>
...@@ -92,25 +96,19 @@ export default { ...@@ -92,25 +96,19 @@ export default {
<gl-form-group class="gl-mb-0"> <gl-form-group class="gl-mb-0">
<div class="gl-display-flex gl-flex-wrap"> <div class="gl-display-flex gl-flex-wrap">
<label class="gl-w-full" for="activation-code-group"> <label class="gl-w-full" for="activation-code-group">
{{ s__('CloudLicense|Activation code') }} {{ $options.i18n.activationCode }}
</label> </label>
<gl-form-input <gl-form-input
id="activation-code-group" id="activation-code-group"
v-model="activationCode" v-model="activationCode"
:disabled="isLoading" :disabled="isLoading"
:placeholder="s__('CloudLicense|Paste your activation code')" :placeholder="$options.i18n.pasteActivationCode"
class="gl-w-full gl-mb-4" class="gl-w-full gl-mb-4"
required required
/> />
<gl-form-checkbox v-model="termsAccepted"> <gl-form-checkbox v-model="termsAccepted">
<gl-sprintf <gl-sprintf :message="$options.i18n.acceptTerms">
:message="
s__(
'CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab.',
)
"
>
<template #link="{ content }"> <template #link="{ content }">
<gl-link href="https://about.gitlab.com/terms/" target="_blank" <gl-link href="https://about.gitlab.com/terms/" target="_blank"
>{{ content }} >{{ content }}
...@@ -127,7 +125,7 @@ export default { ...@@ -127,7 +125,7 @@ export default {
type="submit" type="submit"
variant="confirm" variant="confirm"
> >
{{ s__('CloudLicense|Activate') }} {{ $options.i18n.activateLabel }}
</gl-button> </gl-button>
</div> </div>
</gl-form-group> </gl-form-group>
......
<script>
import { GlButton, GlCard } from '@gitlab/ui';
import { buySubscriptionCard } from '../constants';
export default {
i18n: {
title: buySubscriptionCard.title,
description: buySubscriptionCard.description,
buttonLabel: buySubscriptionCard.buttonLabel,
},
name: 'SubscriptionPurchaseCard',
components: { GlCard, GlButton },
inject: ['buySubscriptionPath'],
};
</script>
<template>
<gl-card>
<template #header>
<h5 class="gl-my-0 gl-font-weight-bold">{{ $options.i18n.title }}</h5>
</template>
<p>{{ $options.i18n.description }}</p>
<gl-button
category="secondary"
class="gl-mt-6"
data-testid="buy-subscription-button"
variant="confirm"
:href="buySubscriptionPath"
>
{{ $options.i18n.buttonLabel }}
</gl-button>
</gl-card>
</template>
<script>
import { GlButton, GlCard } from '@gitlab/ui';
import { trialCard } from '../constants';
export default {
i18n: {
title: trialCard.title,
startTrial: trialCard.startTrial,
description: trialCard.description,
},
name: 'SubscriptionTrialCard',
components: {
GlCard,
GlButton,
},
inject: ['freeTrialPath'],
};
</script>
<template>
<gl-card>
<template #header>
<h5 class="gl-my-0 gl-font-weight-bold">{{ $options.i18n.title }}</h5>
</template>
<p>
{{ $options.i18n.description }}
</p>
<gl-button
category="secondary"
class="gl-mt-6"
data-testid="free-trial-button"
variant="confirm"
:href="freeTrialPath"
>
{{ $options.i18n.startTrial }}
</gl-button>
</gl-card>
</template>
...@@ -57,6 +57,19 @@ export const manualSyncFailureText = s__( ...@@ -57,6 +57,19 @@ export const manualSyncFailureText = s__(
); );
export const manualSyncFailureTitle = s__('SuperSonics|There is a connectivity issue.'); export const manualSyncFailureTitle = s__('SuperSonics|There is a connectivity issue.');
export const subscriptionActivationForm = {
title: s__('CloudLicense|Activate subscription'),
howToActivateSubscription: s__(
'CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}.',
),
activationCode: s__('CloudLicense|Activation code'),
pasteActivationCode: s__('CloudLicense|Paste your activation code'),
acceptTerms: s__(
'CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab.',
),
activateLabel: s__('CloudLicense|Activate'),
};
export const subscriptionType = { export const subscriptionType = {
CLOUD: 'cloud', CLOUD: 'cloud',
LEGACY: 'legacy', LEGACY: 'legacy',
...@@ -70,3 +83,19 @@ export const subscriptionQueries = { ...@@ -70,3 +83,19 @@ export const subscriptionQueries = {
export const subscriptionHistoryQueries = { export const subscriptionHistoryQueries = {
query: getLicenseHistory, query: getLicenseHistory,
}; };
export const trialCard = {
title: s__('CloudLicense|Free trial'),
description: s__(
'CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details.',
),
startTrial: s__('CloudLicense|Start free trial'),
};
export const buySubscriptionCard = {
title: s__('CloudLicense|Subscription'),
description: s__(
'CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage.',
),
buttonLabel: s__('CloudLicense|Buy subscription'),
};
...@@ -17,11 +17,15 @@ export default () => { ...@@ -17,11 +17,15 @@ export default () => {
return null; return null;
} }
const { hasActiveLicense } = el.dataset; const { hasActiveLicense, freeTrialPath, buySubscriptionPath } = el.dataset;
return new Vue({ return new Vue({
el, el,
apolloProvider, apolloProvider,
provide: {
freeTrialPath,
buySubscriptionPath,
},
render: (h) => render: (h) =>
h(CloudLicenseShowApp, { h(CloudLicenseShowApp, {
props: { props: {
......
...@@ -54,7 +54,9 @@ module LicenseHelper ...@@ -54,7 +54,9 @@ module LicenseHelper
def cloud_license_view_data def cloud_license_view_data
{ {
has_active_license: (has_active_license? ? 'true' : 'false') has_active_license: (has_active_license? ? 'true' : 'false'),
free_trial_path: new_trial_url,
buy_subscription_path: ::EE::SUBSCRIPTIONS_PLANS_URL
} }
end end
......
import { shallowMount } from '@vue/test-utils';
import SubscriptionPurchaseCard from 'ee/pages/admin/cloud_licenses/components/subscription_purchase_card.vue';
import { buySubscriptionCard } from 'ee/pages/admin/cloud_licenses/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe('SubscriptionPurchaseCard', () => {
let wrapper;
const buySubscriptionPath = 'sample-buy-subscription-path';
const findBuySubscriptionButton = () => wrapper.findByTestId('buy-subscription-button');
const createComponent = () => {
wrapper = extendedWrapper(
shallowMount(SubscriptionPurchaseCard, {
provide: {
buySubscriptionPath,
},
}),
);
};
describe('text and button', () => {
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('renders card description', () => {
expect(wrapper.text()).toContain(buySubscriptionCard.description);
});
it('has a buy subscription button', () => {
expect(findBuySubscriptionButton().exists()).toBe(true);
expect(findBuySubscriptionButton().attributes('href')).toBe(buySubscriptionPath);
});
});
});
import { shallowMount } from '@vue/test-utils';
import SubscriptionTrialCard from 'ee/pages/admin/cloud_licenses/components/subscription_trial_card.vue';
import { trialCard } from 'ee/pages/admin/cloud_licenses/constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe('SubscriptionTrialCard', () => {
let wrapper;
const freeTrialPath = 'sample-free-trial-path';
const findFreeTrialButton = () => wrapper.findByTestId('free-trial-button');
const createComponent = () => {
wrapper = extendedWrapper(
shallowMount(SubscriptionTrialCard, {
provide: {
freeTrialPath,
},
}),
);
};
describe('text and button', () => {
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('renders card description', () => {
expect(wrapper.text()).toContain(trialCard.description);
});
it('has a free trial button', () => {
expect(findFreeTrialButton().exists()).toBe(true);
expect(findFreeTrialButton().attributes('href')).toBe(freeTrialPath);
});
});
});
...@@ -80,13 +80,21 @@ RSpec.describe LicenseHelper do ...@@ -80,13 +80,21 @@ RSpec.describe LicenseHelper do
end end
describe '#cloud_license_view_data' do describe '#cloud_license_view_data' do
before do
stub_const('::EE::SUBSCRIPTIONS_PLANS_URL', 'subscriptions_plans_url')
allow(helper).to receive(:new_trial_url).and_return('new_trial_url')
end
context 'when there is a current license' do context 'when there is a current license' do
it 'returns the data for the view' do it 'returns the data for the view' do
custom_plan = 'custom plan' custom_plan = 'custom plan'
license = double('License', plan: custom_plan) license = double('License', plan: custom_plan)
allow(License).to receive(:current).and_return(license) allow(License).to receive(:current).and_return(license)
expect(cloud_license_view_data).to eq({ has_active_license: 'true' }) expect(helper.cloud_license_view_data).to eq({ has_active_license: 'true',
free_trial_path: 'new_trial_url',
buy_subscription_path: 'subscriptions_plans_url' })
end end
end end
...@@ -94,7 +102,9 @@ RSpec.describe LicenseHelper do ...@@ -94,7 +102,9 @@ RSpec.describe LicenseHelper do
it 'returns the data for the view' do it 'returns the data for the view' do
allow(License).to receive(:current).and_return(nil) allow(License).to receive(:current).and_return(nil)
expect(cloud_license_view_data).to eq({ has_active_license: 'false' }) expect(helper.cloud_license_view_data).to eq({ has_active_license: 'false',
free_trial_path: 'new_trial_url',
buy_subscription_path: 'subscriptions_plans_url' })
end end
end end
end end
......
...@@ -6668,6 +6668,12 @@ msgstr "" ...@@ -6668,6 +6668,12 @@ msgstr ""
msgid "CloudLicense|Billable users" msgid "CloudLicense|Billable users"
msgstr "" msgstr ""
msgid "CloudLicense|Buy subscription"
msgstr ""
msgid "CloudLicense|Free trial"
msgstr ""
msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab." msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr "" msgstr ""
...@@ -6680,6 +6686,15 @@ msgstr "" ...@@ -6680,6 +6686,15 @@ msgstr ""
msgid "CloudLicense|Paste your activation code" msgid "CloudLicense|Paste your activation code"
msgstr "" msgstr ""
msgid "CloudLicense|Ready to get started? A GitLab plan is ideal for scaling organizations and for multi team usage."
msgstr ""
msgid "CloudLicense|Start free trial"
msgstr ""
msgid "CloudLicense|Subscription"
msgstr ""
msgid "CloudLicense|This is the highest peak of users on your installation since the license started." msgid "CloudLicense|This is the highest peak of users on your installation since the license started."
msgstr "" msgstr ""
...@@ -6695,6 +6710,9 @@ msgstr "" ...@@ -6695,6 +6710,9 @@ msgstr ""
msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license." msgid "CloudLicense|Users with a Guest role or those who don't belong to a Project or Group will not use a seat from your license."
msgstr "" msgstr ""
msgid "CloudLicense|You can start a free trial of GitLab Ultimate without any obligation or payment details."
msgstr ""
msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement." msgid "CloudLicense|You'll be charged for %{trueUpLinkStart}users over license%{trueUpLinkEnd} on a quarterly or annual basis, depending on the terms of your agreement."
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