diff --git a/actions/websocket_actions.jsx b/actions/websocket_actions.jsx index 8837af7b10fa..dbe192987031 100644 --- a/actions/websocket_actions.jsx +++ b/actions/websocket_actions.jsx @@ -72,7 +72,7 @@ import {loadProfilesForSidebar} from 'actions/user_actions.jsx'; import store from 'stores/redux_store.jsx'; import WebSocketClient from 'client/web_websocket_client.jsx'; import {loadPlugin, loadPluginsIfNecessary, removePlugin} from 'plugins'; -import {ActionTypes, Constants, AnnouncementBarMessages, SocketEvents, UserStatuses, ModalIdentifiers} from 'utils/constants'; +import {ActionTypes, Constants, AnnouncementBarMessages, SocketEvents, UserStatuses, ModalIdentifiers, WarnMetricTypes} from 'utils/constants'; import {getSiteURL} from 'utils/url'; import {isGuest} from 'utils/utils'; import RemovedFromChannelModal from 'components/removed_from_channel_modal'; @@ -1256,14 +1256,21 @@ function handleGroupNotAssociatedToChannelEvent(msg) { } function handleWarnMetricStatusReceivedEvent(msg) { + var receivedData = JSON.parse(msg.data.warnMetricStatus); + let bannerData; + if (receivedData.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500) { + bannerData = AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_USERS; + } else if (receivedData.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M) { + bannerData = AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_POSTS; + } store.dispatch(batchActions([ { type: GeneralTypes.WARN_METRIC_STATUS_RECEIVED, - data: JSON.parse(msg.data.warnMetricStatus), + data: receivedData, }, { type: ActionTypes.SHOW_NOTICE, - data: [AnnouncementBarMessages.NUMBER_OF_ACTIVE_USERS_WARN_METRIC_STATUS], + data: [bannerData], }, ])); } diff --git a/components/announcement_bar/configuration_bar/configuration_bar.jsx b/components/announcement_bar/configuration_bar/configuration_bar.jsx index 3ecf7a086daf..607b953fa4b2 100644 --- a/components/announcement_bar/configuration_bar/configuration_bar.jsx +++ b/components/announcement_bar/configuration_bar/configuration_bar.jsx @@ -33,6 +33,8 @@ class ConfigurationAnnouncementBar extends React.PureComponent { dismissedExpiringLicense: PropTypes.bool, dismissedNumberOfActiveUsersWarnMetricStatus: PropTypes.bool, dismissedNumberOfActiveUsersWarnMetricStatusAck: PropTypes.bool, + dismissedNumberOfPostsWarnMetricStatus: PropTypes.bool, + dismissedNumberOfPostsWarnMetricStatusAck: PropTypes.bool, siteURL: PropTypes.string.isRequired, warnMetricsStatus: PropTypes.object, actions: PropTypes.shape({ @@ -45,15 +47,25 @@ class ConfigurationAnnouncementBar extends React.PureComponent { } dismissNumberOfActiveUsersWarnMetric = () => { - this.props.actions.dismissNotice(AnnouncementBarMessages.NUMBER_OF_ACTIVE_USERS_WARN_METRIC_STATUS); + this.props.actions.dismissNotice(AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_USERS); + } + + dismissNumberOfPostsWarnMetric = () => { + this.props.actions.dismissNotice(AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_POSTS); } dismissNumberOfActiveUsersWarnMetricAck = () => { - this.props.actions.dismissNotice(AnnouncementBarMessages.NUMBER_OF_ACTIVE_USERS_WARN_METRIC_STATUS_ACK); + this.props.actions.dismissNotice(AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_USERS_ACK); + } + + dismissNumberOfPostsWarnMetricAck = () => { + this.props.actions.dismissNotice(AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_POSTS_ACK); } getNoticeForWarnMetric = (warnMetricStatus) => { - if (!warnMetricStatus) { + if (!warnMetricStatus || + (warnMetricStatus.id !== WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500 && + warnMetricStatus.id !== WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M)) { return null; } @@ -64,27 +76,51 @@ class ConfigurationAnnouncementBar extends React.PureComponent { var isDismissed = null; var canCloseBar = false; - switch (warnMetricStatus.id) { - case WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500: - if (warnMetricStatus.acked) { + if (warnMetricStatus.acked) { + message = ( + + + + + ); + + if (warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500) { + dismissFunc = this.dismissNumberOfActiveUsersWarnMetricAck; + isDismissed = this.props.dismissedNumberOfActiveUsersWarnMetricStatusAck; + } else if (warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M) { + dismissFunc = this.dismissNumberOfPostsWarnMetricAck; + isDismissed = this.props.dismissedNumberOfPostsWarnMetricStatusAck; + } + + type = AnnouncementBarTypes.ADVISOR_ACK; + showModal = false; + canCloseBar = true; + } else { + if (warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500) { message = ( ); - type = AnnouncementBarTypes.ADVISOR_ACK; - showModal = false; - dismissFunc = this.dismissNumberOfActiveUsersWarnMetricAck; - isDismissed = this.props.dismissedNumberOfActiveUsersWarnMetricStatusAck; - canCloseBar = true; - } else { + dismissFunc = this.dismissNumberOfActiveUsersWarnMetric; + isDismissed = this.props.dismissedNumberOfActiveUsersWarnMetricStatus; + } else if (warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M) { message = ( ); - type = AnnouncementBarTypes.ADVISOR; - showModal = true; - dismissFunc = this.dismissNumberOfActiveUsersWarnMetric; - isDismissed = this.props.dismissedNumberOfActiveUsersWarnMetricStatus; - canCloseBar = false; + dismissFunc = this.dismissNumberOfPostsWarnMetric; + isDismissed = this.props.dismissedNumberOfPostsWarnMetricStatus; } - return { - Message: message, - DismissFunc: dismissFunc, - IsDismissed: isDismissed, - Type: type, - ShowModal: showModal, - CanCloseBar: canCloseBar, - }; - default: - return null; + type = AnnouncementBarTypes.ADVISOR; + showModal = true; + canCloseBar = false; } + return { + Message: message, + DismissFunc: dismissFunc, + IsDismissed: isDismissed, + Type: type, + ShowModal: showModal, + CanCloseBar: canCloseBar, + }; } render() { @@ -176,7 +210,8 @@ class ConfigurationAnnouncementBar extends React.PureComponent { /> ); } - if (this.props.license.IsLicensed === 'false' && this.props.warnMetricsStatus) { + if (this.props.license?.IsLicensed === 'false' && + this.props.warnMetricsStatus) { for (const status of Object.values(this.props.warnMetricsStatus)) { var notice = this.getNoticeForWarnMetric(status); if (!notice || notice.IsDismissed) { @@ -190,7 +225,7 @@ class ConfigurationAnnouncementBar extends React.PureComponent { type={notice.Type} showModal={notice.ShowModal} modalButtonText={t('announcement_bar.error.warn_metric_status.link')} - modalButtonDefaultText={'Learn More'} + modalButtonDefaultText='Learn more' warnMetricStatus={status} message={notice.Message} /> diff --git a/components/announcement_bar/configuration_bar/index.js b/components/announcement_bar/configuration_bar/index.js index 3c0bc7b3defd..f93c415132d4 100644 --- a/components/announcement_bar/configuration_bar/index.js +++ b/components/announcement_bar/configuration_bar/index.js @@ -14,8 +14,10 @@ function mapStateToProps(state) { return { siteURL: getSiteURL(state), dismissedExpiringLicense: Boolean(state.views.notice.hasBeenDismissed[AnnouncementBarMessages.LICENSE_EXPIRING]), - dismissedNumberOfActiveUsersWarnMetricStatus: Boolean(state.views.notice.hasBeenDismissed[AnnouncementBarMessages.NUMBER_OF_ACTIVE_USERS_WARN_METRIC_STATUS]), - dismissedNumberOfActiveUsersWarnMetricStatusAck: Boolean(state.views.notice.hasBeenDismissed[AnnouncementBarMessages.NUMBER_OF_ACTIVE_USERS_WARN_METRIC_STATUS_ACK]), + dismissedNumberOfActiveUsersWarnMetricStatus: Boolean(state.views.notice.hasBeenDismissed[AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_USERS]), + dismissedNumberOfActiveUsersWarnMetricStatusAck: Boolean(state.views.notice.hasBeenDismissed[AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_USERS_ACK]), + dismissedNumberOfPostsWarnMetricStatus: Boolean(state.views.notice.hasBeenDismissed[AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_POSTS]), + dismissedNumberOfPostsWarnMetricStatusAck: Boolean(state.views.notice.hasBeenDismissed[AnnouncementBarMessages.WARN_METRIC_STATUS_NUMBER_OF_POSTS_ACK]), }; } diff --git a/components/warn_metric_ack_modal/__snapshots__/warn_metric_ack_modal.test.tsx.snap b/components/warn_metric_ack_modal/__snapshots__/warn_metric_ack_modal.test.tsx.snap index 47b3b637974a..63b00defab97 100644 --- a/components/warn_metric_ack_modal/__snapshots__/warn_metric_ack_modal.test.tsx.snap +++ b/components/warn_metric_ack_modal/__snapshots__/warn_metric_ack_modal.test.tsx.snap @@ -39,27 +39,13 @@ exports[`components/WarnMetricAckModal error display 1`] = ` bsClass="modal-title" componentClass="h1" id="warnMetricAckHeaderModalLabel" - > - - + />
-
, } } @@ -97,12 +83,12 @@ exports[`components/WarnMetricAckModal error display 1`] = ` } > , @@ -176,27 +162,13 @@ exports[`components/WarnMetricAckModal should match snapshot, init 1`] = ` bsClass="modal-title" componentClass="h1" id="warnMetricAckHeaderModalLabel" - > - - + />
-

, diff --git a/components/warn_metric_ack_modal/index.ts b/components/warn_metric_ack_modal/index.ts index 2c614a2d199a..3050bc1c8b85 100644 --- a/components/warn_metric_ack_modal/index.ts +++ b/components/warn_metric_ack_modal/index.ts @@ -9,7 +9,7 @@ import {ActionFunc} from 'mattermost-redux/types/actions'; import {getStandardAnalytics, sendWarnMetricAck} from 'mattermost-redux/actions/admin'; import {getCurrentUser} from 'mattermost-redux/selectors/entities/common'; -import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general'; +import {getConfig} from 'mattermost-redux/selectors/entities/general'; import {closeModal} from 'actions/views/modals'; @@ -28,7 +28,6 @@ function mapStateToProps(state: GlobalState, ownProps: Props) { return { stats: state.entities.admin.analytics, user: getCurrentUser(state), - license: getLicense(state), diagnosticId: config.DiagnosticId, show: isModalOpen(state, ModalIdentifiers.WARN_METRIC_ACK), closeParentComponent: ownProps.closeParentComponent, diff --git a/components/warn_metric_ack_modal/warn_metric_ack_modal.test.tsx b/components/warn_metric_ack_modal/warn_metric_ack_modal.test.tsx index b631b5d6beba..ddb301eb863f 100644 --- a/components/warn_metric_ack_modal/warn_metric_ack_modal.test.tsx +++ b/components/warn_metric_ack_modal/warn_metric_ack_modal.test.tsx @@ -82,13 +82,15 @@ describe('components/WarnMetricAckModal', () => { }); test('send ack on acknowledge button click', () => { + const props = {...baseProps}; + const wrapper = shallow( - , + , ); wrapper.setState({saving: false}); wrapper.find('.save-button').simulate('click'); - expect(baseProps.actions.sendWarnMetricAck).toHaveBeenCalledTimes(1); + expect(props.actions.sendWarnMetricAck).toHaveBeenCalledTimes(1); }); test('should have called props.onHide when Modal.onExited is called', () => { diff --git a/components/warn_metric_ack_modal/warn_metric_ack_modal.tsx b/components/warn_metric_ack_modal/warn_metric_ack_modal.tsx index 0d2444d31c52..2efd7e62496a 100644 --- a/components/warn_metric_ack_modal/warn_metric_ack_modal.tsx +++ b/components/warn_metric_ack_modal/warn_metric_ack_modal.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react'; +import React, {CSSProperties} from 'react'; import {Modal} from 'react-bootstrap'; import {FormattedMessage} from 'react-intl'; @@ -11,8 +11,8 @@ import {AnalyticsRow} from 'mattermost-redux/types/admin'; import {ActionFunc} from 'mattermost-redux/types/actions'; import {getSiteURL} from 'utils/url'; -import {Constants, ModalIdentifiers} from 'utils/constants'; import {t} from 'utils/i18n'; +import {Constants, ModalIdentifiers, WarnMetricTypes} from 'utils/constants'; import {trackEvent} from 'actions/diagnostics_actions'; import * as AdminActions from 'actions/admin_actions.jsx'; @@ -26,7 +26,6 @@ import ErrorLink from 'components/error_page/error_link'; type Props = { user: UserProfile; - license?: Record; diagnosticId?: string; show: boolean; closeParentComponent?: () => Promise; @@ -41,15 +40,25 @@ type Props = { type State = { serverError: string | null; + gettingTrial: boolean; + gettingTrialError: string | null; saving: boolean; } +const containerStyles: CSSProperties = { + display: 'flex', + opacity: '0.56', + flexWrap: 'wrap', +}; + export default class WarnMetricAckModal extends React.PureComponent { public constructor(props: Props) { super(props); this.state = { saving: false, serverError: null, + gettingTrial: false, + gettingTrialError: null, }; } @@ -82,13 +91,15 @@ export default class WarnMetricAckModal extends React.PureComponent { this.setState({serverError: null, saving: false}); + + this.setState({gettingTrialError: null, gettingTrial: false}); this.props.actions.closeModal(ModalIdentifiers.WARN_METRIC_ACK); if (this.props.closeParentComponent) { this.props.closeParentComponent(); } } - renderError = () => { + renderContactUsError = () => { const {serverError} = this.state; if (!serverError) { return ''; @@ -96,7 +107,13 @@ export default class WarnMetricAckModal extends React.PureComponent ), @@ -142,37 +159,62 @@ export default class WarnMetricAckModal extends React.PureComponent - ); - const descriptionText = ( - - ); + let headerTitle; + if (this.props.warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500) { + headerTitle = ( + + ); + } else if (this.props.warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M) { + headerTitle = ( + + ); + } + let descriptionText; const learnMoreLink = 'https://mattermost.com/pl/default-admin-advisory'; + + if (this.props.warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500) { + descriptionText = ( + + ); + } else if (this.props.warnMetricStatus.id === WarnMetricTypes.SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M) { + descriptionText = ( + + ); + } + const subText = (
), }} @@ -180,11 +222,27 @@ export default class WarnMetricAckModal extends React.PureComponent ); - const buttonText = ( - + const error = this.renderContactUsError(); + const footer = ( + + + ); return ( @@ -209,27 +267,12 @@ export default class WarnMetricAckModal extends React.PureComponent {descriptionText}
- {this.renderError()} + {error}
{subText}
- - - + {footer} ); } diff --git a/i18n/en.json b/i18n/en.json index 6a8f2e470e78..d141c2acbfa1 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1976,14 +1976,19 @@ "announcement_bar.error.email_verification_required": "Check your email inbox to verify the address.", "announcement_bar.error.license_expired": "Enterprise license is expired and some features may be disabled. [Please renew](!{link}).", "announcement_bar.error.license_expiring": "Enterprise license expires on {date, date, long}. [Please renew](!{link}).", - "announcement_bar.error.number_active_users_warn_metric_status_ack.text": "Thank you for contacting Mattermost. We will follow up with you soon.", - "announcement_bar.error.number_active_users_warn_metric_status.text": "You now have over {limit} users. We strongly recommend using advanced features for large-scale servers.", "announcement_bar.error.past_grace": "Enterprise license is expired and some features may be disabled. Please contact your System Administrator for details.", "announcement_bar.error.preview_mode": "Preview Mode: Email notifications have not been configured.", "announcement_bar.error.site_url_gitlab.full": "Please configure your [site URL](https://docs.mattermost.com/administration/config-settings.html#site-url) either on the [System Console](/admin_console/environment/web_server) or, if you're using GitLab Mattermost, in gitlab.rb.", "announcement_bar.error.site_url.full": "Please configure your [site URL](https://docs.mattermost.com/administration/config-settings.html#site-url) on the [System Console](/admin_console/environment/web_server).", "announcement_bar.error.warn_metric_status.link": "Learn more", "announcement_bar.notification.email_verified": "Email verified", + "announcement_bar.number_active_users_warn_metric_status.text": "You now have over {limit} users. We strongly recommend using advanced features for large-scale servers.", + "announcement_bar.number_of_posts_warn_metric_status.text": "You now have over {limit} posts. We strongly advise using advanced features to avoid degraded performance.", + "announcement_bar.warn_metric_status_ack.text": "Thank you for contacting Mattermost. We will follow up with you soon.", + "announcement_bar.warn_metric_status.number_of_posts_ack.text": "Thank you for contacting Mattermost. We will follow up with you soon.", + "announcement_bar.warn_metric_status.number_of_posts.text": "You now have over 2,000,000 posts. We strongly advise using advanced features to avoid degraded performance.", + "announcement_bar.warn_metric_status.number_of_users_ack.text": "Thank you for contacting Mattermost. We will follow up with you soon.", + "announcement_bar.warn_metric_status.number_of_users.text": "You now have over 500 users. We strongly recommend using advanced features for large-scale servers.", "api.channel.add_guest.added": "{addedUsername} added to the channel as a guest by {username}.", "api.channel.add_member.added": "{addedUsername} added to the channel by {username}.", "api.channel.delete_channel.archived": "{username} archived the channel.", @@ -4127,12 +4132,14 @@ "view_image_popover.publicLink": "Get a public link", "view_image.loading": "Loading ", "warn_metric_ack_modal.contact_support": "Acknowledge", - "warn_metric_ack_modal.header.title": "Scaling with Mattermost", "warn_metric_ack_modal.learn_more.link": "Learn more", "warn_metric_ack_modal.mailto.link": "email us", "warn_metric_ack_modal.mailto.message": "Support could not be reached. Please {link}.", "warn_metric_ack_modal.number_of_active_users.description": "Mattermost strongly recommends that deployments of over {limit} users take advantage of features such as user management, server clustering and performance monitoring. Contact us to learn more and let us know how we can help.", - "warn_metric_ack_modal.number_of_active_users.subtext": "By clicking Acknowledge, you will be sharing your information with Mattermost Inc., to learn more about upgrading. {link}", + "warn_metric_ack_modal.number_of_posts.description": "Your Mattermost system has a large number of messages. The default Mattermost database search starts to show performance degradation at around 2.5 million posts. With over 5 million posts, Elasticsearch can help avoid significant performance issues, such as timeouts, with search and at-mentions. Contact us to learn more and let us know how we can help.", + "warn_metric_ack_modal.number_of_posts.header.title": "Improve Performance", + "warn_metric_ack_modal.number_of_users.header.title": "Scaling with Mattermost", + "warn_metric_ack_modal.subtext": "By clicking Acknowledge, you will be sharing your information with Mattermost Inc. {link}", "web.footer.about": "About", "web.footer.help": "Help", "web.footer.privacy": "Privacy", diff --git a/utils/constants.jsx b/utils/constants.jsx index 18c32d07ed6b..29542a785180 100644 --- a/utils/constants.jsx +++ b/utils/constants.jsx @@ -219,9 +219,15 @@ export const PostRequestTypes = keyMirror({ }); export const WarnMetricTypes = { + SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_100: 'warn_metric_number_of_active_users_100', SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_200: 'warn_metric_number_of_active_users_200', - SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_400: 'warn_metric_number_of_active_users_400', + SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_300: 'warn_metric_number_of_active_users_300', SYSTEM_WARN_METRIC_NUMBER_OF_ACTIVE_USERS_500: 'warn_metric_number_of_active_users_500', + SYSTEM_WARN_METRIC_NUMBER_OF_TEAMS_5: 'warn_metric_number_of_teams_5', + SYSTEM_WARN_METRIC_NUMBER_OF_CHANNELS_5: 'warn_metric_number_of_channels_50', + SYSTEM_WARN_METRIC_MFA: 'warn_metric_mfa', + SYSTEM_WARN_METRIC_EMAIL_DOMAIN: 'warn_metric_email_domain', + SYSTEM_WARN_METRIC_NUMBER_OF_POSTS_2M: 'warn_metric_number_of_posts_2M', }; export const ModalIdentifiers = { @@ -560,8 +566,10 @@ export const AnnouncementBarMessages = { LICENSE_PAST_GRACE: t('announcement_bar.error.past_grace'), PREVIEW_MODE: t('announcement_bar.error.preview_mode'), WEBSOCKET_PORT_ERROR: t('channel_loader.socketError'), - NUMBER_OF_ACTIVE_USERS_WARN_METRIC_STATUS: t('announcement_bar.error.number_active_users_warn_metric_status.text'), - NUMBER_OF_ACTIVE_USERS_WARN_METRIC_STATUS_ACK: t('announcement_bar.error.number_active_users_warn_metric_status_ack.text'), + WARN_METRIC_STATUS_NUMBER_OF_USERS: t('announcement_bar.warn_metric_status.number_of_users.text'), + WARN_METRIC_STATUS_NUMBER_OF_USERS_ACK: t('announcement_bar.warn_metric_status.number_of_users_ack.text'), + WARN_METRIC_STATUS_NUMBER_OF_POSTS: t('announcement_bar.warn_metric_status.number_of_posts.text'), + WARN_METRIC_STATUS_NUMBER_OF_POSTS_ACK: t('announcement_bar.warn_metric_status.number_of_posts_ack.text'), }; export const VerifyEmailErrors = {