diff --git a/packages/client/components/DiscussionThreadInput.tsx b/packages/client/components/DiscussionThreadInput.tsx
index fc4ff6e8a7e..33d358a4d88 100644
--- a/packages/client/components/DiscussionThreadInput.tsx
+++ b/packages/client/components/DiscussionThreadInput.tsx
@@ -51,7 +51,6 @@ interface Props {
getMaxSortOrder: () => number
discussion: DiscussionThreadInput_discussion$key
viewer: DiscussionThreadInput_viewer$key
- threadParentId?: string
isReply?: boolean
isDisabled?: boolean
isCreatingPoll?: boolean
@@ -62,7 +61,6 @@ const DiscussionThreadInput = (props: Props) => {
allowedThreadables,
getMaxSortOrder,
discussion: discussionRef,
- threadParentId,
viewer: viewerRef,
isCreatingPoll
} = props
@@ -186,6 +184,7 @@ const DiscussionThreadInput = (props: Props) => {
const addComment = (rawContent: string) => {
submitMutation()
+ const threadParentId = replyingTo?.threadParentId ?? replyingTo?.id
const comment = {
content: rawContent,
isAnonymous: isAnonymousComment,
@@ -234,6 +233,7 @@ const DiscussionThreadInput = (props: Props) => {
const addTask = () => {
const {viewerId} = atmosphere
+ const threadParentId = replyingTo?.threadParentId ?? replyingTo?.id
const newTask = {
status: 'active',
sortOrder: dndNoise(),
diff --git a/packages/client/components/ThreadedCommentBase.tsx b/packages/client/components/ThreadedCommentBase.tsx
index 1c687672a3c..93cec7894d8 100644
--- a/packages/client/components/ThreadedCommentBase.tsx
+++ b/packages/client/components/ThreadedCommentBase.tsx
@@ -14,36 +14,36 @@ import anonymousAvatar from '../styles/theme/images/anonymous-avatar.svg'
import deletedAvatar from '../styles/theme/images/deleted-avatar-placeholder.svg'
import {PARABOL_AI_USER_ID} from '../utils/constants'
import SendClientSideEvent from '../utils/SendClientSideEvent'
+import DiscussionThreadInput from './DiscussionThreadInput'
import {DiscussionThreadables} from './DiscussionThreadList'
import {TipTapEditor} from './promptResponse/TipTapEditor'
import ThreadedAvatarColumn from './ThreadedAvatarColumn'
import ThreadedCommentFooter from './ThreadedCommentFooter'
import ThreadedCommentHeader from './ThreadedCommentHeader'
-import ThreadedItemReply from './ThreadedItemReply'
import ThreadedItemWrapper from './ThreadedItemWrapper'
interface Props {
allowedThreadables: DiscussionThreadables[]
comment: ThreadedCommentBase_comment$key
- children?: ReactNode // the replies, listed here to avoid a circular reference
discussion: ThreadedCommentBase_discussion$key
- isReply?: boolean // this comment is a reply & should be indented
-
viewer: ThreadedCommentBase_viewer$key
+ repliesList?: ReactNode
+ getMaxSortOrder: () => number
}
const ThreadedCommentBase = (props: Props) => {
const {
allowedThreadables,
- children,
comment: commentRef,
discussion: discussionRef,
- viewer: viewerRef
+ viewer: viewerRef,
+ repliesList,
+ getMaxSortOrder
} = props
const viewer = useFragment(
graphql`
fragment ThreadedCommentBase_viewer on User {
- ...ThreadedItemReply_viewer
+ ...DiscussionThreadInput_viewer
billingTier
}
`,
@@ -53,11 +53,13 @@ const ThreadedCommentBase = (props: Props) => {
graphql`
fragment ThreadedCommentBase_discussion on Discussion {
...DiscussionThreadInput_discussion
- ...ThreadedItemReply_discussion
id
meetingId
teamId
discussionTopicId
+ replyingTo {
+ id
+ }
}
`,
discussionRef
@@ -66,7 +68,6 @@ const ThreadedCommentBase = (props: Props) => {
graphql`
fragment ThreadedCommentBase_comment on Comment {
...ThreadedCommentHeader_comment
- ...ThreadedItemReply_threadable
id
isActive
content
@@ -80,21 +81,13 @@ const ThreadedCommentBase = (props: Props) => {
id
isViewerReactji
}
- threadParentId
}
`,
commentRef
)
- const isReply = !!props.isReply
- const {id: discussionId, meetingId, teamId, discussionTopicId} = discussion
- const {
- id: commentId,
- content,
- createdByUserNullable,
- isActive,
- reactjis,
- threadParentId
- } = comment
+ const isReply = !repliesList
+ const {id: discussionId, meetingId, teamId, discussionTopicId, replyingTo} = discussion
+ const {id: commentId, content, createdByUserNullable, isActive, reactjis} = comment
const picture = isActive ? (createdByUserNullable?.picture ?? anonymousAvatar) : deletedAvatar
const {submitMutation, submitting, onError, onCompleted} = useMutationProps()
const atmosphere = useAtmosphere()
@@ -143,7 +136,6 @@ const ThreadedCommentBase = (props: Props) => {
commitLocalUpdate(atmosphere, (store) => {
const comment = store.get(commentId)
if (!comment) return
- comment.setValue(threadParentId, 'threadParentId')
store
.getRoot()
.getLinkedRecord('viewer')
@@ -193,13 +185,16 @@ const ThreadedCommentBase = (props: Props) => {
onReply={onReply}
/>
)}
- {children}
-
+ {repliesList}
+ {replyingTo?.id === comment.id && (
+
+ )}
)
diff --git a/packages/client/components/ThreadedItem.tsx b/packages/client/components/ThreadedItem.tsx
index 9bad832498a..39c07240995 100644
--- a/packages/client/components/ThreadedItem.tsx
+++ b/packages/client/components/ThreadedItem.tsx
@@ -60,13 +60,17 @@ export const ThreadedItem = (props: Props) => {
__typename
replies {
...ThreadedRepliesList_replies
+ threadSortOrder
}
}
`,
threadableRef
)
const {__typename, replies} = threadable
- const child = (
+ const getMaxSortOrder = () => {
+ return replies ? Math.max(0, ...replies.map((reply) => reply.threadSortOrder || 0)) : 0
+ }
+ const repliesList = (
{
task={threadable}
discussion={discussion}
viewer={viewer}
- >
- {child}
-
+ repliesList={repliesList}
+ getMaxSortOrder={getMaxSortOrder}
+ />
)
}
if (__typename === 'Poll') {
@@ -101,9 +105,9 @@ export const ThreadedItem = (props: Props) => {
comment={threadable}
discussion={discussion}
viewer={viewer}
- >
- {child}
-
+ repliesList={repliesList}
+ getMaxSortOrder={getMaxSortOrder}
+ />
)
}
diff --git a/packages/client/components/ThreadedItemReply.tsx b/packages/client/components/ThreadedItemReply.tsx
deleted file mode 100644
index ca282ec963b..00000000000
--- a/packages/client/components/ThreadedItemReply.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import graphql from 'babel-plugin-relay/macro'
-import {useFragment} from 'react-relay'
-import {ThreadedItemReply_discussion$key} from '~/__generated__/ThreadedItemReply_discussion.graphql'
-import {ThreadedItemReply_threadable$key} from '~/__generated__/ThreadedItemReply_threadable.graphql'
-import {ThreadedItemReply_viewer$key} from '~/__generated__/ThreadedItemReply_viewer.graphql'
-import DiscussionThreadInput from './DiscussionThreadInput'
-import {DiscussionThreadables} from './DiscussionThreadList'
-
-interface Props {
- allowedThreadables: DiscussionThreadables[]
- threadable: ThreadedItemReply_threadable$key
- discussion: ThreadedItemReply_discussion$key
- viewer: ThreadedItemReply_viewer$key
-}
-
-const ThreadedItemReply = (props: Props) => {
- const {
- allowedThreadables,
- threadable: threadableRef,
- discussion: discussionRef,
- viewer: viewerRef
- } = props
- const viewer = useFragment(
- graphql`
- fragment ThreadedItemReply_viewer on User {
- ...DiscussionThreadInput_viewer
- }
- `,
- viewerRef
- )
- const threadable = useFragment(
- graphql`
- fragment ThreadedItemReply_threadable on Threadable {
- id
- replies {
- id
- threadSortOrder
- }
- }
- `,
- threadableRef
- )
- const discussion = useFragment(
- graphql`
- fragment ThreadedItemReply_discussion on Discussion {
- ...DiscussionThreadInput_discussion
- replyingTo {
- id
- }
- }
- `,
- discussionRef
- )
- const {id: threadableId, replies} = threadable
- const {replyingTo} = discussion
- const isReplying = replyingTo?.id === threadableId
- if (!isReplying) return null
- const getMaxSortOrder = () => {
- return replies ? Math.max(0, ...replies.map((reply) => reply.threadSortOrder || 0)) : 0
- }
- return (
-
- )
-}
-
-export default ThreadedItemReply
diff --git a/packages/client/components/ThreadedRepliesList.tsx b/packages/client/components/ThreadedRepliesList.tsx
index cdfc65286b5..573807f938b 100644
--- a/packages/client/components/ThreadedRepliesList.tsx
+++ b/packages/client/components/ThreadedRepliesList.tsx
@@ -46,16 +46,17 @@ const ThreadedRepliesList = (props: Props) => {
...ThreadedCommentBase_comment
__typename
id
+ threadSortOrder
}
`,
repliesRef
)
- // https://sentry.io/organizations/parabol/issues/1569570376/?project=107196&query=is%3Aunresolved
- // not sure why this is required addComment and createTask but request replies
- if (!replies) return null
+ const getMaxSortOrder = () => {
+ return replies ? Math.max(0, ...replies.map((reply) => reply.threadSortOrder || 0)) : 0
+ }
return (
<>
- {replies.map((reply) => {
+ {replies?.map((reply) => {
const {__typename, id} = reply
return __typename === 'Task' ? (
{
task={reply}
discussion={discussion}
viewer={viewer}
+ getMaxSortOrder={getMaxSortOrder}
/>
) : (
)
})}
diff --git a/packages/client/components/ThreadedTaskBase.tsx b/packages/client/components/ThreadedTaskBase.tsx
index 193e20cf09e..6185efee089 100644
--- a/packages/client/components/ThreadedTaskBase.tsx
+++ b/packages/client/components/ThreadedTaskBase.tsx
@@ -7,11 +7,11 @@ import {ThreadedTaskBase_task$key} from '~/__generated__/ThreadedTaskBase_task.g
import {ThreadedTaskBase_viewer$key} from '~/__generated__/ThreadedTaskBase_viewer.graphql'
import useAtmosphere from '~/hooks/useAtmosphere'
import {PALETTE} from '~/styles/paletteV3'
+import DiscussionThreadInput from './DiscussionThreadInput'
import {DiscussionThreadables} from './DiscussionThreadList'
import NullableTask from './NullableTask/NullableTask'
import ThreadedAvatarColumn from './ThreadedAvatarColumn'
import ThreadedItemHeaderDescription from './ThreadedItemHeaderDescription'
-import ThreadedItemReply from './ThreadedItemReply'
import ThreadedItemWrapper from './ThreadedItemWrapper'
import ThreadedReplyButton from './ThreadedReplyButton'
@@ -35,15 +35,17 @@ const StyledNullableTask = styled(NullableTask)({
interface Props {
allowedThreadables: DiscussionThreadables[]
task: ThreadedTaskBase_task$key
- children?: ReactNode
+ repliesList?: ReactNode
discussion: ThreadedTaskBase_discussion$key
viewer: ThreadedTaskBase_viewer$key
+ getMaxSortOrder: () => number
}
const ThreadedTaskBase = (props: Props) => {
const {
allowedThreadables,
- children,
+ repliesList,
+ getMaxSortOrder,
discussion: discussionRef,
task: taskRef,
viewer: viewerRef
@@ -51,7 +53,7 @@ const ThreadedTaskBase = (props: Props) => {
const viewer = useFragment(
graphql`
fragment ThreadedTaskBase_viewer on User {
- ...ThreadedItemReply_viewer
+ ...DiscussionThreadInput_viewer
}
`,
viewerRef
@@ -59,7 +61,7 @@ const ThreadedTaskBase = (props: Props) => {
const discussion = useFragment(
graphql`
fragment ThreadedTaskBase_discussion on Discussion {
- ...ThreadedItemReply_discussion
+ ...DiscussionThreadInput_discussion
id
replyingTo {
id
@@ -72,7 +74,6 @@ const ThreadedTaskBase = (props: Props) => {
graphql`
fragment ThreadedTaskBase_task on Task {
...NullableTask_task
- ...ThreadedItemReply_threadable
id
content
createdByUser {
@@ -85,7 +86,7 @@ const ThreadedTaskBase = (props: Props) => {
taskRef
)
const {id: discussionId, replyingTo} = discussion
- const isReply = !!replyingTo
+ const isReply = !repliesList
const {id: taskId, createdByUser, threadParentId} = task
const {picture, preferredName} = createdByUser
const atmosphere = useAtmosphere()
@@ -108,13 +109,16 @@ const ThreadedTaskBase = (props: Props) => {
- {children}
-
+ {repliesList}
+ {replyingTo?.id === task.id && (
+
+ )}
)
diff --git a/packages/client/mutations/CreateTaskMutation.ts b/packages/client/mutations/CreateTaskMutation.ts
index 4e238bd6647..29ef91a1c8f 100644
--- a/packages/client/mutations/CreateTaskMutation.ts
+++ b/packages/client/mutations/CreateTaskMutation.ts
@@ -32,7 +32,6 @@ graphql`
fragment CreateTaskMutation_task on CreateTaskPayload {
task {
...CompleteTaskFrag @relay(mask: false)
- ...ThreadedItemReply_threadable
...ThreadedItem_threadable
discussionId
threadSortOrder
diff --git a/packages/client/mutations/EditCommentingMutation.ts b/packages/client/mutations/EditCommentingMutation.ts
index 058d1b0258c..ba007c2c88f 100644
--- a/packages/client/mutations/EditCommentingMutation.ts
+++ b/packages/client/mutations/EditCommentingMutation.ts
@@ -19,6 +19,11 @@ const mutation = graphql`
mutation EditCommentingMutation($isCommenting: Boolean!, $discussionId: ID!) {
editCommenting(isCommenting: $isCommenting, discussionId: $discussionId) {
...EditCommentingMutation_meeting @relay(mask: false)
+ ... on ErrorPayload {
+ error {
+ message
+ }
+ }
}
}
`