The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/plugins/datasource/loki/components/monaco-query-field/getOverrideServices.ts

112 lines
3.6 KiB

import { monacoTypes } from '@grafana/ui';
// this thing here is a workaround in a way.
// what we want to achieve, is that when the autocomplete-window
// opens, the "second, extra popup" with the extra help,
// also opens automatically.
// but there is no API to achieve it.
// the way to do it is to implement the `storageService`
// interface, and provide our custom implementation,
// which will default to `true` for the correct string-key.
// unfortunately, while the typescript-interface exists,
// it is not exported from monaco-editor,
// so we cannot rely on typescript to make sure
// we do it right. all we can do is to manually
// lookup the interface, and make sure we code our code right.
// our code is a "best effort" approach,
// i am not 100% how the `scope` and `target` things work,
// but so far it seems to work ok.
// i would use an another approach, if there was one available.
function makeStorageService() {
// we need to return an object that fulfills this interface:
// https://github.com/microsoft/vscode/blob/ff1e16eebb93af79fd6d7af1356c4003a120c563/src/vs/platform/storage/common/storage.ts#L37
// unfortunately it is not export from monaco-editor
const strings = new Map<string, string>();
// we want this to be true by default
strings.set('expandSuggestionDocs', true.toString());
return {
// we do not implement the on* handlers
onDidChangeValue: (data: unknown): void => undefined,
onDidChangeTarget: (data: unknown): void => undefined,
onWillSaveState: (data: unknown): void => undefined,
get: (key: string, scope: unknown, fallbackValue?: string): string | undefined => {
return strings.get(key) ?? fallbackValue;
},
getBoolean: (key: string, scope: unknown, fallbackValue?: boolean): boolean | undefined => {
const val = strings.get(key);
if (val !== undefined) {
// the interface docs say the value will be converted
// to a boolean but do not specify how, so we improvise
return val === 'true';
} else {
return fallbackValue;
}
},
getNumber: (key: string, scope: unknown, fallbackValue?: number): number | undefined => {
const val = strings.get(key);
if (val !== undefined) {
return parseInt(val, 10);
} else {
return fallbackValue;
}
},
store: (
key: string,
value: string | boolean | number | undefined | null,
scope: unknown,
target: unknown
): void => {
// the interface docs say if the value is nullish, it should act as delete
if (value === null || value === undefined) {
strings.delete(key);
} else {
strings.set(key, value.toString());
}
},
remove: (key: string, scope: unknown): void => {
strings.delete(key);
},
keys: (scope: unknown, target: unknown): string[] => {
return Array.from(strings.keys());
},
logStorage: (): void => {
console.log('logStorage: not implemented');
},
migrate: (): Promise<void> => {
// we do not implement this
return Promise.resolve(undefined);
},
isNew: (scope: unknown): boolean => {
// we create a new storage for every session, we do not persist it,
// so we return `true`.
return true;
},
flush: (reason?: unknown): Promise<void> => {
// we do not implement this
return Promise.resolve(undefined);
},
};
}
let overrideServices: monacoTypes.editor.IEditorOverrideServices = {
storageService: makeStorageService(),
};
export function getOverrideServices(): monacoTypes.editor.IEditorOverrideServices {
// One instance of this for every query editor
return overrideServices;
}