mirror of
https://github.com/grafana/grafana.git
synced 2025-09-27 15:43:47 +08:00
feat(graph panel): working on adding non time series support to graph panel
This commit is contained in:
@ -41,6 +41,7 @@ import 'app/core/routes/routes';
|
|||||||
import './filters/filters';
|
import './filters/filters';
|
||||||
import coreModule from './core_module';
|
import coreModule from './core_module';
|
||||||
import appEvents from './app_events';
|
import appEvents from './app_events';
|
||||||
|
import colors from './utils/colors';
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -60,4 +61,5 @@ export {
|
|||||||
dashboardSelector,
|
dashboardSelector,
|
||||||
queryPartEditorDirective,
|
queryPartEditorDirective,
|
||||||
WizardFlow,
|
WizardFlow,
|
||||||
|
colors,
|
||||||
};
|
};
|
||||||
|
@ -170,6 +170,7 @@ function (_, $, coreModule) {
|
|||||||
},
|
},
|
||||||
link: {
|
link: {
|
||||||
pre: function postLink($scope, elem, attrs) {
|
pre: function postLink($scope, elem, attrs) {
|
||||||
|
var cachedOptions;
|
||||||
|
|
||||||
$scope.valueToSegment = function(value) {
|
$scope.valueToSegment = function(value) {
|
||||||
var option = _.find($scope.options, {value: value});
|
var option = _.find($scope.options, {value: value});
|
||||||
@ -189,13 +190,20 @@ function (_, $, coreModule) {
|
|||||||
});
|
});
|
||||||
return $q.when(optionSegments);
|
return $q.when(optionSegments);
|
||||||
} else {
|
} else {
|
||||||
return $scope.getOptions();
|
return $scope.getOptions().then(function(options) {
|
||||||
|
cachedOptions = options;
|
||||||
|
return _.map(options, function(option) {
|
||||||
|
return uiSegmentSrv.newSegment({value: option.text});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.onSegmentChange = function() {
|
$scope.onSegmentChange = function() {
|
||||||
if ($scope.options) {
|
var options = $scope.options || cachedOptions;
|
||||||
var option = _.find($scope.options, {text: $scope.segment.value});
|
|
||||||
|
if (options) {
|
||||||
|
var option = _.find(options, {text: $scope.segment.value});
|
||||||
if (option && option.value !== $scope.property) {
|
if (option && option.value !== $scope.property) {
|
||||||
$scope.property = option.value;
|
$scope.property = option.value;
|
||||||
} else if (attrs.custom !== 'false') {
|
} else if (attrs.custom !== 'false') {
|
||||||
|
12
public/app/core/utils/colors.ts
Normal file
12
public/app/core/utils/colors.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export default [
|
||||||
|
"#7EB26D","#EAB839","#6ED0E0","#EF843C","#E24D42","#1F78C1","#BA43A9","#705DA0",
|
||||||
|
"#508642","#CCA300","#447EBC","#C15C17","#890F02","#0A437C","#6D1F62","#584477",
|
||||||
|
"#B7DBAB","#F4D598","#70DBED","#F9BA8F","#F29191","#82B5D8","#E5A8E2","#AEA2E0",
|
||||||
|
"#629E51","#E5AC0E","#64B0C8","#E0752D","#BF1B00","#0A50A1","#962D82","#614D93",
|
||||||
|
"#9AC48A","#F2C96D","#65C5DB","#F9934E","#EA6460","#5195CE","#D683CE","#806EB7",
|
||||||
|
"#3F6833","#967302","#2F575E","#99440A","#58140C","#052B51","#511749","#3F2B5B",
|
||||||
|
"#E0F9D7","#FCEACA","#CFFAFF","#F9E2D2","#FCE2DE","#BADFF4","#F9D9F9","#DEDAF7"
|
||||||
|
];
|
||||||
|
|
25
public/app/plugins/panel/graph/axes_edit_tab.ts
Normal file
25
public/app/plugins/panel/graph/axes_edit_tab.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
///<reference path="../../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
export class AxesEditTabCtrl {
|
||||||
|
panel: any;
|
||||||
|
panelCtrl: any;
|
||||||
|
|
||||||
|
/** @ngInject **/
|
||||||
|
constructor($scope) {
|
||||||
|
this.panelCtrl = $scope.ctrl;
|
||||||
|
this.panel = this.panelCtrl.panel;
|
||||||
|
$scope.ctrl = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @ngInject **/
|
||||||
|
export function axesTabCtrl() {
|
||||||
|
'use strict';
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: true,
|
||||||
|
templateUrl: 'public/app/plugins/panel/graph/tab_axes.html',
|
||||||
|
controller: AxesEditTabCtrl,
|
||||||
|
};
|
||||||
|
}
|
164
public/app/plugins/panel/graph/data_processor.ts
Normal file
164
public/app/plugins/panel/graph/data_processor.ts
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
///<reference path="../../../headers/common.d.ts" />
|
||||||
|
|
||||||
|
import kbn from 'app/core/utils/kbn';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import TimeSeries from 'app/core/time_series2';
|
||||||
|
import {colors} from 'app/core/core';
|
||||||
|
|
||||||
|
export class DataProcessor {
|
||||||
|
|
||||||
|
constructor(private panel) {
|
||||||
|
}
|
||||||
|
|
||||||
|
getSeriesList(options) {
|
||||||
|
|
||||||
|
switch (this.panel.xaxis.mode) {
|
||||||
|
case 'series':
|
||||||
|
case 'time': {
|
||||||
|
return options.dataList.map(this.timeSeriesHandler.bind(this));
|
||||||
|
}
|
||||||
|
case 'table': {
|
||||||
|
// Table panel uses only first enabled target, so we can use dataList[0]
|
||||||
|
// dataList.splice(1, dataList.length - 1);
|
||||||
|
// dataHandler = this.tableHandler;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'json': {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
seriesHandler(seriesData, index, datapoints, alias) {
|
||||||
|
var colorIndex = index % colors.length;
|
||||||
|
var color = this.panel.aliasColors[alias] || colors[colorIndex];
|
||||||
|
|
||||||
|
var series = new TimeSeries({datapoints: datapoints, alias: alias, color: color, unit: seriesData.unit});
|
||||||
|
|
||||||
|
// if (datapoints && datapoints.length > 0) {
|
||||||
|
// var last = moment.utc(datapoints[datapoints.length - 1][1]);
|
||||||
|
// var from = moment.utc(this.range.from);
|
||||||
|
// if (last - from < -10000) {
|
||||||
|
// this.datapointsOutside = true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// this.datapointsCount += datapoints.length;
|
||||||
|
// this.panel.tooltip.msResolution = this.panel.tooltip.msResolution || series.isMsResolutionNeeded();
|
||||||
|
// }
|
||||||
|
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeSeriesHandler(seriesData, index) {
|
||||||
|
var datapoints = seriesData.datapoints;
|
||||||
|
var alias = seriesData.target;
|
||||||
|
|
||||||
|
return this.seriesHandler(seriesData, index, datapoints, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
tableHandler(seriesData, index) {
|
||||||
|
var xColumnIndex = Number(this.panel.xaxis.columnIndex);
|
||||||
|
var valueColumnIndex = Number(this.panel.xaxis.valueColumnIndex);
|
||||||
|
var datapoints = _.map(seriesData.rows, (row) => {
|
||||||
|
var value = valueColumnIndex ? row[valueColumnIndex] : _.last(row);
|
||||||
|
return [
|
||||||
|
value, // Y value
|
||||||
|
row[xColumnIndex] // X value
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
var alias = seriesData.columns[valueColumnIndex].text;
|
||||||
|
|
||||||
|
return this.seriesHandler(seriesData, index, datapoints, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
// esRawDocHandler(seriesData, index) {
|
||||||
|
// let xField = this.panel.xaxis.esField;
|
||||||
|
// let valueField = this.panel.xaxis.esValueField;
|
||||||
|
// let datapoints = _.map(seriesData.datapoints, (doc) => {
|
||||||
|
// return [
|
||||||
|
// pluckDeep(doc, valueField), // Y value
|
||||||
|
// pluckDeep(doc, xField) // X value
|
||||||
|
// ];
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // Remove empty points
|
||||||
|
// datapoints = _.filter(datapoints, (point) => {
|
||||||
|
// return point[0] !== undefined;
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// var alias = valueField;
|
||||||
|
// return this.seriesHandler(seriesData, index, datapoints, alias);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
validateXAxisSeriesValue() {
|
||||||
|
switch (this.panel.xaxis.mode) {
|
||||||
|
case 'series': {
|
||||||
|
if (this.panel.xaxis.values.length === 0) {
|
||||||
|
this.panel.xaxis.values = ['total'];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var validOptions = this.getXAxisValueOptions({});
|
||||||
|
var found = _.find(validOptions, {value: this.panel.xaxis.values[0]});
|
||||||
|
if (!found) {
|
||||||
|
this.panel.xaxis.values = ['total'];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getXAxisValueOptions(options) {
|
||||||
|
switch (this.panel.xaxis.mode) {
|
||||||
|
case 'time': {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
case 'series': {
|
||||||
|
return [
|
||||||
|
{text: 'Avg', value: 'avg'},
|
||||||
|
{text: 'Min', value: 'min'},
|
||||||
|
{text: 'Max', value: 'min'},
|
||||||
|
{text: 'Total', value: 'total'},
|
||||||
|
{text: 'Count', value: 'count'},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function getFieldsFromESDoc(doc) {
|
||||||
|
// let fields = [];
|
||||||
|
// let fieldNameParts = [];
|
||||||
|
//
|
||||||
|
// function getFieldsRecursive(obj) {
|
||||||
|
// _.forEach(obj, (value, key) => {
|
||||||
|
// if (_.isObject(value)) {
|
||||||
|
// fieldNameParts.push(key);
|
||||||
|
// getFieldsRecursive(value);
|
||||||
|
// } else {
|
||||||
|
// let field = fieldNameParts.concat(key).join('.');
|
||||||
|
// fields.push(field);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// fieldNameParts.pop();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// getFieldsRecursive(doc);
|
||||||
|
// return fields;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// function pluckDeep(obj: any, property: string) {
|
||||||
|
// let propertyParts = property.split('.');
|
||||||
|
// let value = obj;
|
||||||
|
// for (let i = 0; i < propertyParts.length; ++i) {
|
||||||
|
// if (value[propertyParts[i]]) {
|
||||||
|
// value = value[propertyParts[i]];
|
||||||
|
// } else {
|
||||||
|
// return undefined;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return value;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
@ -14,15 +14,18 @@ import TimeSeries from 'app/core/time_series2';
|
|||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import * as fileExport from 'app/core/utils/file_export';
|
import * as fileExport from 'app/core/utils/file_export';
|
||||||
import {MetricsPanelCtrl, alertTab} from 'app/plugins/sdk';
|
import {MetricsPanelCtrl, alertTab} from 'app/plugins/sdk';
|
||||||
|
import {DataProcessor} from './data_processor';
|
||||||
|
|
||||||
class GraphCtrl extends MetricsPanelCtrl {
|
class GraphCtrl extends MetricsPanelCtrl {
|
||||||
static template = template;
|
static template = template;
|
||||||
|
|
||||||
hiddenSeries: any = {};
|
hiddenSeries: any = {};
|
||||||
seriesList: any = [];
|
seriesList: any = [];
|
||||||
|
dataList: any = [];
|
||||||
logScales: any;
|
logScales: any;
|
||||||
unitFormats: any;
|
unitFormats: any;
|
||||||
xAxisModes: any;
|
xAxisModes: any;
|
||||||
|
xAxisStatOptions: any;
|
||||||
xNameSegment: any;
|
xNameSegment: any;
|
||||||
annotationsPromise: any;
|
annotationsPromise: any;
|
||||||
datapointsCount: number;
|
datapointsCount: number;
|
||||||
@ -30,6 +33,7 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
datapointsWarning: boolean;
|
datapointsWarning: boolean;
|
||||||
colors: any = [];
|
colors: any = [];
|
||||||
subTabIndex: number;
|
subTabIndex: number;
|
||||||
|
processor: DataProcessor;
|
||||||
|
|
||||||
panelDefaults = {
|
panelDefaults = {
|
||||||
// datasource name, null = default datasource
|
// datasource name, null = default datasource
|
||||||
@ -118,7 +122,7 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
_.defaults(this.panel.legend, this.panelDefaults.legend);
|
_.defaults(this.panel.legend, this.panelDefaults.legend);
|
||||||
_.defaults(this.panel.xaxis, this.panelDefaults.xaxis);
|
_.defaults(this.panel.xaxis, this.panelDefaults.xaxis);
|
||||||
|
|
||||||
this.colors = $scope.$root.colors;
|
this.processor = new DataProcessor(this.panel);
|
||||||
|
|
||||||
this.events.on('render', this.onRender.bind(this));
|
this.events.on('render', this.onRender.bind(this));
|
||||||
this.events.on('data-received', this.onDataReceived.bind(this));
|
this.events.on('data-received', this.onDataReceived.bind(this));
|
||||||
@ -144,6 +148,7 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
'log (base 32)': 32,
|
'log (base 32)': 32,
|
||||||
'log (base 1024)': 1024
|
'log (base 1024)': 1024
|
||||||
};
|
};
|
||||||
|
|
||||||
this.unitFormats = kbn.getUnitFormats();
|
this.unitFormats = kbn.getUnitFormats();
|
||||||
|
|
||||||
this.xAxisModes = {
|
this.xAxisModes = {
|
||||||
@ -153,6 +158,14 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
'Json': 'json'
|
'Json': 'json'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.xAxisStatOptions = [
|
||||||
|
{text: 'Avg', value: 'avg'},
|
||||||
|
{text: 'Min', value: 'min'},
|
||||||
|
{text: 'Max', value: 'min'},
|
||||||
|
{text: 'Total', value: 'total'},
|
||||||
|
{text: 'Count', value: 'count'},
|
||||||
|
];
|
||||||
|
|
||||||
this.subTabIndex = 0;
|
this.subTabIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,25 +212,8 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
this.datapointsCount = 0;
|
this.datapointsCount = 0;
|
||||||
this.datapointsOutside = false;
|
this.datapointsOutside = false;
|
||||||
|
|
||||||
let dataHandler: (seriesData, index)=>any;
|
this.dataList = dataList;
|
||||||
switch (this.panel.xaxis.mode) {
|
this.seriesList = this.processor.getSeriesList({dataList: dataList, range: this.range});
|
||||||
case 'series':
|
|
||||||
case 'time': {
|
|
||||||
dataHandler = this.timeSeriesHandler;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'table': {
|
|
||||||
// Table panel uses only first enabled target, so we can use dataList[0]
|
|
||||||
dataList.splice(1, dataList.length - 1);
|
|
||||||
dataHandler = this.tableHandler;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'json': {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.seriesList = dataList.map(dataHandler.bind(this));
|
|
||||||
this.datapointsWarning = this.datapointsCount === 0 || this.datapointsOutside;
|
this.datapointsWarning = this.datapointsCount === 0 || this.datapointsOutside;
|
||||||
|
|
||||||
this.annotationsPromise.then(annotations => {
|
this.annotationsPromise.then(annotations => {
|
||||||
@ -230,73 +226,6 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
seriesHandler(seriesData, index, datapoints, alias) {
|
|
||||||
var colorIndex = index % this.colors.length;
|
|
||||||
var color = this.panel.aliasColors[alias] || this.colors[colorIndex];
|
|
||||||
|
|
||||||
var series = new TimeSeries({
|
|
||||||
datapoints: datapoints,
|
|
||||||
alias: alias,
|
|
||||||
color: color,
|
|
||||||
unit: seriesData.unit,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (datapoints && datapoints.length > 0) {
|
|
||||||
var last = moment.utc(datapoints[datapoints.length - 1][1]);
|
|
||||||
var from = moment.utc(this.range.from);
|
|
||||||
if (last - from < -10000) {
|
|
||||||
this.datapointsOutside = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.datapointsCount += datapoints.length;
|
|
||||||
this.panel.tooltip.msResolution = this.panel.tooltip.msResolution || series.isMsResolutionNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
return series;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeSeriesHandler(seriesData, index) {
|
|
||||||
var datapoints = seriesData.datapoints;
|
|
||||||
var alias = seriesData.target;
|
|
||||||
|
|
||||||
return this.seriesHandler(seriesData, index, datapoints, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
tableHandler(seriesData, index) {
|
|
||||||
var xColumnIndex = Number(this.panel.xaxis.columnIndex);
|
|
||||||
var valueColumnIndex = Number(this.panel.xaxis.valueColumnIndex);
|
|
||||||
var datapoints = _.map(seriesData.rows, (row) => {
|
|
||||||
var value = valueColumnIndex ? row[valueColumnIndex] : _.last(row);
|
|
||||||
return [
|
|
||||||
value, // Y value
|
|
||||||
row[xColumnIndex] // X value
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
var alias = seriesData.columns[valueColumnIndex].text;
|
|
||||||
|
|
||||||
return this.seriesHandler(seriesData, index, datapoints, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
esRawDocHandler(seriesData, index) {
|
|
||||||
let xField = this.panel.xaxis.esField;
|
|
||||||
let valueField = this.panel.xaxis.esValueField;
|
|
||||||
let datapoints = _.map(seriesData.datapoints, (doc) => {
|
|
||||||
return [
|
|
||||||
pluckDeep(doc, valueField), // Y value
|
|
||||||
pluckDeep(doc, xField) // X value
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove empty points
|
|
||||||
datapoints = _.filter(datapoints, (point) => {
|
|
||||||
return point[0] !== undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
var alias = valueField;
|
|
||||||
return this.seriesHandler(seriesData, index, datapoints, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRender() {
|
onRender() {
|
||||||
if (!this.seriesList) { return; }
|
if (!this.seriesList) { return; }
|
||||||
|
|
||||||
@ -380,13 +309,11 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from panel menu
|
|
||||||
toggleLegend() {
|
toggleLegend() {
|
||||||
this.panel.legend.show = !this.panel.legend.show;
|
this.panel.legend.show = !this.panel.legend.show;
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
legendValuesOptionChanged() {
|
legendValuesOptionChanged() {
|
||||||
var legend = this.panel.legend;
|
var legend = this.panel.legend;
|
||||||
legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
|
legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
|
||||||
@ -401,9 +328,21 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
fileExport.exportSeriesListToCsvColumns(this.seriesList);
|
fileExport.exportSeriesListToCsvColumns(this.seriesList);
|
||||||
}
|
}
|
||||||
|
|
||||||
xAxisModeChanged() {
|
xAxisOptionChanged() {
|
||||||
// set defaults
|
switch (this.panel.xaxis.mode) {
|
||||||
this.refresh();
|
case 'time': {
|
||||||
|
this.panel.tooltip.shared = true;
|
||||||
|
this.panel.xaxis.values = [];
|
||||||
|
this.onDataReceived(this.dataList);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'series': {
|
||||||
|
this.panel.tooltip.shared = false;
|
||||||
|
this.processor.validateXAxisSeriesValue();
|
||||||
|
this.onDataReceived(this.dataList);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getXAxisNameOptions() {
|
getXAxisNameOptions() {
|
||||||
@ -413,44 +352,8 @@ class GraphCtrl extends MetricsPanelCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getXAxisValueOptions() {
|
getXAxisValueOptions() {
|
||||||
return this.$q.when([
|
return this.$q.when(this.processor.getXAxisValueOptions({dataList: this.dataList}));
|
||||||
{text: 'Avg', value: 'avg'}
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFieldsFromESDoc(doc) {
|
|
||||||
let fields = [];
|
|
||||||
let fieldNameParts = [];
|
|
||||||
|
|
||||||
function getFieldsRecursive(obj) {
|
|
||||||
_.forEach(obj, (value, key) => {
|
|
||||||
if (_.isObject(value)) {
|
|
||||||
fieldNameParts.push(key);
|
|
||||||
getFieldsRecursive(value);
|
|
||||||
} else {
|
|
||||||
let field = fieldNameParts.concat(key).join('.');
|
|
||||||
fields.push(field);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fieldNameParts.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
getFieldsRecursive(doc);
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
function pluckDeep(obj: any, property: string) {
|
|
||||||
let propertyParts = property.split('.');
|
|
||||||
let value = obj;
|
|
||||||
for (let i = 0; i < propertyParts.length; ++i) {
|
|
||||||
if (value[propertyParts[i]]) {
|
|
||||||
value = value[propertyParts[i]];
|
|
||||||
} else {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export {GraphCtrl, GraphCtrl as PanelCtrl}
|
export {GraphCtrl, GraphCtrl as PanelCtrl}
|
||||||
|
@ -44,24 +44,20 @@
|
|||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-5">Mode</label>
|
<label class="gf-form-label width-5">Mode</label>
|
||||||
<div class="gf-form-select-wrapper max-width-15">
|
<div class="gf-form-select-wrapper max-width-15">
|
||||||
<select class="gf-form-input"
|
<select class="gf-form-input" ng-model="ctrl.panel.xaxis.mode" ng-options="v as k for (k, v) in ctrl.xAxisModes" ng-change="ctrl.xAxisOptionChanged()"> </select>
|
||||||
ng-model="ctrl.panel.xaxis.mode"
|
|
||||||
ng-options="v as k for (k, v) in ctrl.xAxisModes"
|
|
||||||
ng-change="ctrl.xAxisModeChanged()">
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Table mode -->
|
<!-- Table mode -->
|
||||||
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'table' || ctrl.panel.xaxis.mode === 'json'">
|
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'table' || ctrl.panel.xaxis.mode === 'json'">
|
||||||
<label class="gf-form-label width-5">Name</label>
|
<label class="gf-form-label width-5">Name</label>
|
||||||
<metric-segment-model property="ctrl.panel.xaxis.name" get-options="ctrl.getXAxisNameOptions()" on-change="ctrl.render()" custom="false" css-class="width-10" select-mode="true"></metric-segment-model>
|
<metric-segment-model property="ctrl.panel.xaxis.name" get-options="ctrl.getXAxisNameOptions()" on-change="ctrl.xAxisOptionChanged()" custom="false" css-class="width-10" select-mode="true"></metric-segment-model>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Series mode -->
|
<!-- Series mode -->
|
||||||
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode !== 'time'">
|
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'series'">
|
||||||
<label class="gf-form-label width-5">Value</label>
|
<label class="gf-form-label width-5">Value</label>
|
||||||
<metric-segment-model property="ctrl.panel.xaxis.values[0]" get-options="ctrl.getXAxisValueOptions()" on-change="ctrl.render()" custom="false" css-class="width-10" select-mode="true"></metric-segment-model>
|
<metric-segment-model property="ctrl.panel.xaxis.values[0]" options="ctrl.xAxisStatOptions" on-change="ctrl.xAxisOptionChanged()" custom="false" css-class="width-10" select-mode="true"></metric-segment-model>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user