[MM-51922] Enforce minimum 10 seats in seats selector (#22916)

* Enforce minimum 10 seats in seats selector

* Ensure initial value is validated as well

* Fix linter

* fix tests

* Add a test for 10 seat minimum

* Fix linter, merge master
Этот коммит содержится в:
Nick Misasi
2023-04-13 15:27:44 -04:00
коммит произвёл GitHub
родитель a7ce08da95
Коммит 55063b026b
5 изменённых файлов: 36 добавлений и 3 удалений

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

@@ -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, {useEffect} from 'react';
import {useIntl, FormattedMessage, FormattedNumber} from 'react-intl';
import {InformationOutlineIcon} from '@mattermost/compass-icons/components';
@@ -41,6 +41,12 @@ export const errorInvalidNumber = (
defaultMessage='Enter a valid number of seats'
/>
);
export const errorMinSeats = (
<FormattedMessage
id='cloud_upgrade.error_min_seats'
defaultMessage='Minimum of 10 seats required'
/>
);
function validateSeats(seats: string, annualPricePerSeat: number, minSeats: number, cloud: boolean): Seats {
if (seats === '') {
@@ -58,6 +64,13 @@ function validateSeats(seats: string, annualPricePerSeat: number, minSeats: numb
};
}
if (seatsNumber < 10) {
return {
quantity: seats,
error: errorMinSeats,
};
}
const maxSeats = calculateMaxUsers(annualPricePerSeat);
const tooFewUsersErrorMessage = (
<FormattedMessage
@@ -134,6 +147,10 @@ export default function SeatsCalculator(props: Props) {
props.onChange(validateSeats(value, annualPricePerSeat, props.existingUsers, props.isCloud));
};
useEffect(() => {
props.onChange(validateSeats(props.seats.quantity, annualPricePerSeat, props.existingUsers, props.isCloud));
}, []);
const maxSeats = calculateMaxUsers(annualPricePerSeat);
const total = '$' + intl.formatNumber((parseFloat(props.seats.quantity) || 0) * annualPricePerSeat, {maximumFractionDigits: 2});
const userCountTooltip = (

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

@@ -2,6 +2,10 @@
padding: 14px 0;
font-size: 14px;
.Input___customMessage.Input___error {
line-height: 14px;
}
&__seats-item {
position: relative;
display: flex;

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

@@ -69,7 +69,7 @@ const mockCreatedIntent = SelfHostedSignupProgress.CREATED_INTENT;
const mockCreatedLicense = SelfHostedSignupProgress.CREATED_LICENSE;
const failOrg = 'failorg';
const existingUsers = 10;
const existingUsers = 11;
jest.mock('mattermost-redux/client', () => {
const original = jest.requireActual('mattermost-redux/client');
@@ -275,7 +275,17 @@ describe('SelfHostedPurchaseModal', () => {
const tooFewSeats = existingUsers - 1;
fireEvent.change(screen.getByTestId('selfHostedPurchaseSeatsInput'), valueEvent(tooFewSeats.toString()));
expect(screen.getByText('Upgrade')).toBeDisabled();
screen.getByText('Your workspace currently has 10 users', {exact: false});
screen.getByText('Your workspace currently has 11 users', {exact: false});
});
it('Minimum of 10 seats is required for sign up', () => {
renderWithIntlAndStore(<div id='root-portal'><SelfHostedPurchaseModal productId={'prod_professional'}/></div>, initialState);
fillForm(defaultSuccessForm);
const tooFewSeats = 9;
fireEvent.change(screen.getByTestId('selfHostedPurchaseSeatsInput'), valueEvent(tooFewSeats.toString()));
expect(screen.getByText('Upgrade')).toBeDisabled();
screen.getByText('Minimum of 10 seats required', {exact: false});
});
it('happy path submit shows success screen', async () => {

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

@@ -3068,6 +3068,7 @@
"cloud_delinquency.post_downgrade_banner.title": "Update your billing information now to re-activate paid features.",
"cloud_signup.signup_consequences": "Your credit card will be charged today. <a>See how billing works.</a>",
"cloud_subscribe.contact_support": "Compare plans",
"cloud_upgrade.error_min_seats": "Minimum of 10 seats required",
"cloud.fetch_error": "Error fetching billing data. Please try again later.",
"cloud.fetch_error.retry": "Retry",
"cloud.invoice_pdf_preview.download": "<downloadLink>Download</downloadLink> this page for your records",

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

@@ -1983,6 +1983,7 @@ export const Constants = {
CHANNEL_HEADER_BUTTON_DISABLE_TIMEOUT: 1000,
FIRST_ADMIN_ROLE: 'first_admin',
MAX_PURCHASE_SEATS: 1000000,
MIN_PURCHASE_SEATS: 10,
};
export const ValidationErrors = {