[GH-25022]: Add Academy links to Teams training (#25150)

* feat: add link to teams dropdown menu

* fix: refactor link to separate component and update styles

* feat: add academy link to team's join page and settings modal

* fix: i18n and update test snapshots

* fix link styles & update test snapshot

* add state for unit tests

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>
This commit is contained in:
Umar Abid 2023-11-23 02:36:52 +05:00 committed by GitHub
parent 5862213fd4
commit 70e3a01f2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 271 additions and 57 deletions

View File

@ -227,6 +227,13 @@ exports[`components/Menu should match snapshot with guest access disabled and no
to="/create_team"
/>
</Connect(SystemPermissionGate)>
<Memo(MenuGroup)>
<div
className="MainMenu_dropdown-link"
>
<LearnAboutTeamsLink />
</div>
</Memo(MenuGroup)>
</Memo(MenuGroup)>
<Memo(MenuGroup) />
</Menu>
@ -428,6 +435,13 @@ exports[`components/Menu should match snapshot with id 1`] = `
to="/create_team"
/>
</Connect(SystemPermissionGate)>
<Memo(MenuGroup)>
<div
className="MainMenu_dropdown-link"
>
<LearnAboutTeamsLink />
</div>
</Memo(MenuGroup)>
</Memo(MenuGroup)>
<Memo(MenuGroup) />
</Menu>
@ -628,6 +642,13 @@ exports[`components/Menu should match snapshot with most of the thing disabled 1
to="/create_team"
/>
</Connect(SystemPermissionGate)>
<Memo(MenuGroup)>
<div
className="MainMenu_dropdown-link"
>
<LearnAboutTeamsLink />
</div>
</Memo(MenuGroup)>
</Memo(MenuGroup)>
<Memo(MenuGroup) />
</Menu>
@ -1241,6 +1262,13 @@ exports[`components/Menu should match snapshot with most of the thing enabled 1`
to="/create_team"
/>
</Connect(SystemPermissionGate)>
<Memo(MenuGroup)>
<div
className="MainMenu_dropdown-link"
>
<LearnAboutTeamsLink />
</div>
</Memo(MenuGroup)>
</Memo(MenuGroup)>
<Memo(MenuGroup) />
</Menu>
@ -1856,6 +1884,13 @@ exports[`components/Menu should match snapshot with plugins 1`] = `
to="/create_team"
/>
</Connect(SystemPermissionGate)>
<Memo(MenuGroup)>
<div
className="MainMenu_dropdown-link"
>
<LearnAboutTeamsLink />
</div>
</Memo(MenuGroup)>
</Memo(MenuGroup)>
<Memo(MenuGroup)>
<MenuItemAction

View File

@ -0,0 +1,40 @@
.LearnAboutTeamsLink {
>span {
width: 100%;
a {
display: flex;
align-items: center;
padding: 6px 18px;
column-gap: 10px;
&:hover,
&:focus,
&:active {
text-decoration: none;
}
>i {
display: inline-flex !important;
padding: 3px;
background-color: hsla(221, 77%, 48%, 0.08);
border-radius: 50%;
font-size: 14px !important;
&::before {
margin: 0;
}
}
span {
font-size: 12px;
font-weight: 600;
line-height: 16px;
&:hover {
text-decoration: underline;
}
}
}
}
}

View File

@ -0,0 +1,30 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {FormattedMessage} from 'react-intl';
import ExternalLink from 'components/external_link';
import './learn_about_teams_link.scss';
const LearnAboutTeamsLink = () => {
return (
<div className='LearnAboutTeamsLink'>
<FormattedMessage
id='learn_about_teams'
defaultMessage='<a>Learn about teams</a>'
values={{
a: (chunks) => (
<ExternalLink
href='https://mattermost.com/pl/mattermost-academy-team-training'
>
<i className='icon icon-lightbulb-outline'/>
<span>{chunks}</span>
</ExternalLink>
),
}}
/>
</div>
);
};
export default LearnAboutTeamsLink;

View File

@ -0,0 +1,13 @@
.MainMenu_dropdown-link {
a {
&:focus,
&:hover,
&:active {
background-color: rgba(63, 67, 80, 0.1);
}
i + span:hover {
text-decoration: none;
}
}
}

View File

@ -82,6 +82,12 @@ describe('components/Menu', () => {
channels: {
myMembers: [],
},
general: {
config: {},
license: {
Cloud: 'false',
},
},
teams: {
currentTeamId: 'team-id',
myMembers: {

View File

@ -35,6 +35,9 @@ import * as UserAgent from 'utils/user_agent';
import type {ModalData} from 'types/actions';
import type {PluginComponent} from 'types/store/plugins';
import LearnAboutTeamsLink from './learn_about_teams_link';
import './main_menu.scss';
export type Props = {
mobile: boolean;
id?: string;
@ -522,6 +525,11 @@ export class MainMenu extends React.PureComponent<Props> {
)}
/>
</SystemPermissionGate>
<Menu.Group>
<div className='MainMenu_dropdown-link'>
<LearnAboutTeamsLink/>
</div>
</Menu.Group>
</Menu.Group>
<Menu.Group>
{pluginItems}

View File

@ -24,12 +24,17 @@ exports[`components/select_team/SelectTeam should match snapshot 1`] = `
className="signup__content"
id="teamsYouCanJoinContent"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<div
className="SelectTeam__sub-header"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<LearnAboutTeamsLink />
</div>
<InfiniteScroll
bufferValue={280}
callBack={[Function]}
@ -136,12 +141,17 @@ exports[`components/select_team/SelectTeam should match snapshot, on create team
className="signup__content"
id="teamsYouCanJoinContent"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<div
className="SelectTeam__sub-header"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<LearnAboutTeamsLink />
</div>
<InfiniteScroll
bufferValue={280}
callBack={[Function]}
@ -385,12 +395,17 @@ exports[`components/select_team/SelectTeam should match snapshot, on no joinable
className="signup__content"
id="teamsYouCanJoinContent"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<div
className="SelectTeam__sub-header"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<LearnAboutTeamsLink />
</div>
<InfiniteScroll
bufferValue={280}
callBack={[Function]}
@ -609,12 +624,17 @@ exports[`components/select_team/SelectTeam should match snapshot, on no joinable
className="signup__content"
id="teamsYouCanJoinContent"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<div
className="SelectTeam__sub-header"
>
<h4>
<MemoizedFormattedMessage
defaultMessage="Teams you can join: "
id="signup_team.join_open"
/>
</h4>
<LearnAboutTeamsLink />
</div>
<InfiniteScroll
bufferValue={280}
callBack={[Function]}

View File

@ -0,0 +1,18 @@
.SelectTeam__sub-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 10px;
margin-bottom: 24px;
>h4 {
margin: 0;
span {
display: inline-flex;
font-size: 20px;
font-weight: 600;
line-height: 28px;
}
}
}

View File

@ -20,6 +20,7 @@ import InfiniteScroll from 'components/common/infinite_scroll';
import SiteNameAndDescription from 'components/common/site_name_and_description';
import FormattedMarkdownMessage from 'components/formatted_markdown_message';
import LoadingScreen from 'components/loading_screen';
import LearnAboutTeamsLink from 'components/main_menu/learn_about_teams_link';
import SystemPermissionGate from 'components/permissions_gates/system_permission_gate';
import LogoutIcon from 'components/widgets/icons/fa_logout_icon';
@ -28,6 +29,7 @@ import Constants from 'utils/constants';
import * as UserAgent from 'utils/user_agent';
import SelectTeamItem from './components/select_team_item';
import './select_team.scss';
export const TEAMS_PER_PAGE = 30;
const TEAM_MEMBERSHIP_DENIAL_ERROR_ID = 'api.team.add_members.user_denied';
@ -276,12 +278,15 @@ export default class SelectTeam extends React.PureComponent<Props, State> {
id='teamsYouCanJoinContent'
className='signup__content'
>
<h4>
<FormattedMessage
id='signup_team.join_open'
defaultMessage='Teams you can join: '
/>
</h4>
<div className='SelectTeam__sub-header'>
<h4>
<FormattedMessage
id='signup_team.join_open'
defaultMessage='Teams you can join: '
/>
</h4>
<LearnAboutTeamsLink/>
</div>
<InfiniteScroll
callBack={this.fetchMoreTeams}
styleClass='signup-team-all'

View File

@ -40,14 +40,17 @@ exports[`components/TeamSettings hide invite code if no permissions for team inv
<div
className="user-settings"
>
<h3
className="tab-header"
<div
className="GeneralTab__header"
>
<MemoizedFormattedMessage
defaultMessage="General Settings"
id="general_tab.title"
/>
</h3>
<h3>
<MemoizedFormattedMessage
defaultMessage="General Settings"
id="general_tab.title"
/>
</h3>
<LearnAboutTeamsLink />
</div>
<div
className="divider-dark first"
/>
@ -165,14 +168,17 @@ exports[`components/TeamSettings hide invite code if no permissions for team inv
<div
className="user-settings"
>
<h3
className="tab-header"
<div
className="GeneralTab__header"
>
<MemoizedFormattedMessage
defaultMessage="General Settings"
id="general_tab.title"
/>
</h3>
<h3>
<MemoizedFormattedMessage
defaultMessage="General Settings"
id="general_tab.title"
/>
</h3>
<LearnAboutTeamsLink />
</div>
<div
className="divider-dark first"
/>
@ -284,14 +290,17 @@ exports[`components/TeamSettings should match snapshot when team is group constr
<div
className="user-settings"
>
<h3
className="tab-header"
<div
className="GeneralTab__header"
>
<MemoizedFormattedMessage
defaultMessage="General Settings"
id="general_tab.title"
/>
</h3>
<h3>
<MemoizedFormattedMessage
defaultMessage="General Settings"
id="general_tab.title"
/>
</h3>
<LearnAboutTeamsLink />
</div>
<div
className="divider-dark first"
/>

View File

@ -0,0 +1,17 @@
.GeneralTab__header {
display: flex;
align-items: center;
justify-content: space-between;
margin: 20px 0;
>h3 {
margin: 0;
span {
display: inline-flex;
font-size: 20px;
font-weight: 600;
line-height: 28px;
}
}
}

View File

@ -7,6 +7,7 @@ import {FormattedMessage, FormattedDate, injectIntl, type WrappedComponentProps}
import type {Team} from '@mattermost/types/teams';
import LearnAboutTeamsLink from 'components/main_menu/learn_about_teams_link';
import SettingItemMax from 'components/setting_item_max';
import SettingItemMin from 'components/setting_item_min';
import SettingPicture from 'components/setting_picture';
@ -18,6 +19,7 @@ import {imageURLForTeam, localizeMessage, moveCursorToEnd} from 'utils/utils';
import OpenInvite from './open_invite';
import type {PropsFromRedux, OwnProps} from '.';
import './team_general_tab.scss';
const ACCEPTED_TEAM_IMAGE_TYPES = ['image/jpeg', 'image/png', 'image/bmp'];
@ -654,12 +656,15 @@ export class GeneralTab extends React.PureComponent<Props, State> {
</h4>
</div>
<div className='user-settings'>
<h3 className='tab-header'>
<FormattedMessage
id='general_tab.title'
defaultMessage='General Settings'
/>
</h3>
<div className='GeneralTab__header'>
<h3>
<FormattedMessage
id='general_tab.title'
defaultMessage='General Settings'
/>
</h3>
<LearnAboutTeamsLink/>
</div>
<div className='divider-dark first'/>
{nameSection}
<div className='divider-light'/>

View File

@ -3903,6 +3903,7 @@
"last_users_message.others": "{numOthers} others ",
"last_users_message.removed_from_channel.type": "were **removed from the channel**.",
"last_users_message.removed_from_team.type": "were **removed from the team**.",
"learn_about_teams": "<a>Learn about teams</a>",
"learn_more_about_trial.modal.ldapDescription": "Use AD/LDAP groups to organize and apply actions to multiple users at once. Manage team and channel memberships, permissions and more.",
"learn_more_about_trial.modal.ldapTitle": "Synchronize your Active Directory/LDAP groups",
"learn_more_about_trial.modal.systemConsoleDescription": "Use System Roles to give designated users read and/or write access to select sections of System Console.",

View File

@ -631,6 +631,13 @@ exports[`plugins/MainMenuActions should match snapshot in web view 1`] = `
to="/create_team"
/>
</Connect(SystemPermissionGate)>
<Memo(MenuGroup)>
<div
className="MainMenu_dropdown-link"
>
<LearnAboutTeamsLink />
</div>
</Memo(MenuGroup)>
</Memo(MenuGroup)>
<Memo(MenuGroup)>
<MenuItemAction