diff options
Diffstat (limited to 'webapp/components')
-rw-r--r-- | webapp/components/admin_console/team_users.jsx | 25 | ||||
-rw-r--r-- | webapp/components/channel_invite_modal.jsx | 23 | ||||
-rw-r--r-- | webapp/components/channel_members_modal.jsx | 23 | ||||
-rw-r--r-- | webapp/components/member_list_team.jsx | 25 | ||||
-rw-r--r-- | webapp/components/more_channels.jsx | 127 | ||||
-rw-r--r-- | webapp/components/more_direct_channels.jsx | 33 | ||||
-rw-r--r-- | webapp/components/needs_team.jsx | 2 | ||||
-rw-r--r-- | webapp/components/searchable_channel_list.jsx | 2 | ||||
-rw-r--r-- | webapp/components/searchable_user_list.jsx | 38 | ||||
-rw-r--r-- | webapp/components/sidebar.jsx | 32 |
10 files changed, 165 insertions, 165 deletions
diff --git a/webapp/components/admin_console/team_users.jsx b/webapp/components/admin_console/team_users.jsx index 49550d8af..1cbb0e85f 100644 --- a/webapp/components/admin_console/team_users.jsx +++ b/webapp/components/admin_console/team_users.jsx @@ -43,6 +43,8 @@ export default class UserList extends React.Component { this.search = this.search.bind(this); this.loadComplete = this.loadComplete.bind(this); + this.searchTimeoutId = 0; + const stats = TeamStore.getStats(this.props.params.team); this.state = { @@ -148,14 +150,21 @@ export default class UserList extends React.Component { const options = {}; options[UserSearchOptions.ALLOW_INACTIVE] = true; - searchUsers( - term, - this.props.params.team, - options, - (users) => { - this.setState({loading: true, search: true, users}); - loadTeamMembersForProfilesList(users, this.props.params.team, this.loadComplete); - } + clearTimeout(this.searchTimeoutId); + + this.searchTimeoutId = setTimeout( + () => { + searchUsers( + term, + this.props.params.team, + options, + (users) => { + this.setState({loading: true, search: true, users}); + loadTeamMembersForProfilesList(users, this.props.params.team, this.loadComplete); + } + ); + }, + Constants.SEARCH_TIMEOUT_MILLISECONDS ); } diff --git a/webapp/components/channel_invite_modal.jsx b/webapp/components/channel_invite_modal.jsx index 4b72cfc40..355d23d53 100644 --- a/webapp/components/channel_invite_modal.jsx +++ b/webapp/components/channel_invite_modal.jsx @@ -13,6 +13,7 @@ import {searchUsers} from 'actions/user_actions.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import * as UserAgent from 'utils/user_agent.jsx'; +import Constants from 'utils/constants.jsx'; import React from 'react'; import {Modal} from 'react-bootstrap'; @@ -32,6 +33,7 @@ export default class ChannelInviteModal extends React.Component { this.search = this.search.bind(this); this.term = ''; + this.searchTimeoutId = 0; const channelStats = ChannelStore.getStats(props.channel.id); const teamStats = TeamStore.getCurrentStats(); @@ -113,13 +115,20 @@ export default class ChannelInviteModal extends React.Component { return; } - searchUsers( - term, - TeamStore.getCurrentId(), - {not_in_channel_id: this.props.channel.id}, - (users) => { - this.setState({search: true, users}); - } + clearTimeout(this.searchTimeoutId); + + this.searchTimeoutId = setTimeout( + () => { + searchUsers( + term, + TeamStore.getCurrentId(), + {not_in_channel_id: this.props.channel.id}, + (users) => { + this.setState({search: true, users}); + } + ); + }, + Constants.SEARCH_TIMEOUT_MILLISECONDS ); } diff --git a/webapp/components/channel_members_modal.jsx b/webapp/components/channel_members_modal.jsx index 3722195b9..9f6a2a2eb 100644 --- a/webapp/components/channel_members_modal.jsx +++ b/webapp/components/channel_members_modal.jsx @@ -13,6 +13,7 @@ import {removeUserFromChannel} from 'actions/channel_actions.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import * as UserAgent from 'utils/user_agent.jsx'; +import Constants from 'utils/constants.jsx'; import React from 'react'; import {Modal} from 'react-bootstrap'; @@ -33,6 +34,7 @@ export default class ChannelMembersModal extends React.Component { this.nextPage = this.nextPage.bind(this); this.term = ''; + this.searchTimeoutId = 0; const stats = ChannelStore.getStats(props.channel.id); @@ -128,13 +130,20 @@ export default class ChannelMembersModal extends React.Component { return; } - searchUsers( - term, - TeamStore.getCurrentId(), - {in_channel_id: this.props.channel.id}, - (users) => { - this.setState({search: true, users}); - } + clearTimeout(this.searchTimeoutId); + + this.searchTimeoutId = setTimeout( + () => { + searchUsers( + term, + TeamStore.getCurrentId(), + {in_channel_id: this.props.channel.id}, + (users) => { + this.setState({search: true, users}); + } + ); + }, + Constants.SEARCH_TIMEOUT_MILLISECONDS ); } diff --git a/webapp/components/member_list_team.jsx b/webapp/components/member_list_team.jsx index 768129f1c..a9db0e734 100644 --- a/webapp/components/member_list_team.jsx +++ b/webapp/components/member_list_team.jsx @@ -27,6 +27,8 @@ export default class MemberListTeam extends React.Component { this.search = this.search.bind(this); this.loadComplete = this.loadComplete.bind(this); + this.searchTimeoutId = 0; + const stats = TeamStore.getCurrentStats(); this.state = { @@ -86,14 +88,21 @@ export default class MemberListTeam extends React.Component { return; } - searchUsers( - term, - TeamStore.getCurrentId(), - {}, - (users) => { - this.setState({loading: true, search: true, users, term, teamMembers: Object.assign([], TeamStore.getMembersInTeam())}); - loadTeamMembersForProfilesList(users, TeamStore.getCurrentId(), this.loadComplete); - } + clearTimeout(this.searchTimeoutId); + + this.searchTimeoutId = setTimeout( + () => { + searchUsers( + term, + TeamStore.getCurrentId(), + {}, + (users) => { + this.setState({loading: true, search: true, users, term, teamMembers: Object.assign([], TeamStore.getMembersInTeam())}); + loadTeamMembersForProfilesList(users, TeamStore.getCurrentId(), this.loadComplete); + } + ); + }, + Constants.SEARCH_TIMEOUT_MILLISECONDS ); } diff --git a/webapp/components/more_channels.jsx b/webapp/components/more_channels.jsx index d8ba95bdf..b9b841ad8 100644 --- a/webapp/components/more_channels.jsx +++ b/webapp/components/more_channels.jsx @@ -1,8 +1,6 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import $ from 'jquery'; -import NewChannelFlow from './new_channel_flow.jsx'; import SearchableChannelList from './searchable_channel_list.jsx'; import ChannelStore from 'stores/channel_store.jsx'; @@ -13,11 +11,11 @@ import Constants from 'utils/constants.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import {joinChannel, searchMoreChannels} from 'actions/channel_actions.jsx'; -import {FormattedMessage} from 'react-intl'; -import {browserHistory} from 'react-router/es6'; - 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; @@ -29,7 +27,8 @@ export default class MoreChannels extends React.Component { this.onChange = this.onChange.bind(this); this.handleJoin = this.handleJoin.bind(this); - this.handleNewChannel = this.handleNewChannel.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); @@ -38,8 +37,7 @@ export default class MoreChannels extends React.Component { this.searchTimeoutId = 0; this.state = { - channelType: '', - showNewChannelModal: false, + show: true, search: false, channels: null, serverError: null @@ -47,23 +45,24 @@ export default class MoreChannels extends React.Component { } componentDidMount() { - const self = this; ChannelStore.addChangeListener(this.onChange); - - $(this.refs.modal).on('shown.bs.modal', () => { - AsyncClient.getMoreChannelsPage(0, CHANNELS_CHUNK_SIZE * 2); - }); - - $(this.refs.modal).on('show.bs.modal', (e) => { - const button = e.relatedTarget; - self.setState({channelType: $(button).attr('data-channeltype')}); - }); + 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; @@ -83,11 +82,12 @@ export default class MoreChannels extends React.Component { joinChannel( channel, () => { - $(this.refs.modal).modal('hide'); browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/channels/' + channel.name); if (done) { done(); } + + this.handleHide(); }, (err) => { this.setState({serverError: err.message}); @@ -98,11 +98,6 @@ export default class MoreChannels extends React.Component { ); } - handleNewChannel() { - $(this.refs.modal).modal('hide'); - this.setState({showNewChannelModal: true}); - } - search(term) { if (term === '') { this.onChange(true); @@ -135,7 +130,7 @@ export default class MoreChannels extends React.Component { <button type='button' className='btn btn-primary channel-create-btn' - onClick={this.handleNewChannel} + onClick={this.props.handleNewChannel} > <FormattedMessage id='more_channels.create' @@ -167,58 +162,38 @@ export default class MoreChannels extends React.Component { } return ( - <div - className='modal fade more-channel__modal' - id='more_channels' - ref='modal' - tabIndex='-1' - role='dialog' - aria-hidden='true' + <Modal + dialogClassName='more-modal more-public-channels' + show={this.state.show} + onHide={this.handleHide} + onExited={this.handleExit} > - <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'> - <FormattedMessage - id='more_channels.close' - defaultMessage='Close' - /> - </span> - </button> - <h4 className='modal-title'> - <FormattedMessage - id='more_channels.title' - defaultMessage='More Channels' - /> - </h4> - {createNewChannelButton} - <NewChannelFlow - show={this.state.showNewChannelModal} - channelType={this.state.channelType} - onModalDismissed={() => this.setState({showNewChannelModal: false})} - /> - </div> - <div className='modal-body'> - <SearchableChannelList - channels={this.state.channels} - channelsPerPage={CHANNELS_PER_PAGE} - nextPage={this.nextPage} - search={this.search} - handleJoin={this.handleJoin} - noResultsText={createChannelHelpText} - /> - {serverError} - </div> - </div> - </div> - </div> - + <Modal.Header closeButton={true}> + <Modal.Title> + <FormattedMessage + id='more_channels.title' + defaultMessage='More Channels' + /> + </Modal.Title> + {createNewChannelButton} + </Modal.Header> + <Modal.Body> + <SearchableChannelList + channels={this.state.channels} + channelsPerPage={CHANNELS_PER_PAGE} + nextPage={this.nextPage} + search={this.search} + handleJoin={this.handleJoin} + noResultsText={createChannelHelpText} + /> + {serverError} + </Modal.Body> + </Modal> ); } } + +MoreChannels.propTypes = { + onModalDismissed: React.PropTypes.func, + handleNewChannel: React.PropTypes.func +}; diff --git a/webapp/components/more_direct_channels.jsx b/webapp/components/more_direct_channels.jsx index 2d4780359..1b287b3b2 100644 --- a/webapp/components/more_direct_channels.jsx +++ b/webapp/components/more_direct_channels.jsx @@ -35,6 +35,8 @@ export default class MoreDirectChannels extends React.Component { this.nextPage = this.nextPage.bind(this); this.search = this.search.bind(this); + this.searchTimeoutId = 0; + this.state = { users: null, loadingDMChannel: -1, @@ -168,19 +170,26 @@ export default class MoreDirectChannels extends React.Component { teamId = TeamStore.getCurrentId(); } - searchUsers( - term, - teamId, - {}, - (users) => { - for (let i = 0; i < users.length; i++) { - if (users[i].id === UserStore.getCurrentId()) { - users.splice(i, 1); - break; + clearTimeout(this.searchTimeoutId); + + this.searchTimeoutId = setTimeout( + () => { + searchUsers( + term, + teamId, + {}, + (users) => { + for (let i = 0; i < users.length; i++) { + if (users[i].id === UserStore.getCurrentId()) { + users.splice(i, 1); + break; + } + } + this.setState({search: true, users}); } - } - this.setState({search: true, users}); - } + ); + }, + Constants.SEARCH_TIMEOUT_MILLISECONDS ); } diff --git a/webapp/components/needs_team.jsx b/webapp/components/needs_team.jsx index 014d6c93e..f8a774389 100644 --- a/webapp/components/needs_team.jsx +++ b/webapp/components/needs_team.jsx @@ -32,7 +32,6 @@ 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 MoreChannelsModal from 'components/more_channels.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'; @@ -181,7 +180,6 @@ export default class NeedsTeam extends React.Component { <LeaveTeamModal/> <ImportThemeModal/> <TeamSettingsModal/> - <MoreChannelsModal/> <EditPostModal/> <DeletePostModal/> <RemovedFromChannelModal/> diff --git a/webapp/components/searchable_channel_list.jsx b/webapp/components/searchable_channel_list.jsx index 4a7f90455..afd113975 100644 --- a/webapp/components/searchable_channel_list.jsx +++ b/webapp/components/searchable_channel_list.jsx @@ -167,7 +167,7 @@ export default class SearchableChannelList extends React.Component { return ( <div className='filtered-user-list'> <div className='filter-row'> - <div className='col-sm-6'> + <div className='col-sm-12'> <input ref='filter' className='form-control filter-textbox' diff --git a/webapp/components/searchable_user_list.jsx b/webapp/components/searchable_user_list.jsx index 3fa912d6d..8058010ea 100644 --- a/webapp/components/searchable_user_list.jsx +++ b/webapp/components/searchable_user_list.jsx @@ -4,8 +4,6 @@ import UserList from 'components/user_list.jsx'; import * as Utils from 'utils/utils.jsx'; -import Constants from 'utils/constants.jsx'; -const KeyCodes = Constants.KeyCodes; import $ from 'jquery'; import React from 'react'; @@ -21,8 +19,6 @@ export default class SearchableUserList extends React.Component { this.nextPage = this.nextPage.bind(this); this.previousPage = this.previousPage.bind(this); this.doSearch = this.doSearch.bind(this); - this.onSearchBoxKeyPress = this.onSearchBoxKeyPress.bind(this); - this.onSearchBoxChange = this.onSearchBoxChange.bind(this); this.nextTimeoutId = 0; @@ -71,20 +67,6 @@ export default class SearchableUserList extends React.Component { } } - onSearchBoxKeyPress(e) { - if (e.charCode === KeyCodes.ENTER) { - e.preventDefault(); - this.doSearch(); - } - } - - onSearchBoxChange(e) { - if (e.target.value === '') { - this.props.search(''); // clear search - this.setState({page: 0, search: false}); - } - } - render() { let nextButton; let previousButton; @@ -158,28 +140,14 @@ export default class SearchableUserList extends React.Component { return ( <div className='filtered-user-list'> <div className='filter-row'> - <div className='col-xs-9 col-sm-5'> + <div className='col-xs-12'> <input ref='filter' className='form-control filter-textbox' - placeholder={Utils.localizeMessage('filtered_user_list.search', 'Press enter to search')} - onKeyPress={this.onSearchBoxKeyPress} - onChange={this.onSearchBoxChange} + placeholder={Utils.localizeMessage('filtered_user_list.search', 'Search users')} + onInput={this.doSearch} /> </div> - <div className='col-xs-3 col-sm-2 filter-button'> - <button - type='button' - className='btn btn-primary' - onClick={this.doSearch} - disabled={this.props.users == null} - > - <FormattedMessage - id='filtered_user_list.searchButton' - defaultMessage='Search' - /> - </button> - </div> <div className='col-sm-12'> <span className='member-count pull-left'>{count}</span> </div> diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx index 1145c8ab3..fcfa9496c 100644 --- a/webapp/components/sidebar.jsx +++ b/webapp/components/sidebar.jsx @@ -5,6 +5,7 @@ import $ from 'jquery'; import ReactDOM from 'react-dom'; import NewChannelFlow from './new_channel_flow.jsx'; import MoreDirectChannels from './more_direct_channels.jsx'; +import MoreChannels from 'components/more_channels.jsx'; import SidebarHeader from './sidebar_header.jsx'; import UnreadChannelIndicator from './unread_channel_indicator.jsx'; import TutorialTip from './tutorial/tutorial_tip.jsx'; @@ -19,7 +20,6 @@ import * as AsyncClient from 'utils/async_client.jsx'; import * as Utils from 'utils/utils.jsx'; import * as ChannelUtils from 'utils/channel_utils.jsx'; import * as ChannelActions from 'actions/channel_actions.jsx'; -import * as UserAgent from 'utils/user_agent.jsx'; import Constants from 'utils/constants.jsx'; @@ -53,6 +53,7 @@ export default class Sidebar extends React.Component { this.handleLeaveDirectChannel = this.handleLeaveDirectChannel.bind(this); this.showMoreChannelsModal = this.showMoreChannelsModal.bind(this); + this.hideMoreChannelsModal = this.hideMoreChannelsModal.bind(this); this.showNewChannelModal = this.showNewChannelModal.bind(this); this.hideNewChannelModal = this.hideNewChannelModal.bind(this); this.showMoreDirectChannelsModal = this.showMoreDirectChannelsModal.bind(this); @@ -72,6 +73,7 @@ export default class Sidebar extends React.Component { const state = this.getStateFromStores(); state.newChannelModalType = ''; state.showDirectChannelsModal = false; + state.showMoreChannelsModal = false; state.loadingDMChannel = -1; this.state = state; } @@ -340,13 +342,11 @@ export default class Sidebar extends React.Component { } showMoreChannelsModal() { - // manually show the modal because using data-toggle messes with keyboard focus when the modal is dismissed - $('#more_channels').modal({'data-channeltype': 'O'}).modal('show'); - $('#more_channels').on('shown.bs.modal', () => { - if (!UserAgent.isMobile()) { - $('#more_channels input').focus(); - } - }); + this.setState({showMoreChannelsModal: true}); + } + + hideMoreChannelsModal() { + this.setState({showMoreChannelsModal: false}); } showNewChannelModal(type) { @@ -552,6 +552,7 @@ export default class Sidebar extends React.Component { </li> ); } + render() { // Check if we have all info needed to render if (this.state.currentTeam == null || this.state.currentUser == null) { @@ -721,12 +722,24 @@ export default class Sidebar extends React.Component { if (this.state.showDirectChannelsModal) { moreDirectChannelsModal = ( <MoreDirectChannels - show={true} onModalDismissed={this.hideMoreDirectChannelsModal} /> ); } + let moreChannelsModal; + if (this.state.showMoreChannelsModal) { + moreChannelsModal = ( + <MoreChannels + onModalDismissed={this.hideMoreChannelsModal} + handleNewChannel={() => { + this.hideMoreChannelsModal(); + this.showNewChannelModal(Constants.OPEN_CHANNEL); + }} + /> + ); + } + return ( <div className='sidebar--left' @@ -739,6 +752,7 @@ export default class Sidebar extends React.Component { onModalDismissed={this.hideNewChannelModal} /> {moreDirectChannelsModal} + {moreChannelsModal} <SidebarHeader teamDisplayName={this.state.currentTeam.display_name} |