[MM-52158] - Don't show deprecation/move to annual banners to some clients (#22963)
* [MM-52158] - Don't show deprecation/move to annual banners to some clients * create const * feedback impl * update test names * update banner text --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
89f2ebc836
Коммит
87555aa242
@@ -103,6 +103,7 @@ func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
DNS: "",
|
DNS: "",
|
||||||
LastInvoice: &model.Invoice{},
|
LastInvoice: &model.Invoice{},
|
||||||
DelinquentSince: subscription.DelinquentSince,
|
DelinquentSince: subscription.DelinquentSince,
|
||||||
|
BillingType: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ type Subscription struct {
|
|||||||
DelinquentSince *int64 `json:"delinquent_since"`
|
DelinquentSince *int64 `json:"delinquent_since"`
|
||||||
OriginallyLicensedSeats int `json:"originally_licensed_seats"`
|
OriginallyLicensedSeats int `json:"originally_licensed_seats"`
|
||||||
ComplianceBlocked string `json:"compliance_blocked"`
|
ComplianceBlocked string `json:"compliance_blocked"`
|
||||||
|
BillingType string `json:"billing_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subscription History model represents true up event in a yearly subscription
|
// Subscription History model represents true up event in a yearly subscription
|
||||||
|
|||||||
@@ -197,6 +197,58 @@ describe('ToYearlyNudgeBannerDismissable', () => {
|
|||||||
|
|
||||||
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-announcement-bar')).toThrow();
|
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-announcement-bar')).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should NOT show when subscription has billing type of internal', () => {
|
||||||
|
const state = JSON.parse(JSON.stringify(initialState));
|
||||||
|
state.entities.users.profiles = {
|
||||||
|
current_user_id: {roles: 'system_admin'},
|
||||||
|
};
|
||||||
|
state.entities.cloud = {
|
||||||
|
subscription: {
|
||||||
|
product_id: 'prod_professional',
|
||||||
|
is_free_trial: 'false',
|
||||||
|
trial_end_at: 1,
|
||||||
|
billing_type: 'internal',
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
prod_professional: {
|
||||||
|
id: 'prod_professional',
|
||||||
|
sku: CloudProducts.PROFESSIONAL,
|
||||||
|
recurring_interval: RecurringIntervals.MONTH,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
renderWithIntlAndStore(<ToYearlyNudgeBannerDismissable/>, state);
|
||||||
|
|
||||||
|
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-announcement-bar')).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should NOT show when subscription has billing type of licensed', () => {
|
||||||
|
const state = JSON.parse(JSON.stringify(initialState));
|
||||||
|
state.entities.users.profiles = {
|
||||||
|
current_user_id: {roles: 'system_admin'},
|
||||||
|
};
|
||||||
|
state.entities.cloud = {
|
||||||
|
subscription: {
|
||||||
|
product_id: 'prod_professional',
|
||||||
|
is_free_trial: 'false',
|
||||||
|
trial_end_at: 1,
|
||||||
|
billing_type: 'licensed',
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
prod_professional: {
|
||||||
|
id: 'prod_professional',
|
||||||
|
sku: CloudProducts.PROFESSIONAL,
|
||||||
|
recurring_interval: RecurringIntervals.MONTH,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
renderWithIntlAndStore(<ToYearlyNudgeBannerDismissable/>, state);
|
||||||
|
|
||||||
|
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-announcement-bar')).toThrow();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ToYearlyNudgeBanner', () => {
|
describe('ToYearlyNudgeBanner', () => {
|
||||||
@@ -241,6 +293,51 @@ describe('ToYearlyNudgeBanner', () => {
|
|||||||
|
|
||||||
renderWithIntlAndStore(<ToYearlyNudgeBanner/>, state);
|
renderWithIntlAndStore(<ToYearlyNudgeBanner/>, state);
|
||||||
|
|
||||||
|
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-alert-banner')).toThrow();
|
||||||
|
});
|
||||||
|
test('should NOT show when subscription has billing type of internal', () => {
|
||||||
|
const state = JSON.parse(JSON.stringify(initialState));
|
||||||
|
state.entities.cloud = {
|
||||||
|
subscription: {
|
||||||
|
product_id: 'prod_professional',
|
||||||
|
is_free_trial: 'false',
|
||||||
|
trial_end_at: 1,
|
||||||
|
billing_type: 'internal',
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
prod_professional: {
|
||||||
|
id: 'prod_professional',
|
||||||
|
sku: CloudProducts.PROFESSIONAL,
|
||||||
|
recurring_interval: RecurringIntervals.MONTH,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
renderWithIntlAndStore(<ToYearlyNudgeBanner/>, state);
|
||||||
|
|
||||||
|
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-alert-banner')).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should NOT show when subscription has billing type of licensed', () => {
|
||||||
|
const state = JSON.parse(JSON.stringify(initialState));
|
||||||
|
state.entities.cloud = {
|
||||||
|
subscription: {
|
||||||
|
product_id: 'prod_professional',
|
||||||
|
is_free_trial: 'false',
|
||||||
|
trial_end_at: 1,
|
||||||
|
billing_type: 'licensed',
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
prod_professional: {
|
||||||
|
id: 'prod_professional',
|
||||||
|
sku: CloudProducts.PROFESSIONAL,
|
||||||
|
recurring_interval: RecurringIntervals.MONTH,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
renderWithIntlAndStore(<ToYearlyNudgeBanner/>, state);
|
||||||
|
|
||||||
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-alert-banner')).toThrow();
|
expect(() => screen.getByTestId('cloud-pro-monthly-deprecation-alert-banner')).toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ import useOpenCloudPurchaseModal from 'components/common/hooks/useOpenCloudPurch
|
|||||||
import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink';
|
import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink';
|
||||||
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
|
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
|
||||||
|
|
||||||
import {getSubscriptionProduct as selectSubscriptionProduct} from 'mattermost-redux/selectors/entities/cloud';
|
import {getSubscriptionProduct as selectSubscriptionProduct, getCloudSubscription as selectCloudSubscription} from 'mattermost-redux/selectors/entities/cloud';
|
||||||
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||||
import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences';
|
import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences';
|
||||||
|
|
||||||
import {AnnouncementBarTypes, CloudBanners, CloudProducts, Preferences, RecurringIntervals} from 'utils/constants';
|
import {AnnouncementBarTypes, CloudBanners, CloudProducts, Preferences, RecurringIntervals, CloudBillingTypes} from 'utils/constants';
|
||||||
import {t} from 'utils/i18n';
|
import {t} from 'utils/i18n';
|
||||||
|
|
||||||
import {GlobalState} from '@mattermost/types/store';
|
import {GlobalState} from '@mattermost/types/store';
|
||||||
@@ -53,6 +53,7 @@ const ToYearlyNudgeBannerDismissable = () => {
|
|||||||
const show = snoozeInfo.show;
|
const show = snoozeInfo.show;
|
||||||
|
|
||||||
const currentUser = useSelector(getCurrentUser);
|
const currentUser = useSelector(getCurrentUser);
|
||||||
|
const subscription = useSelector(selectCloudSubscription);
|
||||||
const isAdmin = useSelector(isCurrentUserSystemAdmin);
|
const isAdmin = useSelector(isCurrentUserSystemAdmin);
|
||||||
const product = useSelector(selectSubscriptionProduct);
|
const product = useSelector(selectSubscriptionProduct);
|
||||||
const currentProductProfessional = product?.sku === CloudProducts.PROFESSIONAL;
|
const currentProductProfessional = product?.sku === CloudProducts.PROFESSIONAL;
|
||||||
@@ -139,6 +140,10 @@ const ToYearlyNudgeBannerDismissable = () => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subscription?.billing_type === CloudBillingTypes.INTERNAL || subscription?.billing_type === CloudBillingTypes.LICENSED) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const message = (
|
const message = (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='cloud_billing.nudge_to_yearly.announcement_bar'
|
id='cloud_billing.nudge_to_yearly.announcement_bar'
|
||||||
@@ -159,7 +164,7 @@ const ToYearlyNudgeBannerDismissable = () => {
|
|||||||
showCloseButton={daysToProMonthlyEnd > 10}
|
showCloseButton={daysToProMonthlyEnd > 10}
|
||||||
onButtonClick={() => openPurchaseModal({trackingLocation: 'to_yearly_nudge_annoucement_bar'})}
|
onButtonClick={() => openPurchaseModal({trackingLocation: 'to_yearly_nudge_annoucement_bar'})}
|
||||||
modalButtonText={t('cloud_billing.nudge_to_yearly.learn_more')}
|
modalButtonText={t('cloud_billing.nudge_to_yearly.learn_more')}
|
||||||
modalButtonDefaultText='Learn more'
|
modalButtonDefaultText='Update billing'
|
||||||
message={message}
|
message={message}
|
||||||
showLinkAsButton={true}
|
showLinkAsButton={true}
|
||||||
handleClose={showBanner}
|
handleClose={showBanner}
|
||||||
@@ -173,6 +178,7 @@ const ToYearlyNudgeBanner = () => {
|
|||||||
const [openSalesLink] = useOpenSalesLink();
|
const [openSalesLink] = useOpenSalesLink();
|
||||||
const openPurchaseModal = useOpenCloudPurchaseModal({});
|
const openPurchaseModal = useOpenCloudPurchaseModal({});
|
||||||
|
|
||||||
|
const subscription = useSelector(selectCloudSubscription);
|
||||||
const product = useSelector(selectSubscriptionProduct);
|
const product = useSelector(selectSubscriptionProduct);
|
||||||
const currentProductProfessional = product?.sku === CloudProducts.PROFESSIONAL;
|
const currentProductProfessional = product?.sku === CloudProducts.PROFESSIONAL;
|
||||||
const currentProductIsMonthly = product?.recurring_interval === RecurringIntervals.MONTH;
|
const currentProductIsMonthly = product?.recurring_interval === RecurringIntervals.MONTH;
|
||||||
@@ -182,6 +188,10 @@ const ToYearlyNudgeBanner = () => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subscription?.billing_type === CloudBillingTypes.INTERNAL || subscription?.billing_type === CloudBillingTypes.LICENSED) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const now = moment(Date.now());
|
const now = moment(Date.now());
|
||||||
const proMonthlyEndDate = moment(cloudProMonthlyCloseMoment, 'YYYYMMDD');
|
const proMonthlyEndDate = moment(cloudProMonthlyCloseMoment, 'YYYYMMDD');
|
||||||
const daysToProMonthlyEnd = proMonthlyEndDate.diff(now, 'days');
|
const daysToProMonthlyEnd = proMonthlyEndDate.diff(now, 'days');
|
||||||
|
|||||||
@@ -3056,7 +3056,7 @@
|
|||||||
"cloud_billing.nudge_to_yearly.announcement_bar": "Monthly billing will be discontinued in {days} days . Switch to annual billing",
|
"cloud_billing.nudge_to_yearly.announcement_bar": "Monthly billing will be discontinued in {days} days . Switch to annual billing",
|
||||||
"cloud_billing.nudge_to_yearly.contact_sales": "Contact sales",
|
"cloud_billing.nudge_to_yearly.contact_sales": "Contact sales",
|
||||||
"cloud_billing.nudge_to_yearly.description": "Monthly billing will be discontinued on {date}. To keep your workspace, switch to annual billing.",
|
"cloud_billing.nudge_to_yearly.description": "Monthly billing will be discontinued on {date}. To keep your workspace, switch to annual billing.",
|
||||||
"cloud_billing.nudge_to_yearly.learn_more": "Learn more",
|
"cloud_billing.nudge_to_yearly.learn_more": "Update billing",
|
||||||
"cloud_billing.nudge_to_yearly.title": "Action required: Switch to annual billing to keep your workspace.",
|
"cloud_billing.nudge_to_yearly.title": "Action required: Switch to annual billing to keep your workspace.",
|
||||||
"cloud_delinquency.banner.buttonText": "Update billing now",
|
"cloud_delinquency.banner.buttonText": "Update billing now",
|
||||||
"cloud_delinquency.banner.end_user_notify_admin_button": "Notify admin",
|
"cloud_delinquency.banner.end_user_notify_admin_button": "Notify admin",
|
||||||
|
|||||||
@@ -504,6 +504,11 @@ export const CloudProducts = {
|
|||||||
LEGACY: 'cloud-legacy',
|
LEGACY: 'cloud-legacy',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const CloudBillingTypes = {
|
||||||
|
INTERNAL: 'internal',
|
||||||
|
LICENSED: 'licensed',
|
||||||
|
};
|
||||||
|
|
||||||
export const SelfHostedProducts = {
|
export const SelfHostedProducts = {
|
||||||
STARTER: 'starter',
|
STARTER: 'starter',
|
||||||
PROFESSIONAL: 'professional',
|
PROFESSIONAL: 'professional',
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export type Subscription = {
|
|||||||
is_free_trial: string;
|
is_free_trial: string;
|
||||||
delinquent_since?: number;
|
delinquent_since?: number;
|
||||||
compliance_blocked?: string;
|
compliance_blocked?: string;
|
||||||
|
billing_type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Product = {
|
export type Product = {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user