Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Automated cherry pick of #6679 #6744

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion components/admin_console/admin_definition.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
94 changes: 76 additions & 18 deletions components/admin_console/billing/billing_subscriptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -19,10 +31,6 @@ import PlanDetails from './plan_details';
import './billing_subscriptions.scss';
import BillingSummary from './billing_summary';

type Props = {

};

const upgradeMattermostCloud = () => (
<div className='UpgradeMattermostCloud'>
<div className='UpgradeMattermostCloud__image'>
Expand Down Expand Up @@ -77,21 +85,64 @@ const privateCloudCard = () => (
</div>
);

const WARNING_THRESHOLD = 3;

// TODO: temp
const isFree = false;

type Props = {
};

const BillingSubscriptions: React.FC<Props> = () => {
const {formatMessage} = useIntl();
const dispatch = useDispatch<DispatchFunc>();
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<GlobalState, PreferenceType[]>((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 (
<div className='wrapper--fixed BillingSubscriptions'>
Expand All @@ -101,30 +152,37 @@ const BillingSubscriptions: React.FC<Props> = () => {
/>
<div className='admin-console__wrapper'>
<div className='admin-console__content'>
{showDanger &&
{showDanger && (
<AlertBanner
mode='danger'
title='Test Danger Title'
message='This is a test danger message'
onDismiss={() => setShowDanger(false)}
/>
}
{showWarning &&
)}
{showWarning && (
<AlertBanner
mode='warning'
title='Test Warning Title'
message='This is a test warning message'
onDismiss={() => setShowWarning(false)}
/>
}
{showInfo &&
)}
{shouldShowInfoBanner() && (
<AlertBanner
mode='info'
title='Test Info Title'
message='This is a test info message'
onDismiss={() => 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()}
/>
}
)}
<div
className='BillingSubscriptions__topWrapper'
style={{marginTop: '20px'}}
Expand Down
2 changes: 2 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2142,6 +2142,8 @@
"backstage_sidebar.integrations.incoming_webhooks": "Incoming Webhooks",
"backstage_sidebar.integrations.oauthApps": "OAuth 2.0 Applications",
"backstage_sidebar.integrations.outgoing_webhooks": "Outgoing Webhooks",
"billing.subscription.info.headsup": "Just a heads up",
"billing.subscription.info.headsup.description": "You’re nearing the user limit with the free tier of Mattermost Cloud. We’ll let you know if you hit that limit.",
"bot.add.description": "Description",
"bot.add.description.help": "(Optional) Let others know what this bot does.",
"bot.add.display_name.help": "(Optional) You can choose to display your bot's full name rather than its username.",
Expand Down
1 change: 1 addition & 0 deletions utils/constants.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const Preferences = {
TEAMS_ORDER: 'teams_order',
RECOMMENDED_NEXT_STEPS: 'recommended_next_steps',
CLOUD_UPGRADE_BANNER: 'cloud_upgrade_banner',
ADMIN_CLOUD_UPGRADE_PANEL: 'admin_cloud_upgrade_panel',
};

export const ActionTypes = keyMirror({
Expand Down