From 42f6568d0927d11d7830e8c51ea75ebf00f8a2c1 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Fri, 14 Apr 2023 16:50:53 -0400 Subject: [PATCH 01/12] update overage banner/message in invite modal to direct to the self hosted expansion modal if self hosted expansion is available. --- .../enterprise_edition_left_panel.tsx | 5 +- .../overage_users_banner/index.tsx | 16 ++++- .../overage_users_banner.test.tsx | 17 ++++- .../common/hooks/useCanSelfHostedExpand.ts | 1 - .../useControlSelfHostedExpansionModal.ts | 4 -- .../invitation_modal.test.tsx | 15 +++++ .../invitation_modal/invite_view.test.tsx | 64 +++++++++++++------ .../overage_users_banner_notice/index.tsx | 33 +++++++++- .../overage_users_banner_notice.test.tsx | 25 ++++++-- .../self_hosted_expansion_modal/index.tsx | 2 +- 10 files changed, 142 insertions(+), 40 deletions(-) diff --git a/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx b/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx index b2616d9453..db8fba9cf8 100644 --- a/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx +++ b/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx @@ -65,9 +65,8 @@ const EnterpriseEditionLeftPanel = ({ const actionQueryParam = query.get('action'); useEffect(() => { - if (actionQueryParam === 'show_expansion_modal' && canExpand && isSelfHostedExpansionEnabled) { + if (actionQueryParam === 'show_expansion_modal') { selfHostedExpansionModal.open(); - query.set('action', ''); } }, []); @@ -100,7 +99,7 @@ const EnterpriseEditionLeftPanel = ({ ); const handleClickAddSeats = () => { - if (!isSelfHostedExpansionEnabled && !canExpand) { + if (!isSelfHostedExpansionEnabled || !canExpand) { window.open(expandableLink(unsanitizedLicense.Id), '_blank'); } else { selfHostedExpansionModal.open(); diff --git a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx index d22fe6389f..7012548f7a 100644 --- a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx +++ b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx @@ -16,9 +16,11 @@ import {makeGetCategory} from 'mattermost-redux/selectors/entities/preferences'; import {PreferenceType} from '@mattermost/types/preferences'; import {useExpandOverageUsersCheck} from 'components/common/hooks/useExpandOverageUsersCheck'; 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 {getSiteURL} from 'utils/url'; +import useCanSelfHostedExpand from 'components/common/hooks/useCanSelfHostedExpand'; type AdminHasDismissedItArgs = { preferenceName: string; @@ -53,10 +55,13 @@ const OverageUsersBanner = () => { activeUsers, seatsPurchased, }); + const canSelfHostedExpand = useCanSelfHostedExpand(); + const siteURL = getSiteURL(); const prefixPreferences = isOver10PercerntPurchasedSeats ? 'error' : 'warn'; const prefixLicenseId = (license.Id || '').substring(0, 8); const preferenceName = `${prefixPreferences}_overage_seats_${prefixLicenseId}`; + const overageByUsers = activeUsers - seatsPurchased; const isOverageState = isBetween5PercerntAnd10PercentPurchasedSeats || isOver10PercerntPurchasedSeats; @@ -86,6 +91,12 @@ const OverageUsersBanner = () => { const handleUpdateSeatsSelfServeClick = (e: React.MouseEvent) => { e.preventDefault(); trackEventFn('Self Serve'); + + if (canSelfHostedExpand) { + window.open(`${siteURL}/${ConsolePages.LICENSE}?action=show_expansion_modal`); + return; + } + window.open(expandableLink(license.Id), '_blank'); }; @@ -101,7 +112,8 @@ const OverageUsersBanner = () => { return null; } - const message = ( + + let message = ( { getRequestState: 'IDLE', }, }, + hostedCustomer: { + products: { + productsLoaded: true, + products: { + prod_professional: TestHelper.getProductMock({ + id: 'prod_professional', + name: 'Professional', + sku: SelfHostedProducts.PROFESSIONAL, + price_per_seat: 7.5, + + }), + + }, + }, + }, }, }; diff --git a/webapp/channels/src/components/common/hooks/useCanSelfHostedExpand.ts b/webapp/channels/src/components/common/hooks/useCanSelfHostedExpand.ts index 93f2d2092e..1488713947 100644 --- a/webapp/channels/src/components/common/hooks/useCanSelfHostedExpand.ts +++ b/webapp/channels/src/components/common/hooks/useCanSelfHostedExpand.ts @@ -16,7 +16,6 @@ import {findSelfHostedProductBySku} from 'utils/hosted_customer'; import useGetSelfHostedProducts from './useGetSelfHostedProducts'; 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 config = useSelector(getConfig); const isEnterpriseReady = config.BuildEnterpriseReady === 'true'; diff --git a/webapp/channels/src/components/common/hooks/useControlSelfHostedExpansionModal.ts b/webapp/channels/src/components/common/hooks/useControlSelfHostedExpansionModal.ts index a310c4538e..fee2a34351 100644 --- a/webapp/channels/src/components/common/hooks/useControlSelfHostedExpansionModal.ts +++ b/webapp/channels/src/components/common/hooks/useControlSelfHostedExpansionModal.ts @@ -25,7 +25,6 @@ interface HookOptions{ export default function useControlSelfHostedExpansionModal(options: HookOptions): ControlModal { const dispatch = useDispatch(); const currentUser = useSelector(getCurrentUser); - const canExpand = useCanSelfHostedExpand(); const controlModal = useControlModal({ modalId: ModalIdentifiers.SELF_HOSTED_EXPANSION, dialogType: SelfHostedExpansionModal, @@ -35,9 +34,6 @@ export default function useControlSelfHostedExpansionModal(options: HookOptions) return { ...controlModal, open: async () => { - if (!canExpand) { - return; - } const purchaseInProgress = localStorage.getItem(STORAGE_KEY_EXPANSION_IN_PROGRESS) === 'true'; diff --git a/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx b/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx index 0db5a75825..80c5226eec 100644 --- a/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx +++ b/webapp/channels/src/components/invitation_modal/invitation_modal.test.tsx @@ -17,6 +17,8 @@ import ResultView from './result_view'; import InviteView from './invite_view'; import NoPermissionsView from './no_permissions_view'; 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({ actions: { @@ -87,6 +89,19 @@ describe('InvitationModal', () => { preferences: { myPreferences: {}, }, + hostedCustomer: { + products: { + productsLoaded: true, + products: { + prod_professional: TestHelper.getProductMock({ + id: 'prod_professional', + name: 'Professional', + sku: SelfHostedProducts.PROFESSIONAL, + price_per_seat: 7.5, + }), + }, + }, + }, }, }; diff --git a/webapp/channels/src/components/invitation_modal/invite_view.test.tsx b/webapp/channels/src/components/invitation_modal/invite_view.test.tsx index b90af49861..16e49e8f88 100644 --- a/webapp/channels/src/components/invitation_modal/invite_view.test.tsx +++ b/webapp/channels/src/components/invitation_modal/invite_view.test.tsx @@ -11,9 +11,12 @@ import {mountWithThemedIntl} from 'tests/helpers/themed-intl-test-helper'; import deepFreeze from 'mattermost-redux/utils/deep_freeze'; import {Team} from '@mattermost/types/teams'; import {generateId} from 'utils/utils'; +import {TestHelper as TH} from 'utils/test_helper'; import InviteAs, {InviteType} from './invite_as'; import InviteView, {Props} from './invite_view'; +import {SelfHostedProducts} from 'utils/constants'; +import {act} from 'react-dom/test-utils'; const defaultProps: Props = deepFreeze({ setInviteAs: jest.fn(), @@ -99,6 +102,19 @@ describe('InviteView', () => { preferences: { 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; }); - it('shows InviteAs component when user can choose to invite guests or users', () => { - const wrapper = mountWithThemedIntl( - - - , - ); - expect(wrapper.find(InviteAs).length).toBe(1); + it('shows InviteAs component when user can choose to invite guests or users', async () => { + await act(async () => { + const wrapper = mountWithThemedIntl( + + + , + ); + 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 = { ...defaultProps, canAddUsers: false, }; - const wrapper = mountWithThemedIntl( - - - , - ); - expect(wrapper.find(InviteAs).length).toBe(0); + await act(async () => { + const wrapper = mountWithThemedIntl( + + + , + ); + 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 = { ...defaultProps, canInviteGuests: false, }; - const wrapper = mountWithThemedIntl( - - - , - ); - expect(wrapper.find(InviteAs).length).toBe(0); + await act(async () => { + const wrapper = mountWithThemedIntl( + + + , + ); + expect(wrapper.find(InviteAs).length).toBe(0); + }); }); }); diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index ce1cd6a1c3..f05638c2ec 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -4,6 +4,7 @@ import React from 'react'; import {FormattedMessage} from 'react-intl'; import {useDispatch, useSelector} from 'react-redux'; +import {useHistory} from 'react-router-dom' import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; 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 {PreferenceType} from '@mattermost/types/preferences'; 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 ExternalLink from 'components/external_link'; +import useCanSelfHostedExpand from 'components/common/hooks/useCanSelfHostedExpand'; +import {getSiteURL} from 'utils/url'; type AdminHasDismissedArgs = { preferenceName: string; @@ -42,6 +45,9 @@ const OverageUsersBannerNotice = () => { const currentUser = useSelector((state: GlobalState) => getCurrentUser(state)); const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER)); const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0; + const canSelfHostedExpand = useCanSelfHostedExpand(); + const siteURL = getSiteURL(); + const { isBetween5PercerntAnd10PercentPurchasedSeats, isOver10PercerntPurchasedSeats, @@ -83,7 +89,30 @@ const OverageUsersBannerNotice = () => { }; let message; - if (!isGovSku) { + + if (canSelfHostedExpand) { + message = ( + Purchase additional seats to remain compliant.'} + values={{ + a: (chunks: React.ReactNode) => { + return ( + + {chunks} + + ) + } + }} + /> + ) + } else if (!isGovSku) { message = ( { 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)); store.entities.admin = { @@ -502,8 +515,10 @@ describe('components/invitation_modal/overage_users_banner_notice', () => { }; store.entities.general.license.IsGovSku = 'true'; - renderComponent({ - store, + await act( async () => { + renderComponent({ + store, + }); }); screen.getByText(text10PercentageState); diff --git a/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/index.tsx b/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/index.tsx index 5fbd4d6ebc..88efd97956 100644 --- a/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/index.tsx +++ b/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/index.tsx @@ -509,7 +509,7 @@ export default function SelfHostedExpansionModal() { { setFormState({...formState, submitting: false, error: '', succeeded: false}); - closeModal(ModalIdentifiers.SELF_HOSTED_EXPANSION); + dispatch(closeModal(ModalIdentifiers.SELF_HOSTED_EXPANSION)); }} /> )} From 3a64bda17141c3dd4ceae176ab6dd2a0cc1edffb Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Fri, 14 Apr 2023 16:53:28 -0400 Subject: [PATCH 02/12] add additional checks for service setting. --- .../announcement_bar/overage_users_banner/index.tsx | 4 +++- .../invitation_modal/overage_users_banner_notice/index.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx index 7012548f7a..b5e20a1ca8 100644 --- a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx +++ b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx @@ -21,6 +21,7 @@ import {StatTypes, Preferences, AnnouncementBarTypes, ConsolePages} from 'utils/ import './overage_users_banner.scss'; import {getSiteURL} from 'utils/url'; import useCanSelfHostedExpand from 'components/common/hooks/useCanSelfHostedExpand'; +import {getConfig} from 'mattermost-redux/selectors/entities/admin'; type AdminHasDismissedItArgs = { preferenceName: string; @@ -55,7 +56,8 @@ const OverageUsersBanner = () => { activeUsers, seatsPurchased, }); - const canSelfHostedExpand = useCanSelfHostedExpand(); + const isSelfHostedExpansionEnabled = useSelector(getConfig)?.ServiceSettings?.SelfHostedExpansion; + const canSelfHostedExpand = useCanSelfHostedExpand() && isSelfHostedExpansionEnabled; const siteURL = getSiteURL(); const prefixPreferences = isOver10PercerntPurchasedSeats ? 'error' : 'warn'; const prefixLicenseId = (license.Id || '').substring(0, 8); diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index f05638c2ec..bb6702c669 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -23,6 +23,7 @@ import './overage_users_banner_notice.scss'; import ExternalLink from 'components/external_link'; import useCanSelfHostedExpand from 'components/common/hooks/useCanSelfHostedExpand'; import {getSiteURL} from 'utils/url'; +import {getConfig} from 'mattermost-redux/selectors/entities/admin'; type AdminHasDismissedArgs = { preferenceName: string; @@ -45,7 +46,8 @@ const OverageUsersBannerNotice = () => { const currentUser = useSelector((state: GlobalState) => getCurrentUser(state)); const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER)); const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0; - const canSelfHostedExpand = useCanSelfHostedExpand(); + const isSelfHostedExpansionEnabled = useSelector(getConfig)?.ServiceSettings?.SelfHostedExpansion; + const canSelfHostedExpand = useCanSelfHostedExpand() && isSelfHostedExpansionEnabled; const siteURL = getSiteURL(); const { From 64ac8f21f4b7ee56318cd2c5b51ef4451a8a9c32 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Mon, 17 Apr 2023 15:27:48 -0400 Subject: [PATCH 03/12] i18n. --- .../overage_users_banner/overage_users_banner.test.tsx | 2 -- .../invitation_modal/overage_users_banner_notice/index.tsx | 1 - webapp/channels/src/i18n/en.json | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/webapp/channels/src/components/announcement_bar/overage_users_banner/overage_users_banner.test.tsx b/webapp/channels/src/components/announcement_bar/overage_users_banner/overage_users_banner.test.tsx index 3dc3909d93..db667d5794 100644 --- a/webapp/channels/src/components/announcement_bar/overage_users_banner/overage_users_banner.test.tsx +++ b/webapp/channels/src/components/announcement_bar/overage_users_banner/overage_users_banner.test.tsx @@ -116,9 +116,7 @@ describe('components/overage_users_banner', () => { name: 'Professional', sku: SelfHostedProducts.PROFESSIONAL, price_per_seat: 7.5, - }), - }, }, }, diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index bb6702c669..b4c16e114f 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -105,7 +105,6 @@ const OverageUsersBannerNotice = () => { href={`${siteURL}/${ConsolePages.LICENSE}?action=show_expansion_modal`} rel='noopener noreferrer' target="_blank" - > {chunks} diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json index 230a776e60..6b524dc13e 100644 --- a/webapp/channels/src/i18n/en.json +++ b/webapp/channels/src/i18n/en.json @@ -4027,6 +4027,7 @@ "licensingPage.overageUsersBanner.ctaExpandSeats": "Purchase additional seats", "licensingPage.overageUsersBanner.noticeDescription": "Notify your Customer Success Manager on your next true-up check. ", "licensingPage.overageUsersBanner.noticeTitle": "Your workspace user count has exceeded your paid license seat count by {seats, number} {seats, plural, one {seat} other {seats}}", + "licensingPage.overageUsersBanner.selfHostedNoticeDescription": "Purchase additional seats to remain compliant.", "licensingPage.overageUsersBanner.text": "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.", "link_preview.image_preview": "Show Image preview", "link_preview.remove_link_preview": "Remove link preview", From e434ec5e05ca2689640d66a7431963ebbdb697f0 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Tue, 18 Apr 2023 14:24:00 -0400 Subject: [PATCH 04/12] lint. --- .../announcement_bar/overage_users_banner/index.tsx | 4 +--- .../common/hooks/useControlSelfHostedExpansionModal.ts | 2 -- .../overage_users_banner_notice/index.tsx | 9 ++++----- .../overage_users_banner_notice.test.tsx | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx index b5e20a1ca8..165415dd1f 100644 --- a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx +++ b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx @@ -63,7 +63,6 @@ const OverageUsersBanner = () => { const prefixLicenseId = (license.Id || '').substring(0, 8); const preferenceName = `${prefixPreferences}_overage_seats_${prefixLicenseId}`; - const overageByUsers = activeUsers - seatsPurchased; const isOverageState = isBetween5PercerntAnd10PercentPurchasedSeats || isOver10PercerntPurchasedSeats; @@ -114,8 +113,7 @@ const OverageUsersBanner = () => { return null; } - - let message = ( + const message = ( { - const purchaseInProgress = localStorage.getItem(STORAGE_KEY_EXPANSION_IN_PROGRESS) === 'true'; // check if user already has an open purchase modal in current browser. diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index b4c16e114f..a6f3241ef2 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -4,7 +4,6 @@ import React from 'react'; import {FormattedMessage} from 'react-intl'; import {useDispatch, useSelector} from 'react-redux'; -import {useHistory} from 'react-router-dom' import {getCurrentUser, isCurrentUserSystemAdmin} from 'mattermost-redux/selectors/entities/users'; import {GlobalState} from 'types/store'; @@ -104,15 +103,15 @@ const OverageUsersBannerNotice = () => { className='overage_users_banner__button' href={`${siteURL}/${ConsolePages.LICENSE}?action=show_expansion_modal`} rel='noopener noreferrer' - target="_blank" + target='_blank' > {chunks} - ) - } + ); + }, }} /> - ) + ); } else if (!isGovSku) { message = ( { }; store.entities.general.license.IsGovSku = 'true'; - await act( async () => { + await act(async () => { renderComponent({ store, }); From c8008142d76df7076f95fd7195e0eca0ebc2dfb4 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Tue, 18 Apr 2023 14:33:26 -0400 Subject: [PATCH 05/12] fix types. --- .../announcement_bar/overage_users_banner/index.tsx | 2 +- .../invitation_modal/overage_users_banner_notice/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx index 165415dd1f..1aa37d047b 100644 --- a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx +++ b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx @@ -56,7 +56,7 @@ const OverageUsersBanner = () => { activeUsers, seatsPurchased, }); - const isSelfHostedExpansionEnabled = useSelector(getConfig)?.ServiceSettings?.SelfHostedExpansion; + const isSelfHostedExpansionEnabled = useSelector(getConfig)?.ServiceSettings?.SelfHostedPurchase; const canSelfHostedExpand = useCanSelfHostedExpand() && isSelfHostedExpansionEnabled; const siteURL = getSiteURL(); const prefixPreferences = isOver10PercerntPurchasedSeats ? 'error' : 'warn'; diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index a6f3241ef2..9618f56b99 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -45,8 +45,8 @@ const OverageUsersBannerNotice = () => { const currentUser = useSelector((state: GlobalState) => getCurrentUser(state)); const overagePreferences = useSelector((state: GlobalState) => getPreferencesCategory(state, Preferences.OVERAGE_USERS_BANNER)); const activeUsers = ((stats || {})[StatTypes.TOTAL_USERS]) as number || 0; - const isSelfHostedExpansionEnabled = useSelector(getConfig)?.ServiceSettings?.SelfHostedExpansion; - const canSelfHostedExpand = useCanSelfHostedExpand() && isSelfHostedExpansionEnabled; + const isSelfHostedPurchaseEnabled = useSelector(getConfig)?.ServiceSettings?.SelfHostedPurchase; + const canSelfHostedExpand = useCanSelfHostedExpand() && isSelfHostedPurchaseEnabled; const siteURL = getSiteURL(); const { From ac030d70743b744b9f1cc3d161c4c7bc8d4a2a6e Mon Sep 17 00:00:00 2001 From: Conor Macpherson <116016004+ConorMacpherson@users.noreply.github.com> Date: Thu, 20 Apr 2023 12:03:02 -0400 Subject: [PATCH 06/12] Update enterprise_edition_left_panel.tsx --- .../enterprise_edition/enterprise_edition_left_panel.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx b/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx index 790d3e2f9e..1a09207a64 100644 --- a/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx +++ b/webapp/channels/src/components/admin_console/license_settings/enterprise_edition/enterprise_edition_left_panel.tsx @@ -67,6 +67,7 @@ const EnterpriseEditionLeftPanel = ({ useEffect(() => { if (actionQueryParam === 'show_expansion_modal' && canExpand && isSelfHostedPurchaseEnabled) { selfHostedExpansionModal.open(); + query.set('action', ''); } }, []); From e281acd81744b4596c06fbee7a440ddbcdf475d5 Mon Sep 17 00:00:00 2001 From: Conor Macpherson <116016004+ConorMacpherson@users.noreply.github.com> Date: Thu, 20 Apr 2023 12:04:02 -0400 Subject: [PATCH 07/12] Update index.tsx --- .../invitation_modal/overage_users_banner_notice/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index 9618f56b99..54cd025068 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -95,7 +95,7 @@ const OverageUsersBannerNotice = () => { message = ( Purchase additional seats to remain compliant.'} + defaultMessage={'Purchase additional seats to remain compliant.'} values={{ a: (chunks: React.ReactNode) => { return ( From c8afa3b27f280c7ade13c0bb36f7d4853203b6f0 Mon Sep 17 00:00:00 2001 From: Conor Macpherson <116016004+ConorMacpherson@users.noreply.github.com> Date: Thu, 20 Apr 2023 12:04:31 -0400 Subject: [PATCH 08/12] Update en.json --- webapp/channels/src/i18n/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json index 360d514e12..584fea3324 100644 --- a/webapp/channels/src/i18n/en.json +++ b/webapp/channels/src/i18n/en.json @@ -4057,7 +4057,7 @@ "licensingPage.overageUsersBanner.ctaExpandSeats": "Purchase additional seats", "licensingPage.overageUsersBanner.noticeDescription": "Notify your Customer Success Manager on your next true-up check. ", "licensingPage.overageUsersBanner.noticeTitle": "Your workspace user count has exceeded your paid license seat count by {seats, number} {seats, plural, one {seat} other {seats}}", - "licensingPage.overageUsersBanner.selfHostedNoticeDescription": "Purchase additional seats to remain compliant.", + "licensingPage.overageUsersBanner.selfHostedNoticeDescription": "Purchase additional seats to remain compliant.", "licensingPage.overageUsersBanner.text": "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.", "link_preview.image_preview": "Show Image preview", "link_preview.remove_link_preview": "Remove link preview", From 0feb800bf00fa130bf020a5185e58212b001c482 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Thu, 20 Apr 2023 16:51:20 -0400 Subject: [PATCH 09/12] Add missing text for overage banner. --- .../overage_users_banner/index.tsx | 14 +++++++++- .../hooks/useExpandOverageUsersCheck.ts | 28 +++++++++++++------ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx index 1aa37d047b..faee1da5ba 100644 --- a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx +++ b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx @@ -78,6 +78,7 @@ const OverageUsersBanner = () => { licenseId: license.Id, isWarningState: isBetween5PercerntAnd10PercentPurchasedSeats, banner: 'global banner', + canSelfHostedExpand: canSelfHostedExpand || false, }); const handleClose = () => { @@ -113,7 +114,7 @@ const OverageUsersBanner = () => { return null; } - const message = ( + let message = ( { seats: overageByUsers, }} />); + + if (canSelfHostedExpand) { + message = ( + ); + } return ( { const {formatMessage} = useIntl(); const dispatch = useDispatch(); const {getRequestState, is_expandable: isExpandable}: LicenseSelfServeStatusReducer = useSelector((state: GlobalState) => state.entities.cloud.subscriptionStats || {is_expandable: false, getRequestState: 'IDLE'}); const expandableLink = useSelector(getExpandSeatsLink); - const cta = useMemo(() => (isExpandable ? formatMessage({ - id: 'licensingPage.overageUsersBanner.ctaExpandSeats', - defaultMessage: 'Purchase additional seats', - }) : formatMessage({ - id: 'licensingPage.overageUsersBanner.cta', - defaultMessage: 'Contact Sales', - }) - ), [isExpandable]); + const cta = useMemo(() => { + if (isExpandable && !canSelfHostedExpand) { + return formatMessage({ + id: 'licensingPage.overageUsersBanner.ctaExpandSeats', + defaultMessage: 'Purchase additional seats', + }); + } else if (isExpandable && canSelfHostedExpand) { + return formatMessage({ + id: 'licensingPage.overageUsersBanner.ctaUpdateSeats', + defaultMessage: 'Update seat count', + }); + } else { + return formatMessage({ + id: 'licensingPage.overageUsersBanner.cta', + defaultMessage: 'Contact Sales', + }); + } + }, [isExpandable]); const trackEventFn = (cta: 'Contact Sales' | 'Self Serve') => { trackEvent('insights', isWarningState ? 'click_true_up_warning' : 'click_true_up_error', { From 873f2350c5cfb0b74fddc058445b863a978b8070 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Mon, 24 Apr 2023 09:17:10 -0400 Subject: [PATCH 10/12] fix types, lint. --- .../announcement_bar/overage_users_banner/index.tsx | 2 +- .../common/hooks/useExpandOverageUsersCheck.ts | 9 ++++----- .../overage_users_banner_notice/index.tsx | 1 + 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx index faee1da5ba..4ad8d35acf 100644 --- a/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx +++ b/webapp/channels/src/components/announcement_bar/overage_users_banner/index.tsx @@ -122,7 +122,7 @@ const OverageUsersBanner = () => { seats: overageByUsers, }} />); - + if (canSelfHostedExpand) { message = ( { diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index 54cd025068..95b97f5508 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -74,6 +74,7 @@ const OverageUsersBannerNotice = () => { licenseId: license.Id, isWarningState: isBetween5PercerntAnd10PercentPurchasedSeats, banner: 'invite modal', + canSelfHostedExpand: canSelfHostedExpand || false, }); if (!hasPermission || adminHasDismissed({overagePreferences, preferenceName})) { From 76c7c9b294352a43d39703507ce265f5505c546b Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Mon, 24 Apr 2023 09:22:58 -0400 Subject: [PATCH 11/12] i18n. --- webapp/channels/src/i18n/en.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json index 584fea3324..89432dc42d 100644 --- a/webapp/channels/src/i18n/en.json +++ b/webapp/channels/src/i18n/en.json @@ -4055,10 +4055,12 @@ "licensingPage.infoBanner.startTrialTitle": "Free 30 day trial!", "licensingPage.overageUsersBanner.cta": "Contact Sales", "licensingPage.overageUsersBanner.ctaExpandSeats": "Purchase additional seats", + "licensingPage.overageUsersBanner.ctaUpdateSeats": "Update seat count", "licensingPage.overageUsersBanner.noticeDescription": "Notify your Customer Success Manager on your next true-up check. ", "licensingPage.overageUsersBanner.noticeTitle": "Your workspace user count has exceeded your paid license seat count by {seats, number} {seats, plural, one {seat} other {seats}}", "licensingPage.overageUsersBanner.selfHostedNoticeDescription": "Purchase additional seats to remain compliant.", "licensingPage.overageUsersBanner.text": "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.", + "licensingPage.overageUsersBanner.textSelfHostedExpand": "Your workspace user count has exceeded your paid license seat count. Update your seat count to stay compliant.", "link_preview.image_preview": "Show Image preview", "link_preview.remove_link_preview": "Remove link preview", "list_modal.paginatorCount": "{startCount, number} - {endCount, number} of {total, number} total", From 3113503264b77fc822f342054f28fb96b400d484 Mon Sep 17 00:00:00 2001 From: Conor Macpherson <116016004+ConorMacpherson@users.noreply.github.com> Date: Tue, 25 Apr 2023 13:06:30 -0400 Subject: [PATCH 12/12] omit ref and target in external links. --- .../invitation_modal/overage_users_banner_notice/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx index 95b97f5508..fb6c1968a7 100644 --- a/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx +++ b/webapp/channels/src/components/invitation_modal/overage_users_banner_notice/index.tsx @@ -103,8 +103,6 @@ const OverageUsersBannerNotice = () => { {chunks}