1import { CodeEditor, Monaco, MonacoEditor } from '@grafana/ui';
2import { Deferred } from 'app/core/utils/deferred';
3import React, { useCallback, useEffect, useRef } from 'react';
4import { AzureQueryEditorFieldProps } from '../../types';
5import { setKustoQuery } from './setQueryValue';
6
7interface MonacoPromise {
8  editor: MonacoEditor;
9  monaco: Monaco;
10}
11
12interface MonacoLanguages {
13  kusto: {
14    getKustoWorker: () => Promise<
15      (
16        url: any
17      ) => Promise<{
18        setSchema: (schema: any, clusterUrl: string, name: string) => void;
19      }>
20    >;
21  };
22}
23
24const QueryField: React.FC<AzureQueryEditorFieldProps> = ({ query, datasource, onQueryChange }) => {
25  const monacoPromiseRef = useRef<Deferred<MonacoPromise>>();
26  function getPromise() {
27    if (!monacoPromiseRef.current) {
28      monacoPromiseRef.current = new Deferred<MonacoPromise>();
29    }
30
31    return monacoPromiseRef.current.promise;
32  }
33
34  useEffect(() => {
35    if (!query.azureLogAnalytics?.resource) {
36      return;
37    }
38
39    const promises = [
40      datasource.azureLogAnalyticsDatasource.getKustoSchema(query.azureLogAnalytics.resource),
41      getPromise(),
42    ] as const;
43
44    // the kusto schema call might fail, but its okay for that to happen silently
45    Promise.all(promises).then(([schema, { monaco, editor }]) => {
46      const languages = (monaco.languages as unknown) as MonacoLanguages;
47
48      languages.kusto
49        .getKustoWorker()
50        .then((kusto) => {
51          const model = editor.getModel();
52          return model && kusto(model.uri);
53        })
54        .then((worker) => {
55          worker?.setSchema(schema, 'https://help.kusto.windows.net', 'Samples');
56        });
57    });
58  }, [datasource.azureLogAnalyticsDatasource, query.azureLogAnalytics?.resource]);
59
60  const handleEditorMount = useCallback((editor: MonacoEditor, monaco: Monaco) => {
61    monacoPromiseRef.current?.resolve?.({ editor, monaco });
62  }, []);
63
64  const onChange = useCallback(
65    (newQuery: string) => {
66      onQueryChange(setKustoQuery(query, newQuery));
67    },
68    [onQueryChange, query]
69  );
70
71  return (
72    <CodeEditor
73      value={query.azureLogAnalytics?.query ?? ''}
74      language="kusto"
75      height={200}
76      width="100%"
77      showMiniMap={false}
78      onBlur={onChange}
79      onSave={onChange}
80      onEditorDidMount={handleEditorMount}
81    />
82  );
83};
84
85export default QueryField;
86