From 07d6b632b5374ee60ef39965777b3cf60e75cbfb Mon Sep 17 00:00:00 2001 From: Ludovic Viaud Date: Fri, 9 Dec 2022 12:56:47 +0100 Subject: [PATCH] Remove PromExploreQueryEditor and PromQueryEditor (#60020) Remove Prom editor --- .betterer.results | 10 - .../PromExploreQueryEditor.test.tsx | 144 ----------- .../components/PromExploreQueryEditor.tsx | 54 ----- .../components/PromQueryEditor.test.tsx | 75 ------ .../prometheus/components/PromQueryEditor.tsx | 223 ------------------ .../components/PromQueryEditorByApp.test.tsx | 4 +- .../components/PromQueryEditorByApp.tsx | 13 +- .../components/PromQueryBuilderOptions.tsx | 2 +- .../components/PromQueryCodeEditor.tsx | 2 - .../components/PromQueryEditorSelector.tsx | 14 +- 10 files changed, 16 insertions(+), 525 deletions(-) delete mode 100644 public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.test.tsx delete mode 100644 public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.tsx delete mode 100644 public/app/plugins/datasource/prometheus/components/PromQueryEditor.test.tsx delete mode 100644 public/app/plugins/datasource/prometheus/components/PromQueryEditor.tsx diff --git a/.betterer.results b/.betterer.results index b3c1494e10e..32bd5512dd8 100644 --- a/.betterer.results +++ b/.betterer.results @@ -6306,22 +6306,12 @@ exports[`better eslint`] = { "public/app/plugins/datasource/prometheus/components/PromExploreExtraField.test.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], - "public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.test.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"] - ], "public/app/plugins/datasource/prometheus/components/PromLink.test.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/plugins/datasource/prometheus/components/PromLink.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] ], - "public/app/plugins/datasource/prometheus/components/PromQueryEditor.test.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], - "public/app/plugins/datasource/prometheus/components/PromQueryEditor.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], "public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], diff --git a/public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.test.tsx b/public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.test.tsx deleted file mode 100644 index f8b9d9486ae..00000000000 --- a/public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.test.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import React from 'react'; - -import { LoadingState, PanelData, toUtc, TimeRange } from '@grafana/data'; - -import { PrometheusDatasource } from '../datasource'; -import { PromQuery } from '../types'; - -import { testIds as extraFieldTestIds } from './PromExploreExtraField'; -import { PromExploreQueryEditor, testIds } from './PromExploreQueryEditor'; - -// the monaco-based editor uses lazy-loading and that does not work -// well with this test, and we do not need the monaco-related -// functionality in this test anyway, so we mock it out. -jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => { - const fakeQueryField = () =>
prometheus query field
; - return { - MonacoQueryFieldWrapper: fakeQueryField, - }; -}); - -const setup = (propOverrides?: object) => { - const datasourceMock: unknown = { - languageProvider: { - syntax: () => {}, - getLabelKeys: () => [], - metrics: [], - start: () => Promise.resolve([]), - }, - getInitHints: () => [], - exemplarsAvailable: true, - }; - const datasource: PrometheusDatasource = datasourceMock as PrometheusDatasource; - const onRunQuery = jest.fn(); - const onChange = jest.fn(); - const query: PromQuery = { expr: '', refId: 'A', interval: '1s', exemplar: true }; - const range: TimeRange = { - from: toUtc('2020-01-01', 'YYYY-MM-DD'), - to: toUtc('2020-01-02', 'YYYY-MM-DD'), - raw: { - from: toUtc('2020-01-01', 'YYYY-MM-DD'), - to: toUtc('2020-01-02', 'YYYY-MM-DD'), - }, - }; - const data: PanelData = { - state: LoadingState.NotStarted, - series: [], - request: { - requestId: '1', - dashboardId: 1, - intervalMs: 1000, - interval: '1s', - panelId: 1, - range: { - from: toUtc('2020-01-01', 'YYYY-MM-DD'), - to: toUtc('2020-01-02', 'YYYY-MM-DD'), - raw: { - from: toUtc('2020-01-01', 'YYYY-MM-DD'), - to: toUtc('2020-01-02', 'YYYY-MM-DD'), - }, - }, - scopedVars: {}, - targets: [], - timezone: 'GMT', - app: 'Grafana', - startTime: 0, - }, - timeRange: { - from: toUtc('2020-01-01', 'YYYY-MM-DD'), - to: toUtc('2020-01-02', 'YYYY-MM-DD'), - raw: { - from: toUtc('2020-01-01', 'YYYY-MM-DD'), - to: toUtc('2020-01-02', 'YYYY-MM-DD'), - }, - }, - }; - const history: any[] = []; - const exploreMode = 'Metrics'; - - const props: any = { - query, - data, - range, - datasource, - exploreMode, - history, - onChange, - onRunQuery, - }; - - Object.assign(props, propOverrides); - - return ; -}; - -describe('PromExploreQueryEditor', () => { - it('should render component', () => { - render(setup()); - expect(screen.getByTestId(testIds.editor)).toBeInTheDocument(); - }); - - it('should render PromQueryField with ExtraFieldElement', async () => { - render(setup()); - expect(screen.getByTestId(extraFieldTestIds.extraFieldEditor)).toBeInTheDocument(); - }); - - it('should set default value for expr if it is undefined', async () => { - const onChange = jest.fn(); - const query = { expr: undefined, exemplar: false, instant: false, range: true }; - render(setup({ onChange, query })); - expect(onChange).toHaveBeenCalledTimes(1); - expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ expr: '' })); - }); - - it('should set default value for exemplars if it is undefined', async () => { - const onChange = jest.fn(); - const query = { expr: '', instant: false, range: true }; - render(setup({ onChange, query })); - expect(onChange).toHaveBeenCalledTimes(1); - expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ exemplar: true })); - }); - - it('should set default value for instant and range if expr is falsy', async () => { - const onChange = jest.fn(); - let query = { expr: '', exemplar: true }; - render(setup({ onChange, query })); - expect(onChange).toHaveBeenCalledTimes(1); - expect(onChange).toHaveBeenCalledWith(expect.objectContaining({ instant: true, range: true })); - }); - - it('should not set default value for instant and range with truthy expr', async () => { - const onChange = jest.fn(); - let query = { expr: 'foo', exemplar: true }; - render(setup({ onChange, query })); - expect(onChange).toHaveBeenCalledTimes(0); - }); - - it('should add default values for multiple missing values', async () => { - const onChange = jest.fn(); - let query = {}; - render(setup({ onChange, query })); - expect(onChange).toHaveBeenCalledTimes(3); - }); -}); diff --git a/public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.tsx b/public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.tsx deleted file mode 100644 index 5517ef1c8da..00000000000 --- a/public/app/plugins/datasource/prometheus/components/PromExploreQueryEditor.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { memo, useEffect } from 'react'; - -import { QueryEditorProps, CoreApp } from '@grafana/data'; - -import { PrometheusDatasource } from '../datasource'; -import { PromQuery, PromOptions } from '../types'; - -import { PromExploreExtraField } from './PromExploreExtraField'; -import PromQueryField from './PromQueryField'; - -export type Props = QueryEditorProps; - -export const PromExploreQueryEditor = memo((props: Props) => { - const { range, query, data, datasource, history, onChange, onRunQuery } = props; - - // Setting default values - useEffect(() => { - if (query.expr === undefined) { - onChange({ ...query, expr: '' }); - } - if (query.exemplar === undefined) { - onChange({ ...query, exemplar: true }); - } - - // Override query type to "Both" only for new queries (no query.expr). - if (!query.instant && !query.range && !query.expr) { - onChange({ ...query, instant: true, range: true }); - } - }, [onChange, query]); - - return ( - {}} - history={history} - data={data} - data-testid={testIds.editor} - ExtraFieldElement={ - - } - /> - ); -}); - -PromExploreQueryEditor.displayName = 'PromExploreQueryEditor'; - -export const testIds = { - editor: 'prom-editor-explore', -}; diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryEditor.test.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryEditor.test.tsx deleted file mode 100644 index b54fe94a74d..00000000000 --- a/public/app/plugins/datasource/prometheus/components/PromQueryEditor.test.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { screen, render } from '@testing-library/react'; -import React from 'react'; - -import { dateTime, CoreApp } from '@grafana/data'; - -import { PrometheusDatasource } from '../datasource'; -import { PromQuery } from '../types'; - -import { PromQueryEditor, testIds } from './PromQueryEditor'; - -jest.mock('app/features/dashboard/services/TimeSrv', () => { - return { - getTimeSrv: () => ({ - timeRange: () => ({ - from: dateTime(), - to: dateTime(), - }), - }), - }; -}); - -jest.mock('./monaco-query-field/MonacoQueryFieldWrapper', () => { - const fakeQueryField = () =>
prometheus query field
; - return { - MonacoQueryFieldWrapper: fakeQueryField, - }; -}); - -const setup = (propOverrides?: object) => { - const datasourceMock: unknown = { - createQuery: jest.fn((q) => q), - getPrometheusTime: jest.fn((date, roundup) => 123), - languageProvider: { - start: () => Promise.resolve([]), - syntax: () => {}, - getLabelKeys: () => [], - metrics: [], - }, - getInitHints: () => [], - }; - const datasource: PrometheusDatasource = datasourceMock as PrometheusDatasource; - const onRunQuery = jest.fn(); - const onChange = jest.fn(); - const query: PromQuery = { expr: '', refId: 'A' }; - - const props: any = { - datasource, - onChange, - onRunQuery, - query, - }; - - Object.assign(props, propOverrides); - - return render(); -}; - -describe('Render PromQueryEditor with basic options', () => { - it('should render editor', () => { - setup(); - expect(screen.getByTestId(testIds.editor)).toBeInTheDocument(); - }); - - it('should render exemplar editor for dashboard', () => { - setup({ app: CoreApp.Dashboard }); - expect(screen.getByTestId(testIds.editor)).toBeInTheDocument(); - expect(screen.getByTestId(testIds.exemplar)).toBeInTheDocument(); - }); - - it('should not render exemplar editor for unified alerting', () => { - setup({ app: CoreApp.UnifiedAlerting }); - expect(screen.getByTestId(testIds.editor)).toBeInTheDocument(); - expect(screen.queryByTestId(testIds.exemplar)).not.toBeInTheDocument(); - }); -}); diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryEditor.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryEditor.tsx deleted file mode 100644 index 0ba79277e90..00000000000 --- a/public/app/plugins/datasource/prometheus/components/PromQueryEditor.tsx +++ /dev/null @@ -1,223 +0,0 @@ -import { map } from 'lodash'; -import React, { PureComponent } from 'react'; - -// Types -import { CoreApp, SelectableValue } from '@grafana/data'; -import { InlineFormLabel, LegacyForms, Select } from '@grafana/ui'; - -import { PromQuery } from '../types'; - -import { PromExemplarField } from './PromExemplarField'; -import PromLink from './PromLink'; -import PromQueryField from './PromQueryField'; -import { PromQueryEditorProps } from './types'; - -const { Switch } = LegacyForms; - -export const FORMAT_OPTIONS: Array> = [ - { label: 'Time series', value: 'time_series' }, - { label: 'Table', value: 'table' }, - { label: 'Heatmap', value: 'heatmap' }, -]; - -export const INTERVAL_FACTOR_OPTIONS: Array> = map([1, 2, 3, 4, 5, 10], (value: number) => ({ - value, - label: '1/' + value, -})); - -interface State { - legendFormat?: string; - formatOption: SelectableValue; - interval?: string; - intervalFactorOption: SelectableValue; - instant: boolean; - exemplar: boolean; -} - -export class PromQueryEditor extends PureComponent { - // Query target to be modified and used for queries - query: PromQuery; - - constructor(props: PromQueryEditorProps) { - super(props); - // Use default query to prevent undefined input values - const defaultQuery: Partial = { - expr: '', - legendFormat: '', - interval: '', - // Set exemplar to false for alerting queries - exemplar: props.app === CoreApp.UnifiedAlerting ? false : true, - }; - const query = Object.assign({}, defaultQuery, props.query); - this.query = query; - // Query target properties that are fully controlled inputs - this.state = { - // Fully controlled text inputs - interval: query.interval, - legendFormat: query.legendFormat, - // Select options - formatOption: FORMAT_OPTIONS.find((option) => option.value === query.format) || FORMAT_OPTIONS[0], - intervalFactorOption: - INTERVAL_FACTOR_OPTIONS.find((option) => option.value === query.intervalFactor) || INTERVAL_FACTOR_OPTIONS[0], - // Switch options - instant: Boolean(query.instant), - exemplar: Boolean(query.exemplar), - }; - } - - onFieldChange = (query: PromQuery, override?: any) => { - this.query.expr = query.expr; - }; - - onFormatChange = (option: SelectableValue) => { - this.query.format = option.value; - this.setState({ formatOption: option }, this.onRunQuery); - }; - - onInstantChange = (e: React.SyntheticEvent) => { - const instant = e.currentTarget.checked; - this.query.instant = instant; - this.setState({ instant }, this.onRunQuery); - }; - - onIntervalChange = (e: React.SyntheticEvent) => { - const interval = e.currentTarget.value; - this.query.interval = interval; - this.setState({ interval }); - }; - - onIntervalFactorChange = (option: SelectableValue) => { - this.query.intervalFactor = option.value; - this.setState({ intervalFactorOption: option }, this.onRunQuery); - }; - - onLegendChange = (e: React.SyntheticEvent) => { - const legendFormat = e.currentTarget.value; - this.query.legendFormat = legendFormat; - this.setState({ legendFormat }); - }; - - onExemplarChange = (isEnabled: boolean) => { - this.query.exemplar = isEnabled; - this.setState({ exemplar: isEnabled }, this.onRunQuery); - }; - - onRunQuery = () => { - const { query } = this; - // Change of query.hide happens outside of this component and is just passed as prop. We have to update it when running queries. - const { hide } = this.props.query; - this.props.onChange({ ...query, hide }); - this.props.onRunQuery(); - }; - - render() { - const { datasource, query, range, data } = this.props; - const { formatOption, instant, interval, intervalFactorOption, legendFormat } = this.state; - //We want to hide exemplar field for unified alerting as exemplars in alerting don't make sense and are source of confusion - const showExemplarField = this.props.app !== CoreApp.UnifiedAlerting; - - return ( - -
- - Legend - - -
- -
- - An additional lower limit for the step parameter of the Prometheus query and for the{' '} - $__interval and $__rate_interval variables. The limit is absolute and not - modified by the "Resolution" setting. - - } - > - Min step - - -
- -
-
Resolution
- - - - - - -
- {showExemplarField && ( - - )} - - } - /> - ); - } -} - -export const testIds = { - editor: 'prom-editor', - exemplar: 'exemplar-editor', -}; diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx index 9d80cddb841..fdc69769f89 100644 --- a/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx +++ b/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.test.tsx @@ -6,7 +6,6 @@ import { CoreApp } from '@grafana/data'; import { PrometheusDatasource } from '../datasource'; -import { testIds as regularTestIds } from './PromQueryEditor'; import { PromQueryEditorByApp } from './PromQueryEditorByApp'; import { testIds as alertingTestIds } from './PromQueryEditorForAlerting'; @@ -70,10 +69,9 @@ function setup(app: CoreApp): RenderResult & { onRunQuery: jest.Mock } { describe('PromQueryEditorByApp', () => { it('should render simplified query editor for cloud alerting', () => { - const { getByTestId, queryByTestId } = setup(CoreApp.CloudAlerting); + const { getByTestId } = setup(CoreApp.CloudAlerting); expect(getByTestId(alertingTestIds.editor)).toBeInTheDocument(); - expect(queryByTestId(regularTestIds.editor)).toBeNull(); }); it('should render editor selector for unkown apps', () => { diff --git a/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.tsx b/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.tsx index 3e15b9a297d..f10a6e3279a 100644 --- a/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.tsx +++ b/public/app/plugins/datasource/prometheus/components/PromQueryEditorByApp.tsx @@ -1,12 +1,9 @@ import React, { memo } from 'react'; import { CoreApp } from '@grafana/data'; -import { config } from '@grafana/runtime'; import { PromQueryEditorSelector } from '../querybuilder/components/PromQueryEditorSelector'; -import { PromExploreQueryEditor } from './PromExploreQueryEditor'; -import { PromQueryEditor } from './PromQueryEditor'; import { PromQueryEditorForAlerting } from './PromQueryEditorForAlerting'; import { PromQueryEditorProps } from './types'; @@ -16,16 +13,8 @@ export function PromQueryEditorByApp(props: PromQueryEditorProps) { switch (app) { case CoreApp.CloudAlerting: return ; - case CoreApp.Explore: - if (config.featureToggles.promQueryBuilder) { - return ; - } - return ; default: - if (config.featureToggles.promQueryBuilder) { - return ; - } - return ; + return ; } } diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.tsx index 4a846cff03c..a258a3b65d6 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryBuilderOptions.tsx @@ -5,10 +5,10 @@ import { EditorField, EditorRow, EditorSwitch } from '@grafana/experimental'; import { AutoSizeInput, RadioButtonGroup, Select } from '@grafana/ui'; import { getQueryTypeChangeHandler, getQueryTypeOptions } from '../../components/PromExploreExtraField'; -import { FORMAT_OPTIONS, INTERVAL_FACTOR_OPTIONS } from '../../components/PromQueryEditor'; import { PromQuery } from '../../types'; import { QueryOptionGroup } from '../shared/QueryOptionGroup'; +import { FORMAT_OPTIONS, INTERVAL_FACTOR_OPTIONS } from './PromQueryEditorSelector'; import { getLegendModeLabel, PromQueryLegendEditor } from './PromQueryLegendEditor'; export interface UIOptions { diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.tsx index 949d8e3a9a9..f9bfe24bf7d 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryCodeEditor.tsx @@ -4,7 +4,6 @@ import React from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '@grafana/ui'; -import { testIds } from '../../components/PromQueryEditor'; import PromQueryField from '../../components/PromQueryField'; import { PromQueryEditorProps } from '../../components/types'; @@ -28,7 +27,6 @@ export function PromQueryCodeEditor(props: Props) { onChange={onChange} history={[]} data={data} - data-testid={testIds.editor} app={app} /> diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx index ff7f9a88e32..85ad07a6d1b 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/PromQueryEditorSelector.tsx @@ -1,6 +1,7 @@ +import { map } from 'lodash'; import React, { SyntheticEvent, useCallback, useEffect, useState } from 'react'; -import { CoreApp, LoadingState } from '@grafana/data'; +import { CoreApp, LoadingState, SelectableValue } from '@grafana/data'; import { EditorHeader, EditorRows, FlexItem, InlineSelect, Space } from '@grafana/experimental'; import { reportInteraction } from '@grafana/runtime'; import { ConfirmModal, Button } from '@grafana/ui'; @@ -19,6 +20,17 @@ import { PromQueryBuilderContainer } from './PromQueryBuilderContainer'; import { PromQueryBuilderOptions } from './PromQueryBuilderOptions'; import { PromQueryCodeEditor } from './PromQueryCodeEditor'; +export const FORMAT_OPTIONS: Array> = [ + { label: 'Time series', value: 'time_series' }, + { label: 'Table', value: 'table' }, + { label: 'Heatmap', value: 'heatmap' }, +]; + +export const INTERVAL_FACTOR_OPTIONS: Array> = map([1, 2, 3, 4, 5, 10], (value: number) => ({ + value, + label: '1/' + value, +})); + type Props = PromQueryEditorProps; export const PromQueryEditorSelector = React.memo((props) => {