diff --git a/packages/grafana-runtime/src/index.ts b/packages/grafana-runtime/src/index.ts index 386dc95a9ae..5f1438c7fea 100644 --- a/packages/grafana-runtime/src/index.ts +++ b/packages/grafana-runtime/src/index.ts @@ -9,4 +9,4 @@ export * from './types'; export { loadPluginCss, SystemJS, PluginCssOptions } from './utils/plugin'; export { reportMetaAnalytics } from './utils/analytics'; export { DataSourceWithBackend, HealthCheckResult, HealthStatus } from './utils/DataSourceWithBackend'; -export { toDataQueryError, toDataQueryResponse } from './utils/queryResponse'; +export { toDataQueryError, toDataQueryResponse, frameToMetricFindValue } from './utils/queryResponse'; diff --git a/packages/grafana-runtime/src/utils/queryResponse.ts b/packages/grafana-runtime/src/utils/queryResponse.ts index 71ee1f6f455..c010fa534bb 100644 --- a/packages/grafana-runtime/src/utils/queryResponse.ts +++ b/packages/grafana-runtime/src/utils/queryResponse.ts @@ -8,6 +8,9 @@ import { TimeSeries, TableData, toDataFrame, + DataFrame, + MetricFindValue, + FieldType, } from '@grafana/data'; interface DataResponse { @@ -115,3 +118,22 @@ export function toDataQueryError(err: any): DataQueryError { return error; } + +/** Return the first string or non-time field as the value */ +export function frameToMetricFindValue(frame: DataFrame): MetricFindValue[] { + if (!frame || !frame.length) { + return []; + } + + const values: MetricFindValue[] = []; + let field = frame.fields.find(f => f.type === FieldType.string); + if (!field) { + field = frame.fields.find(f => f.type !== FieldType.time); + } + if (field) { + for (let i = 0; i < field.values.length; i++) { + values.push({ text: '' + field.values.get(i) }); + } + } + return values; +} diff --git a/pkg/tsdb/influxdb/flux/query_models.go b/pkg/tsdb/influxdb/flux/query_models.go index 2e588bae6bc..093d264a2f2 100644 --- a/pkg/tsdb/influxdb/flux/query_models.go +++ b/pkg/tsdb/influxdb/flux/query_models.go @@ -66,14 +66,15 @@ func getQueryModelTSDB(query *tsdb.Query, timeRange *tsdb.TimeRange, dsInfo *mod if model.Options.Organization == "" { model.Options.Organization = dsInfo.JsonData.Get("organization").MustString("") } + startTime, err := timeRange.ParseFrom() - if err != nil { - return nil, err + if err != nil && timeRange.From != "" { + return nil, fmt.Errorf("error reading startTime: %w", err) } endTime, err := timeRange.ParseTo() - if err != nil { - return nil, err + if err != nil && timeRange.To != "" { + return nil, fmt.Errorf("error reading endTime: %w", err) } // Copy directly from the well typed query diff --git a/public/app/plugins/datasource/influxdb/components/FluxQueryEditor.tsx b/public/app/plugins/datasource/influxdb/components/FluxQueryEditor.tsx index 17d743bbdaf..e3e6486aeff 100644 --- a/public/app/plugins/datasource/influxdb/components/FluxQueryEditor.tsx +++ b/public/app/plugins/datasource/influxdb/components/FluxQueryEditor.tsx @@ -60,7 +60,7 @@ v1.measurements(bucket: v.bucket)`, label: 'Schema Exploration: (fields)', description: 'Return every possible key in a single table', value: `from(bucket: v.bucket) - |> range(start: v.timeRangeStart, stop:timeRangeStop) + |> range(start: v.timeRangeStart, stop:v.timeRangeStop) |> keys() |> keep(columns: ["_value"]) |> group() diff --git a/public/app/plugins/datasource/influxdb/components/VariableQueryEditor.tsx b/public/app/plugins/datasource/influxdb/components/VariableQueryEditor.tsx new file mode 100644 index 00000000000..6d4ec551531 --- /dev/null +++ b/public/app/plugins/datasource/influxdb/components/VariableQueryEditor.tsx @@ -0,0 +1,47 @@ +import React, { PureComponent } from 'react'; +import InfluxDatasource from '../datasource'; +import { InlineFormLabel, TextArea } from '@grafana/ui'; +import { FluxQueryEditor } from './FluxQueryEditor'; + +interface Props { + query: string; // before flux, it was always a string + onChange: (query?: string) => void; + datasource: InfluxDatasource; +} + +export default class VariableQueryEditor extends PureComponent { + onRefresh = () => { + // noop + }; + + render() { + let { query, datasource, onChange } = this.props; + if (datasource.isFlux) { + return ( + onChange(v.query)} + /> + ); + } + + return ( +
+ Query +
+