Adding unsupported text into the team/e0 edition menu (#27038)

* Adding unsupported text into the team/e0 edition menu

* Fixing CI

* Addressing PR review comments

* Removing start trial from the product menu

* Fixing tests

* Updating i18n
Этот коммит содержится в:
Jesús Espino
2024-05-22 21:24:38 +02:00
коммит произвёл GitHub
родитель 8f95656c8f
Коммит f4a3a2ec07
5 изменённых файлов: 38 добавлений и 282 удалений

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

@@ -333,13 +333,15 @@
} }
} }
.start_trial_content { .editionText {
position: relative; position: relative;
width: 100%; width: 100%;
} a {
color: var(--link-color);
.editionName { &:hover {
text-transform: capitalize; background: none;
}
}
} }
} }
} }

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

@@ -4,8 +4,6 @@
import React from 'react'; import React from 'react';
import * as reactRedux from 'react-redux'; import * as reactRedux from 'react-redux';
import {Permissions} from 'mattermost-redux/constants';
import {mountWithIntl} from 'tests/helpers/intl-test-helper'; import {mountWithIntl} from 'tests/helpers/intl-test-helper';
import mockStore from 'tests/test_store'; import mockStore from 'tests/test_store';
@@ -18,7 +16,7 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
useDispatchMock.mockClear(); useDispatchMock.mockClear();
}); });
test('should render when no trial license has ever been used and there is no license currently loaded', () => { test('should render null there is no license currently loaded', () => {
const state = { const state = {
entities: { entities: {
users: { users: {
@@ -31,99 +29,22 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
}, },
}, },
general: { general: {
config: { config: {},
EnableTutorial: 'true',
BuildEnterpriseReady: 'true',
},
license: {
IsLicensed: 'false',
},
},
admin: {
prevTrialLicense: {
IsLicensed: 'false',
},
},
roles: {
roles: {
system_user: {
permissions: [Permissions.SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE],
},
},
},
preferences: {
myPreferences: {
'tutorial_step-test_id': {
user_id: 'test_id',
category: 'tutorial_step',
name: 'test_id',
value: '6',
},
},
},
},
};
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.find('button').exists()).toEqual(true);
});
test('should render null when prevTrialLicense was used and there is no license currently loaded', () => {
const state = {
entities: {
users: {
currentUserId: 'test_id',
profiles: {
test_id: {
id: 'test_id',
roles: 'system_user',
},
},
},
general: {
config: {
EnableTutorial: 'true',
BuildEnterpriseReady: 'true',
},
license: { license: {
IsLicensed: 'false', IsLicensed: 'false',
IsTrial: 'false', IsTrial: 'false',
}, },
}, },
admin: {
prevTrialLicense: {
IsLicensed: 'true',
},
},
roles: {
roles: {
system_user: {
permissions: [Permissions.SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE],
},
},
},
preferences: {
myPreferences: {
'tutorial_step-test_id': {
user_id: 'test_id',
category: 'tutorial_step',
name: 'test_id',
value: '6',
},
},
},
}, },
}; };
const store = mockStore(state); const store = mockStore(state);
const dummyDispatch = jest.fn(); const dummyDispatch = jest.fn();
useDispatchMock.mockReturnValue(dummyDispatch); useDispatchMock.mockReturnValue(dummyDispatch);
const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>); const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>);
expect(wrapper.find('button').exists()).toEqual(false); expect(wrapper.find('.editionText').exists()).toBe(true);
}); });
test('should render null when no trial license has ever been used but there is a license currently loaded', () => { test('should render null when there is a license currently loaded', () => {
const state = { const state = {
entities: { entities: {
users: { users: {
@@ -136,151 +57,18 @@ describe('components/widgets/menu/menu_items/menu_start_trial', () => {
}, },
}, },
general: { general: {
config: { config: {},
EnableTutorial: 'true',
BuildEnterpriseReady: 'true',
},
license: { license: {
IsLicensed: 'true', IsLicensed: 'true',
IsTrial: 'false', IsTrial: 'false',
}, },
}, },
admin: {
prevTrialLicense: {
IsLicensed: 'false',
},
},
roles: {
roles: {
system_user: {
permissions: [Permissions.SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE],
},
},
},
preferences: {
myPreferences: {
'tutorial_step-test_id': {
user_id: 'test_id',
category: 'tutorial_step',
name: 'test_id',
value: '6',
},
},
},
}, },
}; };
const store = mockStore(state); const store = mockStore(state);
const dummyDispatch = jest.fn(); const dummyDispatch = jest.fn();
useDispatchMock.mockReturnValue(dummyDispatch); useDispatchMock.mockReturnValue(dummyDispatch);
const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>); const wrapper = mountWithIntl(<reactRedux.Provider store={store}><MenuStartTrial id='startTrial'/></reactRedux.Provider>);
expect(wrapper.find('button').exists()).toEqual(false); expect(wrapper.find('.editionText').exists()).toBe(false);
});
test('should render null when is current licensed but is trial and you have no permissions to load the trial', () => {
const state = {
entities: {
users: {
currentUserId: 'test_id',
profiles: {
test_id: {
id: 'test_id',
roles: 'system_user',
},
},
},
general: {
config: {
EnableTutorial: 'true',
BuildEnterpriseReady: 'true',
},
license: {
IsLicensed: 'true',
IsTrial: 'true',
},
},
admin: {
prevTrialLicense: {
IsLicensed: 'false',
},
},
roles: {
roles: {
system_user: {
permissions: [],
},
},
},
preferences: {
myPreferences: {
'tutorial_step-test_id': {
user_id: 'test_id',
category: 'tutorial_step',
name: 'test_id',
value: '6',
},
},
},
},
};
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.find('button').exists()).toEqual(false);
});
test('should render menu option that open the start trial modal when has no license and no previous license and you have permissions to load the trial', () => {
const state = {
entities: {
users: {
currentUserId: 'test_id',
profiles: {
test_id: {
id: 'test_id',
roles: 'system_user',
},
},
},
general: {
config: {
EnableTutorial: 'true',
BuildEnterpriseReady: 'true',
},
license: {
IsLicensed: 'false',
IsTrial: 'false',
},
},
admin: {
prevTrialLicense: {
IsLicensed: 'false',
},
},
roles: {
roles: {
system_user: {
permissions: [Permissions.SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE],
},
},
},
preferences: {
myPreferences: {
'tutorial_step-test_id': {
user_id: 'test_id',
category: 'tutorial_step',
name: 'test_id',
value: '6',
},
},
},
},
};
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.find('button').exists()).toEqual(true);
expect(wrapper.find('div.start_trial_content').text()).toEqual('This is the free edition of Mattermost, ideal for evaluation and small teams.');
expect(wrapper.find('button').text()).toEqual('Start an Enterprise trial');
}); });
}); });

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

@@ -1,29 +1,19 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React, {useEffect} from 'react'; import React from 'react';
import {useIntl} from 'react-intl'; import {useIntl} from 'react-intl';
import {useDispatch, useSelector} from 'react-redux'; import {useSelector} from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import type {GlobalState} from '@mattermost/types/store'; import {getLicense} from 'mattermost-redux/selectors/entities/general';
import {getPrevTrialLicense} from 'mattermost-redux/actions/admin'; import ExternalLink from 'components/external_link';
import {Permissions} from 'mattermost-redux/constants';
import {getLicense, getConfig} from 'mattermost-redux/selectors/entities/general';
import {haveISystemPermission} from 'mattermost-redux/selectors/entities/roles';
import {trackEvent} from 'actions/telemetry_actions'; import {LicenseLinks} from 'utils/constants';
import {openModal} from 'actions/views/modals';
import {makeAsyncComponent} from 'components/async_load';
import {ModalIdentifiers, TELEMETRY_CATEGORIES} from 'utils/constants';
import './menu_item.scss'; import './menu_item.scss';
const LearnMoreTrialModal = makeAsyncComponent('LearnMoreTrialModal', React.lazy(() => import('components/learn_more_trial_modal/learn_more_trial_modal')));
const FreeVersionBadge = styled.div` const FreeVersionBadge = styled.div`
position: relative; position: relative;
top: 1px; top: 1px;
@@ -46,37 +36,14 @@ type Props = {
const MenuStartTrial = (props: Props): JSX.Element | null => { const MenuStartTrial = (props: Props): JSX.Element | null => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const dispatch = useDispatch();
useEffect(() => {
dispatch(getPrevTrialLicense());
}, []);
const config = useSelector(getConfig);
const isE0 = config.BuildEnterpriseReady === 'true';
const hasPermissionForStartTrial = useSelector((state: GlobalState) => haveISystemPermission(state, {permission: Permissions.SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE}));
const openLearnMoreTrialModal = () => {
trackEvent(
TELEMETRY_CATEGORIES.SELF_HOSTED_START_TRIAL_MODAL,
'open_learn_more_trial_modal',
);
dispatch(openModal({
modalId: ModalIdentifiers.LEARN_MORE_TRIAL_MODAL,
dialogType: LearnMoreTrialModal,
}));
};
const prevTrialLicense = useSelector((state: GlobalState) => state.entities.admin.prevTrialLicense);
const license = useSelector(getLicense); const license = useSelector(getLicense);
const isPrevLicensed = prevTrialLicense?.IsLicensed;
const isCurrentLicensed = license?.IsLicensed; const isCurrentLicensed = license?.IsLicensed;
if (isCurrentLicensed === 'true') { if (isCurrentLicensed === 'true') {
return null; return null;
} }
const showTrialButton = isCurrentLicensed === 'false' && isPrevLicensed === 'false' && hasPermissionForStartTrial && isE0;
return ( return (
<li <li
className={'MenuStartTrial'} className={'MenuStartTrial'}
@@ -84,24 +51,24 @@ const MenuStartTrial = (props: Props): JSX.Element | null => {
id={props.id} id={props.id}
> >
<FreeVersionBadge>{'FREE EDITION'}</FreeVersionBadge> <FreeVersionBadge>{'FREE EDITION'}</FreeVersionBadge>
{isE0 && <div className='editionText'>
<div className='start_trial_content'> {formatMessage(
{formatMessage({ {
id: 'navbar_dropdown.versionTextE0', id: 'navbar_dropdown.versionText',
defaultMessage: 'This is the free edition of Mattermost, ideal for evaluation and small teams.', defaultMessage: 'This is the free <link>unsupported</link> edition of Mattermost.',
})} },
</div>} {
{!isE0 && link: (msg: React.ReactNode) => (
<div className='start_trial_content'> <ExternalLink
{formatMessage({ location='menu_start_trial.unsupported-link'
id: 'navbar_dropdown.versionTextTeamEdition', href={LicenseLinks.UNSUPPORTED}
defaultMessage: 'This is the free open source edition of Mattermost, ideal for evaluation and small teams.', >
})} {msg}
</div>} </ExternalLink>
{showTrialButton && ),
<button onClick={openLearnMoreTrialModal}> },
{formatMessage({id: 'navbar_dropdown.startAnEnterpriseTrial', defaultMessage: 'Start an Enterprise trial'})} )}
</button>} </div>
</li> </li>
); );
}; };

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

@@ -4236,7 +4236,6 @@
"navbar_dropdown.nativeApps": "Download Apps", "navbar_dropdown.nativeApps": "Download Apps",
"navbar_dropdown.profileSettings": "Profile", "navbar_dropdown.profileSettings": "Profile",
"navbar_dropdown.report": "Report a Problem", "navbar_dropdown.report": "Report a Problem",
"navbar_dropdown.startAnEnterpriseTrial": "Start an Enterprise trial",
"navbar_dropdown.switchTo": "Switch to ", "navbar_dropdown.switchTo": "Switch to ",
"navbar_dropdown.teamSettings": "Team Settings", "navbar_dropdown.teamSettings": "Team Settings",
"navbar_dropdown.userGroups": "User Groups", "navbar_dropdown.userGroups": "User Groups",
@@ -4247,8 +4246,7 @@
"navbar_dropdown.userGroups.modal.titleAdminPreTrial": "Try unlimited user groups with a free trial", "navbar_dropdown.userGroups.modal.titleAdminPreTrial": "Try unlimited user groups with a free trial",
"navbar_dropdown.userGroups.modal.titleEndUser": "User groups available in paid plans", "navbar_dropdown.userGroups.modal.titleEndUser": "User groups available in paid plans",
"navbar_dropdown.userGroups.tooltip.cloudFreeTrial": "During your trial you are able to create user groups. These user groups will be archived after your trial.", "navbar_dropdown.userGroups.tooltip.cloudFreeTrial": "During your trial you are able to create user groups. These user groups will be archived after your trial.",
"navbar_dropdown.versionTextE0": "This is the free edition of Mattermost, ideal for evaluation and small teams.", "navbar_dropdown.versionText": "This is the free <link>unsupported</link> edition of Mattermost.",
"navbar_dropdown.versionTextTeamEdition": "This is the free open source edition of Mattermost, ideal for evaluation and small teams.",
"navbar_dropdown.viewMembers": "View Members", "navbar_dropdown.viewMembers": "View Members",
"navbar.addGroups": "Add Groups", "navbar.addGroups": "Add Groups",
"navbar.addMembers": "Add Members", "navbar.addMembers": "Add Members",

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

@@ -1114,6 +1114,7 @@ export const LicenseLinks = {
EMBARGOED_COUNTRIES: 'https://mattermost.com/pl/limitations-for-embargoed-countries', EMBARGOED_COUNTRIES: 'https://mattermost.com/pl/limitations-for-embargoed-countries',
SOFTWARE_SERVICES_LICENSE_AGREEMENT: 'https://mattermost.com/pl/software-and-services-license-agreement', SOFTWARE_SERVICES_LICENSE_AGREEMENT: 'https://mattermost.com/pl/software-and-services-license-agreement',
SOFTWARE_SERVICES_LICENSE_AGREEMENT_TEXT: 'Software Services and License Agreement', SOFTWARE_SERVICES_LICENSE_AGREEMENT_TEXT: 'Software Services and License Agreement',
UNSUPPORTED: 'https://mattermost.com/pricing/',
}; };
export const MattermostLink = 'https://mattermost.com/'; export const MattermostLink = 'https://mattermost.com/';