// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import PropTypes from 'prop-types'; import React from 'react'; import {Modal} from 'react-bootstrap'; import {FormattedMessage} from 'react-intl'; import {Client4} from 'mattermost-redux/client'; import {filterProfilesMatchingTerm} from 'mattermost-redux/utils/user_utils'; import {displayEntireNameForUser, localizeMessage} from 'utils/utils.jsx'; import ProfilePicture from 'components/profile_picture.jsx'; import MultiSelect from 'components/multiselect/multiselect.jsx'; import AddIcon from 'components/icon/add_icon'; import {searchUsers} from 'actions/user_actions.jsx'; import Constants from 'utils/constants.jsx'; const USERS_PER_PAGE = 50; const MAX_SELECTABLE_VALUES = 20; export default class ChannelInviteModal extends React.Component { static propTypes = { profilesNotInCurrentChannel: PropTypes.array.isRequired, onHide: PropTypes.func.isRequired, channel: PropTypes.object.isRequired, actions: PropTypes.shape({ addUsersToChannel: PropTypes.func.isRequired, getProfilesNotInChannel: PropTypes.func.isRequired, getTeamStats: PropTypes.func.isRequired, }).isRequired, }; constructor(props) { super(props); this.searchTimeoutId = 0; this.state = { values: [], term: '', show: true, saving: false, loadingUsers: true, }; } addValue = (value) => { const values = Object.assign([], this.state.values); if (values.indexOf(value) === -1) { values.push(value); } this.setState({values}); }; componentDidMount() { this.props.actions.getProfilesNotInChannel(this.props.channel.team_id, this.props.channel.id, 0).then(() => { this.setUsersLoadingState(false); }); this.props.actions.getTeamStats(this.props.channel.team_id); } onHide = () => { this.setState({show: false}); }; handleInviteError = (err) => { if (err) { this.setState({ saving: false, inviteError: err.message, }); } }; handleDelete = (values) => { this.setState({values}); }; setUsersLoadingState = (loadingState) => { this.setState({ loadingUsers: loadingState, }); }; handlePageChange = (page, prevPage) => { if (page > prevPage) { this.setUsersLoadingState(true); this.props.actions.getProfilesNotInChannel(this.props.channel.team_id, this.props.channel.id, page + 1, USERS_PER_PAGE).then(() => { this.setUsersLoadingState(false); }); } }; handleSubmit = (e) => { const {actions, channel} = this.props; if (e) { e.preventDefault(); } const userIds = this.state.values.map((v) => v.id); if (userIds.length === 0) { return; } this.setState({saving: true}); actions.addUsersToChannel(channel.id, userIds).then((result) => { if (result.error) { this.handleInviteError(result.error); } else { this.setState({ saving: false, inviteError: null, }); this.onHide(); } }); }; search = (term) => { clearTimeout(this.searchTimeoutId); this.setState({ term, }); this.searchTimeoutId = setTimeout( () => { this.setUsersLoadingState(true); searchUsers(term, this.props.channel.team_id, {not_in_channel_id: this.props.channel.id}).then(() => { this.setUsersLoadingState(false); }); }, Constants.SEARCH_TIMEOUT_MILLISECONDS ); }; renderOption = (option, isSelected, onAdd) => { var rowSelected = ''; if (isSelected) { rowSelected = 'more-modal__row--selected'; } let tag = null; if (option.is_bot) { tag = (
); } return (
onAdd(option)} >
{displayEntireNameForUser(option)} {tag}
); }; renderValue(props) { return props.data.username; } render() { let inviteError = null; if (this.state.inviteError) { inviteError = (); } const numRemainingText = ( ); const buttonSubmitText = localizeMessage('multiselect.add', 'Add'); const buttonSubmitLoadingText = localizeMessage('multiselect.adding', 'Adding...'); let users = filterProfilesMatchingTerm(this.props.profilesNotInCurrentChannel, this.state.term); users = users.filter((user) => user.delete_at === 0); const content = ( ); return ( {this.props.channel.display_name} {inviteError} {content} ); } }