Commit 2ec48653 authored by Ammar Alakkad's avatar Ammar Alakkad Committed by Scott Hampton

Add trial and subscription to activation form

It adds "Free trial" and "Subscription" blocks to the cloud
licensing activation form.
parent b5962d43
...@@ -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,
...@@ -67,6 +71,14 @@ export default { ...@@ -67,6 +71,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>
<subscription-breakdown <subscription-breakdown
......
...@@ -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>
...@@ -56,6 +56,19 @@ export const userNotifications = { ...@@ -56,6 +56,19 @@ export const userNotifications = {
), ),
}; };
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',
...@@ -69,3 +82,19 @@ export const subscriptionQueries = { ...@@ -69,3 +82,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
......
...@@ -6665,6 +6665,12 @@ msgstr "" ...@@ -6665,6 +6665,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 ""
...@@ -6677,6 +6683,15 @@ msgstr "" ...@@ -6677,6 +6683,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 ""
...@@ -6692,6 +6707,9 @@ msgstr "" ...@@ -6692,6 +6707,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