grafana/public/app/plugins/datasource/cloudwatch/components/SQLCodeEditor.tsx
Sarah Zinger 58a71c7e91
Cloudwatch: Add syntax highlighting and autocomplete for "Metric Search" (#43985)
* Create a "monarch" folder with everything you need to do syntax highlighting and autocompletion.

* Use this new monarch folder with existing cloudwatch sql.

* Add metric math syntax highlighting and autocomplete.

* Make autocomplete "smarter":
- search always inserts a string as first arg
- strings can't contain predefined functions
- operators follow the last closing )

* Add some tests for Metric Math's CompletionItemProvider.

* Fixes After CR:
- refactor CompletionItemProvider, so that it only requires args that are dynamic or outside of it's responsibility
- Update and add tests with mocked monaco
- Add more autocomplete suggestions for SEARCH expression functions
- sort keywords and give different priority from function to make more visually distinctive.

* Change QueryEditor to auto-resize and look more like the one in Prometheus.

* Add autocomplete for time periods for the third arg of Search.

* More CR fixes:
- fix missing break
- add unit tests for statementPosition
- fix broken time period
- sort time periods

* Bug fix
2022-02-01 22:53:32 -05:00

51 lines
1.6 KiB
TypeScript

import React, { FunctionComponent, useCallback, useEffect } from 'react';
import type * as monacoType from 'monaco-editor/esm/vs/editor/editor.api';
import { CodeEditor, Monaco } from '@grafana/ui';
import { CloudWatchDatasource } from '../datasource';
import language from '../cloudwatch-sql/definition';
import { TRIGGER_SUGGEST } from '../monarch/commands';
import { registerLanguage } from '../monarch/register';
export interface Props {
region: string;
sql: string;
onChange: (sql: string) => void;
onRunQuery: () => void;
datasource: CloudWatchDatasource;
}
export const SQLCodeEditor: FunctionComponent<Props> = ({ region, sql, onChange, onRunQuery, datasource }) => {
useEffect(() => {
datasource.sqlCompletionItemProvider.setRegion(region);
}, [region, datasource]);
const onEditorMount = useCallback(
(editor: monacoType.editor.IStandaloneCodeEditor, monaco: Monaco) => {
editor.onDidFocusEditorText(() => editor.trigger(TRIGGER_SUGGEST.id, TRIGGER_SUGGEST.id, {}));
editor.addCommand(monaco.KeyMod.Shift | monaco.KeyCode.Enter, () => {
const text = editor.getValue();
onChange(text);
onRunQuery();
});
},
[onChange, onRunQuery]
);
return (
<CodeEditor
height={'150px'}
language={language.id}
value={sql}
onBlur={(value) => {
if (value !== sql) {
onChange(value);
}
}}
showMiniMap={false}
showLineNumbers={true}
onBeforeEditorMount={(monaco: Monaco) => registerLanguage(monaco, language, datasource.sqlCompletionItemProvider)}
onEditorDidMount={onEditorMount}
/>
);
};