grafana/public/app/features/expressions/ExpressionQueryEditor.tsx
Sonia Aguilar b0ac49926d
Alerting: Expression card improvements (#70395)
* Show description for each expression type in the body and change widht depending on the type

* Move condition indicator to the header

* Make order of fields in expressions to be consistent for each expression type

* Add tooltip for expression type menu

* Update styles depending on the expression type

* Update styles and move add query button under queries

* Add NeedHelpInfo component

* Adress PR review comments

* Apply description updates from #70540

* Rename gelTypes to expressionTypes

* Update layout for expressions according to the real usecases

* Update footer to include series count in all expressions

---------

Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
2023-06-27 11:35:56 +02:00

106 lines
3.9 KiB
TypeScript

import React, { useCallback, useEffect, useRef } from 'react';
import { DataSourceApi, QueryEditorProps, SelectableValue } from '@grafana/data';
import { InlineField, Select } from '@grafana/ui';
import { ClassicConditions } from './components/ClassicConditions';
import { Math } from './components/Math';
import { Reduce } from './components/Reduce';
import { Resample } from './components/Resample';
import { Threshold } from './components/Threshold';
import { ExpressionQuery, ExpressionQueryType, expressionTypes } from './types';
import { getDefaults } from './utils/expressionTypes';
type Props = QueryEditorProps<DataSourceApi<ExpressionQuery>, ExpressionQuery>;
const labelWidth = 14;
type NonClassicExpressionType = Exclude<ExpressionQueryType, ExpressionQueryType.classic>;
type ExpressionTypeConfigStorage = Partial<Record<NonClassicExpressionType, string>>;
function useExpressionsCache() {
const expressionCache = useRef<ExpressionTypeConfigStorage>({});
const getCachedExpression = useCallback((queryType: ExpressionQueryType) => {
switch (queryType) {
case ExpressionQueryType.math:
case ExpressionQueryType.reduce:
case ExpressionQueryType.resample:
case ExpressionQueryType.threshold:
return expressionCache.current[queryType];
case ExpressionQueryType.classic:
return undefined;
}
}, []);
const setCachedExpression = useCallback((queryType: ExpressionQueryType, value: string | undefined) => {
switch (queryType) {
case ExpressionQueryType.math:
expressionCache.current.math = value;
break;
// We want to use the same value for Reduce, Resample and Threshold
case ExpressionQueryType.reduce:
case ExpressionQueryType.resample:
case ExpressionQueryType.resample:
expressionCache.current.reduce = value;
expressionCache.current.resample = value;
expressionCache.current.threshold = value;
break;
}
}, []);
return { getCachedExpression, setCachedExpression };
}
export function ExpressionQueryEditor(props: Props) {
const { query, queries, onRunQuery, onChange } = props;
const { getCachedExpression, setCachedExpression } = useExpressionsCache();
useEffect(() => {
setCachedExpression(query.type, query.expression);
}, [query.expression, query.type, setCachedExpression]);
const onSelectExpressionType = useCallback(
(item: SelectableValue<ExpressionQueryType>) => {
const cachedExpression = getCachedExpression(item.value!);
const defaults = getDefaults({ ...query, type: item.value! });
onChange({ ...defaults, expression: cachedExpression ?? defaults.expression });
},
[query, onChange, getCachedExpression]
);
const renderExpressionType = () => {
const refIds = queries!.filter((q) => query.refId !== q.refId).map((q) => ({ value: q.refId, label: q.refId }));
switch (query.type) {
case ExpressionQueryType.math:
return <Math onChange={onChange} query={query} labelWidth={labelWidth} onRunQuery={onRunQuery} />;
case ExpressionQueryType.reduce:
return <Reduce refIds={refIds} onChange={onChange} labelWidth={labelWidth} query={query} />;
case ExpressionQueryType.resample:
return <Resample query={query} labelWidth={labelWidth} onChange={onChange} refIds={refIds} />;
case ExpressionQueryType.classic:
return <ClassicConditions onChange={onChange} query={query} refIds={refIds} />;
case ExpressionQueryType.threshold:
return <Threshold onChange={onChange} query={query} labelWidth={labelWidth} refIds={refIds} />;
}
};
const selected = expressionTypes.find((o) => o.value === query.type);
return (
<div>
<InlineField label="Operation" labelWidth={labelWidth}>
<Select options={expressionTypes} value={selected} onChange={onSelectExpressionType} width={25} />
</InlineField>
{renderExpressionType()}
</div>
);
}