Implement pagination

This commit is contained in:
Chi Vinh Le
2017-07-20 01:19:45 +07:00
parent 7005175fc0
commit b769e95898
8 changed files with 142 additions and 21 deletions
@@ -0,0 +1 @@
export {addNotification} from 'coral-framework/actions/notification';
+1 -1
View File
@@ -1,3 +1,3 @@
export {t} from 'coral-framework/services/i18n';
export {t, timeago} from 'coral-framework/services/i18n';
export {can} from 'coral-framework/services/perms';
export {isSlotEmpty} from 'coral-framework/helpers/plugins';
+6 -2
View File
@@ -1,2 +1,6 @@
export {isTagged, insertCommentsSorted} from 'coral-framework/utils';
export {getSlotFragmentSpreads} from 'coral-framework/utils';
export {
isTagged,
insertCommentsSorted,
getSlotFragmentSpreads,
forEachError,
} from 'coral-framework/utils';
@@ -2,7 +2,7 @@ import React from 'react';
import cn from 'classnames';
import styles from './Comment.css';
import {name} from '../../package.json';
import {timeago} from 'coral-framework/services/i18n';
import {timeago} from 'plugin-api/beta/client/services';
import {Slot} from 'plugin-api/beta/client/components';
import {Icon} from 'plugin-api/beta/client/components/ui';
@@ -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;
@@ -1,9 +1,9 @@
import React from 'react';
import {TabCount} from 'plugin-api/beta/client/components/ui';
import {t} from 'plugin-api/beta/client/services';
// TODO: This is just example code, and needs to replaced by an actual implementation.
export default ({active, asset: {featuredCommentsCount}}) => (
<span>
Featured <TabCount active={active} sub>{featuredCommentsCount}</TabCount>
{t('featured')} <TabCount active={active} sub>{featuredCommentsCount}</TabCount>
</span>
);
@@ -1,16 +1,47 @@
import React from 'react';
import Comment from '../containers/Comment';
import LoadMore from './LoadMore';
import {forEachError} from 'plugin-api/beta/client/utils';
export default ({root, data, asset: {featuredComments, ...asset}, viewComment}) => (
<div>
{featuredComments.nodes.map((comment) =>
<Comment
key={comment.id}
root={root}
data={data}
comment={comment}
asset={asset}
viewComment={viewComment} />
)}
</div>
);
class TabPane 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 {root, data, asset: {featuredComments, ...asset}, viewComment} = this.props;
return (
<div>
{featuredComments.nodes.map((comment) =>
<Comment
key={comment.id}
root={root}
data={data}
comment={comment}
asset={asset}
viewComment={viewComment} />
)}
{featuredComments.hasNextPage &&
<LoadMore
loadMore={this.loadMore}
loadingState={this.loadingState}
/>
}
</div>
);
}
}
export default TabPane;
@@ -1,3 +1,4 @@
import React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {compose, gql} from 'react-apollo';
@@ -5,12 +6,66 @@ import TabPane from '../components/TabPane';
import {withFragments} from 'plugin-api/beta/client/hocs';
import Comment from '../containers/Comment';
import {getDefinitionName} from 'coral-framework/utils';
import {addNotification} from 'plugin-api/beta/client/actions/notification';
import {viewComment} from 'coral-embed-stream/src/actions/stream';
import {insertCommentsSorted} from 'plugin-api/beta/client/utils';
import update from 'immutability-helper';
class TabPaneContainer extends React.Component {
loadMore = () => {
return this.props.data.fetchMore({
query: LOAD_MORE_QUERY,
variables: {
limit: 5,
cursor: this.props.root.asset.featuredComments.endCursor,
asset_id: this.props.root.asset.id,
sort: 'REVERSE_CHRONOLOGICAL',
excludeIgnored: this.props.data.variables.excludeIgnored,
},
updateQuery: (previous, {fetchMoreResult:{comments}}) => {
const updated = update(previous, {
asset: {
featuredComments: {
nodes: {
$apply: (nodes) => insertCommentsSorted(nodes, comments.nodes, 'REVERSE_CHRONOLOGICAL'),
},
hasNextPage: {$set: comments.hasNextPage},
endCursor: {$set: comments.endCursor},
},
}
});
return updated;
},
});
};
render() {
return <TabPane
{...this.props}
loadMore={this.loadMore}
/>;
}
}
const LOAD_MORE_QUERY = gql`
query CoralEmbedStream_LoadMoreComments($limit: Int = 5, $cursor: Date, $asset_id: ID, $sort: SORT_ORDER, $excludeIgnored: Boolean) {
comments(query: {limit: $limit, cursor: $cursor, tags: ["FEATURED"], asset_id: $asset_id, sort: $sort, excludeIgnored: $excludeIgnored}) {
nodes {
...${getDefinitionName(Comment.fragments.comment)}
}
hasNextPage
startCursor
endCursor
}
}
${Comment.fragments.comment}
`;
const mapDispatchToProps = (dispatch) =>
bindActionCreators({
viewComment,
addNotification,
}, dispatch);
const enhance = compose(
@@ -42,4 +97,4 @@ const enhance = compose(
}),
);
export default enhance(TabPane);
export default enhance(TabPaneContainer);