1
- import React , { useEffect , useState , useMemo } from 'react' ;
1
+ import React , { useEffect , useState } from 'react' ;
2
2
import cn from 'bem-cn-lite' ;
3
3
import MonacoEditor from 'react-monaco-editor' ;
4
4
import { Loader , RadioButton } from '@yandex-cloud/uikit' ;
5
5
import JSONTree from 'react-json-inspector' ;
6
6
import { LANGUAGE_S_EXPRESSION_ID } from '../../../../utils/monaco' ;
7
7
import {
8
- TopologyWrapper ,
9
- CompactTopologyWrapper ,
10
8
TextOverflow ,
11
9
getYdbPlanNodeShape ,
10
+ getCompactTopology ,
11
+ getTopology ,
12
12
} from '@yandex-cloud/paranoid' ;
13
13
import { renderExplainNode } from '../../../../utils' ;
14
14
import { explainVersions } from '../../../../store/reducers/explainQuery' ;
@@ -21,7 +21,7 @@ import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
21
21
import 'react-json-inspector/json-inspector.css' ;
22
22
import './QueryExplain.scss' ;
23
23
import { useDispatch , useSelector } from 'react-redux' ;
24
- import { disableFullscreen } from '../../../../store/reducers/fullscreen' ;
24
+ import { disableFullscreen } from '../../../../store/reducers/fullscreen' ;
25
25
26
26
const b = cn ( 'kv-query-explain' ) ;
27
27
@@ -61,8 +61,42 @@ const explainOptions = [
61
61
{ value : ExplainOptionIds . ast , content : 'AST' } ,
62
62
] ;
63
63
64
+ function GraphRoot ( props ) {
65
+ let paranoid ;
66
+ useEffect ( ( ) => {
67
+ const { data, opts, shapes, version} = props ;
68
+ if ( version === explainVersions . v2 ) {
69
+ paranoid = getTopology ( 'graphRoot' , props . data , opts , shapes ) ;
70
+ paranoid . render ( ) ;
71
+ } else if ( version === explainVersions . v1 ) {
72
+ paranoid = getCompactTopology ( 'graphRoot' , data , opts ) ;
73
+ paranoid . renderCompactTopology ( ) ;
74
+ }
75
+ } , [ ] ) ;
76
+
77
+ useEffect ( ( ) => {
78
+ const graphRoot = document . getElementById ( 'graphRoot' ) ;
79
+
80
+ if ( ! graphRoot ) {
81
+ throw new Error ( "Can't find element with id #graphRoot" ) ;
82
+ }
83
+
84
+ graphRoot . innerHTML = '' ;
85
+
86
+ const { data, opts} = props ;
87
+ paranoid = getCompactTopology ( 'graphRoot' , data , opts ) ;
88
+ paranoid . renderCompactTopology ( ) ;
89
+ } , [ props . opts . colors ] ) ;
90
+
91
+ useEffect ( ( ) => {
92
+ paranoid . updateData ( props . data ) ;
93
+ } , [ props . data ] ) ;
94
+
95
+ return < div id = "graphRoot" style = { { height : '100vh' } } /> ;
96
+ }
97
+
64
98
function QueryExplain ( props ) {
65
- const dispatch = useDispatch ( )
99
+ const dispatch = useDispatch ( ) ;
66
100
const [ activeOption , setActiveOption ] = useState ( ExplainOptionIds . schema ) ;
67
101
68
102
const isFullscreen = useSelector ( ( state ) => state . fullscreen ) ;
@@ -76,41 +110,6 @@ function QueryExplain(props) {
76
110
const { explain = { } , theme} = props ;
77
111
const { links, nodes, version, graphDepth} = explain ;
78
112
79
- const graph = useMemo ( ( ) => {
80
- if ( links && nodes ) {
81
- if ( version === explainVersions . v2 ) {
82
- return (
83
- < TopologyWrapper
84
- data = { { links, nodes} }
85
- opts = { {
86
- renderNodeTitle : renderExplainNode ,
87
- textOverflow : TextOverflow . Normal ,
88
- colors : theme === 'dark' ? DARK_COLORS : { } ,
89
- initialZoomFitsCanvas : true ,
90
- } }
91
- shapes = { {
92
- node : getYdbPlanNodeShape ,
93
- } }
94
- />
95
- ) ;
96
- } else if ( version === explainVersions . v1 ) {
97
- return (
98
- < CompactTopologyWrapper
99
- data = { { links, nodes} }
100
- opts = { {
101
- renderNodeTitle : renderExplainNode ,
102
- textOverflow : TextOverflow . Normal ,
103
- colors : theme === 'dark' ? DARK_COLORS : { } ,
104
- initialZoomFitsCanvas : true ,
105
- } }
106
- />
107
- ) ;
108
- }
109
- return 'The explanation format of the query is not supported' ;
110
- }
111
- return null ;
112
- } , [ links , nodes , theme , version ] ) ;
113
-
114
113
useEffect ( ( ) => {
115
114
if ( ! props . ast && activeOption === ExplainOptionIds . ast ) {
116
115
props . astQuery ( ) ;
@@ -188,19 +187,37 @@ function QueryExplain(props) {
188
187
189
188
const renderGraph = ( ) => {
190
189
const graphHeight = `${ Math . max ( graphDepth * 100 , 200 ) } px` ;
191
- const content = (
192
- < div
193
- className = { b ( 'explain-canvas-container' , {
194
- hidden : activeOption !== ExplainOptionIds . schema ,
195
- } ) }
196
- style = { { height : graphHeight , minHeight : graphHeight , width : '100%' } }
197
- >
198
- { graph }
199
- </ div >
200
- ) ;
190
+
191
+ const content =
192
+ links && nodes && nodes . length ? (
193
+ < div
194
+ className = { b ( 'explain-canvas-container' , {
195
+ hidden : activeOption !== ExplainOptionIds . schema ,
196
+ } ) }
197
+ style = { {
198
+ height : isFullscreen ? '100%' : graphHeight ,
199
+ minHeight : graphHeight ,
200
+ width : '100%' ,
201
+ } }
202
+ >
203
+ < GraphRoot
204
+ version = { version }
205
+ data = { { links, nodes} }
206
+ opts = { {
207
+ renderNodeTitle : renderExplainNode ,
208
+ textOverflow : TextOverflow . Normal ,
209
+ colors : theme === 'dark' ? DARK_COLORS : { } ,
210
+ initialZoomFitsCanvas : true ,
211
+ } }
212
+ shapes = { {
213
+ node : getYdbPlanNodeShape ,
214
+ } }
215
+ />
216
+ </ div >
217
+ ) : null ;
201
218
return (
202
219
< React . Fragment >
203
- { content }
220
+ { ! isFullscreen && content }
204
221
{ isFullscreen && < Fullscreen > { content } </ Fullscreen > }
205
222
{ renderStub ( ) }
206
223
</ React . Fragment >
@@ -249,9 +266,7 @@ function QueryExplain(props) {
249
266
) }
250
267
</ div >
251
268
< div className = { b ( 'controls-left' ) } >
252
- < EnableFullscreenButton
253
- disabled = { Boolean ( props . error ) || activeOption === ExplainOptionIds . schema }
254
- />
269
+ < EnableFullscreenButton disabled = { Boolean ( props . error ) } />
255
270
< PaneVisibilityToggleButtons
256
271
onCollapse = { props . onCollapseResults }
257
272
onExpand = { props . onExpandResults }
0 commit comments