summaryrefslogtreecommitdiffstats
path: root/webapp/components
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/components')
-rw-r--r--webapp/components/post_view/components/post.jsx6
-rw-r--r--webapp/components/post_view/components/post_header.jsx2
-rw-r--r--webapp/components/post_view/components/post_info.jsx8
-rw-r--r--webapp/components/post_view/components/post_list.jsx27
-rw-r--r--webapp/components/user_settings/user_settings_notifications.jsx154
5 files changed, 184 insertions, 13 deletions
diff --git a/webapp/components/post_view/components/post.jsx b/webapp/components/post_view/components/post.jsx
index ff443e355..3fdd8094e 100644
--- a/webapp/components/post_view/components/post.jsx
+++ b/webapp/components/post_view/components/post.jsx
@@ -76,6 +76,10 @@ export default class Post extends React.Component {
return true;
}
+ if (nextProps.isCommentMention !== this.props.isCommentMention) {
+ return true;
+ }
+
if (nextProps.shouldHighlight !== this.props.shouldHighlight) {
return true;
}
@@ -231,6 +235,7 @@ export default class Post extends React.Component {
post={post}
sameRoot={this.props.sameRoot}
commentCount={commentCount}
+ isCommentMention={this.props.isCommentMention}
handleCommentClick={this.handleCommentClick}
handleDropdownOpened={this.handleDropdownOpened}
isLastComment={this.props.isLastComment}
@@ -274,6 +279,7 @@ Post.propTypes = {
compactDisplay: React.PropTypes.bool,
previewCollapsed: React.PropTypes.string,
commentCount: React.PropTypes.number,
+ isCommentMention: React.PropTypes.bool,
useMilitaryTime: React.PropTypes.bool.isRequired,
emojis: React.PropTypes.object.isRequired
};
diff --git a/webapp/components/post_view/components/post_header.jsx b/webapp/components/post_view/components/post_header.jsx
index e76358304..07b601baf 100644
--- a/webapp/components/post_view/components/post_header.jsx
+++ b/webapp/components/post_view/components/post_header.jsx
@@ -63,6 +63,7 @@ export default class PostHeader extends React.Component {
<PostInfo
post={post}
commentCount={this.props.commentCount}
+ isCommentMention={this.props.isCommentMention}
handleCommentClick={this.props.handleCommentClick}
handleDropdownOpened={this.props.handleDropdownOpened}
allowReply='true'
@@ -89,6 +90,7 @@ PostHeader.propTypes = {
user: React.PropTypes.object,
currentUser: React.PropTypes.object.isRequired,
commentCount: React.PropTypes.number.isRequired,
+ isCommentMention: React.PropTypes.bool.isRequired,
isLastComment: React.PropTypes.bool.isRequired,
handleCommentClick: React.PropTypes.func.isRequired,
handleDropdownOpened: React.PropTypes.func.isRequired,
diff --git a/webapp/components/post_view/components/post_info.jsx b/webapp/components/post_view/components/post_info.jsx
index d74be4c72..98639529e 100644
--- a/webapp/components/post_view/components/post_info.jsx
+++ b/webapp/components/post_view/components/post_info.jsx
@@ -174,6 +174,7 @@ export default class PostInfo extends React.Component {
var post = this.props.post;
var comments = '';
var showCommentClass = '';
+ var highlightMentionClass = '';
var commentCountText = this.props.commentCount;
if (this.props.commentCount >= 1) {
@@ -182,11 +183,15 @@ export default class PostInfo extends React.Component {
commentCountText = '';
}
+ if (this.props.isCommentMention) {
+ highlightMentionClass = ' mention--highlight';
+ }
+
if (post.state !== Constants.POST_FAILED && post.state !== Constants.POST_LOADING && !Utils.isPostEphemeral(post)) {
comments = (
<a
href='#'
- className={'comment-icon__container' + showCommentClass}
+ className={'comment-icon__container' + showCommentClass + highlightMentionClass}
onClick={this.props.handleCommentClick}
>
<span
@@ -234,6 +239,7 @@ PostInfo.defaultProps = {
PostInfo.propTypes = {
post: React.PropTypes.object.isRequired,
commentCount: React.PropTypes.number.isRequired,
+ isCommentMention: React.PropTypes.bool.isRequired,
isLastComment: React.PropTypes.bool.isRequired,
allowReply: React.PropTypes.string.isRequired,
handleCommentClick: React.PropTypes.func.isRequired,
diff --git a/webapp/components/post_view/components/post_list.jsx b/webapp/components/post_view/components/post_list.jsx
index 70107c838..9f958a5b6 100644
--- a/webapp/components/post_view/components/post_list.jsx
+++ b/webapp/components/post_view/components/post_list.jsx
@@ -251,15 +251,35 @@ export default class PostList extends React.Component {
}
let commentCount = 0;
+ let nonOwnCommentsExists = false;
+ let isCommentMention = false;
let commentRootId;
if (parentPost) {
commentRootId = post.root_id;
} else {
commentRootId = post.id;
}
- for (const postId in posts) {
- if (posts[postId].root_id === commentRootId) {
- commentCount += 1;
+ if (commentRootId) {
+ const commentsNotifyLevel = this.props.currentUser.notify_props.comments || 'never';
+ for (const postId in posts) {
+ if (posts[postId].root_id === commentRootId) {
+ commentCount += 1;
+ if (posts[postId].user_id !== this.props.currentUser.id) {
+ nonOwnCommentsExists = true;
+ }
+ if (posts[postId].user_id === this.props.currentUser.id && commentsNotifyLevel === 'any' && !isCommentMention) {
+ for (const nextPostId in posts) {
+ if (posts[nextPostId].root_id === commentRootId && posts[nextPostId].user_id !== this.props.currentUser.id &&
+ posts[postId].create_at < posts[nextPostId].create_at) {
+ isCommentMention = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (nonOwnCommentsExists && posts[commentRootId].user_id === this.props.currentUser.id && commentsNotifyLevel !== 'never') {
+ isCommentMention = true;
}
}
@@ -279,6 +299,7 @@ export default class PostList extends React.Component {
currentUser={this.props.currentUser}
center={this.props.displayPostsInCenter}
commentCount={commentCount}
+ isCommentMention={isCommentMention}
compactDisplay={this.props.compactDisplay}
previewCollapsed={this.props.previewsCollapsed}
useMilitaryTime={this.props.useMilitaryTime}
diff --git a/webapp/components/user_settings/user_settings_notifications.jsx b/webapp/components/user_settings/user_settings_notifications.jsx
index 5ae2a83af..b9e9b6de1 100644
--- a/webapp/components/user_settings/user_settings_notifications.jsx
+++ b/webapp/components/user_settings/user_settings_notifications.jsx
@@ -2,7 +2,6 @@
// See License.txt for license information.
import $ from 'jquery';
-import ReactDOM from 'react-dom';
import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx';
@@ -26,6 +25,10 @@ function getNotificationsStateFromStores() {
if (user.notify_props && user.notify_props.desktop) {
desktop = user.notify_props.desktop;
}
+ var comments = 'never';
+ if (user.notify_props && user.notify_props.comments) {
+ comments = user.notify_props.comments;
+ }
var email = 'true';
if (user.notify_props && user.notify_props.email) {
email = user.notify_props.email;
@@ -82,7 +85,8 @@ function getNotificationsStateFromStores() {
customKeys,
customKeysChecked: customKeys.length > 0,
firstNameKey,
- channelKey
+ channelKey,
+ notifyCommentsLevel: comments
};
}
@@ -103,6 +107,10 @@ const holders = defineMessages({
id: 'user.settings.notifications.wordsTrigger',
defaultMessage: 'Words that trigger mentions'
},
+ comments: {
+ id: 'user.settings.notifications.comments',
+ defaultMessage: 'Comment threads notifications'
+ },
close: {
id: 'user.settings.notifications.close',
defaultMessage: 'Close'
@@ -140,6 +148,7 @@ class NotificationsTab extends React.Component {
data.desktop_sound = this.state.enableSound;
data.desktop = this.state.notifyLevel;
data.push = this.state.notifyPushLevel;
+ data.comments = this.state.notifyCommentsLevel;
var mentionKeys = [];
if (this.state.usernameKey) {
@@ -195,21 +204,26 @@ class NotificationsTab extends React.Component {
}
handleNotifyRadio(notifyLevel) {
this.setState({notifyLevel});
- ReactDOM.findDOMNode(this.refs.wrapper).focus();
+ this.refs.wrapper.focus();
+ }
+
+ handleNotifyCommentsRadio(notifyCommentsLevel) {
+ this.setState({notifyCommentsLevel});
+ this.refs.wrapper.focus();
}
handlePushRadio(notifyPushLevel) {
this.setState({notifyPushLevel});
- ReactDOM.findDOMNode(this.refs.wrapper).focus();
+ this.refs.wrapper.focus();
}
handleEmailRadio(enableEmail) {
this.setState({enableEmail});
- ReactDOM.findDOMNode(this.refs.wrapper).focus();
+ this.refs.wrapper.focus();
}
handleSoundRadio(enableSound) {
this.setState({enableSound});
- ReactDOM.findDOMNode(this.refs.wrapper).focus();
+ this.refs.wrapper.focus();
}
updateUsernameKey(val) {
this.setState({usernameKey: val});
@@ -224,10 +238,10 @@ class NotificationsTab extends React.Component {
this.setState({channelKey: val});
}
updateCustomMentionKeys() {
- var checked = ReactDOM.findDOMNode(this.refs.customcheck).checked;
+ var checked = this.refs.customcheck.checked;
if (checked) {
- var text = ReactDOM.findDOMNode(this.refs.custommentions).value;
+ var text = this.refs.custommentions.value;
// remove all spaces and split string into individual keys
this.setState({customKeys: text.replace(/ /g, ''), customKeysChecked: true});
@@ -236,7 +250,7 @@ class NotificationsTab extends React.Component {
}
}
onCustomChange() {
- ReactDOM.findDOMNode(this.refs.customcheck).checked = true;
+ this.refs.customcheck.checked = true;
this.updateCustomMentionKeys();
}
createPushNotificationSection() {
@@ -902,6 +916,126 @@ class NotificationsTab extends React.Component {
);
}
+ var commentsSection;
+ var handleUpdateCommentsSection;
+ if (this.props.activeSection === 'comments') {
+ var commentsActive = [false, false, false];
+ if (this.state.notifyCommentsLevel === 'never') {
+ commentsActive[2] = true;
+ } else if (this.state.notifyCommentsLevel === 'root') {
+ commentsActive[1] = true;
+ } else {
+ commentsActive[0] = true;
+ }
+
+ let inputs = [];
+
+ inputs.push(
+ <div key='userNotificationLevelOption'>
+ <div className='radio'>
+ <label>
+ <input
+ type='radio'
+ name='commentsNotificationLevel'
+ checked={commentsActive[0]}
+ onChange={this.handleNotifyCommentsRadio.bind(this, 'any')}
+ />
+ <FormattedMessage
+ id='user.settings.notifications.commentsAny'
+ defaultMessage='Mention any comments in a thread you participated in (This will include both mentions to your root post and any comments after you commented on a post)'
+ />
+ </label>
+ <br/>
+ </div>
+ <div className='radio'>
+ <label>
+ <input
+ type='radio'
+ name='commentsNotificationLevel'
+ checked={commentsActive[1]}
+ onChange={this.handleNotifyCommentsRadio.bind(this, 'root')}
+ />
+ <FormattedMessage
+ id='user.settings.notifications.commentsRoot'
+ defaultMessage='Mention any comments on your post'
+ />
+ </label>
+ <br/>
+ </div>
+ <div className='radio'>
+ <label>
+ <input
+ type='radio'
+ name='commentsNotificationLevel'
+ checked={commentsActive[2]}
+ onChange={this.handleNotifyCommentsRadio.bind(this, 'never')}
+ />
+ <FormattedMessage
+ id='user.settings.notifications.commentsNever'
+ defaultMessage='No mentions for comments'
+ />
+ </label>
+ </div>
+ </div>
+ );
+
+ const extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.notifications.commentsInfo'
+ defaultMessage='Mode of triggering notifications on posts in comment threads you participated in.'
+ />
+ </span>
+ );
+
+ commentsSection = (
+ <SettingItemMax
+ title={formatMessage(holders.comments)}
+ extraInfo={extraInfo}
+ inputs={inputs}
+ submit={this.handleSubmit}
+ server_error={serverError}
+ updateSection={this.handleCancel}
+ />
+ );
+ } else {
+ let describe = '';
+ if (this.state.notifyCommentsLevel === 'never') {
+ describe = (
+ <FormattedMessage
+ id='user.settings.notifications.commentsNever'
+ defaultMessage='No mentions for comments'
+ />
+ );
+ } else if (this.state.notifyCommentsLevel === 'root') {
+ describe = (
+ <FormattedMessage
+ id='user.settings.notifications.commentsRoot'
+ defaultMessage='Mention any comments on your post'
+ />
+ );
+ } else {
+ describe = (
+ <FormattedMessage
+ id='user.settings.notifications.commentsAny'
+ defaultMessage='Mention any comments in a thread you participated in (This will include both mentions to your root post and any comments after you commented on a post)'
+ />
+ );
+ }
+
+ handleUpdateCommentsSection = function updateCommentsSection() {
+ this.props.updateSection('comments');
+ }.bind(this);
+
+ commentsSection = (
+ <SettingItemMin
+ title={formatMessage(holders.comments)}
+ describe={describe}
+ updateSection={handleUpdateCommentsSection}
+ />
+ );
+ }
+
const pushNotificationSection = this.createPushNotificationSection();
return (
@@ -952,6 +1086,8 @@ class NotificationsTab extends React.Component {
{pushNotificationSection}
<div className='divider-light'/>
{keysSection}
+ <div className='divider-light'/>
+ {commentsSection}
<div className='divider-dark'/>
</div>
</div>