feat(tablepanel): work on table panel

This commit is contained in:
Torkel Ödegaard 2015-11-03 16:19:51 +01:00
parent da9c792ca2
commit 867b838053
6 changed files with 188 additions and 32 deletions

View File

@ -63,7 +63,7 @@
<div class="editor-row">
<div class="section">
<h5>Series specific overrides <tip>Regex match example: /server[0-3]/i </tip></h5>
<div>
<div class="tight-form-container">
<div class="tight-form" ng-repeat="override in panel.seriesOverrides" ng-controller="SeriesOverridesCtrl">
<ul class="tight-form-list">
<li class="tight-form-item">

View File

@ -6,16 +6,13 @@ import _ = require('lodash');
import moment = require('moment');
import PanelMeta = require('app/features/panel/panel_meta');
import TimeSeries = require('app/core/time_series');
import {TableModel} from './table_model';
var panelDefaults = {
targets: [{}],
};
import {TableModel, transformers} from './table_model';
export class TablePanelCtrl {
constructor($scope, $rootScope, $q, panelSrv, panelHelper) {
$scope.ctrl = this;
$scope.transformers = transformers;
$scope.panelMeta = new PanelMeta({
panelName: 'Table',
@ -27,21 +24,31 @@ export class TablePanelCtrl {
$scope.panelMeta.addEditorTab('Options', 'app/panels/table/options.html');
$scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
var panelDefaults = {
targets: [{}],
transform: 'timeseries_to_rows'
};
_.defaults($scope.panel, panelDefaults);
$scope.refreshData = function(datasource) {
panelHelper.updateTimeRange($scope);
return panelHelper.issueMetricQuery($scope, datasource)
.then($scope.dataHandler, function(err) {
$scope.seriesList = [];
$scope.render([]);
throw err;
});
.then($scope.dataHandler, function(err) {
$scope.seriesList = [];
$scope.render([]);
throw err;
});
};
$scope.dataHandler = function(results) {
$scope.tableModel = TableModel.transform(results.data, $scope.panel);
$scope.dataRaw = results.data;
$scope.render();
};
$scope.render = function() {
$scope.tableModel = TableModel.transform($scope.dataRaw, $scope.panel);
panelHelper.broadcastRender($scope, $scope.tableModel);
};

View File

@ -0,0 +1,58 @@
<div class="editor-row">
<div class="tight-form-section">
<h5>Data Table</h5>
<div class="tight-form">
<ul class="tight-form-list">
<li class="tight-form-item" style="width: 170px">
Data to Table Transform
</li>
<li>
<select class="input-xlarge tight-form-input"
ng-model="panel.transform"
ng-options="k as v.description for (k, v) in transformers"
ng-change="render()"></select>
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
</div>
<div class="editor-row">
<div class="tight-form-section">
<h5>Table Display</h5>
</div>
</div>
<div class="editor-row">
<div class="tight-form-section">
<h5>Column Styles</h5>
<div class="tight-form-container">
<div class="tight-form" ng-repeat="column panel.columns">
<ul class="tight-form-list">
<li class="tight-form-item">
<i class="fa fa-remove pointer" ng-click="removeSeriesOverride(override)"></i>
</li>
<li class="tight-form-item">
alias or regex
</li>
<li>
<input type="text" ng-model="override.alias" bs-typeahead="getColumnNames" ng-blur="render()" data-min-length=0 data-items=100 class="input-medium tight-form-input" >
</li>
<li class="dropdown" dropdown-typeahead="overrideMenu" dropdown-typeahead-on-select="setOverride($item, $subItem)">
</li>
</ul>
<div class="clearfix"></div>
</div>
</div>
<button class="btn btn-inverse" style="margin-top: 20px" ng-click="addSeriesOverride()">
Add column display rule
</button>
</div>
</div>

View File

@ -4,25 +4,62 @@ import {TableModel} from '../table_model';
describe('when getting tableData', () => {
describe('simple time series', () => {
describe('timeseries_to_rows', () => {
var panel = {
transform: 'timeseries_to_rows'
};
it ('should return 2 columns', () => {
it ('should return 2 rows', () => {
var data = TableModel.transform([
{
target: 'test',
target: 'series1',
datapoints: [[12.12, new Date().getTime()]],
},
{
target: 'series2',
datapoints: [[12.12, new Date().getTime()]],
}
], panel);
expect(data.columns.length).to.be(2);
expect(data.columns.length).to.be(3);
expect(data.rows.length).to.be(2);
expect(data.columns[0].text).to.be('Time');
expect(data.columns[1].text).to.be('Series');
expect(data.columns[2].text).to.be('Value');
expect(data.rows[0][1]).to.be('series1');
expect(data.rows[0][2]).to.be('12.12');
expect(data.rows[1][1]).to.be('series2');
});
});
describe('timeseries_to_rows', () => {
var panel = {
transform: 'timeseries_to_columns'
};
it ('should return 3 columns', () => {
var data = TableModel.transform([
{
target: 'series1',
datapoints: [[12.12, new Date().getTime()]],
},
{
target: 'series2',
datapoints: [[16.12, new Date().getTime()]],
}
], panel);
expect(data.columns.length).to.be(3);
expect(data.rows.length).to.be(1);
expect(data.columns[0].text).to.be('Time');
expect(data.columns[1].text).to.be('Value');
expect(data.columns[1].text).to.be('series1');
expect(data.columns[2].text).to.be('series2');
expect(data.rows[0][1]).to.be('12.12');
expect(data.rows[0][2]).to.be('16.12');
});
});
});

View File

@ -3,21 +3,17 @@
import moment = require('moment');
import _ = require('lodash');
export class TableModel {
columns: any[];
rows: any[];
static transform(data, panel) {
var model = new TableModel();
if (!data || data.length === 0) {
return model;
}
var transformers = {};
transformers['timeseries_to_rows'] = {
description: 'Time series to rows',
transform: function(data, panel, model) {
model.columns = [
{text: 'Time'},
{text: 'Series'},
{text: 'Value'},
];
model.rows = [];
for (var i = 0; i < data.length; i++) {
@ -32,12 +28,71 @@ export class TableModel {
value = value.toFixed(2);
}
model.rows.push([time, value]);
model.rows.push([time, series.target, value]);
}
}
},
};
transformers['timeseries_to_columns'] = {
description: 'Time series to columns',
transform: function(data, panel, model) {
model.columns = [{text: 'Time'}];
model.rows = [];
var points = {};
for (var i = 0; i < data.length; i++) {
var series = data[i];
model.columns.push({text: series.target});
for (var y = 0; y < series.datapoints.length; y++) {
var dp = series.datapoints[y];
var time = dp[1];
if (!points[time]) {
points[time] = {};
points[time][i] = [dp[0]];
}
else {
points[time][i] = dp[0];
}
}
}
for (var time in points) {
var point = points[time];
var values = [time];
for (var i = 0; i < data.length; i++) {
if (point[i] !== undefined) {
values.push(point[i]);
}
}
model.rows.push(values);
}
}
};
export {transformers}
export class TableModel {
columns: any[];
rows: any[];
static transform(data, panel) {
var model = new TableModel();
if (!data || data.length === 0) {
return model;
}
var transformer = transformers[panel.transform];
if (!transformer) {
throw {message: 'Transformer ' + panel.transformer + ' not found'};
}
transformer.transform(data, panel, model);
return model;
}
}

View File

@ -17,7 +17,6 @@
.gf-table-panel {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}