diff options
author | Joram Wilander <jwawilander@gmail.com> | 2016-08-04 11:38:09 -0400 |
---|---|---|
committer | enahum <nahumhbl@gmail.com> | 2016-08-04 10:38:09 -0500 |
commit | 0184d6059bb1943fb74bf33d1d200a423c5bf5e6 (patch) | |
tree | 4b8480d65d5ec181b372a09f946bb7649809a467 /webapp/components/post_view | |
parent | 9b50b5028391ee29922ad5549b785ac2312be368 (diff) | |
download | chat-0184d6059bb1943fb74bf33d1d200a423c5bf5e6.tar.gz chat-0184d6059bb1943fb74bf33d1d200a423c5bf5e6.tar.bz2 chat-0184d6059bb1943fb74bf33d1d200a423c5bf5e6.zip |
PLT-3506 Added flagged posts functionality (#3679)
* Added flagged posts functionality
* UI Improvements to flags (#3697)
* Added flag functionality for mobile
* Updating flagged text (#3699)
* Add back button to RHS thread when coming from flagged posts
* Updating position of flags (#3708)
* Plt 3506 - Reverting flag position (#3724)
* Revert "Updating position of flags (#3708)"
This reverts commit aaa05632c5d9eda35a048300a5bd7e99584c5b58.
* Fixing the icon in search
* Help text and white space improvements (#3730)
* Updatng help text and some white spacing.
* Updating help text
Diffstat (limited to 'webapp/components/post_view')
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} |