Skip to content

Commit da511da

Browse files
committed
fix(QueryExplain): should render graph in fullscreen view properly
Release-As: 1.0.0
1 parent e2668ef commit da511da

File tree

3 files changed

+73
-55
lines changed

3 files changed

+73
-55
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ The build is minified and the filenames include the hashes.
2424

2525
To test production bundle with latest YDB backend release, do the following:
2626
1) Build a production bundle with a few tweaks for embedded version: `npm run build:embedded`.
27-
2) Invoke `docker run -it --hostname localhost -e YDB_LOCAL_SURVIVE_RESTART=true -dp 2135:2135 -p 8765:8765 -v ~/projects/ydb-embedded-ui/build:/ydb_data/node_1/contentmonitoring cr.yandex/yc/yandex-docker-local-ydb:latest`
27+
2) Invoke `docker run -it --hostname localhost -dp 2135:2135 -p 8765:8765 -v ~/projects/ydb-embedded-ui/build:/ydb_data/node_1/contentmonitoring cr.yandex/yc/yandex-docker-local-ydb:latest`
2828
3) Open [embedded YDB UI](http://localhost:8765/monitoring) to view it in the browser.

src/containers/Tenant/QueryEditor/QueryEditor.js

+3
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ function QueryEditor(props) {
153153

154154
useEffect(() => {
155155
const {monacoHotKey, setMonacoHotKey} = props;
156+
if (monacoHotKey === null) {
157+
return
158+
}
156159
setMonacoHotKey(null);
157160
switch (monacoHotKey) {
158161
case MONACO_HOT_KEY_ACTIONS.sendQuery: {

src/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js

+69-54
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import React, {useEffect, useState, useMemo} from 'react';
1+
import React, {useEffect, useState} from 'react';
22
import cn from 'bem-cn-lite';
33
import MonacoEditor from 'react-monaco-editor';
44
import {Loader, RadioButton} from '@yandex-cloud/uikit';
55
import JSONTree from 'react-json-inspector';
66
import {LANGUAGE_S_EXPRESSION_ID} from '../../../../utils/monaco';
77
import {
8-
TopologyWrapper,
9-
CompactTopologyWrapper,
108
TextOverflow,
119
getYdbPlanNodeShape,
10+
getCompactTopology,
11+
getTopology,
1212
} from '@yandex-cloud/paranoid';
1313
import {renderExplainNode} from '../../../../utils';
1414
import {explainVersions} from '../../../../store/reducers/explainQuery';
@@ -21,7 +21,7 @@ import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
2121
import 'react-json-inspector/json-inspector.css';
2222
import './QueryExplain.scss';
2323
import {useDispatch, useSelector} from 'react-redux';
24-
import { disableFullscreen } from '../../../../store/reducers/fullscreen';
24+
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
2525

2626
const 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+
6498
function 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

Comments
 (0)