* Renamed user limit API to app limit API

* Added post warning limit

* Added tests

* Fixed types

* Renamed AppLimits to ServerLimits

* Fixed tests and review fixes

* Updated generated code

* Updated server i18n

* Fixed TestCreateUserOrGuest test

* Exclude deleted posts from post count for liims

* Reduced limits for ease of testing

* Restored original limts
Этот коммит содержится в:
Harshil Sharma
2024-04-18 11:50:30 +05:30
коммит произвёл GitHub
родитель 4571c6e3a3
Коммит b4a1b33d39
31 изменённых файлов: 448 добавлений и 153 удалений

Просмотреть файл

@@ -7,7 +7,7 @@ import type {Dispatch} from 'redux';
import {uploadLicense, removeLicense, getPrevTrialLicense} from 'mattermost-redux/actions/admin';
import {getLicenseConfig} from 'mattermost-redux/actions/general';
import {getUsersLimits} from 'mattermost-redux/actions/limits';
import {getServerLimits} from 'mattermost-redux/actions/limits';
import {getFilteredUsersStats} from 'mattermost-redux/actions/users';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getFilteredUsersStats as selectFilteredUserStats} from 'mattermost-redux/selectors/entities/users';
@@ -43,7 +43,7 @@ function mapDispatchToProps(dispatch: Dispatch) {
requestTrialLicense,
openModal,
getFilteredUsersStats,
getUsersLimits,
getServerLimits,
}, dispatch),
};
}

Просмотреть файл

@@ -54,7 +54,7 @@ describe('components/admin_console/license_settings/LicenseSettings', () => {
upgradeToE0Status: jest.fn().mockImplementation(() => Promise.resolve({percentage: 0, error: null})),
openModal: jest.fn(),
getFilteredUsersStats: jest.fn(),
getUsersLimits: jest.fn(),
getServerLimits: jest.fn(),
},
};

Просмотреть файл

@@ -7,7 +7,7 @@ import {FormattedMessage, defineMessages} from 'react-intl';
import type {StatusOK} from '@mattermost/types/client4';
import type {ClientLicense} from '@mattermost/types/config';
import type {ServerError} from '@mattermost/types/errors';
import type {UsersLimits} from '@mattermost/types/limits';
import type {ServerLimits} from '@mattermost/types/limits';
import type {GetFilteredUsersStatsOpts, UsersStats} from '@mattermost/types/users';
import type {ActionResult} from 'mattermost-redux/types/actions';
@@ -55,7 +55,7 @@ type Props = {
ping: () => Promise<{status: string}>;
requestTrialLicense: (users: number, termsAccepted: boolean, receiveEmailsAccepted: boolean, featureName: string) => Promise<ActionResult>;
openModal: <P>(modalData: ModalData<P>) => void;
getUsersLimits: () => Promise<ActionResult<UsersLimits, ServerError>>;
getServerLimits: () => Promise<ActionResult<ServerLimits, ServerError>>;
getFilteredUsersStats: (filters: GetFilteredUsersStatsOpts) => Promise<{
data?: UsersStats;
error?: ServerError;
@@ -196,7 +196,7 @@ export default class LicenseSettings extends React.PureComponent<Props, State> {
this.props.actions.getLicenseConfig(),
]);
await this.props.actions.getUsersLimits();
await this.props.actions.getServerLimits();
this.setState({serverError: null, removing: false});
};

Просмотреть файл

@@ -6,6 +6,7 @@ import React from 'react';
import type {ClientLicense, ClientConfig, WarnMetricStatus} from '@mattermost/types/config';
import {ToPaidPlanBannerDismissable} from 'components/admin_console/billing/billing_subscriptions/to_paid_plan_nudge_banner';
import PostLimitsAnnouncementBar from 'components/announcement_bar/post_limits_announcement_bar';
import withGetCloudSubscription from 'components/common/hocs/cloud/with_get_cloud_subscription';
import CloudAnnualRenewalAnnouncementBar from './cloud_annual_renewal';
@@ -98,10 +99,22 @@ class AnnouncementBarController extends React.PureComponent<Props> {
);
}
// The component specified further down takes priority over the component above it.
// For example, consider this-
// {
// Foo
// Bar
// Baz
// }
// Even if all Foo, Bar and Baz render, only Baz is visible as it's further down.
return (
<>
{adminConfiguredAnnouncementBar}
{errorBar}
<PostLimitsAnnouncementBar
license={this.props.license}
userIsAdmin={this.props.userIsAdmin}
/>
<UsersLimitsAnnouncementBar
license={this.props.license}
userIsAdmin={this.props.userIsAdmin}

Просмотреть файл

@@ -0,0 +1,90 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import type {
ShouldShowingPostLimitsAnnouncementBarProps} from 'components/announcement_bar/post_limits_announcement_bar/index';
import {shouldShowPostLimitsAnnouncementBar,
} from 'components/announcement_bar/post_limits_announcement_bar/index';
describe('shouldShowPostLimitsAnnouncementBar', () => {
const defaultProps: ShouldShowingPostLimitsAnnouncementBarProps = {
userIsAdmin: true,
isLicensed: false,
maxPostLimit: 10,
postCount: 5,
};
test('should not show when user is not admin', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
userIsAdmin: false,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(false);
});
test('should not show when post count is 0', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
postCount: 0,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(false);
});
test('should not show when max post limit is 0', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
maxPostLimit: 0,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(false);
});
test('should not show when post count is less than max users limit', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
maxPostLimit: 10,
postCount: 5,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(false);
});
test('should show when post count is equal to max post limit', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
maxPostLimit: 10,
postCount: 10,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(true);
});
test('should show for non licensed servers with post count is greater than max post limit', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
isLicensed: false,
maxPostLimit: 5,
postCount: 10,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(true);
});
test('should not show for licensed server', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
isLicensed: true,
maxPostLimit: 0,
postCount: 0,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(false);
});
test('should not show for licensed server even if post count is greater than max post limit', () => {
const props: ShouldShowingPostLimitsAnnouncementBarProps = {
...defaultProps,
isLicensed: true,
maxPostLimit: 10,
postCount: 11,
};
expect(shouldShowPostLimitsAnnouncementBar(props)).toBe(false);
});
});

Просмотреть файл

@@ -0,0 +1,86 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
import {FormattedMessage} from 'react-intl';
import {useSelector} from 'react-redux';
import {AlertOutlineIcon} from '@mattermost/compass-icons/components';
import type {ClientLicense} from '@mattermost/types/config';
import {getServerLimits} from 'mattermost-redux/selectors/entities/limits';
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
import {AnnouncementBarTypes} from 'utils/constants';
type Props = {
license?: ClientLicense;
userIsAdmin: boolean;
};
const learnMoreExternalLink = 'https://mattermost.com/pl/error-code-error-safety-limits-exceeded';
function PostLimitsAnnouncementBar(props: Props) {
const serverLimits = useSelector(getServerLimits);
const handleCTAClick = useCallback(() => {
window.open(learnMoreExternalLink, '_blank');
}, []);
const isLicensed = props?.license?.IsLicensed === 'true';
const maxPostLimit = serverLimits?.maxPostLimit ?? 0;
const postCount = serverLimits?.postCount ?? 0;
if (!shouldShowPostLimitsAnnouncementBar({userIsAdmin: props.userIsAdmin, isLicensed, maxPostLimit, postCount})) {
return null;
}
return (
<AnnouncementBar
id='post_limits_announcement_bar'
showCloseButton={false}
message={
<FormattedMessage
id='post_limits_announcement_bar.copyText'
defaultMessage='Message limits exceeded. Contact administrator with: {ErrorCode}'
values={{
ErrorCode: 'ERROR_SAFETY_LIMITS_EXCEEDED',
}}
/>
}
type={AnnouncementBarTypes.CRITICAL}
icon={<AlertOutlineIcon size={16}/>}
showCTA={true}
showLinkAsButton={true}
ctaText={
<FormattedMessage
id='users_limits_announcement_bar.ctaText'
defaultMessage='Learn More'
/>
}
onButtonClick={handleCTAClick}
/>
);
}
export type ShouldShowingPostLimitsAnnouncementBarProps = {
userIsAdmin: boolean;
isLicensed: boolean;
maxPostLimit: number;
postCount: number;
};
export function shouldShowPostLimitsAnnouncementBar({userIsAdmin, isLicensed, maxPostLimit, postCount}: ShouldShowingPostLimitsAnnouncementBarProps) {
if (!userIsAdmin) {
return false;
}
if (maxPostLimit === 0 || postCount === 0) {
return false;
}
return !isLicensed && postCount >= maxPostLimit;
}
export default PostLimitsAnnouncementBar;

Просмотреть файл

@@ -8,7 +8,7 @@ import {useSelector} from 'react-redux';
import {AlertOutlineIcon} from '@mattermost/compass-icons/components';
import type {ClientLicense} from '@mattermost/types/config';
import {getUsersLimits} from 'mattermost-redux/selectors/entities/limits';
import {getServerLimits} from 'mattermost-redux/selectors/entities/limits';
import AnnouncementBar from 'components/announcement_bar/default_announcement_bar';
@@ -22,15 +22,15 @@ type Props = {
const learnMoreExternalLink = 'https://mattermost.com/pl/error-code-error-safety-limits-exceeded';
function UsersLimitsAnnouncementBar(props: Props) {
const usersLimits = useSelector(getUsersLimits);
const serverLimits = useSelector(getServerLimits);
const handleCTAClick = useCallback(() => {
window.open(learnMoreExternalLink, '_blank');
}, []);
const isLicensed = props?.license?.IsLicensed === 'true';
const maxUsersLimit = usersLimits?.maxUsersLimit ?? 0;
const activeUserCount = usersLimits?.activeUserCount ?? 0;
const maxUsersLimit = serverLimits?.maxUsersLimit ?? 0;
const activeUserCount = serverLimits?.activeUserCount ?? 0;
if (!shouldShowUserLimitsAnnouncementBar({userIsAdmin: props.userIsAdmin, isLicensed, maxUsersLimit, activeUserCount})) {
return null;
@@ -43,7 +43,10 @@ function UsersLimitsAnnouncementBar(props: Props) {
message={
<FormattedMessage
id='users_limits_announcement_bar.copyText'
defaultMessage='User limits exceeded. Contact administrator with: ERROR_SAFETY_LIMITS_EXCEEDED'
defaultMessage='User limits exceeded. Contact administrator with: {ErrorCode}'
values={{
ErrorCode: 'ERROR_SAFETY_LIMITS_EXCEEDED',
}}
/>
}
type={AnnouncementBarTypes.CRITICAL}