@@ -20,10 +20,9 @@ import {getJsonStream} from '../../../../../core/store/_legacy/history/history/g
20
20
import {
21
21
type CommentBaseCreatePayload ,
22
22
type CommentCreatePayload ,
23
+ CommentDeleteDialog ,
23
24
type CommentInputProps ,
24
25
type CommentReactionOption ,
25
- CommentsListItem ,
26
- type CommentsListItemProps ,
27
26
type CommentThreadItem ,
28
27
type CommentUpdatePayload ,
29
28
useComments ,
@@ -35,8 +34,8 @@ import {getMentionedUsers} from '../form/utils'
35
34
import { type FieldChange , trackFieldChanges } from './helpers/parseTransactions'
36
35
import { EditedAt } from './TaskActivityEditedAt'
37
36
import { TasksActivityCommentInput } from './TasksActivityCommentInput'
37
+ import { TasksActivityCommentItem } from './TasksActivityCommentItem'
38
38
import { TasksActivityCreatedAt } from './TasksActivityCreatedAt'
39
- import { ActivityItem } from './TasksActivityItem'
40
39
import { TasksSubscribers } from './TasksSubscribers'
41
40
42
41
function useActivityLog ( task : TaskDocument ) {
@@ -107,13 +106,6 @@ const VARIANTS: Variants = {
107
106
visible : { opacity : 1 , x : 0 } ,
108
107
}
109
108
110
- const COMMENTS_LIST_ITEM_AVATAR_CONFIG : CommentsListItemProps [ 'avatarConfig' ] = {
111
- parentCommentAvatar : false ,
112
- threadCommentsAvatar : true ,
113
- replyAvatar : true ,
114
- avatarSize : 0 ,
115
- }
116
-
117
109
const MotionStack = styled ( motion ( Stack ) ) ``
118
110
119
111
interface TasksActivityLogProps {
@@ -140,6 +132,10 @@ export function TasksActivityLog(props: TasksActivityLogProps) {
140
132
const { title : workspaceTitle , basePath} = useWorkspace ( )
141
133
142
134
const { comments, mentionOptions, operation, getComment} = useComments ( )
135
+ const [ commentToDeleteId , setCommentToDeleteId ] = useState < string | null > ( null )
136
+ const [ commentDeleteError , setCommentDeleteError ] = useState < Error | null > ( null )
137
+ const [ commentDeleteLoading , setCommentDeleteLoading ] = useState ( false )
138
+
143
139
const loading = comments . loading
144
140
const taskComments = comments . data . open
145
141
@@ -247,13 +243,21 @@ export function TasksActivityLog(props: TasksActivityLogProps) {
247
243
[ operation ] ,
248
244
)
249
245
250
- const handleCommentRemove = useCallback (
251
- ( id : string ) => {
252
- // TODO:
253
- // The remove operation is not optimistic. We should display a
254
- // dialog to confirm the removal and wait for the server to respond
255
- // before removing the comment from the UI. (See `CommentsDocumentInspector`)
256
- operation . remove ( id )
246
+ const handleDeleteCommentStart = useCallback ( ( id : string ) => setCommentToDeleteId ( id ) , [ ] )
247
+ const handleDeleteCommentCancel = useCallback ( ( ) => setCommentToDeleteId ( null ) , [ ] )
248
+
249
+ const handleDeleteCommentConfirm = useCallback (
250
+ async ( id : string ) => {
251
+ try {
252
+ setCommentDeleteLoading ( true )
253
+ setCommentDeleteError ( null )
254
+ await operation . remove ( id )
255
+ setCommentToDeleteId ( null )
256
+ } catch ( err ) {
257
+ setCommentDeleteError ( err )
258
+ } finally {
259
+ setCommentDeleteLoading ( false )
260
+ }
257
261
} ,
258
262
[ operation ] ,
259
263
)
@@ -284,80 +288,94 @@ export function TasksActivityLog(props: TasksActivityLogProps) {
284
288
. sort ( ( a , b ) => new Date ( a . timestamp ) . getTime ( ) - new Date ( b . timestamp ) . getTime ( ) )
285
289
} , [ activityData , taskComments ] )
286
290
291
+ const commentToDeleteIsParent = useMemo ( ( ) => {
292
+ const parent = taskComments . find ( ( c ) => c . parentComment ?. _id === commentToDeleteId )
293
+ const isParent = Boolean ( parent && parent ?. replies ?. length > 0 )
294
+
295
+ return isParent
296
+ } , [ commentToDeleteId , taskComments ] )
297
+
287
298
return (
288
- < Stack space = { 5 } >
289
- < Flex align = "center" >
290
- < Box flex = { 1 } >
291
- < Text size = { 2 } weight = "semibold" >
292
- Activity
293
- </ Text >
294
- </ Box >
295
-
296
- { currentUser ?. id && (
297
- < TasksSubscribers
298
- currentUserId = { currentUser . id }
299
- value = { value }
300
- onChange = { onChange }
301
- path = { path }
302
- />
303
- ) }
304
- </ Flex >
305
-
306
- { loading && < LoadingBlock showText title = "Loading activity" /> }
307
-
308
- < AnimatePresence >
309
- { ! loading && (
310
- < MotionStack animate = "visible" initial = "hidden" space = { 3 } variants = { VARIANTS } >
311
- { value . createdByUser && (
312
- < Stack paddingBottom = { 1 } >
313
- < TasksActivityCreatedAt createdAt = { value . createdByUser } authorId = { value . authorId } />
314
- </ Stack >
315
- ) }
316
-
317
- { currentUser && (
318
- < CurrentWorkspaceProvider >
319
- < Stack space = { 4 } marginTop = { 1 } >
320
- { activity . map ( ( item ) => {
321
- if ( item . _type === 'activity' ) {
322
- return < EditedAt key = { item . timestamp } activity = { item . payload } />
323
- }
324
- return (
325
- < ActivityItem
326
- key = { item . payload . parentComment . _id }
327
- userId = { item . payload . parentComment . authorId }
328
- >
329
- < CommentsListItem
330
- avatarConfig = { COMMENTS_LIST_ITEM_AVATAR_CONFIG }
331
- canReply
299
+ < >
300
+ { commentToDeleteId && (
301
+ < CommentDeleteDialog
302
+ commentId = { commentToDeleteId }
303
+ error = { commentDeleteError }
304
+ isParent = { commentToDeleteIsParent }
305
+ loading = { commentDeleteLoading }
306
+ onClose = { handleDeleteCommentCancel }
307
+ onConfirm = { handleDeleteCommentConfirm }
308
+ />
309
+ ) }
310
+
311
+ < Stack space = { 5 } >
312
+ < Flex align = "center" >
313
+ < Box flex = { 1 } >
314
+ < Text size = { 2 } weight = "semibold" >
315
+ Activity
316
+ </ Text >
317
+ </ Box >
318
+
319
+ { currentUser ?. id && (
320
+ < TasksSubscribers
321
+ currentUserId = { currentUser . id }
322
+ value = { value }
323
+ onChange = { onChange }
324
+ path = { path }
325
+ />
326
+ ) }
327
+ </ Flex >
328
+
329
+ { loading && < LoadingBlock showText title = "Loading activity" /> }
330
+
331
+ < AnimatePresence >
332
+ { ! loading && (
333
+ < MotionStack animate = "visible" initial = "hidden" space = { 3 } variants = { VARIANTS } >
334
+ { value . createdByUser && (
335
+ < Stack paddingBottom = { 1 } >
336
+ < TasksActivityCreatedAt
337
+ createdAt = { value . createdByUser }
338
+ authorId = { value . authorId }
339
+ />
340
+ </ Stack >
341
+ ) }
342
+
343
+ { currentUser && (
344
+ < CurrentWorkspaceProvider >
345
+ < Stack space = { 4 } marginTop = { 1 } >
346
+ { activity . map ( ( item ) => {
347
+ if ( item . _type === 'activity' ) {
348
+ return < EditedAt key = { item . timestamp } activity = { item . payload } />
349
+ }
350
+
351
+ return (
352
+ < TasksActivityCommentItem
332
353
currentUser = { currentUser }
333
- innerPadding = { 1 }
334
- isSelected = { false }
335
354
key = { item . payload . parentComment . _id }
336
355
mentionOptions = { mentionOptions }
337
- mode = "default" // TODO: set dynamic mode?
338
356
onCreateRetry = { handleCommentCreateRetry }
339
- onDelete = { handleCommentRemove }
357
+ onDelete = { handleDeleteCommentStart }
340
358
onEdit = { handleCommentEdit }
341
359
onReactionSelect = { handleCommentReact }
342
360
onReply = { handleCommentReply }
343
361
parentComment = { item . payload . parentComment }
344
362
replies = { item . payload . replies }
345
363
/>
346
- </ ActivityItem >
347
- )
348
- } ) }
349
-
350
- < TasksActivityCommentInput
351
- currentUser = { currentUser }
352
- mentionOptions = { mentionOptions }
353
- onSubmit = { handleCommentCreate }
354
- / >
355
- </ Stack >
356
- </ CurrentWorkspaceProvider >
357
- ) }
358
- </ MotionStack >
359
- ) }
360
- </ AnimatePresence >
361
- </ Stack >
364
+ )
365
+ } ) }
366
+
367
+ < TasksActivityCommentInput
368
+ currentUser = { currentUser }
369
+ mentionOptions = { mentionOptions }
370
+ onSubmit = { handleCommentCreate }
371
+ />
372
+ </ Stack >
373
+ </ CurrentWorkspaceProvider >
374
+ ) }
375
+ </ MotionStack >
376
+ ) }
377
+ </ AnimatePresence >
378
+ </ Stack >
379
+ </ >
362
380
)
363
381
}
0 commit comments