diff options
-rw-r--r-- | webapp/components/channel_header.jsx | 65 | ||||
-rw-r--r-- | webapp/components/confirm_modal.jsx | 20 | ||||
-rw-r--r-- | webapp/components/navbar.jsx | 66 | ||||
-rwxr-xr-x | webapp/i18n/en.json | 3 |
4 files changed, 146 insertions, 8 deletions
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx index 82864d48c..f09a4a61d 100644 --- a/webapp/components/channel_header.jsx +++ b/webapp/components/channel_header.jsx @@ -14,6 +14,7 @@ import ChannelMembersModal from './channel_members_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx'; import RenameChannelModal from './rename_channel_modal.jsx'; +import ConfirmModal from './confirm_modal.jsx'; import ToggleModalButton from './toggle_modal_button.jsx'; import ChannelStore from 'stores/channel_store.jsx'; @@ -57,6 +58,8 @@ export default class ChannelHeader extends React.Component { this.initWebrtc = this.initWebrtc.bind(this); this.onBusy = this.onBusy.bind(this); this.openDirectMessageModal = this.openDirectMessageModal.bind(this); + this.createLeaveChannelModal = this.createLeaveChannelModal.bind(this); + this.hideLeaveChannelModal = this.hideLeaveChannelModal.bind(this); const state = this.getStateFromStores(); state.showEditChannelPurposeModal = false; @@ -84,7 +87,8 @@ export default class ChannelHeader extends React.Component { otherUserId, enableFormatting: PreferenceStore.getBool(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true), isBusy: WebrtcStore.isBusy(), - isFavorite: channel && ChannelUtils.isFavoriteChannel(channel) + isFavorite: channel && ChannelUtils.isFavoriteChannel(channel), + showLeaveChannelModal: false }; } @@ -135,7 +139,13 @@ export default class ChannelHeader extends React.Component { } handleLeave() { - ChannelActions.leaveChannel(this.state.channel.id); + if (this.state.channel.type === Constants.PRIVATE_CHANNEL) { + this.setState({ + showLeaveChannelModal: true + }); + } else { + ChannelActions.leaveChannel(this.state.channel.id); + } } toggleFavorite = (e) => { @@ -219,6 +229,54 @@ export default class ChannelHeader extends React.Component { }); } + hideLeaveChannelModal() { + this.setState({ + showLeaveChannelModal: false + }); + } + + createLeaveChannelModal() { + const title = ( + <FormattedMessage + id='leave_private_channel_modal.title' + defaultMessage='Leave Private Channel {channel}' + values={{ + channel: <b>{this.state.channel.display_name}</b> + }} + /> + ); + + const message = ( + <FormattedMessage + id='leave_private_channel_modal.message' + defaultMessage='Are you sure you wish to leave the private channel {channel}? You must be re-invited in order to re-join this channel in the future.' + values={{ + channel: <b>{this.state.channel.display_name}</b> + }} + /> + ); + + const buttonClass = 'btn btn-danger'; + const button = ( + <FormattedMessage + id='leave_private_channel_modal.leave' + defaultMessage='Yes, leave channel' + /> + ); + + return ( + <ConfirmModal + show={this.state.showLeaveChannelModal} + title={title} + message={message} + confirmButtonClass={buttonClass} + confirmButton={button} + onConfirm={() => ChannelActions.leaveChannel(this.state.channel.id)} + onCancel={this.hideLeaveChannelModal} + /> + ); + } + render() { const flagIcon = Constants.FLAG_ICON_SVG; const pinIcon = Constants.PIN_ICON; @@ -764,6 +822,8 @@ export default class ChannelHeader extends React.Component { ); } + const leaveChannelModal = this.createLeaveChannelModal(); + return ( <div id='channel-header' @@ -876,6 +936,7 @@ export default class ChannelHeader extends React.Component { </table> {editPurposeModal} {channelMembersModal} + {leaveChannelModal} <RenameChannelModal show={this.state.showRenameChannelModal} onHide={this.hideRenameChannelModal} diff --git a/webapp/components/confirm_modal.jsx b/webapp/components/confirm_modal.jsx index 8034caf9d..05288e3ac 100644 --- a/webapp/components/confirm_modal.jsx +++ b/webapp/components/confirm_modal.jsx @@ -10,11 +10,21 @@ export default class ConfirmModal extends React.Component { constructor(props) { super(props); - this.handleConfirm = this.handleConfirm.bind(this); + this.handleKeypress = this.handleKeypress.bind(this); } - handleConfirm() { - this.props.onConfirm(); + componentDidMount() { + document.addEventListener('keypress', this.handleKeypress); + } + + componentWillUnmount() { + document.removeEventListener('keypress', this.handleKeypress); + } + + handleKeypress(e) { + if (e.key === 'Enter' && this.props.show) { + this.props.onConfirm(); + } } render() { @@ -43,7 +53,7 @@ export default class ConfirmModal extends React.Component { </button> <button type='button' - className='btn btn-primary' + className={this.props.confirmButtonClass} onClick={this.props.onConfirm} > {this.props.confirmButton} @@ -57,12 +67,14 @@ export default class ConfirmModal extends React.Component { ConfirmModal.defaultProps = { title: '', message: '', + confirmButtonClass: 'btn btn-primary', confirmButton: '' }; ConfirmModal.propTypes = { show: React.PropTypes.bool.isRequired, title: React.PropTypes.node, message: React.PropTypes.node, + confirmButtonClass: React.PropTypes.string, confirmButton: React.PropTypes.node, onConfirm: React.PropTypes.func.isRequired, onCancel: React.PropTypes.func.isRequired diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index 33df0b423..6a306dafd 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -12,6 +12,7 @@ import ChannelMembersModal from './channel_members_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx'; import RenameChannelModal from './rename_channel_modal.jsx'; +import ConfirmModal from './confirm_modal.jsx'; import ToggleModalButton from './toggle_modal_button.jsx'; import StatusIcon from './status_icon.jsx'; @@ -67,6 +68,9 @@ export default class Navbar extends React.Component { this.openDirectMessageModal = this.openDirectMessageModal.bind(this); this.getPinnedPosts = this.getPinnedPosts.bind(this); + this.createLeaveChannelModal = this.createLeaveChannelModal.bind(this); + this.hideLeaveChannelModal = this.hideLeaveChannelModal.bind(this); + const state = this.getStateFromStores(); state.showEditChannelPurposeModal = false; state.showEditChannelHeaderModal = false; @@ -85,7 +89,8 @@ export default class Navbar extends React.Component { users: [], userCount: ChannelStore.getCurrentStats().member_count, currentUser: UserStore.getCurrentUser(), - isFavorite: channel && ChannelUtils.isFavoriteChannel(channel) + isFavorite: channel && ChannelUtils.isFavoriteChannel(channel), + showLeaveChannelModal: false }; } @@ -117,7 +122,13 @@ export default class Navbar extends React.Component { } handleLeave() { - ChannelActions.leaveChannel(this.state.channel.id); + if (this.state.channel.type === Constants.PRIVATE_CHANNEL) { + this.setState({ + showLeaveChannelModal: true + }); + } else { + ChannelActions.leaveChannel(this.state.channel.id); + } } hideSidebars(e) { @@ -676,6 +687,54 @@ export default class Navbar extends React.Component { return buttons; } + hideLeaveChannelModal() { + this.setState({ + showLeaveChannelModal: false + }); + } + + createLeaveChannelModal() { + const title = ( + <FormattedMessage + id='leave_private_channel_modal.title' + defaultMessage='Leave Private Channel {channel}' + values={{ + channel: <b>{this.state.channel.display_name}</b> + }} + /> + ); + + const message = ( + <FormattedMessage + id='leave_private_channel_modal.message' + defaultMessage='Are you sure you wish to leave the private channel {channel}? You must be re-invited in order to re-join this channel in the future.' + values={{ + channel: <b>{this.state.channel.display_name}</b> + }} + /> + ); + + const buttonClass = 'btn btn-danger'; + const button = ( + <FormattedMessage + id='leave_private_channel_modal.leave' + defaultMessage='Yes, leave channel' + /> + ); + + return ( + <ConfirmModal + show={this.state.showLeaveChannelModal} + title={title} + message={message} + confirmButtonClass={buttonClass} + confirmButton={button} + onConfirm={() => ChannelActions.leaveChannel(this.state.channel.id)} + onCancel={this.hideLeaveChannelModal} + /> + ); + } + getTeammateStatus() { const channel = this.state.channel; @@ -844,6 +903,8 @@ export default class Navbar extends React.Component { var channelMenuDropdown = this.createDropdown(channel, channelTitle, isSystemAdmin, isTeamAdmin, isChannelAdmin, isDirect, isGroup, popoverContent); + const leaveChannelModal = this.createLeaveChannelModal(); + return ( <div> <nav @@ -860,6 +921,7 @@ export default class Navbar extends React.Component { </nav> {editChannelHeaderModal} {editChannelPurposeModal} + {leaveChannelModal} {renameChannelModal} {channelMembersModal} {channelSwitchModal} diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index 29a46ac6b..d52d1c331 100755 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -1583,6 +1583,9 @@ "ldap_signup.length_error": "Name must be 3 or more characters up to a maximum of 15", "ldap_signup.teamName": "Enter name of new team", "ldap_signup.team_error": "Please enter a team name", + "leave_private_channel_modal.title": "Leave Private Channel {channel}", + "leave_private_channel_modal.message": "Are you sure you wish to leave the private channel {channel}? You must be re-invited in order to re-join this channel in the future.", + "leave_private_channel_modal.leave": "Yes, leave channel", "leave_team_modal.desc": "You will be removed from all public and private channels. If the team is private you will not be able to rejoin the team. Are you sure?", "leave_team_modal.no": "No", "leave_team_modal.title": "Leave the team?", |