1
- import { Fragment , useMemo , useRef } from 'react' ;
2
- import type { ListRowProps } from 'react-virtualized' ;
3
- import {
4
- AutoSizer ,
5
- CellMeasurer ,
6
- InfiniteLoader ,
7
- List as ReactVirtualizedList ,
8
- } from 'react-virtualized' ;
1
+ import { Fragment , useMemo } from 'react' ;
9
2
import styled from '@emotion/styled' ;
10
3
11
4
import waitingForEventImg from 'sentry-images/spot/waiting-for-event.svg' ;
12
5
6
+ import { Flex } from 'sentry/components/core/layout' ;
13
7
import { Tooltip } from 'sentry/components/core/tooltip' ;
14
8
import ErrorBoundary from 'sentry/components/errorBoundary' ;
15
9
import FeedbackListHeader from 'sentry/components/feedback/list/feedbackListHeader' ;
16
10
import FeedbackListItem from 'sentry/components/feedback/list/feedbackListItem' ;
17
11
import useFeedbackQueryKeys from 'sentry/components/feedback/useFeedbackQueryKeys' ;
12
+ import InfiniteListItems from 'sentry/components/infiniteList/infiniteListItems' ;
13
+ import InfiniteListState from 'sentry/components/infiniteList/infiniteListState' ;
18
14
import LoadingIndicator from 'sentry/components/loadingIndicator' ;
19
15
import { t } from 'sentry/locale' ;
20
16
import { space } from 'sentry/styles/space' ;
21
- import useFetchInfiniteListData from 'sentry/utils/api/useFetchInfiniteListData ' ;
17
+ import uniqueBy from 'sentry/utils/array/uniqBy ' ;
22
18
import type { FeedbackIssueListItem } from 'sentry/utils/feedback/types' ;
23
19
import { useListItemCheckboxContext } from 'sentry/utils/list/useListItemCheckboxState' ;
24
- import useVirtualizedList from 'sentry/views/replays/detail/useVirtualizedList ' ;
20
+ import { useInfiniteApiQuery } from 'sentry/utils/queryClient ' ;
25
21
26
- // Ensure this object is created once as it is an input to
27
- // `useVirtualizedList`'s memoization
28
- const cellMeasurer = {
29
- fixedWidth : true ,
30
- minHeight : 24 ,
31
- } ;
32
-
33
- function NoFeedback ( { title, subtitle} : { subtitle : string ; title : string } ) {
22
+ function NoFeedback ( ) {
34
23
return (
35
- < Wrapper >
36
- < img src = { waitingForEventImg } alt = "No feedback found spot illustration" />
37
- < EmptyMessage > { title } </ EmptyMessage >
38
- < p > { subtitle } </ p >
39
- </ Wrapper >
24
+ < NoFeedbackWrapper >
25
+ < img src = { waitingForEventImg } alt = { t ( 'A person waiting for a phone to ring' ) } />
26
+ < NoFeedbackMessage > { t ( 'Inbox Zero' ) } </ NoFeedbackMessage >
27
+ < p > { t ( 'You have two options: take a nap or be productive.' ) } </ p >
28
+ </ NoFeedbackWrapper >
40
29
) ;
41
30
}
42
31
43
32
export default function FeedbackList ( ) {
44
33
const { listQueryKey} = useFeedbackQueryKeys ( ) ;
45
- const {
46
- isFetchingNextPage,
47
- isFetchingPreviousPage,
48
- isLoading, // If anything is loaded yet
49
- getRow,
50
- isRowLoaded,
51
- issues,
52
- loadMoreRows,
53
- hits,
54
- } = useFetchInfiniteListData < FeedbackIssueListItem > ( {
34
+ const queryResult = useInfiniteApiQuery < FeedbackIssueListItem [ ] > ( {
55
35
queryKey : listQueryKey ?? [ 'infinite' , '' ] ,
56
- uniqueField : 'id' ,
57
36
enabled : Boolean ( listQueryKey ) ,
58
37
} ) ;
59
38
39
+ const issues = useMemo (
40
+ ( ) => uniqueBy ( queryResult . data ?. pages . flatMap ( ( [ pageData ] ) => pageData ) ?? [ ] , 'id' ) ,
41
+ [ queryResult . data ?. pages ]
42
+ ) ;
60
43
const checkboxState = useListItemCheckboxContext ( {
61
- hits,
44
+ hits : issues . length ,
62
45
knownIds : issues . map ( issue => issue . id ) ,
63
46
queryKey : listQueryKey ,
64
47
} ) ;
65
48
66
- const listRef = useRef < ReactVirtualizedList > ( null ) ;
67
-
68
- const deps = useMemo ( ( ) => [ isLoading , issues . length ] , [ isLoading , issues . length ] ) ;
69
- const { cache, updateList} = useVirtualizedList ( {
70
- cellMeasurer,
71
- ref : listRef ,
72
- deps,
73
- } ) ;
74
-
75
- const renderRow = ( { index, key, style, parent} : ListRowProps ) => {
76
- const item = getRow ( { index} ) ;
77
- if ( ! item ) {
78
- return null ;
79
- }
80
-
81
- return (
82
- < ErrorBoundary mini key = { key } >
83
- < CellMeasurer cache = { cache } columnIndex = { 0 } parent = { parent } rowIndex = { index } >
84
- < FeedbackListItem
85
- feedbackItem = { item }
86
- isSelected = { checkboxState . isSelected ( item . id ) }
87
- onSelect = { ( ) => {
88
- checkboxState . toggleSelected ( item . id ) ;
89
- } }
90
- style = { style }
91
- />
92
- </ CellMeasurer >
93
- </ ErrorBoundary >
94
- ) ;
95
- } ;
96
-
97
49
return (
98
50
< Fragment >
99
51
< FeedbackListHeader { ...checkboxState } />
100
- < FeedbackListItems >
101
- < InfiniteLoader
102
- isRowLoaded = { isRowLoaded }
103
- loadMoreRows = { loadMoreRows }
104
- rowCount = { hits }
52
+ < Flex direction = "column" style = { { flexGrow : 1 } } >
53
+ < InfiniteListState
54
+ queryResult = { queryResult }
55
+ backgroundUpdatingMessage = { ( ) => null }
56
+ loadingMessage = { ( ) => < LoadingIndicator /> }
105
57
>
106
- { ( { onRowsRendered, registerChild} ) => (
107
- < AutoSizer onResize = { updateList } >
108
- { ( { width, height} ) => (
109
- < ReactVirtualizedList
110
- deferredMeasurementCache = { cache }
111
- height = { height }
112
- noRowsRenderer = { ( ) =>
113
- isLoading ? (
114
- < LoadingIndicator />
115
- ) : (
116
- < NoFeedback
117
- title = { t ( 'Inbox Zero' ) }
118
- subtitle = { t ( 'You have two options: take a nap or be productive.' ) }
119
- />
120
- )
121
- }
122
- onRowsRendered = { onRowsRendered }
123
- overscanRowCount = { 5 }
124
- ref = { e => {
125
- listRef . current = e ;
126
- registerChild ( e ) ;
58
+ < InfiniteListItems < FeedbackIssueListItem >
59
+ estimateSize = { ( ) => 24 }
60
+ queryResult = { queryResult }
61
+ itemRenderer = { ( { item} ) => (
62
+ < ErrorBoundary mini >
63
+ < FeedbackListItem
64
+ feedbackItem = { item }
65
+ isSelected = { checkboxState . isSelected ( item . id ) }
66
+ onSelect = { ( ) => {
67
+ checkboxState . toggleSelected ( item . id ) ;
127
68
} }
128
- rowCount = { issues . length }
129
- rowHeight = { cache . rowHeight }
130
- rowRenderer = { renderRow }
131
- width = { width }
132
69
/>
133
- ) }
134
- </ AutoSizer >
135
- ) }
136
- </ InfiniteLoader >
137
- < FloatingContainer style = { { top : '2px' } } >
138
- { isFetchingPreviousPage ? (
139
- < Tooltip title = { t ( 'Loading more feedback...' ) } >
140
- < LoadingIndicator mini />
141
- </ Tooltip >
142
- ) : null }
143
- </ FloatingContainer >
144
- < FloatingContainer style = { { bottom : '2px' } } >
145
- { isFetchingNextPage ? (
146
- < Tooltip title = { t ( 'Loading more feedback...' ) } >
147
- < LoadingIndicator mini />
148
- </ Tooltip >
149
- ) : null }
150
- </ FloatingContainer >
151
- </ FeedbackListItems >
70
+ </ ErrorBoundary >
71
+ ) }
72
+ emptyMessage = { ( ) => < NoFeedback /> }
73
+ loadingMoreMessage = { ( ) => (
74
+ < LoadingMoreContainer >
75
+ < Tooltip title = { t ( 'Loading more feedback...' ) } >
76
+ < LoadingIndicator mini />
77
+ </ Tooltip >
78
+ </ LoadingMoreContainer >
79
+ ) }
80
+ loadingCompleteMessage = { ( ) => null }
81
+ />
82
+ </ InfiniteListState >
83
+ </ Flex >
152
84
</ Fragment >
153
85
) ;
154
86
}
155
87
156
- const FeedbackListItems = styled ( 'div' ) `
157
- display: grid;
158
- flex-grow: 1;
159
- min-height: 300px;
160
- ` ;
161
-
162
- const FloatingContainer = styled ( 'div' ) `
163
- position: absolute;
88
+ const LoadingMoreContainer = styled ( 'div' ) `
164
89
justify-self: center;
165
90
` ;
166
91
167
- const Wrapper = styled ( 'div' ) `
168
- display: flex;
92
+ const NoFeedbackWrapper = styled ( 'div' ) `
169
93
padding: ${ space ( 4 ) } ${ space ( 4 ) } ;
170
94
flex-direction: column;
171
95
align-items: center;
@@ -175,12 +99,9 @@ const Wrapper = styled('div')`
175
99
@media (max-width: ${ p => p . theme . breakpoints . sm } ) {
176
100
font-size: ${ p => p . theme . fontSize . md } ;
177
101
}
178
- position: relative;
179
- top: 50%;
180
- transform: translateY(-50%);
181
102
` ;
182
103
183
- const EmptyMessage = styled ( 'div' ) `
104
+ const NoFeedbackMessage = styled ( 'div' ) `
184
105
font-weight: ${ p => p . theme . fontWeight . bold } ;
185
106
color: ${ p => p . theme . gray400 } ;
186
107
0 commit comments