From 96906482cecb0df21c8e1a40a2ba00c13c0182a7 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 28 Apr 2017 13:16:03 -0400 Subject: PLT-6214 Move channel store and actions over to redux (#6235) * Move channel store and actions over to redux * Fix style errors * Fix unit test * Various fixes * More fixes * Revert config changes --- webapp/components/channel_members_dropdown.jsx | 264 -------------------- .../channel_members_dropdown.jsx | 266 +++++++++++++++++++++ .../components/channel_members_dropdown/index.js | 24 ++ webapp/components/channel_members_modal.jsx | 2 +- webapp/components/channel_view.jsx | 2 +- webapp/components/member_list_channel.jsx | 169 ------------- webapp/components/member_list_channel/index.js | 24 ++ .../member_list_channel/member_list_channel.jsx | 171 +++++++++++++ webapp/components/more_channels.jsx | 201 ---------------- webapp/components/more_channels/index.js | 24 ++ webapp/components/more_channels/more_channels.jsx | 203 ++++++++++++++++ webapp/components/needs_team.jsx | 231 ------------------ webapp/components/needs_team/index.js | 25 ++ webapp/components/needs_team/needs_team.jsx | 234 ++++++++++++++++++ webapp/components/new_channel_flow.jsx | 6 +- webapp/components/post_view/index.js | 24 ++ webapp/components/post_view/post_view_cache.jsx | 9 +- webapp/components/rename_channel_modal.jsx | 5 +- webapp/components/sidebar.jsx | 2 +- webapp/components/team_members_dropdown/index.js | 4 +- .../team_members_dropdown.jsx | 8 +- 21 files changed, 1018 insertions(+), 880 deletions(-) delete mode 100644 webapp/components/channel_members_dropdown.jsx create mode 100644 webapp/components/channel_members_dropdown/channel_members_dropdown.jsx create mode 100644 webapp/components/channel_members_dropdown/index.js delete mode 100644 webapp/components/member_list_channel.jsx create mode 100644 webapp/components/member_list_channel/index.js create mode 100644 webapp/components/member_list_channel/member_list_channel.jsx delete mode 100644 webapp/components/more_channels.jsx create mode 100644 webapp/components/more_channels/index.js create mode 100644 webapp/components/more_channels/more_channels.jsx delete mode 100644 webapp/components/needs_team.jsx create mode 100644 webapp/components/needs_team/index.js create mode 100644 webapp/components/needs_team/needs_team.jsx create mode 100644 webapp/components/post_view/index.js (limited to 'webapp/components') diff --git a/webapp/components/channel_members_dropdown.jsx b/webapp/components/channel_members_dropdown.jsx deleted file mode 100644 index e44108f3c..000000000 --- a/webapp/components/channel_members_dropdown.jsx +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import ChannelStore from 'stores/channel_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import {removeUserFromChannel, makeUserChannelAdmin, makeUserChannelMember} from 'actions/channel_actions.jsx'; - -import * as AsyncClient from 'utils/async_client.jsx'; -import * as Utils from 'utils/utils.jsx'; -import {canManageMembers} from 'utils/channel_utils.jsx'; -import {Constants} from 'utils/constants.jsx'; - -import React from 'react'; -import {FormattedMessage} from 'react-intl'; - -export default class ChannelMembersDropdown extends React.Component { - constructor(props) { - super(props); - - this.handleRemoveFromChannel = this.handleRemoveFromChannel.bind(this); - this.handleMakeChannelMember = this.handleMakeChannelMember.bind(this); - this.handleMakeChannelAdmin = this.handleMakeChannelAdmin.bind(this); - - this.state = { - serverError: null, - user: null, - role: null - }; - } - - handleRemoveFromChannel() { - removeUserFromChannel( - this.props.channel.id, - this.props.user.id, - () => { - AsyncClient.getChannelStats(this.props.channel.id); - }, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - handleMakeChannelMember() { - makeUserChannelMember( - this.props.channel.id, - this.props.user.id, - () => { - AsyncClient.getChannelStats(this.props.channel.id); - }, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - handleMakeChannelAdmin() { - makeUserChannelAdmin( - this.props.channel.id, - this.props.user.id, - () => { - AsyncClient.getChannelStats(this.props.channel.id); - }, - (err) => { - this.setState({serverError: err.message}); - } - ); - } - - // Checks if the user this menu is for is a channel admin or not. - isChannelAdmin() { - if (Utils.isChannelAdmin(this.props.channelMember.roles)) { - return true; - } - - return false; - } - - // Checks if the current user has the power to change the roles of this member. - canChangeMemberRoles() { - if (UserStore.isSystemAdminForCurrentUser()) { - return true; - } else if (TeamStore.isTeamAdminForCurrentTeam()) { - return true; - } else if (ChannelStore.isChannelAdminForCurrentChannel()) { - return true; - } - - return false; - } - - // Checks if the current user has the power to remove this member from the channel. - canRemoveMember() { - return canManageMembers(this.props.channel, UserStore.isSystemAdminForCurrentUser(), TeamStore.isTeamAdminForCurrentTeam(), ChannelStore.isChannelAdminForCurrentChannel()); - } - - render() { - let serverError = null; - if (this.state.serverError) { - serverError = ( -
- -
- ); - } - - if (this.props.user.id === UserStore.getCurrentId()) { - return null; - } - - if (this.canChangeMemberRoles()) { - let role = ( - - ); - - if (this.isChannelAdmin()) { - role = ( - - ); - } - - let removeFromChannel = null; - if (this.canRemoveMember() && this.props.channel.name !== Constants.DEFAULT_CHANNEL) { - removeFromChannel = ( -
  • - - - -
  • - ); - } - - let makeChannelMember = null; - if (this.isChannelAdmin()) { - makeChannelMember = ( -
  • - - - -
  • - ); - } - - let makeChannelAdmin = null; - if (!this.isChannelAdmin()) { - makeChannelAdmin = ( -
  • - - - -
  • - ); - } - - return ( -
    - - {role} - - -
      - {makeChannelMember} - {makeChannelAdmin} - {removeFromChannel} -
    - {serverError} -
    - ); - } else if (this.canRemoveMember() && this.props.channel.name !== Constants.DEFAULT_CHANNEL) { - return ( - - ); - } else if (this.isChannelAdmin()) { - if (this.props.channel.name === Constants.DEFAULT_CHANNEL) { - return ( -
    - ); - } - - return ( -
    - -
    - ); - } - - if (this.props.channel.name === Constants.DEFAULT_CHANNEL) { - return ( -
    - ); - } - - return ( -
    - -
    - ); - } -} - -ChannelMembersDropdown.propTypes = { - channel: React.PropTypes.object.isRequired, - user: React.PropTypes.object.isRequired, - teamMember: React.PropTypes.object.isRequired, - channelMember: React.PropTypes.object.isRequired -}; diff --git a/webapp/components/channel_members_dropdown/channel_members_dropdown.jsx b/webapp/components/channel_members_dropdown/channel_members_dropdown.jsx new file mode 100644 index 000000000..f7d42ce9b --- /dev/null +++ b/webapp/components/channel_members_dropdown/channel_members_dropdown.jsx @@ -0,0 +1,266 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import ChannelStore from 'stores/channel_store.jsx'; +import TeamStore from 'stores/team_store.jsx'; +import UserStore from 'stores/user_store.jsx'; + +import {removeUserFromChannel, makeUserChannelAdmin, makeUserChannelMember} from 'actions/channel_actions.jsx'; + +import * as Utils from 'utils/utils.jsx'; +import {canManageMembers} from 'utils/channel_utils.jsx'; +import {Constants} from 'utils/constants.jsx'; + +import React from 'react'; +import {FormattedMessage} from 'react-intl'; + +export default class ChannelMembersDropdown extends React.Component { + static propTypes = { + channel: React.PropTypes.object.isRequired, + user: React.PropTypes.object.isRequired, + teamMember: React.PropTypes.object.isRequired, + channelMember: React.PropTypes.object.isRequired, + actions: React.PropTypes.shape({ + getChannelStats: React.PropTypes.func.isRequired + }).isRequired + } + + constructor(props) { + super(props); + + this.handleRemoveFromChannel = this.handleRemoveFromChannel.bind(this); + this.handleMakeChannelMember = this.handleMakeChannelMember.bind(this); + this.handleMakeChannelAdmin = this.handleMakeChannelAdmin.bind(this); + + this.state = { + serverError: null, + user: null, + role: null + }; + } + + handleRemoveFromChannel() { + removeUserFromChannel( + this.props.channel.id, + this.props.user.id, + () => { + this.props.actions.getChannelStats(this.props.channel.id); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + + handleMakeChannelMember() { + makeUserChannelMember( + this.props.channel.id, + this.props.user.id, + () => { + this.props.actions.getChannelStats(this.props.channel.id); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + + handleMakeChannelAdmin() { + makeUserChannelAdmin( + this.props.channel.id, + this.props.user.id, + () => { + this.props.actions.getChannelStats(this.props.channel.id); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + + // Checks if the user this menu is for is a channel admin or not. + isChannelAdmin() { + if (Utils.isChannelAdmin(this.props.channelMember.roles)) { + return true; + } + + return false; + } + + // Checks if the current user has the power to change the roles of this member. + canChangeMemberRoles() { + if (UserStore.isSystemAdminForCurrentUser()) { + return true; + } else if (TeamStore.isTeamAdminForCurrentTeam()) { + return true; + } else if (ChannelStore.isChannelAdminForCurrentChannel()) { + return true; + } + + return false; + } + + // Checks if the current user has the power to remove this member from the channel. + canRemoveMember() { + return canManageMembers(this.props.channel, UserStore.isSystemAdminForCurrentUser(), TeamStore.isTeamAdminForCurrentTeam(), ChannelStore.isChannelAdminForCurrentChannel()); + } + + render() { + let serverError = null; + if (this.state.serverError) { + serverError = ( +
    + +
    + ); + } + + if (this.props.user.id === UserStore.getCurrentId()) { + return null; + } + + if (this.canChangeMemberRoles()) { + let role = ( + + ); + + if (this.isChannelAdmin()) { + role = ( + + ); + } + + let removeFromChannel = null; + if (this.canRemoveMember() && this.props.channel.name !== Constants.DEFAULT_CHANNEL) { + removeFromChannel = ( +
  • + + + +
  • + ); + } + + let makeChannelMember = null; + if (this.isChannelAdmin()) { + makeChannelMember = ( +
  • + + + +
  • + ); + } + + let makeChannelAdmin = null; + if (!this.isChannelAdmin()) { + makeChannelAdmin = ( +
  • + + + +
  • + ); + } + + return ( +
    + + {role} + + +
      + {makeChannelMember} + {makeChannelAdmin} + {removeFromChannel} +
    + {serverError} +
    + ); + } else if (this.canRemoveMember() && this.props.channel.name !== Constants.DEFAULT_CHANNEL) { + return ( + + ); + } else if (this.isChannelAdmin()) { + if (this.props.channel.name === Constants.DEFAULT_CHANNEL) { + return ( +
    + ); + } + + return ( +
    + +
    + ); + } + + if (this.props.channel.name === Constants.DEFAULT_CHANNEL) { + return ( +
    + ); + } + + return ( +
    + +
    + ); + } +} diff --git a/webapp/components/channel_members_dropdown/index.js b/webapp/components/channel_members_dropdown/index.js new file mode 100644 index 000000000..11a626e46 --- /dev/null +++ b/webapp/components/channel_members_dropdown/index.js @@ -0,0 +1,24 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; +import {getChannelStats} from 'mattermost-redux/actions/channels'; + +import ChannelMembersDropdown from './channel_members_dropdown.jsx'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + getChannelStats + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(ChannelMembersDropdown); diff --git a/webapp/components/channel_members_modal.jsx b/webapp/components/channel_members_modal.jsx index dab51a1bd..492bc8809 100644 --- a/webapp/components/channel_members_modal.jsx +++ b/webapp/components/channel_members_modal.jsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import MemberListChannel from './member_list_channel.jsx'; +import MemberListChannel from 'components/member_list_channel'; import TeamStore from 'stores/team_store.jsx'; import UserStore from 'stores/user_store.jsx'; diff --git a/webapp/components/channel_view.jsx b/webapp/components/channel_view.jsx index d6a931e0b..e9fb4cf94 100644 --- a/webapp/components/channel_view.jsx +++ b/webapp/components/channel_view.jsx @@ -8,7 +8,7 @@ import * as UserAgent from 'utils/user_agent.jsx'; import ChannelHeader from 'components/channel_header.jsx'; import FileUploadOverlay from 'components/file_upload_overlay.jsx'; import CreatePost from 'components/create_post.jsx'; -import PostViewCache from 'components/post_view/post_view_cache.jsx'; +import PostViewCache from 'components/post_view'; import ChannelStore from 'stores/channel_store.jsx'; diff --git a/webapp/components/member_list_channel.jsx b/webapp/components/member_list_channel.jsx deleted file mode 100644 index df000c132..000000000 --- a/webapp/components/member_list_channel.jsx +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2017-present 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/searchable_user_list_container.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'; - -import store from 'stores/redux_store.jsx'; -import {searchProfilesInCurrentChannel} from 'mattermost-redux/selectors/entities/users'; - -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; - this.term = ''; - - const stats = ChannelStore.getCurrentStats(); - - this.state = { - users: UserStore.getProfileListInChannel(), - teamMembers: Object.assign({}, TeamStore.getMembersInTeam()), - channelMembers: Object.assign({}, ChannelStore.getMembersInChannel()), - total: stats.member_count, - 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() { - let users; - if (this.term) { - users = searchProfilesInCurrentChannel(store.getState(), this.term); - } else { - users = UserStore.getProfileListInChannel(); - } - - this.setState({ - users, - 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); - } - - search(term) { - clearTimeout(this.searchTimeoutId); - this.term = term; - - if (term === '') { - this.setState({loading: false}); - this.searchTimeoutId = ''; - this.onChange(); - return; - } - - const searchTimeoutId = setTimeout( - () => { - searchUsers(term, TeamStore.getCurrentId(), {}, - (users) => { - if (searchTimeoutId !== this.searchTimeoutId) { - return; - } - - this.setState({loading: true}); - - loadTeamMembersAndChannelMembersForProfilesList(users, TeamStore.getCurrentId(), ChannelStore.getCurrentId(), this.loadComplete); - } - ); - }, - Constants.SEARCH_TIMEOUT_MILLISECONDS - ); - - this.searchTimeoutId = searchTimeoutId; - } - - 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 ( - - ); - } -} - -MemberListChannel.propTypes = { - channel: React.PropTypes.object.isRequired -}; diff --git a/webapp/components/member_list_channel/index.js b/webapp/components/member_list_channel/index.js new file mode 100644 index 000000000..c0f70709e --- /dev/null +++ b/webapp/components/member_list_channel/index.js @@ -0,0 +1,24 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; +import {getChannelStats} from 'mattermost-redux/actions/channels'; + +import MemberListChannel from './member_list_channel.jsx'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + getChannelStats + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(MemberListChannel); diff --git a/webapp/components/member_list_channel/member_list_channel.jsx b/webapp/components/member_list_channel/member_list_channel.jsx new file mode 100644 index 000000000..af2304433 --- /dev/null +++ b/webapp/components/member_list_channel/member_list_channel.jsx @@ -0,0 +1,171 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import ChannelMembersDropdown from 'components/channel_members_dropdown'; +import SearchableUserList from 'components/searchable_user_list/searchable_user_list_container.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 Constants from 'utils/constants.jsx'; + +import * as UserAgent from 'utils/user_agent.jsx'; + +import React from 'react'; + +import store from 'stores/redux_store.jsx'; +import {searchProfilesInCurrentChannel} from 'mattermost-redux/selectors/entities/users'; + +const USERS_PER_PAGE = 50; + +export default class MemberListChannel extends React.Component { + static propTypes = { + channel: React.PropTypes.object.isRequired, + actions: React.PropTypes.shape({ + getChannelStats: React.PropTypes.func.isRequired + }).isRequired + } + + 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; + this.term = ''; + + const stats = ChannelStore.getCurrentStats(); + + this.state = { + users: UserStore.getProfileListInChannel(), + teamMembers: Object.assign({}, TeamStore.getMembersInTeam()), + channelMembers: Object.assign({}, ChannelStore.getMembersInChannel()), + total: stats.member_count, + 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); + this.props.actions.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() { + let users; + if (this.term) { + users = searchProfilesInCurrentChannel(store.getState(), this.term); + } else { + users = UserStore.getProfileListInChannel(); + } + + this.setState({ + users, + 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); + } + + search(term) { + clearTimeout(this.searchTimeoutId); + this.term = term; + + if (term === '') { + this.setState({loading: false}); + this.searchTimeoutId = ''; + this.onChange(); + return; + } + + const searchTimeoutId = setTimeout( + () => { + searchUsers(term, TeamStore.getCurrentId(), {}, + (users) => { + if (searchTimeoutId !== this.searchTimeoutId) { + return; + } + + this.setState({loading: true}); + + loadTeamMembersAndChannelMembersForProfilesList(users, TeamStore.getCurrentId(), ChannelStore.getCurrentId(), this.loadComplete); + } + ); + }, + Constants.SEARCH_TIMEOUT_MILLISECONDS + ); + + this.searchTimeoutId = searchTimeoutId; + } + + 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 ( + + ); + } +} diff --git a/webapp/components/more_channels.jsx b/webapp/components/more_channels.jsx deleted file mode 100644 index 02a0628ba..000000000 --- a/webapp/components/more_channels.jsx +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import SearchableChannelList from './searchable_channel_list.jsx'; - -import ChannelStore from 'stores/channel_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import TeamStore from 'stores/team_store.jsx'; - -import Constants from 'utils/constants.jsx'; -import * as AsyncClient from 'utils/async_client.jsx'; -import {joinChannel, searchMoreChannels} from 'actions/channel_actions.jsx'; -import {showCreateOption} from 'utils/channel_utils.jsx'; - -import React from 'react'; -import PureRenderMixin from 'react-addons-pure-render-mixin'; -import {Modal} from 'react-bootstrap'; -import {FormattedMessage} from 'react-intl'; -import {browserHistory} from 'react-router/es6'; - -const CHANNELS_CHUNK_SIZE = 50; -const CHANNELS_PER_PAGE = 50; -const SEARCH_TIMEOUT_MILLISECONDS = 100; - -export default class MoreChannels extends React.Component { - constructor(props) { - super(props); - - this.onChange = this.onChange.bind(this); - this.handleJoin = this.handleJoin.bind(this); - this.handleHide = this.handleHide.bind(this); - this.handleExit = this.handleExit.bind(this); - this.nextPage = this.nextPage.bind(this); - this.search = this.search.bind(this); - - this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this); - - this.searchTimeoutId = 0; - - this.state = { - show: true, - search: false, - channels: null, - serverError: null - }; - } - - componentDidMount() { - ChannelStore.addChangeListener(this.onChange); - AsyncClient.getMoreChannelsPage(0, CHANNELS_CHUNK_SIZE * 2); - } - - componentWillUnmount() { - ChannelStore.removeChangeListener(this.onChange); - } - - handleHide() { - this.setState({show: false}); - } - - handleExit() { - if (this.props.onModalDismissed) { - this.props.onModalDismissed(); - } - } - - onChange(force) { - if (this.state.search && !force) { - return; - } - - this.setState({ - channels: ChannelStore.getMoreChannelsList(), - serverError: null - }); - } - - nextPage(page) { - AsyncClient.getMoreChannelsPage((page + 1) * CHANNELS_PER_PAGE, CHANNELS_PER_PAGE); - } - - handleJoin(channel, done) { - joinChannel( - channel, - () => { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); - if (done) { - done(); - } - - this.handleHide(); - }, - (err) => { - this.setState({serverError: err.message}); - if (done) { - done(); - } - } - ); - } - - search(term) { - clearTimeout(this.searchTimeoutId); - - if (term === '') { - this.onChange(true); - this.setState({search: false}); - this.searchTimeoutId = ''; - return; - } - - const searchTimeoutId = setTimeout( - () => { - searchMoreChannels( - term, - (channels) => { - if (searchTimeoutId !== this.searchTimeoutId) { - return; - } - this.setState({search: true, channels}); - } - ); - }, - SEARCH_TIMEOUT_MILLISECONDS - ); - - this.searchTimeoutId = searchTimeoutId; - } - - render() { - let serverError; - if (this.state.serverError) { - serverError =
    ; - } - - let createNewChannelButton = ( - - ); - - let createChannelHelpText = ( -

    - -

    - ); - - const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser(); - const isSystemAdmin = UserStore.isSystemAdminForCurrentUser(); - - if (!showCreateOption(Constants.OPEN_CHANNEL, isAdmin, isSystemAdmin)) { - createNewChannelButton = null; - createChannelHelpText = null; - } - - return ( - - - - - - {createNewChannelButton} - - - - {serverError} - - - ); - } -} - -MoreChannels.propTypes = { - onModalDismissed: React.PropTypes.func, - handleNewChannel: React.PropTypes.func -}; diff --git a/webapp/components/more_channels/index.js b/webapp/components/more_channels/index.js new file mode 100644 index 000000000..b3ce839ef --- /dev/null +++ b/webapp/components/more_channels/index.js @@ -0,0 +1,24 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; +import {getChannels} from 'mattermost-redux/actions/channels'; + +import MoreChannels from './more_channels.jsx'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + getChannels + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(MoreChannels); diff --git a/webapp/components/more_channels/more_channels.jsx b/webapp/components/more_channels/more_channels.jsx new file mode 100644 index 000000000..3643d916b --- /dev/null +++ b/webapp/components/more_channels/more_channels.jsx @@ -0,0 +1,203 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import SearchableChannelList from 'components/searchable_channel_list.jsx'; + +import ChannelStore from 'stores/channel_store.jsx'; +import UserStore from 'stores/user_store.jsx'; +import TeamStore from 'stores/team_store.jsx'; + +import Constants from 'utils/constants.jsx'; +import {joinChannel, searchMoreChannels} from 'actions/channel_actions.jsx'; +import {showCreateOption} from 'utils/channel_utils.jsx'; + +import React from 'react'; +import PureRenderMixin from 'react-addons-pure-render-mixin'; +import {Modal} from 'react-bootstrap'; +import {FormattedMessage} from 'react-intl'; +import {browserHistory} from 'react-router/es6'; + +const CHANNELS_CHUNK_SIZE = 50; +const CHANNELS_PER_PAGE = 50; +const SEARCH_TIMEOUT_MILLISECONDS = 100; + +export default class MoreChannels extends React.Component { + static propTypes = { + onModalDismissed: React.PropTypes.func, + handleNewChannel: React.PropTypes.func, + actions: React.PropTypes.shape({ + getChannels: React.PropTypes.func.isRequired + }).isRequired + } + + constructor(props) { + super(props); + + this.onChange = this.onChange.bind(this); + this.handleJoin = this.handleJoin.bind(this); + this.handleHide = this.handleHide.bind(this); + this.handleExit = this.handleExit.bind(this); + this.nextPage = this.nextPage.bind(this); + this.search = this.search.bind(this); + + this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this); + + this.searchTimeoutId = 0; + + this.state = { + show: true, + search: false, + channels: null, + serverError: null + }; + } + + componentDidMount() { + ChannelStore.addChangeListener(this.onChange); + this.props.actions.getChannels(TeamStore.getCurrentId(), 0, CHANNELS_CHUNK_SIZE * 2); + } + + componentWillUnmount() { + ChannelStore.removeChangeListener(this.onChange); + } + + handleHide() { + this.setState({show: false}); + } + + handleExit() { + if (this.props.onModalDismissed) { + this.props.onModalDismissed(); + } + } + + onChange(force) { + if (this.state.search && !force) { + return; + } + + this.setState({ + channels: ChannelStore.getMoreChannelsList(), + serverError: null + }); + } + + nextPage(page) { + this.props.actions.getChannels(TeamStore.getCurrentId(), (page + 1) * CHANNELS_PER_PAGE, CHANNELS_PER_PAGE); + } + + handleJoin(channel, done) { + joinChannel( + channel, + () => { + browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); + if (done) { + done(); + } + + this.handleHide(); + }, + (err) => { + this.setState({serverError: err.message}); + if (done) { + done(); + } + } + ); + } + + search(term) { + clearTimeout(this.searchTimeoutId); + + if (term === '') { + this.onChange(true); + this.setState({search: false}); + this.searchTimeoutId = ''; + return; + } + + const searchTimeoutId = setTimeout( + () => { + searchMoreChannels( + term, + (channels) => { + if (searchTimeoutId !== this.searchTimeoutId) { + return; + } + this.setState({search: true, channels}); + } + ); + }, + SEARCH_TIMEOUT_MILLISECONDS + ); + + this.searchTimeoutId = searchTimeoutId; + } + + render() { + let serverError; + if (this.state.serverError) { + serverError =
    ; + } + + let createNewChannelButton = ( + + ); + + let createChannelHelpText = ( +

    + +

    + ); + + const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser(); + const isSystemAdmin = UserStore.isSystemAdminForCurrentUser(); + + if (!showCreateOption(Constants.OPEN_CHANNEL, isAdmin, isSystemAdmin)) { + createNewChannelButton = null; + createChannelHelpText = null; + } + + return ( + + + + + + {createNewChannelButton} + + + + {serverError} + + + ); + } +} diff --git a/webapp/components/needs_team.jsx b/webapp/components/needs_team.jsx deleted file mode 100644 index 42f05c1a9..000000000 --- a/webapp/components/needs_team.jsx +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import $ from 'jquery'; - -import {browserHistory} from 'react-router/es6'; -import * as Utils from 'utils/utils.jsx'; -import * as AsyncClient from 'utils/async_client.jsx'; -import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; -import PreferenceStore from 'stores/preference_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; -import PostStore from 'stores/post_store.jsx'; -import * as GlobalActions from 'actions/global_actions.jsx'; -import {startPeriodicStatusUpdates, stopPeriodicStatusUpdates} from 'actions/status_actions.jsx'; -import {startPeriodicSync, stopPeriodicSync} from 'actions/websocket_actions.jsx'; -import {loadProfilesForSidebar} from 'actions/user_actions.jsx'; - -import Constants from 'utils/constants.jsx'; -const TutorialSteps = Constants.TutorialSteps; -const Preferences = Constants.Preferences; - -import ErrorBar from 'components/error_bar.jsx'; -import SidebarRight from 'components/sidebar_right.jsx'; -import SidebarRightMenu from 'components/sidebar_right_menu.jsx'; -import Navbar from 'components/navbar.jsx'; -import WebrtcSidebar from './webrtc/components/webrtc_sidebar.jsx'; - -import WebrtcNotification from './webrtc/components/webrtc_notification.jsx'; - -// Modals -import GetPostLinkModal from 'components/get_post_link_modal.jsx'; -import GetPublicLinkModal from 'components/get_public_link_modal.jsx'; -import GetTeamInviteLinkModal from 'components/get_team_invite_link_modal.jsx'; -import EditPostModal from 'components/edit_post_modal.jsx'; -import DeletePostModal from 'components/delete_post_modal.jsx'; -import TeamSettingsModal from 'components/team_settings_modal.jsx'; -import RemovedFromChannelModal from 'components/removed_from_channel_modal.jsx'; -import ImportThemeModal from 'components/user_settings/import_theme_modal.jsx'; -import InviteMemberModal from 'components/invite_member_modal.jsx'; -import LeaveTeamModal from 'components/leave_team_modal.jsx'; - -import iNoBounce from 'inobounce'; -import * as UserAgent from 'utils/user_agent.jsx'; - -const UNREAD_CHECK_TIME_MILLISECONDS = 10000; - -export default class NeedsTeam extends React.Component { - constructor(params) { - super(params); - - this.onTeamChanged = this.onTeamChanged.bind(this); - this.onPreferencesChanged = this.onPreferencesChanged.bind(this); - - this.blurTime = new Date().getTime(); - - const team = TeamStore.getCurrent(); - - this.state = { - team, - theme: PreferenceStore.getTheme(team.id) - }; - } - - onTeamChanged() { - const team = TeamStore.getCurrent(); - - this.setState({ - team, - theme: PreferenceStore.getTheme(team.id) - }); - } - - onPreferencesChanged(category) { - if (!category || category === Preferences.CATEGORY_THEME) { - this.setState({ - theme: PreferenceStore.getTheme(this.state.team.id) - }); - } - } - - componentWillMount() { - // Go to tutorial if we are first arriving - const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999); - if (tutorialStep <= TutorialSteps.INTRO_SCREENS) { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/tutorial'); - } - } - - componentDidMount() { - TeamStore.addChangeListener(this.onTeamChanged); - PreferenceStore.addChangeListener(this.onPreferencesChanged); - - // Emit view action - GlobalActions.viewLoggedIn(); - - startPeriodicStatusUpdates(); - startPeriodicSync(); - - // Set up tracking for whether the window is active - window.isActive = true; - $(window).on('focus', () => { - AsyncClient.viewChannel(); - ChannelStore.resetCounts(ChannelStore.getCurrentId()); - ChannelStore.emitChange(); - - window.isActive = true; - if (new Date().getTime() - this.blurTime > UNREAD_CHECK_TIME_MILLISECONDS) { - AsyncClient.getMyChannelMembers().then(loadProfilesForSidebar); - } - }); - - $(window).on('blur', () => { - window.isActive = false; - this.blurTime = new Date().getTime(); - if (UserStore.getCurrentUser()) { - AsyncClient.viewChannel(''); - } - }); - - Utils.applyTheme(this.state.theme); - - if (UserAgent.isIosSafari()) { - // Use iNoBounce to prevent scrolling past the boundaries of the page - iNoBounce.enable(); - } - } - - componentDidUpdate(prevProps, prevState) { - if (!Utils.areObjectsEqual(prevState.theme, this.state.theme)) { - Utils.applyTheme(this.state.theme); - } - } - - componentWillUnmount() { - TeamStore.removeChangeListener(this.onTeamChanged); - PreferenceStore.removeChangeListener(this.onPreferencesChanged); - $(window).off('focus'); - $(window).off('blur'); - - if (UserAgent.isIosSafari()) { - iNoBounce.disable(); - } - stopPeriodicStatusUpdates(); - stopPeriodicSync(); - } - - render() { - let content = []; - if (this.props.children) { - content = this.props.children; - } else { - content.push( - this.props.navbar - ); - content.push(this.props.team_sidebar); - content.push( - this.props.sidebar - ); - content.push( -
    -
    - -
    -
    - {React.cloneElement(this.props.center, { - user: this.props.user, - team: this.state.team - })} -
    -
    - ); - } - - let channel = ChannelStore.getByName(this.props.params.channel); - if (channel == null) { - // the permalink view is not really tied to a particular channel but still needs it - const postId = PostStore.getFocusedPostId(); - const post = PostStore.getEarliestPostFromPage(postId); - - // the post take some time before being available on page load - if (post != null) { - channel = ChannelStore.get(post.channel_id); - } - } - - return ( -
    - - -
    - - - - {content} - - - - - - - - - - - -
    -
    - ); - } -} - -NeedsTeam.propTypes = { - children: React.PropTypes.oneOfType([ - React.PropTypes.arrayOf(React.PropTypes.element), - React.PropTypes.element - ]), - 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/needs_team/index.js b/webapp/components/needs_team/index.js new file mode 100644 index 000000000..ba809fd10 --- /dev/null +++ b/webapp/components/needs_team/index.js @@ -0,0 +1,25 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; +import {viewChannel, getMyChannelMembers} from 'mattermost-redux/actions/channels'; + +import NeedsTeam from './needs_team.jsx'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + viewChannel, + getMyChannelMembers + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(NeedsTeam); diff --git a/webapp/components/needs_team/needs_team.jsx b/webapp/components/needs_team/needs_team.jsx new file mode 100644 index 000000000..2ae3cbeec --- /dev/null +++ b/webapp/components/needs_team/needs_team.jsx @@ -0,0 +1,234 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React from 'react'; + +import $ from 'jquery'; + +import {browserHistory} from 'react-router/es6'; +import * as Utils from 'utils/utils.jsx'; +import TeamStore from 'stores/team_store.jsx'; +import UserStore from 'stores/user_store.jsx'; +import PreferenceStore from 'stores/preference_store.jsx'; +import ChannelStore from 'stores/channel_store.jsx'; +import PostStore from 'stores/post_store.jsx'; +import * as GlobalActions from 'actions/global_actions.jsx'; +import {startPeriodicStatusUpdates, stopPeriodicStatusUpdates} from 'actions/status_actions.jsx'; +import {startPeriodicSync, stopPeriodicSync} from 'actions/websocket_actions.jsx'; +import {loadProfilesForSidebar} from 'actions/user_actions.jsx'; + +import Constants from 'utils/constants.jsx'; +const TutorialSteps = Constants.TutorialSteps; +const Preferences = Constants.Preferences; + +import ErrorBar from 'components/error_bar.jsx'; +import SidebarRight from 'components/sidebar_right.jsx'; +import SidebarRightMenu from 'components/sidebar_right_menu.jsx'; +import Navbar from 'components/navbar.jsx'; +import WebrtcSidebar from 'components/webrtc/components/webrtc_sidebar.jsx'; + +import WebrtcNotification from 'components/webrtc/components/webrtc_notification.jsx'; + +// Modals +import GetPostLinkModal from 'components/get_post_link_modal.jsx'; +import GetPublicLinkModal from 'components/get_public_link_modal.jsx'; +import GetTeamInviteLinkModal from 'components/get_team_invite_link_modal.jsx'; +import EditPostModal from 'components/edit_post_modal.jsx'; +import DeletePostModal from 'components/delete_post_modal.jsx'; +import TeamSettingsModal from 'components/team_settings_modal.jsx'; +import RemovedFromChannelModal from 'components/removed_from_channel_modal.jsx'; +import ImportThemeModal from 'components/user_settings/import_theme_modal.jsx'; +import InviteMemberModal from 'components/invite_member_modal.jsx'; +import LeaveTeamModal from 'components/leave_team_modal.jsx'; + +import iNoBounce from 'inobounce'; +import * as UserAgent from 'utils/user_agent.jsx'; + +const UNREAD_CHECK_TIME_MILLISECONDS = 10000; + +export default class NeedsTeam extends React.Component { + static propTypes = { + children: React.PropTypes.oneOfType([ + React.PropTypes.arrayOf(React.PropTypes.element), + React.PropTypes.element + ]), + 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, + actions: React.PropTypes.shape({ + viewChannel: React.PropTypes.func.isRequired, + getMyChannelMembers: React.PropTypes.func.isRequired + }).isRequired + } + + constructor(params) { + super(params); + + this.onTeamChanged = this.onTeamChanged.bind(this); + this.onPreferencesChanged = this.onPreferencesChanged.bind(this); + + this.blurTime = new Date().getTime(); + + const team = TeamStore.getCurrent(); + + this.state = { + team, + theme: PreferenceStore.getTheme(team.id) + }; + } + + onTeamChanged() { + const team = TeamStore.getCurrent(); + + this.setState({ + team, + theme: PreferenceStore.getTheme(team.id) + }); + } + + onPreferencesChanged(category) { + if (!category || category === Preferences.CATEGORY_THEME) { + this.setState({ + theme: PreferenceStore.getTheme(this.state.team.id) + }); + } + } + + componentWillMount() { + // Go to tutorial if we are first arriving + const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999); + if (tutorialStep <= TutorialSteps.INTRO_SCREENS) { + browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/tutorial'); + } + } + + componentDidMount() { + TeamStore.addChangeListener(this.onTeamChanged); + PreferenceStore.addChangeListener(this.onPreferencesChanged); + + // Emit view action + GlobalActions.viewLoggedIn(); + + startPeriodicStatusUpdates(); + startPeriodicSync(); + + // Set up tracking for whether the window is active + window.isActive = true; + $(window).on('focus', () => { + this.props.actions.viewChannel(ChannelStore.getCurrentId()); + ChannelStore.resetCounts(ChannelStore.getCurrentId()); + ChannelStore.emitChange(); + + window.isActive = true; + if (new Date().getTime() - this.blurTime > UNREAD_CHECK_TIME_MILLISECONDS) { + this.props.actions.getMyChannelMembers(TeamStore.getCurrentId()).then(loadProfilesForSidebar); + } + }); + + $(window).on('blur', () => { + window.isActive = false; + this.blurTime = new Date().getTime(); + if (UserStore.getCurrentUser()) { + this.props.actions.viewChannel(''); + } + }); + + Utils.applyTheme(this.state.theme); + + if (UserAgent.isIosSafari()) { + // Use iNoBounce to prevent scrolling past the boundaries of the page + iNoBounce.enable(); + } + } + + componentDidUpdate(prevProps, prevState) { + if (!Utils.areObjectsEqual(prevState.theme, this.state.theme)) { + Utils.applyTheme(this.state.theme); + } + } + + componentWillUnmount() { + TeamStore.removeChangeListener(this.onTeamChanged); + PreferenceStore.removeChangeListener(this.onPreferencesChanged); + $(window).off('focus'); + $(window).off('blur'); + + if (UserAgent.isIosSafari()) { + iNoBounce.disable(); + } + stopPeriodicStatusUpdates(); + stopPeriodicSync(); + } + + render() { + let content = []; + if (this.props.children) { + content = this.props.children; + } else { + content.push( + this.props.navbar + ); + content.push(this.props.team_sidebar); + content.push( + this.props.sidebar + ); + content.push( +
    +
    + +
    +
    + {React.cloneElement(this.props.center, { + user: this.props.user, + team: this.state.team + })} +
    +
    + ); + } + + let channel = ChannelStore.getByName(this.props.params.channel); + if (channel == null) { + // the permalink view is not really tied to a particular channel but still needs it + const postId = PostStore.getFocusedPostId(); + const post = PostStore.getEarliestPostFromPage(postId); + + // the post take some time before being available on page load + if (post != null) { + channel = ChannelStore.get(post.channel_id); + } + } + + return ( +
    + + +
    + + + + {content} + + + + + + + + + + + +
    +
    + ); + } +} diff --git a/webapp/components/new_channel_flow.jsx b/webapp/components/new_channel_flow.jsx index 0ca504534..91dd04c0c 100644 --- a/webapp/components/new_channel_flow.jsx +++ b/webapp/components/new_channel_flow.jsx @@ -3,7 +3,6 @@ import * as Utils from 'utils/utils.jsx'; import TeamStore from 'stores/team_store.jsx'; -import UserStore from 'stores/user_store.jsx'; import {cleanUpUrlable} from 'utils/url.jsx'; import NewChannelModal from './new_channel_modal.jsx'; @@ -68,9 +67,8 @@ export default class NewChannelFlow extends React.Component { return; } - const cu = UserStore.getCurrentUser(); const channel = { - team_id: cu.team_id, + team_id: TeamStore.getCurrentId(), name: this.state.channelName, display_name: this.state.channelDisplayName, purpose: this.state.channelPurpose, @@ -82,7 +80,7 @@ export default class NewChannelFlow extends React.Component { channel, (data) => { this.doOnModalExited = () => { - browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + data.channel.name); + browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + data.name); }; this.props.onModalDismissed(); diff --git a/webapp/components/post_view/index.js b/webapp/components/post_view/index.js new file mode 100644 index 000000000..b42b486ab --- /dev/null +++ b/webapp/components/post_view/index.js @@ -0,0 +1,24 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {connect} from 'react-redux'; +import {bindActionCreators} from 'redux'; +import {viewChannel} from 'mattermost-redux/actions/channels'; + +import PostViewCache from './post_view_cache.jsx'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps + }; +} + +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + viewChannel + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(PostViewCache); diff --git a/webapp/components/post_view/post_view_cache.jsx b/webapp/components/post_view/post_view_cache.jsx index d7cb360d1..beb20360a 100644 --- a/webapp/components/post_view/post_view_cache.jsx +++ b/webapp/components/post_view/post_view_cache.jsx @@ -5,13 +5,18 @@ import PostViewController from './post_view_controller.jsx'; import ChannelStore from 'stores/channel_store.jsx'; import UserStore from 'stores/user_store.jsx'; -import * as AsyncClient from 'utils/async_client.jsx'; import React from 'react'; const MAXIMUM_CACHED_VIEWS = 5; export default class PostViewCache extends React.Component { + static propTypes = { + actions: React.PropTypes.shape({ + viewChannel: React.PropTypes.func.isRequired + }).isRequired + } + constructor(props) { super(props); @@ -32,7 +37,7 @@ export default class PostViewCache extends React.Component { componentWillUnmount() { if (UserStore.getCurrentUser()) { - AsyncClient.viewChannel('', this.state.currentChannelId || ''); + this.props.actions.viewChannel('', this.state.currentChannelId || ''); } ChannelStore.removeChangeListener(this.onChannelChange); } diff --git a/webapp/components/rename_channel_modal.jsx b/webapp/components/rename_channel_modal.jsx index f7d8fad28..96897eb52 100644 --- a/webapp/components/rename_channel_modal.jsx +++ b/webapp/components/rename_channel_modal.jsx @@ -2,6 +2,7 @@ // See License.txt for license information. import ReactDOM from 'react-dom'; +import {browserHistory} from 'react-router/es6'; import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; import {cleanUpUrlable, getShortenedURL} from 'utils/url.jsx'; @@ -164,8 +165,10 @@ export class RenameChannelModal extends React.Component { } updateChannel(channel, - () => { + (data) => { this.handleHide(); + const team = TeamStore.get(data.team_id); + browserHistory.push('/' + team.name + '/channels/' + data.name); }, (err) => { this.setState({ diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx index 8667802cc..71559de02 100644 --- a/webapp/components/sidebar.jsx +++ b/webapp/components/sidebar.jsx @@ -5,7 +5,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; import NewChannelFlow from './new_channel_flow.jsx'; import MoreDirectChannels from 'components/more_direct_channels'; -import MoreChannels from 'components/more_channels.jsx'; +import MoreChannels from 'components/more_channels'; import SidebarHeader from './sidebar_header.jsx'; import UnreadChannelIndicator from './unread_channel_indicator.jsx'; import TutorialTip from './tutorial/tutorial_tip.jsx'; diff --git a/webapp/components/team_members_dropdown/index.js b/webapp/components/team_members_dropdown/index.js index 9486c89fa..e7b5910a2 100644 --- a/webapp/components/team_members_dropdown/index.js +++ b/webapp/components/team_members_dropdown/index.js @@ -5,6 +5,7 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; import {getUser} from 'mattermost-redux/actions/users'; import {getTeamStats} from 'mattermost-redux/actions/teams'; +import {getChannelStats} from 'mattermost-redux/actions/channels'; import TeamMembersDropdown from './team_members_dropdown.jsx'; @@ -18,7 +19,8 @@ function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ getUser, - getTeamStats + getTeamStats, + getChannelStats }, dispatch) }; } diff --git a/webapp/components/team_members_dropdown/team_members_dropdown.jsx b/webapp/components/team_members_dropdown/team_members_dropdown.jsx index 00441ba37..f01997d12 100644 --- a/webapp/components/team_members_dropdown/team_members_dropdown.jsx +++ b/webapp/components/team_members_dropdown/team_members_dropdown.jsx @@ -10,7 +10,6 @@ import ChannelStore from 'stores/channel_store.jsx'; import {removeUserFromTeam, updateTeamMemberRoles} from 'actions/team_actions.jsx'; import {loadMyTeamMembers, updateActive} from 'actions/user_actions.jsx'; -import * as AsyncClient from 'utils/async_client.jsx'; import * as Utils from 'utils/utils.jsx'; import React from 'react'; @@ -23,7 +22,8 @@ export default class TeamMembersDropdown extends React.Component { teamMember: React.PropTypes.object.isRequired, actions: React.PropTypes.shape({ getUser: React.PropTypes.func.isRequired, - getTeamStats: React.PropTypes.func.isRequired + getTeamStats: React.PropTypes.func.isRequired, + getChannelStats: React.PropTypes.func.isRequired }).isRequired } @@ -88,7 +88,7 @@ export default class TeamMembersDropdown extends React.Component { handleMakeActive() { updateActive(this.props.user.id, true, () => { - AsyncClient.getChannelStats(ChannelStore.getCurrentId()); + this.props.actions.getChannelStats(ChannelStore.getCurrentId()); this.props.actions.getTeamStats(this.props.teamMember.team_id); }, (err) => { @@ -100,7 +100,7 @@ export default class TeamMembersDropdown extends React.Component { handleMakeNotActive() { updateActive(this.props.user.id, false, () => { - AsyncClient.getChannelStats(ChannelStore.getCurrentId()); + this.props.actions.getChannelStats(ChannelStore.getCurrentId()); this.props.actions.getTeamStats(this.props.teamMember.team_id); }, (err) => { -- cgit v1.2.3-1-g7c22