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
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8f95656c8f
Коммит
f4a3a2ec07
@@ -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/';
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user