1
1
import React from 'react' ;
2
2
3
+ import { StopFill } from '@gravity-ui/icons' ;
3
4
import type { ControlGroupOption } from '@gravity-ui/uikit' ;
4
- import { RadioButton , Tabs } from '@gravity-ui/uikit' ;
5
+ import { Button , Icon , RadioButton , Tabs } from '@gravity-ui/uikit' ;
5
6
import JSONTree from 'react-json-inspector' ;
6
7
7
8
import { ClipboardButton } from '../../../../components/ClipboardButton' ;
8
9
import Divider from '../../../../components/Divider/Divider' ;
10
+ import ElapsedTime from '../../../../components/ElapsedTime/ElapsedTime' ;
9
11
import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton' ;
10
12
import Fullscreen from '../../../../components/Fullscreen/Fullscreen' ;
11
13
import { YDBGraph } from '../../../../components/Graph/Graph' ;
14
+ import { LoaderWrapper } from '../../../../components/LoaderWrapper/LoaderWrapper' ;
12
15
import { QueryExecutionStatus } from '../../../../components/QueryExecutionStatus' ;
13
16
import { QueryResultTable } from '../../../../components/QueryResultTable/QueryResultTable' ;
14
17
import { disableFullscreen } from '../../../../store/reducers/fullscreen' ;
15
- import type { ColumnType , KeyValueRow } from '../../../../types/api/query' ;
18
+ import type { ColumnType , KeyValueRow , TKqpStatsQuery } from '../../../../types/api/query' ;
16
19
import type { ValueOf } from '../../../../types/common' ;
17
20
import type { IQueryResult } from '../../../../types/store/query' ;
18
21
import { getArray } from '../../../../utils' ;
@@ -26,6 +29,7 @@ import {ResultIssues} from '../Issues/Issues';
26
29
import { QueryDuration } from '../QueryDuration/QueryDuration' ;
27
30
import { QuerySettingsBanner } from '../QuerySettingsBanner/QuerySettingsBanner' ;
28
31
import { getPreparedResult } from '../utils/getPreparedResult' ;
32
+ import { isQueryCancelledError } from '../utils/isQueryCancelledError' ;
29
33
30
34
import i18n from './i18n' ;
31
35
import { getPlan } from './utils' ;
@@ -46,25 +50,33 @@ type SectionID = ValueOf<typeof resultOptionsIds>;
46
50
interface ExecuteResultProps {
47
51
data : IQueryResult | undefined ;
48
52
error : unknown ;
53
+ cancelError : unknown ;
49
54
isResultsCollapsed ?: boolean ;
50
55
onCollapseResults : VoidFunction ;
51
56
onExpandResults : VoidFunction ;
57
+ onStopButtonClick : VoidFunction ;
52
58
theme ?: string ;
59
+ loading ?: boolean ;
60
+ cancelQueryLoading ?: boolean ;
53
61
}
54
62
55
63
export function ExecuteResult ( {
56
64
data,
57
65
error,
66
+ cancelError,
58
67
isResultsCollapsed,
59
68
onCollapseResults,
60
69
onExpandResults,
70
+ onStopButtonClick,
61
71
theme,
72
+ loading,
73
+ cancelQueryLoading,
62
74
} : ExecuteResultProps ) {
63
75
const [ selectedResultSet , setSelectedResultSet ] = React . useState ( 0 ) ;
64
76
const [ activeSection , setActiveSection ] = React . useState < SectionID > ( resultOptionsIds . result ) ;
65
77
const dispatch = useTypedDispatch ( ) ;
66
78
67
- const stats = data ?. stats ;
79
+ const stats : TKqpStatsQuery | undefined = data ?. stats ;
68
80
const resultsSetsCount = data ?. resultSets ?. length ;
69
81
const isMulti = resultsSetsCount && resultsSetsCount > 0 ;
70
82
const currentResult = isMulti ? data ?. resultSets ?. [ selectedResultSet ] . result : data ?. result ;
@@ -93,8 +105,8 @@ export function ExecuteResult({
93
105
} ;
94
106
} , [ dispatch ] ) ;
95
107
96
- const onSelectSection = ( value : string ) => {
97
- setActiveSection ( value as SectionID ) ;
108
+ const onSelectSection = ( value : SectionID ) => {
109
+ setActiveSection ( value ) ;
98
110
} ;
99
111
100
112
const renderResultTable = (
@@ -207,7 +219,7 @@ export function ExecuteResult({
207
219
} ;
208
220
209
221
const renderResultSection = ( ) => {
210
- if ( error ) {
222
+ if ( error && ! isQueryCancelledError ( error ) ) {
211
223
return renderIssues ( ) ;
212
224
}
213
225
if ( activeSection === resultOptionsIds . result ) {
@@ -230,18 +242,38 @@ export function ExecuteResult({
230
242
< React . Fragment >
231
243
< div className = { b ( 'controls' ) } >
232
244
< div className = { b ( 'controls-right' ) } >
233
- < QueryExecutionStatus error = { error } />
234
- { stats && ! error && (
245
+ < QueryExecutionStatus error = { error } loading = { loading } />
246
+
247
+ { ! error && ! loading && (
235
248
< React . Fragment >
236
- < QueryDuration duration = { stats ?. DurationUs } />
237
- < Divider />
238
- < RadioButton
239
- options = { resultOptions }
240
- value = { activeSection }
241
- onUpdate = { onSelectSection }
242
- />
249
+ { stats ?. DurationUs !== undefined && (
250
+ < QueryDuration duration = { Number ( stats . DurationUs ) } />
251
+ ) }
252
+ { resultOptions && activeSection && (
253
+ < React . Fragment >
254
+ < Divider />
255
+ < RadioButton
256
+ options = { resultOptions }
257
+ value = { activeSection }
258
+ onUpdate = { onSelectSection }
259
+ />
260
+ </ React . Fragment >
261
+ ) }
243
262
</ React . Fragment >
244
263
) }
264
+ { loading ? (
265
+ < React . Fragment >
266
+ < ElapsedTime className = { b ( 'elapsed-time' ) } />
267
+ < Button
268
+ loading = { cancelQueryLoading }
269
+ onClick = { onStopButtonClick }
270
+ className = { b ( 'stop-button' , { error : Boolean ( cancelError ) } ) }
271
+ >
272
+ < Icon data = { StopFill } size = { 16 } />
273
+ { i18n ( 'action.stop' ) }
274
+ </ Button >
275
+ </ React . Fragment >
276
+ ) : null }
245
277
</ div >
246
278
< div className = { b ( 'controls-left' ) } >
247
279
{ renderClipboardButton ( ) }
@@ -254,8 +286,10 @@ export function ExecuteResult({
254
286
/>
255
287
</ div >
256
288
</ div >
257
- < QuerySettingsBanner />
258
- < Fullscreen > { renderResultSection ( ) } </ Fullscreen >
289
+ { loading || isQueryCancelledError ( error ) ? null : < QuerySettingsBanner /> }
290
+ < LoaderWrapper loading = { loading } >
291
+ < Fullscreen > { renderResultSection ( ) } </ Fullscreen >
292
+ </ LoaderWrapper >
259
293
</ React . Fragment >
260
294
) ;
261
295
}
0 commit comments