import { isEqual } from 'lodash'; import React, { useMemo, useState } from 'react'; import { SelectableValue } from '@grafana/data'; import { EditorList } from '@grafana/experimental'; import { CloudWatchDatasource } from '../../datasource'; import { Dimensions as DimensionsType, MetricStat } from '../../types'; import { FilterItem } from './FilterItem'; export interface Props { metricStat: MetricStat; onChange: (dimensions: DimensionsType) => void; datasource: CloudWatchDatasource; dimensionKeys: Array>; disableExpressions: boolean; } export interface DimensionFilterCondition { key?: string; operator?: string; value?: string; } const dimensionsToFilterConditions = (dimensions: DimensionsType | undefined) => Object.entries(dimensions ?? {}).reduce((acc, [key, value]) => { if (value && typeof value === 'string') { const filter = { key, value, operator: '=', }; return [...acc, filter]; } return acc; }, []); const filterConditionsToDimensions = (filters: DimensionFilterCondition[]) => { return filters.reduce((acc, { key, value }) => { if (key && value) { return { ...acc, [key]: value }; } return acc; }, {}); }; export const Dimensions: React.FC = ({ metricStat, datasource, dimensionKeys, disableExpressions, onChange, }) => { const dimensionFilters = useMemo(() => dimensionsToFilterConditions(metricStat.dimensions), [metricStat.dimensions]); const [items, setItems] = useState(dimensionFilters); const onDimensionsChange = (newItems: Array>) => { setItems(newItems); // The onChange event should only be triggered in the case there is a complete dimension object. // So when a new key is added that does not yet have a value, it should not trigger an onChange event. const newDimensions = filterConditionsToDimensions(newItems); if (!isEqual(newDimensions, metricStat.dimensions)) { onChange(newDimensions); } }; return ( ); }; function makeRenderFilter( datasource: CloudWatchDatasource, metricStat: MetricStat, dimensionKeys: Array>, disableExpressions: boolean ) { function renderFilter( item: DimensionFilterCondition, onChange: (item: DimensionFilterCondition) => void, onDelete: () => void ) { return ( onChange(item)} datasource={datasource} metricStat={metricStat} disableExpressions={disableExpressions} dimensionKeys={dimensionKeys} onDelete={onDelete} /> ); } return renderFilter; }