Add confirm dialog before leaving private channel (#6206)

Этот коммит содержится в:
Ryan Wang
2017-04-25 12:34:21 -04:00
коммит произвёл Corey Hulen
родитель 6c4c706313
Коммит f1668bad15
4 изменённых файлов: 146 добавлений и 8 удалений

Просмотреть файл

@@ -14,6 +14,7 @@ import ChannelMembersModal from './channel_members_modal.jsx';
import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx';
import DeleteChannelModal from './delete_channel_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx';
import RenameChannelModal from './rename_channel_modal.jsx'; import RenameChannelModal from './rename_channel_modal.jsx';
import ConfirmModal from './confirm_modal.jsx';
import ToggleModalButton from './toggle_modal_button.jsx'; import ToggleModalButton from './toggle_modal_button.jsx';
import ChannelStore from 'stores/channel_store.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.initWebrtc = this.initWebrtc.bind(this);
this.onBusy = this.onBusy.bind(this); this.onBusy = this.onBusy.bind(this);
this.openDirectMessageModal = this.openDirectMessageModal.bind(this); this.openDirectMessageModal = this.openDirectMessageModal.bind(this);
this.createLeaveChannelModal = this.createLeaveChannelModal.bind(this);
this.hideLeaveChannelModal = this.hideLeaveChannelModal.bind(this);
const state = this.getStateFromStores(); const state = this.getStateFromStores();
state.showEditChannelPurposeModal = false; state.showEditChannelPurposeModal = false;
@@ -84,7 +87,8 @@ export default class ChannelHeader extends React.Component {
otherUserId, otherUserId,
enableFormatting: PreferenceStore.getBool(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true), enableFormatting: PreferenceStore.getBool(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true),
isBusy: WebrtcStore.isBusy(), isBusy: WebrtcStore.isBusy(),
isFavorite: channel && ChannelUtils.isFavoriteChannel(channel) isFavorite: channel && ChannelUtils.isFavoriteChannel(channel),
showLeaveChannelModal: false
}; };
} }
@@ -135,8 +139,14 @@ export default class ChannelHeader extends React.Component {
} }
handleLeave() { handleLeave() {
if (this.state.channel.type === Constants.PRIVATE_CHANNEL) {
this.setState({
showLeaveChannelModal: true
});
} else {
ChannelActions.leaveChannel(this.state.channel.id); ChannelActions.leaveChannel(this.state.channel.id);
} }
}
toggleFavorite = (e) => { toggleFavorite = (e) => {
e.preventDefault(); e.preventDefault();
@@ -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() { render() {
const flagIcon = Constants.FLAG_ICON_SVG; const flagIcon = Constants.FLAG_ICON_SVG;
const pinIcon = Constants.PIN_ICON; const pinIcon = Constants.PIN_ICON;
@@ -764,6 +822,8 @@ export default class ChannelHeader extends React.Component {
); );
} }
const leaveChannelModal = this.createLeaveChannelModal();
return ( return (
<div <div
id='channel-header' id='channel-header'
@@ -876,6 +936,7 @@ export default class ChannelHeader extends React.Component {
</table> </table>
{editPurposeModal} {editPurposeModal}
{channelMembersModal} {channelMembersModal}
{leaveChannelModal}
<RenameChannelModal <RenameChannelModal
show={this.state.showRenameChannelModal} show={this.state.showRenameChannelModal}
onHide={this.hideRenameChannelModal} onHide={this.hideRenameChannelModal}

Просмотреть файл

@@ -10,12 +10,22 @@ export default class ConfirmModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleConfirm = this.handleConfirm.bind(this); this.handleKeypress = this.handleKeypress.bind(this);
} }
handleConfirm() { componentDidMount() {
document.addEventListener('keypress', this.handleKeypress);
}
componentWillUnmount() {
document.removeEventListener('keypress', this.handleKeypress);
}
handleKeypress(e) {
if (e.key === 'Enter' && this.props.show) {
this.props.onConfirm(); this.props.onConfirm();
} }
}
render() { render() {
return ( return (
@@ -43,7 +53,7 @@ export default class ConfirmModal extends React.Component {
</button> </button>
<button <button
type='button' type='button'
className='btn btn-primary' className={this.props.confirmButtonClass}
onClick={this.props.onConfirm} onClick={this.props.onConfirm}
> >
{this.props.confirmButton} {this.props.confirmButton}
@@ -57,12 +67,14 @@ export default class ConfirmModal extends React.Component {
ConfirmModal.defaultProps = { ConfirmModal.defaultProps = {
title: '', title: '',
message: '', message: '',
confirmButtonClass: 'btn btn-primary',
confirmButton: '' confirmButton: ''
}; };
ConfirmModal.propTypes = { ConfirmModal.propTypes = {
show: React.PropTypes.bool.isRequired, show: React.PropTypes.bool.isRequired,
title: React.PropTypes.node, title: React.PropTypes.node,
message: React.PropTypes.node, message: React.PropTypes.node,
confirmButtonClass: React.PropTypes.string,
confirmButton: React.PropTypes.node, confirmButton: React.PropTypes.node,
onConfirm: React.PropTypes.func.isRequired, onConfirm: React.PropTypes.func.isRequired,
onCancel: React.PropTypes.func.isRequired onCancel: React.PropTypes.func.isRequired

Просмотреть файл

@@ -12,6 +12,7 @@ import ChannelMembersModal from './channel_members_modal.jsx';
import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx';
import DeleteChannelModal from './delete_channel_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx';
import RenameChannelModal from './rename_channel_modal.jsx'; import RenameChannelModal from './rename_channel_modal.jsx';
import ConfirmModal from './confirm_modal.jsx';
import ToggleModalButton from './toggle_modal_button.jsx'; import ToggleModalButton from './toggle_modal_button.jsx';
import StatusIcon from './status_icon.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.openDirectMessageModal = this.openDirectMessageModal.bind(this);
this.getPinnedPosts = this.getPinnedPosts.bind(this); this.getPinnedPosts = this.getPinnedPosts.bind(this);
this.createLeaveChannelModal = this.createLeaveChannelModal.bind(this);
this.hideLeaveChannelModal = this.hideLeaveChannelModal.bind(this);
const state = this.getStateFromStores(); const state = this.getStateFromStores();
state.showEditChannelPurposeModal = false; state.showEditChannelPurposeModal = false;
state.showEditChannelHeaderModal = false; state.showEditChannelHeaderModal = false;
@@ -85,7 +89,8 @@ export default class Navbar extends React.Component {
users: [], users: [],
userCount: ChannelStore.getCurrentStats().member_count, userCount: ChannelStore.getCurrentStats().member_count,
currentUser: UserStore.getCurrentUser(), currentUser: UserStore.getCurrentUser(),
isFavorite: channel && ChannelUtils.isFavoriteChannel(channel) isFavorite: channel && ChannelUtils.isFavoriteChannel(channel),
showLeaveChannelModal: false
}; };
} }
@@ -117,8 +122,14 @@ export default class Navbar extends React.Component {
} }
handleLeave() { handleLeave() {
if (this.state.channel.type === Constants.PRIVATE_CHANNEL) {
this.setState({
showLeaveChannelModal: true
});
} else {
ChannelActions.leaveChannel(this.state.channel.id); ChannelActions.leaveChannel(this.state.channel.id);
} }
}
hideSidebars(e) { hideSidebars(e) {
var windowWidth = $(window).outerWidth(); var windowWidth = $(window).outerWidth();
@@ -676,6 +687,54 @@ export default class Navbar extends React.Component {
return buttons; 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() { getTeammateStatus() {
const channel = this.state.channel; 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); var channelMenuDropdown = this.createDropdown(channel, channelTitle, isSystemAdmin, isTeamAdmin, isChannelAdmin, isDirect, isGroup, popoverContent);
const leaveChannelModal = this.createLeaveChannelModal();
return ( return (
<div> <div>
<nav <nav
@@ -860,6 +921,7 @@ export default class Navbar extends React.Component {
</nav> </nav>
{editChannelHeaderModal} {editChannelHeaderModal}
{editChannelPurposeModal} {editChannelPurposeModal}
{leaveChannelModal}
{renameChannelModal} {renameChannelModal}
{channelMembersModal} {channelMembersModal}
{channelSwitchModal} {channelSwitchModal}

Просмотреть файл

@@ -1583,6 +1583,9 @@
"ldap_signup.length_error": "Name must be 3 or more characters up to a maximum of 15", "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.teamName": "Enter name of new team",
"ldap_signup.team_error": "Please enter a team name", "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.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.no": "No",
"leave_team_modal.title": "Leave the team?", "leave_team_modal.title": "Leave the team?",