From c326ae4ca347e06378576237a043551a30fe498a Mon Sep 17 00:00:00 2001 From: Jens Herman Date: Tue, 16 Apr 2024 18:29:55 +0200 Subject: [PATCH] Removed trial announcement bar --- .../announcement_bar_controller.tsx | 29 -- .../cloud_trial_announcement_bar.tsx | 233 ------------- .../cloud_trial_announcement_bar/index.ts | 66 ---- ...loud_trial_ended_announcement_bar.test.tsx | 325 ------------------ .../index.tsx | 129 ------- .../payment_announcement_bar/index.test.tsx | 97 ------ .../payment_announcement_bar/index.tsx | 88 ----- .../show_start_trial_modal.test.tsx.snap | 3 - .../show_start_trial_modal.test.tsx | 304 ---------------- .../show_start_trial_modal.tsx | 92 ----- .../show_three_days_left_trial_modal.test.tsx | 244 ------------- .../show_three_days_left_trial_modal.tsx | 94 ----- 12 files changed, 1704 deletions(-) delete mode 100644 webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/cloud_trial_announcement_bar.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/index.ts delete mode 100644 webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/cloud_trial_ended_announcement_bar.test.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.test.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/show_start_trial_modal/__snapshots__/show_start_trial_modal.test.tsx.snap delete mode 100644 webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.test.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.test.tsx delete mode 100644 webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.tsx diff --git a/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx b/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx index 2df53ce9fd..f6e7c3b5a3 100644 --- a/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx +++ b/webapp/channels/src/components/announcement_bar/announcement_bar_controller.tsx @@ -10,14 +10,9 @@ import withGetCloudSubscription from 'components/common/hocs/cloud/with_get_clou import CloudAnnualRenewalAnnouncementBar from './cloud_annual_renewal'; import CloudDelinquencyAnnouncementBar from './cloud_delinquency'; -import CloudTrialAnnouncementBar from './cloud_trial_announcement_bar'; -import CloudTrialEndAnnouncementBar from './cloud_trial_ended_announcement_bar'; import ConfigurationAnnouncementBar from './configuration_bar'; import AnnouncementBar from './default_announcement_bar'; import OverageUsersBanner from './overage_users_banner'; -import PaymentAnnouncementBar from './payment_announcement_bar'; -import AutoStartTrialModal from './show_start_trial_modal/show_start_trial_modal'; -import ShowThreeDaysLeftTrialModal from './show_tree_days_left_trial_modal/show_three_days_left_trial_modal'; import TextDismissableBar from './text_dismissable_bar'; import UsersLimitsAnnouncementBar from './users_limits_announcement_bar'; import VersionBar from './version_bar'; @@ -64,24 +59,12 @@ class AnnouncementBarController extends React.PureComponent { ); } - let paymentAnnouncementBar = null; - let cloudTrialAnnouncementBar = null; - let cloudTrialEndAnnouncementBar = null; let cloudDelinquencyAnnouncementBar = null; let cloudRenewalAnnouncementBar = null; const notifyAdminDowngradeDelinquencyBar = null; const toYearlyNudgeBannerDismissable = null; let toPaidPlanNudgeBannerDismissable = null; if (this.props.license?.Cloud === 'true') { - paymentAnnouncementBar = ( - - ); - cloudTrialAnnouncementBar = ( - - ); - cloudTrialEndAnnouncementBar = ( - - ); cloudDelinquencyAnnouncementBar = ( ); @@ -91,13 +74,6 @@ class AnnouncementBarController extends React.PureComponent { toPaidPlanNudgeBannerDismissable = (); } - let autoStartTrialModal = null; - if (this.props.userIsAdmin) { - autoStartTrialModal = ( - - ); - } - return ( <> {adminConfiguredAnnouncementBar} @@ -106,17 +82,12 @@ class AnnouncementBarController extends React.PureComponent { license={this.props.license} userIsAdmin={this.props.userIsAdmin} /> - {paymentAnnouncementBar} - {cloudTrialAnnouncementBar} - {cloudTrialEndAnnouncementBar} {cloudDelinquencyAnnouncementBar} {cloudRenewalAnnouncementBar} {notifyAdminDowngradeDelinquencyBar} {toYearlyNudgeBannerDismissable} {toPaidPlanNudgeBannerDismissable} {this.props.license?.Cloud !== 'true' && } - {autoStartTrialModal} - void; - getCloudSubscription: () => void; - openModal:

(modalData: ModalData

) => void; - }; -}; - -const MAX_DAYS_BANNER = 'max_days_banner'; -const THREE_DAYS_BANNER = '3_days_banner'; -class CloudTrialAnnouncementBar extends React.PureComponent { - async componentDidMount() { - if (!isEmpty(this.props.subscription) && this.shouldShowBanner()) { - const {daysLeftOnTrial} = this.props; - if (this.isDismissable()) { - trackEvent( - TELEMETRY_CATEGORIES.CLOUD_ADMIN, - `bannerview_trial_${daysLeftOnTrial}_days`, - ); - } else { - trackEvent( - TELEMETRY_CATEGORIES.CLOUD_ADMIN, - 'bannerview_trial_limit_ended', - ); - } - } - } - - handleClose = async () => { - const {daysLeftOnTrial} = this.props; - let dismissValue = ''; - if (daysLeftOnTrial > TrialPeriodDays.TRIAL_WARNING_THRESHOLD) { - dismissValue = MAX_DAYS_BANNER; - } else if (daysLeftOnTrial <= TrialPeriodDays.TRIAL_WARNING_THRESHOLD && daysLeftOnTrial >= TrialPeriodDays.TRIAL_1_DAY) { - dismissValue = THREE_DAYS_BANNER; - } - trackEvent( - TELEMETRY_CATEGORIES.CLOUD_ADMIN, - `dismissed_banner_trial_${daysLeftOnTrial}_days`, - ); - await this.props.actions.savePreferences(this.props.currentUser.id, [{ - category: Preferences.CLOUD_TRIAL_BANNER, - user_id: this.props.currentUser.id, - name: CloudBanners.TRIAL, - value: `${dismissValue}`, - }]); - }; - - shouldShowBanner = () => { - const {isFreeTrial, userIsAdmin, isCloud} = this.props; - return isFreeTrial && userIsAdmin && isCloud; - }; - - isDismissable = () => { - const {daysLeftOnTrial} = this.props; - let dismissable = true; - - if (daysLeftOnTrial <= TrialPeriodDays.TRIAL_1_DAY) { - dismissable = false; - } - return dismissable; - }; - - showModal = () => { - const {daysLeftOnTrial} = this.props; - if (this.isDismissable()) { - trackEvent( - TELEMETRY_CATEGORIES.CLOUD_ADMIN, - `click_subscribe_from_trial_banner_${daysLeftOnTrial}_days`, - ); - } else { - trackEvent( - TELEMETRY_CATEGORIES.CLOUD_ADMIN, - 'click_subscribe_from_banner_trial_ended', - ); - } - this.props.actions.openModal({ - modalId: ModalIdentifiers.PRICING_MODAL, - dialogType: PricingModal, - }); - }; - - render() { - const {daysLeftOnTrial, preferences} = this.props; - - if (!this.shouldShowBanner()) { - return null; - } - - if ((preferences.some((pref) => pref.name === CloudBanners.TRIAL && pref.value === MAX_DAYS_BANNER) && daysLeftOnTrial > TrialPeriodDays.TRIAL_WARNING_THRESHOLD) || - ((daysLeftOnTrial <= TrialPeriodDays.TRIAL_WARNING_THRESHOLD && daysLeftOnTrial >= TrialPeriodDays.TRIAL_1_DAY) && - preferences.some((pref) => pref.name === CloudBanners.TRIAL && pref.value === THREE_DAYS_BANNER))) { - return null; - } - - let trialMoreThan7DaysMsg = ( - - ); - - let modalButtonText = t('admin.billing.subscription.cloudTrial.subscribeButton'); - let modalButtonDefaultText = 'Upgrade Now'; - - if (this.props.reverseTrial) { - modalButtonText = t('admin.billing.subscription.cloudReverseTrial.subscribeButton'); - modalButtonDefaultText = 'Review your options'; - } - - if (this.props.reverseTrial) { - const trialEnd = getLocaleDateFromUTC((this.props.subscription?.trial_end_at as number / 1000), 'MMMM Do'); - trialMoreThan7DaysMsg = ( - - ); - } - - let trialLessThan7DaysMsg = ( - - ); - - if (this.props.reverseTrial) { - trialLessThan7DaysMsg = ( - - ); - } - - 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 = ( - - ); - - if (this.props.reverseTrial) { - trialLastDaysMsg = ( - - ); - } - - let bannerMessage; - let icon; - - if (daysLeftOnTrial >= TrialPeriodDays.TRIAL_2_DAYS && daysLeftOnTrial <= TrialPeriodDays.TRIAL_WARNING_THRESHOLD) { - bannerMessage = trialLessThan7DaysMsg; - icon = ; - } else if (daysLeftOnTrial <= TrialPeriodDays.TRIAL_1_DAY && daysLeftOnTrial >= TrialPeriodDays.TRIAL_0_DAYS) { - bannerMessage = trialLastDaysMsg; - icon = ; - } else { - bannerMessage = trialMoreThan7DaysMsg; - icon = ; - } - - const dismissable = this.isDismissable(); - - return ( - - ); - } -} - -export default CloudTrialAnnouncementBar; diff --git a/webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/index.ts b/webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/index.ts deleted file mode 100644 index d64fafe534..0000000000 --- a/webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {connect} from 'react-redux'; -import {bindActionCreators} from 'redux'; -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'; - -import {openModal} from 'actions/views/modals'; - -import {Preferences, TrialPeriodDays} from 'utils/constants'; -import {getRemainingDaysFromFutureTimestamp} from 'utils/utils'; - -import type {GlobalState} from 'types/store'; - -import CloudTrialAnnouncementBar from './cloud_trial_announcement_bar'; - -function mapStateToProps(state: GlobalState) { - const getCategory = makeGetCategory(); - - const subscription = state.entities.cloud.subscription; - 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; - daysLeftOnTrial = Math.min( - getRemainingDaysFromFutureTimestamp(subscription.trial_end_at), - TrialPeriodDays.TRIAL_30_DAYS, - ); - } - - return { - isFreeTrial, - daysLeftOnTrial, - userIsAdmin: isCurrentUserSystemAdmin(state), - currentUser: getCurrentUser(state), - isCloud, - subscription, - preferences: getCategory(state, Preferences.CLOUD_TRIAL_BANNER), - reverseTrial: Boolean(config.FeatureFlags?.CloudReverseTrial), - }; -} - -function mapDispatchToProps(dispatch: Dispatch) { - return { - actions: bindActionCreators( - { - savePreferences, - openModal, - getCloudSubscription, - }, - dispatch, - ), - }; -} - -export default connect(mapStateToProps, mapDispatchToProps)(CloudTrialAnnouncementBar); diff --git a/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/cloud_trial_ended_announcement_bar.test.tsx b/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/cloud_trial_ended_announcement_bar.test.tsx deleted file mode 100644 index 7794acd1aa..0000000000 --- a/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/cloud_trial_ended_announcement_bar.test.tsx +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; -import * as reactRedux from 'react-redux'; - -import {getPreferenceKey} from 'mattermost-redux/utils/preference_utils'; - -import {mountWithIntl} from 'tests/helpers/intl-test-helper'; -import mockStore from 'tests/test_store'; -import {CloudProducts, Preferences, CloudBanners} from 'utils/constants'; -import {FileSizes} from 'utils/file_utils'; - -import CloudTrialEndAnnouncementBar from './index'; - -describe('components/global/CloudTrialEndAnnouncementBar', () => { - const useDispatchMock = jest.spyOn(reactRedux, 'useDispatch'); - - beforeEach(() => { - useDispatchMock.mockClear(); - }); - const initialState = { - views: { - announcementBar: { - announcementBarState: { - announcementBarCount: 1, - }, - }, - }, - entities: { - preferences: { - myPreferences: { - category: Preferences.CLOUD_TRIAL_END_BANNER, - name: CloudBanners.HIDE, - user_id: 'current_user_id', - value: 'false', - }, - }, - general: { - license: { - IsLicensed: 'true', - Cloud: 'true', - }, - }, - users: { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin'}, - }, - }, - cloud: { - subscription: { - product_id: 'test_prod_1', - trial_end_at: 1652807380, - is_free_trial: 'false', - }, - products: { - test_prod_1: { - id: 'test_prod_1', - sku: CloudProducts.STARTER, - price_per_seat: 0, - }, - test_prod_2: { - id: 'test_prod_2', - sku: CloudProducts.ENTERPRISE, - price_per_seat: 0, - }, - test_prod_3: { - id: 'test_prod_3', - sku: CloudProducts.PROFESSIONAL, - price_per_seat: 0, - }, - }, - limits: { - limitsLoaded: true, - limits: { - integrations: { - enabled: 10, - }, - messages: { - history: 10000, - }, - files: { - total_storage: FileSizes.Gigabyte, - }, - teams: { - active: 1, - }, - boards: { - cards: 500, - views: 5, - }, - }, - }, - }, - usage: { - integrations: { - enabled: 11, - enabledLoaded: true, - }, - messages: { - history: 10000, - historyLoaded: true, - }, - files: { - totalStorage: FileSizes.Gigabyte, - totalStorageLoaded: true, - }, - teams: { - active: 1, - cloudArchived: 0, - teamsLoaded: true, - }, - boards: { - cards: 500, - cardsLoaded: true, - }, - }, - }, - }; - it('Should show banner when not on free trial with a trial_end_at in the past', () => { - const state = JSON.parse(JSON.stringify(initialState)); - state.entities.cloud.subscription = { - ...state.entities.cloud.subscription, - trial_end_at: 1655577344000, - }; - - // Set the system time to be June 20th, since this banner won't show for trial's ending prior to June 15 - jest.useFakeTimers().setSystemTime(new Date('2022-06-20')); - - const store = mockStore(state); - - const dummyDispatch = jest.fn(); - useDispatchMock.mockReturnValue(dummyDispatch); - - const wrapper = mountWithIntl( - - - , - ); - - expect( - wrapper.find('AnnouncementBar').exists(), - ).toEqual(true); - }); - - it('Should show banner cloudArchived teams exist', () => { - const state = JSON.parse(JSON.stringify(initialState)); - state.entities.cloud.subscription = { - ...state.entities.cloud.subscription, - trial_end_at: 1655577344000, - }; - state.entities.usage.teams = { - cloudArchived: 2, - active: -1, - teamsLoaded: true, - }; - - // Set the system time to be June 20th, since this banner won't show for trial's ending prior to June 15 - jest.useFakeTimers().setSystemTime(new Date('2022-06-20')); - - const store = mockStore(state); - - const dummyDispatch = jest.fn(); - useDispatchMock.mockReturnValue(dummyDispatch); - - const wrapper = mountWithIntl( - - - , - ); - - expect(wrapper.find('AnnouncementBar').exists()).toEqual(true); - }); - - it('should not show banner if on free trial', () => { - const state = JSON.parse(JSON.stringify(initialState)); - state.entities.cloud = { - subscription: { - product_id: 'test_prod_2', - is_free_trial: 'true', - trial_end_at: new Date( - new Date().getTime() + (2 * 24 * 60 * 60 * 1000), - ), - }, - products: { - test_prod_2: { - id: 'test_prod_2', - sku: CloudProducts.ENTERPRISE, - price_per_seat: 10, - }, - }, - limits: { - limitsLoaded: true, - limits: { - integrations: { - enabled: 10, - }, - messages: { - history: 10000, - }, - files: { - total_storage: FileSizes.Gigabyte, - }, - teams: { - active: 1, - }, - boards: { - cards: 500, - views: 5, - }, - }, - }, - usage: { - integrations: { - enabled: 11, - enabledLoaded: true, - }, - messages: { - history: 10000, - historyLoaded: true, - }, - files: { - totalStorage: FileSizes.Gigabyte, - totalStorageLoaded: true, - }, - teams: { - active: 1, - teamsLoaded: true, - }, - boards: { - cards: 500, - cardsLoaded: true, - }, - }, - }; - - const store = mockStore(state); - - const dummyDispatch = jest.fn(); - useDispatchMock.mockReturnValue(dummyDispatch); - - const wrapper = mountWithIntl( - - - , - ); - - expect( - wrapper.find('AnnouncementBar').exists(), - ).toEqual(false); - }); - - it('should not show for non-admins', () => { - const state = JSON.parse(JSON.stringify(initialState)); - state.entities.users = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'user'}, - }, - }; - - const store = mockStore(state); - const wrapper = mountWithIntl( - - - , - ); - - expect( - wrapper.find('AnnouncementBar').exists(), - ).toEqual(false); - }); - - it('should not show for enterprise workspaces', () => { - const state = JSON.parse(JSON.stringify(initialState)); - state.entities.cloud.subscription.product_id = 'test_prod_2'; - - const store = mockStore(state); - const wrapper = mountWithIntl( - - - , - ); - - expect(wrapper.find('AnnouncementBar').exists()).toEqual(false); - }); - - it('should not show for professional workspaces', () => { - const state = JSON.parse(JSON.stringify(initialState)); - state.entities.cloud.subscription.product_id = 'test_prod_3'; - - const store = mockStore(state); - const wrapper = mountWithIntl( - - - , - ); - - expect(wrapper.find('AnnouncementBar').exists()).toEqual(false); - }); - - it('Should not show banner if preference is set to hidden', () => { - const state = JSON.parse(JSON.stringify(initialState)); - state.entities.preferences = { - myPreferences: { - [getPreferenceKey( - Preferences.CLOUD_TRIAL_END_BANNER, - CloudBanners.HIDE, - )]: {name: CloudBanners.HIDE, value: 'true'}, - }, - }; - - const store = mockStore(state); - const wrapper = mountWithIntl( - - - , - ); - - expect( - wrapper.find('AnnouncementBar').exists(), - ).toEqual(false); - }); -}); diff --git a/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx b/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx deleted file mode 100644 index 8d285fbaa5..0000000000 --- a/webapp/channels/src/components/announcement_bar/cloud_trial_ended_announcement_bar/index.tsx +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; -import {FormattedMessage} from 'react-intl'; -import {useSelector, useDispatch} from 'react-redux'; - -import {savePreferences} from 'mattermost-redux/actions/preferences'; -import { - getSubscriptionProduct, -} from 'mattermost-redux/selectors/entities/cloud'; -import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences'; -import { - getCurrentUser, -} from 'mattermost-redux/selectors/entities/users'; -import {isSystemAdmin} from 'mattermost-redux/utils/user_utils'; - -import useGetLimits from 'components/common/hooks/useGetLimits'; -import useGetSubscription from 'components/common/hooks/useGetSubscription'; -import useOpenPricingModal from 'components/common/hooks/useOpenPricingModal'; - -import { - AnnouncementBarTypes, - Preferences, - CloudBanners, - CloudProducts, -} from 'utils/constants'; -import {t} from 'utils/i18n'; - -import type {GlobalState} from 'types/store'; - -import AnnouncementBar from '../default_announcement_bar'; - -const CloudTrialEndAnnouncementBar: React.FC = () => { - const limits = useGetLimits(); - const subscription = useGetSubscription(); - const getCategory = makeGetCategory(); - const dispatch = useDispatch(); - const preferences = useSelector((state: GlobalState) => - getCategory(state, Preferences.CLOUD_TRIAL_END_BANNER), - ); - const currentUser = useSelector((state: GlobalState) => - getCurrentUser(state), - ); - const subscriptionProduct = useSelector((state: GlobalState) => getSubscriptionProduct(state)); - - const openPricingModal = useOpenPricingModal(); - - const shouldShowBanner = () => { - if (!subscription || !subscriptionProduct) { - return false; - } - - // Make sure limits are loaded before showing banner - if (!limits || !limits[1]) { - return false; - } - - if (!preferences) { - return false; - } - if (preferences.some((pref) => pref.name === CloudBanners.HIDE && pref.value === 'true')) { - return false; - } - - // Don't show this banner for professional or enterprise installations - if (subscriptionProduct?.sku !== CloudProducts.STARTER) { - return false; - } - - const isFreeTrial = subscription.is_free_trial === 'true'; - if (isFreeTrial) { - return false; - } - - const trialEnd = new Date(subscription.trial_end_at); - const now = new Date(); - - // trial_end_at values will be 0 for all freemium subscriptions after June 15 - // Subscriptions created prior to that will almost always have a trial_end_at value, guaranteed. - if (subscription.trial_end_at === 0 || trialEnd > now || trialEnd < new Date('2022-06-15')) { - return false; - } - if (!isSystemAdmin(currentUser.roles)) { - return false; - } - return true; - }; - - if (!shouldShowBanner()) { - return null; - } - - const handleClose = () => { - dispatch( - savePreferences(currentUser.id, [ - { - category: Preferences.CLOUD_TRIAL_END_BANNER, - user_id: currentUser.id, - name: CloudBanners.HIDE, - value: 'true', - }, - ]), - ); - }; - - const message = { - id: t('free.banner.downgraded'), - defaultMessage: - 'Your workspace now has restrictions and some data has been archived', - }; - - return ( - openPricingModal({trackingLocation: 'cloud_trial_ended_announcement_bar'})} - modalButtonText={t('more.details')} - modalButtonDefaultText={'More details'} - message={} - showLinkAsButton={true} - isTallBanner={true} - icon={} - handleClose={handleClose} - /> - ); -}; - -export default CloudTrialEndAnnouncementBar; diff --git a/webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.test.tsx b/webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.test.tsx deleted file mode 100644 index 999e683af4..0000000000 --- a/webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.test.tsx +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; - -import * as cloudActions from 'mattermost-redux/actions/cloud'; - -import {renderWithContext, screen} from 'tests/react_testing_utils'; -import {CloudProducts} from 'utils/constants'; - -import PaymentAnnouncementBar from './'; - -jest.mock('mattermost-redux/actions/cloud', () => { - const original = jest.requireActual('mattermost-redux/actions/cloud'); - return { - ...original, - __esModule: true, - - // just testing that it fired, not that the result updated or anything like that - getCloudCustomer: jest.fn(() => ({type: 'bogus'})), - }; -}); - -describe('PaymentAnnouncementBar', () => { - const happyPathStore = { - entities: { - users: { - currentUserId: 'me', - profiles: { - me: { - roles: 'system_admin', - }, - }, - }, - general: { - license: { - Cloud: 'true', - }, - }, - cloud: { - subscription: { - product_id: 'prod_something', - last_invoice: { - status: 'failed', - }, - }, - customer: { - payment_method: { - exp_month: 12, - exp_year: (new Date()).getFullYear() + 1, - }, - }, - products: { - prod_something: { - id: 'prod_something', - sku: CloudProducts.PROFESSIONAL, - }, - }, - }, - }, - views: { - announcementBar: { - announcementBarState: { - announcementBarCount: 1, - }, - }, - }, - }; - - it('when most recent payment failed, shows that', () => { - renderWithContext(, happyPathStore); - screen.getByText('Your most recent payment failed'); - }); - - it('when card is expired, shows that', () => { - const store = JSON.parse(JSON.stringify(happyPathStore)); - store.entities.cloud.customer.payment_method.exp_year = (new Date()).getFullYear() - 1; - store.entities.cloud.subscription.last_invoice.status = 'success'; - renderWithContext(, store); - screen.getByText('Your credit card has expired', {exact: false}); - }); - - it('when needed, fetches, customer', () => { - const store = JSON.parse(JSON.stringify(happyPathStore)); - store.entities.cloud.customer = null; - store.entities.cloud.subscription.last_invoice.status = 'success'; - renderWithContext(, store); - expect(cloudActions.getCloudCustomer).toHaveBeenCalled(); - }); - - it('when not an admin, does not fetch customer', () => { - const store = JSON.parse(JSON.stringify(happyPathStore)); - store.entities.users.profiles.me.roles = ''; - renderWithContext(, store); - expect(cloudActions.getCloudCustomer).not.toHaveBeenCalled(); - }); -}); diff --git a/webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.tsx b/webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.tsx deleted file mode 100644 index 5cfb6c9e06..0000000000 --- a/webapp/channels/src/components/announcement_bar/payment_announcement_bar/index.tsx +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {isEmpty} from 'lodash'; -import React, {useEffect, useState} from 'react'; -import {FormattedMessage} from 'react-intl'; -import {useSelector, useDispatch} from 'react-redux'; - -import {getCloudCustomer} from 'mattermost-redux/actions/cloud'; -import { - getCloudSubscription as selectCloudSubscription, - getCloudCustomer as selectCloudCustomer, - getSubscriptionProduct, -} from 'mattermost-redux/selectors/entities/cloud'; -import {getLicense} from 'mattermost-redux/selectors/entities/general'; -import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; - -import {getHistory} from 'utils/browser_history'; -import {isCustomerCardExpired} from 'utils/cloud_utils'; -import {AnnouncementBarTypes, CloudProducts, ConsolePages} from 'utils/constants'; -import {t} from 'utils/i18n'; - -import AnnouncementBar from '../default_announcement_bar'; - -export default function PaymentAnnouncementBar() { - const [requestedCustomer, setRequestedCustomer] = useState(false); - const dispatch = useDispatch(); - const subscription = useSelector(selectCloudSubscription); - const customer = useSelector(selectCloudCustomer); - const isStarterFree = useSelector(getSubscriptionProduct)?.sku === CloudProducts.STARTER; - const userIsAdmin = useSelector(isCurrentUserSystemAdmin); - const isCloud = useSelector(getLicense).Cloud === 'true'; - - useEffect(() => { - if (isCloud && !isStarterFree && isEmpty(customer) && userIsAdmin && !requestedCustomer) { - setRequestedCustomer(true); - dispatch(getCloudCustomer()); - } - }, - [isCloud, isStarterFree, customer, userIsAdmin, requestedCustomer]); - - const mostRecentPaymentFailed = subscription?.last_invoice?.status === 'failed'; - - if ( - // Prevents banner flashes if the subscription hasn't been loaded yet - isEmpty(subscription) || - isStarterFree || - !isCloud || - !userIsAdmin || - isEmpty(customer) || - (!isCustomerCardExpired(customer) && !mostRecentPaymentFailed) - ) { - return null; - } - - const updatePaymentInfo = () => { - getHistory().push(ConsolePages.PAYMENT_INFO); - }; - - let message = ( - - ); - - if (mostRecentPaymentFailed) { - message = ( - - ); - } - - return ( - - ); -} diff --git a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/__snapshots__/show_start_trial_modal.test.tsx.snap b/webapp/channels/src/components/announcement_bar/show_start_trial_modal/__snapshots__/show_start_trial_modal.test.tsx.snap deleted file mode 100644 index e1baba7fc8..0000000000 --- a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/__snapshots__/show_start_trial_modal.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`components/sidebar/show_start_trial_modal should match snapshot 1`] = `""`; diff --git a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.test.tsx b/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.test.tsx deleted file mode 100644 index f3960cfbd7..0000000000 --- a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.test.tsx +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {mount, shallow} from 'enzyme'; -import React from 'react'; - -import ShowStartTrialModal from 'components/announcement_bar/show_start_trial_modal/show_start_trial_modal'; -import * as getTotalUsersHook from 'components/common/hooks/useGetTotalUsersNoBots'; - -let mockState: any; -const mockDispatch = jest.fn(); - -jest.mock('react-redux', () => ({ - ...jest.requireActual('react-redux') as typeof import('react-redux'), - useSelector: (selector: (state: typeof mockState) => unknown) => selector(mockState), - useDispatch: () => mockDispatch, -})); - -describe('components/sidebar/show_start_trial_modal', () => { - beforeEach(() => { - const now = new Date().getTime(); - - // required state to mount using the provider - mockState = { - entities: { - admin: { - prevTrialLicense: { - IsLicensed: 'false', - }, - }, - preferences: { - myPreferences: { - 'start_trial_modal--trial_modal_auto_shown': { - name: 'trial_modal_auto_shown', - value: 'false', - }, - }, - }, - general: { - config: { - InstallationDate: now, - }, - license: { - IsLicensed: 'false', - }, - }, - users: { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_user'}, - }, - }, - roles: { - roles: { - system_role: {permissions: ['test_system_permission', 'add_user_to_team', 'invite_guest']}, - team_role: {permissions: ['test_team_no_permission']}, - }, - }, - }, - views: { - modals: { - modalState: { - trial_benefits_modal: { - open: false, - }, - }, - }, - }, - }; - }); - - test('should match snapshot', () => { - const wrapper = shallow( - , - ); - expect(wrapper).toMatchSnapshot(); - }); - - test('should NOT dispatch the modal when there are less than 10 users', () => { - const lessThan10Users = 9; - jest.spyOn(getTotalUsersHook, 'default').mockImplementation(() => lessThan10Users); - - const isAdminUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin system_user'}, - }, - }; - - const moreThan6Hours = { - config: { - - // installation date is set to be 10 hours before current time - InstallationDate: new Date().getTime() - ((10 * 60 * 60) * 1000), - }, - }; - - mockState = {...mockState, entities: {...mockState.entities, users: isAdminUser, general: moreThan6Hours}}; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT dispatch the modal when the env has less than 6 hours of creation', () => { - const isAdminUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin system_user'}, - }, - }; - - const moreThan10Users = 11; - - jest.spyOn(getTotalUsersHook, 'default').mockImplementation(() => moreThan10Users); - - const lessThan6Hours = { - config: { - - // installation date is set to be 5 hours before current time - InstallationDate: new Date().getTime() - ((5 * 60 * 60) * 1000), - }, - }; - - mockState = {...mockState, entities: {...mockState.entities, users: isAdminUser, general: lessThan6Hours}}; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT dispatch the modal when the env has previous license', () => { - const isAdminUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin system_user'}, - }, - }; - - const moreThan10UsersAndPrevLicensed = { - prevTrialLicense: { - IsLicensed: 'true', - }, - }; - - const moreThan10Users = 11; - jest.spyOn(getTotalUsersHook, 'default').mockImplementation(() => moreThan10Users); - - mockState = {...mockState, entities: {...mockState.entities, users: isAdminUser, admin: moreThan10UsersAndPrevLicensed}}; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT dispatch the modal when the env is currently licensed', () => { - const isAdminUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin system_user'}, - }, - }; - - const moreThan10Users = 11; - jest.spyOn(getTotalUsersHook, 'default').mockImplementation(() => moreThan10Users); - - const moreThan6HoursAndLicensed = { - config: { - - // installation date is set to be 10 hours before current time - InstallationDate: new Date().getTime() - ((10 * 60 * 60) * 1000), - }, - license: { - IsLicensed: 'true', - }, - }; - - mockState = {...mockState, entities: {...mockState.entities, users: isAdminUser, general: moreThan6HoursAndLicensed}}; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT dispatch the modal when the modal has been already dismissed', () => { - const isAdminUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin system_user'}, - }, - }; - - const moreThan10Users = 11; - jest.spyOn(getTotalUsersHook, 'default').mockImplementation(() => moreThan10Users); - - const moreThan6Hours = { - config: { - - // installation date is set to be 10 hours before current time - InstallationDate: new Date().getTime() - ((10 * 60 * 60) * 1000), - }, - }; - - const modalDismissed = { - myPreferences: { - 'start_trial_modal--trial_modal_auto_shown': { - name: 'trial_modal_auto_shown', - value: 'true', - }, - }, - }; - - mockState = { - ...mockState, - entities: { - ...mockState.entities, - users: isAdminUser, - general: moreThan6Hours, - preferences: modalDismissed, - }, - }; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT dispatch the modal when user is not an admin', () => { - const isAdminUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_user'}, - }, - }; - - const moreThan10Users = 11; - jest.spyOn(getTotalUsersHook, 'default').mockImplementation(() => moreThan10Users); - - const notPreviouslyLicensed = { - prevTrialLicense: { - IsLicensed: 'false', - }, - }; - - const moreThan6Hours = { - config: { - - // installation date is set to be 10 hours before current time - InstallationDate: new Date().getTime() - ((10 * 60 * 60) * 1000), - }, - license: { - IsLicensed: 'false', - }, - }; - - mockState = {...mockState, entities: {...mockState.entities, users: isAdminUser, admin: notPreviouslyLicensed, general: moreThan6Hours}}; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should dispatch the modal when there are more than 10 users', () => { - const isAdminUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin system_user'}, - }, - }; - - const moreThan10Users = 11; - jest.spyOn(getTotalUsersHook, 'default').mockImplementation(() => moreThan10Users); - - const notPreviouslyLicensed = { - prevTrialLicense: { - IsLicensed: 'false', - }, - }; - - const moreThan6Hours = { - config: { - - // installation date is set to be 10 hours before current time - InstallationDate: new Date().getTime() - ((10 * 60 * 60) * 1000), - }, - license: { - IsLicensed: 'false', - }, - }; - - mockState = {...mockState, entities: {...mockState.entities, users: isAdminUser, admin: notPreviouslyLicensed, general: moreThan6Hours}}; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(1); - }); -}); diff --git a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx b/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx deleted file mode 100644 index 6d38b74156..0000000000 --- a/webapp/channels/src/components/announcement_bar/show_start_trial_modal/show_start_trial_modal.tsx +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {useEffect} from 'react'; -import {useSelector, useDispatch} from 'react-redux'; - -import type {PreferenceType} from '@mattermost/types/preferences'; - -import {savePreferences} from 'mattermost-redux/actions/preferences'; -import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; -import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences'; -import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; - -import {trackEvent} from 'actions/telemetry_actions'; -import {isModalOpen} from 'selectors/views/modals'; - -import useGetTotalUsersNoBots from 'components/common/hooks/useGetTotalUsersNoBots'; -import useOpenStartTrialFormModal from 'components/common/hooks/useOpenStartTrialFormModal'; - -import { - Preferences, - Constants, - TELEMETRY_CATEGORIES, - ModalIdentifiers, -} from 'utils/constants'; - -import type {GlobalState} from 'types/store'; - -const ShowStartTrialModal = () => { - const isUserAdmin = useSelector((state: GlobalState) => isCurrentUserSystemAdmin(state)); - const openStartTrialFormModal = useOpenStartTrialFormModal(); - - const dispatch = useDispatch(); - const getCategory = makeGetCategory(); - - const userThreshold = 10; - const TRUE = 'true'; - - const isBenefitsModalOpened = useSelector((state: GlobalState) => isModalOpen(state, ModalIdentifiers.TRIAL_BENEFITS_MODAL)); - - const installationDate = useSelector((state: GlobalState) => getConfig(state).InstallationDate); - const currentUser = useSelector((state: GlobalState) => getCurrentUser(state)); - const preferences = useSelector((state) => getCategory(state, Preferences.START_TRIAL_MODAL)); - - const prevTrialLicense = useSelector((state: GlobalState) => state.entities.admin.prevTrialLicense); - const currentLicense = useSelector(getLicense); - const isLicensed = (license: any) => { - if (!license?.IsLicensed) { - return false; - } - return license.IsLicensed === TRUE; - }; - const isPrevLicensed = isLicensed(prevTrialLicense); - const isCurrentLicensed = isLicensed(currentLicense); - const totalUsers = useGetTotalUsersNoBots(true); - - // Show this modal if the instance is currently not licensed and has never had a trial license loaded before - const isLicensedOrPreviousLicensed = (isCurrentLicensed || isPrevLicensed); - - const handleOnClose = () => { - trackEvent( - TELEMETRY_CATEGORIES.SELF_HOSTED_START_TRIAL_AUTO_MODAL, - 'close_start_trial_auto_modal', - ); - dispatch(savePreferences(currentUser.id, [ - { - category: Preferences.START_TRIAL_MODAL, - user_id: currentUser.id, - name: Constants.TRIAL_MODAL_AUTO_SHOWN, - value: TRUE, - }, - ])); - }; - - useEffect(() => { - const installationDatePlus6Hours = (6 * 60 * 60 * 1000) + Number(installationDate); - const now = new Date().getTime(); - const hasEnvMoreThan6Hours = now > installationDatePlus6Hours; - const hasEnvMoreThan10Users = Number(totalUsers) > userThreshold; - const hadAdminDismissedModal = preferences.some((pref: PreferenceType) => pref.name === Constants.TRIAL_MODAL_AUTO_SHOWN && pref.value === TRUE); - if (isUserAdmin && !isBenefitsModalOpened && hasEnvMoreThan10Users && hasEnvMoreThan6Hours && !hadAdminDismissedModal && !isLicensedOrPreviousLicensed) { - openStartTrialFormModal({trackingLocation: 'show_start_trial_modal'}, handleOnClose); - trackEvent( - TELEMETRY_CATEGORIES.SELF_HOSTED_START_TRIAL_AUTO_MODAL, - 'trigger_start_trial_auto_modal', - ); - } - }, [totalUsers]); - - return null; -}; -export default ShowStartTrialModal; diff --git a/webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.test.tsx b/webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.test.tsx deleted file mode 100644 index 1493b7d29c..0000000000 --- a/webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.test.tsx +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {mount} from 'enzyme'; -import React from 'react'; - -import ShowThreeDaysLeftTrialModal from 'components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal'; - -import {CloudProducts} from 'utils/constants'; -import {FileSizes} from 'utils/file_utils'; - -let mockState: any; -const mockDispatch = jest.fn(); -const nowMiliseconds = new Date().getTime(); -const oneDayMs = 24 * 60 * 60 * 1000; - -jest.mock('react-redux', () => ({ - ...jest.requireActual('react-redux') as typeof import('react-redux'), - useSelector: (selector: (state: typeof mockState) => unknown) => selector(mockState), - useDispatch: () => mockDispatch, -})); - -describe('components/sidebar/show_three_days_left_trial_modal', () => { - beforeEach(() => { - // required state to mount using the provider - mockState = { - entities: { - admin: {}, - preferences: { - myPreferences: { - 'cloud_trial_banner--dismiss_3_days_left_trial_modal': { - name: 'dismiss_3_days_left_trial_modal', - value: 'false', - }, - }, - }, - general: { - license: { - IsLicensed: 'true', - Cloud: 'true', - }, - }, - users: { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_admin system_user'}, - }, - }, - cloud: { - subscription: { - product_id: 'test_prod_1', - trial_end_at: nowMiliseconds + (2 * oneDayMs), - is_free_trial: 'true', - }, - products: { - test_prod_1: { - id: 'test_prod_1', - sku: CloudProducts.STARTER, - price_per_seat: 0, - }, - test_prod_2: { - id: 'test_prod_2', - sku: CloudProducts.ENTERPRISE, - price_per_seat: 0, - }, - test_prod_3: { - id: 'test_prod_3', - sku: CloudProducts.PROFESSIONAL, - price_per_seat: 0, - }, - }, - limits: { - limitsLoaded: true, - limits: { - integrations: { - enabled: 10, - }, - messages: { - history: 10000, - }, - files: { - total_storage: FileSizes.Gigabyte, - }, - teams: { - active: 1, - }, - boards: { - cards: 500, - views: 5, - }, - }, - }, - }, - roles: { - roles: { - system_role: {permissions: ['test_system_permission', 'add_user_to_team', 'invite_guest']}, - team_role: {permissions: ['test_team_no_permission']}, - }, - }, - usage: { - files: { - totalStorage: 0, - totalStorageLoaded: true, - }, - messages: { - history: 0, - historyLoaded: true, - }, - boards: { - cards: 0, - cardsLoaded: true, - }, - integrations: { - enabled: 3, - enabledLoaded: true, - }, - teams: { - active: 0, - cloudArchived: 0, - teamsLoaded: true, - }, - }, - }, - views: { - modals: { - modalState: { - show_three_days_left_trial_modal: { - open: false, - }, - }, - }, - }, - }; - }); - - test('should show the modal when is cloud, free trial, admin, have not dimissed previously and there are less than 3 days in the trial, ', () => { - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(1); - }); - - test('should NOT show the modal when user is not Admin', () => { - const endUser = { - currentUserId: 'current_user_id', - profiles: { - current_user_id: {roles: 'system_user'}, - }, - }; - - mockState = { - ...mockState, - entities: { - ...mockState.entities, - users: endUser, - }, - }; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT show the modal when is not Cloud', () => { - mockState = {...mockState, entities: {...mockState.entities, general: {...mockState.general, license: {Cloud: 'false'}}}}; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT show the modal when is not Free Trial', () => { - mockState = { - ...mockState, - entities: { - ...mockState.entities, - cloud: { - ...mockState.entities.cloud, - subscription: { - ...mockState.entities.cloud.subscription, - is_free_trial: 'false', - }, - }, - }, - }; - - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT show the modal when there are MORE than three days left in the trial', () => { - mockState = { - ...mockState, - entities: { - ...mockState.entities, - general: { - ...mockState.general, - license: { - Cloud: 'true', - }, - }, - cloud: { - ...mockState.entities.cloud, - subscription: { - ...mockState.entities.cloud.subscription, - is_free_trial: 'true', - trial_end_at: nowMiliseconds + (6 * oneDayMs), - }, - }, - }, - }; - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); - - test('should NOT show the modal when admin have already dismissed the modal', () => { - const modalDismissedPreference = { - myPreferences: { - 'cloud_trial_banner--dismiss_3_days_left_trial_modal': { - name: 'dismiss_3_days_left_trial_modal', - value: 'true', - }, - }, - }; - - mockState = { - ...mockState, - entities: { - ...mockState.entities, - preferences: modalDismissedPreference, - }, - }; - mount( - , - ); - expect(mockDispatch).toHaveBeenCalledTimes(0); - }); -}); diff --git a/webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.tsx b/webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.tsx deleted file mode 100644 index 798cdb9041..0000000000 --- a/webapp/channels/src/components/announcement_bar/show_tree_days_left_trial_modal/show_three_days_left_trial_modal.tsx +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import moment from 'moment'; -import {useEffect} from 'react'; -import {useSelector, useDispatch} from 'react-redux'; - -import {savePreferences} from 'mattermost-redux/actions/preferences'; -import {getCloudSubscription} from 'mattermost-redux/selectors/entities/cloud'; -import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common'; -import {getLicense} from 'mattermost-redux/selectors/entities/general'; -import {get as getPreference} from 'mattermost-redux/selectors/entities/preferences'; -import {isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; - -import {trackEvent} from 'actions/telemetry_actions'; -import {openModal, closeModal} from 'actions/views/modals'; - -import useGetHighestThresholdCloudLimit from 'components/common/hooks/useGetHighestThresholdCloudLimit'; -import useGetLimits from 'components/common/hooks/useGetLimits'; -import useGetUsage from 'components/common/hooks/useGetUsage'; -import ThreeDaysLeftTrialModal from 'components/three_days_left_trial_modal/three_days_left_trial_modal'; - -import { - Preferences, - TELEMETRY_CATEGORIES, - ModalIdentifiers, - CloudBanners, -} from 'utils/constants'; - -import type {GlobalState} from 'types/store'; - -const ShowThreeDaysLeftTrialModal = () => { - const license = useSelector(getLicense); - const isCloud = license?.Cloud === 'true'; - const isUserAdmin = useSelector((state: GlobalState) => isCurrentUserSystemAdmin(state)); - const subscription = useSelector(getCloudSubscription); - const isFreeTrial = subscription?.is_free_trial === 'true'; - - const dispatch = useDispatch(); - const hadAdminDismissedModal = useSelector((state: GlobalState) => getPreference(state, Preferences.CLOUD_TRIAL_BANNER, CloudBanners.THREE_DAYS_LEFT_TRIAL_MODAL_DISMISSED)) === 'true'; - - const trialEndDate = new Date(subscription?.trial_end_at || 0); - - const today = moment(); - const formattedEndDate = moment(Number(trialEndDate || 0)); - const diffDays = formattedEndDate.diff(today, 'days'); - - // the trial will end in three days or left - const trialEndInThreeDaysOrLess = diffDays <= 3; - - // validate the logic for the limits and pass that to the modal as a property - const someLimitNeedsAttention = Boolean(useGetHighestThresholdCloudLimit(useGetUsage(), useGetLimits()[0])); - - const currentUserId = useSelector(getCurrentUserId); - - const handleOnClose = async () => { - trackEvent( - TELEMETRY_CATEGORIES.CLOUD_ADMIN, - 'dismissed_three_days_left_trial_modal', - ); - - await dispatch(savePreferences(currentUserId, [{ - category: Preferences.CLOUD_TRIAL_BANNER, - user_id: currentUserId, - name: CloudBanners.THREE_DAYS_LEFT_TRIAL_MODAL_DISMISSED, - value: 'true', - }])); - dispatch(closeModal(ModalIdentifiers.THREE_DAYS_LEFT_TRIAL_MODAL)); - }; - - useEffect(() => { - if (subscription?.trial_end_at === undefined || subscription.trial_end_at === 0) { - return; - } - - if (isCloud && isFreeTrial && isUserAdmin && !hadAdminDismissedModal && trialEndInThreeDaysOrLess) { - dispatch(openModal({ - modalId: ModalIdentifiers.THREE_DAYS_LEFT_TRIAL_MODAL, - dialogType: ThreeDaysLeftTrialModal, - dialogProps: { - limitsOverpassed: someLimitNeedsAttention, - onExited: handleOnClose, - }, - })); - trackEvent( - TELEMETRY_CATEGORIES.CLOUD_THREE_DAYS_LEFT_MODAL, - 'trigger_cloud_three_days_left_modal', - ); - } - }, [subscription?.trial_end_at]); - - return null; -}; -export default ShowThreeDaysLeftTrialModal;