diff --git a/.circleci/config.yml b/.circleci/config.yml index a8dfb8fb90e2..379740beb9be 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,10 +13,10 @@ executors: aliases: - &restore_cache restore_cache: - key: dependencies-{{ .Branch }}-{{ checksum "package-lock.json" }}-3 + key: dependencies-{{ .Branch }}-{{ checksum "package-lock.json" }}-4 - &save_cache save_cache: - key: dependencies-{{ .Branch }}-{{ checksum "package-lock.json" }}-3 + key: dependencies-{{ .Branch }}-{{ checksum "package-lock.json" }}-4 paths: - ~/mattermost/mattermost-webapp/node_modules diff --git a/components/admin_console/admin_definition.jsx b/components/admin_console/admin_definition.jsx index c30b3f916dab..abaa027c34ab 100644 --- a/components/admin_console/admin_definition.jsx +++ b/components/admin_console/admin_definition.jsx @@ -52,7 +52,7 @@ import CustomTermsOfServiceSettings from './custom_terms_of_service_settings'; import SessionLengthSettings from './session_length_settings'; import LDAPFeatureDiscovery from './feature_discovery/ldap.tsx'; import SAMLFeatureDiscovery from './feature_discovery/saml.tsx'; -import BillingSubscriptions from './billing/billing_subscriptions'; +import BillingSubscriptions from './billing/billing_subscriptions.tsx'; import BillingHistory from './billing/billing_history'; import CompanyInfo from './billing/company_info'; import PaymentInfo from './billing/payment_info'; diff --git a/components/admin_console/billing/billing_subscriptions.tsx b/components/admin_console/billing/billing_subscriptions.tsx index 39aa993ff566..ee9f8bb271bb 100644 --- a/components/admin_console/billing/billing_subscriptions.tsx +++ b/components/admin_console/billing/billing_subscriptions.tsx @@ -2,15 +2,27 @@ // See LICENSE.txt for license information. import React, {useState, useEffect} from 'react'; -import {useDispatch, useStore} from 'react-redux'; -import {FormattedMessage} from 'react-intl'; +import {FormattedMessage, useIntl} from 'react-intl'; +import {useDispatch, useStore, useSelector} from 'react-redux'; import {getCloudSubscription, getCloudProducts} from 'mattermost-redux/actions/cloud'; import {DispatchFunc} from 'mattermost-redux/types/actions'; +import {PreferenceType} from 'mattermost-redux/types/preferences'; + +import {getStandardAnalytics} from 'mattermost-redux/actions/admin'; +import {savePreferences} from 'mattermost-redux/actions/preferences'; +import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; +import {getCurrentUser} from 'mattermost-redux/selectors/entities/users'; +import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences'; + +import {GlobalState} from 'types/store'; import AlertBanner from 'components/alert_banner'; import FormattedMarkdownMessage from 'components/formatted_markdown_message'; import FormattedAdminHeader from 'components/widgets/admin_console/formatted_admin_header'; + +import {Preferences, CloudBanners} from 'utils/constants'; + import privateCloudImage from 'images/private-cloud-image.svg'; import upgradeMattermostCloudImage from 'images/upgrade-mattermost-cloud-image.svg'; @@ -19,10 +31,6 @@ import PlanDetails from './plan_details'; import './billing_subscriptions.scss'; import BillingSummary from './billing_summary'; -type Props = { - -}; - const upgradeMattermostCloud = () => (
@@ -77,21 +85,64 @@ const privateCloudCard = () => (
); +const WARNING_THRESHOLD = 3; + // TODO: temp const isFree = false; +type Props = { +}; + const BillingSubscriptions: React.FC = () => { + const {formatMessage} = useIntl(); const dispatch = useDispatch(); const store = useStore(); + const userLimit = useSelector((state: GlobalState) => parseInt(getConfig(state).ExperimentalCloudUserLimit!, 10)); + const analytics = useSelector((state: GlobalState) => state.entities.admin.analytics); + const currentUser = useSelector((state: GlobalState) => getCurrentUser(state)); + const isCloud = useSelector((state: GlobalState) => getLicense(state).Cloud === 'true'); + const subscription = useSelector((state: GlobalState) => state.entities.cloud.subscription); + const getCategory = makeGetCategory(); + const preferences = useSelector((state) => getCategory(state, Preferences.ADMIN_CLOUD_UPGRADE_PANEL)); useEffect(() => { getCloudSubscription()(dispatch, store.getState()); getCloudProducts()(dispatch, store.getState()); }, []); - const [showDanger, setShowDanger] = useState(true); - const [showWarning, setShowWarning] = useState(true); - const [showInfo, setShowInfo] = useState(true); + const [showDanger, setShowDanger] = useState(false); + const [showWarning, setShowWarning] = useState(false); + + useEffect(() => { + if (!analytics) { + (async function getAllAnalytics() { + await dispatch(getStandardAnalytics()); + }()); + } + }, []); + + const shouldShowInfoBanner = (): boolean => { + if (!analytics || !isCloud || !userLimit || !preferences || !subscription || subscription.is_paid_tier === 'true' || preferences.some((pref: PreferenceType) => pref.name === CloudBanners.HIDE && pref.value === 'true')) { + return false; + } + + if ((userLimit - Number(analytics.TOTAL_USERS)) <= WARNING_THRESHOLD && (userLimit - Number(analytics.TOTAL_USERS) >= 0)) { + return true; + } + + return false; + }; + + const handleHide = async () => { + dispatch(savePreferences(currentUser.id, [ + { + category: Preferences.ADMIN_CLOUD_UPGRADE_PANEL, + user_id: currentUser.id, + name: CloudBanners.HIDE, + value: 'true', + }, + ])); + }; return (
@@ -101,30 +152,37 @@ const BillingSubscriptions: React.FC = () => { />
- {showDanger && + {showDanger && ( setShowDanger(false)} /> - } - {showWarning && + )} + {showWarning && ( setShowWarning(false)} /> - } - {showInfo && + )} + {shouldShowInfoBanner() && ( setShowInfo(false)} + title={formatMessage({ + id: 'billing.subscription.info.headsup', + defaultMessage: 'Just a heads up', + })} + message={formatMessage({ + id: 'billing.subscription.info.headsup.description', + defaultMessage: + 'You’re nearing the user limit with the free tier of Mattermost Cloud. We’ll let you know if you hit that limit.', + })} + onDismiss={() => handleHide()} /> - } + )}