Skip to content

Commit

Permalink
feat: add to notification context (#5041)
Browse files Browse the repository at this point in the history
  • Loading branch information
hermanwikner authored and skogsmaskin committed Oct 24, 2023
1 parent 2b31d28 commit 3576c63
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,64 @@ const CommentsProviderInner = memo(function CommentsProviderInner(
const currentUser = useCurrentUser()
const {name: workspaceName, dataset, projectId} = useWorkspace()

const threadItemsByStatus: ThreadItemsByStatus = useMemo(() => {
if (!schemaType || !currentUser) return EMPTY_COMMENTS_DATA
// Since we only make one query to get all comments using the order `_createdAt desc` – we
// can't know for sure that the comments added through the real time listener will be in the
// correct order. In order to avoid that comments are out of order, we make an additional
// sort here. The comments can be out of order if e.g a comment creation fails and is retried
// later.
const sorted = orderBy(data, ['_createdAt'], ['desc'])

const items = buildCommentThreadItems({
comments: sorted,
schemaType,
currentUser,
documentValue,
})

return {
open: items.filter((item) => item.parentComment.status === 'open'),
resolved: items.filter((item) => item.parentComment.status === 'resolved'),
}
}, [currentUser, data, documentValue, schemaType])

const getThreadLength = useCallback(
(threadId: string) => {
return threadItemsByStatus.open.filter((item) => item.threadId === threadId).length
},
[threadItemsByStatus.open],
)

const getComment = useCallback((id: string) => data?.find((c) => c._id === id), [data])

const getCommentPath = useCallback(
(id: string) => {
const comment = getComment(id)
if (!comment) return null

return comment.target.path.field
},
[getComment],
)

const handleSetSelectedPath = useCallback((nextPath: SelectedPath) => {
// If the path is being set to null, immediately set the selected path to null.
if (nextPath === null) {
setSelectedPath(null)
return
}

// Sometimes, a path is cleared (set to null) but at the same time a new path is set.
// In this case, we want to make sure that the selected path is set to the new path
// and not the cleared path. Therefore, we set the selected path in a timeout to make
// sure that the selected path is set after the cleared path.
// todo: can this be done in a better way?
setTimeout(() => {
setSelectedPath(nextPath)
})
}, [])

const handleOnCreate = useCallback(
async (payload: CommentPostPayload) => {
// If the comment we try to create already exists in the local state and has
Expand Down Expand Up @@ -233,6 +291,7 @@ const CommentsProviderInner = memo(function CommentsProviderInner(
projectId,
schemaType,
workspace: workspaceName,
getThreadLength,
// The following callbacks runs when the comment operations are executed.
// They are used to update the local state of the comments immediately after
// a comment operation has been executed. This is done to avoid waiting for
Expand All @@ -253,6 +312,7 @@ const CommentsProviderInner = memo(function CommentsProviderInner(
projectId,
schemaType,
workspaceName,
getThreadLength,
handleOnCreate,
handleOnCreateError,
handleOnEdit,
Expand All @@ -261,57 +321,6 @@ const CommentsProviderInner = memo(function CommentsProviderInner(
),
)

const threadItemsByStatus: ThreadItemsByStatus = useMemo(() => {
if (!schemaType || !currentUser) return EMPTY_COMMENTS_DATA
// Since we only make one query to get all comments using the order `_createdAt desc` – we
// can't know for sure that the comments added through the real time listener will be in the
// correct order. In order to avoid that comments are out of order, we make an additional
// sort here. The comments can be out of order if e.g a comment creation fails and is retried
// later.
const sorted = orderBy(data, ['_createdAt'], ['desc'])

const items = buildCommentThreadItems({
comments: sorted,
schemaType,
currentUser,
documentValue,
})

return {
open: items.filter((item) => item.parentComment.status === 'open'),
resolved: items.filter((item) => item.parentComment.status === 'resolved'),
}
}, [currentUser, data, documentValue, schemaType])

const getComment = useCallback((id: string) => data?.find((c) => c._id === id), [data])

const getCommentPath = useCallback(
(id: string) => {
const comment = getComment(id)
if (!comment) return null

return comment.target.path.field
},
[getComment],
)

const handleSetSelectedPath = useCallback((nextPath: SelectedPath) => {
// If the path is being set to null, immediately set the selected path to null.
if (nextPath === null) {
setSelectedPath(null)
return
}

// Sometimes, a path is cleared (set to null) but at the same time a new path is set.
// In this case, we want to make sure that the selected path is set to the new path
// and not the cleared path. Therefore, we set the selected path in a timeout to make
// sure that the selected path is set after the cleared path.
// todo: can this be done in a better way?
setTimeout(() => {
setSelectedPath(nextPath)
})
}, [])

const ctxValue = useMemo(
() =>
({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {uuid} from '@sanity/uuid'
import {CurrentUser, SchemaType} from '@sanity/types'
import {SanityClient} from '@sanity/client'
import {
CommentContext,
CommentCreatePayload,
CommentEditPayload,
CommentOperations,
Expand All @@ -27,6 +28,8 @@ export interface CommentOperationsHookOptions {
schemaType: SchemaType | undefined
workspace: string

getThreadLength?: (threadId: string) => number

onCreate?: (comment: CommentPostPayload) => void
onCreateError: (id: string, error: Error) => void
onEdit?: (id: string, comment: CommentEditPayload) => void
Expand All @@ -43,6 +46,7 @@ export function useCommentOperations(
dataset,
documentId,
documentType,
getThreadLength,
onCreate,
onCreateError,
onEdit,
Expand Down Expand Up @@ -74,6 +78,23 @@ export function useCommentOperations(
// create the comment.
const commentId = comment?.id || uuid()

// Get the current thread length of the thread the comment is being added to.
// We add 1 to the length to account for the comment being added.
const currentThreadLength = (getThreadLength?.(comment.threadId) || 0) + 1

const {
documentTitle = '',
url = '',
workspaceTitle = '',
} = getNotificationValue({commentId}) || {}

const notification: CommentContext['notification'] = {
currentThreadLength,
documentTitle,
url,
workspaceTitle,
}

const nextComment = {
_id: commentId,
_type: 'comment',
Expand All @@ -88,7 +109,7 @@ export function useCommentOperations(
payload: {
workspace,
},
notification: getNotificationValue({commentId}),
notification,
tool: activeTool?.name || '',
},
target: {
Expand Down Expand Up @@ -129,6 +150,7 @@ export function useCommentOperations(
documentId,
documentType,
getNotificationValue,
getThreadLength,
onCreate,
onCreateError,
projectId,
Expand Down
1 change: 1 addition & 0 deletions packages/sanity/src/desk/comments/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export interface CommentContext {
documentTitle: string
url: string
workspaceTitle: string
currentThreadLength?: number
}
}

Expand Down

0 comments on commit 3576c63

Please sign in to comment.