diff --git a/client/coral-embed-stream/src/components/Comment.js b/client/coral-embed-stream/src/components/Comment.js index 2e854633b..5e357e9b7 100644 --- a/client/coral-embed-stream/src/components/Comment.js +++ b/client/coral-embed-stream/src/components/Comment.js @@ -9,6 +9,7 @@ import {can} from 'coral-framework/services/perms'; import {TransitionGroup} from 'react-transition-group'; import cn from 'classnames'; import styles from './Comment.css'; +import {THREADING_LEVEL} from '../constants/stream'; import { BestButton, @@ -316,6 +317,7 @@ export default class Comment extends React.Component { postDontAgree, setActiveReplyBox, activeReplyBox, + loadMore, deleteAction, disableReply, maxCharCount, @@ -553,7 +555,7 @@ export default class Comment extends React.Component { charCountEnable={charCountEnable} maxCharCount={maxCharCount} setActiveReplyBox={setActiveReplyBox} - parentId={parentId || comment.id} + parentId={(depth < THREADING_LEVEL) ? comment.id : parentId} addNotification={addNotification} postComment={postComment} currentUser={currentUser} @@ -583,6 +585,7 @@ export default class Comment extends React.Component { deleteAction={deleteAction} addTag={addTag} removeTag={removeTag} + loadMore={loadMore} ignoreUser={ignoreUser} charCountEnable={charCountEnable} maxCharCount={maxCharCount} diff --git a/client/coral-embed-stream/src/components/Stream.js b/client/coral-embed-stream/src/components/Stream.js index 0cfaf0368..4b04f5e7b 100644 --- a/client/coral-embed-stream/src/components/Stream.js +++ b/client/coral-embed-stream/src/components/Stream.js @@ -16,6 +16,7 @@ import IgnoredCommentTombstone from './IgnoredCommentTombstone'; import NewCount from './NewCount'; import {TransitionGroup} from 'react-transition-group'; import {forEachError} from 'coral-framework/utils'; +import {getTopLevelParent} from '../graphql/utils'; const hasComment = (nodes, id) => nodes.some((node) => node.id === id); @@ -169,9 +170,7 @@ class Stream extends React.Component { const open = asset.closedAt === null; // even though the permalinked comment is the highlighted one, we're displaying its parent + replies - const highlightedComment = comment && comment.parent - ? comment.parent - : comment; + const highlightedComment = comment && getTopLevelParent(comment); const banned = user && user.status === 'BANNED'; const temporarilySuspended = diff --git a/client/coral-embed-stream/src/constants/stream.js b/client/coral-embed-stream/src/constants/stream.js index 58004e877..5a8784a81 100644 --- a/client/coral-embed-stream/src/constants/stream.js +++ b/client/coral-embed-stream/src/constants/stream.js @@ -3,3 +3,4 @@ export const ADDTL_COMMENTS_ON_LOAD_MORE = 10; export const VIEW_ALL_COMMENTS = 'VIEW_ALL_COMMENTS'; export const ADD_COMMENT_CLASSNAME = 'ADD_COMMENT_CLASSNAME'; export const REMOVE_COMMENT_CLASSNAME = 'REMOVE_COMMENT_CLASSNAME'; +export const THREADING_LEVEL = 2; diff --git a/client/coral-embed-stream/src/containers/Stream.js b/client/coral-embed-stream/src/containers/Stream.js index 3491fc846..28947b77e 100644 --- a/client/coral-embed-stream/src/containers/Stream.js +++ b/client/coral-embed-stream/src/containers/Stream.js @@ -2,7 +2,7 @@ import React from 'react'; import {gql, compose} from 'react-apollo'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {ADDTL_COMMENTS_ON_LOAD_MORE} from '../constants/stream'; +import {ADDTL_COMMENTS_ON_LOAD_MORE, THREADING_LEVEL} from '../constants/stream'; import { withPostComment, withPostFlag, withPostDontAgree, withDeleteAction, withAddTag, withRemoveTag, withIgnoreUser, withEditComment, @@ -91,9 +91,7 @@ class StreamContainer extends React.Component { } loadNewReplies = (parent_id) => { - const comment = this.props.root.comment - ? this.props.root.comment.parent || this.props.root.comment // highlighted comment. - : this.props.root.asset.comments.nodes.filter((comment) => comment.id === parent_id)[0]; + const comment = findCommentInEmbedQuery(this.props.root, parent_id); return this.props.data.fetchMore({ query: LOAD_MORE_QUERY, @@ -153,20 +151,35 @@ class StreamContainer extends React.Component { } } +const nest = (def, level) => { + let result = ''; + for (let x = 0; x < level; x++) { + if (x === 0) { + result += def; + continue; + } + result = result.replace('...nest', def); + } + return result.replace('...nest', ''); +}; + const commentFragment = gql` fragment CoralEmbedStream_Stream_comment on Comment { id ...${getDefinitionName(Comment.fragments.comment)} - replyCount(excludeIgnored: $excludeIgnored) - replies(excludeIgnored: $excludeIgnored) { - nodes { - id - ...${getDefinitionName(Comment.fragments.comment)} + ${nest(` + replyCount(excludeIgnored: $excludeIgnored) + replies(excludeIgnored: $excludeIgnored) { + nodes { + id + ...${getDefinitionName(Comment.fragments.comment)} + ...nest + } + hasNextPage + startCursor + endCursor } - hasNextPage - startCursor - endCursor - } + `, THREADING_LEVEL)} } ${Comment.fragments.comment} `; @@ -205,16 +218,19 @@ const LOAD_MORE_QUERY = gql` nodes { id ...${getDefinitionName(Comment.fragments.comment)} - replyCount(excludeIgnored: $excludeIgnored) - replies(limit: 3, excludeIgnored: $excludeIgnored) { - nodes { - id - ...${getDefinitionName(Comment.fragments.comment)} + ${nest(` + replyCount(excludeIgnored: $excludeIgnored) + replies(limit: 3, excludeIgnored: $excludeIgnored) { + nodes { + id + ...${getDefinitionName(Comment.fragments.comment)} + ...nest + } + hasNextPage + startCursor + endCursor } - hasNextPage - startCursor - endCursor - } + `, THREADING_LEVEL)} } hasNextPage startCursor @@ -229,9 +245,12 @@ const fragments = { fragment CoralEmbedStream_Stream_root on RootQuery { comment(id: $commentId) @include(if: $hasComment) { ...CoralEmbedStream_Stream_comment - parent { - ...CoralEmbedStream_Stream_comment - } + ${nest(` + parent { + ...CoralEmbedStream_Stream_comment + ...nest + } + `, THREADING_LEVEL)} } asset(id: $assetId, url: $assetUrl) { id diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index eff1e2439..518f4b62f 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -1,21 +1,23 @@ import update from 'immutability-helper'; +import {THREADING_LEVEL} from '../constants/stream'; function applyToCommentsOrigin(root, callback) { if (root.comment) { - if (root.comment.parent) { - return update(root, { - comment: { - parent: { - $apply: (node) => callback(node), - }, - }, - }); + let comment = root.comment; + console.log(comment); + for (let depth = 0; depth <= THREADING_LEVEL; depth++) { + let changes = {$apply: (node) => node ? callback(node) : node}; + for (let i = 0; i < depth; i++) { + changes = {parent: changes}; + } + console.log(changes); + comment = update(comment, changes); } - return update(root, { - comment: { - $apply: (node) => callback(node), - }, - }); + + return { + ...root, + comment, + }; } return update(root, { asset: {$apply: (asset) => callback(asset)}, @@ -97,6 +99,13 @@ export function removeCommentFromEmbedQuery(root, id) { return applyToCommentsOrigin(root, (origin) => findAndRemoveComment(origin, id)); } +export function getTopLevelParent(comment) { + if (comment.parent) { + return getTopLevelParent(comment.parent); + } + return comment; +} + function findComment(nodes, callback) { for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; @@ -119,12 +128,7 @@ export function findCommentInEmbedQuery(root, callbackOrId) { callback = (node) => node.id === callbackOrId; } if (root.comment) { - if (callback(root.comment)) { - return root.comment; - } - if (root.comment.parent && callback(root.comment.parent)) { - return root.comment.parent; - } + return findComment([getTopLevelParent(root.comment)], callback); } if (!root.asset.comments) { return false;