diff --git a/.betterer.results b/.betterer.results
index a5ae922b47a..46ecf2ed512 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -4144,9 +4144,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"]
],
- "public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxCheatSheet.tsx:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
- ],
"public/app/plugins/datasource/influxdb/datasource.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxCheatSheet.tsx b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxCheatSheet.tsx
index 7bf562c2cff..04b573159c6 100644
--- a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxCheatSheet.tsx
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxCheatSheet.tsx
@@ -8,7 +8,7 @@ const CHEAT_SHEET_ITEMS = [
},
];
-const InfluxCheatSheet = (props: any) => (
+export const InfluxCheatSheet = () => (
InfluxDB Cheat Sheet
{CHEAT_SHEET_ITEMS.map((item) => (
@@ -19,5 +19,3 @@ const InfluxCheatSheet = (props: any) => (
))}
);
-
-export default InfluxCheatSheet;
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxStartPage.tsx b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxStartPage.tsx
index f5ac86a24d2..10f35190d08 100644
--- a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxStartPage.tsx
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/InfluxStartPage.tsx
@@ -1,11 +1,7 @@
-import React, { PureComponent } from 'react';
+import React from 'react';
-import { QueryEditorHelpProps } from '@grafana/data';
+import { InfluxCheatSheet } from './InfluxCheatSheet';
-import InfluxCheatSheet from './InfluxCheatSheet';
-
-export default class InfluxStartPage extends PureComponent {
- render() {
- return ;
- }
+export function InfluxStartPage() {
+ return ;
}
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/code/RawInfluxQLEditor.tsx b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/code/RawInfluxQLEditor.tsx
index 887bec9ee93..0df57b7b26d 100644
--- a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/code/RawInfluxQLEditor.tsx
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/code/RawInfluxQLEditor.tsx
@@ -4,7 +4,7 @@ import { HorizontalGroup, InlineFormLabel, Input, Select, TextArea } from '@graf
import { InfluxQuery } from '../../../../../types';
import { DEFAULT_RESULT_FORMAT, RESULT_FORMATS } from '../../../constants';
-import { useShadowedState } from '../../hooks/useShadowedState';
+import { useShadowedState } from '../hooks/useShadowedState';
type Props = {
query: InfluxQuery;
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useRetentionPolicies.test.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useRetentionPolicies.test.ts
new file mode 100644
index 00000000000..e4648e2f1e7
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useRetentionPolicies.test.ts
@@ -0,0 +1,44 @@
+import { renderHook } from '@testing-library/react-hooks';
+
+import config from 'app/core/config';
+
+import { getMockDS, getMockDSInstanceSettings, mockBackendService } from '../../../../../specs/mocks';
+
+import { useRetentionPolicies } from './useRetentionPolicies';
+
+jest.mock('@grafana/runtime', () => ({
+ ...jest.requireActual('@grafana/runtime'),
+}));
+
+describe('useRetentionPolicies', () => {
+ it('should return all policies when influxdbBackendMigration feature toggle enabled', async () => {
+ const instanceSettings = getMockDSInstanceSettings();
+ const datasource = getMockDS(instanceSettings);
+ mockBackendService(response);
+
+ config.featureToggles.influxdbBackendMigration = true;
+ const { result, waitForNextUpdate } = renderHook(() => useRetentionPolicies(datasource));
+ await waitForNextUpdate();
+ expect(result.current.retentionPolicies.length).toEqual(4);
+ expect(result.current.retentionPolicies[0]).toEqual('autogen');
+ });
+});
+
+const response = {
+ data: {
+ results: {
+ metadataQuery: {
+ status: 200,
+ frames: [
+ {
+ schema: {
+ refId: 'metadataQuery',
+ fields: [{ name: 'value', type: 'string', typeInfo: { frame: 'string' } }],
+ },
+ data: { values: [['autogen', 'bar', '5m_avg', '1m_avg']] },
+ },
+ ],
+ },
+ },
+ },
+};
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useRetentionPolicies.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useRetentionPolicies.ts
new file mode 100644
index 00000000000..c25b795294c
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useRetentionPolicies.ts
@@ -0,0 +1,15 @@
+import { useEffect, useState } from 'react';
+
+import InfluxDatasource from '../../../../../datasource';
+import { getAllPolicies } from '../../../../../influxql_metadata_query';
+
+export const useRetentionPolicies = (datasource: InfluxDatasource) => {
+ const [retentionPolicies, setRetentionPolicies] = useState([]);
+ useEffect(() => {
+ getAllPolicies(datasource).then((data) => {
+ setRetentionPolicies(data);
+ });
+ }, [datasource]);
+
+ return { retentionPolicies };
+};
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/hooks/useShadowedState.test.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useShadowedState.test.ts
similarity index 100%
rename from public/app/plugins/datasource/influxdb/components/editor/query/hooks/useShadowedState.test.ts
rename to public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useShadowedState.test.ts
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/hooks/useShadowedState.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useShadowedState.ts
similarity index 100%
rename from public/app/plugins/datasource/influxdb/components/editor/query/hooks/useShadowedState.ts
rename to public/app/plugins/datasource/influxdb/components/editor/query/influxql/hooks/useShadowedState.ts
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/filterTags.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/filterTags.ts
new file mode 100644
index 00000000000..904de835063
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/filterTags.ts
@@ -0,0 +1,7 @@
+// it is possible to add fields into the `InfluxQueryTag` structures, and they do work,
+// but in some cases, when we do metadata queries, we have to remove them from the queries.
+import { InfluxQueryTag } from '../../../../../types';
+
+export function filterTags(parts: InfluxQueryTag[], allTagKeys: Set): InfluxQueryTag[] {
+ return parts.filter((t) => t.key.endsWith('::tag') || allTagKeys.has(t.key + '::tag'));
+}
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/getTemplateVariableOptions.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/getTemplateVariableOptions.ts
new file mode 100644
index 00000000000..51db862e4d9
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/getTemplateVariableOptions.ts
@@ -0,0 +1,12 @@
+import { TypedVariableModel } from '@grafana/data/src';
+import { getTemplateSrv } from '@grafana/runtime/src';
+
+export function getTemplateVariableOptions(wrapper: (v: TypedVariableModel) => string) {
+ return (
+ getTemplateSrv()
+ .getVariables()
+ // we make them regex-params, i'm not 100% sure why.
+ // probably because this way multi-value variables work ok too.
+ .map(wrapper)
+ );
+}
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/withTemplateVariableOptions.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/withTemplateVariableOptions.ts
new file mode 100644
index 00000000000..89bd1372bcd
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/withTemplateVariableOptions.ts
@@ -0,0 +1,16 @@
+// helper function to make it easy to call this from the widget-render-code
+import { TypedVariableModel } from '@grafana/data/src';
+
+import { getTemplateVariableOptions } from './getTemplateVariableOptions';
+
+export function withTemplateVariableOptions(
+ optionsPromise: Promise,
+ wrapper: (v: TypedVariableModel) => string,
+ filter?: string
+): Promise {
+ let templateVariableOptions = getTemplateVariableOptions(wrapper);
+ if (filter) {
+ templateVariableOptions = templateVariableOptions.filter((tvo) => tvo.indexOf(filter) > -1);
+ }
+ return optionsPromise.then((options) => [...templateVariableOptions, ...options]);
+}
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/wrapper.ts b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/wrapper.ts
new file mode 100644
index 00000000000..769a9a435a4
--- /dev/null
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/utils/wrapper.ts
@@ -0,0 +1,9 @@
+import { TypedVariableModel } from '@grafana/data/src';
+
+export function wrapRegex(v: TypedVariableModel): string {
+ return `/^$${v.name}$/`;
+}
+
+export function wrapPure(v: TypedVariableModel): string {
+ return `$${v.name}`;
+}
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/InputSection.tsx b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/InputSection.tsx
index 6bf9e24e9b5..71b9fad90d3 100644
--- a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/InputSection.tsx
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/InputSection.tsx
@@ -3,7 +3,7 @@ import React from 'react';
import { Input } from '@grafana/ui';
-import { useShadowedState } from '../../hooks/useShadowedState';
+import { useShadowedState } from '../hooks/useShadowedState';
import { paddingRightClass } from './styles';
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/Seg.tsx b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/Seg.tsx
index 8a2077b0e66..28b679fd5e3 100644
--- a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/Seg.tsx
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/Seg.tsx
@@ -6,7 +6,7 @@ import { useAsyncFn } from 'react-use';
import { SelectableValue } from '@grafana/data';
import { AsyncSelect, InlineLabel, Input, Select } from '@grafana/ui';
-import { useShadowedState } from '../../hooks/useShadowedState';
+import { useShadowedState } from '../hooks/useShadowedState';
// this file is a simpler version of `grafana-ui / SegmentAsync.tsx`
// with some changes:
diff --git a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/VisualInfluxQLEditor.tsx b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/VisualInfluxQLEditor.tsx
index 0a00132e9e1..21951edc28a 100644
--- a/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/VisualInfluxQLEditor.tsx
+++ b/public/app/plugins/datasource/influxdb/components/editor/query/influxql/visual/VisualInfluxQLEditor.tsx
@@ -1,9 +1,7 @@
import { css } from '@emotion/css';
import React, { useId, useMemo } from 'react';
-import { useAsync } from 'react-use';
-import { GrafanaTheme2, TypedVariableModel } from '@grafana/data';
-import { getTemplateSrv } from '@grafana/runtime';
+import { GrafanaTheme2 } from '@grafana/data';
import { InlineLabel, SegmentSection, useStyles2 } from '@grafana/ui';
import InfluxDatasource from '../../../../../datasource';
@@ -25,7 +23,11 @@ import {
} from '../../../../../queryUtils';
import { InfluxQuery, InfluxQueryTag } from '../../../../../types';
import { DEFAULT_RESULT_FORMAT } from '../../../constants';
+import { useRetentionPolicies } from '../hooks/useRetentionPolicies';
+import { filterTags } from '../utils/filterTags';
import { getNewGroupByPartOptions, getNewSelectPartOptions, makePartList } from '../utils/partListUtils';
+import { withTemplateVariableOptions } from '../utils/withTemplateVariableOptions';
+import { wrapPure, wrapRegex } from '../utils/wrapper';
import { FormatAsSection } from './FormatAsSection';
import { FromSection } from './FromSection';
@@ -41,43 +43,6 @@ type Props = {
datasource: InfluxDatasource;
};
-function wrapRegex(v: TypedVariableModel): string {
- return `/^$${v.name}$/`;
-}
-
-function wrapPure(v: TypedVariableModel): string {
- return `$${v.name}`;
-}
-
-function getTemplateVariableOptions(wrapper: (v: TypedVariableModel) => string) {
- return (
- getTemplateSrv()
- .getVariables()
- // we make them regex-params, i'm not 100% sure why.
- // probably because this way multi-value variables work ok too.
- .map(wrapper)
- );
-}
-
-// helper function to make it easy to call this from the widget-render-code
-function withTemplateVariableOptions(
- optionsPromise: Promise,
- wrapper: (v: TypedVariableModel) => string,
- filter?: string
-): Promise {
- let templateVariableOptions = getTemplateVariableOptions(wrapper);
- if (filter) {
- templateVariableOptions = templateVariableOptions.filter((tvo) => tvo.indexOf(filter) > -1);
- }
- return optionsPromise.then((options) => [...templateVariableOptions, ...options]);
-}
-
-// it is possible to add fields into the `InfluxQueryTag` structures, and they do work,
-// but in some cases, when we do metadata queries, we have to remove them from the queries.
-function filterTags(parts: InfluxQueryTag[], allTagKeys: Set): InfluxQueryTag[] {
- return parts.filter((t) => t.key.endsWith('::tag') || allTagKeys.has(t.key + '::tag'));
-}
-
export const VisualInfluxQLEditor = (props: Props): JSX.Element => {
const uniqueId = useId();
const formatAsId = `influxdb-qe-format-as-${uniqueId}`;
@@ -87,9 +52,7 @@ export const VisualInfluxQLEditor = (props: Props): JSX.Element => {
const query = normalizeQuery(props.query);
const { datasource } = props;
const { measurement, policy } = query;
-
- const policyData = useAsync(() => getAllPolicies(datasource), [datasource]);
- const retentionPolicies = !!policyData.error ? [] : policyData.value ?? [];
+ const { retentionPolicies } = useRetentionPolicies(datasource);
const allTagKeys = useMemo(async () => {
const tagKeys = (await getTagKeysForMeasurementAndTags(datasource, [], measurement, policy)).map(
diff --git a/public/app/plugins/datasource/influxdb/module.ts b/public/app/plugins/datasource/influxdb/module.ts
index da229451278..c293c017d6f 100644
--- a/public/app/plugins/datasource/influxdb/module.ts
+++ b/public/app/plugins/datasource/influxdb/module.ts
@@ -2,7 +2,7 @@ import { DataSourcePlugin } from '@grafana/data';
import ConfigEditor from './components/editor/config/ConfigEditor';
import { QueryEditor } from './components/editor/query/QueryEditor';
-import InfluxStartPage from './components/editor/query/influxql/InfluxStartPage';
+import { InfluxStartPage } from './components/editor/query/influxql/InfluxStartPage';
import VariableQueryEditor from './components/editor/variable/VariableQueryEditor';
import InfluxDatasource from './datasource';
diff --git a/public/app/plugins/datasource/influxdb/specs/mocks.ts b/public/app/plugins/datasource/influxdb/specs/mocks.ts
index 9402f08aa44..72c01d4453a 100644
--- a/public/app/plugins/datasource/influxdb/specs/mocks.ts
+++ b/public/app/plugins/datasource/influxdb/specs/mocks.ts
@@ -58,6 +58,6 @@ export function getMockDSInstanceSettings(): DataSourceInstanceSettings