Commit dfe79df4 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Add button for reactivating/extending trial

Changelog: added
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66049
EE: true
parent eb03711a
<script>
import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
import { extendTrial, reactivateTrial } from 'ee/api/subscriptions_api';
import createFlash, { FLASH_TYPES } from '~/flash';
import { sprintf, __ } from '~/locale';
import { i18n, TRIAL_ACTION_EXTEND, TRIAL_ACTIONS } from '../constants';
export default {
name: 'ExtendReactivateTrialButton',
components: { GlButton, GlModal },
directives: {
GlModal: GlModalDirective,
},
props: {
namespaceId: {
type: Number,
required: true,
},
action: {
type: String,
required: true,
default: TRIAL_ACTION_EXTEND,
validator: (value) => TRIAL_ACTIONS.includes(value),
},
planName: {
type: String,
required: true,
},
},
data() {
return {
isButtonVisible: true,
isLoading: false,
};
},
computed: {
i18nContext() {
return this.action === TRIAL_ACTION_EXTEND
? this.$options.i18n.extend
: this.$options.i18n.reactivate;
},
modalText() {
return sprintf(this.i18nContext.modalText, {
action: this.actionName,
planName: sprintf(this.$options.i18n.planName, { planName: this.planName }),
});
},
actionPrimary() {
return {
text: this.i18nContext.buttonText,
};
},
actionSecondary() {
return {
text: __('Cancel'),
};
},
},
methods: {
async submit() {
this.isLoading = true;
this.$refs.modal.hide();
const action = this.action === TRIAL_ACTION_EXTEND ? extendTrial : reactivateTrial;
await action(this.namespaceId)
.then(() => {
createFlash({ message: this.i18nContext.flashText, type: FLASH_TYPES.SUCCESS });
this.isButtonVisible = false;
})
.catch((error) => {
createFlash({
message: this.i18nContext.trialActionError,
captureError: true,
error,
});
})
.finally(() => {
this.isLoading = false;
});
},
},
i18n,
};
</script>
<template>
<div>
<gl-button v-gl-modal.extend-trial :loading="isLoading" category="primary" variant="info">
{{ i18nContext.buttonText }}
</gl-button>
<gl-modal
ref="modal"
modal-id="extend-trial"
:title="i18nContext.buttonText"
:action-primary="actionPrimary"
:action-secondary="actionSecondary"
data-testid="extend-reactivate-trial-modal"
@primary="submit"
>
{{ modalText }}
</gl-modal>
</div>
</template>
import { s__ } from '~/locale';
export const TRIAL_ACTION_EXTEND = 'extend';
export const TRIAL_ACTION_REACTIVATE = 'reactivate';
export const TRIAL_ACTIONS = [TRIAL_ACTION_EXTEND, TRIAL_ACTION_REACTIVATE];
export const i18n = Object.freeze({
planName: s__('Billings|%{planName} plan'),
extend: {
buttonText: s__('Billings|Extend trial'),
modalText: s__(
'Billings|By extending your trial, you will receive an additional 30 days of %{planName}. Your trial can be only extended once.',
),
trialActionError: s__('Billings|An error occurred while extending your trial.'),
},
reactivate: {
buttonText: s__('Billings|Reactivate trial'),
modalText: s__(
'Billings|By reactivating your trial, you will receive an additional 30 days of %{planName}. Your trial can be only reactivated once.',
),
flashText: s__('Billings|Your trial has been reactivated for an additional 30 days.'),
trialActionError: s__('Billings|An error occurred while reactivating your trial.'),
},
});
- page_title _('Billing')
- current_plan = subscription_plan_info(@plans_data, current_user.namespace.actual_plan_name)
- namespace = current_user.namespace
- current_plan = subscription_plan_info(@plans_data, namespace.actual_plan_name)
- data_attributes = subscription_plan_data_attributes(namespace, current_plan).merge(extend_reactivate_trial_button_data(namespace))
= render 'shared/billings/billing_plans', plans_data: @plans_data, namespace: current_user.namespace, current_plan: current_plan
......
import { GlButton, GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import ExtendReactivateTrialButton from 'ee/trials/extend_reactivate_trial/components/extend_reactivate_trial_button.vue';
import {
i18n,
TRIAL_ACTION_EXTEND,
TRIAL_ACTION_REACTIVATE,
} from 'ee/trials/extend_reactivate_trial/constants';
import { sprintf } from '~/locale';
describe('ExtendReactivateTrialButton', () => {
let wrapper;
const createComponent = (props = {}) => {
return shallowMount(ExtendReactivateTrialButton, {
propsData: {
...props,
},
});
};
const findButton = () => wrapper.findComponent(GlButton);
const findModal = () => wrapper.findComponent(GlModal);
afterEach(() => {
wrapper.destroy();
});
describe('rendering', () => {
beforeEach(() => {
wrapper = createComponent({
namespaceId: 1,
action: TRIAL_ACTION_EXTEND,
planName: 'Ultimate',
});
});
it('renders the button visible', () => {
expect(findButton().isVisible()).toBe(true);
});
it('does not have loading icon', () => {
expect(findButton().props('loading')).toBe(false);
});
});
describe('when extending trial', () => {
beforeEach(() => {
wrapper = createComponent({
namespaceId: 1,
action: TRIAL_ACTION_EXTEND,
planName: 'Ultimate',
});
});
it('has the "Extend trial" text on the button', () => {
expect(findButton().text()).toBe(i18n.extend.buttonText);
});
it('has the correct text in the modal', () => {
expect(findModal().text()).toBe(
sprintf(i18n.extend.modalText, { planName: 'Ultimate plan' }),
);
});
});
describe('when reactivating trial', () => {
beforeEach(() => {
wrapper = createComponent({
namespaceId: 1,
action: TRIAL_ACTION_REACTIVATE,
planName: 'Ultimate',
});
});
it('has the "Reactivate trial" text on the button', () => {
expect(findButton().text()).toBe(i18n.reactivate.buttonText);
});
it('has the correct text in the modal', () => {
expect(findModal().text()).toBe(
sprintf(i18n.reactivate.modalText, { planName: 'Ultimate plan' }),
);
});
});
});
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