diff --git a/packages/grafana-ui/src/types/datasource.ts b/packages/grafana-ui/src/types/datasource.ts index 44d38ff20e2..e34cf25dc01 100644 --- a/packages/grafana-ui/src/types/datasource.ts +++ b/packages/grafana-ui/src/types/datasource.ts @@ -3,7 +3,7 @@ import { PluginMeta } from './plugin'; import { TableData, TimeSeries } from './data'; export interface DataQueryResponse { - data: TimeSeries[] | [TableData]; + data: TimeSeries[] | [TableData] | any; } export interface DataQuery { diff --git a/packages/grafana-ui/src/types/plugin.ts b/packages/grafana-ui/src/types/plugin.ts index 420a54e5840..00735827825 100644 --- a/packages/grafana-ui/src/types/plugin.ts +++ b/packages/grafana-ui/src/types/plugin.ts @@ -44,8 +44,8 @@ export interface DataSourceApi { export interface QueryEditorProps { datasource: DSType; query: TQuery; - onExecuteQuery?: () => void; - onQueryChange?: (value: TQuery) => void; + onRunQuery: () => void; + onChange: (value: TQuery) => void; } export interface PluginExports { diff --git a/public/app/core/components/Select/MetricSelect.tsx b/public/app/core/components/Select/MetricSelect.tsx index c9247198052..62045662c64 100644 --- a/public/app/core/components/Select/MetricSelect.tsx +++ b/public/app/core/components/Select/MetricSelect.tsx @@ -1,8 +1,7 @@ import React from 'react'; import _ from 'lodash'; -import { Select } from '@grafana/ui'; -import { SelectOptionItem } from '@grafana/ui'; +import { Select, SelectOptionItem } from '@grafana/ui'; import { Variable } from 'app/types/templates'; export interface Props { diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index a3f78e7152a..abcd5563bd0 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -1,7 +1,6 @@ import _ from 'lodash'; -import { colors } from '@grafana/ui'; -import { TimeSeries } from 'app/core/core'; +import { colors, TimeSeries } from '@grafana/ui'; import { getThemeColor } from 'app/core/utils/colors'; /** @@ -341,6 +340,6 @@ export function makeSeriesForLogs(rows: LogRowModel[], intervalMs: number): Time return a[1] - b[1]; }); - return new TimeSeries(series); + return { datapoints: series.datapoints, target: series.alias, color: series.color }; }); } diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 140bb4b0fd7..491f255d761 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -165,6 +165,11 @@ export class QueriesTab extends PureComponent { this.setState({ isAddingMixed: false }); }; + onQueryChange = (query: DataQuery, index) => { + this.props.panel.changeQuery(query, index); + this.forceUpdate(); + }; + setScrollTop = (event: React.MouseEvent) => { const target = event.target as HTMLElement; this.setState({ scrollTop: target.scrollTop }); @@ -201,6 +206,7 @@ export class QueriesTab extends PureComponent { key={query.refId} panel={panel} query={query} + onChange={query => this.onQueryChange(query, index)} onRemoveQuery={this.onRemoveQuery} onAddQuery={this.onAddQuery} onMoveQuery={this.onMoveQuery} diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index b07b4be6f56..eda10087d41 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -18,6 +18,7 @@ interface Props { onAddQuery: (query?: DataQuery) => void; onRemoveQuery: (query: DataQuery) => void; onMoveQuery: (query: DataQuery, direction: number) => void; + onChange: (query: DataQuery) => void; dataSourceValue: string | null; inMixedMode: boolean; } @@ -105,17 +106,12 @@ export class QueryEditorRow extends PureComponent { this.setState({ isCollapsed: !this.state.isCollapsed }); }; - onQueryChange = (query: DataQuery) => { - Object.assign(this.props.query, query); - this.onExecuteQuery(); - }; - - onExecuteQuery = () => { + onRunQuery = () => { this.props.panel.refresh(); }; renderPluginEditor() { - const { query } = this.props; + const { query, onChange } = this.props; const { datasource } = this.state; if (datasource.pluginExports.QueryCtrl) { @@ -128,8 +124,8 @@ export class QueryEditorRow extends PureComponent { ); } @@ -166,7 +162,7 @@ export class QueryEditorRow extends PureComponent { onDisableQuery = () => { this.props.query.hide = !this.props.query.hide; - this.onExecuteQuery(); + this.onRunQuery(); this.forceUpdate(); }; diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 0e5e48cec01..2c0ff674e8a 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -269,6 +269,19 @@ export class PanelModel { }); } + changeQuery(query: DataQuery, index: number) { + // ensure refId is maintained + query.refId = this.targets[index].refId; + + // update query in array + this.targets = this.targets.map((item, itemIndex) => { + if (itemIndex === index) { + return query; + } + return item; + }); + } + destroy() { this.events.emit('panel-teardown'); this.events.removeAllListeners(); diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index 909c4e81b8b..06a6ae24cac 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -216,7 +216,7 @@ export class Explore extends React.PureComponent { {showingStartPage && } {!showingStartPage && ( <> - {supportsGraph && } + {supportsGraph && !supportsLogs && } {supportsTable && } {supportsLogs && ( { // React profiler becomes unusable if we pass all rows to all rows and their labels, using getter instead const getRows = () => processedRows; + const timeSeries = data.series.map(series => new TimeSeries(series)); return (
{ } }; + componentWillUnmount() { + console.log('QueryRow will unmount'); + } + onClickAddButton = () => { const { exploreId, index } = this.props; this.props.addQueryRow(exploreId, index); diff --git a/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx b/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx new file mode 100644 index 00000000000..634a642c65e --- /dev/null +++ b/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx @@ -0,0 +1,80 @@ +// Libraries +import React, { PureComponent } from 'react'; + +// Components +import { Select, SelectOptionItem } from '@grafana/ui'; + +// Types +import { QueryEditorProps } from '@grafana/ui/src/types'; +import { LokiDatasource } from '../datasource'; +import { LokiQuery } from '../types'; +import { LokiQueryField } from './LokiQueryField'; + +type Props = QueryEditorProps; + +interface State { + query: LokiQuery; +} + +export class LokiQueryEditor extends PureComponent { + state: State = { + query: this.props.query, + }; + + onRunQuery = () => { + const { query } = this.state; + + this.props.onChange(query); + this.props.onRunQuery(); + }; + + onFieldChange = (query: LokiQuery, override?) => { + this.setState({ + query: { + ...this.state.query, + expr: query.expr, + } + }); + }; + + onFormatChanged = (option: SelectOptionItem) => { + this.props.onChange({ + ...this.state.query, + resultFormat: option.value, + }); + }; + + render() { + const { query } = this.state; + const { datasource } = this.props; + const formatOptions: SelectOptionItem[] = [ + { label: 'Time Series', value: 'time_series' }, + { label: 'Table', value: 'table' }, + ]; + + query.resultFormat = query.resultFormat || 'time_series'; + const currentFormat = formatOptions.find(item => item.value === query.resultFormat); + + return ( +
+ +
+
+
Format as
+