123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- 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<SelectableValue<string>>;
- disableExpressions: boolean;
- }
- export interface DimensionFilterCondition {
- key?: string;
- operator?: string;
- value?: string;
- }
- const dimensionsToFilterConditions = (dimensions: DimensionsType | undefined) =>
- Object.entries(dimensions ?? {}).reduce<DimensionFilterCondition[]>((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<DimensionsType>((acc, { key, value }) => {
- if (key && value) {
- return { ...acc, [key]: value };
- }
- return acc;
- }, {});
- };
- export const Dimensions: React.FC<Props> = ({
- metricStat,
- datasource,
- dimensionKeys,
- disableExpressions,
- onChange,
- }) => {
- const dimensionFilters = useMemo(() => dimensionsToFilterConditions(metricStat.dimensions), [metricStat.dimensions]);
- const [items, setItems] = useState<DimensionFilterCondition[]>(dimensionFilters);
- const onDimensionsChange = (newItems: Array<Partial<DimensionFilterCondition>>) => {
- 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 (
- <EditorList
- items={items}
- onChange={onDimensionsChange}
- renderItem={makeRenderFilter(datasource, metricStat, dimensionKeys, disableExpressions)}
- />
- );
- };
- function makeRenderFilter(
- datasource: CloudWatchDatasource,
- metricStat: MetricStat,
- dimensionKeys: Array<SelectableValue<string>>,
- disableExpressions: boolean
- ) {
- function renderFilter(
- item: DimensionFilterCondition,
- onChange: (item: DimensionFilterCondition) => void,
- onDelete: () => void
- ) {
- return (
- <FilterItem
- filter={item}
- onChange={(item) => onChange(item)}
- datasource={datasource}
- metricStat={metricStat}
- disableExpressions={disableExpressions}
- dimensionKeys={dimensionKeys}
- onDelete={onDelete}
- />
- );
- }
- return renderFilter;
- }
|