From 976bd1e9add953de3599a1dc0afab5adf7336761 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Tue, 8 Aug 2017 22:39:24 +0700 Subject: [PATCH] Paginate my comments in profile tab --- .../containers/ProfileContainer.js | 94 +++++++++++++------ client/talk-plugin-history/CommentHistory.js | 57 ++++++++--- client/talk-plugin-history/LoadMore.js | 30 ++++++ graph/resolvers/user.js | 4 +- .../client/components/TabPane.js | 2 +- 5 files changed, 138 insertions(+), 49 deletions(-) create mode 100644 client/talk-plugin-history/LoadMore.js diff --git a/client/coral-settings/containers/ProfileContainer.js b/client/coral-settings/containers/ProfileContainer.js index 91de923b2..0090847f7 100644 --- a/client/coral-settings/containers/ProfileContainer.js +++ b/client/coral-settings/containers/ProfileContainer.js @@ -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 ; } - if (!me || data.loading) { + if (loading) { return ; } @@ -73,14 +87,40 @@ class ProfileContainer extends Component {

{t('framework.my_comments')}

{me.comments.nodes.length - ? + ? :

{t('user_no_comment')}

} ); } } -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); diff --git a/client/talk-plugin-history/CommentHistory.js b/client/talk-plugin-history/CommentHistory.js index 72c4de982..d584d6a0a 100644 --- a/client/talk-plugin-history/CommentHistory.js +++ b/client/talk-plugin-history/CommentHistory.js @@ -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 ( -
-
- {props.comments.map((comment, i) => { - return ; - })} +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 ( +
+
+ {comments.nodes.map((comment, i) => { + return ; + })} +
+ {comments.hasNextPage && + + }
-
- ); -}; + ); + } +} CommentHistory.propTypes = { - comments: PropTypes.array.isRequired + comments: PropTypes.object.isRequired }; export default CommentHistory; diff --git a/client/talk-plugin-history/LoadMore.js b/client/talk-plugin-history/LoadMore.js new file mode 100644 index 000000000..a168ed43a --- /dev/null +++ b/client/talk-plugin-history/LoadMore.js @@ -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 ( +
+ +
+ ); + } +} + +LoadMore.propTypes = { + loadMore: PropTypes.func.isRequired, + loadingState: PropTypes.oneOf(['', 'loading', 'success', 'error']), +}; + +export default LoadMore; diff --git a/graph/resolvers/user.js b/graph/resolvers/user.js index 2878d6561..5a851233a 100644 --- a/graph/resolvers/user.js +++ b/graph/resolvers/user.js @@ -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; diff --git a/plugins/talk-plugin-featured-comments/client/components/TabPane.js b/plugins/talk-plugin-featured-comments/client/components/TabPane.js index 3cf8b2cfd..2f5d0c7c2 100644 --- a/plugins/talk-plugin-featured-comments/client/components/TabPane.js +++ b/plugins/talk-plugin-featured-comments/client/components/TabPane.js @@ -36,7 +36,7 @@ class TabPane extends React.Component { {featuredComments.hasNextPage && }