mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(graph): more work on graph panel and support for non time series
This commit is contained in:
parent
cd270f14a2
commit
5682520603
@ -180,6 +180,7 @@ function (_, $, coreModule) {
|
||||
value: option ? option.text : value,
|
||||
selectMode: attrs.selectMode,
|
||||
};
|
||||
|
||||
return uiSegmentSrv.newSegment(segment);
|
||||
};
|
||||
|
||||
|
@ -49,9 +49,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Table mode -->
|
||||
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'custom'">
|
||||
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'field'">
|
||||
<label class="gf-form-label width-5">Name</label>
|
||||
<metric-segment-model property="ctrl.panel.xaxis.name" get-options="ctrl.getDataPropertyNames()" on-change="ctrl.xAxisOptionChanged()" custom="false" css-class="width-10" select-mode="true"></metric-segment-model>
|
||||
<metric-segment-model property="ctrl.panel.xaxis.name" get-options="ctrl.getDataFieldNames(false)" on-change="ctrl.xAxisOptionChanged()" custom="false" css-class="width-10" select-mode="true"></metric-segment-model>
|
||||
</div>
|
||||
|
||||
<!-- Series mode -->
|
||||
<div class="gf-form" ng-if="ctrl.panel.xaxis.mode === 'field'">
|
||||
<label class="gf-form-label width-5">Value</label>
|
||||
<metric-segment-model property="ctrl.panel.xaxis.values[0]" get-options="ctrl.getDataFieldNames(true)" on-change="ctrl.xAxisOptionChanged()" custom="false" css-class="width-10" select-mode="true"></metric-segment-model>
|
||||
</div>
|
||||
|
||||
<!-- Series mode -->
|
||||
|
@ -30,7 +30,7 @@ export class AxesEditorCtrl {
|
||||
this.xAxisModes = {
|
||||
'Time': 'time',
|
||||
'Series': 'series',
|
||||
'Custom': 'custom'
|
||||
'Data field': 'field',
|
||||
};
|
||||
|
||||
this.xAxisStatOptions = [
|
||||
@ -58,37 +58,15 @@ export class AxesEditorCtrl {
|
||||
}
|
||||
|
||||
xAxisOptionChanged() {
|
||||
switch (this.panel.xaxis.mode) {
|
||||
case 'time': {
|
||||
this.panel.bars = false;
|
||||
this.panel.lines = true;
|
||||
this.panel.points = false;
|
||||
this.panel.legend.show = true;
|
||||
this.panel.tooltip.shared = true;
|
||||
this.panel.xaxis.values = [];
|
||||
this.panelCtrl.onDataReceived(this.panelCtrl.dataList);
|
||||
break;
|
||||
}
|
||||
case 'series': {
|
||||
this.panel.bars = true;
|
||||
this.panel.lines = false;
|
||||
this.panel.points = false;
|
||||
this.panel.stack = false;
|
||||
this.panel.legend.show = false;
|
||||
this.panel.tooltip.shared = false;
|
||||
this.panelCtrl.processor.validateXAxisSeriesValue();
|
||||
this.panelCtrl.onDataReceived(this.panelCtrl.dataList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.panelCtrl.processor.setPanelDefaultsForNewXAxisMode();
|
||||
this.panelCtrl.onDataReceived(this.panelCtrl.dataList);
|
||||
}
|
||||
|
||||
getDataPropertyNames() {
|
||||
var props = this.panelCtrl.processor.getDocProperties(this.panelCtrl.dataList);
|
||||
getDataFieldNames(onlyNumbers) {
|
||||
var props = this.panelCtrl.processor.getDataFieldNames(this.panelCtrl.dataList, onlyNumbers);
|
||||
var items = props.map(prop => {
|
||||
return {text: prop};
|
||||
return {text: prop, value: prop};
|
||||
});
|
||||
console.log(items);
|
||||
|
||||
return this.$q.when(items);
|
||||
}
|
||||
|
@ -21,22 +21,60 @@ export class DataProcessor {
|
||||
var firstItem;
|
||||
if (options.dataList && options.dataList.length > 0) {
|
||||
firstItem = options.dataList[0];
|
||||
if (firstItem.type === 'docs') {
|
||||
this.panel.xaxis.mode = 'custom';
|
||||
let autoDetectMode = this.getAutoDetectXAxisMode(firstItem);
|
||||
if (this.panel.xaxis.mode !== autoDetectMode) {
|
||||
this.panel.xaxis.mode = autoDetectMode;
|
||||
this.setPanelDefaultsForNewXAxisMode();
|
||||
}
|
||||
}
|
||||
|
||||
switch (this.panel.xaxis.mode) {
|
||||
case 'series':
|
||||
case 'time': {
|
||||
case 'time': {
|
||||
return options.dataList.map(this.timeSeriesHandler.bind(this));
|
||||
}
|
||||
case 'custom': {
|
||||
case 'field': {
|
||||
return this.customHandler(firstItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getAutoDetectXAxisMode(firstItem) {
|
||||
switch (firstItem.type) {
|
||||
case 'docs': return 'field';
|
||||
case 'table': return 'field';
|
||||
default: {
|
||||
if (this.panel.xaxis.mode === 'series') {
|
||||
return 'series';
|
||||
}
|
||||
return 'time';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setPanelDefaultsForNewXAxisMode() {
|
||||
switch (this.panel.xaxis.mode) {
|
||||
case 'time': {
|
||||
this.panel.bars = false;
|
||||
this.panel.lines = true;
|
||||
this.panel.points = false;
|
||||
this.panel.legend.show = true;
|
||||
this.panel.tooltip.shared = true;
|
||||
this.panel.xaxis.values = [];
|
||||
break;
|
||||
}
|
||||
case 'series': {
|
||||
this.panel.bars = true;
|
||||
this.panel.lines = false;
|
||||
this.panel.points = false;
|
||||
this.panel.stack = false;
|
||||
this.panel.legend.show = false;
|
||||
this.panel.tooltip.shared = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seriesHandler(seriesData, index, datapoints, alias) {
|
||||
var colorIndex = index % colors.length;
|
||||
var color = this.panel.aliasColors[alias] || colors[colorIndex];
|
||||
@ -71,21 +109,21 @@ export class DataProcessor {
|
||||
throw {message: 'No field name specified to use for x-axis, check your axes settings'};
|
||||
}
|
||||
|
||||
// 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;
|
||||
// re
|
||||
// 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;
|
||||
// re
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -142,18 +180,37 @@ export class DataProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
getDocProperties(dataList) {
|
||||
getDataFieldNames(dataList, onlyNumbers) {
|
||||
if (dataList.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let fields = [];
|
||||
var firstItem = dataList[0];
|
||||
if (firstItem.type === 'docs'){
|
||||
if (firstItem.datapoints.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return this.getPropertiesFromDoc(firstItem.datapoints[0]);
|
||||
let fieldParts = [];
|
||||
|
||||
function getPropertiesRecursive(obj) {
|
||||
_.forEach(obj, (value, key) => {
|
||||
if (_.isObject(value)) {
|
||||
fieldParts.push(key);
|
||||
getPropertiesRecursive(value);
|
||||
} else {
|
||||
if (!onlyNumbers || _.isNumber(value)) {
|
||||
let field = fieldParts.concat(key).join('.');
|
||||
fields.push(field);
|
||||
}
|
||||
}
|
||||
});
|
||||
fieldParts.pop();
|
||||
}
|
||||
|
||||
getPropertiesRecursive(firstItem.datapoints[0]);
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,27 +231,6 @@ export class DataProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
getPropertiesFromDoc(doc) {
|
||||
let props = [];
|
||||
let propParts = [];
|
||||
|
||||
function getPropertiesRecursive(obj) {
|
||||
_.forEach(obj, (value, key) => {
|
||||
if (_.isObject(value)) {
|
||||
propParts.push(key);
|
||||
getPropertiesRecursive(value);
|
||||
} else {
|
||||
let field = propParts.concat(key).join('.');
|
||||
props.push(field);
|
||||
}
|
||||
});
|
||||
propParts.pop();
|
||||
}
|
||||
|
||||
getPropertiesRecursive(doc);
|
||||
return props;
|
||||
}
|
||||
|
||||
pluckDeep(obj: any, property: string) {
|
||||
let propertyParts = property.split('.');
|
||||
let value = obj;
|
||||
|
@ -258,29 +258,26 @@ function (angular, $, moment, _, kbn, GraphTooltip, thresholdManExports) {
|
||||
}
|
||||
}
|
||||
|
||||
if (panel.xaxis.mode === 'series') {
|
||||
if (data.length) {
|
||||
switch(panel.xaxis.mode) {
|
||||
case 'series': {
|
||||
options.series.bars.barWidth = 0.7;
|
||||
options.series.bars.align = 'center';
|
||||
addXSeriesAxis(options);
|
||||
break;
|
||||
}
|
||||
|
||||
addXSeriesAxis(options);
|
||||
|
||||
} else if (panel.xaxis.mode === 'table' ||
|
||||
panel.xaxis.mode === 'elastic') {
|
||||
if (data.length) {
|
||||
case 'table': {
|
||||
options.series.bars.barWidth = 0.7;
|
||||
options.series.bars.align = 'center';
|
||||
addXTableAxis(options);
|
||||
break;
|
||||
}
|
||||
|
||||
addXTableAxis(options);
|
||||
|
||||
} else {
|
||||
if (data.length && data[0].stats.timeStep) {
|
||||
options.series.bars.barWidth = data[0].stats.timeStep / 1.5;
|
||||
default: {
|
||||
if (data.length && data[0].stats.timeStep) {
|
||||
options.series.bars.barWidth = data[0].stats.timeStep / 1.5;
|
||||
}
|
||||
addTimeAxis(options);
|
||||
break;
|
||||
}
|
||||
|
||||
addTimeAxis(options);
|
||||
}
|
||||
|
||||
thresholdManager.addPlotOptions(options, panel);
|
||||
|
@ -28,11 +28,37 @@ describe('Graph DataProcessor', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('Should automatically set xaxis mode to custom', () => {
|
||||
expect(panel.xaxis.mode).to.be('custom');
|
||||
it('Should automatically set xaxis mode to field', () => {
|
||||
expect(panel.xaxis.mode).to.be('field');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('getDataFieldNames(', () => {
|
||||
var dataList = [{
|
||||
type: 'docs', datapoints: [
|
||||
{
|
||||
hostname: "server1",
|
||||
valueField: 11,
|
||||
nested: {
|
||||
prop1: 'server2', value2: 23}
|
||||
}
|
||||
]
|
||||
}];
|
||||
|
||||
it('Should return all field names', () => {
|
||||
var fields = processor.getDataFieldNames(dataList, false);
|
||||
expect(fields).to.contain('hostname');
|
||||
expect(fields).to.contain('valueField');
|
||||
expect(fields).to.contain('nested.prop1');
|
||||
expect(fields).to.contain('nested.value2');
|
||||
});
|
||||
|
||||
it('Should return all number fields', () => {
|
||||
var fields = processor.getDataFieldNames(dataList, true);
|
||||
expect(fields).to.contain('valueField');
|
||||
expect(fields).to.contain('nested.value2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user