CloudMonitoring: Fix fastpass issues (#44277)

This commit is contained in:
Andres Martinez Gotor 2022-01-25 17:28:59 +01:00 committed by GitHub
parent de2c5783fa
commit af0ece12f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 186 additions and 152 deletions

View File

@ -1,7 +1,8 @@
import React from 'react';
import { useTheme2 } from '../../themes';
import { IconButton } from '../IconButton/IconButton';
import { getSelectStyles } from './getSelectStyles';
import { Icon } from '../Icon/Icon';
interface MultiValueContainerProps {
innerProps: any;
@ -25,9 +26,5 @@ export type MultiValueRemoveProps = {
export const MultiValueRemove: React.FC<MultiValueRemoveProps> = ({ children, innerProps }) => {
const theme = useTheme2();
const styles = getSelectStyles(theme);
return (
<div {...innerProps} className={styles.multiValueRemove}>
<Icon name="times" size="sm" />
</div>
);
return <IconButton {...innerProps} name="times" size="sm" className={styles.multiValueRemove} />;
};

View File

@ -1,12 +1,13 @@
import React, { FC, useMemo } from 'react';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import React, { FC, useMemo } from 'react';
import { QueryEditorField } from '.';
import { getAggregationOptionsByMetric } from '../functions';
import { MetricDescriptor, ValueTypes, MetricKind } from '../types';
import { MetricDescriptor, MetricKind, ValueTypes } from '../types';
export interface Props {
refId: string;
onChange: (metricDescriptor: string) => void;
metricDescriptor?: MetricDescriptor;
crossSeriesReducer: string;
@ -19,7 +20,12 @@ export const Aggregation: FC<Props> = (props) => {
const selected = useSelectedFromOptions(aggOptions, props);
return (
<QueryEditorField labelWidth={18} label="Group by function" data-testid="cloud-monitoring-aggregation">
<QueryEditorField
labelWidth={18}
label="Group by function"
data-testid="cloud-monitoring-aggregation"
htmlFor={`${props.refId}-group-by-function`}
>
<Select
menuShouldPortal
width={16}
@ -37,6 +43,7 @@ export const Aggregation: FC<Props> = (props) => {
},
]}
placeholder="Select Reducer"
inputId={`${props.refId}-group-by-function`}
/>
</QueryEditorField>
);

View File

@ -1,15 +1,17 @@
import React, { FunctionComponent, useState } from 'react';
import { debounce } from 'lodash';
import { Input } from '@grafana/ui';
import { debounce } from 'lodash';
import React, { FunctionComponent, useState } from 'react';
import { QueryEditorRow } from '.';
import { INPUT_WIDTH } from '../constants';
export interface Props {
refId: string;
onChange: (alias: any) => void;
value?: string;
}
export const AliasBy: FunctionComponent<Props> = ({ value = '', onChange }) => {
export const AliasBy: FunctionComponent<Props> = ({ refId, value = '', onChange }) => {
const [alias, setAlias] = useState(value ?? '');
const propagateOnChange = debounce(onChange, 1000);
@ -20,8 +22,8 @@ export const AliasBy: FunctionComponent<Props> = ({ value = '', onChange }) => {
};
return (
<QueryEditorRow label="Alias by">
<Input width={INPUT_WIDTH} value={alias} onChange={onChange} />
<QueryEditorRow label="Alias by" htmlFor={`${refId}-alias-by`}>
<Input id={`${refId}-alias-by`} width={INPUT_WIDTH} value={alias} onChange={onChange} />
</QueryEditorRow>
);
};

View File

@ -1,11 +1,13 @@
import React, { FC } from 'react';
import { SelectableValue } from '@grafana/data';
import { SELECT_WIDTH } from '../constants';
import { CustomMetaData, MetricQuery, SLOQuery } from '../types';
import React, { FC } from 'react';
import { AlignmentFunction, AlignmentPeriod, AlignmentPeriodLabel, QueryEditorField, QueryEditorRow } from '.';
import { SELECT_WIDTH } from '../constants';
import CloudMonitoringDatasource from '../datasource';
import { CustomMetaData, MetricQuery, SLOQuery } from '../types';
export interface Props {
refId: string;
onChange: (query: MetricQuery | SLOQuery) => void;
query: MetricQuery;
templateVariableOptions: Array<SelectableValue<string>>;
@ -13,16 +15,30 @@ export interface Props {
datasource: CloudMonitoringDatasource;
}
export const Alignment: FC<Props> = ({ templateVariableOptions, onChange, query, customMetaData, datasource }) => {
export const Alignment: FC<Props> = ({
refId,
templateVariableOptions,
onChange,
query,
customMetaData,
datasource,
}) => {
return (
<QueryEditorRow
label="Alignment function"
tooltip="The process of alignment consists of collecting all data points received in a fixed length of time, applying a function to combine those data points, and assigning a timestamp to the result."
fillComponent={<AlignmentPeriodLabel datasource={datasource} customMetaData={customMetaData} />}
htmlFor={`${refId}-alignment-function`}
>
<AlignmentFunction templateVariableOptions={templateVariableOptions} query={query} onChange={onChange} />
<QueryEditorField label="Alignment period">
<AlignmentFunction
inputId={`${refId}-alignment-function`}
templateVariableOptions={templateVariableOptions}
query={query}
onChange={onChange}
/>
<QueryEditorField label="Alignment period" htmlFor={`${refId}-alignment-period`}>
<AlignmentPeriod
inputId={`${refId}-alignment-period`}
selectWidth={SELECT_WIDTH}
templateVariableOptions={templateVariableOptions}
query={query}

View File

@ -1,17 +1,19 @@
import React, { FC, useMemo } from 'react';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import { MetricQuery } from '../types';
import { getAlignmentPickerData } from '../functions';
import React, { FC, useMemo } from 'react';
import { SELECT_WIDTH } from '../constants';
import { getAlignmentPickerData } from '../functions';
import { MetricQuery } from '../types';
export interface Props {
inputId: string;
onChange: (query: MetricQuery) => void;
query: MetricQuery;
templateVariableOptions: Array<SelectableValue<string>>;
}
export const AlignmentFunction: FC<Props> = ({ query, templateVariableOptions, onChange }) => {
export const AlignmentFunction: FC<Props> = ({ inputId, query, templateVariableOptions, onChange }) => {
const { valueType, metricKind, perSeriesAligner: psa, preprocessor } = query;
const { perSeriesAligner, alignOptions } = useMemo(
() => getAlignmentPickerData(valueType, metricKind, psa, preprocessor),
@ -36,6 +38,7 @@ export const AlignmentFunction: FC<Props> = ({ query, templateVariableOptions, o
},
]}
placeholder="Select Alignment"
inputId={inputId}
></Select>
);
};

View File

@ -1,10 +1,12 @@
import React, { useMemo } from 'react';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import React, { useMemo } from 'react';
import { ALIGNMENT_PERIODS } from '../constants';
import { MetricQuery, SLOQuery } from '../types';
export interface Props<TQuery> {
inputId: string;
onChange(query: TQuery): void;
query: TQuery;
templateVariableOptions: Array<SelectableValue<string>>;
@ -12,6 +14,7 @@ export interface Props<TQuery> {
}
export function AlignmentPeriod<TQuery extends MetricQuery | SLOQuery>({
inputId,
templateVariableOptions,
onChange,
query,
@ -45,6 +48,7 @@ export function AlignmentPeriod<TQuery extends MetricQuery | SLOQuery>({
},
]}
placeholder="Select Alignment"
inputId={inputId}
></Select>
);
}

View File

@ -1,15 +1,16 @@
import React from 'react';
import { LegacyForms } from '@grafana/ui';
import { TemplateSrv } from '@grafana/runtime';
import { SelectableValue, toOption } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime';
import { LegacyForms } from '@grafana/ui';
import React from 'react';
import CloudMonitoringDatasource from '../datasource';
import { AnnotationsHelp, LabelFilter, Metrics, Project, QueryEditorRow } from './';
import { AnnotationTarget, EditorMode, MetricDescriptor, MetricKind } from '../types';
import { AnnotationsHelp, LabelFilter, Metrics, Project, QueryEditorRow } from './';
const { Input } = LegacyForms;
export interface Props {
refId: string;
onQueryChange: (target: AnnotationTarget) => void;
target: AnnotationTarget;
datasource: CloudMonitoringDatasource;
@ -97,12 +98,14 @@ export class AnnotationQueryEditor extends React.Component<Props, State> {
return (
<>
<Project
refId={this.props.refId}
templateVariableOptions={variableOptions}
datasource={datasource}
projectName={projectName || datasource.getDefaultProject()}
onChange={(value) => this.onChange('projectName', value)}
/>
<Metrics
refId={this.props.refId}
projectName={projectName}
metricType={metricType}
templateSrv={datasource.templateSrv}

View File

@ -1,6 +1,7 @@
import React, { PureComponent } from 'react';
import { Select, InlineField, Alert } from '@grafana/ui';
import { DataSourcePluginOptionsEditorProps, onUpdateDatasourceJsonDataOptionSelect } from '@grafana/data';
import { Alert, InlineField, Select } from '@grafana/ui';
import React, { PureComponent } from 'react';
import { AuthType, authTypes, CloudMonitoringOptions, CloudMonitoringSecureJsonData } from '../../types';
import { JWTConfig } from './JWTConfig';
@ -19,8 +20,9 @@ export class ConfigEditor extends PureComponent<Props> {
<>
<h3 className="page-heading">Authentication</h3>
<div>
<InlineField label="Type" labelWidth={20}>
<InlineField label="Type" labelWidth={20} htmlFor="cloud-monitoring-type">
<Select
inputId="cloud-monitoring-type"
menuShouldPortal
width={40}
value={authTypes.find((x) => x.value === jsonData.authenticationType) || authTypes[0]}

View File

@ -1,7 +1,8 @@
import React, { FC } from 'react';
import { SelectableValue } from '@grafana/data';
import { HorizontalGroup, InlineLabel, PopoverContent, Select, InlineField } from '@grafana/ui';
import { css } from '@emotion/css';
import { SelectableValue } from '@grafana/data';
import { HorizontalGroup, InlineField, InlineLabel, PopoverContent, Select } from '@grafana/ui';
import React, { FC } from 'react';
import { INNER_LABEL_WIDTH, LABEL_WIDTH } from '../constants';
interface VariableQueryFieldProps {
@ -41,6 +42,7 @@ export interface Props {
noFillEnd?: boolean;
labelWidth?: number;
fillComponent?: React.ReactNode;
htmlFor?: string;
}
export const QueryEditorRow: FC<Props> = ({
@ -50,12 +52,13 @@ export const QueryEditorRow: FC<Props> = ({
fillComponent,
noFillEnd = false,
labelWidth = LABEL_WIDTH,
htmlFor,
...rest
}) => {
return (
<div className="gf-form" {...rest}>
{label && (
<InlineLabel width={labelWidth} tooltip={tooltip}>
<InlineLabel width={labelWidth} tooltip={tooltip} htmlFor={htmlFor}>
{label}
</InlineLabel>
)}

View File

@ -1,12 +1,14 @@
import React, { FunctionComponent, useMemo } from 'react';
import { SelectableValue } from '@grafana/data';
import { MultiSelect } from '@grafana/ui';
import { labelsToGroupedOptions } from '../functions';
import { SYSTEM_LABELS, INPUT_WIDTH } from '../constants';
import { MetricDescriptor, MetricQuery } from '../types';
import React, { FunctionComponent, useMemo } from 'react';
import { Aggregation, QueryEditorRow } from '.';
import { INPUT_WIDTH, SYSTEM_LABELS } from '../constants';
import { labelsToGroupedOptions } from '../functions';
import { MetricDescriptor, MetricQuery } from '../types';
export interface Props {
refId: string;
variableOptionGroup: SelectableValue<string>;
labels: string[];
metricDescriptor?: MetricDescriptor;
@ -15,6 +17,7 @@ export interface Props {
}
export const GroupBy: FunctionComponent<Props> = ({
refId,
labels: groupBys = [],
query,
onChange,
@ -30,9 +33,11 @@ export const GroupBy: FunctionComponent<Props> = ({
<QueryEditorRow
label="Group by"
tooltip="You can reduce the amount of data returned for a metric by combining different time series. To combine multiple time series, you can specify a grouping and a function. Grouping is done on the basis of labels. The grouping function is used to combine the time series in the group into a single time series."
htmlFor={`${refId}-group-by`}
>
<MultiSelect
menuShouldPortal
inputId={`${refId}-group-by`}
width={INPUT_WIDTH}
placeholder="Choose label"
options={options}
@ -47,6 +52,7 @@ export const GroupBy: FunctionComponent<Props> = ({
crossSeriesReducer={query.crossSeriesReducer}
groupBys={query.groupBys ?? []}
onChange={(crossSeriesReducer) => onChange({ ...query, crossSeriesReducer })}
refId={refId}
></Aggregation>
</QueryEditorRow>
);

View File

@ -1,13 +1,13 @@
import React, { FunctionComponent, useCallback, useMemo } from 'react';
import { flatten } from 'lodash';
import { SelectableValue, toOption } from '@grafana/data';
import { CustomControlProps } from '@grafana/ui/src/components/Select/types';
import { Button, HorizontalGroup, Select, VerticalGroup } from '@grafana/ui';
import { CustomControlProps } from '@grafana/ui/src/components/Select/types';
import { flatten } from 'lodash';
import React, { FunctionComponent, useCallback, useMemo } from 'react';
import { QueryEditorRow } from '.';
import { SELECT_WIDTH } from '../constants';
import { labelsToGroupedOptions, stringArrayToFilters } from '../functions';
import { Filter } from '../types';
import { SELECT_WIDTH } from '../constants';
import { QueryEditorRow } from '.';
export interface Props {
labels: { [key: string]: string[] };
@ -20,7 +20,7 @@ const operators = ['=', '!=', '=~', '!=~'];
const FilterButton = React.forwardRef<HTMLButtonElement, CustomControlProps<string>>(
({ value, isOpen, invalid, ...rest }, ref) => {
return <Button {...rest} ref={ref} variant="secondary" icon="plus"></Button>;
return <Button {...rest} ref={ref} variant="secondary" icon="plus" aria-label="Add filter"></Button>;
}
);
FilterButton.displayName = 'FilterButton';
@ -101,6 +101,7 @@ export const LabelFilter: FunctionComponent<Props> = ({
<HorizontalGroup key={index} spacing="xs" width="auto">
<Select
menuShouldPortal
aria-label="Filter label key"
width={SELECT_WIDTH}
allowCustomValue
formatCreateLabel={(v) => `Use label key: ${v}`}
@ -126,6 +127,7 @@ export const LabelFilter: FunctionComponent<Props> = ({
/>
<Select
menuShouldPortal
aria-label="Filter label value"
width={SELECT_WIDTH}
formatCreateLabel={(v) => `Use label value: ${v}`}
allowCustomValue

View File

@ -1,19 +1,20 @@
import React, { useState, useEffect, useCallback } from 'react';
import { SelectableValue } from '@grafana/data';
import { Project, VisualMetricQueryEditor, AliasBy } from '.';
import React, { useCallback, useEffect, useState } from 'react';
import { AliasBy, Project, VisualMetricQueryEditor } from '.';
import CloudMonitoringDatasource from '../datasource';
import { getAlignmentPickerData } from '../functions';
import {
MetricQuery,
MetricDescriptor,
EditorMode,
MetricKind,
PreprocessorType,
AlignmentTypes,
CustomMetaData,
ValueTypes,
EditorMode,
MetricDescriptor,
MetricKind,
MetricQuery,
PreprocessorType,
SLOQuery,
ValueTypes,
} from '../types';
import { getAlignmentPickerData } from '../functions';
import CloudMonitoringDatasource from '../datasource';
import { MQLQueryEditor } from './MQLQueryEditor';
export interface Props {
@ -101,6 +102,7 @@ function Editor({
return (
<>
<Project
refId={refId}
templateVariableOptions={variableOptionGroup.options}
projectName={projectName}
datasource={datasource}
@ -111,6 +113,7 @@ function Editor({
{editorMode === EditorMode.Visual && (
<VisualMetricQueryEditor
refId={refId}
labels={state.labels}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}
@ -130,6 +133,7 @@ function Editor({
)}
<AliasBy
refId={refId}
value={query.aliasBy}
onChange={(aliasBy) => {
onChange({ ...query, aliasBy });

View File

@ -1,16 +1,17 @@
import React, { useCallback, useEffect, useState } from 'react';
import { startCase, uniqBy } from 'lodash';
import { Select, useTheme2, getSelectStyles, useStyles2 } from '@grafana/ui';
import { TemplateSrv } from '@grafana/runtime';
import { SelectableValue, GrafanaTheme2 } from '@grafana/data';
import { QueryEditorRow, QueryEditorField } from '.';
import CloudMonitoringDatasource from '../datasource';
import { INNER_LABEL_WIDTH, LABEL_WIDTH, SELECT_WIDTH } from '../constants';
import { MetricDescriptor } from '../types';
import { css } from '@emotion/css';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime';
import { getSelectStyles, Select, useStyles2, useTheme2 } from '@grafana/ui';
import { startCase, uniqBy } from 'lodash';
import React, { useCallback, useEffect, useState } from 'react';
import { QueryEditorField, QueryEditorRow } from '.';
import { INNER_LABEL_WIDTH, LABEL_WIDTH, SELECT_WIDTH } from '../constants';
import CloudMonitoringDatasource from '../datasource';
import { MetricDescriptor } from '../types';
export interface Props {
refId: string;
onChange: (metricDescriptor: MetricDescriptor) => void;
templateSrv: TemplateSrv;
templateVariableOptions: Array<SelectableValue<string>>;
@ -135,7 +136,7 @@ export function Metrics(props: Props) {
return (
<>
<QueryEditorRow>
<QueryEditorField labelWidth={LABEL_WIDTH} label="Service">
<QueryEditorField labelWidth={LABEL_WIDTH} label="Service" htmlFor={`${props.refId}-service`}>
<Select
menuShouldPortal
width={SELECT_WIDTH}
@ -149,9 +150,10 @@ export function Metrics(props: Props) {
...services,
]}
placeholder="Select Services"
inputId={`${props.refId}-service`}
></Select>
</QueryEditorField>
<QueryEditorField label="Metric name" labelWidth={INNER_LABEL_WIDTH}>
<QueryEditorField label="Metric name" labelWidth={INNER_LABEL_WIDTH} htmlFor={`${props.refId}-select-metric`}>
<Select
menuShouldPortal
width={SELECT_WIDTH}
@ -165,6 +167,7 @@ export function Metrics(props: Props) {
...metrics,
]}
placeholder="Select Metric"
inputId={`${props.refId}-select-metric`}
></Select>
</QueryEditorField>
</QueryEditorRow>

View File

@ -1,18 +1,20 @@
import React, { useEffect, useMemo, useState } from 'react';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import CloudMonitoringDatasource from '../datasource';
import { SELECT_WIDTH } from '../constants';
import React, { useEffect, useMemo, useState } from 'react';
import { QueryEditorRow } from '.';
import { SELECT_WIDTH } from '../constants';
import CloudMonitoringDatasource from '../datasource';
export interface Props {
refId: string;
datasource: CloudMonitoringDatasource;
onChange: (projectName: string) => void;
templateVariableOptions: Array<SelectableValue<string>>;
projectName: string;
}
export function Project({ projectName, datasource, onChange, templateVariableOptions }: Props) {
export function Project({ refId, projectName, datasource, onChange, templateVariableOptions }: Props) {
const [projects, setProjects] = useState<Array<SelectableValue<string>>>([]);
useEffect(() => {
datasource.getProjects().then((projects) => setProjects(projects));
@ -31,7 +33,7 @@ export function Project({ projectName, datasource, onChange, templateVariableOpt
);
return (
<QueryEditorRow label="Project">
<QueryEditorRow label="Project" htmlFor={`${refId}-project`}>
<Select
menuShouldPortal
width={SELECT_WIDTH}
@ -41,6 +43,7 @@ export function Project({ projectName, datasource, onChange, templateVariableOpt
options={projectsWithTemplateVariables}
value={{ value: projectName, label: projectName }}
placeholder="Select Project"
inputId={`${refId}-project`}
/>
</QueryEditorRow>
);

View File

@ -1,13 +1,14 @@
import React, { PureComponent } from 'react';
import { css } from '@emotion/css';
import { QueryEditorProps, toOption } from '@grafana/data';
import { Button, Select } from '@grafana/ui';
import { MetricQueryEditor, SLOQueryEditor, QueryEditorRow } from './';
import { CloudMonitoringQuery, MetricQuery, QueryType, SLOQuery, EditorMode } from '../types';
import { SELECT_WIDTH, QUERY_TYPES } from '../constants';
import React, { PureComponent } from 'react';
import { QUERY_TYPES, SELECT_WIDTH } from '../constants';
import CloudMonitoringDatasource from '../datasource';
import { CloudMonitoringQuery, EditorMode, MetricQuery, QueryType, SLOQuery } from '../types';
import { MetricQueryEditor, QueryEditorRow, SLOQueryEditor } from './';
import { defaultQuery } from './MetricQueryEditor';
import { defaultQuery as defaultSLOQuery } from './SLO/SLOQueryEditor';
import CloudMonitoringDatasource from '../datasource';
export type Props = QueryEditorProps<CloudMonitoringDatasource, CloudMonitoringQuery>;
@ -73,6 +74,7 @@ export class QueryEditor extends PureComponent<Props> {
</Button>
)
}
htmlFor={`${query.refId}-query-type`}
>
<Select
menuShouldPortal
@ -83,6 +85,7 @@ export class QueryEditor extends PureComponent<Props> {
onChange({ ...query, sloQuery, queryType: value! });
onRunQuery();
}}
inputId={`${query.refId}-query-type`}
/>
</QueryEditorRow>
@ -102,6 +105,7 @@ export class QueryEditor extends PureComponent<Props> {
{queryType === QueryType.SLO && (
<SLOQueryEditor
refId={query.refId}
variableOptionGroup={variableOptionGroup}
customMetaData={customMetaData}
onChange={(query: SLOQuery) => this.onQueryChange('sloQuery', query)}

View File

@ -1,47 +0,0 @@
import React, { FunctionComponent } from 'react';
import { SelectableValue } from '@grafana/data';
import { Segment } from '@grafana/ui';
import { QueryType } from '../types';
import { QUERY_TYPES } from '../constants';
export interface Props {
value: QueryType;
onChange: (slo: QueryType) => void;
templateVariableOptions: Array<SelectableValue<string>>;
}
function asQueryType(input: Array<SelectableValue<string>>) {
const res: Array<SelectableValue<QueryType>> = [];
input.forEach((v) => {
if (v.value === QueryType.METRICS) {
res.push({ ...v, value: QueryType.METRICS });
}
if (v.value === QueryType.SLO) {
res.push({ ...v, value: QueryType.SLO });
}
});
return res;
}
export const QueryTypeSelector: FunctionComponent<Props> = ({ onChange, value, templateVariableOptions }) => {
return (
<div className="gf-form-inline">
<label className="gf-form-label query-keyword width-9">Query Type</label>
<Segment
value={[...QUERY_TYPES, ...asQueryType(templateVariableOptions)].find((qt) => qt.value === value)}
options={[
...QUERY_TYPES,
{
label: 'Template Variables',
options: templateVariableOptions,
},
]}
onChange={({ value }: SelectableValue<QueryType>) => onChange(value!)}
/>
<div className="gf-form gf-form--grow">
<label className="gf-form-label gf-form-label--grow"></label>
</div>
</div>
);
};

View File

@ -1,19 +1,21 @@
import React, { useEffect, useState } from 'react';
import { Select } from '@grafana/ui';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import React, { useEffect, useState } from 'react';
import { QueryEditorRow } from '..';
import { SELECT_WIDTH } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { SLOQuery } from '../../types';
import { SELECT_WIDTH } from '../../constants';
export interface Props {
refId: string;
onChange: (query: SLOQuery) => void;
query: SLOQuery;
templateVariableOptions: Array<SelectableValue<string>>;
datasource: CloudMonitoringDatasource;
}
export const SLO: React.FC<Props> = ({ query, templateVariableOptions, onChange, datasource }) => {
export const SLO: React.FC<Props> = ({ refId, query, templateVariableOptions, onChange, datasource }) => {
const [slos, setSLOs] = useState<Array<SelectableValue<string>>>([]);
const { projectName, serviceId } = query;
@ -34,9 +36,10 @@ export const SLO: React.FC<Props> = ({ query, templateVariableOptions, onChange,
}, [datasource, projectName, serviceId, templateVariableOptions]);
return (
<QueryEditorRow label="SLO">
<QueryEditorRow label="SLO" htmlFor={`${refId}-slo`}>
<Select
menuShouldPortal
inputId={`${refId}-slo`}
width={SELECT_WIDTH}
allowCustomValue
value={query?.sloId && { value: query?.sloId, label: query?.sloName || query?.sloId }}

View File

@ -1,12 +1,14 @@
import React from 'react';
import { SelectableValue } from '@grafana/data';
import { Project, AliasBy, AlignmentPeriod, AlignmentPeriodLabel, QueryEditorRow } from '..';
import { AlignmentTypes, CustomMetaData, SLOQuery } from '../../types';
import CloudMonitoringDatasource from '../../datasource';
import React from 'react';
import { Selector, Service, SLO } from '.';
import { AliasBy, AlignmentPeriod, AlignmentPeriodLabel, Project, QueryEditorRow } from '..';
import { SELECT_WIDTH } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { AlignmentTypes, CustomMetaData, SLOQuery } from '../../types';
export interface Props {
refId: string;
customMetaData: CustomMetaData;
variableOptionGroup: SelectableValue<string>;
onChange: (query: SLOQuery) => void;
@ -28,6 +30,7 @@ export const defaultQuery: (dataSource: CloudMonitoringDatasource) => SLOQuery =
});
export function SLOQueryEditor({
refId,
query,
datasource,
onChange,
@ -37,32 +40,37 @@ export function SLOQueryEditor({
return (
<>
<Project
refId={refId}
templateVariableOptions={variableOptionGroup.options}
projectName={query.projectName}
datasource={datasource}
onChange={(projectName) => onChange({ ...query, projectName })}
/>
<Service
refId={refId}
datasource={datasource}
templateVariableOptions={variableOptionGroup.options}
query={query}
onChange={onChange}
></Service>
<SLO
refId={refId}
datasource={datasource}
templateVariableOptions={variableOptionGroup.options}
query={query}
onChange={onChange}
></SLO>
<Selector
refId={refId}
datasource={datasource}
templateVariableOptions={variableOptionGroup.options}
query={query}
onChange={onChange}
></Selector>
<QueryEditorRow label="Alignment period">
<QueryEditorRow label="Alignment period" htmlFor={`${refId}-alignment-period`}>
<AlignmentPeriod
inputId={`${refId}-alignment-period`}
templateVariableOptions={variableOptionGroup.options}
query={{
...query,
@ -74,7 +82,7 @@ export function SLOQueryEditor({
<AlignmentPeriodLabel datasource={datasource} customMetaData={customMetaData} />
</QueryEditorRow>
<AliasBy value={query.aliasBy} onChange={(aliasBy) => onChange({ ...query, aliasBy })} />
<AliasBy refId={refId} value={query.aliasBy} onChange={(aliasBy) => onChange({ ...query, aliasBy })} />
</>
);
}

View File

@ -1,23 +1,26 @@
import React from 'react';
import { Select } from '@grafana/ui';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import React from 'react';
import { QueryEditorRow } from '..';
import { SELECT_WIDTH, SELECTORS } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { SLOQuery } from '../../types';
import { SELECT_WIDTH, SELECTORS } from '../../constants';
export interface Props {
refId: string;
onChange: (query: SLOQuery) => void;
query: SLOQuery;
templateVariableOptions: Array<SelectableValue<string>>;
datasource: CloudMonitoringDatasource;
}
export const Selector: React.FC<Props> = ({ query, templateVariableOptions, onChange, datasource }) => {
export const Selector: React.FC<Props> = ({ refId, query, templateVariableOptions, onChange, datasource }) => {
return (
<QueryEditorRow label="Selector">
<QueryEditorRow label="Selector" htmlFor={`${refId}-slo-selector`}>
<Select
menuShouldPortal
inputId={`${refId}-slo-selector`}
width={SELECT_WIDTH}
allowCustomValue
value={[...SELECTORS, ...templateVariableOptions].find((s) => s.value === query?.selectorName ?? '')}

View File

@ -1,19 +1,21 @@
import React, { useEffect, useState } from 'react';
import { Select } from '@grafana/ui';
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
import React, { useEffect, useState } from 'react';
import { QueryEditorRow } from '..';
import { SELECT_WIDTH } from '../../constants';
import CloudMonitoringDatasource from '../../datasource';
import { SLOQuery } from '../../types';
import { SELECT_WIDTH } from '../../constants';
export interface Props {
refId: string;
onChange: (query: SLOQuery) => void;
query: SLOQuery;
templateVariableOptions: Array<SelectableValue<string>>;
datasource: CloudMonitoringDatasource;
}
export const Service: React.FC<Props> = ({ query, templateVariableOptions, onChange, datasource }) => {
export const Service: React.FC<Props> = ({ refId, query, templateVariableOptions, onChange, datasource }) => {
const [services, setServices] = useState<Array<SelectableValue<string>>>([]);
const { projectName } = query;
@ -34,9 +36,10 @@ export const Service: React.FC<Props> = ({ query, templateVariableOptions, onCha
}, [datasource, projectName, templateVariableOptions]);
return (
<QueryEditorRow label="Service">
<QueryEditorRow label="Service" htmlFor={`${refId}-slo-service`}>
<Select
menuShouldPortal
inputId={`${refId}-slo-service`}
width={SELECT_WIDTH}
allowCustomValue
value={query?.serviceId && { value: query?.serviceId, label: query?.serviceName || query?.serviceId }}

View File

@ -1,10 +1,12 @@
import React from 'react';
import { SelectableValue } from '@grafana/data';
import { Metrics, LabelFilter, GroupBy, Preprocessor, Alignment } from '.';
import { MetricQuery, MetricDescriptor, CustomMetaData, SLOQuery } from '../types';
import React from 'react';
import { Alignment, GroupBy, LabelFilter, Metrics, Preprocessor } from '.';
import CloudMonitoringDatasource from '../datasource';
import { CustomMetaData, MetricDescriptor, MetricQuery, SLOQuery } from '../types';
export interface Props {
refId: string;
customMetaData: CustomMetaData;
variableOptionGroup: SelectableValue<string>;
onMetricTypeChange: (query: MetricDescriptor) => void;
@ -15,6 +17,7 @@ export interface Props {
}
function Editor({
refId,
query,
labels,
datasource,
@ -25,6 +28,7 @@ function Editor({
}: React.PropsWithChildren<Props>) {
return (
<Metrics
refId={refId}
templateSrv={datasource.templateSrv}
projectName={query.projectName}
metricType={query.metricType}
@ -42,6 +46,7 @@ function Editor({
/>
<Preprocessor metricDescriptor={metric} query={query} onChange={onChange} />
<GroupBy
refId={refId}
labels={Object.keys(labels)}
query={query}
onChange={onChange}
@ -49,6 +54,7 @@ function Editor({
metricDescriptor={metric}
/>
<Alignment
refId={refId}
datasource={datasource}
templateVariableOptions={variableOptionGroup.options}
query={query}

View File

@ -12,7 +12,6 @@ export { Aggregation } from './Aggregation';
export { MetricQueryEditor } from './MetricQueryEditor';
export { SLOQueryEditor } from './SLO/SLOQueryEditor';
export { MQLQueryEditor } from './MQLQueryEditor';
export { QueryTypeSelector } from './QueryType';
export { VariableQueryField, QueryEditorRow, QueryEditorField } from './Fields';
export { VisualMetricQueryEditor } from './VisualMetricQueryEditor';
export { Preprocessor } from './Preprocessor';