Skip to content

Commit

Permalink
Merge branch 'main' into forward-http-headers-from-grafana-option
Browse files Browse the repository at this point in the history
  • Loading branch information
asimpson authored Feb 20, 2024
2 parents 2f69b38 + 409f765 commit da85657
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 89 deletions.
21 changes: 1 addition & 20 deletions src/components/SqlEditor.test.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { SqlEditor } from './SqlEditor';
import * as ui from '@grafana/ui';
import { mockDatasource } from '__mocks__/datasource';
import { EditorType } from 'types/sql';
import { Components } from 'selectors';

jest.mock('@grafana/ui', () => ({
...jest.requireActual<typeof ui>('@grafana/ui'),
Expand Down Expand Up @@ -35,21 +33,4 @@ describe('SQL Editor', () => {
);
expect(screen.queryByText(rawSql)).toBeInTheDocument();
});
it('Should Expand Query', async () => {
const onChange = jest.fn();
const onRunQuery = jest.fn();
const result = await waitFor(() =>
render(
<SqlEditor
query={{ pluginVersion: '', rawSql: 'test', refId: 'A', editorType: EditorType.SQL }}
onChange={onChange}
onRunQuery={onRunQuery}
datasource={mockDatasource}
/>
));

expect(result.queryByText('test')).toBeInTheDocument();
await userEvent.click(result.getByTestId(Components.QueryEditor.CodeEditor.Expand));
expect(onChange).toHaveBeenCalledTimes(0); // TODO: codeEditor isn't mounting and wont call onChange
});
});
91 changes: 22 additions & 69 deletions src/components/SqlEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React, { useState } from 'react';
import React from 'react';
import { CoreApp, QueryEditorProps } from '@grafana/data';
import { CodeEditor } from '@grafana/ui';
import { CodeEditor, monacoTypes } from '@grafana/ui';
import { Datasource } from 'data/CHDatasource';
import { registerSQL, Range, Fetcher } from './sqlProvider';
import { CHConfig } from 'types/config';
import { CHQuery, EditorType, CHSqlQuery } from 'types/sql';
import { styles } from 'styles';
import { fetchSuggestions, Schema } from './suggestions';
import { selectors } from 'selectors';
import { validate } from 'data/validate';
import { mapQueryTypeToGrafanaFormat } from 'data/utils';
import { QueryType } from 'types/queryBuilder';
Expand All @@ -16,22 +15,24 @@ import { pluginVersion } from 'utils/version';

type SqlEditorProps = QueryEditorProps<Datasource, CHQuery, CHConfig>;

interface Expand {
height: string;
icon: 'plus' | 'minus';
on: boolean;
function setupAutoSize(editor: monacoTypes.editor.IStandaloneCodeEditor) {
const container = editor.getDomNode();
const updateHeight = () => {
if (container) {
const contentHeight = Math.max(100, Math.min(1000, editor.getContentHeight()));
const width = parseInt(container.style.width, 10);
container.style.width = `${width}px`;
container.style.height = `${contentHeight}px`;
editor.layout({ width, height: contentHeight });
}
};
editor.onDidContentSizeChange(updateHeight);
updateHeight();
}

export const SqlEditor = (props: SqlEditorProps) => {
const defaultHeight = '150px';
const { app, query, onChange, datasource } = props;
const sqlQuery = query as CHSqlQuery;
const [codeEditor, setCodeEditor] = useState<any>();
const [expand, setExpand] = useState<Expand>({
height: defaultHeight,
icon: 'plus',
on: sqlQuery.expand || false,
});
const queryType = sqlQuery.queryType || QueryType.Table;

const saveChanges = (changes: Partial<CHSqlQuery>) => {
Expand All @@ -40,31 +41,8 @@ export const SqlEditor = (props: SqlEditorProps) => {
pluginVersion,
editorType: EditorType.SQL,
format: mapQueryTypeToGrafanaFormat(changes.queryType || queryType),
...changes
...changes,
});
}

const updateExpand = (expand: Expand) => {
setExpand(expand);
saveChanges({ expand: expand.on });
}

const onToggleExpand = () => {
const on = !expand.on;
const icon = on ? 'minus' : 'plus';

if (!codeEditor) {
return;
}
if (on) {
codeEditor.expanded = true;
const height = getEditorHeight(codeEditor);
updateExpand({ height: `${height}px`, on, icon });
return;
}

codeEditor.expanded = false;
updateExpand({ height: defaultHeight, icon, on });
};

const schema: Schema = {
Expand Down Expand Up @@ -101,60 +79,35 @@ export const SqlEditor = (props: SqlEditorProps) => {

const handleMount = (editor: any) => {
const me = registerSQL('chSql', editor, getSuggestions);
editor.expanded = (query as CHSqlQuery).expand;
editor.onDidChangeModelDecorations((a: any) => {
if (editor.expanded) {
const height = getEditorHeight(editor);
updateExpand({ height: `${height}px`, on: true, icon: 'minus' });
}
});
setupAutoSize(editor);
editor.onKeyUp((e: any) => {
if (datasource.settings.jsonData.validateSql) {
const sql = editor.getValue();
validateSql(sql, editor.getModel(), me);
}
});
setCodeEditor(editor);
};

return (
<>
{/* Only show in explore view where panel can't be manually selected. Dashboard view lets you change the panel. */}
{ app === CoreApp.Explore &&
{app === CoreApp.Explore && (
<div className={'gf-form ' + styles.QueryEditor.queryType}>
<QueryTypeSwitcher queryType={queryType} onChange={queryType => saveChanges({ queryType })} sqlEditor />
<QueryTypeSwitcher queryType={queryType} onChange={(queryType) => saveChanges({ queryType })} sqlEditor />
</div>
}
)}
<div className={styles.Common.wrapper}>
<a
onClick={() => onToggleExpand()}
className={styles.Common.expand}
data-testid={selectors.components.QueryEditor.CodeEditor.Expand}
>
<i className={`fa fa-${expand.icon}`}></i>
</a>
<CodeEditor
aria-label="SQL Editor"
height={expand.height}
language="sql"
value={query.rawSql}
onSave={sql => saveChanges({ rawSql: sql })}
onSave={(sql) => saveChanges({ rawSql: sql })}
showMiniMap={false}
showLineNumbers={true}
onBlur={sql => saveChanges({ rawSql: sql })}
onBlur={(sql) => saveChanges({ rawSql: sql })}
onEditorDidMount={(editor: any) => handleMount(editor)}
/>
</div>
</>
);
};

const getEditorHeight = (editor: any): number | undefined => {
const editorElement = editor.getDomNode();
if (!editorElement) {
return;
}

const lineCount = editor.getModel()?.getLineCount() || 1;
return editor.getTopForLineNumber(lineCount + 1) + 40;
};

0 comments on commit da85657

Please sign in to comment.