2015-10-08 12:27:09 -04:00
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
2015-06-14 23:53:32 -08:00
// See License.txt for license information.
2015-10-02 09:50:34 -04:00
const NewChannelFlow = require ( './new_channel_flow.jsx' ) ;
2015-10-14 16:57:03 -04:00
const MoreDirectChannels = require ( './more_direct_channels.jsx' ) ;
2015-10-02 09:50:34 -04:00
const SearchBox = require ( './search_bar.jsx' ) ;
const SidebarHeader = require ( './sidebar_header.jsx' ) ;
const UnreadChannelIndicator = require ( './unread_channel_indicator.jsx' ) ;
2015-10-30 11:35:16 -04:00
const TutorialTip = require ( './tutorial/tutorial_tip.jsx' ) ;
const ChannelStore = require ( '../stores/channel_store.jsx' ) ;
2015-10-02 09:50:34 -04:00
const UserStore = require ( '../stores/user_store.jsx' ) ;
2015-10-30 11:35:16 -04:00
const TeamStore = require ( '../stores/team_store.jsx' ) ;
const PreferenceStore = require ( '../stores/preference_store.jsx' ) ;
const AsyncClient = require ( '../utils/async_client.jsx' ) ;
const Client = require ( '../utils/client.jsx' ) ;
2015-10-02 09:50:34 -04:00
const Utils = require ( '../utils/utils.jsx' ) ;
2015-10-30 11:35:16 -04:00
const Constants = require ( '../utils/constants.jsx' ) ;
const Preferences = Constants . Preferences ;
const TutorialSteps = Constants . TutorialSteps ;
2015-11-05 09:42:29 -05:00
const NotificationPrefs = Constants . NotificationPrefs ;
2015-10-30 11:35:16 -04:00
2015-10-14 17:04:13 +05:00
const Tooltip = ReactBootstrap . Tooltip ;
const OverlayTrigger = ReactBootstrap . OverlayTrigger ;
2015-06-14 23:53:32 -08:00
2015-09-01 08:37:09 -04:00
export default class Sidebar extends React . Component {
constructor ( props ) {
super ( props ) ;
2015-06-14 23:53:32 -08:00
2015-09-01 08:37:09 -04:00
this . badgesActive = false ;
2015-09-16 14:53:16 -04:00
this . firstUnreadChannel = null ;
this . lastUnreadChannel = null ;
2015-06-14 23:53:32 -08:00
2015-10-02 09:50:34 -04:00
this . getStateFromStores = this . getStateFromStores . bind ( this ) ;
2015-09-01 08:37:09 -04:00
this . onChange = this . onChange . bind ( this ) ;
this . onScroll = this . onScroll . bind ( this ) ;
2015-09-16 14:53:16 -04:00
this . updateUnreadIndicators = this . updateUnreadIndicators . bind ( this ) ;
2015-10-02 14:25:55 -04:00
this . handleLeaveDirectChannel = this . handleLeaveDirectChannel . bind ( this ) ;
2015-10-16 12:32:19 +03:00
this . updateScrollbar = this . updateScrollbar . bind ( this ) ;
this . handleResize = this . handleResize . bind ( this ) ;
2015-10-14 16:57:03 -04:00
this . showNewChannelModal = this . showNewChannelModal . bind ( this ) ;
this . hideNewChannelModal = this . hideNewChannelModal . bind ( this ) ;
this . showMoreDirectChannelsModal = this . showMoreDirectChannelsModal . bind ( this ) ;
this . hideMoreDirectChannelsModal = this . hideMoreDirectChannelsModal . bind ( this ) ;
2015-09-01 08:37:09 -04:00
this . createChannelElement = this . createChannelElement . bind ( this ) ;
2015-10-25 15:12:36 +01:00
this . updateTitle = this . updateTitle . bind ( this ) ;
2015-10-26 17:53:21 +01:00
this . setUnreadCountPerChannel = this . setUnreadCountPerChannel . bind ( this ) ;
2015-10-25 15:12:36 +01:00
this . getUnreadCount = this . getUnreadCount . bind ( this ) ;
2015-06-14 23:53:32 -08:00
2015-10-07 11:34:29 -04:00
this . isLeaving = new Map ( ) ;
2015-10-05 09:58:42 -04:00
const state = this . getStateFromStores ( ) ;
2015-10-14 16:57:03 -04:00
state . newChannelModalType = '' ;
2015-10-16 10:15:52 -04:00
state . showDirectChannelsModal = false ;
2015-10-05 09:58:42 -04:00
state . loadingDMChannel = - 1 ;
2015-10-16 12:32:19 +03:00
state . windowWidth = Utils . windowWidth ( ) ;
2015-10-05 09:58:42 -04:00
this . state = state ;
2015-10-26 17:53:21 +01:00
this . unreadCountPerChannel = { } ;
this . setUnreadCountPerChannel ( ) ;
2015-09-01 08:37:09 -04:00
}
2015-10-26 17:53:21 +01:00
setUnreadCountPerChannel ( ) {
2015-10-25 15:12:36 +01:00
const channels = ChannelStore . getAll ( ) ;
const members = ChannelStore . getAllMembers ( ) ;
2015-10-26 17:53:21 +01:00
const channelUnreadCounts = { } ;
2015-10-25 15:12:36 +01:00
channels . forEach ( ( ch ) => {
const chMember = members [ ch . id ] ;
let chMentionCount = chMember . mention _count ;
let chUnreadCount = ch . total _msg _count - chMember . msg _count - chMentionCount ;
if ( ch . type === 'D' ) {
chMentionCount = chUnreadCount ;
chUnreadCount = 0 ;
2015-11-05 09:42:29 -05:00
} else if ( chMember . notify _props && chMember . notify _props . mark _unread === NotificationPrefs . MENTION ) {
2015-11-05 09:39:07 -05:00
chUnreadCount = 0 ;
2015-10-25 15:12:36 +01:00
}
2015-10-26 17:53:21 +01:00
channelUnreadCounts [ ch . id ] = { msgs : chUnreadCount , mentions : chMentionCount } ;
2015-10-25 15:12:36 +01:00
} ) ;
2015-10-26 17:53:21 +01:00
this . unreadCountPerChannel = channelUnreadCounts ;
2015-10-25 15:12:36 +01:00
}
getUnreadCount ( channelId ) {
let mentions = 0 ;
let msgs = 0 ;
if ( channelId ) {
2015-10-26 17:53:21 +01:00
return this . unreadCountPerChannel [ channelId ] ? this . unreadCountPerChannel [ channelId ] : { msgs , mentions } ;
2015-10-25 15:12:36 +01:00
}
2015-10-26 17:53:21 +01:00
Object . keys ( this . unreadCountPerChannel ) . forEach ( ( chId ) => {
msgs += this . unreadCountPerChannel [ chId ] . msgs ;
mentions += this . unreadCountPerChannel [ chId ] . mentions ;
2015-10-25 15:12:36 +01:00
} ) ;
return { msgs , mentions } ;
}
2015-09-01 08:37:09 -04:00
getStateFromStores ( ) {
2015-10-02 09:50:34 -04:00
const members = ChannelStore . getAllMembers ( ) ;
2015-11-03 14:52:25 -05:00
const currentChannelId = ChannelStore . getCurrentId ( ) ;
const channels = Object . assign ( [ ] , ChannelStore . getAll ( ) ) ;
const publicChannels = channels . filter ( ( channel ) => channel . type === Constants . OPEN _CHANNEL ) ;
const privateChannels = channels . filter ( ( channel ) => channel . type === Constants . PRIVATE _CHANNEL ) ;
const directChannels = channels . filter ( ( channel ) => channel . type === Constants . DM _CHANNEL ) ;
2015-06-14 23:53:32 -08:00
2015-10-13 11:52:17 -04:00
const preferences = PreferenceStore . getPreferences ( Constants . Preferences . CATEGORY _DIRECT _CHANNEL _SHOW ) ;
2015-10-02 09:50:34 -04:00
var visibleDirectChannels = [ ] ;
2015-11-03 14:52:25 -05:00
for ( var i = 0 ; i < directChannels . length ; i ++ ) {
const dm = directChannels [ i ] ;
const teammate = Utils . getDirectTeammate ( dm . id ) ;
2015-11-03 15:11:16 -05:00
if ( ! teammate ) {
continue ;
}
2015-06-14 23:53:32 -08:00
2015-11-03 14:52:25 -05:00
const member = members [ dm . id ] ;
const msgCount = dm . total _msg _count - member . msg _count ;
2015-09-01 08:37:09 -04:00
2015-11-03 14:52:25 -05:00
// always show a channel if either it is the current one or if it is unread, but it is not currently being left
const forceShow = ( currentChannelId === dm . id || msgCount > 0 ) && ! this . isLeaving . get ( dm . id ) ;
const preferenceShow = preferences . some ( ( preference ) => ( preference . name === teammate . id && preference . value !== 'false' ) ) ;
2015-10-07 13:07:59 -04:00
2015-11-03 14:52:25 -05:00
if ( preferenceShow || forceShow ) {
dm . display _name = Utils . displayUsername ( teammate . id ) ;
dm . teammate _id = teammate . id ;
dm . status = UserStore . getStatus ( teammate . id ) ;
2015-10-02 14:25:55 -04:00
2015-11-03 14:52:25 -05:00
visibleDirectChannels . push ( dm ) ;
2015-10-05 11:47:34 -04:00
2015-11-03 14:52:25 -05:00
if ( forceShow && ! preferenceShow ) {
// make sure that unread direct channels are visible
const preference = PreferenceStore . setPreference ( Constants . Preferences . CATEGORY _DIRECT _CHANNEL _SHOW , teammate . id , 'true' ) ;
AsyncClient . savePreferences ( [ preference ] ) ;
}
2015-06-14 23:53:32 -08:00
}
}
2015-11-03 14:52:25 -05:00
const hiddenDirectChannelCount = UserStore . getActiveOnlyProfileList ( ) . length - visibleDirectChannels . length ;
2015-10-02 14:25:55 -04:00
visibleDirectChannels . sort ( this . sortChannelsByDisplayName ) ;
2015-06-14 23:53:32 -08:00
2015-10-30 11:35:16 -04:00
const tutorialPref = PreferenceStore . getPreference ( Preferences . TUTORIAL _STEP , UserStore . getCurrentId ( ) , { value : '0' } ) ;
2015-09-01 08:37:09 -04:00
return {
2015-11-03 14:52:25 -05:00
activeId : currentChannelId ,
2015-10-07 13:07:59 -04:00
members ,
2015-11-03 14:52:25 -05:00
publicChannels ,
privateChannels ,
2015-10-07 13:07:59 -04:00
visibleDirectChannels ,
2015-10-30 11:35:16 -04:00
hiddenDirectChannelCount ,
showTutorialTip : parseInt ( tutorialPref . value , 10 ) === TutorialSteps . CHANNEL _POPOVER
2015-09-01 08:37:09 -04:00
} ;
2015-08-11 11:18:15 -04:00
}
2015-10-02 09:50:34 -04:00
2015-09-01 08:37:09 -04:00
componentDidMount ( ) {
2015-08-03 12:09:27 -07:00
ChannelStore . addChangeListener ( this . onChange ) ;
UserStore . addChangeListener ( this . onChange ) ;
UserStore . addStatusesChangeListener ( this . onChange ) ;
2015-08-13 11:00:49 -07:00
TeamStore . addChangeListener ( this . onChange ) ;
2015-10-02 09:50:34 -04:00
PreferenceStore . addChangeListener ( this . onChange ) ;
2015-06-14 23:53:32 -08:00
this . updateTitle ( ) ;
2015-09-16 14:53:16 -04:00
this . updateUnreadIndicators ( ) ;
2015-10-16 12:32:19 +03:00
this . updateScrollbar ( ) ;
2015-08-07 10:58:03 -04:00
2015-10-16 12:32:19 +03:00
window . addEventListener ( 'resize' , this . handleResize ) ;
2015-09-01 08:37:09 -04:00
}
2015-09-16 14:53:16 -04:00
shouldComponentUpdate ( nextProps , nextState ) {
if ( ! Utils . areStatesEqual ( nextState , this . state ) ) {
return true ;
}
return false ;
}
2015-09-01 08:37:09 -04:00
componentDidUpdate ( ) {
2015-06-14 23:53:32 -08:00
this . updateTitle ( ) ;
2015-09-16 14:53:16 -04:00
this . updateUnreadIndicators ( ) ;
2015-10-16 12:32:19 +03:00
this . updateScrollbar ( ) ;
2015-09-01 08:37:09 -04:00
}
componentWillUnmount ( ) {
2015-10-16 12:32:19 +03:00
window . removeEventListener ( 'resize' , this . handleResize ) ;
2015-08-07 10:58:03 -04:00
2015-08-03 12:09:27 -07:00
ChannelStore . removeChangeListener ( this . onChange ) ;
UserStore . removeChangeListener ( this . onChange ) ;
UserStore . removeStatusesChangeListener ( this . onChange ) ;
2015-08-13 11:00:49 -07:00
TeamStore . removeChangeListener ( this . onChange ) ;
2015-10-02 09:50:34 -04:00
PreferenceStore . removeChangeListener ( this . onChange ) ;
2015-09-01 08:37:09 -04:00
}
2015-10-16 12:32:19 +03:00
handleResize ( ) {
this . setState ( {
windowWidth : Utils . windowWidth ( ) ,
windowHeight : Utils . windowHeight ( )
} ) ;
}
updateScrollbar ( ) {
if ( this . state . windowWidth > 768 ) {
$ ( '.nav-pills__container' ) . perfectScrollbar ( ) ;
$ ( '.nav-pills__container' ) . perfectScrollbar ( 'update' ) ;
}
}
2015-09-01 08:37:09 -04:00
onChange ( ) {
var newState = this . getStateFromStores ( ) ;
2015-09-02 08:40:25 -04:00
if ( ! Utils . areStatesEqual ( newState , this . state ) ) {
2015-06-14 23:53:32 -08:00
this . setState ( newState ) ;
}
2015-09-01 08:37:09 -04:00
}
updateTitle ( ) {
2015-09-28 14:58:14 -07:00
const channel = ChannelStore . getCurrent ( ) ;
2015-06-14 23:53:32 -08:00
if ( channel ) {
2015-09-28 14:58:14 -07:00
let currentSiteName = '' ;
2015-10-16 09:10:54 -07:00
if ( global . window . mm _config . SiteName != null ) {
currentSiteName = global . window . mm _config . SiteName ;
2015-09-28 14:58:14 -07:00
}
let currentChannelName = channel . display _name ;
2015-06-14 23:53:32 -08:00
if ( channel . type === 'D' ) {
2015-09-28 14:58:14 -07:00
currentChannelName = Utils . getDirectTeammate ( channel . id ) . username ;
2015-06-14 23:53:32 -08:00
}
2015-09-28 14:58:14 -07:00
2015-10-25 15:12:36 +01:00
const unread = this . getUnreadCount ( ) ;
const mentionTitle = unread . mentions > 0 ? '(' + unread . mentions + ') ' : '' ;
const unreadTitle = unread . msgs > 0 ? '* ' : '' ;
2015-10-27 15:48:51 -04:00
document . title = mentionTitle + unreadTitle + currentChannelName + ' - ' + TeamStore . getCurrent ( ) . display _name + ' ' + currentSiteName ;
2015-06-14 23:53:32 -08:00
}
2015-09-01 08:37:09 -04:00
}
onScroll ( ) {
2015-09-16 14:53:16 -04:00
this . updateUnreadIndicators ( ) ;
2015-09-01 08:37:09 -04:00
}
2015-09-16 14:53:16 -04:00
updateUnreadIndicators ( ) {
2015-10-15 12:07:06 -04:00
const container = $ ( ReactDOM . findDOMNode ( this . refs . container ) ) ;
2015-09-16 14:53:16 -04:00
var showTopUnread = false ;
var showBottomUnread = false ;
if ( this . firstUnreadChannel ) {
2015-10-15 12:07:06 -04:00
var firstUnreadElement = $ ( ReactDOM . findDOMNode ( this . refs [ this . firstUnreadChannel ] ) ) ;
2015-09-16 14:53:16 -04:00
if ( firstUnreadElement . position ( ) . top + firstUnreadElement . height ( ) < 0 ) {
showTopUnread = true ;
}
}
if ( this . lastUnreadChannel ) {
2015-10-15 12:07:06 -04:00
var lastUnreadElement = $ ( ReactDOM . findDOMNode ( this . refs [ this . lastUnreadChannel ] ) ) ;
2015-09-16 14:53:16 -04:00
if ( lastUnreadElement . position ( ) . top > container . height ( ) ) {
showBottomUnread = true ;
}
}
this . setState ( {
showTopUnread ,
showBottomUnread
} ) ;
}
2015-10-02 14:25:55 -04:00
handleLeaveDirectChannel ( channel ) {
2015-10-07 11:34:29 -04:00
if ( ! this . isLeaving . get ( channel . id ) ) {
this . isLeaving . set ( channel . id , true ) ;
2015-10-02 14:25:55 -04:00
2015-10-13 11:52:17 -04:00
const preference = PreferenceStore . setPreference ( Constants . Preferences . CATEGORY _DIRECT _CHANNEL _SHOW , channel . teammate _id , 'false' ) ;
2015-10-13 15:18:01 -04:00
// bypass AsyncClient since we've already saved the updated preferences
Client . savePreferences (
2015-10-02 14:25:55 -04:00
[ preference ] ,
( ) => {
2015-10-07 11:34:29 -04:00
this . isLeaving . set ( channel . id , false ) ;
2015-10-02 14:25:55 -04:00
} ,
( ) => {
2015-10-07 11:34:29 -04:00
this . isLeaving . set ( channel . id , false ) ;
2015-10-02 14:25:55 -04:00
}
) ;
this . setState ( this . getStateFromStores ( ) ) ;
}
if ( channel . id === this . state . activeId ) {
Utils . switchChannel ( ChannelStore . getByName ( Constants . DEFAULT _CHANNEL ) ) ;
}
}
sortChannelsByDisplayName ( a , b ) {
return a . display _name . localeCompare ( b . display _name ) ;
}
2015-10-14 16:57:03 -04:00
showNewChannelModal ( type ) {
this . setState ( { newChannelModalType : type } ) ;
}
hideNewChannelModal ( ) {
this . setState ( { newChannelModalType : '' } ) ;
}
showMoreDirectChannelsModal ( ) {
this . setState ( { showDirectChannelsModal : true } ) ;
}
hideMoreDirectChannelsModal ( ) {
this . setState ( { showDirectChannelsModal : false } ) ;
}
2015-10-30 11:35:16 -04:00
createTutorialTip ( ) {
const screens = [ ] ;
screens . push (
< div >
2015-11-02 11:40:53 +05:00
< h4 > { 'Channels' } < / h4 >
< p > < strong > { 'Channels' } < / strong > { ' organize conversations across different topics. They’ re open to everyone on your team. To send private communications use ' } < strong > { 'Direct Messages' } < / strong > { ' for a single person or ' } < strong > { 'Private Groups' } < / strong > { ' for multiple people.' }
< / p >
2015-10-30 11:35:16 -04:00
< / div >
) ;
screens . push (
< div >
2015-11-02 11:40:53 +05:00
< h4 > { '"Town Square" and "Off-Topic" channels' } < / h4 >
< p > { 'Here are two public channels to start:' } < / p >
< p >
< strong > { 'Town Square' } < / strong > { ' is a place for team-wide communication. Everyone in your team is a member of this channel.' }
< / p >
< p >
< strong > { 'Off-Topic' } < / strong > { ' is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.' }
< / p >
2015-10-30 11:35:16 -04:00
< / div >
) ;
screens . push (
< div >
2015-11-02 11:40:53 +05:00
< h4 > { 'Creating and Joining Channels' } < / h4 >
< p >
{ 'Click ' } < strong > { '"More..."' } < / strong > { ' to create a new channel or join an existing one.' }
< / p >
< p >
{ 'You can also create a new channel or private group by clicking the ' } < strong > { '"+" symbol' } < / strong > { ' next to the channel or private group header.' }
< / p >
2015-10-30 11:35:16 -04:00
< / div >
) ;
return (
< TutorialTip
placement = 'right'
screens = { screens }
2015-11-02 09:21:08 -05:00
overlayClass = 'tip-overlay--sidebar'
2015-10-30 11:35:16 -04:00
/ >
) ;
}
2015-10-02 14:25:55 -04:00
createChannelElement ( channel , index , arr , handleClose ) {
2015-06-14 23:53:32 -08:00
var members = this . state . members ;
2015-08-11 12:20:49 -04:00
var activeId = this . state . activeId ;
2015-09-01 08:37:09 -04:00
var channelMember = members [ channel . id ] ;
2015-10-25 15:12:36 +01:00
var unreadCount = this . getUnreadCount ( channel . id ) ;
2015-09-01 08:37:09 -04:00
var msgCount ;
2015-06-14 23:53:32 -08:00
2015-09-01 08:37:09 -04:00
var linkClass = '' ;
if ( channel . id === activeId ) {
linkClass = 'active' ;
}
2015-06-14 23:53:32 -08:00
2015-10-13 14:35:38 -04:00
let rowClass = 'sidebar-channel' ;
2015-09-01 08:37:09 -04:00
var unread = false ;
if ( channelMember ) {
2015-10-25 15:12:36 +01:00
msgCount = unreadCount . msgs + unreadCount . mentions ;
2015-11-05 09:39:07 -05:00
unread = msgCount > 0 || channelMember . mention _count > 0 ;
2015-09-01 08:37:09 -04:00
}
2015-06-14 23:53:32 -08:00
2015-09-01 08:37:09 -04:00
if ( unread ) {
2015-10-13 14:35:38 -04:00
rowClass += ' unread-title' ;
2015-08-06 16:28:43 -04:00
2015-09-09 15:21:44 -04:00
if ( channel . id !== activeId ) {
2015-09-16 14:53:16 -04:00
if ( ! this . firstUnreadChannel ) {
this . firstUnreadChannel = channel . name ;
}
this . lastUnreadChannel = channel . name ;
2015-06-14 23:53:32 -08:00
}
2015-09-01 08:37:09 -04:00
}
2015-06-14 23:53:32 -08:00
2015-09-01 08:37:09 -04:00
var badge = null ;
if ( channelMember ) {
2015-10-25 15:12:36 +01:00
if ( unreadCount . mentions ) {
badge = < span className = 'badge pull-right small' > { unreadCount . mentions } < / span > ;
2015-09-01 08:37:09 -04:00
this . badgesActive = true ;
2015-06-14 23:53:32 -08:00
}
2015-09-02 14:26:01 -04:00
} else if ( this . state . loadingDMChannel === index && channel . type === 'D' ) {
2015-09-01 08:37:09 -04:00
badge = (
< img
className = 'channel-loading-gif pull-right'
src = '/static/images/load.gif'
/ >
) ;
}
2015-06-14 23:53:32 -08:00
2015-09-16 20:32:10 +05:00
if ( msgCount > 0 ) {
2015-10-13 14:35:38 -04:00
rowClass += ' has-badge' ;
2015-09-16 20:32:10 +05:00
}
2015-09-01 08:37:09 -04:00
// set up status icon for direct message channels
var status = null ;
if ( channel . type === 'D' ) {
var statusIcon = '' ;
if ( channel . status === 'online' ) {
statusIcon = Constants . ONLINE _ICON _SVG ;
} else if ( channel . status === 'away' ) {
statusIcon = Constants . ONLINE _ICON _SVG ;
} else {
statusIcon = Constants . OFFLINE _ICON _SVG ;
}
status = (
< span
className = 'status'
dangerouslySetInnerHTML = { { _ _html : statusIcon } }
/ >
) ;
}
2015-08-14 17:12:02 -07:00
2015-09-01 08:37:09 -04:00
// set up click handler to switch channels (or create a new channel for non-existant ones)
var handleClick = null ;
var href = '#' ;
var teamURL = TeamStore . getCurrentTeamUrl ( ) ;
if ( ! channel . fake ) {
handleClick = function clickHandler ( e ) {
2015-10-07 13:07:59 -04:00
if ( e . target . attributes . getNamedItem ( 'data-close' ) ) {
2015-10-02 14:25:55 -04:00
handleClose ( channel ) ;
2015-10-07 13:07:59 -04:00
} else {
Utils . switchChannel ( channel ) ;
2015-10-02 14:25:55 -04:00
}
2015-09-01 08:37:09 -04:00
e . preventDefault ( ) ;
} ;
} else if ( channel . fake && teamURL ) {
// It's a direct message channel that doesn't exist yet so let's create it now
2015-09-02 08:40:25 -04:00
var otherUserId = Utils . getUserIdFromChannelName ( channel ) ;
2015-09-01 08:37:09 -04:00
2015-09-02 14:26:01 -04:00
if ( this . state . loadingDMChannel === - 1 ) {
2015-08-14 17:39:50 -07:00
handleClick = function clickHandler ( e ) {
2015-08-06 14:03:45 -04:00
e . preventDefault ( ) ;
2015-10-02 14:25:55 -04:00
2015-10-07 13:07:59 -04:00
if ( e . target . attributes . getNamedItem ( 'data-close' ) ) {
handleClose ( channel ) ;
} else {
2015-10-02 14:25:55 -04:00
this . setState ( { loadingDMChannel : index } ) ;
Client . createDirectChannel ( channel , otherUserId ,
2015-10-07 13:07:59 -04:00
( data ) => {
2015-10-02 14:25:55 -04:00
this . setState ( { loadingDMChannel : - 1 } ) ;
AsyncClient . getChannel ( data . id ) ;
Utils . switchChannel ( data ) ;
2015-10-07 13:07:59 -04:00
} ,
( ) => {
2015-10-02 14:25:55 -04:00
this . setState ( { loadingDMChannel : - 1 } ) ;
window . location . href = TeamStore . getCurrentTeamUrl ( ) + '/channels/' + channel . name ;
2015-10-07 13:07:59 -04:00
}
2015-10-02 14:25:55 -04:00
) ;
}
2015-09-02 16:27:55 -04:00
} . bind ( this ) ;
2015-06-14 23:53:32 -08:00
}
2015-08-14 17:39:50 -07:00
}
2015-06-14 23:53:32 -08:00
2015-10-02 14:25:55 -04:00
let closeButton = null ;
2015-10-16 10:15:52 -04:00
const removeTooltip = (
< Tooltip id = 'remove-dm-tooltip' > { 'Remove from list' } < / Tooltip >
) ;
2015-10-05 13:16:39 -04:00
if ( handleClose && ! badge ) {
2015-10-02 14:25:55 -04:00
closeButton = (
2015-10-14 17:04:13 +05:00
< OverlayTrigger
2015-10-16 10:15:52 -04:00
delayShow = { 1000 }
2015-10-14 17:04:13 +05:00
placement = 'top'
overlay = { removeTooltip }
>
2015-10-02 14:25:55 -04:00
< span
2015-10-14 17:04:13 +05:00
className = 'btn-close'
2015-10-02 14:25:55 -04:00
data - close = 'true'
>
{ '× ' }
< / span >
2015-10-14 17:04:13 +05:00
< / OverlayTrigger >
2015-10-02 14:25:55 -04:00
) ;
2015-10-13 14:35:38 -04:00
2015-10-14 09:11:35 -04:00
rowClass += ' has-close' ;
2015-10-02 14:25:55 -04:00
}
2015-10-30 11:35:16 -04:00
let tutorialTip = null ;
if ( this . state . showTutorialTip && channel . name === Constants . DEFAULT _CHANNEL ) {
tutorialTip = this . createTutorialTip ( ) ;
}
2015-09-01 08:37:09 -04:00
return (
< li
key = { channel . name }
ref = { channel . name }
className = { linkClass }
>
< a
2015-10-13 14:35:38 -04:00
className = { rowClass }
2015-09-01 08:37:09 -04:00
href = { href }
onClick = { handleClick }
>
{ status }
{ channel . display _name }
{ badge }
2015-10-02 14:25:55 -04:00
{ closeButton }
2015-09-01 08:37:09 -04:00
< / a >
2015-10-30 11:35:16 -04:00
{ tutorialTip }
2015-09-01 08:37:09 -04:00
< / li >
) ;
}
render ( ) {
this . badgesActive = false ;
2015-10-26 17:53:21 +01:00
this . setUnreadCountPerChannel ( ) ;
2015-10-25 15:12:36 +01:00
2015-09-16 14:53:16 -04:00
// keep track of the first and last unread channels so we can use them to set the unread indicators
this . firstUnreadChannel = null ;
this . lastUnreadChannel = null ;
2015-09-01 08:37:09 -04:00
2015-08-06 14:03:45 -04:00
// create elements for all 3 types of channels
2015-11-03 14:52:25 -05:00
const publicChannelItems = this . state . publicChannels . map ( this . createChannelElement ) ;
2015-06-14 23:53:32 -08:00
2015-11-03 14:52:25 -05:00
const privateChannelItems = this . state . privateChannels . map ( this . createChannelElement ) ;
2015-08-06 14:03:45 -04:00
2015-10-02 14:25:55 -04:00
const directMessageItems = this . state . visibleDirectChannels . map ( ( channel , index , arr ) => {
return this . createChannelElement ( channel , index , arr , this . handleLeaveDirectChannel ) ;
} ) ;
2015-06-14 23:53:32 -08:00
2015-08-06 14:03:45 -04:00
// update the favicon to show if there are any notifications
2015-06-14 23:53:32 -08:00
var link = document . createElement ( 'link' ) ;
link . type = 'image/x-icon' ;
link . rel = 'shortcut icon' ;
link . id = 'favicon' ;
2015-09-01 08:37:09 -04:00
if ( this . badgesActive ) {
2015-06-14 23:53:32 -08:00
link . href = '/static/images/redfavicon.ico' ;
} else {
link . href = '/static/images/favicon.ico' ;
}
var head = document . getElementsByTagName ( 'head' ) [ 0 ] ;
var oldLink = document . getElementById ( 'favicon' ) ;
if ( oldLink ) {
head . removeChild ( oldLink ) ;
}
head . appendChild ( link ) ;
2015-08-06 19:07:51 -04:00
var directMessageMore = null ;
2015-10-14 16:57:03 -04:00
if ( this . state . hiddenDirectChannelCount > 0 ) {
2015-08-06 19:07:51 -04:00
directMessageMore = (
2015-10-02 14:25:55 -04:00
< li key = 'more' >
2015-09-01 08:37:09 -04:00
< a
href = '#'
2015-10-14 16:57:03 -04:00
onClick = { this . showMoreDirectChannelsModal }
2015-09-01 08:37:09 -04:00
>
2015-10-14 16:57:03 -04:00
{ 'More (' + this . state . hiddenDirectChannelCount + ')' }
2015-08-06 19:07:51 -04:00
< / a >
< / li >
) ;
}
2015-09-14 13:56:58 -04:00
let showChannelModal = false ;
2015-10-14 16:57:03 -04:00
if ( this . state . newChannelModalType !== '' ) {
2015-09-14 13:56:58 -04:00
showChannelModal = true ;
}
2015-10-16 10:15:52 -04:00
const createChannelTootlip = (
< Tooltip id = 'new-channel-tooltip' > { 'Create new channel' } < / Tooltip >
) ;
const createGroupTootlip = (
< Tooltip id = 'new-group-tooltip' > { 'Create new group' } < / Tooltip >
) ;
2015-10-14 17:04:13 +05:00
2015-06-14 23:53:32 -08:00
return (
< div >
2015-09-14 13:56:58 -04:00
< NewChannelFlow
show = { showChannelModal }
2015-10-14 16:57:03 -04:00
channelType = { this . state . newChannelModalType }
onModalDismissed = { this . hideNewChannelModal }
/ >
< MoreDirectChannels
show = { this . state . showDirectChannelsModal }
onModalDismissed = { this . hideMoreDirectChannelsModal }
2015-09-14 13:56:58 -04:00
/ >
2015-10-14 16:57:03 -04:00
2015-09-01 08:37:09 -04:00
< SidebarHeader
2015-10-27 15:48:51 -04:00
teamDisplayName = { TeamStore . getCurrent ( ) . display _name }
teamName = { TeamStore . getCurrent ( ) . name }
teamType = { TeamStore . getCurrent ( ) . type }
2015-09-01 08:37:09 -04:00
/ >
2015-06-14 23:53:32 -08:00
< SearchBox / >
2015-09-16 14:53:16 -04:00
< UnreadChannelIndicator
show = { this . state . showTopUnread }
extraClass = 'nav-pills__unread-indicator-top'
text = { 'Unread post(s) above' }
/ >
< UnreadChannelIndicator
show = { this . state . showBottomUnread }
extraClass = 'nav-pills__unread-indicator-bottom'
text = { 'Unread post(s) below' }
2015-09-15 17:36:48 -04:00
/ >
2015-08-06 18:57:57 -04:00
2015-09-01 08:37:09 -04:00
< div
ref = 'container'
className = 'nav-pills__container'
onScroll = { this . onScroll }
>
2015-08-03 12:09:27 -07:00
< ul className = 'nav nav-pills nav-stacked' >
2015-09-01 08:37:09 -04:00
< li >
< h4 >
2015-10-07 13:07:59 -04:00
{ 'Channels' }
2015-10-14 17:04:13 +05:00
< OverlayTrigger
2015-10-16 10:15:52 -04:00
delayShow = { 500 }
2015-10-14 17:04:13 +05:00
placement = 'top'
overlay = { createChannelTootlip }
>
2015-09-01 08:37:09 -04:00
< a
className = 'add-channel-btn'
href = '#'
2015-10-14 16:57:03 -04:00
onClick = { this . showNewChannelModal . bind ( this , 'O' ) }
2015-09-01 08:37:09 -04:00
>
2015-09-14 13:56:58 -04:00
{ '+' }
2015-09-01 08:37:09 -04:00
< / a >
2015-10-14 17:04:13 +05:00
< / OverlayTrigger >
2015-09-01 08:37:09 -04:00
< / h4 >
< / li >
2015-09-15 17:36:48 -04:00
{ publicChannelItems }
2015-09-01 08:37:09 -04:00
< li >
< a
href = '#'
data - toggle = 'modal'
className = 'nav-more'
data - target = '#more_channels'
data - channeltype = 'O'
>
2015-10-07 13:07:59 -04:00
{ 'More...' }
2015-09-01 08:37:09 -04:00
< / a >
< / li >
2015-06-14 23:53:32 -08:00
< / ul >
2015-08-03 12:09:27 -07:00
< ul className = 'nav nav-pills nav-stacked' >
2015-09-01 08:37:09 -04:00
< li >
< h4 >
2015-10-07 13:07:59 -04:00
{ 'Private Groups' }
2015-10-14 17:04:13 +05:00
< OverlayTrigger
2015-10-16 10:15:52 -04:00
delayShow = { 500 }
2015-10-14 17:04:13 +05:00
placement = 'top'
overlay = { createGroupTootlip }
>
2015-09-01 08:37:09 -04:00
< a
className = 'add-channel-btn'
href = '#'
2015-10-14 16:57:03 -04:00
onClick = { this . showNewChannelModal . bind ( this , 'P' ) }
2015-09-01 08:37:09 -04:00
>
2015-09-14 13:56:58 -04:00
{ '+' }
2015-09-01 08:37:09 -04:00
< / a >
2015-10-14 17:04:13 +05:00
< / OverlayTrigger >
2015-09-01 08:37:09 -04:00
< / h4 >
< / li >
2015-06-14 23:53:32 -08:00
{ privateChannelItems }
< / ul >
2015-08-03 12:09:27 -07:00
< ul className = 'nav nav-pills nav-stacked' >
2015-10-07 13:07:59 -04:00
< li > < h4 > { 'Direct Messages' } < / h4 > < / li >
2015-06-14 23:53:32 -08:00
{ directMessageItems }
2015-08-06 19:07:51 -04:00
{ directMessageMore }
2015-06-14 23:53:32 -08:00
< / ul >
< / div >
< / div >
) ;
}
2015-09-01 08:37:09 -04:00
}
Sidebar . defaultProps = {
} ;
Sidebar . propTypes = {
} ;