Skip to content
This repository was archived by the owner on Aug 23, 2025. It is now read-only.

Commit ecd55e0

Browse files
authored
Fix chart download button (#981)
* Add autoHeight to SqlEditor component * Remove unused QueryHistoryResultHeader * Fix chart download button * Remove unused queryResult state
1 parent 49acc47 commit ecd55e0

9 files changed

Lines changed: 84 additions & 132 deletions

client/src/common/SqlEditor.tsx

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ import 'ace-builds/src-noconflict/theme-sqlserver';
1010
const noop = () => {};
1111

1212
export interface Props {
13+
autoHeight: boolean;
1314
onChange?: (value: string) => void;
1415
readOnly: boolean;
1516
value: string;
1617
onSelectionChange: (value: string) => void;
1718
}
1819

19-
function SqlEditor({ onChange, readOnly, value, onSelectionChange }: Props) {
20+
function SqlEditor({
21+
autoHeight,
22+
onChange,
23+
readOnly,
24+
value,
25+
onSelectionChange,
26+
}: Props) {
2027
const { config } = useAppContext();
2128
const [dimensions, setDimensions] = useState({ width: -1, height: -1 });
2229
const [editor, setEditor] = useState<any>(null);
@@ -57,46 +64,72 @@ function SqlEditor({ onChange, readOnly, value, onSelectionChange }: Props) {
5764
tabSize: 2,
5865
};
5966

67+
if (autoHeight) {
68+
return (
69+
<Measure
70+
bounds
71+
onResize={(contentRect: any) => setDimensions(contentRect.bounds)}
72+
>
73+
{({ measureRef }) => (
74+
<div ref={measureRef} className="h-100 w-100">
75+
<AceEditor
76+
editorProps={{ $blockScrolling: Infinity }}
77+
focus={!readOnly}
78+
height={height + 'px'}
79+
fontSize={14}
80+
highlightActiveLine={false}
81+
mode="sql"
82+
name="query-ace-editor"
83+
onChange={onChange || noop}
84+
onLoad={(editor) => setEditor(editor)}
85+
onSelectionChange={handleSelection}
86+
readOnly={readOnly}
87+
setOptions={setOptions}
88+
showGutter={true}
89+
showPrintMargin={false}
90+
theme="sqlserver"
91+
value={value}
92+
width={width + 'px'}
93+
/>
94+
</div>
95+
)}
96+
</Measure>
97+
);
98+
}
99+
60100
return (
61-
<Measure
62-
bounds
63-
onResize={(contentRect: any) => setDimensions(contentRect.bounds)}
64-
>
65-
{({ measureRef }) => (
66-
<div ref={measureRef} className="h-100 w-100">
67-
<AceEditor
68-
editorProps={{ $blockScrolling: Infinity }}
69-
focus={!readOnly}
70-
height={height + 'px'}
71-
fontSize={14}
72-
highlightActiveLine={false}
73-
mode="sql"
74-
name="query-ace-editor"
75-
onChange={onChange || noop}
76-
onLoad={(editor) => setEditor(editor)}
77-
onSelectionChange={handleSelection}
78-
readOnly={readOnly}
79-
setOptions={setOptions}
80-
showGutter={true}
81-
showPrintMargin={false}
82-
theme="sqlserver"
83-
value={value}
84-
width={width + 'px'}
85-
/>
86-
</div>
87-
)}
88-
</Measure>
101+
<AceEditor
102+
editorProps={{ $blockScrolling: Infinity }}
103+
focus={!readOnly}
104+
fontSize={14}
105+
highlightActiveLine={false}
106+
mode="sql"
107+
name="query-ace-editor"
108+
onChange={onChange || noop}
109+
onLoad={(editor) => setEditor(editor)}
110+
onSelectionChange={handleSelection}
111+
readOnly={readOnly}
112+
setOptions={setOptions}
113+
showGutter={true}
114+
showPrintMargin={false}
115+
theme="sqlserver"
116+
value={value}
117+
maxLines={12}
118+
width={'100%'}
119+
/>
89120
);
90121
}
91122

92123
SqlEditor.propTypes = {
124+
autoHeight: PropTypes.bool,
93125
onChange: PropTypes.func,
94126
onSelectionChange: PropTypes.func,
95127
readOnly: PropTypes.bool,
96128
value: PropTypes.string,
97129
};
98130

99131
SqlEditor.defaultProps = {
132+
autoHeight: true,
100133
onSelectionChange: () => {},
101134
readOnly: false,
102135
value: '',

client/src/common/SqlpadTauChart.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ function SqlpadTauChart({
4545
let chart: any;
4646

4747
if (!isRunning && !queryError && chartConfiguration && columns && rows) {
48-
const queryResult = {
48+
const dataRows = getObjectRows(columns, rows);
49+
const chartConfig = getTauChartConfig(
50+
chartConfiguration,
4951
columns,
50-
rows: getObjectRows(columns, rows),
51-
};
52-
const chartConfig = getTauChartConfig(chartConfiguration, queryResult);
52+
dataRows
53+
);
5354
if (chartConfig) {
5455
chart = new Chart(chartConfig);
5556
chart.renderTo('#chart');
@@ -86,7 +87,6 @@ SqlpadTauChart.propTypes = {
8687
isRunning: PropTypes.bool,
8788
chartConfiguration: PropTypes.object,
8889
queryError: PropTypes.string,
89-
queryResult: PropTypes.object,
9090
};
9191

9292
export default SqlpadTauChart;

client/src/common/getTauChartConfig.tsx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import quickFilter from 'taucharts/dist/plugins/quick-filter';
55
import tooltip from 'taucharts/dist/plugins/tooltip';
66
import tcTrendline from 'taucharts/dist/plugins/trendline';
77
import baseUrl from '../utilities/baseUrl';
8+
import { StatementColumn } from '../types';
89

910
/**
1011
* Caution this uses any type for a few things
@@ -25,11 +26,6 @@ interface Field {
2526
inputType: string;
2627
}
2728

28-
interface Column {
29-
name: string;
30-
datatype: string;
31-
}
32-
3329
interface ChartConfiguration {
3430
chartType: string;
3531
fields: StringMap;
@@ -62,13 +58,14 @@ const getUnmetFields = (chartType: string, selectedFieldMap: StringMap) => {
6258

6359
export default function getTauChartConfig(
6460
chartConfiguration: ChartConfiguration,
65-
queryResult: any
61+
columns: StatementColumn[] = [],
62+
rows: any[] = []
6663
) {
6764
if (!chartConfiguration) {
6865
return null;
6966
}
70-
const columns = queryResult ? queryResult.columns : [];
71-
let dataRows = queryResult ? queryResult.rows : [];
67+
68+
let dataRows = rows || [];
7269
const chartType = chartConfiguration.chartType;
7370
const selectedFields = chartConfiguration.fields;
7471

@@ -109,7 +106,7 @@ export default function getTauChartConfig(
109106
// loop through data rows and convert types as needed
110107
dataRows = dataRows.map((row: DataRow) => {
111108
const newRow: DataRow = {};
112-
columns.forEach((col: Column) => {
109+
columns.forEach((col: StatementColumn) => {
113110
const { datatype, name } = col;
114111
if (datatype === 'date' || datatype === 'datetime') {
115112
newRow[name] = new Date(row[name]);
@@ -131,7 +128,7 @@ export default function getTauChartConfig(
131128
forceDimensionFields.forEach((fieldDefinition) => {
132129
const columnName = selectedFields[fieldDefinition.fieldId];
133130
const column = columns.find(
134-
(column: Column) => column.name === columnName
131+
(column: StatementColumn) => column.name === columnName
135132
);
136133
const colDatatype = column ? column.datatype : null;
137134
if (columnName && colDatatype === 'number' && newRow[columnName]) {
@@ -154,7 +151,7 @@ export default function getTauChartConfig(
154151

155152
if (fieldDefinition && fieldDefinition.inputType !== 'field-dropdown') {
156153
fieldsMap[fieldColName] = columnName;
157-
} else if (columns.find((c: Column) => c.name === columnName)) {
154+
} else if (columns.find((c: StatementColumn) => c.name === columnName)) {
158155
fieldsMap[fieldColName] = columnName;
159156
}
160157
return fieldsMap;

client/src/queryEditor/QueryEditorChartToolbar.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@ import React from 'react';
44
import IconButton from '../common/IconButton';
55
import { exportPng } from '../common/tauChartRef';
66
import {
7+
useLastStatementId,
78
useSessionQueryId,
89
useSessionQueryName,
9-
useSessionQueryResult,
10+
useStatementStatus,
1011
} from '../stores/editor-store';
12+
import { api } from '../utilities/api';
1113

1214
function QueryEditorChartToolbar({ children }: any) {
1315
const queryId = useSessionQueryId() || 'new';
1416
const queryName = useSessionQueryName() || 'New query';
15-
const queryResult = useSessionQueryResult();
1617

17-
const downloadEnabled =
18-
queryResult && queryResult.rows && queryResult.rows.length;
18+
const statementId = useLastStatementId();
19+
const status = useStatementStatus(statementId);
20+
const { data } = api.useStatementResults(statementId, status);
21+
22+
const downloadEnabled = data && data.length;
1923

2024
return (
2125
<div

client/src/queryHistory/QueryHistoryResultHeader.module.css

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

client/src/queryHistory/QueryHistoryResultHeader.tsx

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

client/src/stores/editor-actions.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,6 @@ export const loadQuery = async (queryId: string) => {
368368
selectedStatementId: '',
369369
isRunning: false,
370370
queryError: undefined,
371-
queryResult: undefined,
372371
unsavedChanges: false,
373372
});
374373

client/src/stores/editor-store.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export interface EditorSession {
4343
selectedText: string;
4444
selectedStatementId: string;
4545
queryError?: any;
46-
queryResult?: any;
4746
runQueryStartTime?: any;
4847
showValidation: boolean;
4948
unsavedChanges: boolean;
@@ -86,7 +85,6 @@ export const INITIAL_SESSION: EditorSession = {
8685
canWrite: true,
8786
canDelete: true,
8887
queryError: undefined,
89-
queryResult: undefined,
9088
runQueryStartTime: undefined,
9189
selectedText: '',
9290
selectedStatementId: '',
@@ -214,10 +212,6 @@ export function useSessionChartFields() {
214212
return useEditorStore((s) => s.getFocusedSession().chartFields);
215213
}
216214

217-
export function useSessionQueryResult() {
218-
return useEditorStore((s) => s.getFocusedSession().queryResult);
219-
}
220-
221215
export function useSessionQueryError() {
222216
return useEditorStore((s) => {
223217
const { queryError, selectedStatementId } = s.getFocusedSession();

client/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ proxy['^/.*/api/app'] = PROXY_URL;
3131

3232
// https://vitejs.dev/config/
3333
export default defineConfig({
34+
base: '/sqlpad/',
3435
plugins: [reactRefresh()],
3536
server: {
3637
proxy,

0 commit comments

Comments
 (0)