Commit 867b8380 by Torkel Ödegaard

feat(tablepanel): work on table panel

parent da9c792c
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
<div class="editor-row"> <div class="editor-row">
<div class="section"> <div class="section">
<h5>Series specific overrides <tip>Regex match example: /server[0-3]/i </tip></h5> <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"> <div class="tight-form" ng-repeat="override in panel.seriesOverrides" ng-controller="SeriesOverridesCtrl">
<ul class="tight-form-list"> <ul class="tight-form-list">
<li class="tight-form-item"> <li class="tight-form-item">
......
...@@ -6,16 +6,13 @@ import _ = require('lodash'); ...@@ -6,16 +6,13 @@ import _ = require('lodash');
import moment = require('moment'); import moment = require('moment');
import PanelMeta = require('app/features/panel/panel_meta'); import PanelMeta = require('app/features/panel/panel_meta');
import TimeSeries = require('app/core/time_series'); import TimeSeries = require('app/core/time_series');
import {TableModel} from './table_model'; import {TableModel, transformers} from './table_model';
var panelDefaults = {
targets: [{}],
};
export class TablePanelCtrl { export class TablePanelCtrl {
constructor($scope, $rootScope, $q, panelSrv, panelHelper) { constructor($scope, $rootScope, $q, panelSrv, panelHelper) {
$scope.ctrl = this; $scope.ctrl = this;
$scope.transformers = transformers;
$scope.panelMeta = new PanelMeta({ $scope.panelMeta = new PanelMeta({
panelName: 'Table', panelName: 'Table',
...@@ -27,21 +24,31 @@ export class TablePanelCtrl { ...@@ -27,21 +24,31 @@ export class TablePanelCtrl {
$scope.panelMeta.addEditorTab('Options', 'app/panels/table/options.html'); $scope.panelMeta.addEditorTab('Options', 'app/panels/table/options.html');
$scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html'); $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
var panelDefaults = {
targets: [{}],
transform: 'timeseries_to_rows'
};
_.defaults($scope.panel, panelDefaults); _.defaults($scope.panel, panelDefaults);
$scope.refreshData = function(datasource) { $scope.refreshData = function(datasource) {
panelHelper.updateTimeRange($scope); panelHelper.updateTimeRange($scope);
return panelHelper.issueMetricQuery($scope, datasource) return panelHelper.issueMetricQuery($scope, datasource)
.then($scope.dataHandler, function(err) { .then($scope.dataHandler, function(err) {
$scope.seriesList = []; $scope.seriesList = [];
$scope.render([]); $scope.render([]);
throw err; throw err;
}); });
}; };
$scope.dataHandler = function(results) { $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); panelHelper.broadcastRender($scope, $scope.tableModel);
}; };
......
<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>
...@@ -4,25 +4,62 @@ import {TableModel} from '../table_model'; ...@@ -4,25 +4,62 @@ import {TableModel} from '../table_model';
describe('when getting tableData', () => { describe('when getting tableData', () => {
describe('simple time series', () => { describe('timeseries_to_rows', () => {
var panel = { var panel = {
transform: 'timeseries_to_rows'
}; };
it ('should return 2 columns', () => { it ('should return 2 rows', () => {
var data = TableModel.transform([ var data = TableModel.transform([
{ {
target: 'test', target: 'series1',
datapoints: [[12.12, new Date().getTime()]],
},
{
target: 'series2',
datapoints: [[12.12, new Date().getTime()]], datapoints: [[12.12, new Date().getTime()]],
} }
], panel); ], panel);
expect(data.columns.length).to.be(2); expect(data.columns.length).to.be(3);
expect(data.rows.length).to.be(1); expect(data.rows.length).to.be(2);
expect(data.columns[0].text).to.be('Time'); expect(data.columns[0].text).to.be('Time');
expect(data.columns[1].text).to.be('Value'); 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('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');
});
}); });
}); });
...@@ -3,21 +3,17 @@ ...@@ -3,21 +3,17 @@
import moment = require('moment'); import moment = require('moment');
import _ = require('lodash'); import _ = require('lodash');
export class TableModel { var transformers = {};
columns: any[];
rows: any[];
static transform(data, panel) {
var model = new TableModel();
if (!data || data.length === 0) {
return model;
}
transformers['timeseries_to_rows'] = {
description: 'Time series to rows',
transform: function(data, panel, model) {
model.columns = [ model.columns = [
{text: 'Time'}, {text: 'Time'},
{text: 'Series'},
{text: 'Value'}, {text: 'Value'},
]; ];
model.rows = []; model.rows = [];
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
...@@ -32,12 +28,71 @@ export class TableModel { ...@@ -32,12 +28,71 @@ export class TableModel {
value = value.toFixed(2); value = value.toFixed(2);
} }
model.rows.push([time, value]); model.rows.push([time, series.target, value]);
} }
} }
},
};
return model; 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;
}
}
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
.gf-table-panel { .gf-table-panel {
width: 100%; width: 100%;
table-layout: fixed;
border-collapse: collapse; border-collapse: collapse;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment