From 0644410b99be40be56c6acac2fcacffc0cc58169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 14 Jan 2019 14:55:22 +0100 Subject: [PATCH 01/12] wip: react query editors --- public/app/features/dashboard/dashgrid/QueriesTab.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/app/features/dashboard/dashgrid/QueriesTab.tsx b/public/app/features/dashboard/dashgrid/QueriesTab.tsx index 47c4f358136..500dc5c4884 100644 --- a/public/app/features/dashboard/dashgrid/QueriesTab.tsx +++ b/public/app/features/dashboard/dashgrid/QueriesTab.tsx @@ -198,6 +198,11 @@ export class QueriesTab extends PureComponent { this.setState({ isAddingMixed: false }); }; + renderQueryRow(query: DataQuery) { + console.log('render query row', this.state.currentDS); + return
(this.element = element)} />; + } + render() { const { panel } = this.props; const { currentDS, isAddingMixed } = this.state; @@ -218,7 +223,7 @@ export class QueriesTab extends PureComponent { <>
-
(this.element = element)} /> + {panel.targets.map(query => this.renderQueryRow(query))}
From 0260c779e8f167bcd7a83af1b890ccd1b0b69b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 14 Jan 2019 15:44:58 +0100 Subject: [PATCH 02/12] wip: another wip commit --- .../dashboard/panel_editor/QueriesTab.tsx | 7 +---- .../dashboard/panel_editor/QueryEditorRow.tsx | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 public/app/features/dashboard/panel_editor/QueryEditorRow.tsx diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 500dc5c4884..47c4f358136 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -198,11 +198,6 @@ export class QueriesTab extends PureComponent { this.setState({ isAddingMixed: false }); }; - renderQueryRow(query: DataQuery) { - console.log('render query row', this.state.currentDS); - return
(this.element = element)} />; - } - render() { const { panel } = this.props; const { currentDS, isAddingMixed } = this.state; @@ -223,7 +218,7 @@ export class QueriesTab extends PureComponent { <>
- {panel.targets.map(query => this.renderQueryRow(query))} +
(this.element = element)} />
diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx new file mode 100644 index 00000000000..b90c11da7c3 --- /dev/null +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -0,0 +1,30 @@ +// Libraries +import React, { PureComponent } from 'react'; + +// Utils & Services +import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader'; + +// Types +import { PanelModel } from '../panel_model'; +import { DashboardModel } from '../dashboard_model'; + +interface Props { + panel: PanelModel; + dashboard: DashboardModel; +} + +interface State { +} + +export class VisualizationTab extends PureComponent { + element: HTMLElement; + angularQueryEditor: AngularComponent; + + constructor(props) { + super(props); + } + + render() { + + } +} From 33feb26fb5239d3d05b2653d3224632428311174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 15 Jan 2019 11:40:12 +0100 Subject: [PATCH 03/12] WIP: good progress on react query editor support --- .../dashboard/panel_editor/QueriesTab.tsx | 73 ++++-------- .../dashboard/panel_editor/QueryEditorRow.tsx | 106 ++++++++++++++++-- public/app/features/panel/metrics_tab.ts | 31 ----- .../features/panel/partials/metrics_tab.html | 24 ---- .../app/features/plugins/plugin_component.ts | 28 ++--- public/app/types/plugins.ts | 1 + public/app/types/series.ts | 6 +- 7 files changed, 135 insertions(+), 134 deletions(-) delete mode 100644 public/app/features/panel/metrics_tab.ts delete mode 100644 public/app/features/panel/partials/metrics_tab.html diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 47c4f358136..1c842e6572c 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -3,18 +3,16 @@ import React, { PureComponent } from 'react'; import _ from 'lodash'; // Components -import 'app/features/panel/metrics_tab'; import { EditorTabBody, EditorToolbarView } from './EditorTabBody'; import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker'; import { QueryInspector } from './QueryInspector'; import { QueryOptions } from './QueryOptions'; -import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab'; import { PanelOptionsGroup } from '@grafana/ui'; +import { QueryEditorRow } from './QueryEditorRow'; // Services import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { BackendSrv, getBackendSrv } from 'app/core/services/backend_srv'; -import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader'; import config from 'app/core/config'; // Types @@ -37,63 +35,22 @@ interface State { } export class QueriesTab extends PureComponent { - element: HTMLElement; - component: AngularComponent; datasources: DataSourceSelectItem[] = getDatasourceSrv().getMetricSources(); backendSrv: BackendSrv = getBackendSrv(); - constructor(props) { - super(props); - - this.state = { - isLoadingHelp: false, - currentDS: this.findCurrentDataSource(), - helpContent: null, - isPickerOpen: false, - isAddingMixed: false, - }; - } + state: State = { + isLoadingHelp: false, + currentDS: this.findCurrentDataSource(), + helpContent: null, + isPickerOpen: false, + isAddingMixed: false, + }; findCurrentDataSource(): DataSourceSelectItem { const { panel } = this.props; return this.datasources.find(datasource => datasource.value === panel.datasource) || this.datasources[0]; } - getAngularQueryComponentScope(): AngularQueryComponentScope { - const { panel, dashboard } = this.props; - - return { - panel: panel, - dashboard: dashboard, - refresh: () => panel.refresh(), - render: () => panel.render, - addQuery: this.onAddQuery, - moveQuery: this.onMoveQuery, - removeQuery: this.onRemoveQuery, - events: panel.events, - }; - } - - componentDidMount() { - if (!this.element) { - return; - } - - const loader = getAngularLoader(); - const template = ''; - const scopeProps = { - ctrl: this.getAngularQueryComponentScope(), - }; - - this.component = loader.load(this.element, scopeProps, template); - } - - componentWillUnmount() { - if (this.component) { - this.component.destroy(); - } - } - onChangeDataSource = datasource => { const { panel } = this.props; const { currentDS } = this.state; @@ -147,7 +104,6 @@ export class QueriesTab extends PureComponent { } this.props.panel.addQuery(); - this.component.digest(); this.forceUpdate(); }; @@ -190,7 +146,6 @@ export class QueriesTab extends PureComponent { onAddMixedQuery = datasource => { this.onAddQuery({ datasource: datasource.name }); - this.component.digest(); this.setState({ isAddingMixed: false }); }; @@ -218,7 +173,17 @@ export class QueriesTab extends PureComponent { <>
-
(this.element = element)} /> + {panel.targets.map((query, index) => ( + + ))}
diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index b90c11da7c3..1028815cf08 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -2,29 +2,121 @@ import React, { PureComponent } from 'react'; // Utils & Services +import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader'; +import { Emitter } from 'app/core/utils/emitter'; // Types import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; +import { DataQuery, DataSourceApi } from 'app/types/series'; interface Props { panel: PanelModel; - dashboard: DashboardModel; + query: DataQuery; + onAddQuery: (query?: DataQuery) => void; + onRemoveQuery: (query: DataQuery) => void; + onMoveQuery: (query: DataQuery, direction: number) => void; + datasourceName: string | null; } interface State { + datasource: DataSourceApi | null; } -export class VisualizationTab extends PureComponent { - element: HTMLElement; - angularQueryEditor: AngularComponent; +export class QueryEditorRow extends PureComponent { + element: HTMLElement | null = null; + angularQueryEditor: AngularComponent | null = null; - constructor(props) { - super(props); + state: State = { + datasource: null, + }; + + componentDidMount() { + this.loadDatasource(); + } + + getAngularQueryComponentScope(): AngularQueryComponentScope { + const { panel, onAddQuery, onMoveQuery, onRemoveQuery, query } = this.props; + const { datasource } = this.state; + + return { + datasource: datasource, + target: query, + panel: panel, + refresh: () => panel.refresh(), + render: () => panel.render, + addQuery: onAddQuery, + moveQuery: onMoveQuery, + removeQuery: onRemoveQuery, + events: panel.events, + }; + } + + async loadDatasource() { + const { query, panel } = this.props; + const dataSourceSrv = getDatasourceSrv(); + const datasource = await dataSourceSrv.get(query.datasource || panel.datasource); + + this.setState({ datasource }); + } + + componentDidUpdate() { + const { datasource } = this.state; + + // check if we need to load another datasource + if (datasource && datasource.name !== this.props.datasourceName) { + if (this.angularQueryEditor) { + this.angularQueryEditor.destroy(); + this.angularQueryEditor = null; + } + this.loadDatasource(); + return; + } + + if (!this.element || this.angularQueryEditor) { + return; + } + + const loader = getAngularLoader(); + const template = ''; + const scopeProps = { ctrl: this.getAngularQueryComponentScope() }; + + this.angularQueryEditor = loader.load(this.element, scopeProps, template); + } + + componentWillUnmount() { + if (this.angularQueryEditor) { + this.angularQueryEditor.destroy(); + } } render() { + const { datasource } = this.state; + if (!datasource) { + return null; + } + + if (datasource.pluginExports.QueryCtrl) { + return
(this.element = element)} />; + } else if (datasource.pluginExports.QueryEditor) { + const QueryEditor = datasource.pluginExports.QueryEditor; + return ; + } + + return
Data source plugin does not export any Query Editor component
; } } + +export interface AngularQueryComponentScope { + target: DataQuery; + panel: PanelModel; + events: Emitter; + refresh: () => void; + render: () => void; + removeQuery: (query: DataQuery) => void; + addQuery: (query?: DataQuery) => void; + moveQuery: (query: DataQuery, direction: number) => void; + datasource: DataSourceApi; +} + diff --git a/public/app/features/panel/metrics_tab.ts b/public/app/features/panel/metrics_tab.ts deleted file mode 100644 index 74418484e3a..00000000000 --- a/public/app/features/panel/metrics_tab.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Services & utils -import coreModule from 'app/core/core_module'; -import { Emitter } from 'app/core/utils/emitter'; - -// Types -import { DashboardModel } from '../dashboard/dashboard_model'; -import { PanelModel } from '../dashboard/panel_model'; -import { DataQuery } from 'app/types'; - -export interface AngularQueryComponentScope { - panel: PanelModel; - dashboard: DashboardModel; - events: Emitter; - refresh: () => void; - render: () => void; - removeQuery: (query: DataQuery) => void; - addQuery: (query?: DataQuery) => void; - moveQuery: (query: DataQuery, direction: number) => void; -} - -/** @ngInject */ -export function metricsTabDirective() { - 'use strict'; - return { - restrict: 'E', - scope: true, - templateUrl: 'public/app/features/panel/partials/metrics_tab.html', - }; -} - -coreModule.directive('metricsTab', metricsTabDirective); diff --git a/public/app/features/panel/partials/metrics_tab.html b/public/app/features/panel/partials/metrics_tab.html deleted file mode 100644 index 5e9f23ba2ef..00000000000 --- a/public/app/features/panel/partials/metrics_tab.html +++ /dev/null @@ -1,24 +0,0 @@ -
- - - - -
- - - - - - - - - - - - - - - - - - diff --git a/public/app/features/plugins/plugin_component.ts b/public/app/features/plugins/plugin_component.ts index 7092608085d..0b305e05f5b 100644 --- a/public/app/features/plugins/plugin_component.ts +++ b/public/app/features/plugins/plugin_component.ts @@ -105,23 +105,17 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ switch (attrs.type) { // QueryCtrl case 'query-ctrl': { - const datasource = scope.target.datasource || scope.ctrl.panel.datasource; - return datasourceSrv.get(datasource).then(ds => { - scope.datasource = ds; - - return importPluginModule(ds.meta.module).then(dsModule => { - return { - baseUrl: ds.meta.baseUrl, - name: 'query-ctrl-' + ds.meta.id, - bindings: { target: '=', panelCtrl: '=', datasource: '=' }, - attrs: { - target: 'target', - 'panel-ctrl': 'ctrl', - datasource: 'datasource', - }, - Component: dsModule.QueryCtrl, - }; - }); + const ds = scope.ctrl.datasource; + return $q.when({ + baseUrl: ds.meta.baseUrl, + name: 'query-ctrl-' + ds.meta.id, + bindings: { target: '=', panelCtrl: '=', datasource: '=' }, + attrs: { + target: 'ctrl.target', + 'panel-ctrl': 'ctrl', + datasource: 'ctrl.datasource', + }, + Component: ds.pluginExports.QueryCtrl, }); } // Annotations diff --git a/public/app/types/plugins.ts b/public/app/types/plugins.ts index a1403c7a71c..4dacb3f8ccb 100644 --- a/public/app/types/plugins.ts +++ b/public/app/types/plugins.ts @@ -4,6 +4,7 @@ import { PanelProps, PanelOptionsProps } from '@grafana/ui'; export interface PluginExports { Datasource?: any; QueryCtrl?: any; + QueryEditor?: any; ConfigCtrl?: any; AnnotationsQueryCtrl?: any; VariableQueryEditor?: any; diff --git a/public/app/types/series.ts b/public/app/types/series.ts index 9fe68955da5..6f1795ef544 100644 --- a/public/app/types/series.ts +++ b/public/app/types/series.ts @@ -1,4 +1,4 @@ -import { PluginMeta } from './plugins'; +import { PluginMeta, PluginExports } from './plugins'; import { TimeSeries, TimeRange, RawTimeRange } from '@grafana/ui'; export interface DataQueryResponse { @@ -25,6 +25,10 @@ export interface DataQueryOptions { } export interface DataSourceApi { + name: string; + meta: PluginMeta; + pluginExports: PluginExports; + /** * min interval range */ From 166e5edebd39ff6c8073f86f48ec7577b5a428a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 16 Jan 2019 14:00:29 +0100 Subject: [PATCH 04/12] wip: testing new query editor row design --- .../dashboard/panel_editor/QueriesTab.tsx | 63 +++++++++---------- .../dashboard/panel_editor/QueryEditorRow.tsx | 44 ++++++++++++- .../panel/partials/query_editor_row.html | 44 +------------ public/sass/components/_query_editor.scss | 56 +++++++++++++++-- 4 files changed, 123 insertions(+), 84 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index 1c842e6572c..b1d2bd7284b 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -171,40 +171,39 @@ export class QueriesTab extends PureComponent { return ( <> - -
- {panel.targets.map((query, index) => ( - - ))} - -
-
- -
-
- {!isAddingMixed && ( - - )} - {isAddingMixed && this.renderMixedPicker()} -
+
+ {panel.targets.map((query, index) => ( + + ))} +
+
+
+
+ +
+
+ {!isAddingMixed && ( + + )} + {isAddingMixed && this.renderMixedPicker()}
- +
diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index 1028815cf08..def0e85f07b 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -1,5 +1,6 @@ // Libraries import React, { PureComponent } from 'react'; +import classNames from 'classnames'; // Utils & Services import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; @@ -21,6 +22,7 @@ interface Props { interface State { datasource: DataSourceApi | null; + isCollapsed: boolean; } export class QueryEditorRow extends PureComponent { @@ -29,6 +31,7 @@ export class QueryEditorRow extends PureComponent { state: State = { datasource: null, + isCollapsed: false, }; componentDidMount() { @@ -90,15 +93,51 @@ export class QueryEditorRow extends PureComponent { } } + onToggleCollapse = () => { + this.setState({ isCollapsed: !this.state.isCollapsed }); + }; + render() { - const { datasource } = this.state; + const { query } = this.props; + const { datasource, isCollapsed } = this.state; + const bodyClasses = classNames('query-editor-box__body gf-form-query', {hide: isCollapsed}); if (!datasource) { return null; } if (datasource.pluginExports.QueryCtrl) { - return
(this.element = element)} />; + return ( +
+
+
+ {isCollapsed && } + {!isCollapsed && } + {query.refId} +
+
+ + + + + +
+
+
+
(this.element = element)} /> +
+
+ ); } else if (datasource.pluginExports.QueryEditor) { const QueryEditor = datasource.pluginExports.QueryEditor; return ; @@ -119,4 +158,3 @@ export interface AngularQueryComponentScope { moveQuery: (query: DataQuery, direction: number) => void; datasource: DataSourceApi; } - diff --git a/public/app/features/panel/partials/query_editor_row.html b/public/app/features/panel/partials/query_editor_row.html index 34a86813d1d..fc2e3602630 100644 --- a/public/app/features/panel/partials/query_editor_row.html +++ b/public/app/features/panel/partials/query_editor_row.html @@ -1,44 +1,2 @@ -
- +
-
-
- -
-
- -
- -
- - - -
-
diff --git a/public/sass/components/_query_editor.scss b/public/sass/components/_query_editor.scss index 8b876624294..fe455df1bff 100644 --- a/public/sass/components/_query_editor.scss +++ b/public/sass/components/_query_editor.scss @@ -18,12 +18,6 @@ } .gf-form-query { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-content: flex-start; - align-items: flex-start; - .gf-form, .gf-form-filler { margin-bottom: 2px; @@ -188,3 +182,53 @@ input[type='text'].tight-form-func-param { .rst-literal-block .rst-text { display: block; } + +.query-editor-box { + background: $page-bg; + margin-bottom: 2px; + + &:hover { + .query-editor-box__actions { + display: flex; + } + } +} + +.query-editor-box__header { + display: flex; + padding: 4px 0px 4px 8px; + position: relative; + height: 35px; +} + +.query-editor-box__ref-id { + font-weight: $font-weight-semi-bold; + color: $blue; + font-size: $font-size-md; + flex-grow: 1; + cursor: pointer; + display: flex; + align-items: center; + + i { + padding-right: 5px; + color: $text-muted; + position: relative; + } +} + +.query-editor-box__actions { + display: flex; + justify-content: flex-end; + display: none; +} + +.query-editor-box__action { + @include buttonBackground($btn-inverse-bg, $btn-inverse-bg-hl, $btn-inverse-text-color, $btn-inverse-text-shadow); + border: 1px solid $navbar-button-border; + margin-right: 3px; +} + + .query-editor-box__body { + padding: 10px 20px; + } From 6a66d462aa75c1cfa49366a83d273500cfa26cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 16 Jan 2019 17:53:40 +0100 Subject: [PATCH 05/12] Toggle edit mode works --- .../dashboard/panel_editor/QueryEditorRow.tsx | 118 ++++++++++++------ public/app/features/panel/query_editor_row.ts | 5 + public/sass/components/_query_editor.scss | 20 +-- 3 files changed, 96 insertions(+), 47 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index def0e85f07b..a7724eed814 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -23,6 +23,7 @@ interface Props { interface State { datasource: DataSourceApi | null; isCollapsed: boolean; + angularScope: AngularQueryComponentScope | null; } export class QueryEditorRow extends PureComponent { @@ -32,6 +33,7 @@ export class QueryEditorRow extends PureComponent { state: State = { datasource: null, isCollapsed: false, + angularScope: null, }; componentDidMount() { @@ -85,6 +87,11 @@ export class QueryEditorRow extends PureComponent { const scopeProps = { ctrl: this.getAngularQueryComponentScope() }; this.angularQueryEditor = loader.load(this.element, scopeProps, template); + + // give angular time to compile + setTimeout(() => { + this.setState({ angularScope: scopeProps.ctrl }); + }, 10); } componentWillUnmount() { @@ -97,54 +104,84 @@ export class QueryEditorRow extends PureComponent { this.setState({ isCollapsed: !this.state.isCollapsed }); }; - render() { - const { query } = this.props; - const { datasource, isCollapsed } = this.state; - const bodyClasses = classNames('query-editor-box__body gf-form-query', {hide: isCollapsed}); - - if (!datasource) { - return null; - } + renderPluginEditor() { + const { datasource } = this.state; if (datasource.pluginExports.QueryCtrl) { - return ( -
-
-
- {isCollapsed && } - {!isCollapsed && } - {query.refId} -
-
- - - - - -
-
-
-
(this.element = element)} /> -
-
- ); - } else if (datasource.pluginExports.QueryEditor) { + } + return
(this.element = element)} />; + + if (datasource.pluginExports.QueryEditor) { const QueryEditor = datasource.pluginExports.QueryEditor; return ; } return
Data source plugin does not export any Query Editor component
; } + + onToggleEditMode = () => { + const { angularScope } = this.state; + + if (angularScope && angularScope.toggleEditorMode) { + angularScope.toggleEditorMode(); + this.angularQueryEditor.digest(); + } + } + + get hasTextEditMode() { + const { angularScope } = this.state; + return angularScope && angularScope.toggleEditorMode; + } + + render() { + const { query } = this.props; + const { datasource, isCollapsed, angularScope } = this.state; + const bodyClasses = classNames('query-editor-box__body gf-form-query', { hide: isCollapsed }); + + if (!datasource) { + return null; + } + + console.log('Query render'); + if (angularScope !== null && angularScope.toggleEditorMode) { + console.log('Query editor has text edit mode'); + } + + return ( +
+
+
+ {isCollapsed && } + {!isCollapsed && } + {query.refId} +
+
+ {this.hasTextEditMode && ( + + )} + + + + + +
+
+
{this.renderPluginEditor()}
+
+ ); + } } export interface AngularQueryComponentScope { @@ -157,4 +194,5 @@ export interface AngularQueryComponentScope { addQuery: (query?: DataQuery) => void; moveQuery: (query: DataQuery, direction: number) => void; datasource: DataSourceApi; + toggleEditorMode?: () => void; } diff --git a/public/app/features/panel/query_editor_row.ts b/public/app/features/panel/query_editor_row.ts index a44c1e8be6d..82d93ca5cae 100644 --- a/public/app/features/panel/query_editor_row.ts +++ b/public/app/features/panel/query_editor_row.ts @@ -12,6 +12,7 @@ export class QueryRowCtrl { panel: any; collapsed: any; hideEditorRowActions: boolean; + hasTextEditMode: boolean; constructor() { this.panelCtrl = this.queryCtrl.panelCtrl; @@ -19,6 +20,10 @@ export class QueryRowCtrl { this.panel = this.panelCtrl.panel; this.hideEditorRowActions = this.panelCtrl.hideEditorRowActions; + if (this.hasTextEditMode) { + this.panelCtrl.toggleEditorMode = this.toggleEditorMode.bind(this); + } + if (!this.target.refId) { this.target.refId = this.panel.getNextQueryLetter(); } diff --git a/public/sass/components/_query_editor.scss b/public/sass/components/_query_editor.scss index fe455df1bff..7e8eddea414 100644 --- a/public/sass/components/_query_editor.scss +++ b/public/sass/components/_query_editor.scss @@ -184,7 +184,6 @@ input[type='text'].tight-form-func-param { } .query-editor-box { - background: $page-bg; margin-bottom: 2px; &:hover { @@ -199,13 +198,13 @@ input[type='text'].tight-form-func-param { padding: 4px 0px 4px 8px; position: relative; height: 35px; + background: $page-bg; } .query-editor-box__ref-id { font-weight: $font-weight-semi-bold; color: $blue; font-size: $font-size-md; - flex-grow: 1; cursor: pointer; display: flex; align-items: center; @@ -218,17 +217,24 @@ input[type='text'].tight-form-func-param { } .query-editor-box__actions { + flex-grow: 1; display: flex; justify-content: flex-end; - display: none; + color: $text-muted; } .query-editor-box__action { - @include buttonBackground($btn-inverse-bg, $btn-inverse-bg-hl, $btn-inverse-text-color, $btn-inverse-text-shadow); - border: 1px solid $navbar-button-border; - margin-right: 3px; + margin-left: 3px; + background: transparent; + border: none; + box-shadow: none; + + &:hover { + color: $text-color; + } } .query-editor-box__body { - padding: 10px 20px; + margin: 0 0 10px 40px; + background: $page-bg; } From bc956057c34f660765255247ecc8d361ccc35ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 17 Jan 2019 10:26:08 +0100 Subject: [PATCH 06/12] Query editor row react progress, buttons working --- .../dashboard/panel_editor/QueriesTab.tsx | 16 +++-- .../dashboard/panel_editor/QueryEditorRow.tsx | 61 +++++++++++++------ public/sass/components/_query_editor.scss | 39 ++++++++---- 3 files changed, 75 insertions(+), 41 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index b1d2bd7284b..d6c05e1d18c 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -181,18 +181,16 @@ export class QueriesTab extends PureComponent { onRemoveQuery={this.onRemoveQuery} onAddQuery={this.onAddQuery} onMoveQuery={this.onMoveQuery} + inMixedMode={currentDS.meta.mixed} /> ))}
-
-
-
- +
+
+
+ + {' '} + {panel.getNextQueryLetter()}
{!isAddingMixed && ( diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index a7724eed814..1000329cf43 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -1,6 +1,7 @@ // Libraries import React, { PureComponent } from 'react'; import classNames from 'classnames'; +import _ from 'lodash'; // Utils & Services import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; @@ -18,6 +19,7 @@ interface Props { onRemoveQuery: (query: DataQuery) => void; onMoveQuery: (query: DataQuery, direction: number) => void; datasourceName: string | null; + inMixedMode: boolean; } interface State { @@ -133,47 +135,68 @@ export class QueryEditorRow extends PureComponent { return angularScope && angularScope.toggleEditorMode; } + onRemoveQuery = () => { + this.props.onRemoveQuery(this.props.query); + }; + + onCopyQuery = () => { + const copy = _.cloneDeep(this.props.query); + this.props.onAddQuery(copy); + }; + + onDisableQuery = () => { + this.props.query.hide = !this.props.query.hide; + this.forceUpdate(); + }; + render() { - const { query } = this.props; - const { datasource, isCollapsed, angularScope } = this.state; - const bodyClasses = classNames('query-editor-box__body gf-form-query', { hide: isCollapsed }); + const { query, datasourceName, inMixedMode } = this.props; + const { datasource, isCollapsed } = this.state; + const isDisabled = query.hide; + + const bodyClasses = classNames('query-editor-row__body gf-form-query', { + 'query-editor-row__body--collapsed': isCollapsed, + }); + + const rowClasses = classNames('query-editor-row', { + 'query-editor-row--disabled': isDisabled, + 'gf-form-disabled': isDisabled, + }); if (!datasource) { return null; } - console.log('Query render'); - if (angularScope !== null && angularScope.toggleEditorMode) { - console.log('Query editor has text edit mode'); - } - return ( -
-
-
+
+
+
{isCollapsed && } {!isCollapsed && } {query.refId} + {inMixedMode && ({datasourceName})} + {isDisabled && Disabled}
-
+
{this.hasTextEditMode && ( - )} - - - - -
diff --git a/public/sass/components/_query_editor.scss b/public/sass/components/_query_editor.scss index 7e8eddea414..35abd34a770 100644 --- a/public/sass/components/_query_editor.scss +++ b/public/sass/components/_query_editor.scss @@ -3,12 +3,6 @@ color: $blue; } -.gf-form-disabled { - .query-keyword { - color: darken($blue, 20%); - } -} - .query-segment-operator { color: $orange; } @@ -183,17 +177,24 @@ input[type='text'].tight-form-func-param { display: block; } -.query-editor-box { +.query-editor-row { margin-bottom: 2px; &:hover { - .query-editor-box__actions { + .query-editor-row__actions { display: flex; } } + + &--disabled { + .query-keyword { + color: darken($blue, 20%); + } + } + } -.query-editor-box__header { +.query-editor-row__header { display: flex; padding: 4px 0px 4px 8px; position: relative; @@ -201,7 +202,7 @@ input[type='text'].tight-form-func-param { background: $page-bg; } -.query-editor-box__ref-id { +.query-editor-row__ref-id { font-weight: $font-weight-semi-bold; color: $blue; font-size: $font-size-md; @@ -216,14 +217,14 @@ input[type='text'].tight-form-func-param { } } -.query-editor-box__actions { +.query-editor-row__actions { flex-grow: 1; display: flex; justify-content: flex-end; color: $text-muted; } -.query-editor-box__action { +.query-editor-row__action { margin-left: 3px; background: transparent; border: none; @@ -234,7 +235,19 @@ input[type='text'].tight-form-func-param { } } - .query-editor-box__body { + .query-editor-row__body { margin: 0 0 10px 40px; background: $page-bg; + + &--collapsed { + display: none; + } } + +.query-editor-row__context-info { + font-style: italic; + font-size: $font-size-sm; + color: $text-muted; + padding-left: 10px; +} + From 9cb49d14cd5f496cf2fa056c35ed9271ba55e6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 17 Jan 2019 11:25:44 +0100 Subject: [PATCH 07/12] Made scrollbar have scrollTop and setScrollTop props so we can control scroll position --- .../CustomScrollbar/CustomScrollbar.tsx | 33 ++++++++++++ .../dashboard/panel_editor/EditorTabBody.tsx | 6 ++- .../dashboard/panel_editor/QueriesTab.tsx | 54 +++++++++++-------- 3 files changed, 68 insertions(+), 25 deletions(-) diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx index 519e755b474..50b16dbb98e 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx @@ -1,4 +1,5 @@ import React, { PureComponent } from 'react'; +import _ from 'lodash'; import Scrollbars from 'react-custom-scrollbars'; interface Props { @@ -8,6 +9,8 @@ interface Props { autoHideDuration?: number; autoMaxHeight?: string; hideTracksWhenNotNeeded?: boolean; + scrollTop?: number; + setScrollTop: (value: React.MouseEvent) => void; } /** @@ -21,13 +24,43 @@ export class CustomScrollbar extends PureComponent { autoHideDuration: 200, autoMaxHeight: '100%', hideTracksWhenNotNeeded: false, + scrollTop: 0, + setScrollTop: () => {}, }; + private ref: React.RefObject; + + constructor(props: Props) { + super(props); + this.ref = React.createRef(); + } + + updateScroll() { + const ref = this.ref.current; + + if (ref && !_.isNil(this.props.scrollTop)) { + if (this.props.scrollTop > 10000) { + ref.scrollToBottom(); + } else { + ref.scrollTop(this.props.scrollTop); + } + } + } + + componentDidMount() { + this.updateScroll(); + } + + componentDidUpdate() { + this.updateScroll(); + } + render() { const { customClassName, children, autoMaxHeight } = this.props; return ( JSX.Element; toolbarItems?: EditorToolbarView[]; + scrollTop?: number; + setScrollTop?: (value: React.MouseEvent) => void; } export interface EditorToolbarView { @@ -103,7 +105,7 @@ export class EditorTabBody extends PureComponent { } render() { - const { children, renderToolbar, heading, toolbarItems } = this.props; + const { children, renderToolbar, heading, toolbarItems, scrollTop, setScrollTop } = this.props; const { openView, fadeIn, isOpen } = this.state; return ( @@ -119,7 +121,7 @@ export class EditorTabBody extends PureComponent { )}
- +
{openView && this.renderOpenView(openView)} diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index d6c05e1d18c..a62da397d7f 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -32,6 +32,7 @@ interface State { isLoadingHelp: boolean; isPickerOpen: boolean; isAddingMixed: boolean; + scrollTop: number; } export class QueriesTab extends PureComponent { @@ -44,6 +45,7 @@ export class QueriesTab extends PureComponent { helpContent: null, isPickerOpen: false, isAddingMixed: false, + scrollTop: 0, }; findCurrentDataSource(): DataSourceSelectItem { @@ -104,7 +106,7 @@ export class QueriesTab extends PureComponent { } this.props.panel.addQuery(); - this.forceUpdate(); + this.setState({ scrollTop: this.state.scrollTop + 100000 }); }; onRemoveQuery = (query: DataQuery) => { @@ -127,9 +129,21 @@ export class QueriesTab extends PureComponent { }; renderToolbar = () => { - const { currentDS } = this.state; + const { currentDS, isAddingMixed } = this.state; - return ; + return ( + <> + +
+ {!isAddingMixed && ( + + )} + {isAddingMixed && this.renderMixedPicker()} +
+ + ); }; renderMixedPicker = () => { @@ -146,16 +160,21 @@ export class QueriesTab extends PureComponent { onAddMixedQuery = datasource => { this.onAddQuery({ datasource: datasource.name }); - this.setState({ isAddingMixed: false }); + this.setState({ isAddingMixed: false, scrollTop: this.state.scrollTop + 10000 }); }; onMixedPickerBlur = () => { this.setState({ isAddingMixed: false }); }; + setScrollTop = (event: React.MouseEvent) => { + const target = event.target as HTMLElement; + this.setState({ scrollTop: target.scrollTop }); + }; + render() { const { panel } = this.props; - const { currentDS, isAddingMixed } = this.state; + const { currentDS, scrollTop } = this.state; const queryInspector: EditorToolbarView = { title: 'Query Inspector', @@ -169,7 +188,13 @@ export class QueriesTab extends PureComponent { }; return ( - + <>
{panel.targets.map((query, index) => ( @@ -185,23 +210,6 @@ export class QueriesTab extends PureComponent { /> ))}
-
-
-
- - {' '} - {panel.getNextQueryLetter()} -
-
- {!isAddingMixed && ( - - )} - {isAddingMixed && this.renderMixedPicker()} -
-
-
From 548708a8d3024c642f4e0117969146a39c2ece1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 17 Jan 2019 11:27:32 +0100 Subject: [PATCH 08/12] Scroll to top when visualization picker is opened --- .../dashboard/panel_editor/VisualizationTab.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx index ad569a9ff90..64bf3165ddc 100644 --- a/public/app/features/dashboard/panel_editor/VisualizationTab.tsx +++ b/public/app/features/dashboard/panel_editor/VisualizationTab.tsx @@ -26,6 +26,7 @@ interface Props { interface State { isVizPickerOpen: boolean; searchQuery: string; + scrollTop: number; } export class VisualizationTab extends PureComponent { @@ -39,6 +40,7 @@ export class VisualizationTab extends PureComponent { this.state = { isVizPickerOpen: false, searchQuery: '', + scrollTop: 0, }; } @@ -143,7 +145,7 @@ export class VisualizationTab extends PureComponent { }; onOpenVizPicker = () => { - this.setState({ isVizPickerOpen: true }); + this.setState({ isVizPickerOpen: true, scrollTop: 0 }); }; onCloseVizPicker = () => { @@ -201,9 +203,14 @@ export class VisualizationTab extends PureComponent { renderHelp = () => ; + setScrollTop = (event: React.MouseEvent) => { + const target = event.target as HTMLElement; + this.setState({ scrollTop: target.scrollTop }); + }; + render() { const { plugin } = this.props; - const { isVizPickerOpen, searchQuery } = this.state; + const { isVizPickerOpen, searchQuery, scrollTop } = this.state; const pluginHelp: EditorToolbarView = { heading: 'Help', @@ -212,7 +219,8 @@ export class VisualizationTab extends PureComponent { }; return ( - + <> Date: Thu, 17 Jan 2019 13:08:20 +0100 Subject: [PATCH 09/12] Query editor row in react is working --- .../dashboard/panel_editor/QueriesTab.tsx | 2 +- .../dashboard/panel_editor/QueryEditorRow.tsx | 24 +++++- public/app/features/panel/query_editor_row.ts | 78 ++----------------- public/sass/components/_panel_editor.scss | 1 + public/sass/components/_query_editor.scss | 36 +++++++-- 5 files changed, 56 insertions(+), 85 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx index a62da397d7f..e965b285967 100644 --- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx +++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx @@ -189,7 +189,7 @@ export class QueriesTab extends PureComponent { return ( { const { datasource } = this.state; if (datasource.pluginExports.QueryCtrl) { + return
(this.element = element)} />; } - return
(this.element = element)} />; if (datasource.pluginExports.QueryEditor) { const QueryEditor = datasource.pluginExports.QueryEditor; @@ -128,7 +128,7 @@ export class QueryEditorRow extends PureComponent { angularScope.toggleEditorMode(); this.angularQueryEditor.digest(); } - } + }; get hasTextEditMode() { const { angularScope } = this.state; @@ -149,6 +149,16 @@ export class QueryEditorRow extends PureComponent { this.forceUpdate(); }; + renderCollapsedText(): string | null { + const { angularScope } = this.state; + + if (angularScope && angularScope.getCollapsedText) { + return angularScope.getCollapsedText(); + } + + return null; + } + render() { const { query, datasourceName, inMixedMode } = this.props; const { datasource, isCollapsed } = this.state; @@ -177,9 +187,16 @@ export class QueryEditorRow extends PureComponent { {inMixedMode && ({datasourceName})} {isDisabled && Disabled}
+
+ {isCollapsed &&
{this.renderCollapsedText()}
} +
{this.hasTextEditMode && ( - )} @@ -218,4 +235,5 @@ export interface AngularQueryComponentScope { moveQuery: (query: DataQuery, direction: number) => void; datasource: DataSourceApi; toggleEditorMode?: () => void; + getCollapsedText?: () => string; } diff --git a/public/app/features/panel/query_editor_row.ts b/public/app/features/panel/query_editor_row.ts index 82d93ca5cae..fa25ce832be 100644 --- a/public/app/features/panel/query_editor_row.ts +++ b/public/app/features/panel/query_editor_row.ts @@ -3,94 +3,26 @@ import angular from 'angular'; const module = angular.module('grafana.directives'); export class QueryRowCtrl { - collapsedText: string; - canCollapse: boolean; - getCollapsedText: any; target: any; queryCtrl: any; panelCtrl: any; panel: any; - collapsed: any; - hideEditorRowActions: boolean; hasTextEditMode: boolean; constructor() { this.panelCtrl = this.queryCtrl.panelCtrl; this.target = this.queryCtrl.target; this.panel = this.panelCtrl.panel; - this.hideEditorRowActions = this.panelCtrl.hideEditorRowActions; if (this.hasTextEditMode) { - this.panelCtrl.toggleEditorMode = this.toggleEditorMode.bind(this); + // expose this function to react parent component + this.panelCtrl.toggleEditorMode = this.queryCtrl.toggleEditorMode.bind(this.queryCtrl); } - if (!this.target.refId) { - this.target.refId = this.panel.getNextQueryLetter(); + if (this.queryCtrl.getCollapsedText) { + // expose this function to react parent component + this.panelCtrl.getCollapsedText = this.queryCtrl.getCollapsedText.bind(this.queryCtrl); } - - this.toggleCollapse(true); - if (this.target.isNew) { - delete this.target.isNew; - this.toggleCollapse(false); - } - - if (this.panel.targets.length < 4) { - this.collapsed = false; - } - } - - toggleHideQuery() { - this.target.hide = !this.target.hide; - this.panelCtrl.refresh(); - } - - toggleCollapse(init) { - if (!this.canCollapse) { - return; - } - - if (!this.panelCtrl.__collapsedQueryCache) { - this.panelCtrl.__collapsedQueryCache = {}; - } - - if (init) { - this.collapsed = this.panelCtrl.__collapsedQueryCache[this.target.refId] !== false; - } else { - this.collapsed = !this.collapsed; - this.panelCtrl.__collapsedQueryCache[this.target.refId] = this.collapsed; - } - - try { - this.collapsedText = this.queryCtrl.getCollapsedText(); - } catch (e) { - const err = e.message || e.toString(); - this.collapsedText = 'Error: ' + err; - } - } - - toggleEditorMode() { - if (this.canCollapse && this.collapsed) { - this.collapsed = false; - } - - this.queryCtrl.toggleEditorMode(); - } - - removeQuery() { - if (this.panelCtrl.__collapsedQueryCache) { - delete this.panelCtrl.__collapsedQueryCache[this.target.refId]; - } - - this.panelCtrl.removeQuery(this.target); - } - - duplicateQuery() { - const clone = angular.copy(this.target); - this.panelCtrl.addQuery(clone); - } - - moveQuery(direction) { - this.panelCtrl.moveQuery(this.target, direction); } } diff --git a/public/sass/components/_panel_editor.scss b/public/sass/components/_panel_editor.scss index b2ab91ccb19..b791231a242 100644 --- a/public/sass/components/_panel_editor.scss +++ b/public/sass/components/_panel_editor.scss @@ -35,6 +35,7 @@ flex-grow: 1; background: $input-bg; margin: 0 20px 0 84px; + width: calc(100% - 84px); border-radius: 3px; box-shadow: $panel-editor-shadow; min-height: 0; diff --git a/public/sass/components/_query_editor.scss b/public/sass/components/_query_editor.scss index 35abd34a770..8d72f901b6e 100644 --- a/public/sass/components/_query_editor.scss +++ b/public/sass/components/_query_editor.scss @@ -200,6 +200,8 @@ input[type='text'].tight-form-func-param { position: relative; height: 35px; background: $page-bg; + flex-wrap: nowrap; + align-items: center; } .query-editor-row__ref-id { @@ -217,8 +219,26 @@ input[type='text'].tight-form-func-param { } } -.query-editor-row__actions { +.query-editor-row__collapsed-text { + padding: 0 10px; + display: flex; + align-items: center; flex-grow: 1; + overflow: hidden; + + > div { + color: $text-muted; + font-style: italic; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-size: $font-size-sm; + min-width: 0; + } +} + +.query-editor-row__actions { + flex-shrink: 0; display: flex; justify-content: flex-end; color: $text-muted; @@ -235,14 +255,14 @@ input[type='text'].tight-form-func-param { } } - .query-editor-row__body { - margin: 0 0 10px 40px; - background: $page-bg; +.query-editor-row__body { + margin: 0 0 10px 40px; + background: $page-bg; - &--collapsed { - display: none; - } - } + &--collapsed { + display: none; + } +} .query-editor-row__context-info { font-style: italic; From f041928e580a8ed131ae845a5334b2b2f43af420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 17 Jan 2019 13:15:25 +0100 Subject: [PATCH 10/12] Additional query editor row tweaks --- public/app/features/dashboard/panel_editor/QueryEditorRow.tsx | 4 ++++ public/app/plugins/datasource/graphite/query_ctrl.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index 0dc53e69be6..d27e0dead57 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -128,6 +128,10 @@ export class QueryEditorRow extends PureComponent { angularScope.toggleEditorMode(); this.angularQueryEditor.digest(); } + + if (this.state.isCollapsed) { + this.setState({ isCollapsed: false }); + } }; get hasTextEditMode() { diff --git a/public/app/plugins/datasource/graphite/query_ctrl.ts b/public/app/plugins/datasource/graphite/query_ctrl.ts index fa908c5e955..b89e84d23a7 100644 --- a/public/app/plugins/datasource/graphite/query_ctrl.ts +++ b/public/app/plugins/datasource/graphite/query_ctrl.ts @@ -391,6 +391,10 @@ export class GraphiteQueryCtrl extends QueryCtrl { this.paused = false; this.panelCtrl.refresh(); } + + getCollapsedText() { + return this.target.target; + } } function mapToDropdownOptions(results) { From 3047579cdd66f56782ff9162bc093a8c396531ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 17 Jan 2019 13:27:01 +0100 Subject: [PATCH 11/12] removed unused props from angular query component interface --- .../features/dashboard/panel_editor/QueryEditorRow.tsx | 8 +------- .../datasource/postgres/partials/query.editor.html | 6 +++--- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx index d27e0dead57..410d0029b15 100644 --- a/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx +++ b/public/app/features/dashboard/panel_editor/QueryEditorRow.tsx @@ -43,7 +43,7 @@ export class QueryEditorRow extends PureComponent { } getAngularQueryComponentScope(): AngularQueryComponentScope { - const { panel, onAddQuery, onMoveQuery, onRemoveQuery, query } = this.props; + const { panel, query } = this.props; const { datasource } = this.state; return { @@ -52,9 +52,6 @@ export class QueryEditorRow extends PureComponent { panel: panel, refresh: () => panel.refresh(), render: () => panel.render, - addQuery: onAddQuery, - moveQuery: onMoveQuery, - removeQuery: onRemoveQuery, events: panel.events, }; } @@ -234,9 +231,6 @@ export interface AngularQueryComponentScope { events: Emitter; refresh: () => void; render: () => void; - removeQuery: (query: DataQuery) => void; - addQuery: (query?: DataQuery) => void; - moveQuery: (query: DataQuery, direction: number) => void; datasource: DataSourceApi; toggleEditorMode?: () => void; getCollapsedText?: () => string; diff --git a/public/app/plugins/datasource/postgres/partials/query.editor.html b/public/app/plugins/datasource/postgres/partials/query.editor.html index 6c3bf02cb51..5d866245aff 100644 --- a/public/app/plugins/datasource/postgres/partials/query.editor.html +++ b/public/app/plugins/datasource/postgres/partials/query.editor.html @@ -138,9 +138,9 @@
Time series:
 - return column named time (UTC in seconds or timestamp)
 - return column(s) with numeric datatype as values
-Optional: 
-  - return column named metric to represent the series name. 
-  - If multiple value columns are returned the metric column is used as prefix. 
+Optional:
+  - return column named metric to represent the series name.
+  - If multiple value columns are returned the metric column is used as prefix.
   - If no column named metric is found the column name of the value column is used as series name
 
 Resultsets of time series queries need to be sorted by time.

From 3cb73e79487f81a64219ab2b6ed0aab163b3e503 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torkel=20=C3=96degaard?= 
Date: Thu, 17 Jan 2019 15:11:38 +0100
Subject: [PATCH 12/12] Minor fix scrollpos when duplicating

---
 public/app/features/dashboard/panel_editor/QueriesTab.tsx | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/public/app/features/dashboard/panel_editor/QueriesTab.tsx b/public/app/features/dashboard/panel_editor/QueriesTab.tsx
index e965b285967..7d2f77aa338 100644
--- a/public/app/features/dashboard/panel_editor/QueriesTab.tsx
+++ b/public/app/features/dashboard/panel_editor/QueriesTab.tsx
@@ -96,7 +96,7 @@ export class QueriesTab extends PureComponent {
 
   onAddQuery = (query?: Partial) => {
     this.props.panel.addQuery(query);
-    this.forceUpdate();
+    this.setState({ scrollTop: this.state.scrollTop + 100000 });
   };
 
   onAddQueryClick = () => {
@@ -105,8 +105,7 @@ export class QueriesTab extends PureComponent {
       return;
     }
 
-    this.props.panel.addQuery();
-    this.setState({ scrollTop: this.state.scrollTop + 100000 });
+    this.onAddQuery();
   };
 
   onRemoveQuery = (query: DataQuery) => {