System Console enterprise advanced upsells (#30937)

* First set of texts updated for Enterprise Adv upsells and trial

* Updated upsell message for all tiers

* Linting translation file

* Linting

* Reverting unintended styling changes

* my ide making lint more

* Fix tests

* More default texts updated

* Trial banner title

* Make advantages list translatable

* Text updates

* Fix tests

* More text tweaking

* Linting

* Reodered translations

* Fixed e2e test

* More linting

* Removed incorrect new test

* Fix test typo

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Maria A Nunez
2025-05-09 13:33:48 -04:00
коммит произвёл GitHub
родитель cd3046773e
Коммит 190b4e7f03
7 изменённых файлов: 177 добавлений и 106 удалений

Просмотреть файл

@@ -50,18 +50,27 @@ describe('System console', () => {
});
});
it('MM-41397 - License page shows upgrade to Enterprise for E20 licenses', () => {
it('MM-41397 - License page shows upgrade to Enterprise Advanced for Enterprise licenses', () => {
cy.visit('/admin_console/about/license');
cy.get('.admin-console__header').
should('be.visible').
and('have.text', 'Edition and License');
// Validate prompt to increase headcount in Enterprise licenses
// Validate Enterprise to Enterprise Advanced upgrade content
cy.get('.EnterpriseEditionRightPannel').
should('be.visible').
within(() => {
cy.findByText('Need to increase your headcount?');
cy.findByText('Were here to work with you and your needs. Contact us today to get more seats on your plan.');
// Check the title
cy.get('.upgrade-title').should('have.text', 'Upgrade to Enterprise Advanced');
// Check the advantages list
cy.findByText('Attribute-based access control');
cy.findByText('Channel warning banners');
cy.findByText('AD/LDAP group sync');
cy.findByText('Advanced workflows with Playbooks');
cy.findByText('High availability');
cy.findByText('Advanced compliance');
cy.findByText('And more...');
cy.findByRole('button', {name: 'Contact sales'});
});

Просмотреть файл

@@ -52,7 +52,6 @@ describe('components/admin_console/license_settings/enterprise_edition/enterpris
Name: 'LicenseName',
Company: 'Mattermost Inc.',
Users: '1000000',
IsGovSku: 'false',
};
const props = {
@@ -60,36 +59,18 @@ describe('components/admin_console/license_settings/enterprise_edition/enterpris
license,
} as EnterpriseEditionProps;
test('should render for no Gov no Trial no Enterprise', () => {
const store = mockStore(initialState);
const wrapper = mountWithIntl(
<Provider store={store}>
<EnterpriseEditionRightPanel {...props}/>
</Provider>,
);
expect(wrapper.find('.upgrade-title').text()).toEqual('Upgrade to the Enterprise Plan');
const subtitleList = wrapper.find('.upgrade-subtitle').find('.item');
expect(subtitleList.at(0).text()).toEqual('AD/LDAP Group sync');
expect(subtitleList.at(1).text()).toEqual('High Availability');
expect(subtitleList.at(2).text()).toEqual('Advanced compliance');
expect(subtitleList.at(3).text()).toEqual('Advanced roles and permissions');
expect(subtitleList.at(4).text()).toEqual('And more...');
});
test('should render for Gov no Trial no Enterprise', () => {
test('should render for Professional license', () => {
const store = mockStore(initialState);
const wrapper = mountWithIntl(
<Provider store={store}>
<EnterpriseEditionRightPanel
license={{...props.license, IsGovSku: 'true'}}
license={{...props.license, SkuShortName: LicenseSkus.Professional}}
isTrialLicense={props.isTrialLicense}
/>
</Provider>,
);
expect(wrapper.find('.upgrade-title').text()).toEqual('Upgrade to the Enterprise Gov Plan');
expect(wrapper.find('.upgrade-title').text()).toEqual('Upgrade to Enterprise');
const subtitleList = wrapper.find('.upgrade-subtitle').find('.item');
expect(subtitleList.at(0).text()).toEqual('AD/LDAP Group sync');
@@ -99,7 +80,7 @@ describe('components/admin_console/license_settings/enterprise_edition/enterpris
expect(subtitleList.at(4).text()).toEqual('And more...');
});
test('should render for Enterprise no Trial', () => {
test('should render for Enterprise license', () => {
const store = mockStore(initialState);
const wrapper = mountWithIntl(
<Provider store={store}>
@@ -110,16 +91,24 @@ describe('components/admin_console/license_settings/enterprise_edition/enterpris
</Provider>,
);
expect(wrapper.find('.upgrade-title').text()).toEqual('Need to increase your headcount?');
expect(wrapper.find('.upgrade-subtitle').text()).toEqual('Were here to work with you and your needs. Contact us today to get more seats on your plan.');
expect(wrapper.find('.upgrade-title').text()).toEqual('Upgrade to Enterprise Advanced');
const subtitleList = wrapper.find('.upgrade-subtitle').find('.item');
expect(subtitleList.at(0).text()).toEqual('Attribute-based access control');
expect(subtitleList.at(1).text()).toEqual('Channel warning banners');
expect(subtitleList.at(2).text()).toEqual('AD/LDAP group sync');
expect(subtitleList.at(3).text()).toEqual('Advanced workflows with Playbooks');
expect(subtitleList.at(4).text()).toEqual('High availability');
expect(subtitleList.at(5).text()).toEqual('Advanced compliance');
expect(subtitleList.at(6).text()).toEqual('And more...');
});
test('should render for E20 no Trial', () => {
test('should render for Enterprise Advanced license', () => {
const store = mockStore(initialState);
const wrapper = mountWithIntl(
<Provider store={store}>
<EnterpriseEditionRightPanel
license={{...props.license, SkuShortName: LicenseSkus.E20}}
license={{...props.license, SkuShortName: LicenseSkus.EnterpriseAdvanced}}
isTrialLicense={props.isTrialLicense}
/>
</Provider>,
@@ -129,7 +118,7 @@ describe('components/admin_console/license_settings/enterprise_edition/enterpris
expect(wrapper.find('.upgrade-subtitle').text()).toEqual('Were here to work with you and your needs. Contact us today to get more seats on your plan.');
});
test('should render for Trial no Gov', () => {
test('should render for Trial license', () => {
const store = mockStore(initialState);
const wrapper = mountWithIntl(
<Provider store={store}>
@@ -140,22 +129,7 @@ describe('components/admin_console/license_settings/enterprise_edition/enterpris
</Provider>,
);
expect(wrapper.find('.upgrade-title').text()).toEqual('Purchase the Enterprise Plan');
expect(wrapper.find('.upgrade-subtitle').text()).toEqual('Continue your access to Enterprise features by purchasing a license today.');
});
test('should render for Trial Gov', () => {
const store = mockStore(initialState);
const wrapper = mountWithIntl(
<Provider store={store}>
<EnterpriseEditionRightPanel
license={{...props.license, IsGovSku: 'true'}}
isTrialLicense={true}
/>
</Provider>,
);
expect(wrapper.find('.upgrade-title').text()).toEqual('Purchase the Enterprise Gov Plan');
expect(wrapper.find('.upgrade-subtitle').text()).toEqual('Continue your access to Enterprise features by purchasing a license today.');
expect(wrapper.find('.upgrade-title').text()).toEqual('Purchase Enterprise Advanced');
expect(wrapper.find('.upgrade-subtitle').text()).toEqual('Continue your access to Enterprise Advanced features by purchasing a license.');
});
});

Просмотреть файл

@@ -2,14 +2,14 @@
// See LICENSE.txt for license information.
import React, {memo} from 'react';
import {FormattedMessage} from 'react-intl';
import {FormattedMessage, useIntl} from 'react-intl';
import type {ClientLicense} from '@mattermost/types/config';
import ContactUsButton from 'components/announcement_bar/contact_sales/contact_us';
import SetupSystemSvg from 'components/common/svg_images_components/setup_system';
import {isEnterpriseLicense} from 'utils/license_utils';
import {LicenseSkus} from 'utils/constants';
export interface EnterpriseEditionProps {
isTrialLicense: boolean;
@@ -19,17 +19,65 @@ export interface EnterpriseEditionProps {
const EnterpriseEditionRightPanel = ({
isTrialLicense,
license,
}: EnterpriseEditionProps) => {
const intl = useIntl();
const upgradeAdvantages = [
'AD/LDAP Group sync',
'High Availability',
'Advanced compliance',
'Advanced roles and permissions',
'And more...',
intl.formatMessage({
id: 'admin.license.upgradeAdvantage.adLdapSync',
defaultMessage: 'AD/LDAP Group sync',
}),
intl.formatMessage({
id: 'admin.license.upgradeAdvantage.highAvailability',
defaultMessage: 'High Availability',
}),
intl.formatMessage({
id: 'admin.license.upgradeAdvantage.advancedCompliance',
defaultMessage: 'Advanced compliance',
}),
intl.formatMessage({
id: 'admin.license.upgradeAdvantage.advancedRoles',
defaultMessage: 'Advanced roles and permissions',
}),
intl.formatMessage({
id: 'admin.license.upgradeAdvantage.andMore',
defaultMessage: 'And more...',
}),
];
const isEnterpriseOrE20 = isEnterpriseLicense(license);
const enterpriseToAdvancedAdvantages = [
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.attributeBasedAccess',
defaultMessage: 'Attribute-based access control',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.channelWarningBanners',
defaultMessage: 'Channel warning banners',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.adLdapGroupSync',
defaultMessage: 'AD/LDAP group sync',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.advancedWorkflows',
defaultMessage: 'Advanced workflows with Playbooks',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.highAvailability',
defaultMessage: 'High availability',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.advancedCompliance',
defaultMessage: 'Advanced compliance',
}),
intl.formatMessage({
id: 'admin.license.upgradeAdvantage.andMore',
defaultMessage: 'And more...',
}),
];
const isEnterpriseAdvanced = license?.SkuShortName === LicenseSkus.EnterpriseAdvanced;
const isEnterprise = license?.SkuShortName === LicenseSkus.Enterprise;
const isProfessional = license?.SkuShortName === LicenseSkus.Professional;
const contactSalesBtn = (
<div className='purchase-card'>
@@ -40,26 +88,16 @@ const EnterpriseEditionRightPanel = ({
</div>
);
const isGovSku = license.IsGovSku === 'true';
const title = () => {
if (isTrialLicense) {
if (isGovSku) {
return (
<FormattedMessage
id='admin.license.purchaseEnterpriseGovPlanTitle'
defaultMessage='Purchase the Enterprise Gov Plan'
/>
);
}
return (
<FormattedMessage
id='admin.license.purchaseEnterprisePlanTitle'
defaultMessage='Purchase the Enterprise Plan'
defaultMessage='Purchase Enterprise Advanced'
/>
);
}
if (isEnterpriseOrE20) {
if (isEnterpriseAdvanced) {
return (
<FormattedMessage
id='admin.license.enterprisePlanTitle'
@@ -67,24 +105,32 @@ const EnterpriseEditionRightPanel = ({
/>
);
}
if (isGovSku) {
if (isEnterprise) {
return (
<FormattedMessage
id='admin.license.upgradeToEnterpriseGov'
defaultMessage='Upgrade to the Enterprise Gov Plan'
id='admin.license.upgradeToEnterpriseAdvanced'
defaultMessage='Upgrade to Enterprise Advanced'
/>
);
}
if (isProfessional) {
return (
<FormattedMessage
id='admin.license.upgradeToEnterprise'
defaultMessage='Upgrade to Enterprise'
/>
);
}
return (
<FormattedMessage
id='admin.license.upgradeToEnterprise'
defaultMessage='Upgrade to the Enterprise Plan'
defaultMessage='Upgrade to Enterprise'
/>
);
};
const svgImage = () => {
if (isEnterpriseOrE20) {
if (isEnterpriseAdvanced) {
return null; //No image
}
return (
@@ -100,11 +146,11 @@ const EnterpriseEditionRightPanel = ({
return (
<FormattedMessage
id='admin.license.purchaseEnterprisePlanSubtitle'
defaultMessage='Continue your access to Enterprise features by purchasing a license today.'
defaultMessage='Continue your access to Enterprise Advanced features by purchasing a license.'
/>
);
}
if (isEnterpriseOrE20) {
if (isEnterpriseAdvanced) {
return (
<FormattedMessage
id='admin.license.enterprisePlanSubtitle'
@@ -112,15 +158,18 @@ const EnterpriseEditionRightPanel = ({
/>
);
}
const advantages = isEnterprise ? enterpriseToAdvancedAdvantages : upgradeAdvantages;
return (
<div className='advantages-list'>
{upgradeAdvantages.map((item: string, i: number) => {
{advantages.map((item, i) => {
return (
<div
className='item'
key={i.toString()}
>
<i className='fa fa-lock'/>{item}
<i className='fa fa-lock'/>
{item}
</div>
);
})}

Просмотреть файл

@@ -2,18 +2,42 @@
// See LICENSE.txt for license information.
import React, {memo} from 'react';
import {FormattedMessage} from 'react-intl';
import {FormattedMessage, useIntl} from 'react-intl';
import ContactUsButton from 'components/announcement_bar/contact_sales/contact_us';
import SetupSystemSvg from 'components/common/svg_images_components/setup_system';
const StarterRightPanel = () => {
const intl = useIntl();
const upgradeAdvantages = [
'OneLogin/ADFS SAML 2.0',
'OpenID Connect',
'Office365 suite integration',
'Read-only announcement channels',
'And more...',
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.attributeBasedAccess',
defaultMessage: 'Attribute-based access control',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.channelWarningBanners',
defaultMessage: 'Channel warning banners',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.adLdapGroupSync',
defaultMessage: 'AD/LDAP group sync',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.advancedWorkflows',
defaultMessage: 'Advanced workflows with Playbooks',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.highAvailability',
defaultMessage: 'High availability',
}),
intl.formatMessage({
id: 'admin.license.enterpriseToAdvancedAdvantage.advancedCompliance',
defaultMessage: 'Advanced compliance',
}),
intl.formatMessage({
id: 'admin.license.upgradeAdvantage.andMore',
defaultMessage: 'And more...',
}),
];
return (
@@ -27,17 +51,18 @@ const StarterRightPanel = () => {
<div className='upgrade-title'>
<FormattedMessage
id='admin.license.upgradeTitle'
defaultMessage='Upgrade to the Professional Plan'
defaultMessage='Purchase one of our plans to unlock more features'
/>
</div>
<div className='advantages-list'>
{upgradeAdvantages.map((item: string, i: number) => {
{upgradeAdvantages.map((item, i) => {
return (
<div
className='item'
key={i.toString()}
>
<i className='fa fa-lock'/>{item}
<i className='fa fa-lock'/>
{item}
</div>
);
})}

Просмотреть файл

@@ -238,7 +238,7 @@ const TrialBanner = ({
<>
<FormattedMessage
id='admin.license.trial-request.title'
defaultMessage='Experience Mattermost Enterprise Edition for free for the next 30 days. No obligation to buy or credit card required. '
defaultMessage='Experience all that Mattermost Enterprise Advanced has to offer with a free trial for the next 30 days. No obligation to buy and no credit card required. '
/>
<FormattedMessage
id='admin.license.trial-request.accept-terms'
@@ -300,7 +300,7 @@ const TrialBanner = ({
<>
<FormattedMessage
id='admin.license.upgrade-and-trial-request.title'
defaultMessage='Upgrade to Enterprise Edition and Experience Mattermost Enterprise Edition for free for the next 30 days. No obligation to buy or credit card required. '
defaultMessage='Upgrade to the Enterprise Edition to unlock a free 30-day trial of Mattermost Enterprise Advanced—our most powerful plan. No credit card required, no obligation to buy. '
/>
</>
);
@@ -367,7 +367,7 @@ const TrialBanner = ({
title={
<FormattedMessage
id='licensingPage.infoBanner.startTrialTitle'
defaultMessage='Free 30 day trial!'
defaultMessage='Start a free 30-day tral of Mattermost Enterprise Advanced'
/>
}
message={

Просмотреть файл

@@ -11,6 +11,7 @@ import AlertBanner from 'components/alert_banner';
import ContactUsButton from 'components/announcement_bar/contact_sales/contact_us';
import {daysToLicenseExpire} from 'utils/license_utils';
import {getSkuDisplayName} from 'utils/subscription';
import {getBrowserTimezone} from 'utils/timezone';
import './trial_license_card.scss';
@@ -29,7 +30,7 @@ const TrialLicenseCard: React.FC<Props> = ({license}: Props) => {
return (
<FormattedMessage
id='admin.license.trialLicenseCard.expiringToday'
defaultMessage='Your free trial expires <b>Today at {time}</b>. Visit our customer portal to purchase a license now to continue using Mattermost Professional and Enterprise features after trial ends'
defaultMessage='Your free trial expires <b>Today at {time}</b>. Contact sales to purchase a license and continue using advanced features after the trial ends.'
values={{
b: (chunks: string) => <b>{chunks}</b>,
time: moment(endDate).endOf('day').format('h:mm a ') + moment().tz(getBrowserTimezone()).format('z'),
@@ -41,7 +42,7 @@ const TrialLicenseCard: React.FC<Props> = ({license}: Props) => {
return (
<FormattedMessage
id='admin.license.trialLicenseCard.expiringAfterFewDays'
defaultMessage='Your free trial will expire in <b>{daysCount} {daysCount, plural, one {day} other {days}}</b>. Visit our customer portal to purchase a license now to continue using Mattermost Professional and Enterprise features after trial ends.'
defaultMessage='Your free trial will expire in <b>{daysCount} {daysCount, plural, one {day} other {days}}</b>. Contact sales to purchase a license and continue using advanced features.'
values={{
b: (chunks: string) => <b>{chunks}</b>,
daysCount: daysToEndLicense,
@@ -68,7 +69,10 @@ const TrialLicenseCard: React.FC<Props> = ({license}: Props) => {
const cardTitle = (
<FormattedMessage
id='admin.license.trialCard.licenseExpiring'
defaultMessage='Youre currently on a free trial of our Mattermost Enterprise license.'
defaultMessage='Youre currently on a free trial of our Mattermost {licenseType}.'
values={{
licenseType: getSkuDisplayName(license.SkuShortName, license.IsGovSku === 'true'),
}}
/>
);
return (

Просмотреть файл

@@ -1412,7 +1412,13 @@
"admin.license.enterpriseEdition.subtitle": "This is an Enterprise Edition for the Mattermost {skuName} plan",
"admin.license.enterprisePlanSubtitle": "Were here to work with you and your needs. Contact us today to get more seats on your plan.",
"admin.license.enterprisePlanTitle": "Need to increase your headcount?",
"admin.license.freeEdition.subtitle": "Purchase Professional or Enterprise to unlock enterprise features.",
"admin.license.enterpriseToAdvancedAdvantage.adLdapGroupSync": "AD/LDAP group sync",
"admin.license.enterpriseToAdvancedAdvantage.advancedCompliance": "Advanced compliance",
"admin.license.enterpriseToAdvancedAdvantage.advancedWorkflows": "Advanced workflows with Playbooks",
"admin.license.enterpriseToAdvancedAdvantage.attributeBasedAccess": "Attribute-based access control",
"admin.license.enterpriseToAdvancedAdvantage.channelWarningBanners": "Channel warning banners",
"admin.license.enterpriseToAdvancedAdvantage.highAvailability": "High availability",
"admin.license.freeEdition.subtitle": "This is an unlicensed server and does not have commercial support. Purchase a Professional, Enterprise, or Enterprise Advanced plan to unlock paid features.",
"admin.license.freeEdition.title": "Free",
"admin.license.key": "License Key: ",
"admin.license.keyAddNew": "Add a new license",
@@ -1421,9 +1427,8 @@
"admin.license.modal.upload": "Upload",
"admin.license.modal.uploading": "Uploading",
"admin.license.no-file-selected": "No file selected",
"admin.license.purchaseEnterpriseGovPlanTitle": "Purchase the Enterprise Gov Plan",
"admin.license.purchaseEnterprisePlanSubtitle": "Continue your access to Enterprise features by purchasing a license today.",
"admin.license.purchaseEnterprisePlanTitle": "Purchase the Enterprise Plan",
"admin.license.purchaseEnterprisePlanSubtitle": "Continue your access to Enterprise Advanced features by purchasing a license.",
"admin.license.purchaseEnterprisePlanTitle": "Purchase Enterprise Advanced",
"admin.license.remove": "Remove",
"admin.license.removing": "Removing License...",
"admin.license.renewalCard.description.contact_sales": "Renew your {licenseSku} license by contacting sales to avoid any disruption.",
@@ -1438,19 +1443,24 @@
"admin.license.trial-request.embargoed": "We were unable to process the request due to limitations for embargoed countries. <link>Learn more in our documentation</link>, or reach out to legal@mattermost.com for questions around export limitations.",
"admin.license.trial-request.embargoed.button": "Close",
"admin.license.trial-request.startTrial": "Start trial",
"admin.license.trial-request.title": "Experience Mattermost Enterprise Edition for free for the next 30 days. No obligation to buy or credit card required. ",
"admin.license.trial-request.title": "Experience all that Mattermost Enterprise Advanced has to offer with a free trial for the next 30 days. No obligation to buy and no credit card required. ",
"admin.license.trialCard.contactSales": "Contact sales",
"admin.license.trialCard.licenseExpiring": "Youre currently on a free trial of our Mattermost Enterprise license.",
"admin.license.trialCard.licenseExpiring": "Youre currently on a free trial of our Mattermost {licenseType}.",
"admin.license.trialCard.purchase_license": "Purchase a license",
"admin.license.trialLicenseCard.expiringAfterFewDays": "Your free trial will expire in <b>{daysCount} {daysCount, plural, one {day} other {days}}</b>. Visit our customer portal to purchase a license now to continue using Mattermost Professional and Enterprise features after trial ends.",
"admin.license.trialLicenseCard.expiringToday": "Your free trial expires <b>Today at {time}</b>. Visit our customer portal to purchase a license now to continue using Mattermost Professional and Enterprise features after trial ends",
"admin.license.trialLicenseCard.expiringAfterFewDays": "Your free trial will expire in <b>{daysCount} {daysCount, plural, one {day} other {days}}</b>. Contact sales to purchase a license and continue using advanced features.",
"admin.license.trialLicenseCard.expiringToday": "Your free trial expires <b>Today at {time}</b>. Contact sales to purchase a license and continue using advanced features after the trial ends.",
"admin.license.trialUpgradeAndRequest.submit": "Upgrade Server And Start trial",
"admin.license.upgrade-and-trial-request.accept-terms-final-part": "Also, I agree to the terms of the Mattermost {eeModalTerms}. Upgrading will download the binary and update your Team Edition instance.",
"admin.license.upgrade-and-trial-request.accept-terms-initial-part": "By selecting <strong>Upgrade Server And Start trial</strong>, I agree to the <linkEvaluation>Mattermost Software Evaluation Agreement</linkEvaluation>, <linkPrivacy>Privacy Policy</linkPrivacy>, and receiving product emails. ",
"admin.license.upgrade-and-trial-request.title": "Upgrade to Enterprise Edition and Experience Mattermost Enterprise Edition for free for the next 30 days. No obligation to buy or credit card required. ",
"admin.license.upgradeTitle": "Upgrade to the Professional Plan",
"admin.license.upgrade-and-trial-request.title": "Upgrade to the Enterprise Edition to unlock a free 30-day trial of Mattermost Enterprise Advanced—our most powerful plan. No credit card required, no obligation to buy. ",
"admin.license.upgradeAdvantage.adLdapSync": "AD/LDAP Group sync",
"admin.license.upgradeAdvantage.advancedCompliance": "Advanced compliance",
"admin.license.upgradeAdvantage.advancedRoles": "Advanced roles and permissions",
"admin.license.upgradeAdvantage.andMore": "And more...",
"admin.license.upgradeAdvantage.highAvailability": "High Availability",
"admin.license.upgradeTitle": "Purchase one of our plans to unlock more features",
"admin.license.upgradeToEnterprise": "Upgrade to the Enterprise plan",
"admin.license.upgradeToEnterpriseGov": "Upgrade to the Enterprise Gov Plan",
"admin.license.upgradeToEnterpriseAdvanced": "Upgrade to Enterprise Advanced",
"admin.license.upload-modal.file": "File",
"admin.license.upload-modal.subtitle": "Upload a license key for Mattermost Enterprise Edition to upgrade this server. ",
"admin.license.upload-modal.successfulUpgrade": "Successful Upgrade!",
@@ -4343,7 +4353,7 @@
"leave_team_modal.no": "No",
"leave_team_modal.title": "Leave the team?",
"leave_team_modal.yes": "Yes",
"licensingPage.infoBanner.startTrialTitle": "Free 30 day trial!",
"licensingPage.infoBanner.startTrialTitle": "Start a free 30-day tral of Mattermost Enterprise Advanced",
"licensingPage.overageUsersBanner.cta": "Contact Sales",
"licensingPage.overageUsersBanner.noticeDescription": "Notify your Customer Success Manager on your next true-up check. <a></a>",
"licensingPage.overageUsersBanner.noticeTitle": "Your workspace user count has exceeded your paid license seat count by {seats, number} {seats, plural, one {seat} other {seats}}",