From 1f1d7d7f117c571c156a3fa0e4f1229a17604533 Mon Sep 17 00:00:00 2001 From: Russ <8377044+rdubrock@users.noreply.github.com> Date: Mon, 21 Sep 2020 08:56:20 -0700 Subject: [PATCH] =?UTF-8?q?Explore:=20Keep=20typeahead=20suggestions=20for?= =?UTF-8?q?=20exact=20label=20matches=20in=20Loki=20q=E2=80=A6=20(#27201)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Explore: Keep typeahead suggestions for exact label matches in Loki query editor * Simplify some typing * Explore: filter selected loki label option from suggestions Co-authored-by: kay delaney --- .../datasource/loki/language_provider.test.ts | 28 +++++++++++++++++-- .../datasource/loki/language_provider.ts | 11 ++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/public/app/plugins/datasource/loki/language_provider.test.ts b/public/app/plugins/datasource/loki/language_provider.test.ts index 65f4ed07487..0d42433e492 100644 --- a/public/app/plugins/datasource/loki/language_provider.test.ts +++ b/public/app/plugins/datasource/loki/language_provider.test.ts @@ -91,7 +91,15 @@ describe('Language completion provider', () => { const input = createTypeaheadInput('{}', '', '', 1); const result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock }); expect(result.context).toBe('context-labels'); - expect(result.suggestions).toEqual([{ items: [{ label: 'label1' }, { label: 'label2' }], label: 'Labels' }]); + expect(result.suggestions).toEqual([ + { + items: [ + { label: 'label1', filterText: '"label1"' }, + { label: 'label2', filterText: '"label2"' }, + ], + label: 'Labels', + }, + ]); }); it('returns all label suggestions on selector when starting to type', async () => { @@ -100,7 +108,15 @@ describe('Language completion provider', () => { const input = createTypeaheadInput('{l}', '', '', 2); const result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock }); expect(result.context).toBe('context-labels'); - expect(result.suggestions).toEqual([{ items: [{ label: 'label1' }, { label: 'label2' }], label: 'Labels' }]); + expect(result.suggestions).toEqual([ + { + items: [ + { label: 'label1', filterText: '"label1"' }, + { label: 'label2', filterText: '"label2"' }, + ], + label: 'Labels', + }, + ]); }); }); @@ -140,7 +156,13 @@ describe('Language completion provider', () => { result = await provider.provideCompletionItems(input, { absoluteRange: rangeMock }); expect(result.context).toBe('context-label-values'); expect(result.suggestions).toEqual([ - { items: [{ label: 'label1_val1' }, { label: 'label1_val2' }], label: 'Label values for "label1"' }, + { + items: [ + { label: 'label1_val1', filterText: '"label1_val1"' }, + { label: 'label1_val2', filterText: '"label1_val2"' }, + ], + label: 'Label values for "label1"', + }, ]); }); }); diff --git a/public/app/plugins/datasource/loki/language_provider.ts b/public/app/plugins/datasource/loki/language_provider.ts index 6d671a62773..57985d8bf76 100644 --- a/public/app/plugins/datasource/loki/language_provider.ts +++ b/public/app/plugins/datasource/loki/language_provider.ts @@ -28,7 +28,8 @@ const HISTORY_COUNT_CUTOFF = 1000 * 60 * 60 * 24; // 24h const NS_IN_MS = 1000000; export const LABEL_REFRESH_INTERVAL = 1000 * 30; // 30sec -const wrapLabel = (label: string) => ({ label }); +const wrapLabel = (label: string) => ({ label, filterText: `\"${label}\"` }); + export const rangeToParams = (range: AbsoluteTimeRange) => ({ start: range.from * NS_IN_MS, end: range.to * NS_IN_MS }); export type LokiHistoryItem = HistoryItem; @@ -188,14 +189,14 @@ export default class LokiLanguageProvider extends LanguageProvider { const history = context?.history; const suggestions = []; - if (history && history.length) { + if (history?.length) { const historyItems = _.chain(history) .map(h => h.query.expr) .filter() .uniq() .take(HISTORY_ITEM_COUNT) .map(wrapLabel) - .map((item: CompletionItem) => addHistoryMetadata(item, history)) + .map(item => addHistoryMetadata(item, history)) .value(); suggestions.push({ @@ -287,13 +288,13 @@ export default class LokiLanguageProvider extends LanguageProvider { context = 'context-label-values'; suggestions.push({ label: `Label values for "${labelKey}"`, - items: labelValues[labelKey].map(wrapLabel), + // Filter to prevent previously selected values from being repeatedly suggested + items: labelValues[labelKey].map(wrapLabel).filter(({ filterText }) => filterText !== text), }); } } else { // Label keys const labelKeys = labelValues ? Object.keys(labelValues) : DEFAULT_KEYS; - if (labelKeys) { const possibleKeys = _.difference(labelKeys, existingKeys); if (possibleKeys.length) {