1- import { Fragment , useMemo , useState } from 'react' ;
1+ import { Fragment , useCallback , useMemo , useState } from 'react' ;
22import styled from '@emotion/styled' ;
33
44import { Tag } from '@sentry/scraps/badge' ;
55import { Container , Flex } from '@sentry/scraps/layout' ;
66import { Heading , Text } from '@sentry/scraps/text' ;
77
8+ import { bulkUpdate } from 'sentry/actionCreators/group' ;
9+ import { openConfirmModal } from 'sentry/components/confirm' ;
810import { Button } from 'sentry/components/core/button' ;
911import { ButtonBar } from 'sentry/components/core/button/buttonBar' ;
1012import { Checkbox } from 'sentry/components/core/checkbox' ;
@@ -41,8 +43,10 @@ import {
4143import { t , tn } from 'sentry/locale' ;
4244import { space } from 'sentry/styles/space' ;
4345import type { Group } from 'sentry/types/group' ;
46+ import { GroupStatus , GroupSubstatus } from 'sentry/types/group' ;
4447import { getMessage , getTitle } from 'sentry/utils/events' ;
4548import { useApiQuery } from 'sentry/utils/queryClient' ;
49+ import useApi from 'sentry/utils/useApi' ;
4650import useCopyToClipboard from 'sentry/utils/useCopyToClipboard' ;
4751import useOrganization from 'sentry/utils/useOrganization' ;
4852import usePageFilters from 'sentry/utils/usePageFilters' ;
@@ -362,7 +366,9 @@ function ClusterCard({
362366 onTagClick ?: ( tag : string ) => void ;
363367 selectedTags ?: Set < string > ;
364368} ) {
369+ const api = useApi ( ) ;
365370 const organization = useOrganization ( ) ;
371+ const { selection} = usePageFilters ( ) ;
366372 const [ showDescription , setShowDescription ] = useState ( false ) ;
367373 const clusterStats = useClusterStats ( cluster . group_ids ) ;
368374 const { copy} = useCopyToClipboard ( ) ;
@@ -380,9 +386,64 @@ function ClusterCard({
380386 copy ( formatClusterInfoForClipboard ( cluster ) ) ;
381387 } ;
382388
389+ const handleResolve = useCallback ( ( ) => {
390+ openConfirmModal ( {
391+ header : t ( 'Resolve All Issues in Cluster' ) ,
392+ message : t (
393+ 'Are you sure you want to resolve all %s issues in this cluster?.' ,
394+ cluster . group_ids . length
395+ ) ,
396+ confirmText : t ( 'Resolve All' ) ,
397+ onConfirm : ( ) => {
398+ bulkUpdate (
399+ api ,
400+ {
401+ orgId : organization . slug ,
402+ itemIds : cluster . group_ids . map ( String ) ,
403+ data : { status : GroupStatus . RESOLVED } ,
404+ project : selection . projects ,
405+ environment : selection . environments ,
406+ ...selection . datetime ,
407+ } ,
408+ { }
409+ ) ;
410+ } ,
411+ } ) ;
412+ } , [ api , cluster . group_ids , organization . slug , selection ] ) ;
413+
414+ const handleArchive = useCallback ( ( ) => {
415+ openConfirmModal ( {
416+ header : t ( 'Archive All Issues in Cluster' ) ,
417+ message : t (
418+ 'Are you sure you want to archive all %s issues in this cluster?.' ,
419+ cluster . group_ids . length
420+ ) ,
421+ confirmText : t ( 'Archive All' ) ,
422+ onConfirm : ( ) => {
423+ bulkUpdate (
424+ api ,
425+ {
426+ orgId : organization . slug ,
427+ itemIds : cluster . group_ids . map ( String ) ,
428+ data : {
429+ status : GroupStatus . IGNORED ,
430+ statusDetails : { } ,
431+ substatus : GroupSubstatus . ARCHIVED_UNTIL_ESCALATING ,
432+ } ,
433+ project : selection . projects ,
434+ environment : selection . environments ,
435+ ...selection . datetime ,
436+ } ,
437+ { }
438+ ) ;
439+ } ,
440+ } ) ;
441+ } , [ api , cluster . group_ids , organization . slug , selection ] ) ;
442+
443+ const handleDismiss = ( ) => { } ;
444+
383445 return (
384446 < CardContainer >
385- { /* Zone 1: Title + Description (Primary Focus) */ }
386447 < CardHeader >
387448 < ClusterTitle > { renderWithInlineCode ( cluster . title ) } </ ClusterTitle >
388449 < ClusterTags
@@ -403,7 +464,6 @@ function ClusterCard({
403464 ) }
404465 </ CardHeader >
405466
406- { /* Zone 2: Stats (Secondary Context) */ }
407467 < ClusterStatsBar >
408468 { cluster . fixability_score !== null && cluster . fixability_score !== undefined && (
409469 < StatItem >
@@ -470,7 +530,6 @@ function ClusterCard({
470530 ) }
471531 </ ClusterStatsBar >
472532
473- { /* Zone 3: Nested Issues (Detail Content) */ }
474533 < IssuesSection >
475534 < IssuesSectionHeader >
476535 < Text size = "sm" bold uppercase >
@@ -482,7 +541,6 @@ function ClusterCard({
482541 </ IssuesList >
483542 </ IssuesSection >
484543
485- { /* Zone 4: Actions (Tertiary) */ }
486544 < CardFooter >
487545 < ButtonBar merged gap = "0" >
488546 < SeerButton
@@ -525,18 +583,18 @@ function ClusterCard({
525583 items = { [
526584 {
527585 key : 'resolve' ,
528- label : t ( 'Resolve' ) ,
529- onAction : ( ) => { } ,
586+ label : t ( 'Resolve All ' ) ,
587+ onAction : handleResolve ,
530588 } ,
531589 {
532590 key : 'archive' ,
533- label : t ( 'Archive' ) ,
534- onAction : ( ) => { } ,
591+ label : t ( 'Archive All ' ) ,
592+ onAction : handleArchive ,
535593 } ,
536594 {
537595 key : 'dismiss' ,
538596 label : t ( 'Dismiss' ) ,
539- onAction : ( ) => { } ,
597+ onAction : handleDismiss ,
540598 } ,
541599 ] }
542600 trigger = { triggerProps => (
0 commit comments