From 02083d71c814bb11c5a7833a50b4b88241e29775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 23 Jan 2019 17:44:22 +0100 Subject: [PATCH 01/51] Loki query editor is starting to work, had to make changes to explore query field in order to update query from the outside without unmount between --- packages/grafana-ui/src/types/datasource.ts | 2 +- packages/grafana-ui/src/types/plugin.ts | 4 +- .../dashboard/panel_editor/QueryEditorRow.tsx | 7 ++- public/app/features/explore/QueryField.tsx | 17 +++++-- public/app/features/explore/QueryRow.tsx | 4 ++ .../loki/components/LokiQueryEditor.tsx | 47 +++++++++++++++++++ .../loki/components/LokiQueryField.tsx | 5 +- .../app/plugins/datasource/loki/datasource.ts | 4 +- public/app/plugins/datasource/loki/module.ts | 2 + .../app/plugins/datasource/loki/plugin.json | 4 +- .../datasource/testdata/QueryEditor.tsx | 4 +- public/sass/pages/_explore.scss | 24 +++++----- 12 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx diff --git a/packages/grafana-ui/src/types/datasource.ts b/packages/grafana-ui/src/types/datasource.ts index ffcbbb5fe64..4f5225cf00e 100644 --- a/packages/grafana-ui/src/types/datasource.ts +++ b/packages/grafana-ui/src/types/datasource.ts @@ -3,7 +3,7 @@ import { TimeSeries } from './series'; import { PluginMeta } from './plugin'; export interface DataQueryResponse { - data: TimeSeries[]; + data: TimeSeries[] | 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/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index 540b6a8353e..2f3f5590c25 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -107,10 +107,9 @@ export class QueryEditorRow extends PureComponent { onQueryChange = (query: DataQuery) => { Object.assign(this.props.query, query); - this.onExecuteQuery(); }; - onExecuteQuery = () => { + onRunQuery = () => { this.props.panel.refresh(); }; @@ -128,8 +127,8 @@ export class QueryEditorRow extends PureComponent { ); } diff --git a/public/app/features/explore/QueryField.tsx b/public/app/features/explore/QueryField.tsx index 24b8b8f5b16..1a42cb095a8 100644 --- a/public/app/features/explore/QueryField.tsx +++ b/public/app/features/explore/QueryField.tsx @@ -101,11 +101,20 @@ export class QueryField extends React.PureComponent { } }; + 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..d2cd2fa988e --- /dev/null +++ b/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx @@ -0,0 +1,47 @@ +// Libraries +import React, { PureComponent } from 'react'; + +// 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: query + }); + }; + + render() { + const { query } = this.state; + const { datasource } = this.props; + + return ( +
+ +
+ ); + } +} + +export default LokiQueryEditor; diff --git a/public/app/plugins/datasource/loki/components/LokiQueryField.tsx b/public/app/plugins/datasource/loki/components/LokiQueryField.tsx index febb322acca..c50f80fa435 100644 --- a/public/app/plugins/datasource/loki/components/LokiQueryField.tsx +++ b/public/app/plugins/datasource/loki/components/LokiQueryField.tsx @@ -12,6 +12,7 @@ import QueryField, { TypeaheadInput, QueryFieldState } from 'app/features/explor import { getNextCharacter, getPreviousCousin } from 'app/features/explore/utils/dom'; import BracesPlugin from 'app/features/explore/slate-plugins/braces'; import RunnerPlugin from 'app/features/explore/slate-plugins/runner'; +import LokiDatasource from '../datasource'; // Types import { LokiQuery } from '../types'; @@ -64,7 +65,7 @@ interface CascaderOption { } interface LokiQueryFieldProps { - datasource: any; + datasource: LokiDatasource; error?: string | JSX.Element; hint?: any; history?: any[]; @@ -79,7 +80,7 @@ interface LokiQueryFieldState { syntaxLoaded: boolean; } -class LokiQueryField extends React.PureComponent { +export class LokiQueryField extends React.PureComponent { plugins: any[]; pluginsSearch: any[]; languageProvider: any; diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index 95d7a2a830e..b57586f8f2c 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -32,7 +32,7 @@ function serializeParams(data: any) { .join('&'); } -export default class LokiDatasource { +export class LokiDatasource { languageProvider: LanguageProvider; maxLines: number; @@ -173,3 +173,5 @@ export default class LokiDatasource { }); } } + +export default LokiDatasource; diff --git a/public/app/plugins/datasource/loki/module.ts b/public/app/plugins/datasource/loki/module.ts index 41847855c2f..571fa944fe5 100644 --- a/public/app/plugins/datasource/loki/module.ts +++ b/public/app/plugins/datasource/loki/module.ts @@ -2,6 +2,7 @@ import Datasource from './datasource'; import LokiStartPage from './components/LokiStartPage'; import LokiQueryField from './components/LokiQueryField'; +import LokiQueryEditor from './components/LokiQueryEditor'; export class LokiConfigCtrl { static templateUrl = 'partials/config.html'; @@ -9,6 +10,7 @@ export class LokiConfigCtrl { export { Datasource, + LokiQueryEditor as QueryEditor, LokiConfigCtrl as ConfigCtrl, LokiQueryField as ExploreQueryField, LokiStartPage as ExploreStartPage, diff --git a/public/app/plugins/datasource/loki/plugin.json b/public/app/plugins/datasource/loki/plugin.json index 64462a08415..94ea089d938 100644 --- a/public/app/plugins/datasource/loki/plugin.json +++ b/public/app/plugins/datasource/loki/plugin.json @@ -2,12 +2,14 @@ "type": "datasource", "name": "Loki", "id": "loki", - "metrics": false, + + "metrics": true, "alerting": false, "annotations": false, "logs": true, "explore": true, "tables": false, + "info": { "description": "Loki Logging Data Source for Grafana", "author": { diff --git a/public/app/plugins/datasource/testdata/QueryEditor.tsx b/public/app/plugins/datasource/testdata/QueryEditor.tsx index 20b86d571df..c483df41096 100644 --- a/public/app/plugins/datasource/testdata/QueryEditor.tsx +++ b/public/app/plugins/datasource/testdata/QueryEditor.tsx @@ -41,9 +41,9 @@ export class QueryEditor extends PureComponent { } onScenarioChange = (item: SelectOptionItem) => { - this.props.onQueryChange({ + this.props.onChange({ + ...this.props.query, scenarioId: item.value, - ...this.props.query }); } diff --git a/public/sass/pages/_explore.scss b/public/sass/pages/_explore.scss index abd13a10368..6e92ed0191f 100644 --- a/public/sass/pages/_explore.scss +++ b/public/sass/pages/_explore.scss @@ -239,22 +239,20 @@ // Prometheus-specifics, to be extracted to datasource soon -.explore { - .prom-query-field { - display: flex; - } +.prom-query-field { + display: flex; +} - .prom-query-field-wrapper { - width: 100%; - } +.prom-query-field-wrapper { + width: 100%; +} - .prom-query-field-info { - margin: 0.25em 0.5em 0.5em; - display: flex; +.prom-query-field-info { + margin: 0.25em 0.5em 0.5em; + display: flex; - details { - margin-left: 1em; - } + details { + margin-left: 1em; } } From 0de861a3a8ca9cc5e91f17a9ca235d3b1ff20120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 29 Jan 2019 09:39:23 +0100 Subject: [PATCH 02/51] Minor progress on react query editor support, solving updating query persisted state --- .../core/components/Select/MetricSelect.tsx | 3 +- .../dashboard/panel_editor/QueriesTab.tsx | 6 +++ .../dashboard/panel_editor/QueryEditorRow.tsx | 11 ++--- public/app/features/dashboard/panel_model.ts | 13 ++++++ .../loki/components/LokiQueryEditor.tsx | 41 ++++++++++++++++--- public/app/plugins/datasource/loki/types.ts | 3 ++ 6 files changed, 62 insertions(+), 15 deletions(-) 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/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 28d822e3ad5..1937bebc95c 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 720e972031a..abc33e9ca25 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,16 +106,12 @@ export class QueryEditorRow extends PureComponent { this.setState({ isCollapsed: !this.state.isCollapsed }); }; - onQueryChange = (query: DataQuery) => { - Object.assign(this.props.query, query); - }; - onRunQuery = () => { this.props.panel.refresh(); }; renderPluginEditor() { - const { query } = this.props; + const { query, onChange } = this.props; const { datasource } = this.state; if (datasource.pluginExports.QueryCtrl) { @@ -127,7 +124,7 @@ export class QueryEditorRow extends PureComponent { ); @@ -165,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/panel_model.ts b/public/app/features/dashboard/panel_model.ts index 6aded0da1d7..2a5af602662 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -268,6 +268,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/plugins/datasource/loki/components/LokiQueryEditor.tsx b/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx index d2cd2fa988e..a72bc585a65 100644 --- a/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx +++ b/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx @@ -1,6 +1,9 @@ // 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'; @@ -14,13 +17,12 @@ interface State { } export class LokiQueryEditor extends PureComponent { - state: State = { - query: this.props.query + query: this.props.query, }; onRunQuery = () => { - const { query } = this.state; + const { query } = this.state; this.props.onChange(query); this.props.onRunQuery(); @@ -28,17 +30,44 @@ export class LokiQueryEditor extends PureComponent { onFieldChange = (query: LokiQuery, override?) => { this.setState({ - query: query + 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 { query } = this.state; const { datasource } = this.props; + const formatOptions: SelectOptionItem[] = [ + { label: 'Time Series', value: 'time_series' }, + { label: 'Table', value: 'table' }, + { label: 'Logs', value: 'logs' }, + ]; + + query.resultFormat = query.resultFormat || 'time_series'; + const currentFormat = formatOptions.find(item => item.value === query.resultFormat); return (
- + +
+
Format as
+ +
+
+
Format as
+