diff --git a/.betterer.results.json b/.betterer.results.json
index 4dd7405a36d..abeb9276cfb 100644
--- a/.betterer.results.json
+++ b/.betterer.results.json
@@ -1028,12 +1028,6 @@
"count": 5
}
],
- "/packages/grafana-ui/src/components/Splitter/Splitter.tsx": [
- {
- "message": "Do not use any type assertions.",
- "count": 1
- }
- ],
"/packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx": [
{
"message": "Unexpected any. Specify a different type.",
diff --git a/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx b/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx
index 48613c882e1..758dfc7055c 100644
--- a/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx
+++ b/public/app/plugins/datasource/loki/components/VariableQueryEditor.test.tsx
@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
import React from 'react';
import { select } from 'react-select-event';
+import { TimeRange, dateTime } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime';
import { createLokiDatasource } from '../__mocks__/datasource';
@@ -133,4 +134,132 @@ describe('LokiVariableQueryEditor', () => {
await select(screen.getByLabelText('Label'), 'luna', { container: document.body });
await screen.findByText('luna');
});
+
+ test('Calls language provider fetchLabels with the time range received in props', async () => {
+ const now = dateTime('2023-09-16T21:26:00Z');
+ const range: TimeRange = {
+ from: dateTime(now).subtract(2, 'days'),
+ to: now,
+ raw: {
+ from: 'now-2d',
+ to: 'now',
+ },
+ };
+ props.range = range;
+ props.query = {
+ refId: 'test',
+ type: LokiVariableQueryType.LabelValues,
+ label: 'luna',
+ };
+
+ render();
+ await waitFor(() =>
+ expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledWith({ timeRange: range })
+ );
+ });
+
+ test('does not re-run fetch labels when type does not change', async () => {
+ const now = dateTime('2023-09-16T21:26:00Z');
+ const range: TimeRange = {
+ from: dateTime(now).subtract(2, 'days'),
+ to: now,
+ raw: {
+ from: 'now-2d',
+ to: 'now',
+ },
+ };
+ props.range = range;
+ props.query = {
+ refId: 'test',
+ type: LokiVariableQueryType.LabelValues,
+ };
+
+ props.datasource.languageProvider.fetchLabels = jest.fn().mockResolvedValue([]);
+ const { rerender } = render();
+ rerender(
+
+ );
+
+ await waitFor(() => {
+ expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ test('runs fetch labels when type changes to from LabelNames to LabelValues', async () => {
+ const now = dateTime('2023-09-16T21:26:00Z');
+ const range: TimeRange = {
+ from: dateTime(now).subtract(2, 'days'),
+ to: now,
+ raw: {
+ from: 'now-2d',
+ to: 'now',
+ },
+ };
+ props.range = range;
+ props.query = {
+ refId: 'test',
+ type: LokiVariableQueryType.LabelNames,
+ };
+
+ props.datasource.languageProvider.fetchLabels = jest.fn().mockResolvedValue([]);
+ const { rerender } = render();
+ rerender(
+
+ );
+
+ await waitFor(() => {
+ expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ test('runs fetch labels when type changes to LabelValues', async () => {
+ const now = dateTime('2023-09-16T21:26:00Z');
+ const range: TimeRange = {
+ from: dateTime(now).subtract(2, 'days'),
+ to: now,
+ raw: {
+ from: 'now-2d',
+ to: 'now',
+ },
+ };
+ props.range = range;
+ props.query = {
+ refId: 'test',
+ type: LokiVariableQueryType.LabelNames,
+ };
+
+ props.datasource.languageProvider.fetchLabels = jest.fn().mockResolvedValue([]);
+ // Starting with LabelNames
+ const { rerender } = render();
+
+ // Changing to LabelValues, should run fetchLabels
+ rerender(
+
+ );
+ await waitFor(() => {
+ expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
+ });
+
+ // Keeping the type of LabelValues, should not run additional fetchLabels
+ rerender(
+
+ );
+ await waitFor(() => {
+ expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
+ });
+
+ // Changing to LabelNames, should not run additional fetchLabels
+ rerender();
+ await waitFor(() => {
+ expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(1);
+ });
+
+ // Changing to LabelValues, should run additional fetchLabels
+ rerender(
+
+ );
+ await waitFor(() => {
+ expect(props.datasource.languageProvider.fetchLabels).toHaveBeenCalledTimes(2);
+ });
+ });
});
diff --git a/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx b/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx
index 749b564b80a..63246b73657 100644
--- a/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx
+++ b/public/app/plugins/datasource/loki/components/VariableQueryEditor.tsx
@@ -1,4 +1,5 @@
import React, { FormEvent, useState, useEffect } from 'react';
+import { usePrevious } from 'react-use';
import { QueryEditorProps, SelectableValue } from '@grafana/data';
import { InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
@@ -16,11 +17,12 @@ export type Props = QueryEditorProps {
+export const LokiVariableQueryEditor = ({ onChange, query, datasource, range }: Props) => {
const [type, setType] = useState(undefined);
const [label, setLabel] = useState('');
const [labelOptions, setLabelOptions] = useState>>([]);
const [stream, setStream] = useState('');
+ const previousType = usePrevious(type);
useEffect(() => {
if (!query) {
@@ -34,14 +36,15 @@ export const LokiVariableQueryEditor = ({ onChange, query, datasource }: Props)
}, [query]);
useEffect(() => {
- if (type !== QueryType.LabelValues) {
+ // Fetch label names when the query type is LabelValues, and the previous type was not the same
+ if (type !== QueryType.LabelValues || previousType === type) {
return;
}
- datasource.languageProvider.fetchLabels().then((labelNames: string[]) => {
+ datasource.languageProvider.fetchLabels({ timeRange: range }).then((labelNames) => {
setLabelOptions(labelNames.map((labelName) => ({ label: labelName, value: labelName })));
});
- }, [datasource, type]);
+ }, [datasource, type, range, previousType]);
const onQueryTypeChange = (newType: SelectableValue) => {
setType(newType.value);