diff --git a/webapp/channels/src/components/seats_calculator/index.tsx b/webapp/channels/src/components/seats_calculator/index.tsx
index fe2b9259a2..a38d09b70d 100644
--- a/webapp/channels/src/components/seats_calculator/index.tsx
+++ b/webapp/channels/src/components/seats_calculator/index.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, {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 = (
+
+);
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 = (
{
+ 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 = (
diff --git a/webapp/channels/src/components/seats_calculator/seats_calculator.scss b/webapp/channels/src/components/seats_calculator/seats_calculator.scss
index 18dd6699a6..80add6f083 100644
--- a/webapp/channels/src/components/seats_calculator/seats_calculator.scss
+++ b/webapp/channels/src/components/seats_calculator/seats_calculator.scss
@@ -2,6 +2,10 @@
padding: 14px 0;
font-size: 14px;
+ .Input___customMessage.Input___error {
+ line-height: 14px;
+ }
+
&__seats-item {
position: relative;
display: flex;
diff --git a/webapp/channels/src/components/self_hosted_purchase_modal/index.test.tsx b/webapp/channels/src/components/self_hosted_purchase_modal/index.test.tsx
index 81437b3d7a..c8d568206b 100644
--- a/webapp/channels/src/components/self_hosted_purchase_modal/index.test.tsx
+++ b/webapp/channels/src/components/self_hosted_purchase_modal/index.test.tsx
@@ -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(
, 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 () => {
diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json
index 269e9af208..3434e71dd2 100644
--- a/webapp/channels/src/i18n/en.json
+++ b/webapp/channels/src/i18n/en.json
@@ -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. See how billing works.",
"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": "Download this page for your records",
diff --git a/webapp/channels/src/utils/constants.tsx b/webapp/channels/src/utils/constants.tsx
index 091eb5aff6..87fc6be03a 100644
--- a/webapp/channels/src/utils/constants.tsx
+++ b/webapp/channels/src/utils/constants.tsx
@@ -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 = {