mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
IntelliSense: Fix autocomplete and highlighting for Loki, Prometheus, Cloudwatch (#29381)
* Pass languages directly to SlatePrism plugin * Update * Remove unused variables * Update packages/grafana-ui/src/components/DataLinks/DataLinkInput.tsx Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/components/PromQueryField.tsx Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/prometheus/components/PromQueryField.tsx Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/loki/components/LokiQueryFieldForm.tsx Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Update public/app/plugins/datasource/cloudwatch/components/LogsQueryField.tsx Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com> * Try Prism import instead of languages * Update webpack Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
This commit is contained in:
parent
3dcfe54d8d
commit
2a61d7ff9f
@ -6,7 +6,7 @@ import { SelectionReference } from './SelectionReference';
|
||||
import { Portal, getFormStyles } from '../index';
|
||||
|
||||
// @ts-ignore
|
||||
import Prism from 'prismjs';
|
||||
import Prism, { Grammar, LanguageMap } from 'prismjs';
|
||||
import { Editor } from '@grafana/slate-react';
|
||||
import { Value } from 'slate';
|
||||
import Plain from 'slate-plain-serializer';
|
||||
@ -27,11 +27,20 @@ interface DataLinkInputProps {
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
const datalinksSyntax: Grammar = {
|
||||
builtInVariable: {
|
||||
pattern: /(\${\S+?})/,
|
||||
},
|
||||
};
|
||||
|
||||
const plugins = [
|
||||
SlatePrism({
|
||||
onlyIn: (node: any) => node.type === 'code_block',
|
||||
getSyntax: () => 'links',
|
||||
}),
|
||||
SlatePrism(
|
||||
{
|
||||
onlyIn: (node: any) => node.type === 'code_block',
|
||||
getSyntax: () => 'links',
|
||||
},
|
||||
{ ...(Prism.languages as LanguageMap), links: datalinksSyntax }
|
||||
),
|
||||
];
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
@ -56,19 +65,10 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
`,
|
||||
}));
|
||||
|
||||
export const enableDatalinksPrismSyntax = () => {
|
||||
Prism.languages['links'] = {
|
||||
builtInVariable: {
|
||||
pattern: /(\${\S+?})/,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// This memoised also because rerendering the slate editor grabs focus which created problem in some cases this
|
||||
// was used and changes to different state were propagated here.
|
||||
export const DataLinkInput: React.FC<DataLinkInputProps> = memo(
|
||||
({ value, onChange, suggestions, placeholder = 'http://your-grafana.com/d/000000010/annotations' }) => {
|
||||
enableDatalinksPrismSyntax();
|
||||
const editorRef = useRef<Editor>() as RefObject<Editor>;
|
||||
const theme = useContext(ThemeContext);
|
||||
const styles = getStyles(theme);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Prism from 'prismjs';
|
||||
import Prism, { LanguageMap } from 'prismjs';
|
||||
import { Block, Text, Decoration } from 'slate';
|
||||
import { Plugin } from '@grafana/slate-react';
|
||||
import Options, { OptionsFormat } from './options';
|
||||
@ -19,7 +19,7 @@ export interface Token {
|
||||
/**
|
||||
* A Slate plugin to highlight code syntax.
|
||||
*/
|
||||
export function SlatePrism(optsParam: OptionsFormat = {}): Plugin {
|
||||
export function SlatePrism(optsParam: OptionsFormat = {}, prismLanguages = Prism.languages as LanguageMap): Plugin {
|
||||
const opts: Options = new Options(optsParam);
|
||||
|
||||
return {
|
||||
@ -30,7 +30,7 @@ export function SlatePrism(optsParam: OptionsFormat = {}): Plugin {
|
||||
|
||||
const block = Block.create(node as Block);
|
||||
const grammarName = opts.getSyntax(block);
|
||||
const grammar = Prism.languages[grammarName];
|
||||
const grammar = prismLanguages[grammarName];
|
||||
|
||||
if (!grammar) {
|
||||
// Grammar not loaded
|
||||
|
@ -192,7 +192,7 @@ const CLIQ_EXAMPLES: QueryExample[] = [
|
||||
];
|
||||
|
||||
function renderHighlightedMarkup(code: string, keyPrefix: string) {
|
||||
const grammar = Prism.languages['cloudwatch'] ?? tokenizer;
|
||||
const grammar = tokenizer;
|
||||
const tokens = flattenTokens(Prism.tokenize(code, grammar));
|
||||
const spans = tokens
|
||||
.filter(token => typeof token !== 'string')
|
||||
|
@ -24,7 +24,7 @@ import syntax from '../syntax';
|
||||
import { ExploreQueryFieldProps, AbsoluteTimeRange, SelectableValue, AppEvents } from '@grafana/data';
|
||||
import { CloudWatchQuery, CloudWatchLogsQuery } from '../types';
|
||||
import { CloudWatchDatasource } from '../datasource';
|
||||
import Prism, { Grammar } from 'prismjs';
|
||||
import { Grammar, LanguageMap, languages as prismLanguages } from 'prismjs';
|
||||
import { CloudWatchLanguageProvider } from '../language_provider';
|
||||
import { css } from 'emotion';
|
||||
import { ExploreId } from 'app/types';
|
||||
@ -95,13 +95,15 @@ export class CloudWatchLogsQueryField extends React.PureComponent<CloudWatchLogs
|
||||
constructor(props: CloudWatchLogsQueryFieldProps, context: React.Context<any>) {
|
||||
super(props, context);
|
||||
|
||||
Prism.languages['cloudwatch'] = syntax;
|
||||
this.plugins = [
|
||||
BracesPlugin(),
|
||||
SlatePrism({
|
||||
onlyIn: (node: Node) => node.object === 'block' && node.type === 'code_block',
|
||||
getSyntax: (node: Node) => 'cloudwatch',
|
||||
}),
|
||||
SlatePrism(
|
||||
{
|
||||
onlyIn: (node: Node) => node.object === 'block' && node.type === 'code_block',
|
||||
getSyntax: (node: Node) => 'cloudwatch',
|
||||
},
|
||||
{ ...(prismLanguages as LanguageMap), cloudwatch: syntax }
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import Prism, { Grammar } from 'prismjs';
|
||||
import { Grammar } from 'prismjs';
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
import { useRefMounted } from 'app/core/hooks/useRefMounted';
|
||||
import { CloudWatchLanguageProvider } from './language_provider';
|
||||
|
||||
const PRISM_SYNTAX = 'cloudwatch';
|
||||
|
||||
/**
|
||||
* Initialise the language provider. Returns a languageProviderInitialized boolean cause there does not seem other way
|
||||
* to know if the provider is already initialised or not. By the initialisation it modifies the provided
|
||||
@ -44,7 +42,6 @@ const useCloudwatchSyntax = (languageProvider: CloudWatchLanguageProvider, langu
|
||||
useEffect(() => {
|
||||
if (languageProviderInitialized) {
|
||||
const syntax = languageProvider.getSyntax();
|
||||
Prism.languages[PRISM_SYNTAX] = syntax;
|
||||
setSyntax(syntax);
|
||||
}
|
||||
}, [languageProviderInitialized, languageProvider]);
|
||||
|
@ -20,7 +20,7 @@ import { Plugin, Node } from 'slate';
|
||||
import { DOMUtil } from '@grafana/ui';
|
||||
import { ExploreQueryFieldProps, AbsoluteTimeRange } from '@grafana/data';
|
||||
import { LokiQuery, LokiOptions } from '../types';
|
||||
import { Grammar } from 'prismjs';
|
||||
import { Grammar, LanguageMap, languages as prismLanguages } from 'prismjs';
|
||||
import LokiLanguageProvider, { LokiHistoryItem } from '../language_provider';
|
||||
import LokiDatasource from '../datasource';
|
||||
import LokiOptionFields from './LokiOptionFields';
|
||||
@ -82,10 +82,13 @@ export class LokiQueryFieldForm extends React.PureComponent<LokiQueryFieldFormPr
|
||||
|
||||
this.plugins = [
|
||||
BracesPlugin(),
|
||||
SlatePrism({
|
||||
onlyIn: (node: Node) => node.object === 'block' && node.type === 'code_block',
|
||||
getSyntax: (node: Node) => 'promql',
|
||||
}),
|
||||
SlatePrism(
|
||||
{
|
||||
onlyIn: (node: Node) => node.object === 'block' && node.type === 'code_block',
|
||||
getSyntax: (node: Node) => 'logql',
|
||||
},
|
||||
{ ...(prismLanguages as LanguageMap), logql: this.props.datasource.languageProvider.getSyntax() }
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import Prism, { Grammar } from 'prismjs';
|
||||
import { Grammar } from 'prismjs';
|
||||
import { AbsoluteTimeRange } from '@grafana/data';
|
||||
import LokiLanguageProvider from 'app/plugins/datasource/loki/language_provider';
|
||||
import { useLokiLabels } from 'app/plugins/datasource/loki/components/useLokiLabels';
|
||||
import { useRefMounted } from 'app/core/hooks/useRefMounted';
|
||||
|
||||
const PRISM_SYNTAX = 'promql';
|
||||
|
||||
/**
|
||||
* Initialise the language provider. Returns a languageProviderInitialized boolean cause there does not seem other way
|
||||
* to know if the provider is already initialised or not. By the initialisation it modifies the provided
|
||||
@ -45,7 +43,6 @@ const useLokiSyntax = (languageProvider: LokiLanguageProvider, languageProviderI
|
||||
useEffect(() => {
|
||||
if (languageProviderInitialized) {
|
||||
const syntax = languageProvider.getSyntax();
|
||||
Prism.languages[PRISM_SYNTAX] = syntax;
|
||||
setSyntax(syntax);
|
||||
}
|
||||
}, [languageProviderInitialized, languageProvider]);
|
||||
|
@ -7,7 +7,11 @@ import { PromQuery } from '../types';
|
||||
import { LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data';
|
||||
|
||||
const setup = (renderMethod: any, propOverrides?: object) => {
|
||||
const datasourceMock: unknown = {};
|
||||
const datasourceMock: unknown = {
|
||||
languageProvider: {
|
||||
syntax: () => {},
|
||||
},
|
||||
};
|
||||
const datasource: PrometheusDatasource = datasourceMock as PrometheusDatasource;
|
||||
const onRunQuery = jest.fn();
|
||||
const onChange = jest.fn();
|
||||
|
@ -17,6 +17,7 @@ describe('PromQueryField', () => {
|
||||
const datasource = ({
|
||||
languageProvider: {
|
||||
start: () => Promise.resolve([]),
|
||||
syntax: () => {},
|
||||
},
|
||||
} as unknown) as DataSourceInstanceSettings<PromOptions>;
|
||||
|
||||
@ -35,10 +36,16 @@ describe('PromQueryField', () => {
|
||||
});
|
||||
|
||||
it('renders a disabled metrics chooser if lookups are disabled in datasource settings', () => {
|
||||
const datasource = ({
|
||||
languageProvider: {
|
||||
start: () => Promise.resolve([]),
|
||||
syntax: () => {},
|
||||
},
|
||||
} as unknown) as DataSourceInstanceSettings<PromOptions>;
|
||||
const queryField = render(
|
||||
<PromQueryField
|
||||
// @ts-ignore
|
||||
datasource={{ lookupsDisabled: true }}
|
||||
datasource={{ ...datasource, lookupsDisabled: true }}
|
||||
query={{ expr: '', refId: '' }}
|
||||
onRunQuery={() => {}}
|
||||
onChange={() => {}}
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
BracesPlugin,
|
||||
} from '@grafana/ui';
|
||||
|
||||
import Prism from 'prismjs';
|
||||
import { LanguageMap, languages as prismLanguages } from 'prismjs';
|
||||
|
||||
// dom also includes Element polyfills
|
||||
import { PromQuery, PromOptions, PromMetricsMetadata } from '../types';
|
||||
@ -22,7 +22,6 @@ import { DOMUtil, SuggestionsState } from '@grafana/ui';
|
||||
import { PrometheusDatasource } from '../datasource';
|
||||
|
||||
const HISTOGRAM_GROUP = '__histograms__';
|
||||
const PRISM_SYNTAX = 'promql';
|
||||
export const RECORDING_RULES_GROUP = '__recording_rules__';
|
||||
|
||||
function getChooserText(metricsLookupDisabled: boolean, hasSyntax: boolean, metrics: string[]) {
|
||||
@ -133,10 +132,13 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
|
||||
this.plugins = [
|
||||
BracesPlugin(),
|
||||
SlatePrism({
|
||||
onlyIn: (node: any) => node.type === 'code_block',
|
||||
getSyntax: (node: any) => 'promql',
|
||||
}),
|
||||
SlatePrism(
|
||||
{
|
||||
onlyIn: (node: any) => node.type === 'code_block',
|
||||
getSyntax: (node: any) => 'promql',
|
||||
},
|
||||
{ ...(prismLanguages as LanguageMap), promql: this.props.datasource.languageProvider.syntax }
|
||||
),
|
||||
];
|
||||
|
||||
this.state = {
|
||||
@ -222,7 +224,6 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
datasource: { languageProvider },
|
||||
} = this.props;
|
||||
|
||||
Prism.languages[PRISM_SYNTAX] = languageProvider.syntax;
|
||||
this.languageProviderInitializationPromise = makePromiseCancelable(languageProvider.start());
|
||||
|
||||
try {
|
||||
|
@ -45,7 +45,13 @@ exports[`PromExploreQueryEditor should render component 1`] = `
|
||||
},
|
||||
}
|
||||
}
|
||||
datasource={Object {}}
|
||||
datasource={
|
||||
Object {
|
||||
"languageProvider": Object {
|
||||
"syntax": [Function],
|
||||
},
|
||||
}
|
||||
}
|
||||
history={Array []}
|
||||
onBlur={[Function]}
|
||||
onChange={[MockFunction]}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Grammar } from 'prismjs';
|
||||
import { CompletionItem } from '@grafana/ui';
|
||||
|
||||
export const RATE_RANGES: CompletionItem[] = [
|
||||
@ -376,7 +377,7 @@ export const FUNCTIONS = [
|
||||
},
|
||||
];
|
||||
|
||||
const tokenizer = {
|
||||
const tokenizer: Grammar = {
|
||||
comment: {
|
||||
pattern: /#.*/,
|
||||
},
|
||||
|
@ -48,6 +48,9 @@ module.exports = {
|
||||
// storybook v6 bump caused the app to bundle multiple versions of react breaking hooks
|
||||
// make sure to resolve only from the project: https://github.com/facebook/react/issues/13991#issuecomment-435587809
|
||||
react: path.resolve(__dirname, '../../node_modules/react'),
|
||||
// some of data source pluginis use global Prism object to add the language definition
|
||||
// we want to have same Prism object in core and in grafana/ui
|
||||
prismjs: path.resolve(__dirname, '../../node_modules/prismjs'),
|
||||
},
|
||||
modules: [
|
||||
'node_modules',
|
||||
|
Loading…
Reference in New Issue
Block a user