From ae0d4dce7bc42f75568d65aa66c8db244f8f329f Mon Sep 17 00:00:00 2001
From: hmhealey <harrisonmhealey@gmail.com>
Date: Wed, 14 Oct 2015 16:57:03 -0400
Subject: Updated More Direct Channels modal and converted it to ReactBootstrap

---
 web/react/components/more_direct_channels.jsx | 350 ++++++++++++++++++--------
 1 file changed, 245 insertions(+), 105 deletions(-)

(limited to 'web/react/components/more_direct_channels.jsx')

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
+};
-- 
cgit v1.2.3-1-g7c22

