From d6c6ba642e62cb03e2707216117d23c38d942f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 11 Dec 2018 10:33:09 +0100 Subject: [PATCH 01/17] Don't show heading for first tab --- .../app/features/dashboard/dashgrid/VisualizationTab.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx index 97e4e3aa556..19026754f83 100644 --- a/public/app/features/dashboard/dashgrid/VisualizationTab.tsx +++ b/public/app/features/dashboard/dashgrid/VisualizationTab.tsx @@ -87,10 +87,11 @@ export class VisualizationTab extends PureComponent { let template = ''; for (let i = 0; i < panelCtrl.editorTabs.length; i++) { - template += ` -
-
{{ctrl.editorTabs[${i}].title}}
-
+ template += + ` +
` + + (i > 0 ? `
{{ctrl.editorTabs[${i}].title}}
` : '') + + `
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 02/17] 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 { From d998527128eef7c3f0a1cf404053961885c70c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 11 Dec 2018 17:03:38 +0100 Subject: [PATCH 03/17] wip --- .../dashboard/dashgrid/DataSourcePicker.tsx | 46 ++- .../dashboard/dashgrid/EditorTabBody.tsx | 127 +++---- .../dashboard/dashgrid/QueriesTab.tsx | 334 +++++++++--------- public/sass/components/_panel_editor.scss | 13 + 4 files changed, 252 insertions(+), 268 deletions(-) diff --git a/public/app/features/dashboard/dashgrid/DataSourcePicker.tsx b/public/app/features/dashboard/dashgrid/DataSourcePicker.tsx index 21eaac3e027..dc49c9998ab 100644 --- a/public/app/features/dashboard/dashgrid/DataSourcePicker.tsx +++ b/public/app/features/dashboard/dashgrid/DataSourcePicker.tsx @@ -7,10 +7,12 @@ import { DataSourceSelectItem } from 'app/types'; export interface Props { onChangeDataSource: (ds: DataSourceSelectItem) => void; datasources: DataSourceSelectItem[]; + current: DataSourceSelectItem; } interface State { searchQuery: string; + isOpen: boolean; } export class DataSourcePicker extends PureComponent { @@ -18,8 +20,10 @@ export class DataSourcePicker extends PureComponent { constructor(props) { super(props); + this.state = { searchQuery: '', + isOpen: false, }; } @@ -95,21 +99,39 @@ export class DataSourcePicker extends PureComponent { ); } + onOpen = () => { + this.setState({ isOpen: true }); + }; + render() { + const { current } = this.props; + const { isOpen } = this.state; + return ( - ( - <> -
- {this.renderFilters(keyNavProps)} -
-
-
- {this.getDataSources().map((ds, index) => this.renderDataSource(ds, index, keyNavProps))} -
- +
+ {!isOpen && ( +
+ +
{current.name}
+ +
)} - /> + {isOpen && ( + ( +
+
+ {this.renderFilters(keyNavProps)} +
+
+
+ {this.getDataSources().map((ds, index) => this.renderDataSource(ds, index, keyNavProps))} +
+
+ )} + /> + )} +
); } } diff --git a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx index d0ec87dd7bf..4a22a7a0b9d 100644 --- a/public/app/features/dashboard/dashgrid/EditorTabBody.tsx +++ b/public/app/features/dashboard/dashgrid/EditorTabBody.tsx @@ -5,22 +5,10 @@ import { FadeIn } from 'app/core/components/Animations/FadeIn'; interface Props { children: JSX.Element; heading: string; - main?: EditorToolBarView; - toolbarItems: EditorToolBarView[]; -} - -export interface EditorToolBarView { - title: string; - imgSrc?: string; - icon?: string; - disabled?: boolean; - onClick?: () => void; - render: (closeFunction: any) => JSX.Element | JSX.Element[]; + renderToolbar: () => JSX.Element; } interface State { - openView?: EditorToolBarView; - isOpen: boolean; fadeIn: boolean; } @@ -29,9 +17,7 @@ export class EditorTabBody extends PureComponent { super(props); this.state = { - openView: null, fadeIn: false, - isOpen: false, }; } @@ -39,87 +25,56 @@ export class EditorTabBody extends PureComponent { this.setState({ fadeIn: true }); } - onToggleToolBarView = (item: EditorToolBarView) => { - this.setState({ - openView: item, - isOpen: !this.state.isOpen, - }); - }; - - onCloseOpenView = () => { - this.setState({ isOpen: false }); - }; - - static getDerivedStateFromProps(props, state) { - if (state.openView) { - const activeToolbarItem = props.toolbarItems.find( - item => item.title === state.openView.title && item.icon === state.openView.icon - ); - if (activeToolbarItem) { - return { - ...state, - openView: activeToolbarItem, - }; - } - } - return state; - } - - renderMainSelection(view: EditorToolBarView) { - return ( -
this.onToggleToolBarView(view)} key={view.title + view.icon}> - -
{view.title}
- -
- ); - } - - renderButton(view: EditorToolBarView) { - const onClick = () => { - if (view.onClick) { - view.onClick(); - } - this.onToggleToolBarView(view); - }; - - return ( -
- -
- ); - } - - renderOpenView(view: EditorToolBarView) { - return ( -
- - {view.render(this.onCloseOpenView)} -
- ); - } + // renderMainSelection(view: EditorToolBarView) { + // return ( + //
this.onToggleToolBarView(view)} key={view.title + view.icon}> + // + //
{view.title}
+ // + //
+ // ); + // } + // + // renderButton(view: EditorToolBarView) { + // const onClick = () => { + // if (view.onClick) { + // view.onClick(); + // } + // this.onToggleToolBarView(view); + // }; + // + // return ( + //
+ // + //
+ // ); + // } + // + // renderOpenView(view: EditorToolBarView) { + // return ( + //
+ // + // {view.render(this.onCloseOpenView)} + //
+ // ); + // } render() { - const { children, toolbarItems, main, heading } = this.props; - const { openView, fadeIn, isOpen } = this.state; + const { children, renderToolbar, heading } = this.props; + const { fadeIn } = this.state; return ( <>
{heading}
- {main && this.renderMainSelection(main)} -
- {toolbarItems.map(item => this.renderButton(item))} + {renderToolbar && renderToolbar()}
- -
{openView && this.renderOpenView(openView)}
-
{children} diff --git a/public/app/features/dashboard/dashgrid/QueriesTab.tsx b/public/app/features/dashboard/dashgrid/QueriesTab.tsx index 1e00e193456..fe23dbf4f32 100644 --- a/public/app/features/dashboard/dashgrid/QueriesTab.tsx +++ b/public/app/features/dashboard/dashgrid/QueriesTab.tsx @@ -28,15 +28,11 @@ interface Props { dashboard: DashboardModel; } -interface Help { - isLoading: boolean; - helpHtml: any; -} - interface State { - currentDatasource: DataSourceSelectItem; - help: Help; - hideTimeOverride: boolean; + currentDS: DataSourceSelectItem; + helpContent: JSX.Element; + isLoadingHelp: string; + isPickerOpen: boolean; } interface LoadingPlaceholderProps { @@ -56,12 +52,10 @@ export class QueriesTab extends PureComponent { const { panel } = props; this.state = { - currentDatasource: this.datasources.find(datasource => datasource.value === panel.datasource), - help: { - isLoading: false, - helpHtml: null, - }, - hideTimeOverride: false, + currentDS: this.datasources.find(datasource => datasource.value === panel.datasource), + isLoadingHelp: false, + helpContent: null, + isPickerOpen: false, }; } @@ -102,7 +96,7 @@ export class QueriesTab extends PureComponent { onChangeDataSource = datasource => { const { panel } = this.props; - const { currentDatasource } = this.state; + const { currentDS } = this.state; // switching to mixed if (datasource.meta.mixed) { @@ -112,13 +106,13 @@ export class QueriesTab extends PureComponent { target.datasource = config.defaultDatasource; } }); - } else if (currentDatasource) { + } else if (currentDS) { // if switching from mixed - if (currentDatasource.meta.mixed) { + if (currentDS.meta.mixed) { for (const target of panel.targets) { delete target.datasource; } - } else if (currentDatasource.meta.id !== datasource.meta.id) { + } else if (currentDS.meta.id !== datasource.meta.id) { // we are changing data source type, clear queries panel.targets = [{ refId: 'A' }]; } @@ -127,128 +121,118 @@ export class QueriesTab extends PureComponent { panel.datasource = datasource.value; panel.refresh(); - this.setState(prevState => ({ - ...prevState, - currentDatasource: datasource, - })); + this.setState({ + currentDS: datasource, + }); }; - loadHelp = () => { - const { currentDatasource } = this.state; - const hasHelp = currentDatasource.meta.hasQueryHelp; + // loadHelp = () => { + // const { currentDatasource } = this.state; + // const hasHelp = currentDatasource.meta.hasQueryHelp; + // + // if (hasHelp) { + // this.setState({ + // helpContent:

Loading help...

, + // isLoadingHelp: true + // }); + // + // this.backendSrv + // .get(`/api/plugins/${currentDatasource.meta.id}/markdown/query_help`) + // .then(res => { + // const md = new Remarkable(); + // const helpHtml = md.render(res); // TODO: Clean out dangerous code? Previous: this.helpHtml = this.$sce.trustAsHtml(md.render(res)); + // this.setState({ + // helpContent:
, + // isLoadingHelp: false + // }); + // }) + // .catch(() => { + // this.setState({ + // helpContent: 'Error occured when loading help', + // isLoadingHelp: false, + // }); + // }); + // } + // }; - if (hasHelp) { - this.setState(prevState => ({ - ...prevState, - help: { - helpHtml:

Loading help...

, - isLoading: true, - }, - })); - - this.backendSrv - .get(`/api/plugins/${currentDatasource.meta.id}/markdown/query_help`) - .then(res => { - const md = new Remarkable(); - const helpHtml = md.render(res); // TODO: Clean out dangerous code? Previous: this.helpHtml = this.$sce.trustAsHtml(md.render(res)); - this.setState(prevState => ({ - ...prevState, - help: { - helpHtml:
, - isLoading: false, - }, - })); - }) - .catch(() => { - this.setState(prevState => ({ - ...prevState, - help: { - helpHtml: 'Error occured when loading help', - isLoading: false, - }, - })); - }); - } - }; - - renderOptions = close => { - const { currentDatasource } = this.state; - const { queryOptions } = currentDatasource.meta; - const { panel } = this.props; - - const onChangeFn = (panelKey: string) => { - return (value: string | number) => { - panel[panelKey] = value; - panel.refresh(); - }; - }; - - const allOptions = { - cacheTimeout: { - label: 'Cache timeout', - placeholder: '60', - name: 'cacheTimeout', - value: panel.cacheTimeout, - tooltipInfo: ( - <> - If your time series store has a query cache this option can override the default cache timeout. Specify a - numeric value in seconds. - - ), - }, - maxDataPoints: { - label: 'Max data points', - placeholder: 'auto', - name: 'maxDataPoints', - value: panel.maxDataPoints, - tooltipInfo: ( - <> - The maximum data points the query should return. For graphs this is automatically set to one data point per - pixel. - - ), - }, - minInterval: { - label: 'Min time interval', - placeholder: '0', - name: 'minInterval', - value: panel.interval, - panelKey: 'interval', - tooltipInfo: ( - <> - A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '} - 1m if your data is written every minute. Access auto interval via variable{' '} - $__interval for time range string and $__interval_ms for numeric variable that can - be used in math expressions. - - ), - }, - }; - - const dsOptions = queryOptions - ? Object.keys(queryOptions).map(key => { - const options = allOptions[key]; - return ; - }) - : null; - - return ( - <> - - {dsOptions} - - ); - }; + // renderOptions = close => { + // const { currentDatasource } = this.state; + // const { queryOptions } = currentDatasource.meta; + // const { panel } = this.props; + // + // const onChangeFn = (panelKey: string) => { + // return (value: string | number) => { + // panel[panelKey] = value; + // panel.refresh(); + // }; + // }; + // + // const allOptions = { + // cacheTimeout: { + // label: 'Cache timeout', + // placeholder: '60', + // name: 'cacheTimeout', + // value: panel.cacheTimeout, + // tooltipInfo: ( + // <> + // If your time series store has a query cache this option can override the default cache timeout. Specify a + // numeric value in seconds. + // + // ), + // }, + // maxDataPoints: { + // label: 'Max data points', + // placeholder: 'auto', + // name: 'maxDataPoints', + // value: panel.maxDataPoints, + // tooltipInfo: ( + // <> + // The maximum data points the query should return. For graphs this is automatically set to one data point per + // pixel. + // + // ), + // }, + // minInterval: { + // label: 'Min time interval', + // placeholder: '0', + // name: 'minInterval', + // value: panel.interval, + // panelKey: 'interval', + // tooltipInfo: ( + // <> + // A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example{' '} + // 1m if your data is written every minute. Access auto interval via variable{' '} + // $__interval for time range string and $__interval_ms for numeric variable that can + // be used in math expressions. + // + // ), + // }, + // }; + // + // const dsOptions = queryOptions + // ? Object.keys(queryOptions).map(key => { + // const options = allOptions[key]; + // return ; + // }) + // : null; + // + // return ( + // <> + // + // {dsOptions} + // + // ); + // }; renderQueryInspector = () => { const { panel } = this.props; return ; }; - renderHelp = () => { - const { helpHtml, isLoading } = this.state.help; - return isLoading ? : helpHtml; - }; + // renderHelp = () => { + // const { helpHtml, isLoading } = this.state.help; + // return isLoading ? : helpHtml; + // }; onAddQuery = (query?: DataQuery) => { this.props.panel.addQuery(query); @@ -280,47 +264,57 @@ export class QueriesTab extends PureComponent { 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, - render: closeOpenView => ( - { - closeOpenView(); - this.onChangeDataSource(ds); - }} - /> - ), - }; - - const queryInspector = { - title: 'Query Inspector', - render: this.renderQueryInspector, - }; - - const dsHelp = { - title: '', - icon: 'fa fa-question', - disabled: !hasQueryHelp, - onClick: this.loadHelp, - render: this.renderHelp, - }; - - const options = { - title: 'Time Range', - icon: '', - disabled: false, - render: this.renderOptions, - }; + renderToolbar = () => { + const { currentDS } = this.state; return ( - + + ); + }; + + render() { + const { panel } = this.props; + + // const dsInformation = { + // title: currentDatasource.name, + // imgSrc: currentDatasource.meta.info.logos.small, + // render: closeOpenView => ( + // { + // closeOpenView(); + // this.onChangeDataSource(ds); + // }} + // /> + // ), + // }; + // + // const queryInspector = { + // title: 'Query Inspector', + // render: this.renderQueryInspector, + // }; + // + // const dsHelp = { + // title: '', + // icon: 'fa fa-question', + // disabled: !hasQueryHelp, + // onClick: this.loadHelp, + // render: this.renderHelp, + // }; + // + // const options = { + // title: 'Time Range', + // icon: '', + // disabled: false, + // render: this.renderOptions, + // }; + + return ( +
(this.element = element)} /> diff --git a/public/sass/components/_panel_editor.scss b/public/sass/components/_panel_editor.scss index ae480c5a3d3..2243556bdd7 100644 --- a/public/sass/components/_panel_editor.scss +++ b/public/sass/components/_panel_editor.scss @@ -273,6 +273,19 @@ } } +.ds-picker { + position: relative; +} + +.ds-picker-menu { + min-width: 400px; + max-width: 500px; + position: absolute; + background: $panel-editor-toolbar-view-bg; + padding: 5px; + overflow: auto; +} + .ds-picker-list__name { text-overflow: ellipsis; overflow: hidden; From 1d7d72b49dc93b7560905d2a39cc4ccc07a2bb61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 11 Dec 2018 18:49:48 +0100 Subject: [PATCH 04/17] wip: react select css refactoring --- .../components/Picker/DescriptionOption.tsx | 13 +- .../dashboard/dashgrid/DataSourcePicker.tsx | 154 +++++------------- .../sass/components/_description-picker.scss | 24 +++ public/sass/components/_form_select_box.scss | 12 +- public/sass/components/_panel_editor.scss | 1 + 5 files changed, 85 insertions(+), 119 deletions(-) diff --git a/public/app/core/components/Picker/DescriptionOption.tsx b/public/app/core/components/Picker/DescriptionOption.tsx index 9ddf13f7532..94b2b240dfc 100644 --- a/public/app/core/components/Picker/DescriptionOption.tsx +++ b/public/app/core/components/Picker/DescriptionOption.tsx @@ -8,15 +8,16 @@ interface ExtendedOptionProps extends OptionProps { } export const Option = (props: ExtendedOptionProps) => { - const { children, isSelected, data, className } = props; + const { children, isSelected, data } = props; + return ( -
- {isSelected &&