|
|
|
@ -1,4 +1,4 @@ |
|
|
|
|
import React, { PureComponent } from 'react'; |
|
|
|
|
import React, { useCallback, useEffect, useRef } from 'react'; |
|
|
|
|
|
|
|
|
|
import { DataSourceApi, QueryEditorProps, SelectableValue } from '@grafana/data'; |
|
|
|
|
import { InlineField, Select } from '@grafana/ui'; |
|
|
|
@ -13,15 +13,61 @@ import { getDefaults } from './utils/expressionTypes'; |
|
|
|
|
type Props = QueryEditorProps<DataSourceApi<ExpressionQuery>, ExpressionQuery>; |
|
|
|
|
|
|
|
|
|
const labelWidth = 14; |
|
|
|
|
export class ExpressionQueryEditor extends PureComponent<Props> { |
|
|
|
|
onSelectExpressionType = (item: SelectableValue<ExpressionQueryType>) => { |
|
|
|
|
const { query, onChange } = this.props; |
|
|
|
|
|
|
|
|
|
onChange(getDefaults({ ...query, type: item.value! })); |
|
|
|
|
}; |
|
|
|
|
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: |
|
|
|
|
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; |
|
|
|
|
|
|
|
|
|
renderExpressionType() { |
|
|
|
|
const { onChange, onRunQuery, query, queries } = this.props; |
|
|
|
|
// We want to use the same value for Reduce and Resample
|
|
|
|
|
case ExpressionQueryType.reduce: |
|
|
|
|
case ExpressionQueryType.resample: |
|
|
|
|
expressionCache.current.reduce = value; |
|
|
|
|
expressionCache.current.resample = 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) { |
|
|
|
@ -37,19 +83,16 @@ export class ExpressionQueryEditor extends PureComponent<Props> { |
|
|
|
|
case ExpressionQueryType.classic: |
|
|
|
|
return <ClassicConditions onChange={onChange} query={query} refIds={refIds} />; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
render() { |
|
|
|
|
const { query } = this.props; |
|
|
|
|
const selected = gelTypes.find((o) => o.value === query.type); |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<div> |
|
|
|
|
<InlineField label="Operation" labelWidth={labelWidth}> |
|
|
|
|
<Select options={gelTypes} value={selected} onChange={this.onSelectExpressionType} width={25} /> |
|
|
|
|
</InlineField> |
|
|
|
|
{this.renderExpressionType()} |
|
|
|
|
</div> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const selected = gelTypes.find((o) => o.value === query.type); |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<div> |
|
|
|
|
<InlineField label="Operation" labelWidth={labelWidth}> |
|
|
|
|
<Select options={gelTypes} value={selected} onChange={onSelectExpressionType} width={25} /> |
|
|
|
|
</InlineField> |
|
|
|
|
{renderExpressionType()} |
|
|
|
|
</div> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|