Skip to content

Commit f2d7ec4

Browse files
refactor: merge query result components
1 parent 9377841 commit f2d7ec4

File tree

31 files changed

+167
-255
lines changed

31 files changed

+167
-255
lines changed

src/containers/Tenant/Query/ExecuteResult/utils.ts

Lines changed: 0 additions & 44 deletions
This file was deleted.

src/containers/Tenant/Query/ExplainResult/i18n/en.json

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/containers/Tenant/Query/ExplainResult/i18n/index.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ import {
4848
PaneVisibilityActionTypes,
4949
paneVisibilityToggleReducerCreator,
5050
} from '../../utils/paneVisibilityToggleHelpers';
51-
import {ExecuteResult} from '../ExecuteResult/ExecuteResult';
52-
import {ExplainResult} from '../ExplainResult/ExplainResult';
5351
import {Preview} from '../Preview/Preview';
5452
import {QueryEditorControls} from '../QueryEditorControls/QueryEditorControls';
53+
import {ExecuteResult} from '../QueryResult/ExecuteResult';
54+
import {ExplainResult} from '../QueryResult/ExplainResult';
5555
import {QuerySettingsDialog} from '../QuerySettingsDialog/QuerySettingsDialog';
5656
import {SAVE_QUERY_DIALOG} from '../SaveQuery/SaveQuery';
5757
import i18n from '../i18n';

src/containers/Tenant/Query/ExecuteResult/ExecuteResult.scss renamed to src/containers/Tenant/Query/QueryResult/ExecuteResult.scss

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@
3434
padding-left: 10px;
3535
}
3636

37-
&__error {
38-
padding: 15px 10px;
39-
}
40-
4137
&__controls {
4238
position: sticky;
4339
z-index: 2;
@@ -67,22 +63,6 @@
6763
gap: 4px;
6864
}
6965

70-
&__inspector {
71-
overflow: auto;
72-
73-
width: 100%;
74-
height: 100%;
75-
padding: 15px 10px;
76-
@include json-tree-styles();
77-
}
78-
79-
&__explain-canvas-container {
80-
overflow-y: auto;
81-
82-
width: 100%;
83-
height: 100%;
84-
}
85-
8666
&__elapsed-label {
8767
margin-left: var(--g-spacing-3);
8868
}

src/containers/Tenant/Query/ExecuteResult/ExecuteResult.tsx renamed to src/containers/Tenant/Query/QueryResult/ExecuteResult.tsx

Lines changed: 15 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,36 @@ import React from 'react';
22

33
import type {ControlGroupOption} from '@gravity-ui/uikit';
44
import {ClipboardButton, RadioButton, Tabs, Text} from '@gravity-ui/uikit';
5-
import JSONTree from 'react-json-inspector';
65

76
import Divider from '../../../../components/Divider/Divider';
87
import ElapsedTime from '../../../../components/ElapsedTime/ElapsedTime';
98
import EnableFullscreenButton from '../../../../components/EnableFullscreenButton/EnableFullscreenButton';
109
import Fullscreen from '../../../../components/Fullscreen/Fullscreen';
11-
import {YDBGraph} from '../../../../components/Graph/Graph';
1210
import {LoaderWrapper} from '../../../../components/LoaderWrapper/LoaderWrapper';
1311
import {QueryExecutionStatus} from '../../../../components/QueryExecutionStatus';
1412
import {QueryResultTable} from '../../../../components/QueryResultTable/QueryResultTable';
1513
import {disableFullscreen} from '../../../../store/reducers/fullscreen';
1614
import type {QueryResult} from '../../../../store/reducers/query/types';
17-
import type {TKqpStatsQuery} from '../../../../types/api/query';
1815
import type {ValueOf} from '../../../../types/common';
1916
import {getArray} from '../../../../utils';
2017
import {cn} from '../../../../utils/cn';
2118
import {USE_SHOW_PLAN_SVG_KEY} from '../../../../utils/constants';
2219
import {getStringifiedData} from '../../../../utils/dataFormatters/dataFormatters';
2320
import {useSetting, useTypedDispatch} from '../../../../utils/hooks';
24-
import {parseQueryError} from '../../../../utils/query';
2521
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
2622
import {CancelQueryButton} from '../CancelQueryButton/CancelQueryButton';
27-
import {SimplifiedPlan} from '../ExplainResult/components/SimplifiedPlan/SimplifiedPlan';
28-
import {ResultIssues} from '../Issues/Issues';
2923
import {QueryDuration} from '../QueryDuration/QueryDuration';
3024
import {QuerySettingsBanner} from '../QuerySettingsBanner/QuerySettingsBanner';
3125
import {getPreparedResult} from '../utils/getPreparedResult';
3226
import {isQueryCancelledError} from '../utils/isQueryCancelledError';
3327

34-
import {PlanToSvgButton} from './PlanToSvgButton';
35-
import {TraceButton} from './TraceButton';
28+
import {Graph} from './components/Graph/Graph';
29+
import {PlanToSvgButton} from './components/PlanToSvgButton/PlanToSvgButton';
30+
import {QueryJSONViewer} from './components/QueryJSONViewer/QueryJSONViewer';
31+
import {QueryResultError} from './components/QueryResultError/QueryResultError';
32+
import {SimplifiedPlan} from './components/SimplifiedPlan/SimplifiedPlan';
33+
import {TraceButton} from './components/TraceButton/TraceButton';
3634
import i18n from './i18n';
37-
import {getPlan} from './utils';
3835

3936
import './ExecuteResult.scss';
4037

@@ -71,18 +68,17 @@ export function ExecuteResult({
7168
const dispatch = useTypedDispatch();
7269
const [useShowPlanToSvg] = useSetting<boolean>(USE_SHOW_PLAN_SVG_KEY);
7370

74-
const {error, isLoading, queryId, data} = result;
71+
const {error, isLoading, queryId, data = {}} = result;
72+
const {preparedPlan, simplifiedPlan, stats} = data;
7573

76-
const stats: TKqpStatsQuery | undefined = data?.stats;
7774
const resultsSetsCount = data?.resultSets?.length || 0;
7875
const currentResult = data?.resultSets?.[selectedResultSet];
79-
const {plan, simplifiedPlan} = React.useMemo(() => getPlan(data), [data]);
8076

8177
const resultOptions: ControlGroupOption<SectionID>[] = [
8278
{value: resultOptionsIds.result, content: i18n('action.result')},
8379
{value: resultOptionsIds.stats, content: i18n('action.stats')},
8480
];
85-
if (plan) {
81+
if (preparedPlan) {
8682
resultOptions.push({value: resultOptionsIds.schema, content: i18n('action.schema')});
8783
}
8884
if (simplifiedPlan?.plan) {
@@ -92,8 +88,6 @@ export function ExecuteResult({
9288
});
9389
}
9490

95-
const parsedError = parseQueryError(error);
96-
9791
React.useEffect(() => {
9892
return () => {
9993
dispatch(disableFullscreen());
@@ -177,69 +171,21 @@ export function ExecuteResult({
177171
);
178172
};
179173

180-
const renderStats = () => {
181-
return (
182-
<div className={b('inspector')}>
183-
<JSONTree
184-
data={stats}
185-
isExpanded={() => true}
186-
searchOptions={{
187-
debounceTime: 300,
188-
}}
189-
/>
190-
</div>
191-
);
192-
};
193-
194-
const renderSchema = () => {
195-
const isEnoughDataForGraph = plan?.links && plan?.nodes && plan?.nodes.length;
196-
197-
if (!isEnoughDataForGraph) {
198-
return i18n('description.graph-is-not-supported');
199-
}
200-
201-
return (
202-
<div className={b('explain-canvas-container')}>
203-
<YDBGraph key={theme} data={plan} />
204-
</div>
205-
);
206-
};
207-
208-
const renderSimplified = () => {
209-
const {plan} = simplifiedPlan ?? {};
210-
if (!plan) {
211-
return null;
212-
}
213-
return <SimplifiedPlan plan={plan} />;
214-
};
215-
216-
const renderIssues = () => {
217-
if (!parsedError) {
218-
return null;
219-
}
220-
221-
if (typeof parsedError === 'object') {
222-
return <ResultIssues data={parsedError} />;
223-
}
224-
225-
return <div className={b('error')}>{parsedError}</div>;
226-
};
227-
228174
const renderResultSection = () => {
229-
if (error && !isQueryCancelledError(error)) {
230-
return renderIssues();
175+
if (error) {
176+
return <QueryResultError error={error} />;
231177
}
232178
if (activeSection === resultOptionsIds.result) {
233179
return renderResult();
234180
}
235181
if (activeSection === resultOptionsIds.stats) {
236-
return renderStats();
182+
return <QueryJSONViewer data={stats} />;
237183
}
238184
if (activeSection === resultOptionsIds.schema) {
239-
return renderSchema();
185+
return <Graph theme={theme} explain={preparedPlan} />;
240186
}
241-
if (activeSection === resultOptionsIds.simplified) {
242-
return renderSimplified();
187+
if (activeSection === resultOptionsIds.simplified && simplifiedPlan?.plan) {
188+
return <SimplifiedPlan plan={simplifiedPlan.plan} />;
243189
}
244190

245191
return null;

src/containers/Tenant/Query/ExplainResult/ExplainResult.scss renamed to src/containers/Tenant/Query/QueryResult/ExplainResult.scss

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
flex-grow: 1;
88
flex-direction: column;
99
}
10-
&__text-message {
11-
padding: 15px 20px;
12-
}
1310

1411
&__controls {
1512
position: sticky;

src/containers/Tenant/Query/ExplainResult/ExplainResult.tsx renamed to src/containers/Tenant/Query/QueryResult/ExplainResult.tsx

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import type {ValueOf} from '../../../../types/common';
1414
import {cn} from '../../../../utils/cn';
1515
import {getStringifiedData} from '../../../../utils/dataFormatters/dataFormatters';
1616
import {useTypedDispatch} from '../../../../utils/hooks';
17-
import {parseQueryErrorToString} from '../../../../utils/query';
1817
import {PaneVisibilityToggleButtons} from '../../utils/paneVisibilityToggleHelpers';
1918
import {CancelQueryButton} from '../CancelQueryButton/CancelQueryButton';
2019
import {QueryDuration} from '../QueryDuration/QueryDuration';
@@ -23,8 +22,10 @@ import {isQueryCancelledError} from '../utils/isQueryCancelledError';
2322

2423
import {Ast} from './components/Ast/Ast';
2524
import {Graph} from './components/Graph/Graph';
25+
import {QueryJSONViewer} from './components/QueryJSONViewer/QueryJSONViewer';
26+
import {QueryResultError} from './components/QueryResultError/QueryResultError';
2627
import {SimplifiedPlan} from './components/SimplifiedPlan/SimplifiedPlan';
27-
import {TextExplain} from './components/TextExplain/TextExplain';
28+
import {StubMessage} from './components/Stub/Stub';
2829
import i18n from './i18n';
2930

3031
import './ExplainResult.scss';
@@ -75,7 +76,7 @@ export function ExplainResult({
7576
isResultsCollapsed,
7677
}: ExplainResultProps) {
7778
const dispatch = useTypedDispatch();
78-
const [activeOption, setActiveOption] = React.useState<QueryExplainTab>(
79+
const [activeSection, setActiveSection] = React.useState<QueryExplainTab>(
7980
EXPLAIN_OPTIONS_IDS.schema,
8081
);
8182
const [isPending, startTransition] = React.useTransition();
@@ -91,29 +92,25 @@ export function ExplainResult({
9192

9293
const renderStub = () => {
9394
return (
94-
<div className={b('text-message')}>
95-
{i18n('description.empty-result', {
96-
activeOption: EXPLAIN_OPTIONS_NAMES[activeOption],
95+
<StubMessage
96+
message={i18n('description.empty-result', {
97+
activeSection: EXPLAIN_OPTIONS_NAMES[activeSection],
9798
})}
98-
</div>
99+
/>
99100
);
100101
};
101102

102103
const renderContent = () => {
103-
if (isQueryCancelledError(error)) {
104-
return null;
105-
}
106-
107104
if (error) {
108-
return <div className={b('text-message')}>{parseQueryErrorToString(error)}</div>;
105+
return <QueryResultError error={error} />;
109106
}
110107

111-
switch (activeOption) {
108+
switch (activeSection) {
112109
case EXPLAIN_OPTIONS_IDS.json: {
113110
if (!explain?.pristine) {
114111
return renderStub();
115112
}
116-
return <TextExplain explain={explain.pristine} />;
113+
return <QueryJSONViewer data={explain.pristine} />;
117114
}
118115
case EXPLAIN_OPTIONS_IDS.ast: {
119116
if (!ast) {
@@ -140,7 +137,7 @@ export function ExplainResult({
140137
};
141138

142139
const getStatsToCopy = () => {
143-
switch (activeOption) {
140+
switch (activeSection) {
144141
case EXPLAIN_OPTIONS_IDS.json:
145142
return explain?.pristine;
146143
case EXPLAIN_OPTIONS_IDS.ast:
@@ -152,8 +149,20 @@ export function ExplainResult({
152149
}
153150
};
154151

155-
const statsToCopy = getStatsToCopy();
156-
const copyText = getStringifiedData(statsToCopy);
152+
const renderClipboardButton = () => {
153+
const statsToCopy = getStatsToCopy();
154+
const copyText = getStringifiedData(statsToCopy);
155+
if (!copyText) {
156+
return null;
157+
}
158+
return (
159+
<ClipboardButton
160+
text={copyText}
161+
view="flat-secondary"
162+
title={i18n('action.copy', {activeSection})}
163+
/>
164+
);
165+
};
157166

158167
return (
159168
<React.Fragment>
@@ -170,9 +179,9 @@ export function ExplainResult({
170179
<Divider />
171180
<RadioButton
172181
options={explainOptions}
173-
value={activeOption}
182+
value={activeSection}
174183
onUpdate={(tabId) => {
175-
startTransition(() => setActiveOption(tabId));
184+
startTransition(() => setActiveSection(tabId));
176185
}}
177186
/>
178187
</React.Fragment>
@@ -186,13 +195,7 @@ export function ExplainResult({
186195
) : null}
187196
</div>
188197
<div className={b('controls-left')}>
189-
{copyText && (
190-
<ClipboardButton
191-
text={copyText}
192-
view="flat-secondary"
193-
title={i18n('action.copy', {activeOption})}
194-
/>
195-
)}
198+
{renderClipboardButton()}
196199
<EnableFullscreenButton disabled={Boolean(error)} />
197200
<PaneVisibilityToggleButtons
198201
onCollapse={onCollapseResults}

0 commit comments

Comments
 (0)