import React, { useEffect, useState } from 'react'; import { SelectableValue } from '@grafana/data'; import { Segment, SegmentAsync } from '@grafana/ui'; import { CloudWatchMetricsQuery, SelectableStrings } from '../types'; import { CloudWatchDatasource } from '../datasource'; import { Dimensions, QueryInlineField, Stats } from '.'; export type Props = { query: CloudWatchMetricsQuery; datasource: CloudWatchDatasource; onRunQuery?: () => void; onChange: (value: CloudWatchMetricsQuery) => void; }; interface State { regions: SelectableStrings; namespaces: SelectableStrings; metricNames: SelectableStrings; variableOptionGroup: SelectableValue; showMeta: boolean; } export function MetricsQueryFieldsEditor({ query, datasource, onChange, onRunQuery = () => {}, }: React.PropsWithChildren) { const metricsQuery = query as CloudWatchMetricsQuery; const [state, setState] = useState({ regions: [], namespaces: [], metricNames: [], variableOptionGroup: {}, showMeta: false, }); useEffect(() => { const variableOptionGroup = { label: 'Template Variables', options: datasource.getVariables().map(toOption), }; Promise.all([datasource.metricFindQuery('regions()'), datasource.metricFindQuery('namespaces()')]).then( ([regions, namespaces]) => { setState({ ...state, regions: [...regions, variableOptionGroup], namespaces: [...namespaces, variableOptionGroup], variableOptionGroup, }); } ); }, []); const loadMetricNames = async () => { const { namespace, region } = query; return datasource.metricFindQuery(`metrics(${namespace},${region})`).then(appendTemplateVariables); }; const appendTemplateVariables = (values: SelectableValue[]) => [ ...values, { label: 'Template Variables', options: datasource.getVariables().map(toOption) }, ]; const toOption = (value: any) => ({ label: value, value }); const onQueryChange = (query: CloudWatchMetricsQuery) => { onChange(query); onRunQuery(); }; // Load dimension values based on current selected dimensions. // Remove the new dimension key and all dimensions that has a wildcard as selected value const loadDimensionValues = (newKey: string) => { const { [newKey]: value, ...dim } = metricsQuery.dimensions; const newDimensions = Object.entries(dim).reduce( (result, [key, value]) => (value === '*' ? result : { ...result, [key]: value }), {} ); return datasource .getDimensionValues(query.region, query.namespace, metricsQuery.metricName, newKey, newDimensions) .then((values) => (values.length ? [{ value: '*', text: '*', label: '*' }, ...values] : values)) .then(appendTemplateVariables); }; const { regions, namespaces, variableOptionGroup } = state; return ( <> onQueryChange({ ...query, region: region! })} /> {query.expression?.length === 0 && ( <> onQueryChange({ ...query, namespace: namespace! })} /> onQueryChange({ ...metricsQuery, metricName })} /> onQueryChange({ ...metricsQuery, statistics })} variableOptionGroup={variableOptionGroup} /> onQueryChange({ ...metricsQuery, dimensions })} loadKeys={() => datasource.getDimensionKeys(query.namespace, query.region).then(appendTemplateVariables)} loadValues={loadDimensionValues} /> )} ); }