Skip to content

Commit b5a9121

Browse files
authored
feat: support for schema autocomplete for queries. (#18)
fix: load monaco kusto once. fix: split kusto monaco and others.
1 parent 8ba47f7 commit b5a9121

5 files changed

Lines changed: 144 additions & 10 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<template>
2+
<div :style="$attrs.style" />
3+
</template>
4+
<script>
5+
import loader from '@monaco-editor/loader';
6+
import loadMonacoKusto from '@/helpers/loadMonacoKusto';
7+
import { getKustoSchema } from '@/helpers/apiClient';
8+
9+
export default {
10+
name: 'KustoMonacoEditor',
11+
model: {
12+
event: 'change',
13+
},
14+
props: {
15+
options: {
16+
default: () => {},
17+
type: Object,
18+
},
19+
value: {
20+
type: String,
21+
required: true,
22+
},
23+
cluster: {
24+
type: String,
25+
default: null,
26+
},
27+
database: {
28+
type: String,
29+
default: null,
30+
},
31+
},
32+
data: () => ({
33+
monaco: null,
34+
editor: null,
35+
}),
36+
watch: {
37+
value(newValue) {
38+
if (this.editor && this.value !== this.editor.getValue()) {
39+
this.editor.setValue(newValue);
40+
}
41+
},
42+
cluster(newCluster, oldCluster) {
43+
if (newCluster && oldCluster !== newCluster) {
44+
this.loadSchema();
45+
}
46+
},
47+
database(newDatabase, oldDatabase) {
48+
if (newDatabase && oldDatabase !== newDatabase) {
49+
this.loadSchema();
50+
}
51+
},
52+
},
53+
mounted() {
54+
this.initialiseMonaco();
55+
},
56+
methods: {
57+
async initialiseMonaco() {
58+
loader.config({
59+
paths: {
60+
vs: `${import.meta.env.BASE_URL}monaco-editor/min/vs`,
61+
},
62+
});
63+
64+
const monaco = await loader.init();
65+
this.monaco = monaco;
66+
67+
await loadMonacoKusto();
68+
console.log('Loaded monaco kusto.');
69+
70+
this.editor = monaco.editor.create(
71+
this.$el,
72+
{
73+
value: this.value,
74+
language: 'kusto',
75+
...this.options,
76+
},
77+
);
78+
this.editor.onDidChangeModelContent(() => {
79+
const value = this.editor.getValue();
80+
if (this.value !== value) {
81+
this.$emit('change', value);
82+
}
83+
});
84+
},
85+
async loadSchema() {
86+
if (this.cluster === '' || this.database === '') {
87+
return;
88+
}
89+
90+
const schema = await this.parseSchema();
91+
const workerAccessor = await this.monaco.languages.kusto.getKustoWorker();
92+
const model = this.editor.getModel();
93+
const worker = await workerAccessor(model.uri);
94+
await worker.setSchemaFromShowSchema(
95+
schema,
96+
this.cluster,
97+
this.database,
98+
);
99+
},
100+
async parseSchema() {
101+
const schema = await getKustoSchema(this.cluster, this.database);
102+
return JSON.parse(schema?.data?.at(0)?.ClusterSchema);
103+
},
104+
},
105+
};
106+
</script>

frontend/src/components/KustoQueryResult.vue

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
<v-icon>mdi-help-circle-outline</v-icon>
9898
</v-btn>
9999
</p>
100-
<MonacoEditor
100+
<KustoMonacoEditor
101101
v-model="editParams.query"
102102
style="
103103
width: 100%;
@@ -107,7 +107,8 @@
107107
resize: vertical;
108108
overflow: hidden;
109109
"
110-
language="kusto"
110+
:cluster="editParams.cluster"
111+
:database="editParams.database"
111112
:options="options"
112113
/>
113114
</v-form>
@@ -141,7 +142,7 @@ import {
141142
import KustoPivot from '@/components/grids/KustoPivot.vue';
142143
import NewQueryButton from '@/components/NewQueryButton.vue';
143144
import eventBus from '@/helpers/eventBus';
144-
import MonacoEditor from '@/components/MonacoEditor.vue';
145+
import KustoMonacoEditor from '@/components/KustoMonacoEditor.vue';
145146
import TimeSelection from '@/components/TimeSelection.vue';
146147
import QueryHelperDialog from '@/components/QueryHelperDialog.vue';
147148
import ClusterSelection from '@/components/ClusterSelection.vue';
@@ -154,7 +155,7 @@ export default {
154155
TimeSelection,
155156
NewQueryButton,
156157
KustoPivot,
157-
MonacoEditor,
158+
KustoMonacoEditor,
158159
},
159160
props: {
160161
uuid: {

frontend/src/components/MonacoEditor.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
</template>
44
<script>
55
import loader from '@monaco-editor/loader';
6-
import loadMonacoKusto from '@/helpers/loadMonacoKusto';
76
87
export default {
9-
name: 'Editor',
8+
name: 'MonacoEditor',
109
model: {
1110
event: 'change',
1211
},
@@ -46,7 +45,6 @@ export default {
4645
});
4746
4847
const monaco = await loader.init();
49-
await loadMonacoKusto();
5048
5149
this.editor = monaco.editor.create(
5250
this.$el,

frontend/src/helpers/apiClient.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export const executeQuery = async (
100100
...additionalParameters,
101101
};
102102

103-
return axios.post(`${runtimeConfig.apiEndpoint}query/executeQuery`, body, {
103+
return axios.post(`${runtimeConfig.apiEndpoint}kusto/query`, body, {
104104
headers,
105105
});
106106
};
@@ -113,11 +113,31 @@ export const getQueryResult = async (queryRunId) => {
113113
};
114114

115115
return axios.get(
116-
`${runtimeConfig.apiEndpoint}query/getQueryResult?queryRunId=${queryRunId}`,
116+
`${runtimeConfig.apiEndpoint}kusto/query/${queryRunId}`,
117117
{ headers },
118118
);
119119
};
120120

121+
export const getKustoSchema = async (
122+
cluster,
123+
database,
124+
) => {
125+
const accessToken = await auth.getApiToken();
126+
127+
const headers = {
128+
Authorization: `Bearer ${accessToken}`,
129+
};
130+
131+
const body = {
132+
cluster,
133+
database,
134+
};
135+
136+
return axios.post(`${runtimeConfig.apiEndpoint}kusto/schema`, body, {
137+
headers,
138+
});
139+
};
140+
121141
export const saveEvents = async (events) => {
122142
const accessToken = await auth.getApiToken();
123143

frontend/src/helpers/loadMonacoKusto.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Original source code: https://github.com/grafana/grafana/pull/33528
22

3+
let promise = null;
4+
35
const loadMonacoKusto = () => new Promise((resolve) => {
46
window.monacoKustoResolvePromise = resolve;
57

@@ -24,7 +26,7 @@ const loadScript = (script) => new Promise((resolve, reject) => {
2426
document.body.appendChild(scriptEl);
2527
});
2628

27-
const loadKusto = async () => {
29+
const loadScripts = async () => {
2830
const scripts = [
2931
`${import.meta.env.BASE_URL}monaco-editor/min/vs/language/kusto/kusto.javascript.client.min.js`,
3032
`${import.meta.env.BASE_URL}monaco-editor/min/vs/language/kusto/newtonsoft.json.min.js`,
@@ -39,4 +41,11 @@ const loadKusto = async () => {
3941
await loadMonacoKusto();
4042
};
4143

44+
const loadKusto = async () => {
45+
if (promise === null) {
46+
promise = loadScripts();
47+
}
48+
return promise;
49+
};
50+
4251
export default loadKusto;

0 commit comments

Comments
 (0)