mirror of
https://github.com/wassname/talk.git
synced 2026-07-03 12:20:39 +08:00
Retrieving counts and displaying new comments to user.
This commit is contained in:
@@ -177,7 +177,7 @@ class Comment extends React.Component {
|
||||
comment.replies &&
|
||||
<div className='coral-load-more-replies'>
|
||||
<LoadMore
|
||||
id={asset.id}
|
||||
assetId={asset.id}
|
||||
comments={comment.replies}
|
||||
parentId={comment.id}
|
||||
moreComments={comment.replyCount > comment.replies.length}
|
||||
|
||||
@@ -12,6 +12,7 @@ const {fetchAssetSuccess} = assetActions;
|
||||
import {queryStream} from 'coral-framework/graphql/queries';
|
||||
import {postComment, postFlag, postLike, deleteAction} from 'coral-framework/graphql/mutations';
|
||||
import {editName} from 'coral-framework/actions/user';
|
||||
import {updateCountCache} from 'coral-framework/actions/asset';
|
||||
import {Notification, notificationActions, authActions, assetActions, pym} from 'coral-framework';
|
||||
|
||||
import Stream from './Stream';
|
||||
@@ -28,6 +29,7 @@ import SettingsContainer from 'coral-settings/containers/SettingsContainer';
|
||||
import RestrictedContent from 'coral-framework/components/RestrictedContent';
|
||||
import ConfigureStreamContainer from 'coral-configure/containers/ConfigureStreamContainer';
|
||||
import LoadMore from './LoadMore';
|
||||
import NewCount from './NewCount';
|
||||
|
||||
class Embed extends Component {
|
||||
|
||||
@@ -82,7 +84,7 @@ class Embed extends Component {
|
||||
|
||||
render () {
|
||||
const {activeTab} = this.state;
|
||||
const {closedAt} = this.props.asset;
|
||||
const {closedAt, countCache = {}} = this.props.asset;
|
||||
const {loading, asset, refetch} = this.props.data;
|
||||
const {loggedIn, isAdmin, user, showSignInDialog, signInOffset} = this.props.auth;
|
||||
|
||||
@@ -147,6 +149,7 @@ class Embed extends Component {
|
||||
}
|
||||
{!loggedIn && <SignInContainer requireEmailConfirmation={asset.settings.requireEmailConfirmation} offset={signInOffset}/>}
|
||||
{loggedIn && user && <ChangeUsernameContainer loggedIn={loggedIn} offset={signInOffset} user={user} />}
|
||||
<NewCount commentCount={asset.commentCount} countCache={countCache[asset.id]}/>
|
||||
<Stream
|
||||
refetch={refetch}
|
||||
addNotification={this.props.addNotification}
|
||||
@@ -155,6 +158,8 @@ class Embed extends Component {
|
||||
currentUser={user}
|
||||
postLike={this.props.postLike}
|
||||
postFlag={this.props.postFlag}
|
||||
getCounts={this.props.getCounts}
|
||||
updateCountCache={this.props.updateCountCache}
|
||||
loadMore={this.props.loadMore}
|
||||
deleteAction={this.props.deleteAction}
|
||||
showSignInDialog={this.props.showSignInDialog}
|
||||
@@ -216,6 +221,7 @@ const mapDispatchToProps = dispatch => ({
|
||||
clearNotification: () => dispatch(clearNotification()),
|
||||
editName: (username) => dispatch(editName(username)),
|
||||
showSignInDialog: (offset) => dispatch(showSignInDialog(offset)),
|
||||
updateCountCache: (id, count) => dispatch(updateCountCache(id, count)),
|
||||
logout: () => dispatch(logout()),
|
||||
dispatch: d => dispatch(d)
|
||||
});
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
|
||||
const NewCount = ({commentCount, countCache}) =>
|
||||
<div>
|
||||
{
|
||||
countCache && commentCount - countCache > 0 &&
|
||||
<div>
|
||||
Load {commentCount - countCache} More Comments
|
||||
</div>
|
||||
}
|
||||
</div>;
|
||||
|
||||
NewCount.propTypes = {
|
||||
commentCount: PropTypes.number.isRequired,
|
||||
countCache: PropTypes.number
|
||||
};
|
||||
|
||||
export default NewCount;
|
||||
@@ -17,10 +17,30 @@ class Stream extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {activeReplyBox: ''};
|
||||
this.state = {activeReplyBox: '', countPoll: null};
|
||||
this.setActiveReplyBox = this.setActiveReplyBox.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {asset, getCounts, updateCountCache} = this.props;
|
||||
|
||||
updateCountCache(asset.id, asset.comments.length);
|
||||
|
||||
// Note: Apollo's built-in polling doesn't work with fetchMore queries, so a
|
||||
// setInterval is being used instead.
|
||||
this.setState({
|
||||
countPoll: setInterval(() => getCounts({
|
||||
asset_id: asset.id,
|
||||
limit: asset.comments.length,
|
||||
sort: 'REVERSE_CHRONOLOGICAL'
|
||||
}), 5000),
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.state.countPoll);
|
||||
}
|
||||
|
||||
setActiveReplyBox (reactKey) {
|
||||
if (!this.props.currentUser) {
|
||||
const offset = document.getElementById(`c_${reactKey}`).getBoundingClientRect().top - 75;
|
||||
|
||||
@@ -38,6 +38,7 @@ export const updateOpenStream = closedBody => (dispatch, getState) => {
|
||||
|
||||
const openStream = () => ({type: actions.OPEN_COMMENTS});
|
||||
const closeStream = () => ({type: actions.CLOSE_COMMENTS});
|
||||
export const updateCountCache = (id, count) => ({type: actions.UPDATE_COUNT_CACHE, id, count});
|
||||
|
||||
export const updateOpenStatus = status => dispatch => {
|
||||
if (status === 'open') {
|
||||
|
||||
@@ -8,3 +8,4 @@ export const UPDATE_ASSET_SETTINGS_FAILURE = 'UPDATE_ASSET_SETTINGS_FAILURE';
|
||||
|
||||
export const OPEN_COMMENTS = 'OPEN_COMMENTS';
|
||||
export const CLOSE_COMMENTS = 'CLOSE_COMMENTS';
|
||||
export const UPDATE_COUNT_CACHE = 'UPDATE_COUNT_CACHE';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {graphql} from 'react-apollo';
|
||||
import STREAM_QUERY from './streamQuery.graphql';
|
||||
import LOAD_MORE from './loadMore.graphql';
|
||||
import GET_COUNTS from './getCounts.graphql';
|
||||
import MY_COMMENT_HISTORY from './myCommentHistory.graphql';
|
||||
|
||||
function getQueryVariable(variable) {
|
||||
@@ -17,6 +18,62 @@ function getQueryVariable(variable) {
|
||||
return 'http://localhost/default/stream';
|
||||
}
|
||||
|
||||
export const getCounts = (data) => ({asset_id, limit, sort}) => {
|
||||
return data.fetchMore({
|
||||
query: GET_COUNTS,
|
||||
variables: {
|
||||
asset_id,
|
||||
limit,
|
||||
sort
|
||||
},
|
||||
updateQuery: (oldData, {fetchMoreResult:{data}}) => {
|
||||
|
||||
return {
|
||||
...oldData,
|
||||
asset: {
|
||||
...oldData.asset,
|
||||
commentCount: data.asset.commentCount
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const loadMore = (data) => ({limit, cursor, parent_id, asset_id, sort}) => {
|
||||
return data.fetchMore({
|
||||
query: LOAD_MORE,
|
||||
variables: {
|
||||
limit,
|
||||
cursor,
|
||||
parent_id,
|
||||
asset_id,
|
||||
sort
|
||||
},
|
||||
updateQuery: (oldData, {fetchMoreResult:{data:{new_top_level_comments}}}) =>
|
||||
|
||||
// If loading more replies
|
||||
parent_id ? {
|
||||
...oldData,
|
||||
asset: {
|
||||
...oldData.asset,
|
||||
comments: oldData.asset.comments.map((comment) =>
|
||||
comment.id === parent_id
|
||||
? {...comment, replies: [...comment.replies, ...new_top_level_comments]}
|
||||
: comment)
|
||||
}
|
||||
}
|
||||
|
||||
// If loading more top-level comments
|
||||
: {
|
||||
...oldData,
|
||||
asset: {
|
||||
...oldData.asset,
|
||||
comments: [...oldData.asset.comments, ...new_top_level_comments]
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const queryStream = graphql(STREAM_QUERY, {
|
||||
options: () => ({
|
||||
variables: {
|
||||
@@ -25,40 +82,8 @@ export const queryStream = graphql(STREAM_QUERY, {
|
||||
}),
|
||||
props: ({data}) => ({
|
||||
data,
|
||||
loadMore: ({limit, cursor, parent_id, asset_id, sort}) => {
|
||||
return data.fetchMore({
|
||||
query: LOAD_MORE,
|
||||
variables: {
|
||||
limit,
|
||||
cursor,
|
||||
parent_id,
|
||||
asset_id,
|
||||
sort
|
||||
},
|
||||
updateQuery: (oldData, {fetchMoreResult:{data:{new_top_level_comments}}}) =>
|
||||
|
||||
// If loading more replies
|
||||
parent_id ? {
|
||||
...oldData,
|
||||
asset: {
|
||||
...oldData.asset,
|
||||
comments: oldData.asset.comments.map((comment) =>
|
||||
comment.id === parent_id
|
||||
? {...comment, replies: [...comment.replies, ...new_top_level_comments]}
|
||||
: comment)
|
||||
}
|
||||
}
|
||||
|
||||
// If loading more top-level comments
|
||||
: {
|
||||
...oldData,
|
||||
asset: {
|
||||
...oldData.asset,
|
||||
comments: [...oldData.asset.comments, ...new_top_level_comments]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
loadMore: loadMore(data),
|
||||
getCounts: getCounts(data),
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ export default function asset (state = initialState, action) {
|
||||
case actions.UPDATE_ASSET_SETTINGS_SUCCESS:
|
||||
return state
|
||||
.setIn(['settings'], action.settings);
|
||||
case actions.UPDATE_COUNT_CACHE:
|
||||
return state
|
||||
.setIn(['countCache', action.id], action.count);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import {Map} from 'immutable';
|
||||
import {expect} from 'chai';
|
||||
import assetReducer from '../../../../client/coral-framework/reducers/asset';
|
||||
import * as actions from '../../../../client/coral-framework/constants/asset';
|
||||
|
||||
describe ('coral-embed-stream assetReducer', () => {
|
||||
describe('UPDATE_COUNT_CACHE', () => {
|
||||
it('should update the count cache', () => {
|
||||
const action = {
|
||||
type: actions.UPDATE_COUNT_CACHE,
|
||||
id: '123',
|
||||
count: 456
|
||||
};
|
||||
const store = new Map({});
|
||||
const result = assetReducer(store, action);
|
||||
expect(result.getIn(['countCache', '123'])).to.equal(456);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import {Map} from 'immutable';
|
||||
import {expect} from 'chai';
|
||||
import notificationReducer from '../../../../client/coral-framework/reducers/notification';
|
||||
import * as actions from '../../../../client/coral-framework/actions/notification';
|
||||
|
||||
describe ('notificationsReducer', () => {
|
||||
describe('ADD_NOTIFICATION', () => {
|
||||
it('should add a notification', () => {
|
||||
const action = {
|
||||
type: actions.ADD_NOTIFICATION,
|
||||
text: 'Test notification',
|
||||
notifType: 'test'
|
||||
};
|
||||
const store = new Map({});
|
||||
const result = notificationReducer(store, action);
|
||||
expect(result.get('text')).to.equal(action.text);
|
||||
expect(result.get('type')).to.equal(action.notifType);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CLEAR_NOTIFICATION', () => {
|
||||
it('should clear a notification', () => {
|
||||
const action = {
|
||||
type: actions.CLEAR_NOTIFICATION
|
||||
};
|
||||
const store = new Map({
|
||||
text: 'Test notification',
|
||||
type: 'test'
|
||||
});
|
||||
const result = notificationReducer(store, action);
|
||||
expect(result.get('text')).to.equal('');
|
||||
expect(result.get('type')).to.equal('');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user