From 95251258f513d076c99da164e607dae5c39b9275 Mon Sep 17 00:00:00 2001
From: George Goldberg <george@gberg.me>
Date: Sun, 15 Jan 2017 15:40:43 +0000
Subject: PLT-5049 (Webapp) New Channel Members UI. (#5036)

This replaces the existing Channel Members UI with one based on the Team
Members UI, so that either a button, a role or a role with a menu can be
displayed.

Basic logic for which actions and roles are displayed is implemented,
although this doesn't change behaviour or functionality at all, as that
will come in later PRs. It does, however, add code to fetch the
ChannelMember objects as that is necessary to provide the full set of
actions and roles as intended.
---
 webapp/components/member_list_channel.jsx | 173 ++++++++++++++++++++++++++++++
 1 file changed, 173 insertions(+)
 create mode 100644 webapp/components/member_list_channel.jsx

(limited to 'webapp/components/member_list_channel.jsx')

diff --git a/webapp/components/member_list_channel.jsx b/webapp/components/member_list_channel.jsx
new file mode 100644
index 000000000..75ecd8172
--- /dev/null
+++ b/webapp/components/member_list_channel.jsx
@@ -0,0 +1,173 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import ChannelMembersDropdown from 'components/channel_members_dropdown.jsx';
+import SearchableUserList from 'components/searchable_user_list.jsx';
+
+import ChannelStore from 'stores/channel_store.jsx';
+import UserStore from 'stores/user_store.jsx';
+import TeamStore from 'stores/team_store.jsx';
+
+import {searchUsers, loadProfilesAndTeamMembersAndChannelMembers, loadTeamMembersAndChannelMembersForProfilesList} from 'actions/user_actions.jsx';
+import {getChannelStats} from 'utils/async_client.jsx';
+
+import Constants from 'utils/constants.jsx';
+
+import * as UserAgent from 'utils/user_agent.jsx';
+
+import React from 'react';
+
+const USERS_PER_PAGE = 50;
+
+export default class MemberListChannel extends React.Component {
+    constructor(props) {
+        super(props);
+
+        this.onChange = this.onChange.bind(this);
+        this.onStatsChange = this.onStatsChange.bind(this);
+        this.search = this.search.bind(this);
+        this.loadComplete = this.loadComplete.bind(this);
+
+        this.searchTimeoutId = 0;
+
+        const stats = ChannelStore.getCurrentStats();
+
+        this.state = {
+            users: UserStore.getProfileListInChannel(),
+            teamMembers: Object.assign({}, TeamStore.getMembersInTeam()),
+            channelMembers: Object.assign({}, ChannelStore.getMembersInChannel()),
+            total: stats.member_count,
+            search: false,
+            term: '',
+            loading: true
+        };
+    }
+
+    componentDidMount() {
+        UserStore.addInTeamChangeListener(this.onChange);
+        UserStore.addStatusesChangeListener(this.onChange);
+        TeamStore.addChangeListener(this.onChange);
+        ChannelStore.addChangeListener(this.onChange);
+        ChannelStore.addStatsChangeListener(this.onStatsChange);
+
+        loadProfilesAndTeamMembersAndChannelMembers(0, Constants.PROFILE_CHUNK_SIZE, TeamStore.getCurrentId(), ChannelStore.getCurrentId(), this.loadComplete);
+        getChannelStats(ChannelStore.getCurrentId());
+    }
+
+    componentWillUnmount() {
+        UserStore.removeInTeamChangeListener(this.onChange);
+        UserStore.removeStatusesChangeListener(this.onChange);
+        TeamStore.removeChangeListener(this.onChange);
+        ChannelStore.removeChangeListener(this.onChange);
+        ChannelStore.removeStatsChangeListener(this.onStatsChange);
+    }
+
+    loadComplete() {
+        this.setState({loading: false});
+    }
+
+    onChange(force) {
+        if (this.state.search && !force) {
+            return;
+        } else if (this.state.search) {
+            this.search(this.state.term);
+            return;
+        }
+
+        this.setState({
+            users: UserStore.getProfileListInChannel(),
+            teamMembers: Object.assign({}, TeamStore.getMembersInTeam()),
+            channelMembers: Object.assign({}, ChannelStore.getMembersInChannel())
+        });
+    }
+
+    onStatsChange() {
+        const stats = ChannelStore.getCurrentStats();
+        this.setState({total: stats.member_count});
+    }
+
+    nextPage(page) {
+        loadProfilesAndTeamMembersAndChannelMembers((page + 1) * USERS_PER_PAGE, USERS_PER_PAGE);
+    }
+
+    search(term) {
+        if (term === '') {
+            this.setState({
+                search: false,
+                term,
+                users: UserStore.getProfileListInChannel(),
+                teamMembers: Object.assign([], TeamStore.getMembersInTeam()),
+                channelMembers: Object.assign([], ChannelStore.getMembersInChannel())
+            });
+            return;
+        }
+
+        clearTimeout(this.searchTimeoutId);
+
+        this.searchTimeoutId = setTimeout(
+            () => {
+                searchUsers(
+                    term,
+                    TeamStore.getCurrentId(),
+                    {},
+                    (users) => {
+                        this.setState({
+                            loading: true,
+                            search: true,
+                            users,
+                            term,
+                            teamMembers: Object.assign([], TeamStore.getMembersInTeam()),
+                            channelMembers: Object.assign([], ChannelStore.getMembersInChannel())
+                        });
+                        loadTeamMembersAndChannelMembersForProfilesList(users, TeamStore.getCurrentId(), ChannelStore.getCurrentId(), this.loadComplete);
+                    }
+                );
+            },
+            Constants.SEARCH_TIMEOUT_MILLISECONDS
+        );
+    }
+
+    render() {
+        const teamMembers = this.state.teamMembers;
+        const channelMembers = this.state.channelMembers;
+        const users = this.state.users;
+        const actionUserProps = {};
+
+        let usersToDisplay;
+        if (this.state.loading) {
+            usersToDisplay = null;
+        } else {
+            usersToDisplay = [];
+
+            for (let i = 0; i < users.length; i++) {
+                const user = users[i];
+
+                if (teamMembers[user.id] && channelMembers[user.id]) {
+                    usersToDisplay.push(user);
+                    actionUserProps[user.id] = {
+                        channel: this.props.channel,
+                        teamMember: teamMembers[user.id],
+                        channelMember: channelMembers[user.id]
+                    };
+                }
+            }
+        }
+
+        return (
+            <SearchableUserList
+                users={usersToDisplay}
+                usersPerPage={USERS_PER_PAGE}
+                total={this.state.total}
+                nextPage={this.nextPage}
+                search={this.search}
+                actions={[ChannelMembersDropdown]}
+                actionUserProps={actionUserProps}
+                focusOnMount={!UserAgent.isMobile()}
+            />
+        );
+    }
+}
+
+MemberListChannel.propTypes = {
+    channel: React.PropTypes.object.isRequired
+};
-- 
cgit v1.2.3-1-g7c22

