* 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)
Этот коммит содержится в:
enahum
2016-12-19 10:05:46 -03:00
коммит произвёл Joram Wilander
родитель 3ce2ce9dc8
Коммит 999d1553e1
50 изменённых файлов: 1139 добавлений и 183 удалений

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

@@ -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'])
};

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

@@ -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>
);
}
}