PLT-4167 Team Sidebar (#4569)
* PLT-4167 Team Sidebar * Address feedback from PM * change route from my_members to members * bug fixes * Updating styles for teams sidebar (#4681) * Added PM changes * Fix corner cases * Addressing feedback * use two different endpoints * Bug fixes * Rename model and client functions, using preferences to store last team and channel viewed * Fix mobile notification count and closing the team sidebar * unit test, fixed bad merge and retrieve from cached when available * bug fixes * use id for last channel in preferences, query optimization * Updating multi team css (#4830)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
3ce2ce9dc8
Коммит
999d1553e1
84
webapp/components/team_sidebar/components/team_button.jsx
Обычный файл
84
webapp/components/team_sidebar/components/team_button.jsx
Обычный файл
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import Constants from 'utils/constants.jsx';
|
||||
|
||||
import React from 'react';
|
||||
import {Link} from 'react-router/es6';
|
||||
import {Tooltip, OverlayTrigger} from 'react-bootstrap';
|
||||
|
||||
export default class TeamButton extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleDisabled = this.handleDisabled.bind(this);
|
||||
}
|
||||
|
||||
handleDisabled(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
render() {
|
||||
let teamClass = this.props.active ? 'active' : '';
|
||||
const disabled = this.props.disabled ? 'team-disabled' : '';
|
||||
const handleClick = (this.props.active || this.props.disabled) ? this.handleDisabled : null;
|
||||
let badge;
|
||||
|
||||
if (!teamClass) {
|
||||
teamClass = this.props.unread ? 'unread' : '';
|
||||
|
||||
if (this.props.mentions) {
|
||||
badge = (
|
||||
<span className='badge pull-right small'>{this.props.mentions}</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`team-container ${teamClass}`}
|
||||
>
|
||||
<Link
|
||||
className={disabled}
|
||||
to={this.props.url}
|
||||
onClick={handleClick}
|
||||
>
|
||||
<OverlayTrigger
|
||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||
placement={this.props.placement}
|
||||
overlay={
|
||||
<Tooltip id={`tooltip-${this.props.url}`}>
|
||||
{this.props.tip}
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
<div className='team-btn'>
|
||||
{badge}
|
||||
{this.props.contents}
|
||||
</div>
|
||||
</OverlayTrigger>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TeamButton.defaultProps = {
|
||||
tip: '',
|
||||
placement: 'right',
|
||||
active: false,
|
||||
disabled: false,
|
||||
unread: false,
|
||||
mentions: 0
|
||||
};
|
||||
|
||||
TeamButton.propTypes = {
|
||||
url: React.PropTypes.string.isRequired,
|
||||
contents: React.PropTypes.node.isRequired,
|
||||
tip: React.PropTypes.node,
|
||||
active: React.PropTypes.bool,
|
||||
disabled: React.PropTypes.bool,
|
||||
unread: React.PropTypes.bool,
|
||||
mentions: React.PropTypes.number,
|
||||
placement: React.PropTypes.oneOf(['left', 'right', 'top', 'bottom'])
|
||||
};
|
||||
169
webapp/components/team_sidebar/team_sidebar_controller.jsx
Обычный файл
169
webapp/components/team_sidebar/team_sidebar_controller.jsx
Обычный файл
@@ -0,0 +1,169 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import TeamButton from './components/team_button.jsx';
|
||||
|
||||
import TeamStore from 'stores/team_store.jsx';
|
||||
import UserStore from 'stores/user_store.jsx';
|
||||
|
||||
import * as AsyncClient from 'utils/async_client.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
|
||||
import $ from 'jquery';
|
||||
import React from 'react';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
export default class TeamSidebar extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.getStateFromStores = this.getStateFromStores.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.handleResize = this.handleResize.bind(this);
|
||||
this.setStyles = this.setStyles.bind(this);
|
||||
|
||||
this.state = this.getStateFromStores();
|
||||
}
|
||||
|
||||
getStateFromStores() {
|
||||
const teamMembers = TeamStore.getMyTeamMembers();
|
||||
const currentTeamId = TeamStore.getCurrentId();
|
||||
|
||||
return {
|
||||
teams: TeamStore.getAll(),
|
||||
teamListings: TeamStore.getTeamListings(),
|
||||
teamMembers,
|
||||
currentTeamId,
|
||||
show: teamMembers && teamMembers.length > 1
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
TeamStore.addChangeListener(this.onChange);
|
||||
TeamStore.addUnreadChangeListener(this.onChange);
|
||||
AsyncClient.getAllTeamListings();
|
||||
this.setStyles();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
TeamStore.removeChangeListener(this.onChange);
|
||||
TeamStore.removeUnreadChangeListener(this.onChange);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
$('.team-wrapper').perfectScrollbar();
|
||||
|
||||
// reset the scrollbar upon switching teams
|
||||
if (this.state.currentTeam !== prevState.currentTeam) {
|
||||
this.refs.container.scrollTop = 0;
|
||||
$('.team-wrapper').perfectScrollbar('update');
|
||||
}
|
||||
}
|
||||
|
||||
onChange() {
|
||||
this.setState(this.getStateFromStores());
|
||||
this.setStyles();
|
||||
}
|
||||
|
||||
handleResize() {
|
||||
const teamMembers = this.state.teamMembers;
|
||||
this.setState({show: teamMembers && teamMembers.length > 1});
|
||||
this.setStyles();
|
||||
}
|
||||
|
||||
setStyles() {
|
||||
const root = document.querySelector('#root');
|
||||
|
||||
if (this.state.show) {
|
||||
root.classList.add('multi-teams');
|
||||
} else {
|
||||
root.classList.remove('multi-teams');
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.show) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const myTeams = [];
|
||||
const isSystemAdmin = Utils.isSystemAdmin(UserStore.getCurrentUser().roles);
|
||||
const isAlreadyMember = new Map();
|
||||
let moreTeams = false;
|
||||
|
||||
for (const index in this.state.teamMembers) {
|
||||
if (this.state.teamMembers.hasOwnProperty(index)) {
|
||||
const teamMember = this.state.teamMembers[index];
|
||||
const teamId = teamMember.team_id;
|
||||
myTeams.push(Object.assign({
|
||||
unread: teamMember.msg_count > 0,
|
||||
mentions: teamMember.mention_count
|
||||
}, this.state.teams[teamId]));
|
||||
isAlreadyMember[teamId] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const id in this.state.teamListings) {
|
||||
if (this.state.teamListings.hasOwnProperty(id) && !isAlreadyMember[id]) {
|
||||
moreTeams = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const teams = myTeams.
|
||||
sort((a, b) => a.display_name.localeCompare(b.display_name)).
|
||||
map((team) => {
|
||||
return (
|
||||
<TeamButton
|
||||
key={'switch_team_' + team.name}
|
||||
url={`/${team.name}`}
|
||||
tip={team.display_name}
|
||||
active={team.id === this.state.currentTeamId}
|
||||
contents={team.display_name.substring(0, 1).toUpperCase()}
|
||||
unread={team.unread}
|
||||
mentions={team.mentions}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
if (moreTeams) {
|
||||
teams.push(
|
||||
<TeamButton
|
||||
key='more_teams'
|
||||
url='/select_team'
|
||||
tip={
|
||||
<FormattedMessage
|
||||
id='team_sidebar.join'
|
||||
defaultMessage='Other teams you can join.'
|
||||
/>
|
||||
}
|
||||
contents={<i className='fa fa-plus'/>}
|
||||
/>
|
||||
);
|
||||
} else if (global.window.mm_config.EnableTeamCreation === 'true' || isSystemAdmin) {
|
||||
teams.push(
|
||||
<TeamButton
|
||||
key='more_teams'
|
||||
url='/create_team'
|
||||
tip={
|
||||
<FormattedMessage
|
||||
id='navbar_dropdown.create'
|
||||
defaultMessage='Create a New Team'
|
||||
/>
|
||||
}
|
||||
contents={<i className='fa fa-plus'/>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='team-sidebar'>
|
||||
<div className='team-wrapper'>
|
||||
{teams}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user