diff options
author | Christopher Speller <crspeller@gmail.com> | 2015-10-15 13:34:42 -0400 |
---|---|---|
committer | Christopher Speller <crspeller@gmail.com> | 2015-10-15 13:34:42 -0400 |
commit | f09685a37398da7808117b960321a14ab7989da7 (patch) | |
tree | ba26c3925482553465ba589ba009a2e74fb3f4c2 /web/react/components/more_direct_channels.jsx | |
parent | adc20981e2c370f09467d4fa249065d23f533a0a (diff) | |
parent | ae0d4dce7bc42f75568d65aa66c8db244f8f329f (diff) | |
download | chat-f09685a37398da7808117b960321a14ab7989da7.tar.gz chat-f09685a37398da7808117b960321a14ab7989da7.tar.bz2 chat-f09685a37398da7808117b960321a14ab7989da7.zip |
Merge pull request #1057 from hmhealey/plt520
PLT-520 Updated More Direct Channels modal and converted it to ReactBootstrap
Diffstat (limited to 'web/react/components/more_direct_channels.jsx')
-rw-r--r-- | web/react/components/more_direct_channels.jsx | 350 |
1 files changed, 245 insertions, 105 deletions
diff --git a/web/react/components/more_direct_channels.jsx b/web/react/components/more_direct_channels.jsx index bc610cd60..99babe714 100644 --- a/web/react/components/more_direct_channels.jsx +++ b/web/react/components/more_direct_channels.jsx @@ -1,133 +1,273 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -var TeamStore = require('../stores/team_store.jsx'); -var Client = require('../utils/client.jsx'); -var Constants = require('../utils/constants.jsx'); -var AsyncClient = require('../utils/async_client.jsx'); -var PreferenceStore = require('../stores/preference_store.jsx'); -var utils = require('../utils/utils.jsx'); +const AsyncClient = require('../utils/async_client.jsx'); +const ChannelStore = require('../stores/channel_store.jsx'); +const Constants = require('../utils/constants.jsx'); +const Client = require('../utils/client.jsx'); +const Modal = ReactBootstrap.Modal; +const PreferenceStore = require('../stores/preference_store.jsx'); +const TeamStore = require('../stores/team_store.jsx'); +const UserStore = require('../stores/user_store.jsx'); +const Utils = require('../utils/utils.jsx'); export default class MoreDirectChannels extends React.Component { constructor(props) { super(props); - this.state = {channels: [], loadingDMChannel: -1}; + this.handleFilterChange = this.handleFilterChange.bind(this); + this.handleHide = this.handleHide.bind(this); + this.handleShowDirectChannel = this.handleShowDirectChannel.bind(this); + this.handleUserChange = this.handleUserChange.bind(this); + + this.createRowForUser = this.createRowForUser.bind(this); + + this.state = { + users: this.getUsersFromStore(), + filter: '', + loadingDMChannel: -1 + }; + } + + getUsersFromStore() { + const currentId = UserStore.getCurrentId(); + const profiles = UserStore.getProfiles(); + const users = []; + + for (const id in profiles) { + if (id !== currentId) { + users.push(profiles[id]); + } + } + + users.sort((a, b) => a.username.localeCompare(b.username)); + + return users; } componentDidMount() { - $(React.findDOMNode(this.refs.modal)).on('show.bs.modal', (e) => { - var button = e.relatedTarget; - this.setState({channels: $(button).data('channels')}); // eslint-disable-line react/no-did-mount-set-state - }); + UserStore.addChangeListener(this.handleUserChange); } - handleJoinDirectChannel(channel) { - const preference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, channel.teammate_id, 'true'); - AsyncClient.savePreferences([preference]); + componentWillUnmount() { + UserStore.addChangeListener(this.handleUserChange); } - render() { - var directMessageItems = this.state.channels.map((channel, index) => { - var badge = ''; - var titleClass = ''; - var handleClick = null; - - if (channel.fake) { - // It's a direct message channel that doesn't exist yet so let's create it now - var otherUserId = utils.getUserIdFromChannelName(channel); - - if (this.state.loadingDMChannel === index) { - badge = ( - <img - className='channel-loading-gif pull-right' - src='/static/images/load.gif' - /> - ); - } + handleFilterChange() { + const filter = React.findDOMNode(this.refs.filter).value; - if (this.state.loadingDMChannel === -1) { - handleClick = (e) => { - e.preventDefault(); - this.setState({loadingDMChannel: index}); - this.handleJoinDirectChannel(channel); - - Client.createDirectChannel(channel, otherUserId, - (data) => { - $(React.findDOMNode(this.refs.modal)).modal('hide'); - this.setState({loadingDMChannel: -1}); - AsyncClient.getChannel(data.id); - utils.switchChannel(data); - }, - () => { - this.setState({loadingDMChannel: -1}); - window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/' + channel.name; - } - ); - }; - } - } else { - if (channel.unread) { - badge = <span className='badge pull-right small'>{channel.unread}</span>; - titleClass = 'unread-title'; + if (filter !== this.state.filter) { + this.setState({filter}); + } + } + + handleHide() { + if (this.props.onModalDismissed) { + this.props.onModalDismissed(); + } + + this.setState({filter: ''}); + } + + handleShowDirectChannel(teammate, e) { + if (this.state.loadingDMChannel !== -1) { + return; + } + + e.preventDefault(); + + const channelName = Utils.getDirectChannelName(UserStore.getCurrentId(), teammate.id); + let channel = ChannelStore.getByName(channelName); + + const preference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, teammate.id, 'true'); + AsyncClient.savePreferences([preference]); + + if (channel) { + Utils.switchChannel(channel); + + this.handleHide(); + } else { + this.setState({loadingDMChannel: teammate.id}); + + channel = { + name: channelName, + last_post_at: 0, + total_msg_count: 0, + type: 'D', + display_name: teammate.username, + teammate_id: teammate.id, + status: UserStore.getStatus(teammate.id) + }; + + Client.createDirectChannel( + channel, + teammate.id, + (data) => { + this.setState({loadingDMChannel: -1}); + + AsyncClient.getChannel(data.id); + Utils.switchChannel(data); + + this.handleHide(); + }, + () => { + this.setState({loadingDMChannel: -1}); + window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/' + channelName; } + ); + } + } - handleClick = (e) => { - e.preventDefault(); - this.handleJoinDirectChannel(channel); - utils.switchChannel(channel); - $(React.findDOMNode(this.refs.modal)).modal('hide'); - }; - } + handleUserChange() { + this.setState({users: this.getUsersFromStore()}); + } + + createRowForUser(user) { + const details = []; + + const fullName = Utils.getFullName(user); + if (fullName) { + details.push( + <span + key={`${user.id}__full-name`} + className='full-name' + > + {fullName} + </span> + ); + } - return ( - <li key={channel.name}> - <a - className={'sidebar-channel ' + titleClass} - href='#' - onClick={handleClick} - >{badge}{channel.display_name}</a> - </li> + if (user.nickname) { + const separator = fullName ? ' - ' : ''; + details.push( + <span + key={`${user.nickname}__nickname`} + className='nickname' + > + {separator + user.nickname} + </span> ); - }); + } + + let joinButton; + if (this.state.loadingDMChannel === user.id) { + joinButton = ( + <img + className='channel-loading-gif' + src='/static/images/load.gif' + /> + ); + } else { + joinButton = ( + <button + type='button' + className='btn btn-primary btn-message' + onClick={this.handleShowDirectChannel.bind(this, user)} + > + {'Message'} + </button> + ); + } return ( - <div - className='modal fade' - id='more_direct_channels' - ref='modal' - tabIndex='-1' - role='dialog' - aria-hidden='true' + <li + key={user.id} + className='direct-channel' > - <div className='modal-dialog'> - <div className='modal-content'> - <div className='modal-header'> - <button - type='button' - className='close' - data-dismiss='modal' - > - <span aria-hidden='true'>{'×'}</span> - <span className='sr-only'>{'Close'}</span> - </button> - <h4 className='modal-title'>{'More Direct Messages'}</h4> - </div> - <div className='modal-body'> - <ul className='nav nav-pills nav-stacked'> - {directMessageItems} - </ul> - </div> - <div className='modal-footer'> - <button - type='button' - className='btn btn-default' - data-dismiss='modal' - >{'Close'}</button> - </div> + <div className='col-xs-1 image-div'> + <img + className='profile-image' + src={`/api/v1/users/${user.id}/image?time=${user.update_at}`} + /> + </div> + <div className='col-xs-9'> + <div className='username'> + {user.username} </div> + <div> + {details} + </div> + </div> + <div className='col-xs-2 btn-div'> + {joinButton} </div> - </div> + </li> + ); + } + + render() { + if (!this.props.show) { + return null; + } + + let users = this.state.users; + if (this.state.filter !== '') { + users = users.filter((user) => { + return user.username.indexOf(this.state.filter) !== -1 || + user.first_name.indexOf(this.state.filter) !== -1 || + user.last_name.indexOf(this.state.filter) !== -1 || + user.nickname.indexOf(this.state.filter) !== -1; + }); + } + + const userEntries = users.map(this.createRowForUser); + + if (userEntries.length === 0) { + userEntries.push(<li key='no-users-found'>{'No users found :('}</li>); + } + + let memberString = 'Member'; + if (users.length !== 1) { + memberString += 's'; + } + + let count; + if (users.length === this.state.users.length) { + count = `${users.length} ${memberString}`; + } else { + count = `${users.length} ${memberString} of ${this.state.users.length} Total`; + } + + return ( + <Modal + className='modal-direct-channels' + show={this.props.show} + bsSize='large' + onHide={this.handleHide} + > + <Modal.Header closeButton={true}> + <Modal.Title>{'More Direct Messages'}</Modal.Title> + </Modal.Header> + <Modal.Body> + <div> + <input + ref='filter' + className='form-control filter-textbox' + placeholder='Search members' + onInput={this.handleFilterChange} + style={{width: '200px', display: 'inline'}} + /> + <span className='member-count pull-right'>{count}</span> + </div> + <ul className='user-list'> + {userEntries} + </ul> + </Modal.Body> + <Modal.Footer> + <button + type='button' + className='btn btn-default' + onClick={this.handleHide} + > + {'Close'} + </button> + </Modal.Footer> + </Modal> ); } } + +MoreDirectChannels.propTypes = { + show: React.PropTypes.bool.isRequired, + onModalDismissed: React.PropTypes.func +}; |