@@ -11,18 +11,28 @@ import HistoryContext from '../../../../contexts/HistoryContext';
11
11
12
12
import routes , { createHref } from '../../../../routes' ;
13
13
14
- import { sendShardQuery , setShardQueryOptions } from '../../../../store/reducers/shardsWorkload' ;
14
+ import {
15
+ sendShardQuery ,
16
+ setShardQueryOptions ,
17
+ setTopShardFilters ,
18
+ } from '../../../../store/reducers/shardsWorkload' ;
15
19
import { setCurrentSchemaPath , getSchema } from '../../../../store/reducers/schema' ;
20
+ import type { IShardsWorkloadFilters } from '../../../../types/store/shardsWorkload' ;
16
21
17
22
import type { EPathType } from '../../../../types/api/schema' ;
18
23
19
- import { DEFAULT_TABLE_SETTINGS } from '../../../../utils/constants' ;
24
+ import { formatDateTime , formatNumber } from '../../../../utils' ;
25
+ import { DEFAULT_TABLE_SETTINGS , HOUR_IN_SECONDS } from '../../../../utils/constants' ;
20
26
import { useAutofetcher , useTypedSelector } from '../../../../utils/hooks' ;
21
- import { i18n } from '../../../../utils/i18n' ;
22
27
import { prepareQueryError } from '../../../../utils/query' ;
23
28
29
+ import { getDefaultNodePath } from '../../../Node/NodePages' ;
30
+
24
31
import { isColumnEntityType } from '../../utils/schema' ;
25
32
33
+ import { DateRange , DateRangeValues } from './DateRange' ;
34
+
35
+ import i18n from './i18n' ;
26
36
import './TopShards.scss' ;
27
37
28
38
const b = cn ( 'top-shards' ) ;
@@ -41,16 +51,15 @@ const tableColumnsNames = {
41
51
CPUCores : 'CPUCores' ,
42
52
DataSize : 'DataSize' ,
43
53
Path : 'Path' ,
54
+ NodeId : 'NodeId' ,
55
+ PeakTime : 'PeakTime' ,
56
+ InFlightTxCount : 'InFlightTxCount' ,
44
57
} ;
45
58
46
59
function prepareCPUWorkloadValue ( value : string ) {
47
60
return `${ ( Number ( value ) * 100 ) . toFixed ( 2 ) } %` ;
48
61
}
49
62
50
- function prepareDateSizeValue ( value : number ) {
51
- return new Intl . NumberFormat ( i18n . lang ) . format ( value ) ;
52
- }
53
-
54
63
function stringToDataTableSortOrder ( value : string ) : SortOrder [ ] | undefined {
55
64
return value
56
65
? value . split ( ',' ) . map ( ( columnId ) => ( {
@@ -87,10 +96,24 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
87
96
const {
88
97
loading,
89
98
data : { result : data = undefined } = { } ,
99
+ filters : storeFilters ,
90
100
error,
91
101
wasLoaded,
92
102
} = useTypedSelector ( ( state ) => state . shardsWorkload ) ;
93
103
104
+ // default date range should be the last hour, but shouldn't propagate into URL until user interacts with the control
105
+ // redux initial value can't be used, as it synchronizes with URL
106
+ const [ filters , setFilters ] = useState < IShardsWorkloadFilters > ( ( ) => {
107
+ if ( ! storeFilters ?. from && ! storeFilters ?. to ) {
108
+ return {
109
+ from : Date . now ( ) - HOUR_IN_SECONDS * 1000 ,
110
+ to : Date . now ( ) ,
111
+ } ;
112
+ }
113
+
114
+ return storeFilters ;
115
+ } ) ;
116
+
94
117
const [ sortOrder , setSortOrder ] = useState ( tableColumnsNames . CPUCores ) ;
95
118
96
119
useAutofetcher (
@@ -100,10 +123,11 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
100
123
database : tenantPath ,
101
124
path : currentSchemaPath ,
102
125
sortOrder : stringToQuerySortOrder ( sortOrder ) ,
126
+ filters,
103
127
} ) ,
104
128
) ;
105
129
} ,
106
- [ dispatch , currentSchemaPath , tenantPath , sortOrder ] ,
130
+ [ dispatch , tenantPath , currentSchemaPath , sortOrder , filters ] ,
107
131
autorefresh ,
108
132
) ;
109
133
@@ -115,7 +139,7 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
115
139
data : undefined ,
116
140
} ) ,
117
141
) ;
118
- } , [ dispatch , currentSchemaPath , tenantPath ] ) ;
142
+ } , [ dispatch , currentSchemaPath , tenantPath , filters ] ) ;
119
143
120
144
const history = useContext ( HistoryContext ) ;
121
145
@@ -126,6 +150,11 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
126
150
setSortOrder ( dataTableToStringSortOrder ( newSortOrder ) ) ;
127
151
} ;
128
152
153
+ const handleDateRangeChange = ( value : DateRangeValues ) => {
154
+ dispatch ( setTopShardFilters ( value ) ) ;
155
+ setFilters ( value ) ;
156
+ } ;
157
+
129
158
const tableColumns : Column < any > [ ] = useMemo ( ( ) => {
130
159
const onSchemaClick = ( schemaPath : string ) => {
131
160
return ( ) => {
@@ -161,7 +190,7 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
161
190
name : tableColumnsNames . DataSize ,
162
191
header : 'DataSize (B)' ,
163
192
render : ( { value} ) => {
164
- return prepareDateSizeValue ( value as number ) ;
193
+ return formatNumber ( value as number ) ;
165
194
} ,
166
195
align : DataTable . RIGHT ,
167
196
} ,
@@ -176,6 +205,29 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
176
205
} ,
177
206
sortable : false ,
178
207
} ,
208
+ {
209
+ name : tableColumnsNames . NodeId ,
210
+ render : ( { value : nodeId } ) => {
211
+ return (
212
+ < InternalLink to = { getDefaultNodePath ( nodeId as string ) } >
213
+ { nodeId as string }
214
+ </ InternalLink >
215
+ ) ;
216
+ } ,
217
+ align : DataTable . RIGHT ,
218
+ sortable : false ,
219
+ } ,
220
+ {
221
+ name : tableColumnsNames . PeakTime ,
222
+ render : ( { value} ) => formatDateTime ( new Date ( value as string ) . valueOf ( ) ) ,
223
+ sortable : false ,
224
+ } ,
225
+ {
226
+ name : tableColumnsNames . InFlightTxCount ,
227
+ render : ( { value} ) => formatNumber ( value as number ) ,
228
+ align : DataTable . RIGHT ,
229
+ sortable : false ,
230
+ } ,
179
231
] ;
180
232
} , [ dispatch , history , tenantPath ] ) ;
181
233
@@ -192,12 +244,12 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
192
244
return renderLoader ( ) ;
193
245
}
194
246
195
- if ( ! data || data . length === 0 || isColumnEntityType ( type ) ) {
196
- return 'No data' ;
247
+ if ( error && ! error . isCancelled ) {
248
+ return < div className = "error" > { prepareQueryError ( error ) } </ div > ;
197
249
}
198
250
199
- if ( error && ! error . isCancelled ) {
200
- return prepareQueryError ( error ) ;
251
+ if ( ! data || isColumnEntityType ( type ) ) {
252
+ return i18n ( 'no-data' ) ;
201
253
}
202
254
203
255
return (
@@ -216,6 +268,10 @@ export const TopShards = ({tenantPath, type}: TopShardsProps) => {
216
268
217
269
return (
218
270
< div className = { b ( ) } >
271
+ < div className = { b ( 'controls' ) } >
272
+ { i18n ( 'description' ) }
273
+ < DateRange from = { filters . from } to = { filters . to } onChange = { handleDateRangeChange } />
274
+ </ div >
219
275
{ renderContent ( ) }
220
276
</ div >
221
277
) ;
0 commit comments