1- import React , { useEffect , useState , useMemo } from 'react' ;
1+ import React , { useEffect , useState } from 'react' ;
22import cn from 'bem-cn-lite' ;
33import MonacoEditor from 'react-monaco-editor' ;
44import { Loader , RadioButton } from '@yandex-cloud/uikit' ;
55import JSONTree from 'react-json-inspector' ;
66import { LANGUAGE_S_EXPRESSION_ID } from '../../../../utils/monaco' ;
77import {
8- TopologyWrapper ,
9- CompactTopologyWrapper ,
108 TextOverflow ,
119 getYdbPlanNodeShape ,
10+ getCompactTopology ,
11+ getTopology ,
1212} from '@yandex-cloud/paranoid' ;
1313import { renderExplainNode } from '../../../../utils' ;
1414import { explainVersions } from '../../../../store/reducers/explainQuery' ;
@@ -21,7 +21,7 @@ import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
2121import 'react-json-inspector/json-inspector.css' ;
2222import './QueryExplain.scss' ;
2323import { useDispatch , useSelector } from 'react-redux' ;
24- import { disableFullscreen } from '../../../../store/reducers/fullscreen' ;
24+ import { disableFullscreen } from '../../../../store/reducers/fullscreen' ;
2525
2626const b = cn ( 'kv-query-explain' ) ;
2727
@@ -61,8 +61,42 @@ const explainOptions = [
6161 { value : ExplainOptionIds . ast , content : 'AST' } ,
6262] ;
6363
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+
6498function QueryExplain ( props ) {
65- const dispatch = useDispatch ( )
99+ const dispatch = useDispatch ( ) ;
66100 const [ activeOption , setActiveOption ] = useState ( ExplainOptionIds . schema ) ;
67101
68102 const isFullscreen = useSelector ( ( state ) => state . fullscreen ) ;
@@ -76,41 +110,6 @@ function QueryExplain(props) {
76110 const { explain = { } , theme} = props ;
77111 const { links, nodes, version, graphDepth} = explain ;
78112
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-
114113 useEffect ( ( ) => {
115114 if ( ! props . ast && activeOption === ExplainOptionIds . ast ) {
116115 props . astQuery ( ) ;
@@ -188,19 +187,37 @@ function QueryExplain(props) {
188187
189188 const renderGraph = ( ) => {
190189 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 ;
201218 return (
202219 < React . Fragment >
203- { content }
220+ { ! isFullscreen && content }
204221 { isFullscreen && < Fullscreen > { content } </ Fullscreen > }
205222 { renderStub ( ) }
206223 </ React . Fragment >
@@ -249,9 +266,7 @@ function QueryExplain(props) {
249266 ) }
250267 </ div >
251268 < div className = { b ( 'controls-left' ) } >
252- < EnableFullscreenButton
253- disabled = { Boolean ( props . error ) || activeOption === ExplainOptionIds . schema }
254- />
269+ < EnableFullscreenButton disabled = { Boolean ( props . error ) } />
255270 < PaneVisibilityToggleButtons
256271 onCollapse = { props . onCollapseResults }
257272 onExpand = { props . onExpandResults }
0 commit comments