1- import React , { type ReactNode , useEffect , useState } from 'react' ;
1+ import React , { useEffect , useState } from 'react' ;
22import { useDispatch } from 'react-redux' ;
33import cn from 'bem-cn-lite' ;
44import JSONTree from 'react-json-inspector' ;
55
6- import { RadioButton } from '@gravity-ui/uikit' ;
6+ import { RadioButton , Tabs } from '@gravity-ui/uikit' ;
77
88import CopyToClipboard from '../../../../components/CopyToClipboard/CopyToClipboard' ;
99import Divider from '../../../../components/Divider/Divider' ;
1010import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton' ;
1111import Fullscreen from '../../../../components/Fullscreen/Fullscreen' ;
1212import { QueryExecutionStatus } from '../../../../components/QueryExecutionStatus' ;
13+ import { QueryResultTable } from '../../../../components/QueryResultTable/QueryResultTable' ;
1314
1415import type { ValueOf } from '../../../../types/common' ;
1516import type { IQueryResult , QueryErrorResponse } from '../../../../types/store/query' ;
17+ import type { ColumnType , KeyValueRow } from '../../../../types/api/query' ;
1618import { disableFullscreen } from '../../../../store/reducers/fullscreen' ;
1719import { prepareQueryError } from '../../../../utils/query' ;
1820import { useTypedSelector } from '../../../../utils/hooks' ;
21+ import { getArray } from '../../../../utils' ;
1922
2023import { PaneVisibilityToggleButtons } from '../../utils/paneVisibilityToggleHelpers' ;
2124
2225import { ResultIssues } from '../Issues/Issues' ;
2326import { QueryDuration } from '../QueryDuration/QueryDuration' ;
27+ import { getPreparedResult } from '../utils/getPreparedResult' ;
2428
2529import './ExecuteResult.scss' ;
2630
@@ -39,30 +43,35 @@ const resultOptions = [
3943] ;
4044
4145interface ExecuteResultProps {
42- textResults : string ;
43- result : ReactNode ;
46+ data : IQueryResult | undefined ;
4447 stats : IQueryResult [ 'stats' ] | undefined ;
4548 error : string | QueryErrorResponse | undefined ;
46- copyDisabled ?: boolean ;
4749 isResultsCollapsed ?: boolean ;
4850 onCollapseResults : VoidFunction ;
4951 onExpandResults : VoidFunction ;
5052}
5153
5254export function ExecuteResult ( {
53- textResults,
54- result,
55+ data,
5556 stats,
5657 error,
57- copyDisabled,
5858 isResultsCollapsed,
5959 onCollapseResults,
6060 onExpandResults,
6161} : ExecuteResultProps ) {
62+ const [ selectedResultSet , setSelectedResultSet ] = useState ( 0 ) ;
6263 const [ activeSection , setActiveSection ] = useState < SectionID > ( resultOptionsIds . result ) ;
64+
6365 const isFullscreen = useTypedSelector ( ( state ) => state . fullscreen ) ;
6466 const dispatch = useDispatch ( ) ;
6567
68+ const resultsSetsCount = data ?. resultSets ?. length ;
69+ const isMulti = resultsSetsCount && resultsSetsCount > 0 ;
70+ const currentResult = isMulti ? data ?. resultSets ?. [ selectedResultSet ] . result : data ?. result ;
71+ const currentColumns = isMulti ? data ?. resultSets ?. [ selectedResultSet ] . columns : data ?. columns ;
72+ const textResults = getPreparedResult ( currentResult ) ;
73+ const copyDisabled = ! textResults . length ;
74+
6675 useEffect ( ( ) => {
6776 return ( ) => {
6877 dispatch ( disableFullscreen ( ) ) ;
@@ -73,6 +82,37 @@ export function ExecuteResult({
7382 setActiveSection ( value as SectionID ) ;
7483 } ;
7584
85+ const renderResultTable = (
86+ result : KeyValueRow [ ] | undefined ,
87+ columns : ColumnType [ ] | undefined ,
88+ ) => {
89+ return < QueryResultTable data = { result } columns = { columns } settings = { { sortable : false } } /> ;
90+ } ;
91+
92+ const renderContent = ( ) => {
93+ return (
94+ < >
95+ { isMulti && resultsSetsCount > 1 && (
96+ < div >
97+ < Tabs
98+ className = { b ( 'result-tabs' ) }
99+ size = "l"
100+ items = { getArray ( resultsSetsCount ) . map ( ( item ) => ( {
101+ id : String ( item ) ,
102+ title : `Result #${ item + 1 } ` ,
103+ } ) ) }
104+ activeTab = { String ( selectedResultSet ) }
105+ onSelectTab = { ( tabId ) => setSelectedResultSet ( Number ( tabId ) ) }
106+ />
107+ </ div >
108+ ) }
109+ < div className = { b ( 'result' ) } >
110+ { renderResultTable ( currentResult , currentColumns ) }
111+ </ div >
112+ </ >
113+ ) ;
114+ } ;
115+
76116 const renderClipboardButton = ( ) => {
77117 return (
78118 < CopyToClipboard
@@ -108,12 +148,14 @@ export function ExecuteResult({
108148 } ;
109149
110150 const renderResult = ( ) => {
151+ const content = renderContent ( ) ;
152+
111153 return (
112154 < React . Fragment >
113- { result }
155+ { content }
114156 { isFullscreen && (
115157 < Fullscreen >
116- < div className = { b ( 'result' , { fullscreen : true } ) } > { result } </ div >
158+ < div className = { b ( 'result- fullscreen-wrapper' ) } > { content } </ div >
117159 </ Fullscreen >
118160 ) }
119161 </ React . Fragment >
@@ -126,13 +168,15 @@ export function ExecuteResult({
126168 }
127169
128170 if ( typeof error === 'object' && error . data ?. issues && Array . isArray ( error . data . issues ) ) {
171+ const content = < ResultIssues data = { error . data } /> ;
172+
129173 return (
130174 < React . Fragment >
131- < ResultIssues data = { error . data } />
175+ { content }
132176 { isFullscreen && (
133177 < Fullscreen >
134- < div className = { b ( 'result' , { fullscreen : true } ) } >
135- < ResultIssues data = { error . data } />
178+ < div className = { b ( 'result-fullscreen-wrapper ' , b ( 'result' ) ) } >
179+ { content }
136180 </ div >
137181 </ Fullscreen >
138182 ) }
@@ -145,6 +189,19 @@ export function ExecuteResult({
145189 return < div className = { b ( 'error' ) } > { parsedError } </ div > ;
146190 } ;
147191
192+ const renderResultSection = ( ) => {
193+ if ( activeSection === resultOptionsIds . result && ! error ) {
194+ return renderResult ( ) ;
195+ }
196+
197+ return (
198+ < div className = { b ( 'result' ) } >
199+ { activeSection === resultOptionsIds . stats && ! error && renderStats ( ) }
200+ { renderIssues ( ) }
201+ </ div >
202+ ) ;
203+ } ;
204+
148205 return (
149206 < React . Fragment >
150207 < div className = { b ( 'controls' ) } >
@@ -174,11 +231,8 @@ export function ExecuteResult({
174231 />
175232 </ div >
176233 </ div >
177- < div className = { b ( 'result' ) } >
178- { activeSection === resultOptionsIds . result && ! error && renderResult ( ) }
179- { activeSection === resultOptionsIds . stats && ! error && renderStats ( ) }
180- { renderIssues ( ) }
181- </ div >
234+
235+ { renderResultSection ( ) }
182236 </ React . Fragment >
183237 ) ;
184238}
0 commit comments