1- import { Fragment , useEffect , useState } from 'react' ;
1+ import { useEffect , useState } from 'react' ;
22import styled from '@emotion/styled' ;
33import { Location } from 'history' ;
4+ import debounce from 'lodash/debounce' ;
45
56import { Client } from 'app/api' ;
67import Button from 'app/components/button' ;
@@ -10,6 +11,7 @@ import ListItem from 'app/components/list/listItem';
1011import LoadingError from 'app/components/loadingError' ;
1112import LoadingIndicator from 'app/components/loadingIndicator' ;
1213import Pagination from 'app/components/pagination' ;
14+ import { DEFAULT_DEBOUNCE_DURATION } from 'app/constants' ;
1315import { IconFlag } from 'app/icons' ;
1416import { t , tct } from 'app/locale' ;
1517import space from 'app/styles/space' ;
@@ -30,10 +32,16 @@ type Props = {
3032 api : Client ;
3133} ;
3234
35+ type ErrorCode = 'not_hierarchical' | 'no_events' | 'merged_issues' | 'missing_feature' ;
36+
3337type Error = {
3438 status : number ;
3539 responseJSON ?: {
36- detail : string ;
40+ detail : {
41+ code : ErrorCode ;
42+ extra : Record < string , any > ;
43+ message : string ;
44+ } ;
3745 } ;
3846} ;
3947
@@ -76,6 +84,10 @@ function Grouping({api, groupId, location}: Props) {
7684 fetchGroupingLevelDetails ( ) ;
7785 } , [ activeGroupingLevel , location . query ] ) ;
7886
87+ const handleSetActiveGroupingLevel = debounce ( ( groupingLevelId : string ) => {
88+ setActiveGroupingLevel ( Number ( groupingLevelId ) ) ;
89+ } , DEFAULT_DEBOUNCE_DURATION ) ;
90+
7991 async function fetchGroupingLevels ( ) {
8092 setIsLoading ( true ) ;
8193 setError ( undefined ) ;
@@ -135,19 +147,23 @@ function Grouping({api, groupId, location}: Props) {
135147
136148 if ( error ) {
137149 if ( error . status === 403 && error . responseJSON ?. detail ) {
150+ const { message, code} = error . responseJSON . detail ;
138151 return (
139152 < Wrapper >
140153 < EmptyMessage
154+ size = "large"
141155 icon = { < IconFlag size = "xl" /> }
142156 action = {
143- < Button
144- to = { `/organizations/sentry/issues/${ groupId } /merged/?${ location . search } ` }
145- >
146- { t ( 'Unmerge issue' ) }
147- </ Button >
157+ code === 'merged_issues' ? (
158+ < Button
159+ to = { `/organizations/sentry/issues/${ groupId } /merged/?${ location . search } ` }
160+ >
161+ { t ( 'Unmerge issue' ) }
162+ </ Button >
163+ ) : undefined
148164 }
149165 >
150- { error . responseJSON . detail }
166+ { message }
151167 </ EmptyMessage >
152168 </ Wrapper >
153169 ) ;
@@ -169,10 +185,6 @@ function Grouping({api, groupId, location}: Props) {
169185 ) ;
170186 }
171187
172- //function handleRegroup() {
173- // Todo(Priscila): Implement it
174- //}
175-
176188 const links = parseLinkHeader ( pagination ) ;
177189 const hasMore = links . previous ?. results || links . next ?. results ;
178190
@@ -196,59 +208,37 @@ function Grouping({api, groupId, location}: Props) {
196208 return value === 0 ? t ( 'Automatically grouped' ) : t ( 'Level %s' , value ) ;
197209 } }
198210 value = { activeGroupingLevel ?? 0 }
199- onChange = { groupingLevelId =>
200- setActiveGroupingLevel ( Number ( groupingLevelId ) )
201- }
211+ onChange = { handleSetActiveGroupingLevel }
202212 />
203213 </ StyledListItem >
204214 < StyledListItem >
205- { isGroupingLevelDetailsLoading ? (
206- < div >
207- < div > { t ( 'What happens to this issue' ) } </ div >
208- < LoadingIndicator mini />
209- </ div >
210- ) : (
211- < Fragment >
212- < div >
213- { t ( 'What happens to this issue' ) }
214- < WhatHappensDescription >
215- { tct (
216- `This issue will be deleted and [quantity] new issues will be created.` ,
217- {
218- quantity : hasMore
219- ? `${ activeGroupingLevelDetails . length } +`
220- : activeGroupingLevelDetails . length ,
221- }
222- ) }
223- </ WhatHappensDescription >
224- </ div >
225- < NewIssues >
226- { activeGroupingLevelDetails . map ( activeGroupingLevelDetail => (
227- < NewIssue
228- key = { activeGroupingLevelDetail . hash }
229- sampleEvent = { activeGroupingLevelDetail . latestEvent }
230- eventCount = { activeGroupingLevelDetail . eventCount }
231- />
232- ) ) }
233- </ NewIssues >
234- </ Fragment >
235- ) }
215+ < div >
216+ { t ( 'What happens to this issue' ) }
217+ < WhatHappensDescription >
218+ { tct (
219+ `This issue will be deleted and [quantity] new issues will be created.` ,
220+ {
221+ quantity : hasMore
222+ ? `${ activeGroupingLevelDetails . length } +`
223+ : activeGroupingLevelDetails . length ,
224+ }
225+ ) }
226+ </ WhatHappensDescription >
227+ </ div >
228+ < NewIssues >
229+ { activeGroupingLevelDetails . map ( ( { hash, latestEvent, eventCount} ) => (
230+ < NewIssue
231+ key = { hash }
232+ sampleEvent = { latestEvent }
233+ eventCount = { eventCount }
234+ isReloading = { isGroupingLevelDetailsLoading }
235+ />
236+ ) ) }
237+ </ NewIssues >
236238 </ StyledListItem >
237239 </ StyledList >
238240 < Pagination pageLinks = { pagination } />
239241 </ div >
240- < Action >
241- < Button
242- priority = "primary"
243- disabled = {
244- isGroupingLevelDetailsLoading ||
245- ! activeGroupingLevel ||
246- activeGroupingLevel === 0
247- }
248- >
249- { t ( 'Regroup' ) }
250- </ Button >
251- </ Action >
252242 </ Wrapper >
253243 ) ;
254244}
@@ -258,6 +248,7 @@ export default withApi(Grouping);
258248const Wrapper = styled ( 'div' ) `
259249 flex: 1;
260250 display: grid;
251+ align-content: flex-start;
261252 background: ${ p => p . theme . background } ;
262253 grid-gap: ${ space ( 2 ) } ;
263254 margin: -${ space ( 3 ) } -${ space ( 4 ) } ;
@@ -268,21 +259,13 @@ const Description = styled('p')`
268259 margin-bottom: ${ space ( 0.5 ) } ;
269260` ;
270261
271- const Action = styled ( 'div' ) `
272- border-top: 1px solid ${ p => p . theme . border } ;
273- display: flex;
274- justify-content: flex-end;
275- padding: ${ space ( 2 ) } 0 0;
276- margin-top: ${ space ( 1 ) } ;
277- ` ;
278-
279262const StyledListItem = styled ( ListItem ) `
280263 display: grid;
281264 grid-gap: ${ space ( 1.5 ) } ;
282265` ;
283266
284267const StyledRangeSlider = styled ( RangeSlider ) `
285- max-width: 20% ;
268+ max-width: 300px ;
286269` ;
287270
288271const StyledList = styled ( List ) `
0 commit comments