[CLD-6870] Remove CloudFreeDeprecated feature flag (#27675)

* Remove CloudFreeDeprecated feature flag

* Fixes for CI pipelines

* Remove CloudReverseTrial feature flag and accompanying code (#27676)

Co-authored-by: Mattermost Build <build@mattermost.com>

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Nick Misasi
2024-07-29 11:42:08 -04:00
коммит произвёл GitHub
родитель aa85a13c8f
Коммит dda726ee02
15 изменённых файлов: 15 добавлений и 196 удалений

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

@@ -36,8 +36,6 @@ type FeatureFlags struct {
DeprecateCloudFree bool
CloudReverseTrial bool
EnableExportDirectDownload bool
MoveThreadsEnabled bool
@@ -69,7 +67,6 @@ func (f *FeatureFlags) SetDefaults() {
f.DeprecateCloudFree = false
f.WysiwygEditor = false
f.OnboardingTourTips = true
f.CloudReverseTrial = false
f.EnableExportDirectDownload = false
f.MoveThreadsEnabled = false
f.StreamlinedMarketplace = true

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

@@ -20,7 +20,6 @@ const initialState = {
general: {
config: {
CWSURL: '',
FeatureFlagDeprecateCloudFree: 'true',
},
license: {
IsLicensed: 'true',

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

@@ -10,7 +10,7 @@ import type {GlobalState} from '@mattermost/types/store';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {getSubscriptionProduct as selectSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud';
import {deprecateCloudFree, get as getPreference} from 'mattermost-redux/selectors/entities/preferences';
import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
@@ -48,7 +48,6 @@ export const ToPaidPlanBannerDismissable = () => {
const currentUser = useSelector(getCurrentUser);
const isAdmin = useSelector(isCurrentUserSystemAdmin);
const product = useSelector(selectSubscriptionProduct);
const cloudFreeDeprecated = useSelector(deprecateCloudFree);
const currentProductStarter = product?.sku === CloudProducts.STARTER;
const now = moment(Date.now());
@@ -123,10 +122,6 @@ export const ToPaidPlanBannerDismissable = () => {
}]));
};
if (!cloudFreeDeprecated) {
return null;
}
if (!show) {
return null;
}

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

@@ -44,7 +44,6 @@ describe('components/feature_discovery', () => {
hadPrevCloudTrial={false}
isSubscriptionLoaded={true}
isPaidSubscription={false}
cloudFreeDeprecated={false}
actions={{
getPrevTrialLicense,
getCloudSubscription,
@@ -104,7 +103,6 @@ describe('components/feature_discovery', () => {
hadPrevCloudTrial={false}
isPaidSubscription={false}
isSubscriptionLoaded={true}
cloudFreeDeprecated={false}
actions={{
getPrevTrialLicense,
getCloudSubscription,
@@ -165,7 +163,6 @@ describe('components/feature_discovery', () => {
hadPrevCloudTrial={false}
isSubscriptionLoaded={false}
isPaidSubscription={false}
cloudFreeDeprecated={false}
actions={{
getPrevTrialLicense,
getCloudSubscription,

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

@@ -52,7 +52,6 @@ type Props = {
isSubscriptionLoaded: boolean;
isPaidSubscription: boolean;
customer?: CloudCustomer;
cloudFreeDeprecated: boolean;
}
type State = {

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

@@ -9,7 +9,6 @@ import {getPrevTrialLicense} from 'mattermost-redux/actions/admin';
import {getCloudSubscription} from 'mattermost-redux/actions/cloud';
import {checkHadPriorTrial, getCloudCustomer} from 'mattermost-redux/selectors/entities/cloud';
import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {openModal} from 'actions/views/modals';
@@ -29,7 +28,6 @@ function mapStateToProps(state: GlobalState) {
const hasPriorTrial = checkHadPriorTrial(state);
const isCloudTrial = subscription?.is_free_trial === 'true';
const customer = getCloudCustomer(state);
const cloudFreeDeprecated = deprecateCloudFree(state);
return {
stats: state.entities.admin.analytics,
prevTrialLicense: state.entities.admin.prevTrialLicense,
@@ -39,7 +37,6 @@ function mapStateToProps(state: GlobalState) {
hadPrevCloudTrial: hasPriorTrial,
isPaidSubscription: isCloud && license?.SkuShortName !== LicenseSkus.Starter && !isCloudTrial,
customer,
cloudFreeDeprecated,
};
}

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

@@ -36,7 +36,6 @@ type Props = {
daysLeftOnTrial: number;
isCloud: boolean;
subscription?: Subscription;
reverseTrial: boolean;
actions: {
savePreferences: (userId: string, preferences: PreferenceType[]) => void;
getCloudSubscription: () => void;
@@ -131,7 +130,7 @@ class CloudTrialAnnouncementBar extends React.PureComponent<Props> {
return null;
}
let trialMoreThan7DaysMsg = (
const trialMoreThan7DaysMsg = (
<FormattedMessage
id='admin.billing.subscription.cloudTrial.daysLeft'
defaultMessage='Your trial has started! There are {daysLeftOnTrial} days left'
@@ -139,63 +138,26 @@ class CloudTrialAnnouncementBar extends React.PureComponent<Props> {
/>
);
let modalButtonText;
if (this.props.reverseTrial) {
modalButtonText = messages.trialButton;
} else {
modalButtonText = messages.reverseTrialButton;
}
const modalButtonText = messages.trialButton;
if (this.props.reverseTrial) {
const trialEnd = getLocaleDateFromUTC((this.props.subscription?.trial_end_at as number / 1000), 'MMMM Do');
trialMoreThan7DaysMsg = (
<FormattedMessage
id='admin.billing.subscription.cloudTrial.moreThan3Days'
defaultMessage='Your 30 day Enterprise trial has started! Purchase before {trialEnd} to keep your workspace.'
values={{trialEnd}}
/>
);
}
let trialLessThan7DaysMsg = (
const trialLessThan7DaysMsg = (
<FormattedMessage
id='admin.billing.subscription.cloudTrial.daysLeftOnTrial'
defaultMessage='There are {daysLeftOnTrial} days left on your free trial'
id='admin.billing.subscription.cloudReverseTrial.daysLeftOnTrial'
defaultMessage='{daysLeftOnTrial} days left on your trial. Purchase a plan or contact sales to keep your workspace.'
values={{daysLeftOnTrial}}
/>
);
if (this.props.reverseTrial) {
trialLessThan7DaysMsg = (
<FormattedMessage
id='admin.billing.subscription.cloudReverseTrial.daysLeftOnTrial'
defaultMessage='{daysLeftOnTrial} days left on your trial. Purchase a plan or contact sales to keep your workspace.'
values={{daysLeftOnTrial}}
/>
);
}
const userEndTrialDate = getLocaleDateFromUTC((this.props.subscription?.trial_end_at as number / 1000), 'MMMM Do YYYY');
const userEndTrialHour = getLocaleDateFromUTC((this.props.subscription?.trial_end_at as number / 1000), 'HH:mm', this.props.currentUser.timezone?.automaticTimezone as string);
let trialLastDaysMsg = (
const trialLastDaysMsg = (
<FormattedMessage
id='admin.billing.subscription.cloudTrial.lastDay'
defaultMessage='This is the last day of your free trial. Your access will expire on {userEndTrialDate} at {userEndTrialHour}.'
values={{userEndTrialHour, userEndTrialDate}}
id='admin.billing.subscription.cloudReverseTrial.lastDay'
defaultMessage='This is the last day of your trial. Purchase a plan before {userEndTrialHour} or contact sales'
values={{userEndTrialHour}}
/>
);
if (this.props.reverseTrial) {
trialLastDaysMsg = (
<FormattedMessage
id='admin.billing.subscription.cloudReverseTrial.lastDay'
defaultMessage='This is the last day of your trial. Purchase a plan before {userEndTrialHour} or contact sales'
values={{userEndTrialHour}}
/>
);
}
let bannerMessage;
let icon;

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

@@ -7,7 +7,6 @@ import type {Dispatch} from 'redux';
import {getCloudSubscription} from 'mattermost-redux/actions/cloud';
import {savePreferences} from 'mattermost-redux/actions/preferences';
import {getConfig} from 'mattermost-redux/selectors/entities/admin';
import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
@@ -28,7 +27,6 @@ function mapStateToProps(state: GlobalState) {
const isCloud = getLicense(state).Cloud === 'true';
let isFreeTrial = false;
let daysLeftOnTrial = 0;
const config = getConfig(state);
if (isCloud && subscription?.is_free_trial === 'true') {
isFreeTrial = true;
@@ -46,7 +44,6 @@ function mapStateToProps(state: GlobalState) {
isCloud,
subscription,
preferences: getCategory(state, Preferences.CLOUD_TRIAL_BANNER),
reverseTrial: Boolean(config.FeatureFlags?.CloudReverseTrial),
};
}

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

@@ -8,7 +8,6 @@ import {useSelector, useDispatch} from 'react-redux';
import {getPrevTrialLicense} from 'mattermost-redux/actions/admin';
import {getSubscriptionProduct, checkHadPriorTrial} from 'mattermost-redux/selectors/entities/cloud';
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import {closeModal, openModal} from 'actions/views/modals';
@@ -40,7 +39,6 @@ export type Props = {
export default function InviteAs(props: Props) {
const {formatMessage} = useIntl();
const license = useSelector(getLicense);
const cloudFreeDeprecated = useSelector(deprecateCloudFree);
const dispatch = useDispatch();
useEffect(() => {
@@ -83,7 +81,7 @@ export default function InviteAs(props: Props) {
if (isFreeTrial) {
ctaExtraContentMsg = formatMessage({id: 'free.professional_feature.professional', defaultMessage: 'Professional feature'});
} else {
ctaExtraContentMsg = (hasPriorTrial || cloudFreeDeprecated) ? formatMessage({id: 'free.professional_feature.upgrade', defaultMessage: 'Upgrade'}) : formatMessage({id: 'free.professional_feature.try_free', defaultMessage: 'Professional feature- try it out free'});
ctaExtraContentMsg = (hasPriorTrial) ? formatMessage({id: 'free.professional_feature.upgrade', defaultMessage: 'Upgrade'}) : formatMessage({id: 'free.professional_feature.try_free', defaultMessage: 'Professional feature- try it out free'});
}
const restrictedIndicator = (

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

@@ -2,16 +2,9 @@
// See LICENSE.txt for license information.
import React from 'react';
import {FormattedMessage} from 'react-intl';
import {useSelector} from 'react-redux';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import ExternalLink from 'components/external_link';
import TrialBenefitsModalStepMore from 'components/trial_benefits_modal/trial_benefits_modal_step_more';
import {AboutLinks, LicenseLinks} from 'utils/constants';
import './learn_more_trial_modal_step.scss';
export type LearnMoreTrialModalStepProps = {
@@ -38,7 +31,6 @@ const LearnMoreTrialModalStep = (
buttonLabel,
handleOnClose,
}: LearnMoreTrialModalStepProps) => {
const cloudFreeDeprecated = useSelector(deprecateCloudFree);
return (
<div
id={`learnMoreTrialModalStep-${id}`}
@@ -63,36 +55,6 @@ const LearnMoreTrialModalStep = (
telemetryId={'learn_more_trial_modal'}
/>
)}
{
cloudFreeDeprecated ? '' : (
<div className='disclaimer'>
<span>
<FormattedMessage
id='start_trial.modal.disclaimer'
defaultMessage='By clicking “Start trial”, I agree to the <linkEvaluation>Mattermost Software and Services License Agreement</linkEvaluation>, <linkPrivacy>privacy policy</linkPrivacy> and receiving product emails.'
values={{
linkEvaluation: (msg: React.ReactNode) => (
<ExternalLink
href={LicenseLinks.SOFTWARE_SERVICES_LICENSE_AGREEMENT}
location='learn_more_trial_modal_step'
>
{msg}
</ExternalLink>
),
linkPrivacy: (msg: React.ReactNode) => (
<ExternalLink
href={AboutLinks.PRIVACY_POLICY}
location='learn_more_trial_modal_step'
>
{msg}
</ExternalLink>
),
}}
/>
</span>
</div>
)
}
{bottomLeftMessage && (
<div className='bottom-text-left-message'>
{bottomLeftMessage}

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

@@ -11,7 +11,6 @@ import {
getSubscriptionProduct as selectSubscriptionProduct,
getCloudProducts as selectCloudProducts,
} from 'mattermost-redux/selectors/entities/cloud';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import {trackEvent} from 'actions/telemetry_actions';
@@ -27,7 +26,6 @@ import {findOnlyYearlyProducts, findProductBySku} from 'utils/products';
import Card, {BlankCard, ButtonCustomiserClasses} from './card';
import ContactSalesCTA from './contact_sales_cta';
import StartTrialCaution from './start_trial_caution';
import './content.scss';
@@ -48,7 +46,6 @@ function Content(props: ContentProps) {
const currentProduct = useSelector(selectSubscriptionProduct);
const products = useSelector(selectCloudProducts);
const cloudFreeDeprecated = useSelector(deprecateCloudFree);
const yearlyProducts = findOnlyYearlyProducts(products || {}); // pricing modal should now only show yearly products
const currentSubscriptionIsMonthly = currentProduct?.recurring_interval === RecurringIntervals.MONTH;
@@ -220,10 +217,10 @@ function Content(props: ContentProps) {
renderLastDaysOnTrial={true}
/>) : undefined}
buttonDetails={enterpriseBtnDetails()}
planTrialDisclaimer={(!isPostTrial && isAdmin && !cloudFreeDeprecated) ? <StartTrialCaution/> : undefined}
contactSalesCTA={(isPostTrial || !isAdmin || cloudFreeDeprecated) ? undefined : <ContactSalesCTA/>}
planTrialDisclaimer={undefined}
contactSalesCTA={(isPostTrial || !isAdmin) ? undefined : <ContactSalesCTA/>}
briefing={{
title: cloudFreeDeprecated ? formatMessage({id: 'pricing_modal.briefing.title_large_scale', defaultMessage: 'Large scale collaboration'}) : formatMessage({id: 'pricing_modal.briefing.title', defaultMessage: 'Top features'}),
title: formatMessage({id: 'pricing_modal.briefing.title_large_scale', defaultMessage: 'Large scale collaboration'}),
items: [
formatMessage({id: 'pricing_modal.briefing.enterprise.groupSync', defaultMessage: 'AD/LDAP group sync'}),
formatMessage({id: 'pricing_modal.briefing.enterprise.rolesAndPermissions', defaultMessage: 'Advanced roles and permissions'}),

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

@@ -162,43 +162,6 @@ describe('components/widgets/menu/menu_items/menu_cloud_trial', () => {
expect(wrapper.find('.MenuCloudTrial').exists()).toEqual(false);
});
test('should invite to start trial when the subscription is not paid and have not had trial before', () => {
const state = {
entities: {
general: {
license: {
IsLicensed: 'true',
Cloud: 'true',
},
},
cloud: {
subscription: {
is_free_trial: 'false',
trial_end_at: 0,
product_id: 'prod_starter',
},
products: {
prod_starter: {
id: 'prod_starter',
sku: CloudProducts.STARTER,
},
},
limits,
},
usage,
users: {
currentUserId: 'current_user_id',
profiles: {
current_user_id: {roles: 'system_admin'},
},
},
},
};
const store = mockStore(state);
const wrapper = mountWithIntl(<Provider store={store}><MenuCloudTrial id='menuCloudTrial'/></Provider>);
expect(wrapper.find('.open-learn-more-trial-modal').exists()).toEqual(true);
});
test('should show the open trial benefits modal when is free trial', () => {
const state = {
entities: {

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

@@ -8,7 +8,6 @@ import {useSelector, useDispatch} from 'react-redux';
import {getCloudSubscription, getSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud';
import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
import {openModal} from 'actions/views/modals';
@@ -17,7 +16,6 @@ import useGetHighestThresholdCloudLimit from 'components/common/hooks/useGetHigh
import useGetLimits from 'components/common/hooks/useGetLimits';
import useGetUsage from 'components/common/hooks/useGetUsage';
import useOpenPricingModal from 'components/common/hooks/useOpenPricingModal';
import LearnMoreTrialModal from 'components/learn_more_trial_modal/learn_more_trial_modal';
import TrialBenefitsModal from 'components/trial_benefits_modal/trial_benefits_modal';
import {ModalIdentifiers, CloudProducts} from 'utils/constants';
@@ -31,12 +29,10 @@ const MenuCloudTrial = ({id}: Props): JSX.Element | null => {
const subscription = useSelector(getCloudSubscription);
const subscriptionProduct = useSelector(getSubscriptionProduct);
const license = useSelector(getLicense);
const cloudFreeDeprecated = useSelector(deprecateCloudFree);
const dispatch = useDispatch();
const isCloud = license?.Cloud === 'true';
const isFreeTrial = subscription?.is_free_trial === 'true';
const noPriorTrial = !(subscription?.is_free_trial === 'false' && subscription?.trial_end_at > 0);
const freeTrialEndDay = moment(subscription?.trial_end_at).format('MMMM DD');
const isAdmin = useSelector(isCurrentUserSystemAdmin);
const openPricingModal = useOpenPricingModal();
@@ -48,16 +44,6 @@ const MenuCloudTrial = ({id}: Props): JSX.Element | null => {
}));
};
const openLearnMoreTrialModal = async () => {
await dispatch(openModal({
modalId: ModalIdentifiers.LEARN_MORE_TRIAL_MODAL,
dialogType: LearnMoreTrialModal,
dialogProps: {
launchedBy: 'main_menu_cloud_trial',
},
}));
};
const someLimitNeedsAttention = Boolean(useGetHighestThresholdCloudLimit(useGetUsage(), useGetLimits()[0]));
if (!isCloud) {
@@ -109,24 +95,7 @@ const MenuCloudTrial = ({id}: Props): JSX.Element | null => {
);
// menu option displayed when the workspace is not running any trial
const noFreeTrialContent = (noPriorTrial && !cloudFreeDeprecated) ? (
<FormattedMessage
id='menu.cloudFree.priorTrial.tryEnterprise'
defaultMessage='Interested in a limitless plan with high-security features? <openModalLink>Try Enterprise free for 30 days</openModalLink>'
values={
{
openModalLink: (msg: string) => (
<a
className='open-learn-more-trial-modal style-link'
onClick={openLearnMoreTrialModal}
>
{msg}
</a>
),
}
}
/>
) : (
const noFreeTrialContent = (
<FormattedMessage
id='menu.cloudFree.postTrial.tryEnterprise'
defaultMessage='Interested in a limitless plan with high-security features? <openModalLink>See plans</openModalLink>'

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

@@ -336,9 +336,6 @@
"admin.billing.subscription.cloudReverseTrial.lastDay": "This is the last day of your trial. Purchase a plan before {userEndTrialHour} or contact sales",
"admin.billing.subscription.cloudReverseTrial.subscribeButton": "Review your options",
"admin.billing.subscription.cloudTrial.daysLeft": "Your trial has started! There are {daysLeftOnTrial} days left",
"admin.billing.subscription.cloudTrial.daysLeftOnTrial": "There are {daysLeftOnTrial} days left on your free trial",
"admin.billing.subscription.cloudTrial.lastDay": "This is the last day of your free trial. Your access will expire on {userEndTrialDate} at {userEndTrialHour}.",
"admin.billing.subscription.cloudTrial.moreThan3Days": "Your trial has started! There are {daysLeftOnTrial} days left",
"admin.billing.subscription.cloudTrial.subscribeButton": "Upgrade Now",
"admin.billing.subscription.cloudTrialBadge.daysLeftOnTrial": "{daysLeftOnTrial} trial days left",
"admin.billing.subscription.cloudYearlyBadge": "Annual",
@@ -4151,7 +4148,6 @@
"menu.cloudFree.enterpriseTrialDescription": "Your trial is active until {trialEndDay}. Discover our top Enterprise features. <openModalLink>Learn more</openModalLink>",
"menu.cloudFree.enterpriseTrialTitle": "Enterprise Trial",
"menu.cloudFree.postTrial.tryEnterprise": "Interested in a limitless plan with high-security features? <openModalLink>See plans</openModalLink>",
"menu.cloudFree.priorTrial.tryEnterprise": "Interested in a limitless plan with high-security features? <openModalLink>Try Enterprise free for 30 days</openModalLink>",
"message_submit_error.invalidCommand": "Command with a trigger of ''{command}'' not found. ",
"message_submit_error.sendAsMessageLink": "Click here to send as a message.",
"mfa.confirm.complete": "**Set up complete!**",
@@ -5041,7 +5037,6 @@
"start_trial_form.modal_title": "Start Trial",
"start_trial_form.name": "Name",
"start_trial.modal_btn.start_free_trial": "Start free 30-day trial",
"start_trial.modal.disclaimer": "By clicking “Start free 30-day trial”, I agree to the <linkEvaluation>Mattermost Software Evaluation Agreement</linkEvaluation>, <linkPrivacy>privacy policy</linkPrivacy> and receiving product emails.",
"start_trial.modal.failed": "Failed",
"start_trial.modal.gettingTrial": "Getting Trial...",
"start_trial.modal.loaded": "Loaded!",

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

@@ -329,14 +329,6 @@ export function onboardingTourTipsEnabled(state: GlobalState): boolean {
return getFeatureFlagValue(state, 'OnboardingTourTips') === 'true';
}
export function deprecateCloudFree(state: GlobalState): boolean {
return getFeatureFlagValue(state, 'DeprecateCloudFree') === 'true';
}
export function cloudReverseTrial(state: GlobalState): boolean {
return getFeatureFlagValue(state, 'CloudReverseTrial') === 'true';
}
export function moveThreadsEnabled(state: GlobalState): boolean {
return getFeatureFlagValue(state, 'MoveThreadsEnabled') === 'true' && getLicense(state).IsLicensed === 'true';
}