diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AliasBy.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AliasBy.tsx index b4abe66e4b6..294c5c92f6f 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AliasBy.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AliasBy.tsx @@ -1,7 +1,7 @@ import { debounce } from 'lodash'; import React, { FunctionComponent, useState } from 'react'; -import { EditorField, EditorRow, Input } from '@grafana/ui'; +import { EditorField, Input } from '@grafana/ui'; import { SELECT_WIDTH } from '../../constants'; @@ -22,10 +22,8 @@ export const AliasBy: FunctionComponent = ({ refId, value = '', onChange }; return ( - - - - - + + + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.test.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.test.tsx index a81039f9b03..a3fa46189b4 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.test.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.test.tsx @@ -80,23 +80,4 @@ describe('Alignment', () => { await userEvent.click(screen.getByText('1m')); expect(onChange).toBeCalledWith(expect.objectContaining({ alignmentPeriod: '+60s' })); }); - - it('renders period label if alignment period and per series aligner is set', () => { - const datasource = createMockDatasource(); - const query = createMockMetricQuery(); - const onChange = jest.fn(); - - render( - - ); - - expect(screen.getByText('10s interval (delta)')); - }); }); diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx index 49091c626f8..a25371ee94e 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Alignment.tsx @@ -1,14 +1,14 @@ -import React, { FC } from 'react'; +import React, { FC, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; -import { EditorRow, EditorFieldGroup, EditorField, Stack } from '@grafana/ui'; +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 } from './AlignmentFunction'; -import { AlignmentPeriodLabel } from './AlignmentPeriodLabel'; import { PeriodSelect } from './PeriodSelect'; export interface Props { @@ -28,34 +28,29 @@ export const Alignment: FC = ({ customMetaData, datasource, }) => { + const alignmentLabel = useMemo(() => alignmentPeriodLabel(customMetaData, datasource), [customMetaData, datasource]); return ( - - - - - - - onChange({ ...query, alignmentPeriod: period })} - aligmentPeriods={ALIGNMENT_PERIODS} - /> - - - - - - + + + + + + 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 index 49025f84028..bcc1a250f0c 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/AlignmentFunction.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/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 ( onChange(value!)} value={[...options, ...templateVariableOptions].find((s) => s.value === current)} options={[ diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.tsx index 9f968830395..590d7c1cb89 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Preprocessor.tsx @@ -1,7 +1,7 @@ import React, { FunctionComponent, useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; -import { EditorField, EditorRow, RadioButtonGroup } from '@grafana/ui'; +import { EditorField, RadioButtonGroup } from '@grafana/ui'; import { getAlignmentPickerData } from '../../functions'; import { MetricDescriptor, MetricKind, MetricQuery, PreprocessorType, ValueTypes } from '../../types'; @@ -17,22 +17,20 @@ export interface Props { export const Preprocessor: FunctionComponent = ({ query, metricDescriptor, onChange }) => { const options = useOptions(metricDescriptor); return ( - - - { - const { valueType, metricKind, perSeriesAligner: psa } = query; - const { perSeriesAligner } = getAlignmentPickerData(valueType, metricKind, psa, value); - onChange({ ...query, preprocessor: value, perSeriesAligner }); - }} - value={query.preprocessor ?? PreprocessorType.None} - options={options} - /> - - + + { + const { valueType, metricKind, perSeriesAligner: psa } = query; + const { perSeriesAligner } = getAlignmentPickerData(valueType, metricKind, psa, value); + onChange({ ...query, preprocessor: value, perSeriesAligner }); + }} + value={query.preprocessor ?? PreprocessorType.None} + options={options} + /> + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Project.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Project.tsx index 4a92219497a..9a82c54b295 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Project.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Project.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { SelectableValue } from '@grafana/data'; -import { EditorField, EditorRow, Select } from '@grafana/ui'; +import { EditorField, Select } from '@grafana/ui'; import CloudMonitoringDatasource from '../../datasource'; @@ -32,19 +32,17 @@ export function Project({ refId, projectName, datasource, onChange, templateVari ); 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/SLO.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLO.tsx index f25af420afe..71561804469 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLO.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLO.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import { SelectableValue } from '@grafana/data'; -import { EditorField, EditorRow, Select } from '@grafana/ui'; +import { Select, EditorField } from '@grafana/ui'; import CloudMonitoringDatasource from '../../datasource'; import { SLOQuery } from '../../types'; @@ -35,22 +35,20 @@ export const SLO: React.FC = ({ refId, query, templateVariableOptions, on }, [datasource, projectName, serviceId, templateVariableOptions]); 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/Experimental/SLOQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.tsx index 43be8272279..1651585cb55 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/SLOQueryEditor.tsx @@ -1,14 +1,14 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { SelectableValue } from '@grafana/data'; -import { EditorRow, EditorFieldGroup, EditorField, Stack } from '@grafana/ui'; +import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/ui'; import { ALIGNMENT_PERIODS } from '../../constants'; import CloudMonitoringDatasource from '../../datasource'; +import { alignmentPeriodLabel } from '../../functions'; import { AlignmentTypes, CustomMetaData, SLOQuery } from '../../types'; import { AliasBy } from './AliasBy'; -import { AlignmentPeriodLabel } from './AlignmentPeriodLabel'; import { PeriodSelect } from './PeriodSelect'; import { Project } from './Project'; import { SLO } from './SLO'; @@ -45,40 +45,41 @@ export function SLOQueryEditor({ variableOptionGroup, customMetaData, }: React.PropsWithChildren) { + const alignmentLabel = useMemo(() => alignmentPeriodLabel(customMetaData, datasource), [customMetaData, datasource]); return ( <> - onChange({ ...query, projectName })} - /> - - - - + onChange({ ...query, projectName })} + /> + + + + - + - - - - - onChange({ ...query, aliasBy })} /> + onChange({ ...query, aliasBy })} /> + ); } diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Selector.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Selector.tsx index d65e609ea8d..250d19e03d6 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Selector.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Selector.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { SelectableValue } from '@grafana/data'; -import { EditorField, EditorRow, Select } from '@grafana/ui'; +import { EditorField, Select } from '@grafana/ui'; import { SELECTORS } from '../../constants'; import CloudMonitoringDatasource from '../../datasource'; @@ -17,23 +17,21 @@ export interface Props { export const Selector: React.FC = ({ refId, query, templateVariableOptions, onChange, datasource }) => { return ( - - - s.value === query?.selectorName ?? '')} + options={[ + { + label: 'Template Variables', + options: templateVariableOptions, + }, + ...SELECTORS, + ]} + onChange={({ value: selectorName }) => onChange({ ...query, selectorName: selectorName ?? '' })} + /> + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Service.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Service.tsx index 8aa5f1b74aa..c592e6dd412 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Service.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/Service.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import { SelectableValue } from '@grafana/data'; -import { EditorField, EditorRow, Select } from '@grafana/ui'; +import { EditorField, Select } from '@grafana/ui'; import CloudMonitoringDatasource from '../../datasource'; import { SLOQuery } from '../../types'; @@ -35,20 +35,18 @@ export const Service: React.FC = ({ refId, query, templateVariableOptions }, [datasource, projectName, templateVariableOptions]); return ( - - - + onChange({ ...query, serviceId, serviceName, sloId: '' }) + } + /> + ); }; diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx index f2396901211..7829cd48c3e 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Experimental/VisualMetricQueryEditor.tsx @@ -1,10 +1,12 @@ 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'; @@ -40,6 +42,8 @@ function Editor({ templateVariableOptions={variableOptionGroup.options} datasource={datasource} onChange={onMetricTypeChange} + onProjectChange={onChange} + query={query} > {(metric) => ( <> @@ -49,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/functions.test.ts b/public/app/plugins/datasource/cloud-monitoring/functions.test.ts index 3e5c2409b58..3d932ed7ef5 100644 --- a/public/app/plugins/datasource/cloud-monitoring/functions.test.ts +++ b/public/app/plugins/datasource/cloud-monitoring/functions.test.ts @@ -9,6 +9,7 @@ import { getMetricTypesByService, labelsToGroupedOptions, stringArrayToFilters, + alignmentPeriodLabel, } from './functions'; import { newMockDatasource } from './specs/testData'; import { AlignmentTypes, MetricDescriptor, MetricKind, ValueTypes } from './types'; @@ -226,4 +227,13 @@ describe('functions', () => { ]); }); }); + + describe('alignmentPeriodLabel', () => { + it('returns period label if alignment period and per series aligner is set', () => { + const datasource = newMockDatasource(); + + const label = alignmentPeriodLabel({ perSeriesAligner: 'ALIGN_DELTA', alignmentPeriod: '10' }, datasource); + expect(label).toBe('10s interval (delta)'); + }); + }); }); diff --git a/public/app/plugins/datasource/cloud-monitoring/functions.ts b/public/app/plugins/datasource/cloud-monitoring/functions.ts index 0dd7bc46ed0..fb7c1ab2ccb 100644 --- a/public/app/plugins/datasource/cloud-monitoring/functions.ts +++ b/public/app/plugins/datasource/cloud-monitoring/functions.ts @@ -1,10 +1,11 @@ import { chunk, initial, startCase, uniqBy } from 'lodash'; +import { rangeUtil } from '@grafana/data'; import { getTemplateSrv, TemplateSrv } from '@grafana/runtime'; import { AGGREGATIONS, ALIGNMENTS, SYSTEM_LABELS } from './constants'; import CloudMonitoringDatasource from './datasource'; -import { AlignmentTypes, MetricDescriptor, MetricKind, PreprocessorType, ValueTypes } from './types'; +import { AlignmentTypes, CustomMetaData, MetricDescriptor, MetricKind, PreprocessorType, ValueTypes } from './types'; const templateSrv: TemplateSrv = getTemplateSrv(); @@ -113,3 +114,15 @@ export const stringArrayToFilters = (filterArray: string[]) => value, condition, })); + +export const alignmentPeriodLabel = (customMetaData: CustomMetaData, datasource: CloudMonitoringDatasource) => { + const { perSeriesAligner, alignmentPeriod } = customMetaData; + if (!alignmentPeriod || !perSeriesAligner) { + return ''; + } + + const alignment = ALIGNMENTS.find((ap) => ap.value === datasource.templateSrv.replace(perSeriesAligner)); + const seconds = parseInt(alignmentPeriod, 10); + const hms = rangeUtil.secondsToHms(seconds); + return `${hms} interval (${alignment?.text ?? ''})`; +};