update overage banner/message in invite modal to direct to the self hosted expansion modal if self hosted expansion is available.
Этот коммит содержится в:
@@ -65,9 +65,8 @@ const EnterpriseEditionLeftPanel = ({
|
|||||||
const actionQueryParam = query.get('action');
|
const actionQueryParam = query.get('action');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (actionQueryParam === 'show_expansion_modal' && canExpand && isSelfHostedExpansionEnabled) {
|
if (actionQueryParam === 'show_expansion_modal') {
|
||||||
selfHostedExpansionModal.open();
|
selfHostedExpansionModal.open();
|
||||||
query.set('action', '');
|
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -100,7 +99,7 @@ const EnterpriseEditionLeftPanel = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleClickAddSeats = () => {
|
const handleClickAddSeats = () => {
|
||||||
if (!isSelfHostedExpansionEnabled && !canExpand) {
|
if (!isSelfHostedExpansionEnabled || !canExpand) {
|
||||||
window.open(expandableLink(unsanitizedLicense.Id), '_blank');
|
window.open(expandableLink(unsanitizedLicense.Id), '_blank');
|
||||||
} else {
|
} else {
|
||||||
selfHostedExpansionModal.open();
|
selfHostedExpansionModal.open();
|
||||||
|
|||||||
@@ -16,9 +16,11 @@ import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
|||||||
import {PreferenceType} from '@mattermost/types/preferences';
|
import {PreferenceType} from '@mattermost/types/preferences';
|
||||||
import {useExpandOverageUsersCheck} from 'components/common/hooks/useExpandOverageUsersCheck';
|
import {useExpandOverageUsersCheck} from 'components/common/hooks/useExpandOverageUsersCheck';
|
||||||
import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink';
|
import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink';
|
||||||
import {StatTypes, Preferences, AnnouncementBarTypes} from 'utils/constants';
|
import {StatTypes, Preferences, AnnouncementBarTypes, ConsolePages} from 'utils/constants';
|
||||||
|
|
||||||
import './overage_users_banner.scss';
|
import './overage_users_banner.scss';
|
||||||
|
import {getSiteURL} from 'utils/url';
|
||||||
|
import useCanSelfHostedExpand from 'components/common/hooks/useCanSelfHostedExpand';
|
||||||
|
|
||||||
type AdminHasDismissedItArgs = {
|
type AdminHasDismissedItArgs = {
|
||||||
preferenceName: string;
|
preferenceName: string;
|
||||||
@@ -53,10 +55,13 @@ const OverageUsersBanner = () => {
|
|||||||
activeUsers,
|
activeUsers,
|
||||||
seatsPurchased,
|
seatsPurchased,
|
||||||
});
|
});
|
||||||
|
const canSelfHostedExpand = useCanSelfHostedExpand();
|
||||||
|
const siteURL = getSiteURL();
|
||||||
const prefixPreferences = isOver10PercerntPurchasedSeats ? 'error' : 'warn';
|
const prefixPreferences = isOver10PercerntPurchasedSeats ? 'error' : 'warn';
|
||||||
const prefixLicenseId = (license.Id || '').substring(0, 8);
|
const prefixLicenseId = (license.Id || '').substring(0, 8);
|
||||||
const preferenceName = `${prefixPreferences}_overage_seats_${prefixLicenseId}`;
|
const preferenceName = `${prefixPreferences}_overage_seats_${prefixLicenseId}`;
|
||||||
|
|
||||||
|
|
||||||
const overageByUsers = activeUsers - seatsPurchased;
|
const overageByUsers = activeUsers - seatsPurchased;
|
||||||
|
|
||||||
const isOverageState = isBetween5PercerntAnd10PercentPurchasedSeats || isOver10PercerntPurchasedSeats;
|
const isOverageState = isBetween5PercerntAnd10PercentPurchasedSeats || isOver10PercerntPurchasedSeats;
|
||||||
@@ -86,6 +91,12 @@ const OverageUsersBanner = () => {
|
|||||||
const handleUpdateSeatsSelfServeClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
const handleUpdateSeatsSelfServeClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
trackEventFn('Self Serve');
|
trackEventFn('Self Serve');
|
||||||
|
|
||||||
|
if (canSelfHostedExpand) {
|
||||||
|
window.open(`${siteURL}/${ConsolePages.LICENSE}?action=show_expansion_modal`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
window.open(expandableLink(license.Id), '_blank');
|
window.open(expandableLink(license.Id), '_blank');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,7 +112,8 @@ const OverageUsersBanner = () => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = (
|
|
||||||
|
let message = (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='licensingPage.overageUsersBanner.text'
|
id='licensingPage.overageUsersBanner.text'
|
||||||
defaultMessage='Your workspace user count has exceeded your paid license seat count by {seats, number} {seats, plural, one {seat} other {seats}}. Purchase additional seats to remain compliant.'
|
defaultMessage='Your workspace user count has exceeded your paid license seat count by {seats, number} {seats, plural, one {seat} other {seats}}. Purchase additional seats to remain compliant.'
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {fireEvent, screen} from '@testing-library/react';
|
|||||||
import {DeepPartial} from '@mattermost/types/utilities';
|
import {DeepPartial} from '@mattermost/types/utilities';
|
||||||
import {GlobalState} from 'types/store';
|
import {GlobalState} from 'types/store';
|
||||||
import {General} from 'mattermost-redux/constants';
|
import {General} from 'mattermost-redux/constants';
|
||||||
import {OverActiveUserLimits, Preferences, StatTypes} from 'utils/constants';
|
import {OverActiveUserLimits, Preferences, SelfHostedProducts, StatTypes} from 'utils/constants';
|
||||||
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
|
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
|
||||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||||
import {trackEvent} from 'actions/telemetry_actions';
|
import {trackEvent} from 'actions/telemetry_actions';
|
||||||
@@ -107,6 +107,21 @@ describe('components/overage_users_banner', () => {
|
|||||||
getRequestState: 'IDLE',
|
getRequestState: 'IDLE',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
hostedCustomer: {
|
||||||
|
products: {
|
||||||
|
productsLoaded: true,
|
||||||
|
products: {
|
||||||
|
prod_professional: TestHelper.getProductMock({
|
||||||
|
id: 'prod_professional',
|
||||||
|
name: 'Professional',
|
||||||
|
sku: SelfHostedProducts.PROFESSIONAL,
|
||||||
|
price_per_seat: 7.5,
|
||||||
|
|
||||||
|
}),
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {findSelfHostedProductBySku} from 'utils/hosted_customer';
|
|||||||
import useGetSelfHostedProducts from './useGetSelfHostedProducts';
|
import useGetSelfHostedProducts from './useGetSelfHostedProducts';
|
||||||
|
|
||||||
export default function useCanSelfHostedExpand() {
|
export default function useCanSelfHostedExpand() {
|
||||||
// NOTE: This is a basic implementation to get things up and running, more details to come later.
|
|
||||||
const [expansionAvailable, setExpansionAvailable] = useState(false);
|
const [expansionAvailable, setExpansionAvailable] = useState(false);
|
||||||
const config = useSelector(getConfig);
|
const config = useSelector(getConfig);
|
||||||
const isEnterpriseReady = config.BuildEnterpriseReady === 'true';
|
const isEnterpriseReady = config.BuildEnterpriseReady === 'true';
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ interface HookOptions{
|
|||||||
export default function useControlSelfHostedExpansionModal(options: HookOptions): ControlModal {
|
export default function useControlSelfHostedExpansionModal(options: HookOptions): ControlModal {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const currentUser = useSelector(getCurrentUser);
|
const currentUser = useSelector(getCurrentUser);
|
||||||
const canExpand = useCanSelfHostedExpand();
|
|
||||||
const controlModal = useControlModal({
|
const controlModal = useControlModal({
|
||||||
modalId: ModalIdentifiers.SELF_HOSTED_EXPANSION,
|
modalId: ModalIdentifiers.SELF_HOSTED_EXPANSION,
|
||||||
dialogType: SelfHostedExpansionModal,
|
dialogType: SelfHostedExpansionModal,
|
||||||
@@ -35,9 +34,6 @@ export default function useControlSelfHostedExpansionModal(options: HookOptions)
|
|||||||
return {
|
return {
|
||||||
...controlModal,
|
...controlModal,
|
||||||
open: async () => {
|
open: async () => {
|
||||||
if (!canExpand) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const purchaseInProgress = localStorage.getItem(STORAGE_KEY_EXPANSION_IN_PROGRESS) === 'true';
|
const purchaseInProgress = localStorage.getItem(STORAGE_KEY_EXPANSION_IN_PROGRESS) === 'true';
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import ResultView from './result_view';
|
|||||||
import InviteView from './invite_view';
|
import InviteView from './invite_view';
|
||||||
import NoPermissionsView from './no_permissions_view';
|
import NoPermissionsView from './no_permissions_view';
|
||||||
import InvitationModal, {Props, View, InvitationModal as BaseInvitationModal} from './invitation_modal';
|
import InvitationModal, {Props, View, InvitationModal as BaseInvitationModal} from './invitation_modal';
|
||||||
|
import {SelfHostedProducts} from 'utils/constants';
|
||||||
|
import {TestHelper} from 'utils/test_helper';
|
||||||
|
|
||||||
const defaultProps: Props = deepFreeze({
|
const defaultProps: Props = deepFreeze({
|
||||||
actions: {
|
actions: {
|
||||||
@@ -87,6 +89,19 @@ describe('InvitationModal', () => {
|
|||||||
preferences: {
|
preferences: {
|
||||||
myPreferences: {},
|
myPreferences: {},
|
||||||
},
|
},
|
||||||
|
hostedCustomer: {
|
||||||
|
products: {
|
||||||
|
productsLoaded: true,
|
||||||
|
products: {
|
||||||
|
prod_professional: TestHelper.getProductMock({
|
||||||
|
id: 'prod_professional',
|
||||||
|
name: 'Professional',
|
||||||
|
sku: SelfHostedProducts.PROFESSIONAL,
|
||||||
|
price_per_seat: 7.5,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ import {mountWithThemedIntl} from 'tests/helpers/themed-intl-test-helper';
|
|||||||
import deepFreeze from 'mattermost-redux/utils/deep_freeze';
|
import deepFreeze from 'mattermost-redux/utils/deep_freeze';
|
||||||
import {Team} from '@mattermost/types/teams';
|
import {Team} from '@mattermost/types/teams';
|
||||||
import {generateId} from 'utils/utils';
|
import {generateId} from 'utils/utils';
|
||||||
|
import {TestHelper as TH} from 'utils/test_helper';
|
||||||
|
|
||||||
import InviteAs, {InviteType} from './invite_as';
|
import InviteAs, {InviteType} from './invite_as';
|
||||||
import InviteView, {Props} from './invite_view';
|
import InviteView, {Props} from './invite_view';
|
||||||
|
import {SelfHostedProducts} from 'utils/constants';
|
||||||
|
import {act} from 'react-dom/test-utils';
|
||||||
|
|
||||||
const defaultProps: Props = deepFreeze({
|
const defaultProps: Props = deepFreeze({
|
||||||
setInviteAs: jest.fn(),
|
setInviteAs: jest.fn(),
|
||||||
@@ -99,6 +102,19 @@ describe('InviteView', () => {
|
|||||||
preferences: {
|
preferences: {
|
||||||
myPreferences: {},
|
myPreferences: {},
|
||||||
},
|
},
|
||||||
|
hostedCustomer: {
|
||||||
|
products: {
|
||||||
|
productsLoaded: true,
|
||||||
|
products: {
|
||||||
|
prod_professional: TH.getProductMock({
|
||||||
|
id: 'prod_professional',
|
||||||
|
name: 'Professional',
|
||||||
|
sku: SelfHostedProducts.PROFESSIONAL,
|
||||||
|
price_per_seat: 7.5,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -108,40 +124,46 @@ describe('InviteView', () => {
|
|||||||
props = defaultProps;
|
props = defaultProps;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows InviteAs component when user can choose to invite guests or users', () => {
|
it('shows InviteAs component when user can choose to invite guests or users', async () => {
|
||||||
const wrapper = mountWithThemedIntl(
|
await act(async () => {
|
||||||
<Provider store={store}>
|
const wrapper = mountWithThemedIntl(
|
||||||
<InviteView {...props}/>
|
<Provider store={store}>
|
||||||
</Provider>,
|
<InviteView {...props}/>
|
||||||
);
|
</Provider>,
|
||||||
expect(wrapper.find(InviteAs).length).toBe(1);
|
);
|
||||||
|
expect(wrapper.find(InviteAs).length).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('hides InviteAs component when user can not choose members option', () => {
|
it('hides InviteAs component when user can not choose members option', async () => {
|
||||||
props = {
|
props = {
|
||||||
...defaultProps,
|
...defaultProps,
|
||||||
canAddUsers: false,
|
canAddUsers: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mountWithThemedIntl(
|
await act(async () => {
|
||||||
<Provider store={store}>
|
const wrapper = mountWithThemedIntl(
|
||||||
<InviteView {...props}/>
|
<Provider store={store}>
|
||||||
</Provider>,
|
<InviteView {...props}/>
|
||||||
);
|
</Provider>,
|
||||||
expect(wrapper.find(InviteAs).length).toBe(0);
|
);
|
||||||
|
expect(wrapper.find(InviteAs).length).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('hides InviteAs component when user can not choose guests option', () => {
|
it('hides InviteAs component when user can not choose guests option', async () => {
|
||||||
props = {
|
props = {
|
||||||
...defaultProps,
|
...defaultProps,
|
||||||
canInviteGuests: false,
|
canInviteGuests: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = mountWithThemedIntl(
|
await act(async () => {
|
||||||
<Provider store={store}>
|
const wrapper = mountWithThemedIntl(
|
||||||
<InviteView {...props}/>
|
<Provider store={store}>
|
||||||
</Provider>,
|
<InviteView {...props}/>
|
||||||
);
|
</Provider>,
|
||||||
expect(wrapper.find(InviteAs).length).toBe(0);
|
);
|
||||||
|
expect(wrapper.find(InviteAs).length).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
import {useDispatch, useSelector} from 'react-redux';
|
import {useDispatch, useSelector} from 'react-redux';
|
||||||
|
import {useHistory} from 'react-router-dom'
|
||||||
|
|
||||||
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users';
|
||||||
import {GlobalState} from 'types/store';
|
import {GlobalState} from 'types/store';
|
||||||
@@ -16,10 +17,12 @@ import {savePreferences} from 'mattermost-redux/actions/preferences';
|
|||||||
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences';
|
||||||
import {PreferenceType} from '@mattermost/types/preferences';
|
import {PreferenceType} from '@mattermost/types/preferences';
|
||||||
import {useExpandOverageUsersCheck} from 'components/common/hooks/useExpandOverageUsersCheck';
|
import {useExpandOverageUsersCheck} from 'components/common/hooks/useExpandOverageUsersCheck';
|
||||||
import {LicenseLinks, StatTypes, Preferences} from 'utils/constants';
|
import {LicenseLinks, StatTypes, Preferences, ConsolePages} from 'utils/constants';
|
||||||
|
|
||||||
import './overage_users_banner_notice.scss';
|
import './overage_users_banner_notice.scss';
|
||||||
import ExternalLink from 'components/external_link';
|
import ExternalLink from 'components/external_link';
|
||||||
|
import useCanSelfHostedExpand from 'components/common/hooks/useCanSelfHostedExpand';
|
||||||
|
import {getSiteURL} from 'utils/url';
|
||||||
|
|
||||||
type AdminHasDismissedArgs = {
|
type AdminHasDismissedArgs = {
|
||||||
preferenceName: string;
|
preferenceName: string;
|
||||||
@@ -42,6 +45,9 @@ const OverageUsersBannerNotice = () => {
|
|||||||
const currentUser = useSelector((state: GlobalState) => getCurrentUser(state));
|
const currentUser = useSelector((state: GlobalState) => getCurrentUser(state));
|
||||||
const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER));
|
const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER));
|
||||||
const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0;
|
const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0;
|
||||||
|
const canSelfHostedExpand = useCanSelfHostedExpand();
|
||||||
|
const siteURL = getSiteURL();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isBetween5PercerntAnd10PercentPurchasedSeats,
|
isBetween5PercerntAnd10PercentPurchasedSeats,
|
||||||
isOver10PercerntPurchasedSeats,
|
isOver10PercerntPurchasedSeats,
|
||||||
@@ -83,7 +89,30 @@ const OverageUsersBannerNotice = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let message;
|
let message;
|
||||||
if (!isGovSku) {
|
|
||||||
|
if (canSelfHostedExpand) {
|
||||||
|
message = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='licensingPage.overageUsersBanner.selfHostedNoticeDescription'
|
||||||
|
defaultMessage={'<a>Purchase additional seats </a> to remain compliant.'}
|
||||||
|
values={{
|
||||||
|
a: (chunks: React.ReactNode) => {
|
||||||
|
return (
|
||||||
|
<ExternalLink
|
||||||
|
className='overage_users_banner__button'
|
||||||
|
href={`${siteURL}/${ConsolePages.LICENSE}?action=show_expansion_modal`}
|
||||||
|
rel='noopener noreferrer'
|
||||||
|
target="_blank"
|
||||||
|
|
||||||
|
>
|
||||||
|
{chunks}
|
||||||
|
</ExternalLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
} else if (!isGovSku) {
|
||||||
message = (
|
message = (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='licensingPage.overageUsersBanner.noticeDescription'
|
id='licensingPage.overageUsersBanner.noticeDescription'
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {fireEvent, screen} from '@testing-library/react';
|
import {act, fireEvent, screen} from '@testing-library/react';
|
||||||
|
|
||||||
import {DeepPartial} from '@mattermost/types/utilities';
|
import {DeepPartial} from '@mattermost/types/utilities';
|
||||||
import {GlobalState} from 'types/store';
|
import {GlobalState} from 'types/store';
|
||||||
import {General} from 'mattermost-redux/constants';
|
import {General} from 'mattermost-redux/constants';
|
||||||
import {LicenseLinks, OverActiveUserLimits, Preferences, StatTypes} from 'utils/constants';
|
import {LicenseLinks, OverActiveUserLimits, Preferences, SelfHostedProducts, StatTypes} from 'utils/constants';
|
||||||
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
|
import {renderWithIntlAndStore} from 'tests/react_testing_utils';
|
||||||
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
import {savePreferences} from 'mattermost-redux/actions/preferences';
|
||||||
import {trackEvent} from 'actions/telemetry_actions';
|
import {trackEvent} from 'actions/telemetry_actions';
|
||||||
@@ -93,6 +93,19 @@ describe('components/invitation_modal/overage_users_banner_notice', () => {
|
|||||||
getRequestState: 'IDLE',
|
getRequestState: 'IDLE',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
hostedCustomer: {
|
||||||
|
products: {
|
||||||
|
productsLoaded: true,
|
||||||
|
products: {
|
||||||
|
prod_professional: TestHelper.getProductMock({
|
||||||
|
id: 'prod_professional',
|
||||||
|
name: 'Professional',
|
||||||
|
sku: SelfHostedProducts.PROFESSIONAL,
|
||||||
|
price_per_seat: 7.5,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -483,7 +496,7 @@ describe('components/invitation_modal/overage_users_banner_notice', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gov sku sees overage notice but not a call to do true up', () => {
|
it('gov sku sees overage notice but not a call to do true up', async () => {
|
||||||
const store: GlobalState = JSON.parse(JSON.stringify(initialState));
|
const store: GlobalState = JSON.parse(JSON.stringify(initialState));
|
||||||
|
|
||||||
store.entities.admin = {
|
store.entities.admin = {
|
||||||
@@ -502,8 +515,10 @@ describe('components/invitation_modal/overage_users_banner_notice', () => {
|
|||||||
};
|
};
|
||||||
store.entities.general.license.IsGovSku = 'true';
|
store.entities.general.license.IsGovSku = 'true';
|
||||||
|
|
||||||
renderComponent({
|
await act( async () => {
|
||||||
store,
|
renderComponent({
|
||||||
|
store,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
screen.getByText(text10PercentageState);
|
screen.getByText(text10PercentageState);
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ export default function SelfHostedExpansionModal() {
|
|||||||
<SuccessPage
|
<SuccessPage
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setFormState({...formState, submitting: false, error: '', succeeded: false});
|
setFormState({...formState, submitting: false, error: '', succeeded: false});
|
||||||
closeModal(ModalIdentifiers.SELF_HOSTED_EXPANSION);
|
dispatch(closeModal(ModalIdentifiers.SELF_HOSTED_EXPANSION));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user