From 91dd9b157af0ce2fd9a0266877c78ff9d173095f Mon Sep 17 00:00:00 2001 From: Chi Vinh Le Date: Fri, 2 Mar 2018 00:00:51 +0100 Subject: [PATCH] Implement new permlink view for real --- .../coral-embed-stream/src/graphql/utils.js | 41 +++++++++++++++---- .../src/tabs/stream/components/Comment.css | 4 ++ .../src/tabs/stream/components/Comment.js | 3 +- .../src/tabs/stream/components/Stream.js | 20 +++------ .../src/tabs/stream/containers/Comment.js | 2 +- .../src/tabs/stream/containers/Stream.js | 25 ++++++++--- 6 files changed, 64 insertions(+), 31 deletions(-) diff --git a/client/coral-embed-stream/src/graphql/utils.js b/client/coral-embed-stream/src/graphql/utils.js index 720cb7f2e..96cf49cad 100644 --- a/client/coral-embed-stream/src/graphql/utils.js +++ b/client/coral-embed-stream/src/graphql/utils.js @@ -141,7 +141,7 @@ export function findCommentInAsset(asset, callbackOrId) { callback = node => node.id === callbackOrId; } if (asset.comment) { - return findComment([getTopLevelParent(asset.comment)], callback); + return findComment([reverseCommentParentTree(asset.comment)], callback); } if (!asset.comments) { return false; @@ -187,11 +187,12 @@ export function insertFetchedCommentsIntoEmbedQuery(root, comments, parent_id) { ); } -/** - * attachCommentToParent recurses through the comment tree starting at `topLevelComment` - * to find the parent of `comment` and attach it to the replies. - */ -export function attachCommentToParent(topLevelComment, comment) { +function attachComment(topLevelComment, comment) { + if (!topLevelComment.replies) { + topLevelComment = update(topLevelComment, { + replies: { $set: { nodes: [] } }, + }); + } if (topLevelComment.id === comment.parent.id) { return update(topLevelComment, { replies: { @@ -204,16 +205,40 @@ export function attachCommentToParent(topLevelComment, comment) { }, }); } + if (!topLevelComment.replies.nodes.length) { + return topLevelComment; + } return update(topLevelComment, { replies: { nodes: { - $apply: nodes => - nodes.map(node => attachCommentToParent(node, comment)), + $apply: nodes => nodes.map(node => attachComment(node, comment)), }, }, }); } +/** + * attachCommentToParent recurses through the comment tree starting at `topLevelComment` + * to find the ancestor of `comment` and attach it to the replies. + */ +export function attachCommentToParent(topLevelComment, comment) { + let result = topLevelComment; + if (comment.parent.parent) { + result = attachCommentToParent(result, comment.parent); + } + return attachComment(result, comment); +} + +/** + * reverseCommentParentTree reverses a comment parent relationship tree + * like `comment -> parent -> parent` into `parent -> parent -> comment -> replies`. + */ +export function reverseCommentParentTree(comment) { + return comment.parent + ? attachCommentToParent(getTopLevelParent(comment), comment) + : comment; +} + /** * Nest a string in itself repeatly until `level` has been reached. * diff --git a/client/coral-embed-stream/src/tabs/stream/components/Comment.css b/client/coral-embed-stream/src/tabs/stream/components/Comment.css index 8945bc790..58ff0e731 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/Comment.css +++ b/client/coral-embed-stream/src/tabs/stream/components/Comment.css @@ -22,6 +22,10 @@ .commentLevel0 { padding-left: 0px; + + &.highlightedComment { + margin-top: 8px; + } } .commentLevel1 { diff --git a/client/coral-embed-stream/src/tabs/stream/components/Comment.js b/client/coral-embed-stream/src/tabs/stream/components/Comment.js index d75789a63..f46630e97 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/Comment.js +++ b/client/coral-embed-stream/src/tabs/stream/components/Comment.js @@ -13,6 +13,7 @@ import styles from './Comment.css'; import { THREADING_LEVEL } from '../../../constants/stream'; import merge from 'lodash/merge'; import mapValues from 'lodash/mapValues'; +import get from 'lodash/get'; import LoadMore from './LoadMore'; import { getEditableUntilDate } from './util'; @@ -471,7 +472,7 @@ export default class Comment extends React.Component { const { highlighted, comment } = this.props; // Only render highlighted reply when we are the parent of it. - if (highlighted && highlighted.parent.id === comment.id) { + if (get(highlighted, 'parent.id') === comment.id) { return this.renderReplies([highlighted]); } diff --git a/client/coral-embed-stream/src/tabs/stream/components/Stream.js b/client/coral-embed-stream/src/tabs/stream/components/Stream.js index 8a6b75be3..c8a304214 100644 --- a/client/coral-embed-stream/src/tabs/stream/components/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/components/Stream.js @@ -12,15 +12,11 @@ import RestrictedMessageBox from 'coral-framework/components/RestrictedMessageBo import t, { timeago } from 'coral-framework/services/i18n'; import CommentBox from '../containers/CommentBox'; import QuestionBox from '../../../components/QuestionBox'; -import { isCommentActive } from 'coral-framework/utils'; import { Tab, TabCount, TabPane } from 'coral-ui'; import cn from 'classnames'; import get from 'lodash/get'; -import { - getTopLevelParent, - attachCommentToParent, -} from '../../../graphql/utils'; +import { reverseCommentParentTree } from '../../../graphql/utils'; import AllCommentsPane from './AllCommentsPane'; import ExtendableTabPanel from '../../../containers/ExtendableTabPanel'; @@ -64,16 +60,10 @@ class Stream extends React.Component { viewAllComments, } = this.props; - // even though the permalinked comment is the highlighted one, we're displaying its parent + replies - let topLevelComment = getTopLevelParent(comment); - if (topLevelComment) { - // Inactive comments can be viewed by moderators and admins (e.g. using permalinks). - const isInactive = !isCommentActive(comment.status); - if (comment.parent && isInactive) { - // the highlighted comment is not active and as such not in the replies, so we - // attach it to the right parent. - topLevelComment = attachCommentToParent(topLevelComment, comment); - } + let topLevelComment = null; + if (comment) { + // Reverse the comment tree that we get from bottom-top (comment -> parent) to top-bottom (parent -> comment) + topLevelComment = reverseCommentParentTree(comment); } return ( diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Comment.js b/client/coral-embed-stream/src/tabs/stream/containers/Comment.js index 5a6c332e0..03a816107 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Comment.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Comment.js @@ -64,7 +64,7 @@ const withAnimateEnter = hoistStatics(BaseComponent => { return WithAnimateEnter; }); -const singleCommentFragment = gql` +export const singleCommentFragment = gql` fragment CoralEmbedStream_Comment_SingleComment on Comment { id body diff --git a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js index e80719646..191490914 100644 --- a/client/coral-embed-stream/src/tabs/stream/containers/Stream.js +++ b/client/coral-embed-stream/src/tabs/stream/containers/Stream.js @@ -24,7 +24,7 @@ import { viewAllComments, } from '../../../actions/stream'; import Stream from '../components/Stream'; -import Comment from './Comment'; +import { default as Comment, singleCommentFragment } from './Comment'; import { withFragments, withEmit } from 'coral-framework/hocs'; import { getDefinitionName, @@ -282,7 +282,7 @@ StreamContainer.propTypes = { previousTab: PropTypes.string, }; -const commentFragment = gql` +const streamCommentFragment = gql` fragment CoralEmbedStream_Stream_comment on Comment { id status @@ -294,6 +294,18 @@ const commentFragment = gql` ${Comment.fragments.comment} `; +const streamSingleCommentFragment = gql` + fragment CoralEmbedStream_Stream_singleComment on Comment { + id + status + user { + id + } + ...${getDefinitionName(singleCommentFragment)} + } + ${singleCommentFragment} +`; + const COMMENTS_ADDED_SUBSCRIPTION = gql` subscription CommentAdded($assetId: ID!, $excludeIgnored: Boolean) { commentAdded(asset_id: $assetId) { @@ -303,7 +315,7 @@ const COMMENTS_ADDED_SUBSCRIPTION = gql` ...CoralEmbedStream_Stream_comment } } - ${commentFragment} + ${streamCommentFragment} `; const COMMENTS_EDITED_SUBSCRIPTION = gql` @@ -351,7 +363,7 @@ const LOAD_MORE_QUERY = gql` endCursor } } - ${commentFragment} + ${streamCommentFragment} `; const slots = [ @@ -398,7 +410,7 @@ const fragments = { ${nest( ` parent { - ...CoralEmbedStream_Stream_comment + ...CoralEmbedStream_Stream_singleComment ...nest } `, @@ -437,7 +449,8 @@ const fragments = { ...${getDefinitionName(Comment.fragments.asset)} } ${Comment.fragments.asset} - ${commentFragment} + ${streamCommentFragment} + ${streamSingleCommentFragment} `, };