Implement PLT-6246 - Confirm before sending (at)all, (at)channel message (#6250)
* implement PLT-6246 - Confirm before sending (at)all, (at)channel message * refactor per review * add constant to define the notify all modal
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
eab6f74594
Коммит
d409c7c1c6
@@ -16,11 +16,23 @@ export default class ConfirmModal extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
document.addEventListener('keypress', this.handleKeypress);
|
if (this.props.show) {
|
||||||
|
document.addEventListener('keypress', this.handleKeypress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
document.removeEventListener('keypress', this.handleKeypress);
|
if (!this.props.show) {
|
||||||
|
document.removeEventListener('keypress', this.handleKeypress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (this.props.show && !nextProps.show) {
|
||||||
|
document.removeEventListener('keypress', this.handleKeypress);
|
||||||
|
} else if (!this.props.show && nextProps.show) {
|
||||||
|
document.addEventListener('keypress', this.handleKeypress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeypress(e) {
|
handleKeypress(e) {
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ import PostStore from 'stores/post_store.jsx';
|
|||||||
import MessageHistoryStore from 'stores/message_history_store.jsx';
|
import MessageHistoryStore from 'stores/message_history_store.jsx';
|
||||||
import UserStore from 'stores/user_store.jsx';
|
import UserStore from 'stores/user_store.jsx';
|
||||||
import PreferenceStore from 'stores/preference_store.jsx';
|
import PreferenceStore from 'stores/preference_store.jsx';
|
||||||
|
import ConfirmModal from './confirm_modal.jsx';
|
||||||
|
|
||||||
import Constants from 'utils/constants.jsx';
|
import Constants from 'utils/constants.jsx';
|
||||||
|
|
||||||
import {FormattedHTMLMessage} from 'react-intl';
|
import {FormattedHTMLMessage, FormattedMessage} from 'react-intl';
|
||||||
import {browserHistory} from 'react-router/es6';
|
import {browserHistory} from 'react-router/es6';
|
||||||
|
|
||||||
const Preferences = Constants.Preferences;
|
const Preferences = Constants.Preferences;
|
||||||
@@ -45,6 +46,7 @@ export default class CreatePost extends React.Component {
|
|||||||
|
|
||||||
this.lastTime = 0;
|
this.lastTime = 0;
|
||||||
|
|
||||||
|
this.doSubmit = this.doSubmit.bind(this);
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
this.handleSubmit = this.handleSubmit.bind(this);
|
||||||
this.postMsgKeyPress = this.postMsgKeyPress.bind(this);
|
this.postMsgKeyPress = this.postMsgKeyPress.bind(this);
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
@@ -68,12 +70,19 @@ export default class CreatePost extends React.Component {
|
|||||||
this.handleEmojiPickerClick = this.handleEmojiPickerClick.bind(this);
|
this.handleEmojiPickerClick = this.handleEmojiPickerClick.bind(this);
|
||||||
this.handlePostError = this.handlePostError.bind(this);
|
this.handlePostError = this.handlePostError.bind(this);
|
||||||
this.closeEmoji = this.closeEmoji.bind(this);
|
this.closeEmoji = this.closeEmoji.bind(this);
|
||||||
|
this.hideNotifyAllModal = this.hideNotifyAllModal.bind(this);
|
||||||
|
this.showNotifyAllModal = this.showNotifyAllModal.bind(this);
|
||||||
|
this.handleNotifyModalCancel = this.handleNotifyModalCancel.bind(this);
|
||||||
|
this.handleNotifyAllConfirmation = this.handleNotifyAllConfirmation.bind(this);
|
||||||
|
|
||||||
PostStore.clearDraftUploads();
|
PostStore.clearDraftUploads();
|
||||||
|
|
||||||
const channelId = ChannelStore.getCurrentId();
|
const channelId = ChannelStore.getCurrentId();
|
||||||
const draft = PostStore.getPostDraft(channelId);
|
const draft = PostStore.getPostDraft(channelId);
|
||||||
|
|
||||||
|
const stats = ChannelStore.getCurrentStats();
|
||||||
|
const members = stats.member_count - 1;
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
channelId,
|
channelId,
|
||||||
message: draft.message,
|
message: draft.message,
|
||||||
@@ -86,7 +95,9 @@ export default class CreatePost extends React.Component {
|
|||||||
showPostDeletedModal: false,
|
showPostDeletedModal: false,
|
||||||
enableSendButton: false,
|
enableSendButton: false,
|
||||||
showEmojiPicker: false,
|
showEmojiPicker: false,
|
||||||
emojiPickerEnabled: Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMOJI_PICKER_PREVIEW)
|
emojiPickerEnabled: Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMOJI_PICKER_PREVIEW),
|
||||||
|
showConfirmModal: false,
|
||||||
|
totalMembers: members
|
||||||
};
|
};
|
||||||
|
|
||||||
this.lastBlurAt = 0;
|
this.lastBlurAt = 0;
|
||||||
@@ -108,13 +119,9 @@ export default class CreatePost extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmit(e) {
|
doSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (this.state.uploadsInProgress.length > 0 || this.state.submitting) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const post = {};
|
const post = {};
|
||||||
post.file_ids = [];
|
post.file_ids = [];
|
||||||
post.message = this.state.message;
|
post.message = this.state.message;
|
||||||
@@ -193,6 +200,35 @@ export default class CreatePost extends React.Component {
|
|||||||
this.focusTextbox(forceFocus);
|
this.focusTextbox(forceFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNotifyAllConfirmation(e) {
|
||||||
|
this.hideNotifyAllModal();
|
||||||
|
this.doSubmit(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideNotifyAllModal() {
|
||||||
|
this.setState({showConfirmModal: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
showNotifyAllModal() {
|
||||||
|
this.setState({showConfirmModal: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit(e) {
|
||||||
|
const stats = ChannelStore.getCurrentStats();
|
||||||
|
const members = stats.member_count - 1;
|
||||||
|
|
||||||
|
if ((this.state.message.includes('@all') || this.state.message.includes('@channel')) && members >= Constants.NOTIFY_ALL_MEMBERS) {
|
||||||
|
this.setState({totalMembers: members});
|
||||||
|
this.showNotifyAllModal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.doSubmit(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNotifyModalCancel() {
|
||||||
|
this.setState({showConfirmModal: false});
|
||||||
|
}
|
||||||
|
|
||||||
sendMessage(post) {
|
sendMessage(post) {
|
||||||
post.channel_id = this.state.channelId;
|
post.channel_id = this.state.channelId;
|
||||||
post.file_ids = this.state.fileInfos.map((info) => info.id);
|
post.file_ids = this.state.fileInfos.map((info) => info.id);
|
||||||
@@ -574,6 +610,30 @@ export default class CreatePost extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const notifyAllTitle = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='notify_all.title.confirm'
|
||||||
|
defaultMessage='Confirm sending notifications to entire channel'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const notifyAllConfirm = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='notify_all.confirm'
|
||||||
|
defaultMessage='Confirm'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const notifyAllMessage = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='notify_all.question'
|
||||||
|
defaultMessage='By using @all or @channel you are about to send notifications to {totalMembers} people. Are you sure you want to do this?'
|
||||||
|
values={{
|
||||||
|
totalMembers: this.state.totalMembers
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
let serverError = null;
|
let serverError = null;
|
||||||
if (this.state.serverError) {
|
if (this.state.serverError) {
|
||||||
serverError = (
|
serverError = (
|
||||||
@@ -699,6 +759,14 @@ export default class CreatePost extends React.Component {
|
|||||||
show={this.state.showPostDeletedModal}
|
show={this.state.showPostDeletedModal}
|
||||||
onHide={this.hidePostDeletedModal}
|
onHide={this.hidePostDeletedModal}
|
||||||
/>
|
/>
|
||||||
|
<ConfirmModal
|
||||||
|
title={notifyAllTitle}
|
||||||
|
message={notifyAllMessage}
|
||||||
|
confirmButton={notifyAllConfirm}
|
||||||
|
show={this.state.showConfirmModal}
|
||||||
|
onConfirm={this.handleNotifyAllConfirmation}
|
||||||
|
onCancel={this.handleNotifyModalCancel}
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1257,6 +1257,9 @@
|
|||||||
"delete_post.warning": "This post has {count} comment(s) on it.",
|
"delete_post.warning": "This post has {count} comment(s) on it.",
|
||||||
"edit_channel_header.editHeader": "Edit the Channel Header...",
|
"edit_channel_header.editHeader": "Edit the Channel Header...",
|
||||||
"edit_channel_header.previewHeader": "Edit header",
|
"edit_channel_header.previewHeader": "Edit header",
|
||||||
|
"notify_all.title.confirm": "Confirm sending notifications to entire channel",
|
||||||
|
"notify_all.question": "By using @all or @channel you are about to send notifications to {totalMembers} people. Are you sure you want to do this?",
|
||||||
|
"notify_all.confirm": "Confirm",
|
||||||
"edit_channel_header_modal.cancel": "Cancel",
|
"edit_channel_header_modal.cancel": "Cancel",
|
||||||
"edit_channel_header_modal.description": "Edit the text appearing next to the channel name in the channel header.",
|
"edit_channel_header_modal.description": "Edit the text appearing next to the channel name in the channel header.",
|
||||||
"edit_channel_header_modal.error": "This channel header is too long, please enter a shorter one",
|
"edit_channel_header_modal.error": "This channel header is too long, please enter a shorter one",
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ export const Constants = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
SPECIAL_MENTIONS: ['all', 'channel', 'here'],
|
SPECIAL_MENTIONS: ['all', 'channel', 'here'],
|
||||||
|
NOTIFY_ALL_MEMBERS: 5,
|
||||||
CHARACTER_LIMIT: 4000,
|
CHARACTER_LIMIT: 4000,
|
||||||
IMAGE_TYPES: ['jpg', 'gif', 'bmp', 'png', 'jpeg'],
|
IMAGE_TYPES: ['jpg', 'gif', 'bmp', 'png', 'jpeg'],
|
||||||
AUDIO_TYPES: ['mp3', 'wav', 'wma', 'm4a', 'flac', 'aac', 'ogg'],
|
AUDIO_TYPES: ['mp3', 'wav', 'wma', 'm4a', 'flac', 'aac', 'ogg'],
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user