import { css } from '@emotion/css'; import React, { useEffect, useState } from 'react'; import { SemVer } from 'semver'; import { getDefaultTimeRange, GrafanaTheme2, QueryEditorProps } from '@grafana/data'; import { Alert, InlineField, InlineLabel, Input, QueryField, useStyles2 } from '@grafana/ui'; import { ElasticDatasource } from '../../datasource'; import { useNextId } from '../../hooks/useNextId'; import { useDispatch } from '../../hooks/useStatelessReducer'; import { ElasticsearchOptions, ElasticsearchQuery } from '../../types'; import { isSupportedVersion, unsupportedVersionMessage } from '../../utils'; import { BucketAggregationsEditor } from './BucketAggregationsEditor'; import { ElasticsearchProvider } from './ElasticsearchQueryContext'; import { MetricAggregationsEditor } from './MetricAggregationsEditor'; import { metricAggregationConfig } from './MetricAggregationsEditor/utils'; import { changeAliasPattern, changeQuery } from './state'; export type ElasticQueryEditorProps = QueryEditorProps; // a react hook that returns the elasticsearch database version, // or `null`, while loading, or if it is not possible to determine the value. function useElasticVersion(datasource: ElasticDatasource): SemVer | null { const [version, setVersion] = useState(null); useEffect(() => { let canceled = false; datasource.getDatabaseVersion().then( (version) => { if (!canceled) { setVersion(version); } }, (error) => { // we do nothing console.log(error); } ); return () => { canceled = true; }; }, [datasource]); return version; } export const QueryEditor = ({ query, onChange, onRunQuery, datasource, range }: ElasticQueryEditorProps) => { const elasticVersion = useElasticVersion(datasource); const showUnsupportedMessage = elasticVersion != null && !isSupportedVersion(elasticVersion); return ( {showUnsupportedMessage && } ); }; const getStyles = (theme: GrafanaTheme2) => ({ root: css` display: flex; `, queryFieldWrapper: css` flex-grow: 1; margin: 0 ${theme.spacing(0.5)} ${theme.spacing(0.5)} 0; `, }); interface Props { value: ElasticsearchQuery; } export const ElasticSearchQueryField = ({ value, onChange }: { value?: string; onChange: (v: string) => void }) => { const styles = useStyles2(getStyles); return (
{}} onChange={onChange} placeholder="Lucene Query" portalOrigin="elasticsearch" />
); }; const QueryEditorForm = ({ value }: Props) => { const dispatch = useDispatch(); const nextId = useNextId(); const styles = useStyles2(getStyles); // To be considered a time series query, the last bucked aggregation must be a Date Histogram const isTimeSeriesQuery = value?.bucketAggs?.slice(-1)[0]?.type === 'date_histogram'; const showBucketAggregationsEditor = value.metrics?.every( (metric) => !metricAggregationConfig[metric.type].isSingleMetric ); return ( <>
Query dispatch(changeQuery(query))} value={value?.query} /> dispatch(changeAliasPattern(e.currentTarget.value))} defaultValue={value.alias} />
{showBucketAggregationsEditor && } ); };