mirror of https://github.com/grafana/grafana.git
				
				
				
			Chore: InfluxDB - Reformatting and restructuring (#69669)
* Reformatting and restructuring * Update unit test * Export as function
This commit is contained in:
		
							parent
							
								
									9f18e0ccf3
								
							
						
					
					
						commit
						3341229bc2
					
				| 
						 | 
					@ -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.", "1"],
 | 
				
			||||||
      [0, 0, 0, "Do not use any type assertions.", "2"]
 | 
					      [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": [
 | 
					    "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.", "0"],
 | 
				
			||||||
      [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
 | 
					      [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ const CHEAT_SHEET_ITEMS = [
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const InfluxCheatSheet = (props: any) => (
 | 
					export const InfluxCheatSheet = () => (
 | 
				
			||||||
  <div>
 | 
					  <div>
 | 
				
			||||||
    <h2>InfluxDB Cheat Sheet</h2>
 | 
					    <h2>InfluxDB Cheat Sheet</h2>
 | 
				
			||||||
    {CHEAT_SHEET_ITEMS.map((item) => (
 | 
					    {CHEAT_SHEET_ITEMS.map((item) => (
 | 
				
			||||||
| 
						 | 
					@ -19,5 +19,3 @@ const InfluxCheatSheet = (props: any) => (
 | 
				
			||||||
    ))}
 | 
					    ))}
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					 | 
				
			||||||
export default InfluxCheatSheet;
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 function InfluxStartPage() {
 | 
				
			||||||
 | 
					  return <InfluxCheatSheet />;
 | 
				
			||||||
export default class InfluxStartPage extends PureComponent<QueryEditorHelpProps> {
 | 
					 | 
				
			||||||
  render() {
 | 
					 | 
				
			||||||
    return <InfluxCheatSheet onClickExample={this.props.onClickExample} />;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ import { HorizontalGroup, InlineFormLabel, Input, Select, TextArea } from '@graf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { InfluxQuery } from '../../../../../types';
 | 
					import { InfluxQuery } from '../../../../../types';
 | 
				
			||||||
import { DEFAULT_RESULT_FORMAT, RESULT_FORMATS } from '../../../constants';
 | 
					import { DEFAULT_RESULT_FORMAT, RESULT_FORMATS } from '../../../constants';
 | 
				
			||||||
import { useShadowedState } from '../../hooks/useShadowedState';
 | 
					import { useShadowedState } from '../hooks/useShadowedState';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					type Props = {
 | 
				
			||||||
  query: InfluxQuery;
 | 
					  query: InfluxQuery;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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']] },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -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<string[]>([]);
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    getAllPolicies(datasource).then((data) => {
 | 
				
			||||||
 | 
					      setRetentionPolicies(data);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }, [datasource]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return { retentionPolicies };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -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<string>): InfluxQueryTag[] {
 | 
				
			||||||
 | 
					  return parts.filter((t) => t.key.endsWith('::tag') || allTagKeys.has(t.key + '::tag'));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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<string[]>,
 | 
				
			||||||
 | 
					  wrapper: (v: TypedVariableModel) => string,
 | 
				
			||||||
 | 
					  filter?: string
 | 
				
			||||||
 | 
					): Promise<string[]> {
 | 
				
			||||||
 | 
					  let templateVariableOptions = getTemplateVariableOptions(wrapper);
 | 
				
			||||||
 | 
					  if (filter) {
 | 
				
			||||||
 | 
					    templateVariableOptions = templateVariableOptions.filter((tvo) => tvo.indexOf(filter) > -1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return optionsPromise.then((options) => [...templateVariableOptions, ...options]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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}`;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Input } from '@grafana/ui';
 | 
					import { Input } from '@grafana/ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useShadowedState } from '../../hooks/useShadowedState';
 | 
					import { useShadowedState } from '../hooks/useShadowedState';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { paddingRightClass } from './styles';
 | 
					import { paddingRightClass } from './styles';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ import { useAsyncFn } from 'react-use';
 | 
				
			||||||
import { SelectableValue } from '@grafana/data';
 | 
					import { SelectableValue } from '@grafana/data';
 | 
				
			||||||
import { AsyncSelect, InlineLabel, Input, Select } from '@grafana/ui';
 | 
					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`
 | 
					// this file is a simpler version of `grafana-ui / SegmentAsync.tsx`
 | 
				
			||||||
// with some changes:
 | 
					// with some changes:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,7 @@
 | 
				
			||||||
import { css } from '@emotion/css';
 | 
					import { css } from '@emotion/css';
 | 
				
			||||||
import React, { useId, useMemo } from 'react';
 | 
					import React, { useId, useMemo } from 'react';
 | 
				
			||||||
import { useAsync } from 'react-use';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { GrafanaTheme2, TypedVariableModel } from '@grafana/data';
 | 
					import { GrafanaTheme2 } from '@grafana/data';
 | 
				
			||||||
import { getTemplateSrv } from '@grafana/runtime';
 | 
					 | 
				
			||||||
import { InlineLabel, SegmentSection, useStyles2 } from '@grafana/ui';
 | 
					import { InlineLabel, SegmentSection, useStyles2 } from '@grafana/ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import InfluxDatasource from '../../../../../datasource';
 | 
					import InfluxDatasource from '../../../../../datasource';
 | 
				
			||||||
| 
						 | 
					@ -25,7 +23,11 @@ import {
 | 
				
			||||||
} from '../../../../../queryUtils';
 | 
					} from '../../../../../queryUtils';
 | 
				
			||||||
import { InfluxQuery, InfluxQueryTag } from '../../../../../types';
 | 
					import { InfluxQuery, InfluxQueryTag } from '../../../../../types';
 | 
				
			||||||
import { DEFAULT_RESULT_FORMAT } from '../../../constants';
 | 
					import { DEFAULT_RESULT_FORMAT } from '../../../constants';
 | 
				
			||||||
 | 
					import { useRetentionPolicies } from '../hooks/useRetentionPolicies';
 | 
				
			||||||
 | 
					import { filterTags } from '../utils/filterTags';
 | 
				
			||||||
import { getNewGroupByPartOptions, getNewSelectPartOptions, makePartList } from '../utils/partListUtils';
 | 
					import { getNewGroupByPartOptions, getNewSelectPartOptions, makePartList } from '../utils/partListUtils';
 | 
				
			||||||
 | 
					import { withTemplateVariableOptions } from '../utils/withTemplateVariableOptions';
 | 
				
			||||||
 | 
					import { wrapPure, wrapRegex } from '../utils/wrapper';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { FormatAsSection } from './FormatAsSection';
 | 
					import { FormatAsSection } from './FormatAsSection';
 | 
				
			||||||
import { FromSection } from './FromSection';
 | 
					import { FromSection } from './FromSection';
 | 
				
			||||||
| 
						 | 
					@ -41,43 +43,6 @@ type Props = {
 | 
				
			||||||
  datasource: InfluxDatasource;
 | 
					  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<string[]>,
 | 
					 | 
				
			||||||
  wrapper: (v: TypedVariableModel) => string,
 | 
					 | 
				
			||||||
  filter?: string
 | 
					 | 
				
			||||||
): Promise<string[]> {
 | 
					 | 
				
			||||||
  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<string>): InfluxQueryTag[] {
 | 
					 | 
				
			||||||
  return parts.filter((t) => t.key.endsWith('::tag') || allTagKeys.has(t.key + '::tag'));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const VisualInfluxQLEditor = (props: Props): JSX.Element => {
 | 
					export const VisualInfluxQLEditor = (props: Props): JSX.Element => {
 | 
				
			||||||
  const uniqueId = useId();
 | 
					  const uniqueId = useId();
 | 
				
			||||||
  const formatAsId = `influxdb-qe-format-as-${uniqueId}`;
 | 
					  const formatAsId = `influxdb-qe-format-as-${uniqueId}`;
 | 
				
			||||||
| 
						 | 
					@ -87,9 +52,7 @@ export const VisualInfluxQLEditor = (props: Props): JSX.Element => {
 | 
				
			||||||
  const query = normalizeQuery(props.query);
 | 
					  const query = normalizeQuery(props.query);
 | 
				
			||||||
  const { datasource } = props;
 | 
					  const { datasource } = props;
 | 
				
			||||||
  const { measurement, policy } = query;
 | 
					  const { measurement, policy } = query;
 | 
				
			||||||
 | 
					  const { retentionPolicies } = useRetentionPolicies(datasource);
 | 
				
			||||||
  const policyData = useAsync(() => getAllPolicies(datasource), [datasource]);
 | 
					 | 
				
			||||||
  const retentionPolicies = !!policyData.error ? [] : policyData.value ?? [];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const allTagKeys = useMemo(async () => {
 | 
					  const allTagKeys = useMemo(async () => {
 | 
				
			||||||
    const tagKeys = (await getTagKeysForMeasurementAndTags(datasource, [], measurement, policy)).map(
 | 
					    const tagKeys = (await getTagKeysForMeasurementAndTags(datasource, [], measurement, policy)).map(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ import { DataSourcePlugin } from '@grafana/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ConfigEditor from './components/editor/config/ConfigEditor';
 | 
					import ConfigEditor from './components/editor/config/ConfigEditor';
 | 
				
			||||||
import { QueryEditor } from './components/editor/query/QueryEditor';
 | 
					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 VariableQueryEditor from './components/editor/variable/VariableQueryEditor';
 | 
				
			||||||
import InfluxDatasource from './datasource';
 | 
					import InfluxDatasource from './datasource';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,6 +58,6 @@ export function getMockDSInstanceSettings(): DataSourceInstanceSettings<InfluxOp
 | 
				
			||||||
      module: '',
 | 
					      module: '',
 | 
				
			||||||
      baseUrl: '',
 | 
					      baseUrl: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    jsonData: { version: InfluxVersion.InfluxQL, httpMode: 'POST' },
 | 
					    jsonData: { version: InfluxVersion.InfluxQL, httpMode: 'POST', dbName: 'site' },
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue