mirror of
https://github.com/mattermost/mattermost.git
synced 2026-09-01 15:00:08 +08:00
Entry Sku Product Label (#33847)
* Initial commit * Linting * Update FREE EDITION to TEAM EDITION * Added permalink for entry limit info
This commit is contained in:
@@ -24,7 +24,7 @@ test(
|
||||
// # Get license information and prepare test args
|
||||
const testArgs = {page, browserName, viewport};
|
||||
const license = await adminClient.getClientLicenseOld();
|
||||
const editionSuffix = license.IsLicensed === 'true' ? '' : 'free edition';
|
||||
const editionSuffix = license.IsLicensed === 'true' ? '' : 'team edition';
|
||||
|
||||
// * Verify login page appears as expected
|
||||
await pw.matchSnapshot({...testInfo, title: `${testInfo.title} ${editionSuffix}`}, testArgs);
|
||||
|
||||
@@ -29,7 +29,7 @@ test(
|
||||
|
||||
// # Get license information to determine snapshot suffix
|
||||
const license = await adminClient.getClientLicenseOld();
|
||||
const editionSuffix = license.IsLicensed === 'true' ? '' : 'free edition';
|
||||
const editionSuffix = license.IsLicensed === 'true' ? '' : 'team edition';
|
||||
const testArgs = {page, browserName, viewport};
|
||||
|
||||
// * Verify visual appearance of signup page
|
||||
|
||||
+75
-1
@@ -148,6 +148,80 @@ exports[`components/global/product_switcher should match snapshot 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`components/global/product_switcher should match snapshot for Entry license 1`] = `
|
||||
<div>
|
||||
<MenuWrapper
|
||||
animationComponent={[Function]}
|
||||
className=""
|
||||
open={true}
|
||||
>
|
||||
<ProductMenuContainer
|
||||
onClick={[Function]}
|
||||
>
|
||||
<ProductMenuButton
|
||||
aria-controls="product-switcher-menu"
|
||||
aria-expanded={true}
|
||||
aria-label="Product switch menu"
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "rgba(var(--sidebar-text-rgb), 0.16)",
|
||||
"color": "rgba(var(--sidebar-text-rgb), 0.56)",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ProductsIcon
|
||||
color="rgba(var(--sidebar-text-rgb), 0.56)"
|
||||
size={20}
|
||||
/>
|
||||
<ProductBrandingFreeEdition />
|
||||
</ProductMenuButton>
|
||||
</ProductMenuContainer>
|
||||
<Menu
|
||||
ariaLabel="switcherOpen"
|
||||
className="product-switcher-menu"
|
||||
id="product-switcher-menu"
|
||||
listId="product-switcher-menu-dropdown"
|
||||
>
|
||||
<ProductMenuItem
|
||||
active={true}
|
||||
destination="/"
|
||||
icon="product-channels"
|
||||
onClick={[Function]}
|
||||
text="Channels"
|
||||
/>
|
||||
<ProductMenuItem
|
||||
active={false}
|
||||
destination=""
|
||||
icon="product-boards"
|
||||
id="product-menu-item-Boards"
|
||||
key="Boards"
|
||||
onClick={[Function]}
|
||||
text="Boards"
|
||||
/>
|
||||
<ProductMenuItem
|
||||
active={false}
|
||||
destination=""
|
||||
icon="product-playbooks"
|
||||
id="product-menu-item-Playbooks"
|
||||
key="Playbooks"
|
||||
onClick={[Function]}
|
||||
text="Playbooks"
|
||||
/>
|
||||
<Connect(ProductMenuList)
|
||||
handleVisitConsoleClick={[Function]}
|
||||
isMessaging={true}
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<Memo(MenuGroup)>
|
||||
<MenuStartTrial
|
||||
id="startTrial"
|
||||
/>
|
||||
</Memo(MenuGroup)>
|
||||
</Menu>
|
||||
</MenuWrapper>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`components/global/product_switcher should match snapshot with product switcher menu 1`] = `
|
||||
<div>
|
||||
<MenuWrapper
|
||||
@@ -247,7 +321,7 @@ exports[`components/global/product_switcher should match snapshot without licens
|
||||
color="rgba(var(--sidebar-text-rgb), 0.56)"
|
||||
size={20}
|
||||
/>
|
||||
<ProductBrandingTeamEdition />
|
||||
<ProductBrandingFreeEdition />
|
||||
</ProductMenuButton>
|
||||
</ProductMenuContainer>
|
||||
<Menu
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
export {default} from './product_branding_team_edition';
|
||||
export {default} from './product_branding_free_edition';
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {renderWithContext, screen} from 'tests/react_testing_utils';
|
||||
import {TestHelper} from 'utils/test_helper';
|
||||
|
||||
import ProductBrandingFreeEdition from './product_branding_free_edition';
|
||||
|
||||
describe('ProductBrandingFreeEdition', () => {
|
||||
const baseProps = {};
|
||||
|
||||
test('should show ENTRY EDITION for Entry license', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'true',
|
||||
SkuShortName: 'entry',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const {container} = renderWithContext(
|
||||
<ProductBrandingFreeEdition {...baseProps}/>,
|
||||
state,
|
||||
);
|
||||
|
||||
expect(screen.getByText('ENTRY EDITION')).toBeInTheDocument();
|
||||
const logoElement = container.querySelector('svg');
|
||||
expect(logoElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show TEAM EDITION for unlicensed', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'false',
|
||||
SkuShortName: '',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const {container} = renderWithContext(
|
||||
<ProductBrandingFreeEdition {...baseProps}/>,
|
||||
state,
|
||||
);
|
||||
|
||||
expect(screen.getByText('TEAM EDITION')).toBeInTheDocument();
|
||||
const logoElement = container.querySelector('svg');
|
||||
expect(logoElement).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show empty badge for Professional license', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'true',
|
||||
SkuShortName: 'professional',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithContext(
|
||||
<ProductBrandingFreeEdition {...baseProps}/>,
|
||||
state,
|
||||
);
|
||||
|
||||
// Should not show any edition badge
|
||||
expect(screen.queryByText('ENTRY EDITION')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('TEAM EDITION')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('PROFESSIONAL EDITION')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show empty badge for Enterprise license', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'true',
|
||||
SkuShortName: 'enterprise',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithContext(
|
||||
<ProductBrandingFreeEdition {...baseProps}/>,
|
||||
state,
|
||||
);
|
||||
|
||||
// Should not show any edition badge
|
||||
expect(screen.queryByText('ENTRY EDITION')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('TEAM EDITION')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('ENTERPRISE EDITION')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should show empty badge when no license object', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
general: {
|
||||
license: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
renderWithContext(
|
||||
<ProductBrandingFreeEdition {...baseProps}/>,
|
||||
state,
|
||||
);
|
||||
|
||||
// Should not show any edition badge when license object is empty
|
||||
expect(screen.queryByText('ENTRY EDITION')).not.toBeInTheDocument();
|
||||
expect(screen.queryByText('TEAM EDITION')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
+20
-6
@@ -2,11 +2,16 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {useSelector} from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import {getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
|
||||
import Logo from 'components/common/svg_images_components/logo_dark_blue_svg';
|
||||
|
||||
const ProductBrandingTeamEditionContainer = styled.span`
|
||||
import {LicenseSkus} from 'utils/constants';
|
||||
|
||||
const ProductBrandingFreeEditionContainer = styled.span`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -36,16 +41,25 @@ const Badge = styled.span`
|
||||
line-height: 16px;
|
||||
`;
|
||||
|
||||
const ProductBrandingTeamEdition = (): JSX.Element => {
|
||||
const ProductBrandingFreeEdition = (): JSX.Element => {
|
||||
const license = useSelector(getLicense);
|
||||
|
||||
let badgeText = '';
|
||||
if (license?.SkuShortName === LicenseSkus.Entry) {
|
||||
badgeText = 'ENTRY EDITION';
|
||||
} else if (license?.IsLicensed === 'false') {
|
||||
badgeText = 'TEAM EDITION';
|
||||
}
|
||||
|
||||
return (
|
||||
<ProductBrandingTeamEditionContainer tabIndex={-1}>
|
||||
<ProductBrandingFreeEditionContainer tabIndex={-1}>
|
||||
<StyledLogo
|
||||
width={116}
|
||||
height={20}
|
||||
/>
|
||||
<Badge>{'FREE EDITION'}</Badge>
|
||||
</ProductBrandingTeamEditionContainer>
|
||||
<Badge>{badgeText}</Badge>
|
||||
</ProductBrandingFreeEditionContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductBrandingTeamEdition;
|
||||
export default ProductBrandingFreeEdition;
|
||||
+116
@@ -10,6 +10,8 @@ import {TopLevelProducts} from 'utils/constants';
|
||||
import * as productUtils from 'utils/products';
|
||||
import {TestHelper} from 'utils/test_helper';
|
||||
|
||||
import ProductBranding from './product_branding';
|
||||
import ProductBrandingFreeEdition from './product_branding_team_edition';
|
||||
import ProductMenu, {ProductMenuButton, ProductMenuContainer} from './product_menu';
|
||||
import ProductMenuItem from './product_menu_item';
|
||||
import ProductMenuList from './product_menu_list';
|
||||
@@ -185,4 +187,118 @@ describe('components/global/product_switcher', () => {
|
||||
expect(wrapper.find(ProductMenuList)).toHaveLength(1);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render ProductBrandingFreeEdition for Entry license', () => {
|
||||
const state = {
|
||||
views: {
|
||||
productMenu: {
|
||||
switcherOpen: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
useSelectorMock.mockReturnValue(true);
|
||||
useSelectorMock.mockReturnValueOnce(true);
|
||||
useSelectorMock.mockReturnValueOnce({IsLicensed: 'true', SkuShortName: 'entry'});
|
||||
const wrapper = shallow(<ProductMenu/>, {
|
||||
wrappingComponent: reactRedux.Provider,
|
||||
wrappingComponentProps: {store},
|
||||
});
|
||||
|
||||
expect(wrapper.find(ProductBrandingFreeEdition)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductBranding)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should render ProductBrandingFreeEdition for unlicensed', () => {
|
||||
const state = {
|
||||
views: {
|
||||
productMenu: {
|
||||
switcherOpen: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
useSelectorMock.mockReturnValue(true);
|
||||
useSelectorMock.mockReturnValueOnce(true);
|
||||
useSelectorMock.mockReturnValueOnce({IsLicensed: 'false'});
|
||||
const wrapper = shallow(<ProductMenu/>, {
|
||||
wrappingComponent: reactRedux.Provider,
|
||||
wrappingComponentProps: {store},
|
||||
});
|
||||
|
||||
expect(wrapper.find(ProductBrandingFreeEdition)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductBranding)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should render ProductBranding for Professional license', () => {
|
||||
const state = {
|
||||
views: {
|
||||
productMenu: {
|
||||
switcherOpen: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
useSelectorMock.mockReturnValue(true);
|
||||
useSelectorMock.mockReturnValueOnce(true);
|
||||
useSelectorMock.mockReturnValueOnce({IsLicensed: 'true', SkuShortName: 'professional'});
|
||||
const wrapper = shallow(<ProductMenu/>, {
|
||||
wrappingComponent: reactRedux.Provider,
|
||||
wrappingComponentProps: {store},
|
||||
});
|
||||
|
||||
expect(wrapper.find(ProductBranding)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductBrandingFreeEdition)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should render ProductBranding for Enterprise license', () => {
|
||||
const state = {
|
||||
views: {
|
||||
productMenu: {
|
||||
switcherOpen: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
useSelectorMock.mockReturnValue(true);
|
||||
useSelectorMock.mockReturnValueOnce(true);
|
||||
useSelectorMock.mockReturnValueOnce({IsLicensed: 'true', SkuShortName: 'enterprise'});
|
||||
const wrapper = shallow(<ProductMenu/>, {
|
||||
wrappingComponent: reactRedux.Provider,
|
||||
wrappingComponentProps: {store},
|
||||
});
|
||||
|
||||
expect(wrapper.find(ProductBranding)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductBrandingFreeEdition)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should match snapshot for Entry license', () => {
|
||||
const state = {
|
||||
views: {
|
||||
productMenu: {
|
||||
switcherOpen: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
useSelectorMock.mockReturnValue(true);
|
||||
useSelectorMock.mockReturnValueOnce(true);
|
||||
useSelectorMock.mockReturnValueOnce({IsLicensed: 'true', SkuShortName: 'entry'});
|
||||
const wrapper = shallow(<ProductMenu/>, {
|
||||
wrappingComponent: reactRedux.Provider,
|
||||
wrappingComponentProps: {store},
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
+9
-3
@@ -24,10 +24,11 @@ import {
|
||||
import Menu from 'components/widgets/menu/menu';
|
||||
import MenuWrapper from 'components/widgets/menu/menu_wrapper';
|
||||
|
||||
import {LicenseSkus} from 'utils/constants';
|
||||
import {useCurrentProductId, useProducts, isChannels} from 'utils/products';
|
||||
|
||||
import ProductBranding from './product_branding';
|
||||
import ProductBrandingTeamEdition from './product_branding_team_edition';
|
||||
import ProductBrandingFreeEdition from './product_branding_team_edition';
|
||||
import ProductMenuItem from './product_menu_item';
|
||||
import ProductMenuList from './product_menu_list';
|
||||
|
||||
@@ -113,6 +114,8 @@ const ProductMenu = (): JSX.Element => {
|
||||
);
|
||||
});
|
||||
|
||||
const isFreeEdition = license.IsLicensed === 'false' || license.SkuShortName === LicenseSkus.Entry;
|
||||
|
||||
return (
|
||||
<div ref={menuRef}>
|
||||
<MenuWrapper
|
||||
@@ -132,8 +135,11 @@ const ProductMenu = (): JSX.Element => {
|
||||
size={20}
|
||||
color='rgba(var(--sidebar-text-rgb), 0.56)'
|
||||
/>
|
||||
{license.IsLicensed === 'false' && <ProductBrandingTeamEdition/>}
|
||||
{license.IsLicensed === 'true' && <ProductBranding/>}
|
||||
{isFreeEdition ? (
|
||||
<ProductBrandingFreeEdition/>
|
||||
) : (
|
||||
<ProductBranding/>
|
||||
)}
|
||||
</ProductMenuButton>
|
||||
</ProductMenuContainer>
|
||||
<Menu
|
||||
|
||||
@@ -12,6 +12,7 @@ import BackButton from 'components/common/back_button';
|
||||
import Logo from 'components/common/svg_images_components/logo_dark_blue_svg';
|
||||
|
||||
import './header.scss';
|
||||
import {LicenseSkus} from 'utils/constants';
|
||||
|
||||
export type HeaderProps = {
|
||||
alternateLink?: React.ReactElement;
|
||||
@@ -27,7 +28,9 @@ const Header = ({alternateLink, backButtonURL, onBackButtonClick}: HeaderProps)
|
||||
|
||||
let freeBanner = null;
|
||||
if (license.IsLicensed === 'false') {
|
||||
freeBanner = <><Logo/><span className='freeBadge'>{'FREE EDITION'}</span></>;
|
||||
freeBanner = <><Logo/><span className='freeBadge'>{'TEAM EDITION'}</span></>;
|
||||
} else if (license.SkuShortName === LicenseSkus.Entry) {
|
||||
freeBanner = <><Logo/><span className='freeBadge'>{'ENTRY EDITION'}</span></>;
|
||||
}
|
||||
|
||||
let title: React.ReactNode = SiteName;
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as reactRedux from 'react-redux';
|
||||
|
||||
import {mountWithIntl} from 'tests/helpers/intl-test-helper';
|
||||
import mockStore from 'tests/test_store';
|
||||
import {TestHelper} from 'utils/test_helper';
|
||||
|
||||
import MenuStartTrial from './menu_start_trial';
|
||||
|
||||
@@ -16,24 +17,17 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
|
||||
useDispatchMock.mockClear();
|
||||
});
|
||||
|
||||
test('should render null there is no license currently loaded', () => {
|
||||
test('should render TEAM EDITION for unlicensed', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
users: {
|
||||
currentUserId: 'test_id',
|
||||
profiles: {
|
||||
test_id: {
|
||||
id: 'test_id',
|
||||
roles: 'system_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
general: {
|
||||
config: {},
|
||||
license: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'false',
|
||||
IsTrial: 'false',
|
||||
},
|
||||
SkuShortName: '',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -41,27 +35,23 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>);
|
||||
|
||||
expect(wrapper.find('.editionText').exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain('TEAM EDITION');
|
||||
expect(wrapper.text()).toContain('This is the free');
|
||||
});
|
||||
|
||||
test('should render null when there is a license currently loaded', () => {
|
||||
test('should render ENTRY EDITION for Entry license', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
users: {
|
||||
currentUserId: 'test_id',
|
||||
profiles: {
|
||||
test_id: {
|
||||
id: 'test_id',
|
||||
roles: 'system_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
general: {
|
||||
config: {},
|
||||
license: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'true',
|
||||
IsTrial: 'false',
|
||||
},
|
||||
SkuShortName: 'entry',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -69,6 +59,53 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>);
|
||||
expect(wrapper.find('.editionText').exists()).toBe(false);
|
||||
|
||||
expect(wrapper.find('.editionText').exists()).toBe(true);
|
||||
expect(wrapper.text()).toContain('ENTRY EDITION');
|
||||
expect(wrapper.text()).toContain('Entry offers Enterprise Advance capabilities');
|
||||
});
|
||||
|
||||
test('should return null for Professional license', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
users: {
|
||||
currentUserId: 'test_id',
|
||||
},
|
||||
general: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'true',
|
||||
SkuShortName: 'professional',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>);
|
||||
|
||||
expect(wrapper.isEmptyRender()).toBe(true);
|
||||
});
|
||||
|
||||
test('should return null for Enterprise license', () => {
|
||||
const state = {
|
||||
entities: {
|
||||
users: {
|
||||
currentUserId: 'test_id',
|
||||
},
|
||||
general: {
|
||||
license: TestHelper.getLicenseMock({
|
||||
IsLicensed: 'true',
|
||||
SkuShortName: 'enterprise',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
const store = mockStore(state);
|
||||
const dummyDispatch = jest.fn();
|
||||
useDispatchMock.mockReturnValue(dummyDispatch);
|
||||
const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>);
|
||||
|
||||
expect(wrapper.isEmptyRender()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import {getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
|
||||
import ExternalLink from 'components/external_link';
|
||||
|
||||
import {LicenseLinks} from 'utils/constants';
|
||||
import {LicenseLinks, LicenseSkus} from 'utils/constants';
|
||||
|
||||
import './menu_item.scss';
|
||||
|
||||
@@ -39,34 +39,57 @@ const MenuStartTrial = (props: Props): JSX.Element | null => {
|
||||
|
||||
const license = useSelector(getLicense);
|
||||
const isCurrentLicensed = license?.IsLicensed;
|
||||
const skuShortName = license?.SkuShortName;
|
||||
|
||||
if (isCurrentLicensed === 'true') {
|
||||
// If licensed and NOT Entry, return null
|
||||
if (isCurrentLicensed === 'true' && skuShortName !== LicenseSkus.Entry) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Determine badge text and description based on license type
|
||||
const isEntryLicense = isCurrentLicensed === 'true' && skuShortName === LicenseSkus.Entry;
|
||||
const badgeText = isEntryLicense ? 'ENTRY EDITION' : 'TEAM EDITION';
|
||||
|
||||
return (
|
||||
<li
|
||||
className={'MenuStartTrial'}
|
||||
role='menuitem'
|
||||
id={props.id}
|
||||
>
|
||||
<FreeVersionBadge>{'FREE EDITION'}</FreeVersionBadge>
|
||||
<FreeVersionBadge>{badgeText}</FreeVersionBadge>
|
||||
<div className='editionText'>
|
||||
{formatMessage(
|
||||
{
|
||||
id: 'navbar_dropdown.versionText',
|
||||
defaultMessage: 'This is the free <link>unsupported</link> edition of Mattermost.',
|
||||
{isEntryLicense ? (
|
||||
formatMessage({
|
||||
id: 'navbar_dropdown.entryVersionText',
|
||||
defaultMessage: 'Entry offers Enterprise Advance capabilities <link>with limits</link> designed to support evaluation.',
|
||||
},
|
||||
{
|
||||
link: (msg: React.ReactNode) => (
|
||||
<ExternalLink
|
||||
location='menu_start_trial.unsupported-link'
|
||||
href={LicenseLinks.UNSUPPORTED}
|
||||
location='menu_start_trial.entry-link'
|
||||
href={LicenseLinks.ENTRY_LIMITS_INFO}
|
||||
>
|
||||
{msg}
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
})
|
||||
) : (
|
||||
formatMessage(
|
||||
{
|
||||
id: 'navbar_dropdown.versionText',
|
||||
defaultMessage: 'This is the free <link>unsupported</link> edition of Mattermost.',
|
||||
},
|
||||
{
|
||||
link: (msg: React.ReactNode) => (
|
||||
<ExternalLink
|
||||
location='menu_start_trial.unsupported-link'
|
||||
href={LicenseLinks.UNSUPPORTED}
|
||||
>
|
||||
{msg}
|
||||
</ExternalLink>
|
||||
),
|
||||
},
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -4902,6 +4902,7 @@
|
||||
"navbar_dropdown.create.modal.titleAdminPreTrial": "Try unlimited teams with a free trial",
|
||||
"navbar_dropdown.create.modal.titleEndUser": "Multiple teams available in paid plans",
|
||||
"navbar_dropdown.create.tooltip.cloudFreeTrial": "During your trial you are able to create multiple teams. These teams will be archived after your trial.",
|
||||
"navbar_dropdown.entryVersionText": "Entry offers Enterprise Advance capabilities <link>with limits</link> designed to support evaluation.",
|
||||
"navbar_dropdown.help": "Help",
|
||||
"navbar_dropdown.integrations": "Integrations",
|
||||
"navbar_dropdown.invitePeople": "Invite People",
|
||||
|
||||
@@ -1166,6 +1166,7 @@ export const DeveloperLinks = {
|
||||
|
||||
export const LicenseLinks = {
|
||||
CONTACT_SALES: 'https://mattermost.com/contact-sales/',
|
||||
ENTRY_LIMITS_INFO: 'https://mattermost.com/pl/entry',
|
||||
TRIAL_INFO_LINK: 'https://mattermost.com/trial',
|
||||
EMBARGOED_COUNTRIES: 'https://mattermost.com/pl/limitations-for-embargoed-countries',
|
||||
SOFTWARE_SERVICES_LICENSE_AGREEMENT: 'https://mattermost.com/pl/software-and-services-license-agreement',
|
||||
|
||||
Reference in New Issue
Block a user