PLT-6215 Major post list refactor (#6501)
* Major post list refactor * Fix post and thread deletion * Fix preferences not selecting correctly * Fix military time displaying * Fix UP key for editing posts * Fix ESLint error * Various fixes and updates per feedback * Fix for permalink view * Revert to old scrolling method and various fixes * Add floating timestamp, new message indicator, scroll arrows * Update post loading for focus mode and add visibility limit * Fix pinning posts and a react warning * Add loading UI updates from Asaad * Fix refreshing loop * Temporarily bump post visibility limit * Update infinite scrolling * Remove infinite scrolling
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
0231e95f1c
Коммит
ab67f6e257
31
webapp/components/post_view/post_info/index.js
Обычный файл
31
webapp/components/post_view/post_info/index.js
Обычный файл
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {removePost, addReaction} from 'mattermost-redux/actions/posts';
|
||||
|
||||
import {getBool} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import {Preferences} from 'utils/constants.jsx';
|
||||
|
||||
import PostInfo from './post_info.jsx';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
...ownProps,
|
||||
useMilitaryTime: getBool(state, Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.USE_MILITARY_TIME, false),
|
||||
isFlagged: getBool(state, Preferences.CATEGORY_FLAGGED_POST, ownProps.post.id)
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
removePost,
|
||||
addReaction
|
||||
}, dispatch)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(PostInfo);
|
||||
243
webapp/components/post_view/post_info/post_info.jsx
Обычный файл
243
webapp/components/post_view/post_info/post_info.jsx
Обычный файл
@@ -0,0 +1,243 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import PostTime from 'components/post_view/post_time.jsx';
|
||||
import PostFlagIcon from 'components/post_view/post_flag_icon.jsx';
|
||||
import CommentIcon from 'components/common/comment_icon.jsx';
|
||||
import EmojiPickerOverlay from 'components/emoji_picker/emoji_picker_overlay.jsx';
|
||||
import DotMenu from 'components/dot_menu';
|
||||
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
import * as PostUtils from 'utils/post_utils.jsx';
|
||||
import Constants from 'utils/constants.jsx';
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
|
||||
export default class PostInfo extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
||||
/*
|
||||
* The post to render the info for
|
||||
*/
|
||||
post: PropTypes.object.isRequired,
|
||||
|
||||
/*
|
||||
* Function called when the comment icon is clicked
|
||||
*/
|
||||
handleCommentClick: PropTypes.func.isRequired,
|
||||
|
||||
/*
|
||||
* Funciton called when the post options dropdown is opened
|
||||
*/
|
||||
handleDropdownOpened: PropTypes.func.isRequired,
|
||||
|
||||
/*
|
||||
* Set to display in 24 hour format
|
||||
*/
|
||||
useMilitaryTime: PropTypes.bool.isRequired,
|
||||
|
||||
/*
|
||||
* Set to mark the post as flagged
|
||||
*/
|
||||
isFlagged: PropTypes.bool,
|
||||
|
||||
/*
|
||||
* The number of replies in the same thread as this post
|
||||
*/
|
||||
replyCount: PropTypes.number,
|
||||
|
||||
/*
|
||||
* Post identifiers for selenium tests
|
||||
*/
|
||||
lastPostCount: PropTypes.number,
|
||||
|
||||
/**
|
||||
* Function to get the post list HTML element
|
||||
*/
|
||||
getPostList: PropTypes.func.isRequired,
|
||||
|
||||
actions: PropTypes.shape({
|
||||
|
||||
/*
|
||||
* Function to remove the post
|
||||
*/
|
||||
removePost: PropTypes.func.isRequired,
|
||||
|
||||
/*
|
||||
* Function to add a reaction to the post
|
||||
*/
|
||||
addReaction: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.removePost = this.removePost.bind(this);
|
||||
this.reactEmojiClick = this.reactEmojiClick.bind(this);
|
||||
|
||||
this.state = {
|
||||
showEmojiPicker: false,
|
||||
reactionPickerOffset: 21,
|
||||
canEdit: PostUtils.canEditPost(props.post, this.editDisableAction)
|
||||
};
|
||||
}
|
||||
|
||||
toggleEmojiPicker = () => {
|
||||
const showEmojiPicker = !this.state.showEmojiPicker;
|
||||
|
||||
this.setState({showEmojiPicker});
|
||||
this.props.handleDropdownOpened(showEmojiPicker);
|
||||
}
|
||||
|
||||
hideEmojiPicker = () => {
|
||||
this.setState({showEmojiPicker: false});
|
||||
this.props.handleDropdownOpened(false);
|
||||
}
|
||||
|
||||
removePost() {
|
||||
this.props.actions.removePost(this.props.post);
|
||||
}
|
||||
|
||||
createRemovePostButton() {
|
||||
return (
|
||||
<a
|
||||
href='#'
|
||||
className='post__remove theme'
|
||||
type='button'
|
||||
onClick={this.removePost}
|
||||
>
|
||||
{'×'}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
reactEmojiClick(emoji) {
|
||||
const pickerOffset = 21;
|
||||
this.setState({showEmojiPicker: false, reactionPickerOffset: pickerOffset});
|
||||
const emojiName = emoji.name || emoji.aliases[0];
|
||||
this.props.actions.addReaction(this.props.post.id, emojiName);
|
||||
}
|
||||
|
||||
getDotMenu = () => {
|
||||
return this.refs.dotMenu;
|
||||
}
|
||||
|
||||
render() {
|
||||
const post = this.props.post;
|
||||
|
||||
let idCount = -1;
|
||||
if (this.props.lastPostCount >= 0 && this.props.lastPostCount < Constants.TEST_ID_COUNT) {
|
||||
idCount = this.props.lastPostCount;
|
||||
}
|
||||
|
||||
const isEphemeral = Utils.isPostEphemeral(post);
|
||||
const isSystemMessage = PostUtils.isSystemMessage(post);
|
||||
|
||||
let comments = null;
|
||||
let react = null;
|
||||
if (!isEphemeral && !post.failed && !isSystemMessage) {
|
||||
comments = (
|
||||
<CommentIcon
|
||||
idPrefix='commentIcon'
|
||||
idCount={idCount}
|
||||
handleCommentClick={this.props.handleCommentClick}
|
||||
commentCount={this.props.replyCount}
|
||||
id={post.channel_id + '_' + post.id}
|
||||
/>
|
||||
);
|
||||
|
||||
if (Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMOJI_PICKER_PREVIEW)) {
|
||||
react = (
|
||||
<span>
|
||||
<EmojiPickerOverlay
|
||||
show={this.state.showEmojiPicker}
|
||||
container={this.props.getPostList}
|
||||
target={this.getDotMenu}
|
||||
onHide={this.hideEmojiPicker}
|
||||
onEmojiClick={this.reactEmojiClick}
|
||||
/>
|
||||
<a
|
||||
href='#'
|
||||
className='reacticon__container'
|
||||
onClick={this.toggleEmojiPicker}
|
||||
>
|
||||
<i className='fa fa-smile-o'/>
|
||||
</a>
|
||||
</span>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let options;
|
||||
if (isEphemeral) {
|
||||
options = (
|
||||
<div className='col col__remove'>
|
||||
{this.createRemovePostButton()}
|
||||
</div>
|
||||
);
|
||||
} else if (!post.failed) {
|
||||
const dotMenu = (
|
||||
<DotMenu
|
||||
idPrefix={Constants.CENTER}
|
||||
idCount={idCount}
|
||||
post={this.props.post}
|
||||
commentCount={this.props.replyCount}
|
||||
isFlagged={this.props.isFlagged}
|
||||
handleCommentClick={this.props.handleCommentClick}
|
||||
handleDropdownOpened={this.props.handleDropdownOpened}
|
||||
/>
|
||||
);
|
||||
|
||||
if (dotMenu) {
|
||||
options = (
|
||||
<div
|
||||
ref='dotMenu'
|
||||
className='col col__reply'
|
||||
>
|
||||
{dotMenu}
|
||||
{react}
|
||||
{comments}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let pinnedBadge;
|
||||
if (post.is_pinned) {
|
||||
pinnedBadge = (
|
||||
<span className='post__pinned-badge'>
|
||||
<FormattedMessage
|
||||
id='post_info.pinned'
|
||||
defaultMessage='Pinned'
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='post__header--info'>
|
||||
<div className='col'>
|
||||
<PostTime
|
||||
eventTime={post.create_at}
|
||||
useMilitaryTime={this.props.useMilitaryTime}
|
||||
postId={post.id}
|
||||
/>
|
||||
{pinnedBadge}
|
||||
{this.state.showEmojiPicker}
|
||||
<PostFlagIcon
|
||||
idPrefix={'centerPostFlag'}
|
||||
idCount={idCount}
|
||||
postId={post.id}
|
||||
isFlagged={this.props.isFlagged}
|
||||
isEphemeral={isEphemeral}
|
||||
/>
|
||||
</div>
|
||||
{options}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user