From 92857ef33105fa837624236df6fbd38bd992303c Mon Sep 17 00:00:00 2001 From: Adam Simpson Date: Thu, 15 Sep 2022 10:12:26 -0400 Subject: [PATCH] CloudMonitor: Remove cloudMonitoringExperimentalUI feature flag (#55054) * CloudMonitor: remove cloudMonitoringExperimentalUI * fix: address typecheck errors * fix: fix SLO import and width cleanup * fix wrong metricType when switching datasources * fix: remove legacy SLO and fix queryType check --- .betterer.results | 30 +-- packages/grafana-data/src/types/data.ts | 1 - .../src/types/featureToggles.gen.ts | 1 - pkg/services/featuremgmt/registry.go | 6 - pkg/services/featuremgmt/toggles_gen.go | 4 - .../components/Aggregation.tsx | 15 +- .../cloud-monitoring/components/AliasBy.tsx | 12 +- .../{Experimental => }/Alignment.test.tsx | 6 +- .../cloud-monitoring/components/Alignment.tsx | 41 ++-- .../components/AlignmentFunction.tsx | 4 +- .../components/AnnotationQueryEditor.tsx | 60 ++--- .../Experimental/Aggregation.test.tsx | 65 ------ .../components/Experimental/Aggregation.tsx | 67 ------ .../components/Experimental/AliasBy.tsx | 29 --- .../components/Experimental/Alignment.tsx | 56 ----- .../Experimental/AlignmentFunction.tsx | 42 ---- .../Experimental/GraphPeriod.test.tsx | 39 ---- .../components/Experimental/GraphPeriod.tsx | 48 ---- .../components/Experimental/GroupBy.tsx | 61 ------ .../components/Experimental/LabelFilter.tsx | 118 ---------- .../Experimental/MetricQueryEditor.test.tsx | 40 ---- .../Experimental/MetricQueryEditor.tsx | 140 ------------ .../components/Experimental/Metrics.tsx | 193 ---------------- .../components/Experimental/PeriodSelect.tsx | 59 ----- .../components/Experimental/Preprocessor.tsx | 66 ------ .../components/Experimental/Project.tsx | 48 ---- .../Experimental/SLOQueryEditor.test.tsx | 40 ---- .../Experimental/VisualMetricQueryEditor.tsx | 88 -------- .../components/GraphPeriod.tsx | 43 ++-- .../{Experimental => }/GroupBy.test.tsx | 2 +- .../cloud-monitoring/components/GroupBy.tsx | 41 ++-- .../{Experimental => }/LabelFilter.test.tsx | 0 .../components/LabelFilter.tsx | 206 ++++++++---------- .../LookbackPeriodSelect.tsx | 2 +- .../components/MetricQueryEditor.tsx | 26 +-- .../{Experimental => }/Metrics.test.tsx | 6 +- .../cloud-monitoring/components/Metrics.tsx | 160 +++++++------- .../components/PeriodSelect.tsx | 5 +- .../{Experimental => }/Preprocessor.test.tsx | 6 +- .../components/Preprocessor.tsx | 10 +- .../cloud-monitoring/components/Project.tsx | 11 +- .../components/QueryEditor.tsx | 82 +------ .../{Experimental => }/QueryHeader.test.tsx | 4 +- .../{Experimental => }/QueryHeader.tsx | 4 +- .../components/{Experimental => }/SLO.tsx | 4 +- .../components/SLO/LookbackPeriodSelect.tsx | 53 ----- .../cloud-monitoring/components/SLO/SLO.tsx | 56 ----- .../components/SLO/SLOQueryEditor.tsx | 100 --------- .../components/SLO/Selector.tsx | 38 ---- .../components/SLO/Service.tsx | 54 ----- .../cloud-monitoring/components/SLO/index.ts | 3 - .../{Experimental => }/SLOQueryEditor.tsx | 8 +- .../{Experimental => }/Selector.tsx | 6 +- .../components/{Experimental => }/Service.tsx | 4 +- .../components/VisualMetricQueryEditor.tsx | 54 +++-- .../cloud-monitoring/components/index.ts | 2 +- 56 files changed, 345 insertions(+), 2024 deletions(-) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/Alignment.test.tsx (91%) delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.test.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/AliasBy.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/AlignmentFunction.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/GraphPeriod.test.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/GraphPeriod.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/GroupBy.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/LabelFilter.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.test.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/Metrics.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/PeriodSelect.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/Project.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.test.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/GroupBy.test.tsx (94%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/LabelFilter.test.tsx (100%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/LookbackPeriodSelect.tsx (96%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/Metrics.test.tsx (96%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/Preprocessor.test.tsx (94%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/QueryHeader.test.tsx (95%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/QueryHeader.tsx (94%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/SLO.tsx (94%) delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/SLO/LookbackPeriodSelect.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/SLO/SLO.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/SLO/SLOQueryEditor.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/SLO/Selector.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/SLO/Service.tsx delete mode 100644 public/app/plugins/datasource/cloud-monitoring/components/SLO/index.ts rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/SLOQueryEditor.tsx (94%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/Selector.tsx (87%) rename public/app/plugins/datasource/cloud-monitoring/components/{Experimental => }/Service.tsx (93%) diff --git a/.betterer.results b/.betterer.results index d0d5515d2d8..658624103d9 100644 --- a/.betterer.results +++ b/.betterer.results @@ -5846,30 +5846,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], - "public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.test.tsx:5381": [ - [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.", "2"] - ], - "public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"] - ], - "public/app/plugins/datasource/cloud-monitoring/components/Experimental/AliasBy.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/cloud-monitoring/components/Experimental/GroupBy.test.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], - "public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.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/cloud-monitoring/components/Experimental/Metrics.tsx:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], - "public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx:5381": [ + "public/app/plugins/datasource/cloud-monitoring/components/GroupBy.test.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/plugins/datasource/cloud-monitoring/components/MQLQueryEditor.tsx:5381": [ @@ -5880,10 +5857,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], "public/app/plugins/datasource/cloud-monitoring/components/Metrics.tsx:5381": [ - [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.", "2"], - [0, 0, 0, "Unexpected any. Specify a different type.", "3"] + [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], "public/app/plugins/datasource/cloud-monitoring/components/QueryEditor.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], diff --git a/packages/grafana-data/src/types/data.ts b/packages/grafana-data/src/types/data.ts index ab18139742b..825001dce65 100644 --- a/packages/grafana-data/src/types/data.ts +++ b/packages/grafana-data/src/types/data.ts @@ -76,7 +76,6 @@ export interface QueryResultMeta { /** * Legacy data source specific, should be moved to custom * */ - alignmentPeriod?: number; // used by cloud monitoring searchWords?: string[]; // used by log models and loki limit?: number; // used by log models and loki json?: boolean; // used to keep track of old json doc values diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index ed4e8dd14b2..1d01c4bf423 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -57,7 +57,6 @@ export interface FeatureToggles { canvasPanelNesting?: boolean; scenes?: boolean; useLegacyHeatmapPanel?: boolean; - cloudMonitoringExperimentalUI?: boolean; disableSecretsCompatibility?: boolean; logRequestsInstrumentedAsUnknown?: boolean; dataConnectionsConsole?: boolean; diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index a6ccfc6c1a6..781ef89aef6 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -232,12 +232,6 @@ var ( Description: "Continue to use the angular/flot based heatmap panel", State: FeatureStateStable, }, - { - Name: "cloudMonitoringExperimentalUI", - Description: "Use grafana-experimental UI in Cloud Monitoring", - State: FeatureStateAlpha, - FrontendOnly: true, - }, { Name: "disableSecretsCompatibility", Description: "Disable duplicated secret storage in legacy tables", diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 22e1c0d2dfc..d055159894a 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -171,10 +171,6 @@ const ( // Continue to use the angular/flot based heatmap panel FlagUseLegacyHeatmapPanel = "useLegacyHeatmapPanel" - // FlagCloudMonitoringExperimentalUI - // Use grafana-experimental UI in Cloud Monitoring - FlagCloudMonitoringExperimentalUI = "cloudMonitoringExperimentalUI" - // FlagDisableSecretsCompatibility // Disable duplicated secret storage in legacy tables FlagDisableSecretsCompatibility = "disableSecretsCompatibility" diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx index d5433be8b55..cdf34ecafe2 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx @@ -1,13 +1,11 @@ import React, { FC, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; -import { Select } from '@grafana/ui'; +import { EditorField, Select } from '@grafana/ui'; import { getAggregationOptionsByMetric } from '../functions'; import { MetricDescriptor, MetricKind, ValueTypes } from '../types'; -import { QueryEditorField } from '.'; - export interface Props { refId: string; onChange: (metricDescriptor: string) => void; @@ -22,14 +20,9 @@ export const Aggregation: FC = (props) => { const selected = useSelectedFromOptions(aggOptions, props); return ( - + - + + + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx similarity index 91% rename from public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.test.tsx rename to public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx index a3fa46189b4..ea7ddbe435d 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.test.tsx @@ -5,9 +5,9 @@ import { openMenu } from 'react-select-event'; import { TemplateSrvMock } from 'app/features/templating/template_srv.mock'; -import { createMockDatasource } from '../../__mocks__/cloudMonitoringDatasource'; -import { createMockMetricQuery } from '../../__mocks__/cloudMonitoringQuery'; -import { MetricKind, ValueTypes } from '../../types'; +import { createMockDatasource } from '../__mocks__/cloudMonitoringDatasource'; +import { createMockMetricQuery } from '../__mocks__/cloudMonitoringQuery'; +import { MetricKind, ValueTypes } from '../types'; import { Alignment } from './Alignment'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx index edb9e8163a1..e6634c60c23 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Alignment.tsx @@ -1,12 +1,15 @@ -import React, { FC } from 'react'; +import React, { FC, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; +import { EditorField, EditorFieldGroup } from '@grafana/ui'; -import { ALIGNMENT_PERIODS, SELECT_WIDTH } from '../constants'; +import { ALIGNMENT_PERIODS } from '../constants'; import CloudMonitoringDatasource from '../datasource'; +import { alignmentPeriodLabel } from '../functions'; import { CustomMetaData, MetricQuery, SLOQuery } from '../types'; -import { AlignmentFunction, PeriodSelect, AlignmentPeriodLabel, QueryEditorField, QueryEditorRow } from '.'; +import { AlignmentFunction } from './AlignmentFunction'; +import { PeriodSelect } from './PeriodSelect'; export interface Props { refId: string; @@ -25,29 +28,29 @@ export const Alignment: FC = ({ customMetaData, datasource, }) => { + const alignmentLabel = useMemo(() => alignmentPeriodLabel(customMetaData, datasource), [customMetaData, datasource]); return ( - } - htmlFor={`${refId}-alignment-function`} - > - - + + + + + onChange({ ...query, alignmentPeriod: period })} aligmentPeriods={ALIGNMENT_PERIODS} /> - - + + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx b/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx index 21baefb8db5..6f43517cc34 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/AlignmentFunction.tsx @@ -3,7 +3,6 @@ import React, { FC, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; import { Select } from '@grafana/ui'; -import { SELECT_WIDTH } from '../constants'; import { getAlignmentPickerData } from '../functions'; import { MetricQuery } from '../types'; @@ -23,7 +22,6 @@ export const AlignmentFunction: FC = ({ inputId, query, templateVariableO return ( + /> ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx index 4967ae95231..08d70b5c06d 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/AnnotationQueryEditor.tsx @@ -2,10 +2,8 @@ import React, { useState } from 'react'; import { useDebounce } from 'react-use'; import { QueryEditorProps, toOption } from '@grafana/data'; -import { config } from '@grafana/runtime'; import { EditorField, EditorRows, Input } from '@grafana/ui'; -import { INPUT_WIDTH } from '../constants'; import CloudMonitoringDatasource from '../datasource'; import { EditorMode, @@ -16,10 +14,9 @@ import { AlignmentTypes, } from '../types'; -import { MetricQueryEditor as ExperimentalMetricQueryEditor } from './Experimental/MetricQueryEditor'; import { MetricQueryEditor } from './MetricQueryEditor'; -import { AnnotationsHelp, QueryEditorRow } from './'; +import { AnnotationsHelp } from './'; export type Props = QueryEditorProps; @@ -80,44 +77,23 @@ export const AnnotationQueryEditor = (props: Props) => { return ( - {config.featureToggles.cloudMonitoringExperimentalUI ? ( - <> - - - - - - - - - ) : ( - <> - - - - - - - - - - )} + <> + + + + + + + + ); diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.test.tsx deleted file mode 100644 index 4544201c624..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.test.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import React from 'react'; -import { openMenu } from 'react-select-event'; -import { TemplateSrvStub } from 'test/specs/helpers'; - -import { ValueTypes, MetricKind } from '../../types'; - -import { Aggregation, Props } from './Aggregation'; - -const props: Props = { - onChange: () => {}, - // @ts-ignore - templateSrv: new TemplateSrvStub(), - metricDescriptor: { - valueType: '', - metricKind: '', - } as any, - crossSeriesReducer: '', - groupBys: [], - templateVariableOptions: [], -}; - -describe('Aggregation', () => { - it('renders correctly', () => { - render(); - expect(screen.getByTestId('cloud-monitoring-aggregation')).toBeInTheDocument(); - }); - - describe('options', () => { - describe('when DOUBLE and GAUGE is passed as props', () => { - const nextProps = { - ...props, - metricDescriptor: { - valueType: ValueTypes.DOUBLE, - metricKind: MetricKind.GAUGE, - } as any, - }; - - it('should not have the reduce values', () => { - render(); - const label = screen.getByLabelText('Group by function'); - openMenu(label); - expect(screen.queryByText('count true')).not.toBeInTheDocument(); - expect(screen.queryByText('count false')).not.toBeInTheDocument(); - }); - }); - - describe('when MONEY and CUMULATIVE is passed as props', () => { - const nextProps = { - ...props, - metricDescriptor: { - valueType: ValueTypes.MONEY, - metricKind: MetricKind.CUMULATIVE, - } as any, - }; - - it('should have the reduce values', () => { - render(); - const label = screen.getByLabelText('Group by function'); - openMenu(label); - expect(screen.getByText('none')).toBeInTheDocument(); - }); - }); - }); -}); diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.tsx deleted file mode 100644 index 3479484be4a..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Aggregation.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React, { FC, useMemo } from 'react'; - -import { SelectableValue } from '@grafana/data'; -import { EditorField, Select } from '@grafana/ui'; - -import { getAggregationOptionsByMetric } from '../../functions'; -import { MetricDescriptor, MetricKind, ValueTypes } from '../../types'; - -export interface Props { - refId: string; - onChange: (metricDescriptor: string) => void; - metricDescriptor?: MetricDescriptor; - crossSeriesReducer: string; - groupBys: string[]; - templateVariableOptions: Array>; -} - -export const Aggregation: FC = (props) => { - const aggOptions = useAggregationOptionsByMetric(props); - const selected = useSelectedFromOptions(aggOptions, props); - - return ( - - - - ); -}; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx deleted file mode 100644 index a25371ee94e..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React, { FC, useMemo } from 'react'; - -import { SelectableValue } from '@grafana/data'; -import { EditorField, EditorFieldGroup } from '@grafana/ui'; - -import { ALIGNMENT_PERIODS } from '../../constants'; -import CloudMonitoringDatasource from '../../datasource'; -import { alignmentPeriodLabel } from '../../functions'; -import { CustomMetaData, MetricQuery, SLOQuery } from '../../types'; - -import { AlignmentFunction } from './AlignmentFunction'; -import { PeriodSelect } from './PeriodSelect'; - -export interface Props { - refId: string; - onChange: (query: MetricQuery | SLOQuery) => void; - query: MetricQuery; - templateVariableOptions: Array>; - customMetaData: CustomMetaData; - datasource: CloudMonitoringDatasource; -} - -export const Alignment: FC = ({ - refId, - templateVariableOptions, - onChange, - query, - customMetaData, - datasource, -}) => { - const alignmentLabel = useMemo(() => alignmentPeriodLabel(customMetaData, datasource), [customMetaData, datasource]); - return ( - - - - - - onChange({ ...query, alignmentPeriod: period })} - aligmentPeriods={ALIGNMENT_PERIODS} - /> - - - ); -}; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AlignmentFunction.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AlignmentFunction.tsx deleted file mode 100644 index bcc1a250f0c..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AlignmentFunction.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { FC, useMemo } from 'react'; - -import { SelectableValue } from '@grafana/data'; -import { Select } from '@grafana/ui'; - -import { getAlignmentPickerData } from '../../functions'; -import { MetricQuery } from '../../types'; - -export interface Props { - inputId: string; - onChange: (query: MetricQuery) => void; - query: MetricQuery; - templateVariableOptions: Array>; -} - -export const AlignmentFunction: FC = ({ inputId, query, templateVariableOptions, onChange }) => { - const { valueType, metricKind, perSeriesAligner: psa, preprocessor } = query; - const { perSeriesAligner, alignOptions } = useMemo( - () => getAlignmentPickerData(valueType, metricKind, psa, preprocessor), - [valueType, metricKind, psa, preprocessor] - ); - - return ( - `Use label key: ${v}`} - allowCustomValue - value={key} - options={options} - onChange={({ value: key = '' }) => onChangeItem({ key, operator, value, condition })} - /> - `Use label value: ${v}`} - allowCustomValue - value={value} - options={valueOptions} - onChange={({ value = '' }) => onChangeItem({ key, operator, value, condition })} - /> - - - ); - }; - - return ( - - - - - - ); -}; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.test.tsx deleted file mode 100644 index 52567630f2d..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { render, screen, act } from '@testing-library/react'; -import React from 'react'; - -import { config } from '@grafana/runtime'; -import { TemplateSrvMock } from 'app/features/templating/template_srv.mock'; - -import { createMockDatasource } from '../../__mocks__/cloudMonitoringDatasource'; -import { createMockMetricQuery } from '../../__mocks__/cloudMonitoringQuery'; - -import { MetricQueryEditor, Props } from './MetricQueryEditor'; - -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - getTemplateSrv: () => new TemplateSrvMock({}), -})); - -const props: Props = { - onChange: jest.fn(), - refId: 'refId', - customMetaData: {}, - onRunQuery: jest.fn(), - datasource: createMockDatasource(), - variableOptionGroup: { options: [] }, - query: createMockMetricQuery(), -}; - -describe('Cloud monitoring: Metric Query Editor', () => { - it('shoud render Project selector', async () => { - await act(async () => { - const originalValue = config.featureToggles.cloudMonitoringExperimentalUI; - config.featureToggles.cloudMonitoringExperimentalUI = true; - - render(); - - expect(screen.getByLabelText('Project')).toBeInTheDocument(); - - config.featureToggles.cloudMonitoringExperimentalUI = originalValue; - }); - }); -}); diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.tsx deleted file mode 100644 index 4db17479d9e..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/MetricQueryEditor.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import React, { useCallback, useEffect, useState } from 'react'; - -import { SelectableValue } from '@grafana/data'; -import { EditorRows } from '@grafana/ui'; - -import CloudMonitoringDatasource from '../../datasource'; -import { getAlignmentPickerData } from '../../functions'; -import { - AlignmentTypes, - CustomMetaData, - EditorMode, - MetricDescriptor, - MetricKind, - MetricQuery, - PreprocessorType, - SLOQuery, - ValueTypes, -} from '../../types'; - -import { MQLQueryEditor } from './../MQLQueryEditor'; -import { GraphPeriod } from './GraphPeriod'; -import { VisualMetricQueryEditor } from './VisualMetricQueryEditor'; - -export interface Props { - refId: string; - customMetaData: CustomMetaData; - variableOptionGroup: SelectableValue; - onChange: (query: MetricQuery) => void; - onRunQuery: () => void; - query: MetricQuery; - datasource: CloudMonitoringDatasource; -} - -interface State { - labels: any; - [key: string]: any; -} - -export const defaultState: State = { - labels: {}, -}; - -export const defaultQuery: (dataSource: CloudMonitoringDatasource) => MetricQuery = (dataSource) => ({ - editorMode: EditorMode.Visual, - projectName: dataSource.getDefaultProject(), - metricType: '', - metricKind: MetricKind.GAUGE, - valueType: '', - crossSeriesReducer: 'REDUCE_MEAN', - alignmentPeriod: 'cloud-monitoring-auto', - perSeriesAligner: AlignmentTypes.ALIGN_MEAN, - groupBys: [], - filters: [], - aliasBy: '', - query: '', - preprocessor: PreprocessorType.None, -}); - -function Editor({ - refId, - query, - datasource, - onChange: onQueryChange, - onRunQuery, - customMetaData, - variableOptionGroup, -}: React.PropsWithChildren) { - const [state, setState] = useState(defaultState); - const { projectName, metricType, groupBys, editorMode, crossSeriesReducer } = query; - - useEffect(() => { - if (projectName && metricType) { - datasource - .getLabels(metricType, refId, projectName) - .then((labels) => setState((prevState) => ({ ...prevState, labels }))); - } - }, [datasource, groupBys, metricType, projectName, refId, crossSeriesReducer]); - - const onChange = useCallback( - (metricQuery: MetricQuery | SLOQuery) => { - onQueryChange({ ...query, ...metricQuery }); - onRunQuery(); - }, - [onQueryChange, onRunQuery, query] - ); - - const onMetricTypeChange = useCallback( - ({ valueType, metricKind, type }: MetricDescriptor) => { - const preprocessor = - metricKind === MetricKind.GAUGE || valueType === ValueTypes.DISTRIBUTION - ? PreprocessorType.None - : PreprocessorType.Rate; - const { perSeriesAligner } = getAlignmentPickerData(valueType, metricKind, state.perSeriesAligner, preprocessor); - onChange({ - ...query, - perSeriesAligner, - metricType: type, - valueType, - metricKind, - preprocessor, - }); - }, - [onChange, query, state] - ); - - return ( - - {editorMode === EditorMode.Visual && ( - - )} - - {editorMode === EditorMode.MQL && ( - <> - onQueryChange({ ...query, query: q })} - onRunQuery={onRunQuery} - query={query.query} - > - onQueryChange({ ...query, graphPeriod })} - graphPeriod={query.graphPeriod} - refId={refId} - variableOptionGroup={variableOptionGroup} - /> - - )} - - ); -} - -export const MetricQueryEditor = React.memo(Editor); diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Metrics.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Metrics.tsx deleted file mode 100644 index 4b31d5ba864..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Metrics.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import { css } from '@emotion/css'; -import { startCase, uniqBy } from 'lodash'; -import React, { useCallback, useEffect, useState } from 'react'; - -import { GrafanaTheme2, SelectableValue } from '@grafana/data'; -import { EditorField, EditorFieldGroup, EditorRow, getSelectStyles, Select, useStyles2, useTheme2 } from '@grafana/ui'; - -import CloudMonitoringDatasource from '../../datasource'; -import { MetricDescriptor, MetricQuery } from '../../types'; - -import { Project } from './Project'; - -export interface Props { - refId: string; - onChange: (metricDescriptor: MetricDescriptor) => void; - templateVariableOptions: Array>; - datasource: CloudMonitoringDatasource; - projectName: string; - metricType: string; - query: MetricQuery; - children: (metricDescriptor?: MetricDescriptor) => JSX.Element; - onProjectChange: (query: MetricQuery) => void; -} - -export function Metrics(props: Props) { - const [metricDescriptors, setMetricDescriptors] = useState([]); - const [metricDescriptor, setMetricDescriptor] = useState(); - const [metrics, setMetrics] = useState>>([]); - const [services, setServices] = useState>>([]); - const [service, setService] = useState(''); - - const theme = useTheme2(); - const selectStyles = getSelectStyles(theme); - - const customStyle = useStyles2(getStyles); - - const { - onProjectChange, - query, - refId, - metricType, - templateVariableOptions, - projectName, - datasource, - onChange, - children, - } = props; - const { templateSrv } = datasource; - - const getSelectedMetricDescriptor = useCallback( - (metricDescriptors: MetricDescriptor[], metricType: string) => { - return metricDescriptors.find((md) => md.type === templateSrv.replace(metricType))!; - }, - [templateSrv] - ); - - useEffect(() => { - const getMetricsList = (metricDescriptors: MetricDescriptor[]) => { - const selectedMetricDescriptor = getSelectedMetricDescriptor(metricDescriptors, metricType); - if (!selectedMetricDescriptor) { - return []; - } - - const metricsByService = metricDescriptors - .filter((m) => m.service === selectedMetricDescriptor.service) - .map((m) => ({ - service: m.service, - value: m.type, - label: m.displayName, - component: function optionComponent() { - return ( -
-
{m.type}
-
{m.description}
-
- ); - }, - })); - return metricsByService; - }; - - const loadMetricDescriptors = async () => { - if (projectName) { - const metricDescriptors = await datasource.getMetricTypes(projectName); - const services = getServicesList(metricDescriptors); - const metrics = getMetricsList(metricDescriptors); - const service = metrics.length > 0 ? metrics[0].service : ''; - const metricDescriptor = getSelectedMetricDescriptor(metricDescriptors, metricType); - setMetricDescriptors(metricDescriptors); - setServices(services); - setMetrics(metrics); - setService(service); - setMetricDescriptor(metricDescriptor); - } - }; - loadMetricDescriptors(); - }, [datasource, getSelectedMetricDescriptor, metricType, projectName, customStyle, selectStyles.optionDescription]); - - const onServiceChange = ({ value: service }: any) => { - const metrics = metricDescriptors - .filter((m: MetricDescriptor) => m.service === templateSrv.replace(service)) - .map((m: MetricDescriptor) => ({ - service: m.service, - value: m.type, - label: m.displayName, - description: m.description, - })); - - if (metrics.length > 0 && !metrics.some((m) => m.value === templateSrv.replace(metricType))) { - onMetricTypeChange(metrics[0]); - setService(service); - setMetrics(metrics); - } else { - setService(service); - setMetrics(metrics); - } - }; - - const onMetricTypeChange = ({ value }: SelectableValue) => { - const metricDescriptor = getSelectedMetricDescriptor(metricDescriptors, value!); - setMetricDescriptor(metricDescriptor); - onChange({ ...metricDescriptor, type: value! }); - }; - - const getServicesList = (metricDescriptors: MetricDescriptor[]) => { - const services = metricDescriptors.map((m) => ({ - value: m.service, - label: startCase(m.serviceShortName), - })); - - return services.length > 0 ? uniqBy(services, (s) => s.value) : []; - }; - - return ( - <> - - - { - onProjectChange({ ...query, projectName }); - }} - /> - - - s.value === metricType)} - options={[ - { - label: 'Template Variables', - options: templateVariableOptions, - }, - ...metrics, - ]} - placeholder="Select Metric" - inputId={`${props.refId}-select-metric`} - /> - - - - - {children(metricDescriptor)} - - ); -} - -const getStyles = (theme: GrafanaTheme2) => css` - label: grafana-select-option-description; - font-weight: normal; - font-style: italic; - color: ${theme.colors.text.secondary}; -`; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/PeriodSelect.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/PeriodSelect.tsx deleted file mode 100644 index ce388b98cb4..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/PeriodSelect.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React, { useMemo } from 'react'; - -import { SelectableValue } from '@grafana/data'; -import { Select } from '@grafana/ui'; - -import { periodOption } from '../../constants'; - -export interface Props { - inputId: string; - onChange: (period: string) => void; - templateVariableOptions: Array>; - aligmentPeriods: periodOption[]; - selectWidth?: number; - category?: string; - disabled?: boolean; - current?: string; -} - -export function PeriodSelect({ - inputId, - templateVariableOptions, - onChange, - current, - disabled, - aligmentPeriods, -}: Props) { - const options = useMemo( - () => - aligmentPeriods.map((ap) => ({ - ...ap, - label: ap.text, - })), - [aligmentPeriods] - ); - const visibleOptions = useMemo(() => options.filter((ap) => !ap.hidden), [options]); - - return ( - `Use project: ${v}`} - onChange={({ value }) => onChange(value!)} - options={projectsWithTemplateVariables} - value={{ value: projectName, label: projectName }} - placeholder="Select Project" - inputId={`${refId}-project`} - /> - - ); -} diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.test.tsx deleted file mode 100644 index ec89ce8fe0d..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { render, screen, act } from '@testing-library/react'; -import React from 'react'; - -import { config } from '@grafana/runtime'; -import { TemplateSrvMock } from 'app/features/templating/template_srv.mock'; - -import { createMockDatasource } from '../../__mocks__/cloudMonitoringDatasource'; -import { createMockSLOQuery } from '../../__mocks__/cloudMonitoringQuery'; - -import { SLOQueryEditor, Props } from './SLOQueryEditor'; - -jest.mock('@grafana/runtime', () => ({ - ...jest.requireActual('@grafana/runtime'), - getTemplateSrv: () => new TemplateSrvMock({}), -})); - -const props: Props = { - onChange: jest.fn(), - refId: 'refId', - customMetaData: {}, - onRunQuery: jest.fn(), - datasource: createMockDatasource(), - variableOptionGroup: { options: [] }, - query: createMockSLOQuery(), -}; - -describe('Cloud monitoring: SLO Query Editor', () => { - it('shoud render Service selector', async () => { - await act(async () => { - const originalValue = config.featureToggles.cloudMonitoringExperimentalUI; - config.featureToggles.cloudMonitoringExperimentalUI = true; - - render(); - - expect(screen.getByLabelText('Service')).toBeInTheDocument(); - - config.featureToggles.cloudMonitoringExperimentalUI = originalValue; - }); - }); -}); diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx deleted file mode 100644 index 7829cd48c3e..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React from 'react'; - -import { SelectableValue } from '@grafana/data'; -import { EditorRow } from '@grafana/ui'; - -import CloudMonitoringDatasource from '../../datasource'; -import { CustomMetaData, MetricDescriptor, MetricQuery, SLOQuery } from '../../types'; - -import { AliasBy } from './AliasBy'; -import { Alignment } from './Alignment'; -import { GroupBy } from './GroupBy'; -import { LabelFilter } from './LabelFilter'; -import { Metrics } from './Metrics'; -import { Preprocessor } from './Preprocessor'; - -export interface Props { - refId: string; - customMetaData: CustomMetaData; - variableOptionGroup: SelectableValue; - onMetricTypeChange: (query: MetricDescriptor) => void; - onChange: (query: MetricQuery | SLOQuery) => void; - query: MetricQuery; - datasource: CloudMonitoringDatasource; - labels: any; -} - -function Editor({ - refId, - query, - labels, - datasource, - onChange, - onMetricTypeChange, - customMetaData, - variableOptionGroup, -}: React.PropsWithChildren) { - return ( - - {(metric) => ( - <> - onChange({ ...query, filters })} - variableOptionGroup={variableOptionGroup} - /> - - - - - { - onChange({ ...query, aliasBy }); - }} - /> - - - )} - - ); -} - -export const VisualMetricQueryEditor = React.memo(Editor); diff --git a/public/app/plugins/datasource/cloud-monitoring/components/GraphPeriod.tsx b/public/app/plugins/datasource/cloud-monitoring/components/GraphPeriod.tsx index e6081a1b43f..cdd9e2c6c3d 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/GraphPeriod.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/GraphPeriod.tsx @@ -1,11 +1,11 @@ import React, { FunctionComponent } from 'react'; import { SelectableValue } from '@grafana/data'; -import { Switch } from '@grafana/ui'; +import { EditorField, EditorRow, HorizontalGroup, Switch } from '@grafana/ui'; -import { GRAPH_PERIODS, SELECT_WIDTH } from '../constants'; +import { GRAPH_PERIODS } from '../constants'; -import { PeriodSelect, QueryEditorRow } from '.'; +import { PeriodSelect } from './index'; export interface Props { refId: string; @@ -16,8 +16,8 @@ export interface Props { export const GraphPeriod: FunctionComponent = ({ refId, onChange, graphPeriod, variableOptionGroup }) => { return ( - <> - + = ({ refId, onChange, graphPe } > - onChange(e.currentTarget.checked ? '' : 'disabled')} - /> - - - + + onChange(e.currentTarget.checked ? '' : 'disabled')} + /> + + + + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/GroupBy.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.test.tsx similarity index 94% rename from public/app/plugins/datasource/cloud-monitoring/components/Experimental/GroupBy.test.tsx rename to public/app/plugins/datasource/cloud-monitoring/components/GroupBy.test.tsx index be4b7fce748..781b7fe32a1 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/GroupBy.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.test.tsx @@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; import { openMenu, select } from 'react-select-event'; -import { createMockMetricQuery } from '../../__mocks__/cloudMonitoringQuery'; +import { createMockMetricQuery } from '../__mocks__/cloudMonitoringQuery'; import { GroupBy, Props } from './GroupBy'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx b/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx index 52d6f01ec57..0fcb97cde9c 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/GroupBy.tsx @@ -1,13 +1,13 @@ import React, { FunctionComponent, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; -import { MultiSelect } from '@grafana/ui'; +import { EditorField, EditorFieldGroup, MultiSelect } from '@grafana/ui'; -import { INPUT_WIDTH, SYSTEM_LABELS } from '../constants'; +import { SYSTEM_LABELS } from '../constants'; import { labelsToGroupedOptions } from '../functions'; import { MetricDescriptor, MetricQuery } from '../types'; -import { Aggregation, QueryEditorRow } from '.'; +import { Aggregation } from './Aggregation'; export interface Props { refId: string; @@ -32,21 +32,22 @@ export const GroupBy: FunctionComponent = ({ ); return ( - - { - onChange({ ...query, groupBys: options.map((o) => o.value!) }); - }} - > + + + { + onChange({ ...query, groupBys: options.map((o) => o.value!) }); + }} + /> + = ({ groupBys={query.groupBys ?? []} onChange={(crossSeriesReducer) => onChange({ ...query, crossSeriesReducer })} refId={refId} - > - + /> + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/LabelFilter.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/LabelFilter.test.tsx similarity index 100% rename from public/app/plugins/datasource/cloud-monitoring/components/Experimental/LabelFilter.test.tsx rename to public/app/plugins/datasource/cloud-monitoring/components/LabelFilter.test.tsx diff --git a/public/app/plugins/datasource/cloud-monitoring/components/LabelFilter.tsx b/public/app/plugins/datasource/cloud-monitoring/components/LabelFilter.tsx index 55bd19d7b3c..d949b63da65 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/LabelFilter.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/LabelFilter.tsx @@ -1,15 +1,9 @@ -import { flatten } from 'lodash'; -import React, { FunctionComponent, useCallback, useMemo } from 'react'; +import React, { FunctionComponent, useMemo } from 'react'; import { SelectableValue, toOption } from '@grafana/data'; -import { Button, HorizontalGroup, Select, VerticalGroup } from '@grafana/ui'; -import { CustomControlProps } from '@grafana/ui/src/components/Select/types'; +import { AccessoryButton, EditorField, EditorList, EditorRow, HorizontalGroup, Select } from '@grafana/ui'; -import { SELECT_WIDTH } from '../constants'; import { labelsToGroupedOptions, stringArrayToFilters } from '../functions'; -import { Filter } from '../types'; - -import { QueryEditorRow } from '.'; export interface Props { labels: { [key: string]: string[] }; @@ -18,137 +12,107 @@ export interface Props { variableOptionGroup: SelectableValue; } -const operators = ['=', '!=', '=~', '!=~']; +interface Filter { + key: string; + operator: string; + value: string; + condition: string; +} -const FilterButton = React.forwardRef>( - ({ value, isOpen, invalid, ...rest }, ref) => { - return ; - } -); -FilterButton.displayName = 'FilterButton'; +const DEFAULT_OPERATOR = '='; +const DEFAULT_CONDITION = 'AND'; -const OperatorButton = React.forwardRef>(({ value, ...rest }, ref) => { - return ( - - ); -}); -OperatorButton.displayName = 'OperatorButton'; +const filtersToStringArray = (filters: Filter[]) => + filters.flatMap(({ key, operator, value, condition }) => [key, operator, value, condition]).slice(0, -1); + +const operators = ['=', '!=', '=~', '!=~'].map(toOption); export const LabelFilter: FunctionComponent = ({ labels = {}, filters: filterArray, - onChange, + onChange: _onChange, variableOptionGroup, }) => { - const filters = useMemo(() => stringArrayToFilters(filterArray), [filterArray]); + const filters: Filter[] = useMemo(() => stringArrayToFilters(filterArray), [filterArray]); const options = useMemo( () => [variableOptionGroup, ...labelsToGroupedOptions(Object.keys(labels))], [labels, variableOptionGroup] ); - const filtersToStringArray = useCallback((filters: Filter[]) => { - const strArr = flatten(filters.map(({ key, operator, value, condition }) => [key, operator, value, condition!])); - return strArr.slice(0, strArr.length - 1); - }, []); + const getOptions = ({ key = '', value = '' }: Partial) => { + // Add the current key and value as options if they are manually entered + const keyPresent = options.some((op) => { + if (op.options) { + return options.some((opp) => opp.label === key); + } + return op.label === key; + }); + if (!keyPresent) { + options.push({ label: key, value: key }); + } + + const valueOptions = labels.hasOwnProperty(key) + ? [variableOptionGroup, ...labels[key].map(toOption)] + : [variableOptionGroup]; + const valuePresent = valueOptions.some((op) => op.label === value); + if (!valuePresent) { + valueOptions.push({ label: value, value }); + } + + return { options, valueOptions }; + }; + + const onChange = (items: Array>) => { + const filters = items.map(({ key, operator, value, condition }) => ({ + key: key || '', + operator: operator || DEFAULT_OPERATOR, + value: value || '', + condition: condition || DEFAULT_CONDITION, + })); + _onChange(filtersToStringArray(filters)); + }; + + const renderItem = (item: Partial, onChangeItem: (item: Filter) => void, onDeleteItem: () => void) => { + const { key = '', operator = DEFAULT_OPERATOR, value = '', condition = DEFAULT_CONDITION } = item; + const { options, valueOptions } = getOptions(item); - const AddFilter = () => { return ( - `Use label key: ${v}`} + allowCustomValue + value={key} + options={options} + onChange={({ value: key = '' }) => onChangeItem({ key, operator, value, condition })} + /> + `Use label value: ${v}`} + allowCustomValue + value={value} + options={valueOptions} + onChange={({ value = '' }) => onChangeItem({ key, operator, value, condition })} + /> + + ); }; return ( - 1} - > - - {filters.map(({ key, operator, value, condition }, index) => { - // Add the current key and value as options if they are manually entered - const keyPresent = options.some((op) => { - if (op.options) { - return options.some((opp) => opp.label === key); - } - return op.label === key; - }); - if (!keyPresent) { - options.push({ label: key, value: key }); - } - - const valueOptions = labels.hasOwnProperty(key) - ? [variableOptionGroup, ...labels[key].map(toOption)] - : [variableOptionGroup]; - const valuePresent = valueOptions.some((op) => { - return op.label === value; - }); - if (!valuePresent) { - valueOptions.push({ label: value, value }); - } - - return ( - - - onChange(filtersToStringArray(filters.map((f, i) => (i === index ? { ...f, operator } : f)))) - } - menuPlacement="bottom" - renderControl={OperatorButton} - /> - s.value === service)} - options={[ - { - label: 'Template Variables', - options: templateVariableOptions, - }, - ...services, - ]} - placeholder="Select Services" - inputId={`${props.refId}-service`} - > -
- - - - + + + { + onProjectChange({ ...query, projectName }); + }} + /> - {children(state.metricDescriptor)} + + s.value === metricType)} + options={[ + { + label: 'Template Variables', + options: templateVariableOptions, + }, + ...metrics, + ]} + placeholder="Select Metric" + inputId={`${props.refId}-select-metric`} + /> + + + + + {children(metricDescriptor)} ); } diff --git a/public/app/plugins/datasource/cloud-monitoring/components/PeriodSelect.tsx b/public/app/plugins/datasource/cloud-monitoring/components/PeriodSelect.tsx index 15aab5d45ef..24fe3dbbfd5 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/PeriodSelect.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/PeriodSelect.tsx @@ -21,7 +21,6 @@ export function PeriodSelect({ templateVariableOptions, onChange, current, - selectWidth, disabled, aligmentPeriods, }: Props) { @@ -37,7 +36,7 @@ export function PeriodSelect({ return ( + /> ); } diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx similarity index 94% rename from public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.test.tsx rename to public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx index 3a0a0346048..f2c7c216717 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.test.tsx @@ -4,9 +4,9 @@ import React from 'react'; import { TemplateSrvMock } from 'app/features/templating/template_srv.mock'; -import { createMockMetricDescriptor } from '../../__mocks__/cloudMonitoringMetricDescriptor'; -import { createMockMetricQuery } from '../../__mocks__/cloudMonitoringQuery'; -import { MetricKind, ValueTypes } from '../../types'; +import { createMockMetricDescriptor } from '../__mocks__/cloudMonitoringMetricDescriptor'; +import { createMockMetricQuery } from '../__mocks__/cloudMonitoringQuery'; +import { MetricKind, ValueTypes } from '../types'; import { Preprocessor } from './Preprocessor'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx index 1dc72c44ef6..3b24d172ef7 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Preprocessor.tsx @@ -1,13 +1,11 @@ import React, { FunctionComponent, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; -import { RadioButtonGroup } from '@grafana/ui'; +import { EditorField, RadioButtonGroup } from '@grafana/ui'; import { getAlignmentPickerData } from '../functions'; import { MetricDescriptor, MetricKind, MetricQuery, PreprocessorType, ValueTypes } from '../types'; -import { QueryEditorRow } from '.'; - const NONE_OPTION = { label: 'None', value: PreprocessorType.None }; export interface Props { @@ -19,7 +17,7 @@ export interface Props { export const Preprocessor: FunctionComponent = ({ query, metricDescriptor, onChange }) => { const options = useOptions(metricDescriptor); return ( - @@ -31,8 +29,8 @@ export const Preprocessor: FunctionComponent = ({ query, metricDescriptor }} value={query.preprocessor ?? PreprocessorType.None} options={options} - > - + /> + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Project.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Project.tsx index 436bcd6b18f..172cd7d9089 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Project.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Project.tsx @@ -1,13 +1,10 @@ import React, { useEffect, useMemo, useState } from 'react'; import { SelectableValue } from '@grafana/data'; -import { Select } from '@grafana/ui'; +import { EditorField, Select } from '@grafana/ui'; -import { SELECT_WIDTH } from '../constants'; import CloudMonitoringDatasource from '../datasource'; -import { QueryEditorRow } from '.'; - export interface Props { refId: string; datasource: CloudMonitoringDatasource; @@ -35,9 +32,9 @@ export function Project({ refId, projectName, datasource, onChange, templateVari ); return ( - + { - onChange({ ...query, sloQuery, queryType: value! }); - onRunQuery(); - }} - inputId={`${query.refId}-query-type`} - /> - - {queryType === QueryType.METRICS && ( void; - templateVariableOptions: Array>; - current?: string; -} - -export const LookbackPeriodSelect: FunctionComponent = ({ - refId, - current, - templateVariableOptions, - onChange, -}) => { - const options = LOOKBACK_PERIODS.map((lp) => ({ - ...lp, - label: lp.text, - })); - if (current && !options.find((op) => op.value === current)) { - options.push({ label: current, text: current, value: current, hidden: false }); - } - const visibleOptions = options.filter((lp) => !lp.hidden); - - return ( - - { - const slos = await datasource.getServiceLevelObjectives(projectName, serviceId); - const slo = slos.find(({ value }) => value === datasource.templateSrv.replace(sloId)); - onChange({ ...query, sloId, sloName, goal: slo?.goal }); - }} - /> - - ); -}; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/SLO/SLOQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/SLO/SLOQueryEditor.tsx deleted file mode 100644 index ea94d1fb2cf..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/SLO/SLOQueryEditor.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React from 'react'; - -import { SelectableValue } from '@grafana/data'; - -import { AliasBy, PeriodSelect, AlignmentPeriodLabel, Project, QueryEditorRow } from '..'; -import { ALIGNMENT_PERIODS, SELECT_WIDTH, SLO_BURN_RATE_SELECTOR_NAME } from '../../constants'; -import CloudMonitoringDatasource from '../../datasource'; -import { AlignmentTypes, CustomMetaData, SLOQuery } from '../../types'; - -import { LookbackPeriodSelect } from './LookbackPeriodSelect'; - -import { Selector, Service, SLO } from '.'; - -export interface Props { - refId: string; - customMetaData: CustomMetaData; - variableOptionGroup: SelectableValue; - onChange: (query: SLOQuery) => void; - onRunQuery: () => void; - query: SLOQuery; - datasource: CloudMonitoringDatasource; -} - -export const defaultQuery: (dataSource: CloudMonitoringDatasource) => SLOQuery = (dataSource) => ({ - projectName: dataSource.getDefaultProject(), - alignmentPeriod: 'cloud-monitoring-auto', - perSeriesAligner: AlignmentTypes.ALIGN_MEAN, - aliasBy: '', - selectorName: 'select_slo_health', - serviceId: '', - serviceName: '', - sloId: '', - sloName: '', - lookbackPeriod: '', -}); - -export function SLOQueryEditor({ - refId, - query, - datasource, - onChange, - variableOptionGroup, - customMetaData, -}: React.PropsWithChildren) { - return ( - <> - onChange({ ...query, projectName })} - /> - - - - - {query.selectorName === SLO_BURN_RATE_SELECTOR_NAME && ( - onChange({ ...query, lookbackPeriod: lookbackPeriod })} - current={query.lookbackPeriod} - templateVariableOptions={variableOptionGroup.options} - /> - )} - - - onChange({ ...query, alignmentPeriod: period })} - aligmentPeriods={ALIGNMENT_PERIODS} - /> - - - - onChange({ ...query, aliasBy })} /> - - ); -} diff --git a/public/app/plugins/datasource/cloud-monitoring/components/SLO/Selector.tsx b/public/app/plugins/datasource/cloud-monitoring/components/SLO/Selector.tsx deleted file mode 100644 index bc9f812b84a..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/SLO/Selector.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; - -import { SelectableValue } from '@grafana/data'; -import { Select } from '@grafana/ui'; - -import { QueryEditorRow } from '..'; -import { SELECT_WIDTH, SELECTORS } from '../../constants'; -import CloudMonitoringDatasource from '../../datasource'; -import { SLOQuery } from '../../types'; - -export interface Props { - refId: string; - onChange: (query: SLOQuery) => void; - query: SLOQuery; - templateVariableOptions: Array>; - datasource: CloudMonitoringDatasource; -} - -export const Selector = ({ refId, query, templateVariableOptions, onChange, datasource }: Props) => { - return ( - - - onChange({ ...query, serviceId, serviceName, sloId: '' }) - } - /> - - ); -}; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/SLO/index.ts b/public/app/plugins/datasource/cloud-monitoring/components/SLO/index.ts deleted file mode 100644 index 67aea9f0767..00000000000 --- a/public/app/plugins/datasource/cloud-monitoring/components/SLO/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { Service } from './Service'; -export { SLO } from './SLO'; -export { Selector } from './Selector'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/SLOQueryEditor.tsx similarity index 94% rename from public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.tsx rename to public/app/plugins/datasource/cloud-monitoring/components/SLOQueryEditor.tsx index 58a2e4fc1ef..7bd8bee4cf3 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/SLOQueryEditor.tsx @@ -3,10 +3,10 @@ import React, { useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/ui'; -import { ALIGNMENT_PERIODS, SLO_BURN_RATE_SELECTOR_NAME } from '../../constants'; -import CloudMonitoringDatasource from '../../datasource'; -import { alignmentPeriodLabel } from '../../functions'; -import { AlignmentTypes, CustomMetaData, SLOQuery } from '../../types'; +import { ALIGNMENT_PERIODS, SLO_BURN_RATE_SELECTOR_NAME } from '../constants'; +import CloudMonitoringDatasource from '../datasource'; +import { alignmentPeriodLabel } from '../functions'; +import { AlignmentTypes, CustomMetaData, SLOQuery } from '../types'; import { AliasBy } from './AliasBy'; import { LookbackPeriodSelect } from './LookbackPeriodSelect'; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Selector.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Selector.tsx similarity index 87% rename from public/app/plugins/datasource/cloud-monitoring/components/Experimental/Selector.tsx rename to public/app/plugins/datasource/cloud-monitoring/components/Selector.tsx index e338c906781..66104222e3f 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Selector.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Selector.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { SelectableValue } from '@grafana/data'; import { EditorField, Select } from '@grafana/ui'; -import { SELECTORS } from '../../constants'; -import CloudMonitoringDatasource from '../../datasource'; -import { SLOQuery } from '../../types'; +import { SELECTORS } from '../constants'; +import CloudMonitoringDatasource from '../datasource'; +import { SLOQuery } from '../types'; export interface Props { refId: string; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Service.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Service.tsx similarity index 93% rename from public/app/plugins/datasource/cloud-monitoring/components/Experimental/Service.tsx rename to public/app/plugins/datasource/cloud-monitoring/components/Service.tsx index 8c4a0dfa99a..963adea22a5 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Service.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Service.tsx @@ -3,8 +3,8 @@ import React, { useEffect, useState } from 'react'; import { SelectableValue } from '@grafana/data'; import { EditorField, Select } from '@grafana/ui'; -import CloudMonitoringDatasource from '../../datasource'; -import { SLOQuery } from '../../types'; +import CloudMonitoringDatasource from '../datasource'; +import { SLOQuery } from '../types'; export interface Props { refId: string; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx index 79bb0b228c8..a42f6638696 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/VisualMetricQueryEditor.tsx @@ -1,11 +1,17 @@ import React from 'react'; import { SelectableValue } from '@grafana/data'; +import { EditorRow } from '@grafana/ui'; import CloudMonitoringDatasource from '../datasource'; import { CustomMetaData, MetricDescriptor, MetricQuery, SLOQuery } from '../types'; -import { Alignment, GroupBy, LabelFilter, Metrics, Preprocessor } from '.'; +import { AliasBy } from './AliasBy'; +import { Alignment } from './Alignment'; +import { GroupBy } from './GroupBy'; +import { LabelFilter } from './LabelFilter'; +import { Metrics } from './Metrics'; +import { Preprocessor } from './Preprocessor'; export interface Props { refId: string; @@ -31,12 +37,13 @@ function Editor({ return ( {(metric) => ( <> @@ -46,23 +53,32 @@ function Editor({ onChange={(filters: string[]) => onChange({ ...query, filters })} variableOptionGroup={variableOptionGroup} /> - - - + + + + + { + onChange({ ...query, aliasBy }); + }} + /> + )} diff --git a/public/app/plugins/datasource/cloud-monitoring/components/index.ts b/public/app/plugins/datasource/cloud-monitoring/components/index.ts index 0b51aad1ead..d16b907c48a 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/index.ts +++ b/public/app/plugins/datasource/cloud-monitoring/components/index.ts @@ -9,7 +9,7 @@ export { AlignmentPeriodLabel } from './AlignmentPeriodLabel'; export { AliasBy } from './AliasBy'; export { Aggregation } from './Aggregation'; export { MetricQueryEditor } from './MetricQueryEditor'; -export { SLOQueryEditor } from './SLO/SLOQueryEditor'; +export { SLOQueryEditor } from './SLOQueryEditor'; export { MQLQueryEditor } from './MQLQueryEditor'; export { VariableQueryField, QueryEditorRow, QueryEditorField } from './Fields'; export { VisualMetricQueryEditor } from './VisualMetricQueryEditor';