diff options
Diffstat (limited to 'webapp/components')
19 files changed, 410 insertions, 153 deletions
diff --git a/webapp/components/admin_console/admin_navbar_dropdown.jsx b/webapp/components/admin_console/admin_navbar_dropdown.jsx index f20451b4b..5b65868e9 100644 --- a/webapp/components/admin_console/admin_navbar_dropdown.jsx +++ b/webapp/components/admin_console/admin_navbar_dropdown.jsx @@ -50,13 +50,14 @@ export default class AdminNavbarDropdown extends React.Component { } render() { - var teams = []; + const teams = []; + let switchTeams; if (this.state.teamMembers && this.state.teamMembers.length > 0) { - for (var index in this.state.teamMembers) { + for (const index in this.state.teamMembers) { if (this.state.teamMembers.hasOwnProperty(index)) { - var teamMember = this.state.teamMembers[index]; - var team = this.state.teams[teamMember.team_id]; + const teamMember = this.state.teamMembers[index]; + const team = this.state.teams[teamMember.team_id]; teams.push( <li key={'team_' + team.name}> <Link @@ -79,6 +80,20 @@ export default class AdminNavbarDropdown extends React.Component { className='divider' /> ); + } else { + switchTeams = ( + <li> + <Link + to={'/select_team'} + > + <i className='fa fa-exchange'/> + <FormattedMessage + id='admin.nav.switch' + defaultMessage='Team Selection' + /> + </Link> + </li> + ); } return ( @@ -104,17 +119,7 @@ export default class AdminNavbarDropdown extends React.Component { role='menu' > {teams} - <li> - <Link - to={'/select_team'} - > - <i className='fa fa-exchange'/> - <FormattedMessage - id='admin.nav.switch' - defaultMessage='Team Selection' - /> - </Link> - </li> + {switchTeams} <li key='teamDiv' className='divider' diff --git a/webapp/components/create_team/create_team_controller.jsx b/webapp/components/create_team/create_team_controller.jsx index 77a7f659f..84b890e26 100644 --- a/webapp/components/create_team/create_team_controller.jsx +++ b/webapp/components/create_team/create_team_controller.jsx @@ -2,6 +2,8 @@ // See License.txt for license information. import ErrorBar from 'components/error_bar.jsx'; +import ChannelStore from 'stores/channel_store.jsx'; +import TeamStore from 'stores/team_store.jsx'; import {FormattedMessage} from 'react-intl'; import {browserHistory, Link} from 'react-router/es6'; @@ -47,11 +49,21 @@ export default class CreateTeamController extends React.Component { ); } + let url = '/select_team'; + const team = TeamStore.getCurrent(); + const channel = ChannelStore.getCurrent(); + if (team) { + url = `/${team.name}`; + if (channel) { + url += `/channels/${channel.name}`; + } + } + return ( <div> <ErrorBar/> <div className='signup-header'> - <Link to='/select_team'> + <Link to={url}> <span className='fa fa-chevron-left'/> <FormattedMessage id='web.header.back' diff --git a/webapp/components/login/login_controller.jsx b/webapp/components/login/login_controller.jsx index 4ed6b67e8..726853cf2 100644 --- a/webapp/components/login/login_controller.jsx +++ b/webapp/components/login/login_controller.jsx @@ -54,7 +54,7 @@ export default class LoginController extends React.Component { document.title = global.window.mm_config.SiteName; if (UserStore.getCurrentUser()) { - browserHistory.push('/select_team'); + GlobalActions.redirectUserToDefaultTeam(); } AsyncClient.checkVersion(); @@ -205,7 +205,7 @@ export default class LoginController extends React.Component { } else if (team) { browserHistory.push(`/${team.name}`); } else { - browserHistory.push('/select_team'); + GlobalActions.redirectUserToDefaultTeam(); } } ); diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index 0a5f04394..0a49d2497 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -146,6 +146,7 @@ export default class Navbar extends React.Component { if (e.target.className !== 'navbar-toggle' && e.target.className !== 'icon-bar') { $('.app__body .inner-wrap').removeClass('move--right move--left move--left-small'); $('.app__body .sidebar--left').removeClass('move--right'); + $('.multi-teams .team-sidebar').removeClass('move--right'); $('.app__body .sidebar--right').removeClass('move--left'); $('.app__body .sidebar--menu').removeClass('move--left'); } @@ -155,6 +156,7 @@ export default class Navbar extends React.Component { toggleLeftSidebar() { $('.app__body .inner-wrap').toggleClass('move--right'); $('.app__body .sidebar--left').toggleClass('move--right'); + $('.multi-teams .team-sidebar').toggleClass('move--right'); } toggleRightSidebar() { diff --git a/webapp/components/needs_team.jsx b/webapp/components/needs_team.jsx index f8a774389..f90297065 100644 --- a/webapp/components/needs_team.jsx +++ b/webapp/components/needs_team.jsx @@ -141,6 +141,7 @@ export default class NeedsTeam extends React.Component { content.push( this.props.navbar ); + content.push(this.props.team_sidebar); content.push( this.props.sidebar ); @@ -197,6 +198,7 @@ NeedsTeam.propTypes = { ]), navbar: React.PropTypes.element, sidebar: React.PropTypes.element, + team_sidebar: React.PropTypes.element, center: React.PropTypes.element, params: React.PropTypes.object, user: React.PropTypes.object diff --git a/webapp/components/notify_counts.jsx b/webapp/components/notify_counts.jsx index 6ccbd228b..d49925780 100644 --- a/webapp/components/notify_counts.jsx +++ b/webapp/components/notify_counts.jsx @@ -3,14 +3,22 @@ import * as utils from 'utils/utils.jsx'; import ChannelStore from 'stores/channel_store.jsx'; +import TeamStore from 'stores/team_store.jsx'; function getCountsStateFromStores() { - var count = 0; - var channels = ChannelStore.getAll(); - var members = ChannelStore.getMyMembers(); + let count = 0; + const teamMembers = TeamStore.getMyTeamMembers(); + const channels = ChannelStore.getAll(); + const members = ChannelStore.getMyMembers(); + + teamMembers.forEach((member) => { + if (member.team_id !== TeamStore.getCurrentId()) { + count += ((member.msg_count || 0) + (member.mention_count || 0)); + } + }); channels.forEach((channel) => { - var channelMember = members[channel.id]; + const channelMember = members[channel.id]; if (channelMember == null) { return; } @@ -41,10 +49,12 @@ export default class NotifyCounts extends React.Component { componentDidMount() { this.mounted = true; ChannelStore.addChangeListener(this.onListenerChange); + TeamStore.addChangeListener(this.onListenerChange); } componentWillUnmount() { this.mounted = false; ChannelStore.removeChangeListener(this.onListenerChange); + TeamStore.removeChangeListener(this.onListenerChange); } onListenerChange() { if (this.mounted) { diff --git a/webapp/components/root.jsx b/webapp/components/root.jsx index 9bb7d2970..2cfd9d303 100644 --- a/webapp/components/root.jsx +++ b/webapp/components/root.jsx @@ -50,7 +50,7 @@ export default class Root extends React.Component { if (UserStore.getNoAccounts()) { browserHistory.push('/signup_user_complete'); } else if (UserStore.getCurrentUser()) { - browserHistory.push('/select_team'); + GlobalActions.redirectUserToDefaultTeam(); } else { browserHistory.push('/login'); } diff --git a/webapp/components/select_team/components/select_team_listing.jsx b/webapp/components/select_team/components/select_team_listing.jsx deleted file mode 100644 index e69de29bb..000000000 --- a/webapp/components/select_team/components/select_team_listing.jsx +++ /dev/null diff --git a/webapp/components/select_team/select_team.jsx b/webapp/components/select_team/select_team.jsx index eef3b7931..361c95c49 100644 --- a/webapp/components/select_team/select_team.jsx +++ b/webapp/components/select_team/select_team.jsx @@ -24,6 +24,7 @@ export default class SelectTeam extends React.Component { super(props); this.onTeamChange = this.onTeamChange.bind(this); this.handleTeamClick = this.handleTeamClick.bind(this); + this.teamContentsCompare = this.teamContentsCompare.bind(this); const state = this.getStateFromStores(false); state.loadingTeamId = ''; @@ -61,33 +62,15 @@ export default class SelectTeam extends React.Component { } render() { - let content = null; - let teamContents = []; + let openTeamContents = []; const isAlreadyMember = new Map(); const isSystemAdmin = Utils.isSystemAdmin(UserStore.getCurrentUser().roles); - let teamMembersCount = 0; for (const teamMember of this.state.teamMembers) { const teamId = teamMember.team_id; - const team = this.state.teams[teamId]; isAlreadyMember[teamId] = true; - teamMembersCount++; - - teamContents.push( - <SelectTeamItem - key={'team_' + team.name} - team={team} - url={'/' + team.name + '/channels/town-square'} - onTeamClick={this.handleTeamClick} - loading={this.state.loadingTeamId === teamId} - /> - ); } - teamContents = teamContents.sort(this.teamContentsCompare); - - var openTeamContents = []; - for (const id in this.state.teamListings) { if (this.state.teamListings.hasOwnProperty(id) && !isAlreadyMember[id]) { const openTeam = this.state.teamListings[id]; @@ -103,8 +86,8 @@ export default class SelectTeam extends React.Component { } } - if (teamMembersCount === 0 && teamContents.length === 0 && openTeamContents.length === 0 && (global.window.mm_config.EnableTeamCreation === 'true' || isSystemAdmin)) { - teamContents = ( + if (openTeamContents.length === 0 && (global.window.mm_config.EnableTeamCreation === 'true' || isSystemAdmin)) { + openTeamContents = ( <div className='signup-team-dir-err'> <div> <FormattedMessage @@ -114,8 +97,8 @@ export default class SelectTeam extends React.Component { </div> </div> ); - } else if (teamMembersCount === 0 && teamContents.length === 0 && openTeamContents.length === 0) { - teamContents = ( + } else if (openTeamContents.length === 0) { + openTeamContents = ( <div className='signup-team-dir-err'> <div> <FormattedMessage @@ -125,42 +108,25 @@ export default class SelectTeam extends React.Component { </div> </div> ); - } else if (teamContents.length === 0 && openTeamContents.length > 0) { - teamContents = null; } - if (teamContents) { - content = ( - <div className='signup__content'> - <h4> - <FormattedMessage - id='signup_team.choose' - defaultMessage='Your teams:' - /> - </h4> - <div className='signup-team-all'> - {teamContents} - </div> - </div> - ); + if (Array.isArray(openTeamContents)) { + openTeamContents = openTeamContents.sort(this.teamContentsCompare); } - var openContent; - if (openTeamContents.length > 0) { - openContent = ( - <div className='signup__content'> - <h4> - <FormattedMessage - id='signup_team.join_open' - defaultMessage='Teams you can join: ' - /> - </h4> - <div className='signup-team-all'> - {openTeamContents.sort(this.teamContentsCompare)} - </div> + let openContent = ( + <div className='signup__content'> + <h4> + <FormattedMessage + id='signup_team.join_open' + defaultMessage='Teams you can join: ' + /> + </h4> + <div className='signup-team-all'> + {openTeamContents} </div> - ); - } + </div> + ); if (!this.state.loaded) { openContent = <LoadingScreen/>; @@ -177,7 +143,7 @@ export default class SelectTeam extends React.Component { } let teamSignUp; - if (isSystemAdmin || (global.window.mm_config.EnableTeamCreation === 'true' && !UserAgent.isMobileApp())) { + if (isSystemAdmin || global.window.mm_config.EnableTeamCreation === 'true') { teamSignUp = ( <div className='margin--extra'> <Link @@ -197,7 +163,7 @@ export default class SelectTeam extends React.Component { } let adminConsoleLink; - if (isSystemAdmin) { + if (isSystemAdmin && !UserAgent.isMobileApp()) { adminConsoleLink = ( <div className='margin--extra hidden-xs'> <Link @@ -225,19 +191,30 @@ export default class SelectTeam extends React.Component { ); } + let headerButton; + if (this.state.teamMembers.length) { + headerButton = ( + <Link to='/'> + <span className='fa fa-chevron-left'/> + <FormattedMessage id='web.header.back'/> + </Link> + ); + } else { + headerButton = ( + <a + href='#' + onClick={GlobalActions.emitUserLoggedOutEvent} + > + <span className='fa fa-chevron-left'/> + <FormattedMessage id='web.header.logout'/> + </a> + ); + } return ( <div> <ErrorBar/> <div className='signup-header'> - <a - href='#' - onClick={GlobalActions.emitUserLoggedOutEvent} - > - <span className='fa fa-chevron-left'/> - <FormattedMessage - id='navbar_dropdown.logout' - /> - </a> + {headerButton} </div> <div className='col-sm-12'> <div className={'signup-team__container'}> @@ -249,7 +226,6 @@ export default class SelectTeam extends React.Component { <h4 className='color--light'> {description} </h4> - {content} {openContent} {teamSignUp} {adminConsoleLink} diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx index fcfa9496c..203464600 100644 --- a/webapp/components/sidebar.jsx +++ b/webapp/components/sidebar.jsx @@ -82,11 +82,19 @@ export default class Sidebar extends React.Component { let msgs = 0; let mentions = 0; const unreadCounts = this.state.unreadCounts; + const teamMembers = this.state.teamMembers; + + teamMembers.forEach((member) => { + if (member.team_id !== this.state.currentTeam.id) { + msgs += member.msg_count || 0; + mentions += member.mention_count || 0; + } + }); Object.keys(unreadCounts).forEach((chId) => { const channel = ChannelStore.get(chId); - if (channel && (!channel.team_id || channel.team_id === this.state.currentTeam.id)) { + if (channel && (channel.type === 'D' || channel.team_id === this.state.currentTeam.id)) { msgs += unreadCounts[chId].msgs; mentions += unreadCounts[chId].mentions; } @@ -97,6 +105,7 @@ export default class Sidebar extends React.Component { getStateFromStores() { const members = ChannelStore.getMyMembers(); + const teamMembers = TeamStore.getMyTeamMembers(); const currentChannelId = ChannelStore.getCurrentId(); const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999); const channelList = ChannelUtils.buildDisplayableChannelList(Object.assign([], ChannelStore.getAll())); @@ -104,6 +113,7 @@ export default class Sidebar extends React.Component { return { activeId: currentChannelId, members, + teamMembers, ...channelList, unreadCounts: JSON.parse(JSON.stringify(ChannelStore.getUnreadCounts())), showTutorialTip: tutorialStep === TutorialSteps.CHANNEL_POPOVER, @@ -153,6 +163,7 @@ export default class Sidebar extends React.Component { if (this.state.activeId !== prevState.activeId) { $('.app__body .inner-wrap').removeClass('move--right'); $('.app__body .sidebar--left').removeClass('move--right'); + $('.multi-teams .team-sidebar').removeClass('move--right'); } } @@ -169,6 +180,7 @@ export default class Sidebar extends React.Component { onChange() { this.setState(this.getStateFromStores()); + this.updateTitle(); } updateTitle() { diff --git a/webapp/components/sidebar_header_dropdown.jsx b/webapp/components/sidebar_header_dropdown.jsx index dcd791cc6..cfa4d2f80 100644 --- a/webapp/components/sidebar_header_dropdown.jsx +++ b/webapp/components/sidebar_header_dropdown.jsx @@ -45,7 +45,6 @@ export default class SidebarHeaderDropdown extends React.Component { this.showGetTeamInviteLinkModal = this.showGetTeamInviteLinkModal.bind(this); this.showTeamMembersModal = this.showTeamMembersModal.bind(this); this.hideTeamMembersModal = this.hideTeamMembersModal.bind(this); - this.handleSwitchTeams = this.handleSwitchTeams.bind(this); this.onTeamChange = this.onTeamChange.bind(this); this.openAccountSettings = this.openAccountSettings.bind(this); @@ -55,8 +54,8 @@ export default class SidebarHeaderDropdown extends React.Component { this.handleClick = this.handleClick.bind(this); this.state = { - teams: TeamStore.getAll(), teamMembers: TeamStore.getMyTeamMembers(), + teamListings: TeamStore.getTeamListings(), showAboutModal: false, showDropdown: false, showTeamMembersModal: false, @@ -131,11 +130,6 @@ export default class SidebarHeaderDropdown extends React.Component { }); } - handleSwitchTeams() { - // The actual switching of teams is handled by the react-router Link - this.setState({showDropdown: false}); - } - componentDidMount() { TeamStore.addChangeListener(this.onTeamChange); document.addEventListener('keydown', this.openAccountSettings); @@ -143,8 +137,8 @@ export default class SidebarHeaderDropdown extends React.Component { onTeamChange() { this.setState({ - teams: TeamStore.getAll(), - teamMembers: TeamStore.getMyTeamMembers() + teamMembers: TeamStore.getMyTeamMembers(), + teamListings: TeamStore.getTeamListings() }); } @@ -182,14 +176,14 @@ export default class SidebarHeaderDropdown extends React.Component { render() { const config = global.mm_config; - var teamLink = ''; - var inviteLink = ''; - var manageLink = ''; - var sysAdminLink = ''; - var currentUser = this.props.currentUser; - var isAdmin = false; - var isSystemAdmin = false; - var teamSettings = null; + const currentUser = this.props.currentUser; + let teamLink = ''; + let inviteLink = ''; + let manageLink = ''; + let sysAdminLink = ''; + let isAdmin = false; + let isSystemAdmin = false; + let teamSettings = null; let integrationsLink = null; if (!currentUser) { @@ -322,6 +316,7 @@ export default class SidebarHeaderDropdown extends React.Component { } const teams = []; + let moreTeams = false; if (config.EnableTeamCreation === 'true') { teams.push( @@ -340,6 +335,31 @@ export default class SidebarHeaderDropdown extends React.Component { ); } + const isAlreadyMember = this.state.teamMembers.reduce((result, item) => { + result[item.team_id] = true; + return result; + }, {}); + + for (const id in this.state.teamListings) { + if (this.state.teamListings.hasOwnProperty(id) && !isAlreadyMember[id]) { + moreTeams = true; + break; + } + } + + if (moreTeams) { + teams.push( + <li key='joinTeam_li'> + <Link to='/select_team'> + <FormattedMessage + id='navbar_dropdown.join' + defaultMessage='Join Another Team' + /> + </Link> + </li> + ); + } + teams.push( <li key='leaveTeam_li'> <a @@ -354,39 +374,6 @@ export default class SidebarHeaderDropdown extends React.Component { </li> ); - if (this.state.teamMembers && this.state.teamMembers.length > 1) { - teams.push( - <li - key='teamDiv' - className='divider' - /> - ); - - for (var index in this.state.teamMembers) { - if (this.state.teamMembers.hasOwnProperty(index)) { - var teamMember = this.state.teamMembers[index]; - var team = this.state.teams[teamMember.team_id]; - - if (team.name !== this.props.teamName) { - teams.push( - <li key={'team_' + team.name}> - <Link - to={'/' + team.name + '/channels/town-square'} - onClick={this.handleSwitchTeams} - > - <FormattedMessage - id='navbar_dropdown.switchTo' - defaultMessage='Switch to ' - /> - {team.display_name} - </Link> - </li> - ); - } - } - } - } - let helpLink = null; if (config.HelpLink) { helpLink = ( diff --git a/webapp/components/sidebar_right.jsx b/webapp/components/sidebar_right.jsx index 1f4c394bb..1be2a3287 100644 --- a/webapp/components/sidebar_right.jsx +++ b/webapp/components/sidebar_right.jsx @@ -82,6 +82,7 @@ export default class SidebarRight extends React.Component { $('.app__body .inner-wrap').removeClass('.move--right'); $('.app__body .inner-wrap').addClass('move--left'); $('.app__body .sidebar--left').removeClass('move--right'); + $('.multi-teams .team-sidebar').removeClass('move--right'); $('.app__body .sidebar--right').addClass('move--left'); //$('.sidebar--right').prepend('<div class="sidebar__overlay"></div>'); diff --git a/webapp/components/sidebar_right_menu.jsx b/webapp/components/sidebar_right_menu.jsx index f201adfcf..982562c2c 100644 --- a/webapp/components/sidebar_right_menu.jsx +++ b/webapp/components/sidebar_right_menu.jsx @@ -391,15 +391,6 @@ export default class SidebarRightMenu extends React.Component { {teamSettingsLink} {manageLink} {consoleLink} - <li> - <Link to='/select_team'> - <i className='icon fa fa-exchange'/> - <FormattedMessage - id='sidebar_right_menu.switch_team' - defaultMessage='Team Selection' - /> - </Link> - </li> <li className='divider'/> {helpLink} {reportLink} diff --git a/webapp/components/signup/components/signup_email.jsx b/webapp/components/signup/components/signup_email.jsx index b67179604..aa3493c96 100644 --- a/webapp/components/signup/components/signup_email.jsx +++ b/webapp/components/signup/components/signup_email.jsx @@ -110,7 +110,7 @@ export default class SignupEmail extends React.Component { if (query.redirect_to) { browserHistory.push(query.redirect_to); } else { - browserHistory.push('/select_team'); + GlobalActions.redirectUserToDefaultTeam(); } } ); @@ -133,7 +133,7 @@ export default class SignupEmail extends React.Component { if (query.redirect_to) { browserHistory.push(query.redirect_to); } else { - browserHistory.push('/select_team'); + GlobalActions.redirectUserToDefaultTeam(); } } ); diff --git a/webapp/components/signup/components/signup_ldap.jsx b/webapp/components/signup/components/signup_ldap.jsx index bc8c073ad..d80b27159 100644 --- a/webapp/components/signup/components/signup_ldap.jsx +++ b/webapp/components/signup/components/signup_ldap.jsx @@ -90,8 +90,13 @@ export default class SignupLdap extends React.Component { finishSignup() { GlobalActions.emitInitialLoad( () => { + const query = this.props.location.query; GlobalActions.loadDefaultLocale(); - browserHistory.push('/select_team'); + if (query.redirect_to) { + browserHistory.push(query.redirect_to); + } else { + GlobalActions.redirectUserToDefaultTeam(); + } } ); } diff --git a/webapp/components/signup/signup_controller.jsx b/webapp/components/signup/signup_controller.jsx index 0f0b6c867..3d853a9ee 100644 --- a/webapp/components/signup/signup_controller.jsx +++ b/webapp/components/signup/signup_controller.jsx @@ -122,7 +122,7 @@ export default class SignupController extends React.Component { } if (userLoggedIn) { - browserHistory.push('/select_team'); + GlobalActions.redirectUserToDefaultTeam(); } } } diff --git a/webapp/components/team_sidebar/components/team_button.jsx b/webapp/components/team_sidebar/components/team_button.jsx new file mode 100644 index 000000000..0033ae25a --- /dev/null +++ b/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']) +}; diff --git a/webapp/components/team_sidebar/team_sidebar_controller.jsx b/webapp/components/team_sidebar/team_sidebar_controller.jsx new file mode 100644 index 000000000..f005afeb3 --- /dev/null +++ b/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> + ); + } +} diff --git a/webapp/components/webrtc/components/webrtc_sidebar.jsx b/webapp/components/webrtc/components/webrtc_sidebar.jsx index d28158b09..2979e6025 100644 --- a/webapp/components/webrtc/components/webrtc_sidebar.jsx +++ b/webapp/components/webrtc/components/webrtc_sidebar.jsx @@ -50,6 +50,7 @@ export default class SidebarRight extends React.Component { $('.app__body .inner-wrap').removeClass('move--right'); $('.app__body .inner-wrap').addClass('webrtc--show'); $('.app__body .sidebar--left').removeClass('move--right'); + $('.multi-teams .team-sidebar').removeClass('move--right'); $('.app__body .webrtc').addClass('webrtc--show'); //$('.sidebar--right').prepend('<div class="sidebar__overlay"></div>'); |