From 12d3273d3de2d1da97093e912a0780d859ab9cfb Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 4 Aug 2017 22:02:44 +0700 Subject: [PATCH 1/4] Support load more in user history --- .../coral-admin/src/components/LoadMore.css | 21 +++++++ .../Moderation => }/components/LoadMore.js | 2 +- .../coral-admin/src/components/UserDetail.js | 8 ++- .../src/components/UserDetailComment.css | 4 ++ .../coral-admin/src/containers/UserDetail.js | 56 ++++++++++++++++++- .../Moderation/components/ModerationQueue.js | 2 +- .../routes/Moderation/components/styles.css | 22 +------- graph/helpers/response.js | 9 +-- 8 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 client/coral-admin/src/components/LoadMore.css rename client/coral-admin/src/{routes/Moderation => }/components/LoadMore.js (92%) diff --git a/client/coral-admin/src/components/LoadMore.css b/client/coral-admin/src/components/LoadMore.css new file mode 100644 index 000000000..64c51f870 --- /dev/null +++ b/client/coral-admin/src/components/LoadMore.css @@ -0,0 +1,21 @@ +.loadMoreContainer { + display: flex; + justify-content: center; + width: 100%; +} + +.loadMore { + width: 100%; + text-align: center; + color: #FFF; + max-width: 660px; + margin-bottom: 30px; + background-color: #2376D8; + cursor: pointer; +} + +.loadMore:hover { + background-color: #4399FF; +} + + diff --git a/client/coral-admin/src/routes/Moderation/components/LoadMore.js b/client/coral-admin/src/components/LoadMore.js similarity index 92% rename from client/coral-admin/src/routes/Moderation/components/LoadMore.js rename to client/coral-admin/src/components/LoadMore.js index 612629647..ac7ea38d6 100644 --- a/client/coral-admin/src/routes/Moderation/components/LoadMore.js +++ b/client/coral-admin/src/components/LoadMore.js @@ -1,6 +1,6 @@ import React, {PropTypes} from 'react'; import {Button} from 'coral-ui'; -import styles from './styles.css'; +import styles from './LoadMore.css'; const LoadMore = ({loadMore, showLoadMore}) =>
diff --git a/client/coral-admin/src/components/UserDetail.js b/client/coral-admin/src/components/UserDetail.js index eab25c41d..dcc40a029 100644 --- a/client/coral-admin/src/components/UserDetail.js +++ b/client/coral-admin/src/components/UserDetail.js @@ -6,6 +6,7 @@ import {Slot} from 'coral-framework/components'; import ButtonCopyToClipboard from './ButtonCopyToClipboard'; import {actionsMap} from '../utils/moderationQueueActionsMap'; import ClickOutside from 'coral-framework/components/ClickOutside'; +import LoadMore from '../components/LoadMore'; export default class UserDetail extends React.Component { @@ -59,7 +60,7 @@ export default class UserDetail extends React.Component { user, totalComments, rejectedComments, - comments: {nodes} + comments: {nodes, hasNextPage} }, activeTab, selectedCommentIds, @@ -70,6 +71,7 @@ export default class UserDetail extends React.Component { bulkReject, hideUserDetail, viewUserDetail, + loadMore, } = this.props; const localProfile = user.profiles.find((p) => p.provider === 'local'); @@ -167,6 +169,10 @@ export default class UserDetail extends React.Component { }) }
+ ); diff --git a/client/coral-admin/src/components/UserDetailComment.css b/client/coral-admin/src/components/UserDetailComment.css index 0e10f00c0..b042aea39 100644 --- a/client/coral-admin/src/components/UserDetailComment.css +++ b/client/coral-admin/src/components/UserDetailComment.css @@ -8,6 +8,10 @@ min-height: 0; } +.root:last-child { + border: 0; +} + .rootSelected { background-color: #ecf4ff; } diff --git a/client/coral-admin/src/containers/UserDetail.js b/client/coral-admin/src/containers/UserDetail.js index a54e70734..e59629a85 100644 --- a/client/coral-admin/src/containers/UserDetail.js +++ b/client/coral-admin/src/containers/UserDetail.js @@ -14,6 +14,7 @@ import { } from 'coral-admin/src/actions/userDetail'; import {withSetCommentStatus} from 'coral-framework/graphql/mutations'; import UserDetailComment from './UserDetailComment'; +import update from 'immutability-helper'; const commentConnectionFragment = gql` fragment CoralAdmin_Moderation_CommentConnection on CommentConnection { @@ -32,6 +33,7 @@ const slots = [ ]; class UserDetailContainer extends React.Component { + isLoadingMore = false; // status can be 'ACCEPTED' or 'REJECTED' bulkSetCommentStatus = (status) => { @@ -40,7 +42,6 @@ class UserDetailContainer extends React.Component { }); Promise.all(changes).then(() => { - this.props.data.refetch(); // some comments may have moved out of this tab this.props.clearUserDetailSelections(); // un-select everything }); } @@ -61,12 +62,53 @@ class UserDetailContainer extends React.Component { return this.props.setCommentStatus({commentId, status: 'REJECTED'}); } + loadMore = () => { + if (this.isLoadingMore) { + return; + } + + this.isLoadingMore = true; + const variables = { + limit: 10, + cursor: this.props.root.comments.endCursor, + author_id: this.props.data.variables.author_id, + statuses: this.props.data.variables.statuses, + }; + this.props.data.fetchMore({ + query: LOAD_MORE_QUERY, + variables, + updateQuery: (prev, {fetchMoreResult:{comments}}) => { + return update(prev, { + comments: { + nodes: {$push: comments.nodes}, + hasNextPage: {$set: comments.hasNextPage}, + startCursor: {$set: comments.startCursor}, + endCursor: {$set: comments.endCursor}, + }, + }); + } + }) + .then(() => { + this.isLoadingMore = false; + }) + .catch((err) => { + this.isLoadingMore = false; + throw err; + }); + }; + + componentWillReceiveProps(next) { + if (this.props.userId === null && next.userId) { + next.data.refetch(); + } + } + render () { if (!this.props.userId) { return null; } - const loading = !('user' in this.props.root) || this.props.root.user.id !== this.props.userId; + const loading = [1, 2, 4].indexOf(this.props.data.networkStatus) >= 0; return ; } } +const LOAD_MORE_QUERY = gql` + query CoralAdmin_Moderation_LoadMore($limit: Int = 10, $cursor: Date, $author_id: ID!, $statuses: [COMMENT_STATUS!]) { + comments(query: {limit: $limit, cursor: $cursor, author_id: $author_id, statuses: $statuses}) { + ...CoralAdmin_Moderation_CommentConnection + } + } + ${commentConnectionFragment} +`; + export const withUserDetailQuery = withQuery(gql` query CoralAdmin_UserDetail($author_id: ID!, $statuses: [COMMENT_STATUS!]) { user(id: $author_id) { diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js index 57b551df2..7f96c7c90 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js @@ -4,7 +4,7 @@ import Comment from '../containers/Comment'; import styles from './styles.css'; import EmptyCard from '../../../components/EmptyCard'; import {actionsMap} from '../../../utils/moderationQueueActionsMap'; -import LoadMore from './LoadMore'; +import LoadMore from '../../../components/LoadMore'; import t from 'coral-framework/services/i18n'; import {CSSTransitionGroup} from 'react-transition-group'; diff --git a/client/coral-admin/src/routes/Moderation/components/styles.css b/client/coral-admin/src/routes/Moderation/components/styles.css index ccc762641..72c5e4d63 100644 --- a/client/coral-admin/src/routes/Moderation/components/styles.css +++ b/client/coral-admin/src/routes/Moderation/components/styles.css @@ -397,26 +397,6 @@ span { } } -.loadMoreContainer { - display: flex; - justify-content: center; - width: 100%; -}; - -.loadMore { - width: 100%; - text-align: center; - color: #FFF; - max-width: 660px; - margin-bottom: 30px; - background-color: #2376D8; - cursor: pointer; -} - -.loadMore:hover { - background-color: #4399FF; -} - .tabIcon { position: relative; top: 3px; @@ -499,4 +479,4 @@ span { right: 0px; top: 0px; text-align: right; -} \ No newline at end of file +} diff --git a/graph/helpers/response.js b/graph/helpers/response.js index ebdbc02ec..f5e7a54f4 100644 --- a/graph/helpers/response.js +++ b/graph/helpers/response.js @@ -2,18 +2,19 @@ const errors = require('../../errors'); const {Error: {ValidationError}} = require('mongoose'); /** - * Wraps up a promise to return an object with the resolution of the promise + * Wraps up a promise or value to return an object with the resolution of the promise * keyed at `key` or an error caught at `errors`. */ -const wrapResponse = (key) => (promise) => { - return promise.then((value) => { +const wrapResponse = (key) => (promiseOrValue) => { + return Promise.resolve(promiseOrValue).then((value) => { let res = {}; if (key) { res[key] = value; } return res; - }).catch((err) => { + }) + .catch((err) => { if (err instanceof errors.APIError) { return { errors: [err] From 0df4fd1e378527aa700a0f60bf10d274bf6dff35 Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 4 Aug 2017 23:24:40 +0700 Subject: [PATCH 2/4] Adjust styling --- client/coral-admin/src/components/LoadMore.js | 5 +++-- client/coral-admin/src/components/UserDetail.css | 9 +++++++++ client/coral-admin/src/components/UserDetail.js | 1 + client/coral-ui/components/Drawer.css | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/client/coral-admin/src/components/LoadMore.js b/client/coral-admin/src/components/LoadMore.js index ac7ea38d6..969c6734f 100644 --- a/client/coral-admin/src/components/LoadMore.js +++ b/client/coral-admin/src/components/LoadMore.js @@ -1,9 +1,10 @@ import React, {PropTypes} from 'react'; import {Button} from 'coral-ui'; import styles from './LoadMore.css'; +import cn from 'classnames'; -const LoadMore = ({loadMore, showLoadMore}) => -
+const LoadMore = ({loadMore, showLoadMore, className, ...rest}) => +
{ showLoadMore &&
diff --git a/client/coral-ui/components/Drawer.css b/client/coral-ui/components/Drawer.css index d6a7e6871..88c30425f 100644 --- a/client/coral-ui/components/Drawer.css +++ b/client/coral-ui/components/Drawer.css @@ -3,7 +3,7 @@ min-width: 550px; position: fixed; top: 0; - right: -17px; + right: 0px; bottom: 0; background-color: white; transition: transform 500ms ease-in-out; From 567f8bf94eba5f02db08c83a0e269f4e5d9b0b5f Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Mon, 7 Aug 2017 14:54:11 +1000 Subject: [PATCH 3/4] adjusted wrapResponse function --- graph/helpers/response.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/graph/helpers/response.js b/graph/helpers/response.js index f5e7a54f4..1db1e9b89 100644 --- a/graph/helpers/response.js +++ b/graph/helpers/response.js @@ -6,15 +6,17 @@ const {Error: {ValidationError}} = require('mongoose'); * keyed at `key` or an error caught at `errors`. */ -const wrapResponse = (key) => (promiseOrValue) => { - return Promise.resolve(promiseOrValue).then((value) => { +const wrapResponse = (key) => async (promise) => { + try { + let value = await promise; + let res = {}; if (key) { res[key] = value; } + return res; - }) - .catch((err) => { + } catch (err) { if (err instanceof errors.APIError) { return { errors: [err] @@ -26,7 +28,7 @@ const wrapResponse = (key) => (promiseOrValue) => { } throw err; - }); + } }; module.exports = wrapResponse; From 1e8d2ce3a665f5cd065e991dc3a537f015ebb83a Mon Sep 17 00:00:00 2001 From: Erik Reyna Date: Mon, 7 Aug 2017 14:11:51 -0400 Subject: [PATCH 4/4] expose talk-stream-comment-avatar class --- client/coral-embed-stream/src/components/Comment.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 34f672d8a..1c57e2d1e 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -400,7 +400,7 @@ export default class Comment extends React.Component {