mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Moved more metrics tab to react
This commit is contained in:
parent
d6c6ba642e
commit
4591c3555c
@ -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();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -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';
|
||||
}
|
||||
|
@ -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<LoadingPlaceholderProps> = ({ text }) => <h2>{text}</h2>;
|
||||
|
||||
export class QueriesTab extends PureComponent<Props, State> {
|
||||
element: any;
|
||||
element: HTMLElement;
|
||||
component: AngularComponent;
|
||||
datasources: DataSourceSelectItem[] = getDatasourceSrv().getMetricSources();
|
||||
backendSrv: BackendSrv = getBackendSrv();
|
||||
@ -59,20 +65,30 @@ export class QueriesTab extends PureComponent<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
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 = '<metrics-tab />';
|
||||
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<Props, State> {
|
||||
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<Props, State> {
|
||||
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<Props, State> {
|
||||
return isLoading ? <LoadingPlaceholder text="Loading help..." /> : 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<Props, State> {
|
||||
|
||||
return (
|
||||
<EditorTabBody heading="Queries" main={dsInformation} toolbarItems={[options, queryInspector, dsHelp]}>
|
||||
<>
|
||||
<div ref={element => (this.element = element)} style={{ width: '100%' }} />
|
||||
</>
|
||||
<div className="query-editor-rows gf-form-group">
|
||||
<div ref={element => (this.element = element)} />
|
||||
|
||||
<div className="gf-form-query">
|
||||
<div className="gf-form gf-form-query-letter-cell">
|
||||
<label className="gf-form-label">
|
||||
<span className="gf-form-query-letter-cell-carret muted">
|
||||
<i className="fa fa-caret-down" />
|
||||
</span>
|
||||
<span className="gf-form-query-letter-cell-letter">{panel.getNextQueryLetter()}</span>
|
||||
</label>
|
||||
<button className="btn btn-secondary gf-form-btn" onClick={this.onAddQueryClick}>
|
||||
Add Query
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EditorTabBody>
|
||||
);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
|
||||
<div class="query-editor-rows gf-form-group" ng-if="ctrl.datasourceInstance">
|
||||
<div ng-repeat="target in ctrl.panel.targets" ng-class="{'gf-form-disabled': target.hide}">
|
||||
<rebuild-on-change property="ctrl.panel.datasource || target.datasource" show-null="true">
|
||||
<plugin-component type="query-ctrl">
|
||||
@ -7,21 +5,20 @@
|
||||
</rebuild-on-change>
|
||||
</div>
|
||||
|
||||
<div class="gf-form-query">
|
||||
<div class="gf-form gf-form-query-letter-cell">
|
||||
<label class="gf-form-label">
|
||||
<span class="gf-form-query-letter-cell-carret">
|
||||
<i class="fa fa-caret-down"></i>
|
||||
</span>
|
||||
<span class="gf-form-query-letter-cell-letter">{{ctrl.nextRefId}}</span>
|
||||
</label>
|
||||
<button class="btn btn-secondary gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.datasourceInstance.meta.mixed">
|
||||
Add Query
|
||||
</button>
|
||||
<div class="dropdown" ng-if="ctrl.datasourceInstance.meta.mixed">
|
||||
<gf-form-dropdown model="ctrl.addQueryDropdown" get-options="ctrl.getOptions(false)" on-change="ctrl.addMixedQuery($option)">
|
||||
</gf-form-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="gf-form-query"> -->
|
||||
<!-- <div class="gf-form gf-form-query-letter-cell"> -->
|
||||
<!-- <label class="gf-form-label"> -->
|
||||
<!-- <span class="gf-form-query-letter-cell-carret"> -->
|
||||
<!-- <i class="fa fa-caret-down"></i> -->
|
||||
<!-- </span> -->
|
||||
<!-- <span class="gf-form-query-letter-cell-letter">{{ctrl.nextRefId}}</span> -->
|
||||
<!-- </label> -->
|
||||
<!-- <button class="btn btn-secondary gf-form-btn" ng-click="ctrl.addQuery()" ng-hide="ctrl.datasourceInstance.meta.mixed"> -->
|
||||
<!-- Add Query -->
|
||||
<!-- </button> -->
|
||||
<!-- <div class="dropdown" ng-if="ctrl.datasourceInstance.meta.mixed"> -->
|
||||
<!-- <gf-form-dropdown model="ctrl.addQueryDropdown" get-options="ctrl.getOptions(false)" on-change="ctrl.addMixedQuery($option)"> -->
|
||||
<!-- </gf-form-dropdown> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
|
@ -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);
|
||||
|
@ -110,7 +110,6 @@ $input-border: 1px solid $input-border-color;
|
||||
|
||||
&--grow {
|
||||
flex-grow: 1;
|
||||
min-height: 2.6rem;
|
||||
}
|
||||
|
||||
&--error {
|
||||
|
Loading…
Reference in New Issue
Block a user