Merge pull request #842 from coralproject/paginate-my-comments

Paginate my comments in profile tab
This commit is contained in:
Kim Gardner
2017-08-09 10:51:31 +01:00
committed by GitHub
5 changed files with 138 additions and 49 deletions
@@ -1,7 +1,8 @@
import {connect} from 'react-redux';
import {compose, graphql, gql} from 'react-apollo';
import {compose, gql} from 'react-apollo';
import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {withQuery} from 'coral-framework/hocs';
import {withStopIgnoringUser} from 'coral-framework/graphql/mutations';
@@ -11,18 +12,12 @@ import IgnoredUsers from '../components/IgnoredUsers';
import {Spinner} from 'coral-ui';
import CommentHistory from 'talk-plugin-history/CommentHistory';
import {showSignInDialog, checkLogin} from 'coral-framework/actions/auth';
import {insertCommentsSorted} from 'plugin-api/beta/client/utils';
import update from 'immutability-helper';
import t from 'coral-framework/services/i18n';
class ProfileContainer extends Component {
constructor() {
super();
this.state = {
activeTab: 0
};
}
componentWillReceiveProps(nextProps) {
if (!this.props.auth.loggedIn && nextProps.auth.loggedIn) {
@@ -31,21 +26,40 @@ class ProfileContainer extends Component {
}
}
handleTabChange = (tab) => {
this.setState({
activeTab: tab
loadMore = () => {
return this.props.data.fetchMore({
query: LOAD_MORE_QUERY,
variables: {
limit: 5,
cursor: this.props.root.me.comments.endCursor,
},
updateQuery: (previous, {fetchMoreResult:{comments}}) => {
const updated = update(previous, {
me: {
comments: {
nodes: {
$apply: (nodes) => insertCommentsSorted(nodes, comments.nodes, 'REVERSE_CHRONOLOGICAL'),
},
hasNextPage: {$set: comments.hasNextPage},
endCursor: {$set: comments.endCursor},
},
}
});
return updated;
},
});
};
render() {
const {auth, asset, data, showSignInDialog, stopIgnoringUser} = this.props;
const {me} = this.props.data;
const {auth, asset, showSignInDialog, stopIgnoringUser} = this.props;
const {me} = this.props.root;
const loading = [1, 2, 4].indexOf(this.props.data.networkStatus) >= 0;
if (!auth.loggedIn) {
return <NotLoggedIn showSignInDialog={showSignInDialog} />;
}
if (!me || data.loading) {
if (loading) {
return <Spinner />;
}
@@ -73,14 +87,40 @@ class ProfileContainer extends Component {
<h3>{t('framework.my_comments')}</h3>
{me.comments.nodes.length
? <CommentHistory comments={me.comments.nodes} asset={asset} link={link} />
? <CommentHistory comments={me.comments} asset={asset} link={link} loadMore={this.loadMore}/>
: <p>{t('user_no_comment')}</p>}
</div>
);
}
}
const withQuery = graphql(
const CommentFragment = gql`
fragment TalkSettings_CommentConnectionFragment on CommentConnection {
nodes {
id
body
asset {
id
title
url
}
created_at
}
endCursor
hasNextPage
}
`;
const LOAD_MORE_QUERY = gql`
query TalkSettings_LoadMoreComments($limit: Int, $cursor: Date) {
comments(query: {limit: $limit, cursor: $cursor}) {
...TalkSettings_CommentConnectionFragment
}
}
${CommentFragment}
`;
const withProfileQuery = withQuery(
gql`
query CoralEmbedStream_Profile {
me {
@@ -89,21 +129,13 @@ const withQuery = graphql(
id,
username,
}
comments {
nodes {
id
body
asset {
id
title
url
}
created_at
}
comments(query: {limit: 10}) {
...TalkSettings_CommentConnectionFragment
}
}
}`
);
}
${CommentFragment}
`);
const mapStateToProps = (state) => ({
user: state.user.toJS(),
@@ -117,5 +149,5 @@ const mapDispatchToProps = (dispatch) =>
export default compose(
connect(mapStateToProps, mapDispatchToProps),
withStopIgnoringUser,
withQuery
withProfileQuery
)(ProfileContainer);
+42 -15
View File
@@ -1,25 +1,52 @@
import React, {PropTypes} from 'react';
import Comment from './Comment';
import styles from './CommentHistory.css';
import LoadMore from './LoadMore';
import {forEachError} from 'plugin-api/beta/client/utils';
const CommentHistory = (props) => {
return (
<div className={`${styles.header} commentHistory`}>
<div className="commentHistory__list">
{props.comments.map((comment, i) => {
return <Comment
key={i}
comment={comment}
link={props.link}
asset={comment.asset} />;
})}
class CommentHistory extends React.Component {
state = {
loadingState: '',
};
loadMore = () => {
this.setState({loadingState: 'loading'});
this.props.loadMore()
.then(() => {
this.setState({loadingState: 'success'});
})
.catch((error) => {
this.setState({loadingState: 'error'});
forEachError(error, ({msg}) => {this.props.addNotification('error', msg);});
});
}
render() {
const {link, comments} = this.props;
return (
<div className={`${styles.header} commentHistory`}>
<div className="commentHistory__list">
{comments.nodes.map((comment, i) => {
return <Comment
key={i}
comment={comment}
link={link}
asset={comment.asset} />;
})}
</div>
{comments.hasNextPage &&
<LoadMore
loadMore={this.loadMore}
loadingState={this.state.loadingState}
/>
}
</div>
</div>
);
};
);
}
}
CommentHistory.propTypes = {
comments: PropTypes.array.isRequired
comments: PropTypes.object.isRequired
};
export default CommentHistory;
+30
View File
@@ -0,0 +1,30 @@
import React from 'react';
import PropTypes from 'prop-types';
import {Button} from 'coral-ui';
import t from 'coral-framework/services/i18n';
import cn from 'classnames';
class LoadMore extends React.Component {
render () {
const {loadingState, loadMore} = this.props;
const disabled = loadingState === 'loading';
return (
<div className='talk-load-more'>
<Button
onClick={loadMore}
className={cn('talk-load-more-button', {[`talk-load-more-button-${loadingState}`]: loadingState})}
disabled={disabled}
>
{t('framework.view_more_comments')}
</Button>
</div>
);
}
}
LoadMore.propTypes = {
loadMore: PropTypes.func.isRequired,
loadingState: PropTypes.oneOf(['', 'loading', 'success', 'error']),
};
export default LoadMore;
+2 -2
View File
@@ -29,12 +29,12 @@ const User = {
return null;
},
comments({id}, _, {loaders: {Comments}, user}) {
comments({id}, {query}, {loaders: {Comments}, user}) {
// If the user is not an admin, only return comment list for the owner of
// the comments.
if (user && (user.can(SEARCH_OTHERS_COMMENTS) || user.id === id)) {
return Comments.getByQuery({author_id: id, sort: 'REVERSE_CHRONOLOGICAL'});
return Comments.getByQuery(Object.assign({}, query, {author_id: id}));
}
return null;
@@ -36,7 +36,7 @@ class TabPane extends React.Component {
{featuredComments.hasNextPage &&
<LoadMore
loadMore={this.loadMore}
loadingState={this.loadingState}
loadingState={this.state.loadingState}
/>
}
</div>