Skip to content

Commit

Permalink
RHS info cards support (mattermost#2305)
Browse files Browse the repository at this point in the history
* RHS info cards support

* Fixing check-style and tests

* Adding rhs.js tests

* Adding tests to rhs_card component

* Two extra fixes

* Fixing translation error

* Added proposed changes from UX

* Showing the info icon in the rhs_root_post too

* Improved the rhs card visualization

* Making the post 'show more' max height configurable

* Adding the info icon in search results

* Adding more consistent behavior with other RHS sections

* Fixing tests

* Updating info icon

* Changing how the post/author is show in the RHS

* Updating css for Rhs info card

* Adding tooltip and using the right icon in all the places

* Adding translation strings

* Removing maxHeight variable, not longer necessary

* Fixing tests

* Updating info icon on compact view

* Adding proposed changes

* Fixing tests

* Updating info icon in RHS compact view

* Fixing long name in the footers

* Fixing tests
  • Loading branch information
jespino committed Jun 14, 2019
1 parent 255819e commit 27c8ab4
Show file tree
Hide file tree
Showing 43 changed files with 1,408 additions and 50 deletions.
10 changes: 9 additions & 1 deletion actions/post_actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import * as StorageActions from 'actions/storage';
import {loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions.jsx';
import * as RhsActions from 'actions/views/rhs';
import {isEmbedVisible} from 'selectors/posts';
import {getSelectedPostId, getRhsState} from 'selectors/rhs';
import {getSelectedPostId, getSelectedPostCardId, getRhsState} from 'selectors/rhs';
import {
ActionTypes,
Constants,
Expand Down Expand Up @@ -246,6 +246,14 @@ export function deleteAndRemovePost(post) {
});
}

if (post.id === getSelectedPostCardId(getState())) {
dispatch({
type: ActionTypes.SELECT_POST_CARD,
postId: '',
channelId: '',
});
}

dispatch(PostActions.removePost(post));

return {data: true};
Expand Down
15 changes: 15 additions & 0 deletions actions/views/rhs.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ export function selectPostFromRightHandSideSearch(post) {
};
}

export function selectPostCardFromRightHandSideSearch(post) {
return async (dispatch, getState) => {
dispatch({
type: ActionTypes.SELECT_POST_CARD,
postId: post.id,
channelId: post.channel_id,
previousRhsState: getRhsState(getState()),
});
};
}

export function selectPostFromRightHandSideSearchByPostId(postId) {
return async (dispatch, getState) => {
const post = getPost(getState(), postId);
Expand Down Expand Up @@ -231,3 +242,7 @@ export function toggleRhsExpanded() {
export function selectPost(post) {
return {type: ActionTypes.SELECT_POST, postId: post.root_id || post.id, channelId: post.channel_id};
}

export function selectPostCard(post) {
return {type: ActionTypes.SELECT_POST_CARD, postId: post.id, channelId: post.channel_id};
}
8 changes: 4 additions & 4 deletions components/__snapshots__/profile_picture.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ exports[`components/ProfilePicture should match snapshot, no user specified, def
>
<img
alt=""
className="more-modal__image"
className="more-modal__image rounded"
height="36"
src="http:https://example.com/image.png"
width="36"
Expand All @@ -24,7 +24,7 @@ exports[`components/ProfilePicture should match snapshot, no user specified, ove
>
<img
alt=""
className="more-modal__image"
className="more-modal__image rounded"
height="48"
src="http:https://example.com/image.png"
width="48"
Expand All @@ -42,7 +42,7 @@ exports[`components/ProfilePicture should match snapshot, user specified 1`] = `
>
<img
alt=""
className="more-modal__image"
className="more-modal__image rounded"
height="36"
src="http:https://example.com/image.png"
width="36"
Expand All @@ -60,7 +60,7 @@ exports[`components/ProfilePicture should match snapshot, user specified, overri
>
<img
alt=""
className="more-modal__image"
className="more-modal__image rounded"
height="48"
src="http:https://example.com/image.png"
width="48"
Expand Down
3 changes: 2 additions & 1 deletion components/post_view/post/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {get} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
import {isPostEphemeral, isSystemMessage} from 'mattermost-redux/utils/post_utils';

import {selectPost} from 'actions/views/rhs';
import {selectPost, selectPostCard} from 'actions/views/rhs';
import {Preferences} from 'utils/constants.jsx';

import Post from './post.jsx';
Expand Down Expand Up @@ -89,6 +89,7 @@ function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
selectPost,
selectPostCard,
}, dispatch),
};
}
Expand Down
10 changes: 10 additions & 0 deletions components/post_view/post/post.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export default class Post extends React.PureComponent {

actions: PropTypes.shape({
selectPost: PropTypes.func.isRequired,
selectPostCard: PropTypes.func.isRequired,
}).isRequired,
}

Expand Down Expand Up @@ -102,6 +103,14 @@ export default class Post extends React.PureComponent {
this.props.actions.selectPost(post);
}

handleCardClick = (post) => {
if (!post) {
return;
}

this.props.actions.selectPostCard(post);
}

handleDropdownOpened = (opened) => {
if (this.props.togglePostMenu) {
this.props.togglePostMenu(opened);
Expand Down Expand Up @@ -258,6 +267,7 @@ export default class Post extends React.PureComponent {
<PostHeader
post={post}
handleCommentClick={this.handleCommentClick}
handleCardClick={this.handleCardClick}
handleDropdownOpened={this.handleDropdownOpened}
compactDisplay={this.props.compactDisplay}
isFirstReply={this.props.isFirstReply}
Expand Down
6 changes: 6 additions & 0 deletions components/post_view/post_header/post_header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ export default class PostHeader extends React.PureComponent {
*/
handleCommentClick: PropTypes.func.isRequired,

/*
* Function called when the card icon is clicked
*/
handleCardClick: PropTypes.func.isRequired,

/*
* Function called when the post options dropdown is opened
*/
Expand Down Expand Up @@ -151,6 +156,7 @@ export default class PostHeader extends React.PureComponent {
<PostInfo
post={post}
handleCommentClick={this.props.handleCommentClick}
handleCardClick={this.props.handleCardClick}
handleDropdownOpened={this.props.handleDropdownOpened}
compactDisplay={this.props.compactDisplay}
replyCount={this.props.replyCount}
Expand Down
3 changes: 3 additions & 0 deletions components/post_view/post_info/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import {get} from 'mattermost-redux/selectors/entities/preferences';
import {getConfig} from 'mattermost-redux/selectors/entities/general';

import {Preferences} from 'utils/constants.jsx';
import {getSelectedPostCard} from 'selectors/rhs.jsx';

import PostInfo from './post_info.jsx';

function mapStateToProps(state, ownProps) {
const selectedCard = getSelectedPostCard(state);
const config = getConfig(state);
const channel = state.entities.channels.channels[ownProps.post.channel_id];
const channelIsArchived = channel ? channel.delete_at !== 0 : null;
Expand All @@ -24,6 +26,7 @@ function mapStateToProps(state, ownProps) {
teamId,
isFlagged: get(state, Preferences.CATEGORY_FLAGGED_POST, ownProps.post.id, null) != null,
isMobile: state.views.channel.mobileView,
isCardOpen: selectedCard && selectedCard.id === ownProps.post.id,
enableEmojiPicker,
isReadOnly: isCurrentChannelReadOnly(state) || channelIsArchived,
};
Expand Down
46 changes: 46 additions & 0 deletions components/post_view/post_info/post_info.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
import PropTypes from 'prop-types';
import React from 'react';
import {FormattedMessage} from 'react-intl';
import {OverlayTrigger, Tooltip} from 'react-bootstrap';

import {Posts} from 'mattermost-redux/constants';
import * as ReduxPostUtils from 'mattermost-redux/utils/post_utils';

import * as PostUtils from 'utils/post_utils.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
import CommentIcon from 'components/common/comment_icon.jsx';
import DotMenu from 'components/dot_menu';
import PostFlagIcon from 'components/post_view/post_flag_icon';
import PostReaction from 'components/post_view/post_reaction';
import PostTime from 'components/post_view/post_time';
import InfoSmallIcon from 'components/svg/info_small_icon';

export default class PostInfo extends React.PureComponent {
static propTypes = {
Expand All @@ -34,6 +37,11 @@ export default class PostInfo extends React.PureComponent {
*/
handleCommentClick: PropTypes.func.isRequired,

/*
* Function called when the card icon is clicked
*/
handleCardClick: PropTypes.func.isRequired,

/*
* Funciton called when the post options dropdown is opened
*/
Expand All @@ -44,6 +52,11 @@ export default class PostInfo extends React.PureComponent {
*/
isFlagged: PropTypes.bool,

/*
* Set to mark the post as open the extra info in the rhs
*/
isCardOpen: PropTypes.bool,

/*
* The number of replies in the same thread as this post
*/
Expand Down Expand Up @@ -219,6 +232,38 @@ export default class PostInfo extends React.PureComponent {
);
}

let postInfoIcon;
if (post.props && post.props.card) {
postInfoIcon = (
<OverlayTrigger
trigger={['hover', 'focus']}
delayShow={Constants.OVERLAY_TIME_DELAY}
placement='top'
overlay={
<Tooltip>
<FormattedMessage
id='post_info.info.view_additional_info'
defaultMessage='View additional info'
/>
</Tooltip>
}
>
<button
className={'card-icon__container icon--show style--none ' + (this.props.isCardOpen ? 'active' : '')}
onClick={(e) => {
e.preventDefault();
this.props.handleCardClick(this.props.post);
}}
>
<InfoSmallIcon
className='icon icon__info'
aria-hidden='true'
/>
</button>
</OverlayTrigger>
);
}

let options;
if (isEphemeral) {
options = (
Expand Down Expand Up @@ -274,6 +319,7 @@ export default class PostInfo extends React.PureComponent {
<div className='col'>
{postTime}
{pinnedBadge}
{postInfoIcon}
{postFlagIcon}
{visibleMessage}
</div>
Expand Down
1 change: 1 addition & 0 deletions components/post_view/post_info/post_info.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('components/post_view/PostInfo', () => {
const requiredProps = {
post,
handleCommentClick: jest.fn(),
handleCardClick: jest.fn(),
handleDropdownOpened: jest.fn(),
compactDisplay: false,
replyCount: 0,
Expand Down
6 changes: 3 additions & 3 deletions components/profile_picture.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default class ProfilePicture extends React.PureComponent {
>
<span className='status-wrapper'>
<img
className='more-modal__image'
className='more-modal__image rounded'
alt={`${this.props.username || 'user'} profile image`}
width={this.props.width}
height={this.props.width}
Expand All @@ -67,8 +67,8 @@ export default class ProfilePicture extends React.PureComponent {
return (
<span className='status-wrapper'>
<img
className='more-modal__image'
alt={''}
className='more-modal__image rounded'
alt=''
width={this.props.width}
height={this.props.width}
src={this.props.src}
Expand Down
Loading

0 comments on commit 27c8ab4

Please sign in to comment.