From 4591c3555caa47b925fc0dc1aa3b0e598c165629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 11 Dec 2018 13:36:44 +0100 Subject: [PATCH] Moved more metrics tab to react --- .../features/dashboard/dashboard_migration.ts | 2 +- .../app/features/dashboard/dashboard_model.ts | 10 - .../dashboard/dashgrid/QueriesTab.tsx | 111 ++++++++--- public/app/features/dashboard/panel_model.ts | 18 ++ public/app/features/panel/metrics_tab.ts | 176 +----------------- .../features/panel/partials/metrics_tab.html | 37 ++-- public/app/features/panel/query_editor_row.ts | 2 +- public/sass/components/_gf-form.scss | 1 - 8 files changed, 136 insertions(+), 221 deletions(-) diff --git a/public/app/features/dashboard/dashboard_migration.ts b/public/app/features/dashboard/dashboard_migration.ts index 5f1deae6e14..c5a960304fd 100644 --- a/public/app/features/dashboard/dashboard_migration.ts +++ b/public/app/features/dashboard/dashboard_migration.ts @@ -143,7 +143,7 @@ export class DashboardMigrator { panelUpgrades.push(panel => { _.each(panel.targets, target => { if (!target.refId) { - target.refId = this.dashboard.getNextQueryLetter(panel); + target.refId = panel.getNextQueryLetter(); } }); }); diff --git a/public/app/features/dashboard/dashboard_model.ts b/public/app/features/dashboard/dashboard_model.ts index 18a16d5c1d4..6f98bc5a17a 100644 --- a/public/app/features/dashboard/dashboard_model.ts +++ b/public/app/features/dashboard/dashboard_model.ts @@ -806,16 +806,6 @@ export class DashboardModel { return this.timezone === 'browser' ? moment(date).fromNow() : moment.utc(date).fromNow(); } - getNextQueryLetter(panel) { - const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - - return _.find(letters, refId => { - return _.every(panel.targets, other => { - return other.refId !== refId; - }); - }); - } - isTimezoneUtc() { return this.getTimezone() === 'utc'; } diff --git a/public/app/features/dashboard/dashgrid/QueriesTab.tsx b/public/app/features/dashboard/dashgrid/QueriesTab.tsx index 4c341f684f7..1e00e193456 100644 --- a/public/app/features/dashboard/dashgrid/QueriesTab.tsx +++ b/public/app/features/dashboard/dashgrid/QueriesTab.tsx @@ -1,21 +1,27 @@ +// Libraries import React, { SFC, PureComponent } from 'react'; +import Remarkable from 'remarkable'; +import _ from 'lodash'; + +// Components import DataSourceOption from './DataSourceOption'; -import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; import { EditorTabBody } from './EditorTabBody'; import { DataSourcePicker } from './DataSourcePicker'; -import { PanelModel } from '../panel_model'; -import { DashboardModel } from '../dashboard_model'; -import './../../panel/metrics_tab'; -import config from 'app/core/config'; import { QueryInspector } from './QueryInspector'; import { TimeRangeOptions } from './TimeRangeOptions'; +import './../../panel/metrics_tab'; +import { AngularQueryComponentScope } from 'app/features/panel/metrics_tab'; // Services import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv'; -import { DataSourceSelectItem } from 'app/types'; +import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; +import config from 'app/core/config'; -import Remarkable from 'remarkable'; +// Types +import { PanelModel } from '../panel_model'; +import { DashboardModel } from '../dashboard_model'; +import { DataSourceSelectItem, DataQuery } from 'app/types'; interface Props { panel: PanelModel; @@ -40,7 +46,7 @@ interface LoadingPlaceholderProps { const LoadingPlaceholder: SFC = ({ text }) =>

{text}

; export class QueriesTab extends PureComponent { - element: any; + element: HTMLElement; component: AngularComponent; datasources: DataSourceSelectItem[] = getDatasourceSrv().getMetricSources(); backendSrv: BackendSrv = getBackendSrv(); @@ -59,20 +65,30 @@ export class QueriesTab extends PureComponent { }; } + 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 { panel, dashboard } = this.props; const loader = getAngularLoader(); const template = ''; const scopeProps = { - ctrl: { - panel: panel, - dashboard: dashboard, - refresh: () => panel.refresh(), - }, + ctrl: this.getAngularQueryComponentScope(), }; this.component = loader.load(this.element, scopeProps, template); @@ -87,6 +103,7 @@ export class QueriesTab extends PureComponent { onChangeDataSource = datasource => { const { panel } = this.props; const { currentDatasource } = this.state; + // switching to mixed if (datasource.meta.mixed) { panel.targets.forEach(target => { @@ -95,10 +112,16 @@ export class QueriesTab extends PureComponent { target.datasource = config.defaultDatasource; } }); - } else if (currentDatasource && currentDatasource.meta.mixed) { - panel.targets.forEach(target => { - delete target.datasource; - }); + } else if (currentDatasource) { + // if switching from mixed + if (currentDatasource.meta.mixed) { + for (const target of panel.targets) { + delete target.datasource; + } + } else if (currentDatasource.meta.id !== datasource.meta.id) { + // we are changing data source type, clear queries + panel.targets = [{ refId: 'A' }]; + } } panel.datasource = datasource.value; @@ -227,9 +250,41 @@ export class QueriesTab extends PureComponent { return isLoading ? : helpHtml; }; + onAddQuery = (query?: DataQuery) => { + this.props.panel.addQuery(query); + this.forceUpdate(); + }; + + onAddQueryClick = () => { + this.props.panel.addQuery(); + this.component.digest(); + this.forceUpdate(); + }; + + onRemoveQuery = (query: DataQuery) => { + const { panel } = this.props; + + const index = _.indexOf(panel.targets, query); + panel.targets.splice(index, 1); + panel.refresh(); + + this.forceUpdate(); + }; + + onMoveQuery = (query: DataQuery, direction: number) => { + const { panel } = this.props; + + const index = _.indexOf(panel.targets, query); + _.move(panel.targets, index, index + direction); + + this.forceUpdate(); + }; + render() { + const { panel } = this.props; const { currentDatasource } = this.state; const { hasQueryHelp } = currentDatasource.meta; + const dsInformation = { title: currentDatasource.name, imgSrc: currentDatasource.meta.info.logos.small, @@ -266,9 +321,23 @@ export class QueriesTab extends PureComponent { return ( - <> -
(this.element = element)} style={{ width: '100%' }} /> - +
+
(this.element = element)} /> + +
+
+ + +
+
+
); } diff --git a/public/app/features/dashboard/panel_model.ts b/public/app/features/dashboard/panel_model.ts index a664e3d8ea1..e0a3e6707cb 100644 --- a/public/app/features/dashboard/panel_model.ts +++ b/public/app/features/dashboard/panel_model.ts @@ -1,6 +1,7 @@ import { Emitter } from 'app/core/utils/emitter'; import _ from 'lodash'; import { PANEL_OPTIONS_KEY_PREFIX } from 'app/core/constants'; +import { DataQuery } from 'app/types'; export interface GridPos { x: number; @@ -237,6 +238,23 @@ export class PanelModel { this.restorePanelOptions(pluginId); } + addQuery(query?: DataQuery) { + query = query || { refId: 'A' }; + (query.refId = this.getNextQueryLetter()), (query.isNew = true); + + this.targets.push(query); + } + + getNextQueryLetter(): string { + const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + return _.find(letters, refId => { + return _.every(this.targets, other => { + return other.refId !== refId; + }); + }); + } + destroy() { this.events.emit('panel-teardown'); this.events.removeAllListeners(); diff --git a/public/app/features/panel/metrics_tab.ts b/public/app/features/panel/metrics_tab.ts index 2ceb39e8a82..70b3571e30d 100644 --- a/public/app/features/panel/metrics_tab.ts +++ b/public/app/features/panel/metrics_tab.ts @@ -1,181 +1,24 @@ // Libraries import _ from 'lodash'; -import Remarkable from 'remarkable'; // Services & utils import coreModule from 'app/core/core_module'; -import config from 'app/core/config'; 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 class MetricsTabCtrl { - dsName: string; - panel: any; - panelCtrl: any; - datasources: any[]; - datasourceInstance: any; - nextRefId: string; +export interface AngularQueryComponentScope { + panel: PanelModel; dashboard: DashboardModel; - panelDsValue: any; - addQueryDropdown: any; - queryTroubleshooterOpen: boolean; - helpOpen: boolean; - optionsOpen: boolean; - hasQueryHelp: boolean; - helpHtml: string; - queryOptions: any; events: Emitter; - - /** @ngInject */ - constructor($scope, private $sce, datasourceSrv, private backendSrv) { - this.panelCtrl = $scope.ctrl; - $scope.ctrl = this; - - this.panel = this.panelCtrl.panel; - this.panel.datasource = this.panel.datasource || null; - this.panel.targets = this.panel.targets || [{}]; - - this.dashboard = this.panelCtrl.dashboard; - this.datasources = datasourceSrv.getMetricSources(); - this.panelDsValue = this.panelCtrl.panel.datasource; - - // added here as old query controller expects this on panelCtrl but - // they are getting MetricsTabCtrl instead - this.events = this.panel.events; - - for (const ds of this.datasources) { - if (ds.value === this.panelDsValue) { - this.datasourceInstance = ds; - } - } - - this.addQueryDropdown = { text: 'Add Query', value: null, fake: true }; - - // update next ref id - this.nextRefId = this.dashboard.getNextQueryLetter(this.panel); - this.updateDatasourceOptions(); - } - - updateDatasourceOptions() { - if (this.datasourceInstance) { - this.hasQueryHelp = this.datasourceInstance.meta.hasQueryHelp; - this.queryOptions = this.datasourceInstance.meta.queryOptions; - } - } - - getOptions(includeBuiltin) { - return Promise.resolve( - this.datasources - .filter(value => { - return includeBuiltin || !value.meta.builtIn; - }) - .map(ds => { - return { value: ds.value, text: ds.name, datasource: ds }; - }) - ); - } - - datasourceChanged(option) { - if (!option) { - return; - } - - this.setDatasource(option.datasource); - this.updateDatasourceOptions(); - } - - setDatasource(datasource) { - // switching to mixed - if (datasource.meta.mixed) { - _.each(this.panel.targets, target => { - target.datasource = this.panel.datasource; - if (!target.datasource) { - target.datasource = config.defaultDatasource; - } - }); - } else if (this.datasourceInstance) { - // if switching from mixed - if (this.datasourceInstance.meta.mixed) { - _.each(this.panel.targets, target => { - delete target.datasource; - }); - } else if (this.datasourceInstance.meta.id !== datasource.meta.id) { - // we are changing data source type, clear queries - this.panel.targets = [{ refId: 'A' }]; - this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel); - } - } - - this.datasourceInstance = datasource; - this.panel.datasource = datasource.value; - this.panel.refresh(); - } - - addMixedQuery(option) { - if (!option) { - return; - } - - this.panelCtrl.addQuery({ - isNew: true, - datasource: option.datasource.name, - }); - this.addQueryDropdown = { text: 'Add Query', value: null, fake: true }; - } - - toggleHelp() { - this.optionsOpen = false; - this.queryTroubleshooterOpen = false; - this.helpOpen = !this.helpOpen; - - this.backendSrv.get(`/api/plugins/${this.datasourceInstance.meta.id}/markdown/query_help`).then(res => { - const md = new Remarkable(); - this.helpHtml = this.$sce.trustAsHtml(md.render(res)); - }); - } - - toggleOptions() { - this.helpOpen = false; - this.queryTroubleshooterOpen = false; - this.optionsOpen = !this.optionsOpen; - } - - toggleQueryTroubleshooter() { - this.helpOpen = false; - this.optionsOpen = false; - this.queryTroubleshooterOpen = !this.queryTroubleshooterOpen; - } - - addQuery(query?) { - query = query || {}; - query.refId = this.dashboard.getNextQueryLetter(this.panel); - query.isNew = true; - - this.panel.targets.push(query); - this.nextRefId = this.dashboard.getNextQueryLetter(this.panel); - } - - refresh() { - this.panel.refresh(); - } - - render() { - this.panel.render(); - } - - removeQuery(target) { - const index = _.indexOf(this.panel.targets, target); - this.panel.targets.splice(index, 1); - this.nextRefId = this.dashboard.getNextQueryLetter(this.panel); - this.panel.refresh(); - } - - moveQuery(target, direction) { - const index = _.indexOf(this.panel.targets, target); - _.move(this.panel.targets, index, index + direction); - } + refresh: () => void; + render: () => void; + removeQuery: (query: DataQuery) => void; + addQuery: (query?: DataQuery) => void; + moveQuery: (query: DataQuery, direction: number) => void; } /** @ngInject */ @@ -185,7 +28,6 @@ export function metricsTabDirective() { restrict: 'E', scope: true, templateUrl: 'public/app/features/panel/partials/metrics_tab.html', - controller: MetricsTabCtrl, }; } diff --git a/public/app/features/panel/partials/metrics_tab.html b/public/app/features/panel/partials/metrics_tab.html index ecee1f76ea9..5e9f23ba2ef 100644 --- a/public/app/features/panel/partials/metrics_tab.html +++ b/public/app/features/panel/partials/metrics_tab.html @@ -1,5 +1,3 @@ - -
@@ -7,21 +5,20 @@
-
-
- - - -
-
-
+ + + + + + + + + + + + + + + + + diff --git a/public/app/features/panel/query_editor_row.ts b/public/app/features/panel/query_editor_row.ts index 39bd6008873..a44c1e8be6d 100644 --- a/public/app/features/panel/query_editor_row.ts +++ b/public/app/features/panel/query_editor_row.ts @@ -20,7 +20,7 @@ export class QueryRowCtrl { this.hideEditorRowActions = this.panelCtrl.hideEditorRowActions; if (!this.target.refId) { - this.target.refId = this.panelCtrl.dashboard.getNextQueryLetter(this.panel); + this.target.refId = this.panel.getNextQueryLetter(); } this.toggleCollapse(true); diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index 0c6ef7d1fa0..f0855ead897 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -110,7 +110,6 @@ $input-border: 1px solid $input-border-color; &--grow { flex-grow: 1; - min-height: 2.6rem; } &--error {