summaryrefslogtreecommitdiffstats
path: root/webapp/components/post_view
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/components/post_view')
-rw-r--r--webapp/components/post_view/components/post.jsx8
-rw-r--r--webapp/components/post_view/components/post_header.jsx4
-rw-r--r--webapp/components/post_view/components/post_info.jsx119
-rw-r--r--webapp/components/post_view/components/post_list.jsx9
-rw-r--r--webapp/components/post_view/post_focus_view_controller.jsx13
-rw-r--r--webapp/components/post_view/post_view_controller.jsx11
6 files changed, 154 insertions, 10 deletions
diff --git a/webapp/components/post_view/components/post.jsx b/webapp/components/post_view/components/post.jsx
index 3fdd8094e..038bcab78 100644
--- a/webapp/components/post_view/components/post.jsx
+++ b/webapp/components/post_view/components/post.jsx
@@ -100,6 +100,10 @@ export default class Post extends React.Component {
return true;
}
+ if (nextProps.isFlagged !== this.props.isFlagged) {
+ return true;
+ }
+
if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) {
return true;
}
@@ -245,6 +249,7 @@ export default class Post extends React.Component {
compactDisplay={this.props.compactDisplay}
displayNameType={this.props.displayNameType}
useMilitaryTime={this.props.useMilitaryTime}
+ isFlagged={this.props.isFlagged}
/>
<PostBody
post={post}
@@ -281,5 +286,6 @@ Post.propTypes = {
commentCount: React.PropTypes.number,
isCommentMention: React.PropTypes.bool,
useMilitaryTime: React.PropTypes.bool.isRequired,
- emojis: React.PropTypes.object.isRequired
+ emojis: React.PropTypes.object.isRequired,
+ isFlagged: React.PropTypes.bool
};
diff --git a/webapp/components/post_view/components/post_header.jsx b/webapp/components/post_view/components/post_header.jsx
index 07b601baf..6c356126d 100644
--- a/webapp/components/post_view/components/post_header.jsx
+++ b/webapp/components/post_view/components/post_header.jsx
@@ -72,6 +72,7 @@ export default class PostHeader extends React.Component {
currentUser={this.props.currentUser}
compactDisplay={this.props.compactDisplay}
useMilitaryTime={this.props.useMilitaryTime}
+ isFlagged={this.props.isFlagged}
/>
</li>
</ul>
@@ -97,5 +98,6 @@ PostHeader.propTypes = {
sameUser: React.PropTypes.bool.isRequired,
compactDisplay: React.PropTypes.bool,
displayNameType: React.PropTypes.string,
- useMilitaryTime: React.PropTypes.bool.isRequired
+ useMilitaryTime: React.PropTypes.bool.isRequired,
+ isFlagged: React.PropTypes.bool.isRequired
};
diff --git a/webapp/components/post_view/components/post_info.jsx b/webapp/components/post_view/components/post_info.jsx
index ba6a9a982..d48d97ba1 100644
--- a/webapp/components/post_view/components/post_info.jsx
+++ b/webapp/components/post_view/components/post_info.jsx
@@ -2,17 +2,21 @@
// See License.txt for license information.
import $ from 'jquery';
-import * as Utils from 'utils/utils.jsx';
+
import PostTime from './post_time.jsx';
+
import * as GlobalActions from 'actions/global_actions.jsx';
+import * as PostActions from 'actions/post_actions.jsx';
+
import TeamStore from 'stores/team_store.jsx';
import UserStore from 'stores/user_store.jsx';
+import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
-
-import {FormattedMessage} from 'react-intl';
+import {Tooltip, OverlayTrigger} from 'react-bootstrap';
import React from 'react';
+import {FormattedMessage} from 'react-intl';
export default class PostInfo extends React.Component {
constructor(props) {
@@ -21,7 +25,10 @@ export default class PostInfo extends React.Component {
this.handleDropdownClick = this.handleDropdownClick.bind(this);
this.handlePermalink = this.handlePermalink.bind(this);
this.removePost = this.removePost.bind(this);
+ this.flagPost = this.flagPost.bind(this);
+ this.unflagPost = this.unflagPost.bind(this);
}
+
handleDropdownClick(e) {
var position = $('#post-list').height() - $(e.target).offset().top;
var dropdown = $(e.target).closest('.col__reply').find('.dropdown-menu');
@@ -29,10 +36,12 @@ export default class PostInfo extends React.Component {
dropdown.addClass('bottom');
}
}
+
componentDidMount() {
$('#post_dropdown' + this.props.post.id).on('shown.bs.dropdown', () => this.props.handleDropdownOpened(true));
$('#post_dropdown' + this.props.post.id).on('hidden.bs.dropdown', () => this.props.handleDropdownOpened(false));
}
+
createDropdown() {
var post = this.props.post;
var isOwner = this.props.currentUser.id === post.user_id;
@@ -74,6 +83,44 @@ export default class PostInfo extends React.Component {
);
}
+ if (Utils.isMobile()) {
+ if (this.props.isFlagged) {
+ dropdownContents.push(
+ <li
+ key='mobileFlag'
+ role='presentation'
+ >
+ <a
+ href='#'
+ onClick={this.unflagPost}
+ >
+ <FormattedMessage
+ id='rhs_root.mobile.unflag'
+ defaultMessage='Unflag'
+ />
+ </a>
+ </li>
+ );
+ } else {
+ dropdownContents.push(
+ <li
+ key='mobileFlag'
+ role='presentation'
+ >
+ <a
+ href='#'
+ onClick={this.flagPost}
+ >
+ <FormattedMessage
+ id='rhs_root.mobile.flag'
+ defaultMessage='Flag'
+ />
+ </a>
+ </li>
+ );
+ }
+ }
+
dropdownContents.push(
<li
key='copyLink'
@@ -186,12 +233,23 @@ export default class PostInfo extends React.Component {
);
}
+ flagPost(e) {
+ e.preventDefault();
+ PostActions.flagPost(this.props.post.id);
+ }
+
+ unflagPost(e) {
+ e.preventDefault();
+ PostActions.unflagPost(this.props.post.id);
+ }
+
render() {
var post = this.props.post;
var comments = '';
var showCommentClass = '';
var highlightMentionClass = '';
var commentCountText = this.props.commentCount;
+ const flagIcon = Constants.FLAG_ICON_SVG;
if (this.props.commentCount >= 1) {
showCommentClass = ' icon--show';
@@ -240,6 +298,44 @@ export default class PostInfo extends React.Component {
);
}
+ let flag;
+ let flagFunc;
+ let flagVisible = '';
+ let flagTooltip = (
+ <Tooltip id='flagTooltip'>
+ <FormattedMessage
+ id='flag_post.flag'
+ defaultMessage='Flag for follow up'
+ />
+ </Tooltip>
+ );
+ if (this.props.isFlagged) {
+ flagVisible = 'visible';
+ flag = (
+ <span
+ className='icon'
+ dangerouslySetInnerHTML={{__html: flagIcon}}
+ />
+ );
+ flagFunc = this.unflagPost;
+ flagTooltip = (
+ <Tooltip id='flagTooltip'>
+ <FormattedMessage
+ id='flag_post.unflag'
+ defaultMessage='Unflag'
+ />
+ </Tooltip>
+ );
+ } else {
+ flag = (
+ <span
+ className='icon'
+ dangerouslySetInnerHTML={{__html: flagIcon}}
+ />
+ );
+ flagFunc = this.flagPost;
+ }
+
return (
<ul className='post__header--info'>
<li className='col'>
@@ -249,6 +345,20 @@ export default class PostInfo extends React.Component {
compactDisplay={this.props.compactDisplay}
useMilitaryTime={this.props.useMilitaryTime}
/>
+ <OverlayTrigger
+ key={'flagtooltipkey' + flagVisible}
+ delayShow={Constants.OVERLAY_TIME_DELAY}
+ placement='top'
+ overlay={flagTooltip}
+ >
+ <a
+ href='#'
+ className={'flag-icon__container ' + flagVisible}
+ onClick={flagFunc}
+ >
+ {flag}
+ </a>
+ </OverlayTrigger>
</li>
{options}
</ul>
@@ -274,5 +384,6 @@ PostInfo.propTypes = {
sameUser: React.PropTypes.bool.isRequired,
currentUser: React.PropTypes.object.isRequired,
compactDisplay: React.PropTypes.bool,
- useMilitaryTime: React.PropTypes.bool.isRequired
+ useMilitaryTime: React.PropTypes.bool.isRequired,
+ isFlagged: React.PropTypes.bool
};
diff --git a/webapp/components/post_view/components/post_list.jsx b/webapp/components/post_view/components/post_list.jsx
index befd1a10d..95b30a9d7 100644
--- a/webapp/components/post_view/components/post_list.jsx
+++ b/webapp/components/post_view/components/post_list.jsx
@@ -284,6 +284,11 @@ export default class PostList extends React.Component {
}
}
+ let isFlagged = false;
+ if (this.props.flaggedPosts) {
+ isFlagged = this.props.flaggedPosts.get(post.id) === 'true';
+ }
+
const postCtl = (
<Post
key={keyPrefix + 'postKey'}
@@ -305,6 +310,7 @@ export default class PostList extends React.Component {
previewCollapsed={this.props.previewsCollapsed}
useMilitaryTime={this.props.useMilitaryTime}
emojis={this.props.emojis}
+ isFlagged={isFlagged}
/>
);
@@ -572,5 +578,6 @@ PostList.propTypes = {
previewsCollapsed: React.PropTypes.string,
useMilitaryTime: React.PropTypes.bool.isRequired,
isFocusPost: React.PropTypes.bool,
- emojis: React.PropTypes.object.isRequired
+ emojis: React.PropTypes.object.isRequired,
+ flaggedPosts: React.PropTypes.object
};
diff --git a/webapp/components/post_view/post_focus_view_controller.jsx b/webapp/components/post_view/post_focus_view_controller.jsx
index f8738e056..4a7d312f5 100644
--- a/webapp/components/post_view/post_focus_view_controller.jsx
+++ b/webapp/components/post_view/post_focus_view_controller.jsx
@@ -8,6 +8,7 @@ import EmojiStore from 'stores/emoji_store.jsx';
import PostStore from 'stores/post_store.jsx';
import UserStore from 'stores/user_store.jsx';
import ChannelStore from 'stores/channel_store.jsx';
+import PreferenceStore from 'stores/preference_store.jsx';
import Constants from 'utils/constants.jsx';
const ScrollTypes = Constants.ScrollTypes;
@@ -22,6 +23,7 @@ export default class PostFocusView extends React.Component {
this.onPostsChange = this.onPostsChange.bind(this);
this.onUserChange = this.onUserChange.bind(this);
this.onEmojiChange = this.onEmojiChange.bind(this);
+ this.onPreferenceChange = this.onPreferenceChange.bind(this);
this.onPostListScroll = this.onPostListScroll.bind(this);
const focusedPostId = PostStore.getFocusedPostId();
@@ -41,7 +43,8 @@ export default class PostFocusView extends React.Component {
scrollPostId: focusedPostId,
atTop: PostStore.getVisibilityAtTop(focusedPostId),
atBottom: PostStore.getVisibilityAtBottom(focusedPostId),
- emojis: EmojiStore.getEmojis()
+ emojis: EmojiStore.getEmojis(),
+ flaggedPosts: PreferenceStore.getCategory(Constants.Preferences.CATEGORY_FLAGGED_POST)
};
}
@@ -50,6 +53,7 @@ export default class PostFocusView extends React.Component {
PostStore.addChangeListener(this.onPostsChange);
UserStore.addChangeListener(this.onUserChange);
EmojiStore.addChangeListener(this.onEmojiChange);
+ PreferenceStore.addChangeListener(this.onPreferenceChange);
}
componentWillUnmount() {
@@ -98,6 +102,12 @@ export default class PostFocusView extends React.Component {
});
}
+ onPreferenceChange() {
+ this.setState({
+ flaggedPosts: PreferenceStore.getCategory(Constants.Preferences.CATEGORY_FLAGGED_POST)
+ });
+ }
+
onPostListScroll() {
this.setState({scrollType: ScrollTypes.FREE});
}
@@ -128,6 +138,7 @@ export default class PostFocusView extends React.Component {
postsToHighlight={postsToHighlight}
isFocusPost={true}
emojis={this.state.emojis}
+ flaggedPosts={this.state.flaggedPosts}
/>
);
}
diff --git a/webapp/components/post_view/post_view_controller.jsx b/webapp/components/post_view/post_view_controller.jsx
index a7583fa38..1dd5e9176 100644
--- a/webapp/components/post_view/post_view_controller.jsx
+++ b/webapp/components/post_view/post_view_controller.jsx
@@ -58,7 +58,8 @@ export default class PostViewController extends React.Component {
compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT,
previewsCollapsed: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, 'false'),
useMilitaryTime: PreferenceStore.getBool(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.USE_MILITARY_TIME, false),
- emojis: EmojiStore.getEmojis()
+ emojis: EmojiStore.getEmojis(),
+ flaggedPosts: PreferenceStore.getCategory(Constants.Preferences.CATEGORY_FLAGGED_POST)
};
}
@@ -87,7 +88,8 @@ export default class PostViewController extends React.Component {
displayPostsInCenter: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_CENTERED,
compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT,
previewsCollapsed: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.COLLAPSE_DISPLAY, 'false') + previewSuffix,
- useMilitaryTime: PreferenceStore.getBool(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.USE_MILITARY_TIME, false)
+ useMilitaryTime: PreferenceStore.getBool(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.USE_MILITARY_TIME, false),
+ flaggedPosts: PreferenceStore.getCategory(Constants.Preferences.CATEGORY_FLAGGED_POST)
});
}
@@ -224,6 +226,10 @@ export default class PostViewController extends React.Component {
return true;
}
+ if (!Utils.areObjectsEqual(nextState.flaggedPosts, this.state.flaggedPosts)) {
+ return true;
+ }
+
if (nextState.lastViewed !== this.state.lastViewed) {
return true;
}
@@ -292,6 +298,7 @@ export default class PostViewController extends React.Component {
compactDisplay={this.state.compactDisplay}
previewsCollapsed={this.state.previewsCollapsed}
useMilitaryTime={this.state.useMilitaryTime}
+ flaggedPosts={this.state.flaggedPosts}
lastViewed={this.state.lastViewed}
emojis={this.state.emojis}
ownNewMessage={this.state.ownNewMessage}