Skip to content

Commit 6635d72

Browse files
authoredMar 20, 2024
fix(tasks): update info passed to the tasks comments notification context (#6087)
1 parent f89111c commit 6635d72

File tree

3 files changed

+118
-109
lines changed

3 files changed

+118
-109
lines changed
 

‎packages/sanity/src/tasks/src/tasks/components/activity/TasksActivityLog.tsx

+35-105
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
import {Box, Flex, Stack, Text} from '@sanity/ui'
22
import {uuid} from '@sanity/uuid'
33
import {AnimatePresence, motion, type Variants} from 'framer-motion'
4-
import {useCallback, useEffect, useMemo, useState} from 'react'
4+
import {useCallback, useMemo, useState} from 'react'
55
import {
66
type FormPatch,
7-
getPublishedId,
87
LoadingBlock,
98
type PatchEvent,
109
type Path,
1110
set,
12-
type TransactionLogEventWithEffects,
13-
useClient,
1411
useCurrentUser,
1512
useTranslation,
1613
useWorkspace,
1714
} from 'sanity'
1815
import styled from 'styled-components'
1916

20-
import {getJsonStream} from '../../../../../core/store/_legacy/history/history/getJsonStream'
2117
import {
2218
type CommentBaseCreatePayload,
2319
type CommentCreatePayload,
@@ -29,78 +25,15 @@ import {
2925
useComments,
3026
} from '../../../../../structure/comments'
3127
import {tasksLocaleNamespace} from '../../../../i18n'
32-
import {API_VERSION} from '../../constants/API_VERSION'
3328
import {type TaskDocument} from '../../types'
34-
import {CurrentWorkspaceProvider} from '../form/CurrentWorkspaceProvider'
3529
import {getMentionedUsers} from '../form/utils'
36-
import {type FieldChange, trackFieldChanges} from './helpers/parseTransactions'
30+
import {type FieldChange} from './helpers/parseTransactions'
3731
import {EditedAt} from './TaskActivityEditedAt'
3832
import {TasksActivityCommentInput} from './TasksActivityCommentInput'
3933
import {TasksActivityCommentItem} from './TasksActivityCommentItem'
4034
import {TasksActivityCreatedAt} from './TasksActivityCreatedAt'
4135
import {TasksSubscribers} from './TasksSubscribers'
4236

43-
function useActivityLog(task: TaskDocument) {
44-
const [changes, setChanges] = useState<FieldChange[]>([])
45-
const client = useClient({apiVersion: API_VERSION})
46-
const {dataset, token} = client.config()
47-
48-
const queryParams = `tag=sanity.studio.tasks.history&effectFormat=mendoza&excludeContent=true&includeIdentifiedDocumentsOnly=true&reverse=true`
49-
const transactionsUrl = client.getUrl(
50-
`/data/history/${dataset}/transactions/${getPublishedId(task._id)}?${queryParams}`,
51-
)
52-
53-
const fetchAndParse = useCallback(
54-
async (newestTaskDocument: TaskDocument) => {
55-
try {
56-
const transactions: TransactionLogEventWithEffects[] = []
57-
58-
const stream = await getJsonStream(transactionsUrl, token)
59-
const reader = stream.getReader()
60-
let result
61-
for (;;) {
62-
result = await reader.read()
63-
if (result.done) {
64-
break
65-
}
66-
if ('error' in result.value) {
67-
throw new Error(result.value.error.description || result.value.error.type)
68-
}
69-
transactions.push(result.value)
70-
}
71-
72-
const fieldsToTrack: (keyof Omit<TaskDocument, '_rev'>)[] = [
73-
'createdByUser',
74-
'title',
75-
'description',
76-
'dueBy',
77-
'assignedTo',
78-
'status',
79-
'target',
80-
]
81-
82-
const parsedChanges = await trackFieldChanges(
83-
newestTaskDocument,
84-
[...transactions],
85-
fieldsToTrack,
86-
)
87-
88-
setChanges(parsedChanges)
89-
} catch (error) {
90-
console.error('Failed to fetch and parse activity log', error)
91-
}
92-
},
93-
[transactionsUrl, token],
94-
)
95-
96-
useEffect(() => {
97-
fetchAndParse(task)
98-
// Task is updated on every change, wait until the revision changes to update the activity log.
99-
// eslint-disable-next-line react-hooks/exhaustive-deps
100-
}, [fetchAndParse, task._rev])
101-
return {changes}
102-
}
103-
10437
const EMPTY_ARRAY: [] = []
10538

10639
const VARIANTS: Variants = {
@@ -114,6 +47,7 @@ interface TasksActivityLogProps {
11447
onChange: (patch: FormPatch | PatchEvent | FormPatch[]) => void
11548
path?: Path
11649
value: TaskDocument
50+
activityData: FieldChange[]
11751
}
11852

11953
type Activity =
@@ -129,21 +63,21 @@ type Activity =
12963
}
13064

13165
export function TasksActivityLog(props: TasksActivityLogProps) {
132-
const {value, onChange, path} = props
66+
const {value, onChange, path, activityData = []} = props
13367
const currentUser = useCurrentUser()
134-
const {title: workspaceTitle, basePath} = useWorkspace()
13568

69+
const {title: workspaceTitle, basePath} = useWorkspace()
13670
const {comments, mentionOptions, operation, getComment} = useComments()
13771
const [commentToDeleteId, setCommentToDeleteId] = useState<string | null>(null)
13872
const [commentDeleteError, setCommentDeleteError] = useState<Error | null>(null)
13973
const [commentDeleteLoading, setCommentDeleteLoading] = useState(false)
14074

14175
const loading = comments.loading
14276
const taskComments = comments.data.open
143-
14477
const handleGetNotificationValue = useCallback(
14578
(message: CommentInputProps['value'], commentId: string) => {
146-
const studioUrl = new URL(`${window.location.origin}${basePath}/`)
79+
const studioUrl = new URL(`${window.location.origin}${basePath ? `${basePath}/` : ''}`)
80+
14781
studioUrl.searchParams.set('sidebar', 'tasks')
14882
studioUrl.searchParams.set('selectedTask', value?._id)
14983
studioUrl.searchParams.set('viewMode', 'edit')
@@ -271,8 +205,6 @@ export function TasksActivityLog(props: TasksActivityLogProps) {
271205
[operation],
272206
)
273207

274-
const activityData = useActivityLog(value).changes
275-
276208
const activity: Activity[] = useMemo(() => {
277209
const taskActivity: Activity[] = activityData.map((item) => ({
278210
_type: 'activity' as const,
@@ -344,36 +276,34 @@ export function TasksActivityLog(props: TasksActivityLogProps) {
344276
)}
345277

346278
{currentUser && (
347-
<CurrentWorkspaceProvider>
348-
<Stack space={4} marginTop={1}>
349-
{activity.map((item) => {
350-
if (item._type === 'activity') {
351-
return <EditedAt key={item.timestamp} activity={item.payload} />
352-
}
353-
354-
return (
355-
<TasksActivityCommentItem
356-
currentUser={currentUser}
357-
key={item.payload.parentComment._id}
358-
mentionOptions={mentionOptions}
359-
onCreateRetry={handleCommentCreateRetry}
360-
onDelete={handleDeleteCommentStart}
361-
onEdit={handleCommentEdit}
362-
onReactionSelect={handleCommentReact}
363-
onReply={handleCommentReply}
364-
parentComment={item.payload.parentComment}
365-
replies={item.payload.replies}
366-
/>
367-
)
368-
})}
369-
370-
<TasksActivityCommentInput
371-
currentUser={currentUser}
372-
mentionOptions={mentionOptions}
373-
onSubmit={handleCommentCreate}
374-
/>
375-
</Stack>
376-
</CurrentWorkspaceProvider>
279+
<Stack space={4} marginTop={1}>
280+
{activity.map((item) => {
281+
if (item._type === 'activity') {
282+
return <EditedAt key={item.timestamp} activity={item.payload} />
283+
}
284+
285+
return (
286+
<TasksActivityCommentItem
287+
currentUser={currentUser}
288+
key={item.payload.parentComment._id}
289+
mentionOptions={mentionOptions}
290+
onCreateRetry={handleCommentCreateRetry}
291+
onDelete={handleDeleteCommentStart}
292+
onEdit={handleCommentEdit}
293+
onReactionSelect={handleCommentReact}
294+
onReply={handleCommentReply}
295+
parentComment={item.payload.parentComment}
296+
replies={item.payload.replies}
297+
/>
298+
)
299+
})}
300+
301+
<TasksActivityCommentInput
302+
currentUser={currentUser}
303+
mentionOptions={mentionOptions}
304+
onSubmit={handleCommentCreate}
305+
/>
306+
</Stack>
377307
)}
378308
</MotionStack>
379309
)}

‎packages/sanity/src/tasks/src/tasks/components/form/tasksFormBuilder/FormEdit.tsx

+13-4
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ import {CommentsProvider} from '../../../../../../structure/comments'
2121
import {MenuButton, MenuItem} from '../../../../../../ui-components'
2222
import {tasksLocaleNamespace} from '../../../../../i18n'
2323
import {useTasksNavigation} from '../../../context'
24+
import {useActivityLog} from '../../../hooks/useActivityLog'
2425
import {useRemoveTask} from '../../../hooks/useRemoveTask'
2526
import {type TaskDocument} from '../../../types'
2627
import {TasksActivityLog} from '../../activity'
28+
import {CurrentWorkspaceProvider} from '../CurrentWorkspaceProvider'
2729
import {AssigneeEditFormField} from '../fields/assignee'
2830
import {DateEditFormField} from '../fields/DateEditFormField'
2931
import {StatusSelector} from '../fields/StatusSelector'
@@ -95,6 +97,7 @@ function FormEditInner(props: ObjectInputProps) {
9597
const value = props.value as TaskDocument
9698
const currentUser = useCurrentUser()
9799
const {t} = useTranslation(tasksLocaleNamespace)
100+
const activityData = useActivityLog(value).changes
98101
const handleChangeAndSubscribe = useCallback(
99102
(patch: FormPatch | PatchEvent | FormPatch[]) => {
100103
const subscribers = value.subscribers || []
@@ -155,16 +158,22 @@ function FormEditInner(props: ObjectInputProps) {
155158
</Card>
156159

157160
{props.renderDefault(props)}
158-
159161
<CommentsProvider
160162
documentId={value._id}
161163
documentType="tasks.task"
162164
sortOrder="asc"
163165
type="task"
164166
>
165-
<Card borderTop paddingTop={4} marginTop={4} paddingBottom={6}>
166-
<TasksActivityLog value={value} onChange={props.onChange} path={['subscribers']} />
167-
</Card>
167+
<CurrentWorkspaceProvider>
168+
<Card borderTop paddingTop={4} marginTop={4} paddingBottom={6}>
169+
<TasksActivityLog
170+
value={value}
171+
onChange={props.onChange}
172+
path={['subscribers']}
173+
activityData={activityData}
174+
/>
175+
</Card>
176+
</CurrentWorkspaceProvider>
168177
</CommentsProvider>
169178
</>
170179
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import {useCallback, useEffect, useState} from 'react'
2+
import {getPublishedId, type TransactionLogEventWithEffects, useClient} from 'sanity'
3+
4+
import {getJsonStream} from '../../../../core/store/_legacy/history/history/getJsonStream'
5+
import {type FieldChange, trackFieldChanges} from '../components/activity/helpers/parseTransactions'
6+
import {API_VERSION} from '../constants/API_VERSION'
7+
import {type TaskDocument} from '../types'
8+
9+
export function useActivityLog(task: TaskDocument): {
10+
changes: FieldChange[]
11+
} {
12+
const [changes, setChanges] = useState<FieldChange[]>([])
13+
const client = useClient({apiVersion: API_VERSION})
14+
const {dataset, token} = client.config()
15+
16+
const queryParams = `tag=sanity.studio.tasks.history&effectFormat=mendoza&excludeContent=true&includeIdentifiedDocumentsOnly=true&reverse=true`
17+
const transactionsUrl = client.getUrl(
18+
`/data/history/${dataset}/transactions/${getPublishedId(task._id)}?${queryParams}`,
19+
)
20+
21+
const fetchAndParse = useCallback(
22+
async (newestTaskDocument: TaskDocument) => {
23+
try {
24+
const transactions: TransactionLogEventWithEffects[] = []
25+
26+
const stream = await getJsonStream(transactionsUrl, token)
27+
const reader = stream.getReader()
28+
let result
29+
for (;;) {
30+
result = await reader.read()
31+
if (result.done) {
32+
break
33+
}
34+
if ('error' in result.value) {
35+
throw new Error(result.value.error.description || result.value.error.type)
36+
}
37+
transactions.push(result.value)
38+
}
39+
40+
const fieldsToTrack: (keyof Omit<TaskDocument, '_rev'>)[] = [
41+
'createdByUser',
42+
'title',
43+
'description',
44+
'dueBy',
45+
'assignedTo',
46+
'status',
47+
'target',
48+
]
49+
50+
const parsedChanges = await trackFieldChanges(
51+
newestTaskDocument,
52+
[...transactions],
53+
fieldsToTrack,
54+
)
55+
56+
setChanges(parsedChanges)
57+
} catch (error) {
58+
console.error('Failed to fetch and parse activity log', error)
59+
}
60+
},
61+
[transactionsUrl, token],
62+
)
63+
64+
useEffect(() => {
65+
fetchAndParse(task)
66+
// Task is updated on every change, wait until the revision changes to update the activity log.
67+
// eslint-disable-next-line react-hooks/exhaustive-deps
68+
}, [fetchAndParse, task._rev])
69+
return {changes}
70+
}

0 commit comments

Comments
 (0)
Please sign in to comment.