diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts
index 8e3dd9d09f2..398a6f50233 100644
--- a/public/app/features/panel/panel_ctrl.ts
+++ b/public/app/features/panel/panel_ctrl.ts
@@ -80,13 +80,16 @@ export class PanelCtrl {
return;
}
- addEditorTab(title, templateUrl) {
- this.editorTabs.push({
- title: title,
- directiveFn: function() {
- return {templateUrl: templateUrl};
- }
- });
+ addEditorTab(title, directiveFn) {
+ var editorTab = {title, directiveFn};
+
+ if (_.isString(directiveFn)) {
+ editorTab.directiveFn = function() {
+ return {templateUrl: directiveFn};
+ };
+ }
+
+ this.editorTabs.push(editorTab);
}
getMenu() {
diff --git a/public/app/plugins/panel/table/controller.ts b/public/app/plugins/panel/table/controller.ts
index 376f36fd84d..9b06b437db9 100644
--- a/public/app/plugins/panel/table/controller.ts
+++ b/public/app/plugins/panel/table/controller.ts
@@ -4,132 +4,131 @@ import angular from 'angular';
import _ from 'lodash';
import moment from 'moment';
import * as FileExport from 'app/core/utils/file_export';
-import PanelMeta from 'app/features/panel/panel_meta2';
+import {MetricsPanelCtrl} from '../../../features/panel/panel';
import {transformDataToTable} from './transformers';
+import {tablePanelEditor} from './editor';
-export class TablePanelCtrl {
+var panelDefaults = {
+ targets: [{}],
+ transform: 'timeseries_to_columns',
+ pageSize: null,
+ showHeader: true,
+ styles: [
+ {
+ type: 'date',
+ pattern: 'Time',
+ dateFormat: 'YYYY-MM-DD HH:mm:ss',
+ },
+ {
+ unit: 'short',
+ type: 'number',
+ decimals: 2,
+ colors: ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
+ colorMode: null,
+ pattern: '/.*/',
+ thresholds: [],
+ }
+ ],
+ columns: [],
+ scroll: true,
+ fontSize: '100%',
+ sort: {col: 0, desc: true},
+};
+
+export class TablePanelCtrl extends MetricsPanelCtrl {
+ pageIndex: number;
+ dataRaw: any;
+ table: any;
/** @ngInject */
- constructor($scope, $rootScope, $q, panelSrv, panelHelper, annotationsSrv) {
- $scope.ctrl = this;
- $scope.pageIndex = 0;
+ constructor($scope, $injector, private annotationsSrv) {
+ super($scope, $injector);
+ this.pageIndex = 0;
- $scope.panelMeta = new PanelMeta({
- panelName: 'Table',
- editIcon: "fa fa-table",
- fullscreen: true,
- metricsEditor: true,
- });
+ if (this.panel.styles === void 0) {
+ this.panel.styles = this.panel.columns;
+ this.panel.columns = this.panel.fields;
+ delete this.panel.columns;
+ delete this.panel.fields;
+ }
- $scope.panelMeta.addEditorTab('Options', 'app/plugins/panel/table/options.html');
- $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
- $scope.panelMeta.addExtendedMenuItem('Export CSV', '', 'exportCsv()');
+ _.defaults(this.panel, panelDefaults);
+ }
- var panelDefaults = {
- targets: [{}],
- transform: 'timeseries_to_columns',
- pageSize: null,
- showHeader: true,
- styles: [
- {
- type: 'date',
- pattern: 'Time',
- dateFormat: 'YYYY-MM-DD HH:mm:ss',
- },
- {
- unit: 'short',
- type: 'number',
- decimals: 2,
- colors: ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
- colorMode: null,
- pattern: '/.*/',
- thresholds: [],
- }
- ],
- columns: [],
- scroll: true,
- fontSize: '100%',
- sort: {col: 0, desc: true},
- };
+ initEditMode() {
+ super.initEditMode();
+ this.addEditorTab('Options', tablePanelEditor);
+ this.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
+ }
- $scope.init = function() {
- if ($scope.panel.styles === void 0) {
- $scope.panel.styles = $scope.panel.columns;
- $scope.panel.columns = $scope.panel.fields;
- delete $scope.panel.columns;
- delete $scope.panel.fields;
- }
+ getExtendedMenu() {
+ var menu = super.getExtendedMenu();
+ menu.push({text: 'Export CSV', click: 'exportCsv()'});
+ return menu;
+ }
- _.defaults($scope.panel, panelDefaults);
- panelSrv.init($scope);
- };
+ refreshData(datasource) {
+ this.pageIndex = 0;
- $scope.refreshData = function(datasource) {
- panelHelper.updateTimeRange($scope);
-
- $scope.pageIndex = 0;
-
- if ($scope.panel.transform === 'annotations') {
- return annotationsSrv.getAnnotations($scope.dashboard).then(annotations => {
- $scope.dataRaw = annotations;
- $scope.render();
- });
- }
-
- return panelHelper.issueMetricQuery($scope, datasource)
- .then($scope.dataHandler, function(err) {
- $scope.render();
- throw err;
+ if (this.panel.transform === 'annotations') {
+ return this.annotationsSrv.getAnnotations(this.dashboard).then(annotations => {
+ this.dataRaw = annotations;
+ this.render();
});
- };
+ }
- $scope.toggleColumnSort = function(col, colIndex) {
- if ($scope.panel.sort.col === colIndex) {
- if ($scope.panel.sort.desc) {
- $scope.panel.sort.desc = false;
- } else {
- $scope.panel.sort.col = null;
- }
+ return this.issueQueries(datasource)
+ .then(this.dataHandler.bind(this))
+ .catch(err => {
+ this.render();
+ throw err;
+ });
+ }
+
+ toggleColumnSort(col, colIndex) {
+ if (this.panel.sort.col === colIndex) {
+ if (this.panel.sort.desc) {
+ this.panel.sort.desc = false;
} else {
- $scope.panel.sort.col = colIndex;
- $scope.panel.sort.desc = true;
+ this.panel.sort.col = null;
}
+ } else {
+ this.panel.sort.col = colIndex;
+ this.panel.sort.desc = true;
+ }
- $scope.render();
- };
+ this.render();
+ }
- $scope.dataHandler = function(results) {
- $scope.dataRaw = results.data;
- $scope.pageIndex = 0;
- $scope.render();
- };
+ dataHandler(results) {
+ this.dataRaw = results.data;
+ this.pageIndex = 0;
+ this.render();
+ }
- $scope.render = function() {
- // automatically correct transform mode
- // based on data
- if ($scope.dataRaw && $scope.dataRaw.length) {
- if ($scope.dataRaw[0].type === 'table') {
- $scope.panel.transform = 'table';
+ render() {
+ // automatically correct transform mode
+ // based on data
+ if (this.dataRaw && this.dataRaw.length) {
+ if (this.dataRaw[0].type === 'table') {
+ this.panel.transform = 'table';
+ } else {
+ if (this.dataRaw[0].type === 'docs') {
+ this.panel.transform = 'json';
} else {
- if ($scope.dataRaw[0].type === 'docs') {
- $scope.panel.transform = 'json';
- } else {
- if ($scope.panel.transform === 'table' || $scope.panel.transform === 'json') {
- $scope.panel.transform = 'timeseries_to_rows';
- }
+ if (this.panel.transform === 'table' || this.panel.transform === 'json') {
+ this.panel.transform = 'timeseries_to_rows';
}
}
}
+ }
- $scope.table = transformDataToTable($scope.dataRaw, $scope.panel);
- $scope.table.sort($scope.panel.sort);
- panelHelper.broadcastRender($scope, $scope.table, $scope.dataRaw);
- };
+ this.table = transformDataToTable(this.dataRaw, this.panel);
+ this.table.sort(this.panel.sort);
+ this.broadcastRender(this.table);
+ }
- $scope.exportCsv = function() {
- FileExport.exportTableDataToCsv($scope.table);
- };
-
- $scope.init();
+ exportCsv() {
+ FileExport.exportTableDataToCsv(this.table);
}
}
diff --git a/public/app/plugins/panel/table/editor.html b/public/app/plugins/panel/table/editor.html
index 0b13c61c884..010c30326d9 100644
--- a/public/app/plugins/panel/table/editor.html
+++ b/public/app/plugins/panel/table/editor.html
@@ -9,9 +9,9 @@
+ ng-model="editor.panel.transform"
+ ng-options="k as v.description for (k, v) in editor.transformers"
+ ng-change="editor.transformChanged()">
@@ -21,14 +21,14 @@
Columns
-
-
+
+
{{column.text}}
-
+
@@ -46,16 +46,16 @@
+ empty-to-null ng-model="editor.panel.pageSize" ng-change="editor.render()" ng-model-onblur>
-
+
Font size
-
+
@@ -68,11 +68,11 @@
Column Styles
-
+
-
diff --git a/public/app/plugins/panel/table/editor.ts b/public/app/plugins/panel/table/editor.ts
index 42536642d4a..dde691b00f3 100644
--- a/public/app/plugins/panel/table/editor.ts
+++ b/public/app/plugins/panel/table/editor.ts
@@ -10,105 +10,123 @@ import {transformers} from './transformers';
import kbn from 'app/core/utils/kbn';
export class TablePanelEditorCtrl {
+ panel: any;
+ panelCtrl: any;
+ transformers: any;
+ colorModes: any;
+ columnStyles: any;
+ columnTypes: any;
+ fontSizes: any;
+ dateFormats: any;
+ addColumnSegment: any;
+ unitFormats: any;
+ getColumnNames: any;
/** @ngInject */
- constructor($scope, $q, uiSegmentSrv) {
- $scope.transformers = transformers;
- $scope.unitFormats = kbn.getUnitFormats();
- $scope.colorModes = [
+ constructor($scope, private $q, private uiSegmentSrv) {
+ $scope.editor = this;
+ this.panelCtrl = $scope.ctrl;
+ this.panel = this.panelCtrl.panel;
+ this.transformers = transformers;
+ this.unitFormats = kbn.getUnitFormats();
+ this.colorModes = [
{text: 'Disabled', value: null},
{text: 'Cell', value: 'cell'},
{text: 'Value', value: 'value'},
{text: 'Row', value: 'row'},
];
- $scope.columnTypes = [
+ this.columnTypes = [
{text: 'Number', value: 'number'},
{text: 'String', value: 'string'},
{text: 'Date', value: 'date'},
];
- $scope.fontSizes = ['80%', '90%', '100%', '110%', '120%', '130%', '150%', '160%', '180%', '200%', '220%', '250%'];
- $scope.dateFormats = [
+ this.fontSizes = ['80%', '90%', '100%', '110%', '120%', '130%', '150%', '160%', '180%', '200%', '220%', '250%'];
+ this.dateFormats = [
{text: 'YYYY-MM-DD HH:mm:ss', value: 'YYYY-MM-DD HH:mm:ss'},
{text: 'MM/DD/YY h:mm:ss a', value: 'MM/DD/YY h:mm:ss a'},
{text: 'MMMM D, YYYY LT', value: 'MMMM D, YYYY LT'},
];
- $scope.addColumnSegment = uiSegmentSrv.newPlusButton();
+ this.addColumnSegment = uiSegmentSrv.newPlusButton();
- $scope.getColumnOptions = function() {
- if (!$scope.dataRaw) {
- return $q.when([]);
- }
- var columns = transformers[$scope.panel.transform].getColumns($scope.dataRaw);
- var segments = _.map(columns, (c: any) => uiSegmentSrv.newSegment({value: c.text}));
- return $q.when(segments);
- };
-
- $scope.addColumn = function() {
- var columns = transformers[$scope.panel.transform].getColumns($scope.dataRaw);
- var column = _.findWhere(columns, {text: $scope.addColumnSegment.value});
-
- if (column) {
- $scope.panel.columns.push(column);
- $scope.render();
- }
-
- var plusButton = uiSegmentSrv.newPlusButton();
- $scope.addColumnSegment.html = plusButton.html;
- $scope.addColumnSegment.value = plusButton.value;
- };
-
- $scope.transformChanged = function() {
- $scope.panel.columns = [];
- $scope.render();
- };
-
- $scope.removeColumn = function(column) {
- $scope.panel.columns = _.without($scope.panel.columns, column);
- $scope.render();
- };
-
- $scope.setUnitFormat = function(column, subItem) {
- column.unit = subItem.value;
- $scope.render();
- };
-
- $scope.addColumnStyle = function() {
- var columnStyleDefaults = {
- unit: 'short',
- type: 'number',
- decimals: 2,
- colors: ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
- colorMode: null,
- pattern: '/.*/',
- dateFormat: 'YYYY-MM-DD HH:mm:ss',
- thresholds: [],
- };
-
- $scope.panel.styles.push(angular.copy(columnStyleDefaults));
- };
-
- $scope.removeColumnStyle = function(style) {
- $scope.panel.styles = _.without($scope.panel.styles, style);
- };
-
- $scope.getColumnNames = function() {
- if (!$scope.table) {
+ // this is used from bs-typeahead and needs to be instance bound
+ this.getColumnNames = () => {
+ if (!this.panelCtrl.table) {
return [];
}
- return _.map($scope.table.columns, function(col: any) {
+ return _.map(this.panelCtrl.table.columns, function(col: any) {
return col.text;
});
};
+ }
- $scope.invertColorOrder = function(index) {
- var ref = $scope.panel.styles[index].colors;
- var copy = ref[0];
- ref[0] = ref[2];
- ref[2] = copy;
- $scope.render();
+ getColumnOptions() {
+ if (!this.panelCtrl.dataRaw) {
+ return this.$q.when([]);
+ }
+ var columns = this.transformers[this.panel.transform].getColumns(this.panelCtrl.dataRaw);
+ var segments = _.map(columns, (c: any) => this.uiSegmentSrv.newSegment({value: c.text}));
+ return this.$q.when(segments);
+ }
+
+ addColumn() {
+ var columns = transformers[this.panel.transform].getColumns(this.panelCtrl.dataRaw);
+ var column = _.findWhere(columns, {text: this.addColumnSegment.value});
+
+ if (column) {
+ this.panel.columns.push(column);
+ this.render();
+ }
+
+ var plusButton = this.uiSegmentSrv.newPlusButton();
+ this.addColumnSegment.html = plusButton.html;
+ this.addColumnSegment.value = plusButton.value;
+ }
+
+ transformChanged() {
+ this.panel.columns = [];
+ this.render();
+ }
+
+ render() {
+ this.panelCtrl.render();
+ }
+
+ removeColumn(column) {
+ this.panel.columns = _.without(this.panel.columns, column);
+ this.panelCtrl.render();
+ }
+
+ setUnitFormat(column, subItem) {
+ column.unit = subItem.value;
+ this.panelCtrl.render();
+ };
+
+ addColumnStyle() {
+ var columnStyleDefaults = {
+ unit: 'short',
+ type: 'number',
+ decimals: 2,
+ colors: ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"],
+ colorMode: null,
+ pattern: '/.*/',
+ dateFormat: 'YYYY-MM-DD HH:mm:ss',
+ thresholds: [],
};
+ this.panel.styles.push(angular.copy(columnStyleDefaults));
+ }
+
+ removeColumnStyle(style) {
+ this.panel.styles = _.without(this.panel.styles, style);
+ }
+
+ invertColorOrder(index) {
+ var ref = this.panel.styles[index].colors;
+ var copy = ref[0];
+ ref[0] = ref[2];
+ ref[2] = copy;
+ this.panelCtrl.render();
}
}
diff --git a/public/app/plugins/panel/table/module.html b/public/app/plugins/panel/table/module.html
index 75b9b4ce136..0c69fe6cb9b 100644
--- a/public/app/plugins/panel/table/module.html
+++ b/public/app/plugins/panel/table/module.html
@@ -1,28 +1,24 @@
-
-
-
-
-
+
+
diff --git a/public/app/plugins/panel/table/module.ts b/public/app/plugins/panel/table/module.ts
index 834bea42ba5..0903275b802 100644
--- a/public/app/plugins/panel/table/module.ts
+++ b/public/app/plugins/panel/table/module.ts
@@ -5,103 +5,96 @@ import kbn = require('app/core/utils/kbn');
import _ from 'lodash';
import $ from 'jquery';
import moment from 'moment';
-import angular from 'angular';
+import {PanelDirective} from '../../../features/panel/panel';
import {TablePanelCtrl} from './controller';
import {TableRenderer} from './renderer';
-import {tablePanelEditor} from './editor';
-angular.module('grafana.directives').directive('grafanaPanelTableEditor', tablePanelEditor);
+class TablePanel extends PanelDirective {
+ templateUrl = 'app/plugins/panel/table/module.html';
+ controller = TablePanelCtrl;
-function tablePanel() {
- 'use strict';
- return {
- restrict: 'E',
- templateUrl: 'app/plugins/panel/table/module.html',
- controller: TablePanelCtrl,
- link: function(scope, elem) {
- var data;
- var panel = scope.panel;
- var pageCount = 0;
- var formaters = [];
+ link(scope, elem, attrs, ctrl) {
+ var data;
+ var panel = ctrl.panel;
+ var pageCount = 0;
+ var formaters = [];
- function getTableHeight() {
- var panelHeight = scope.height || scope.panel.height || scope.row.height;
- if (_.isString(panelHeight)) {
- panelHeight = parseInt(panelHeight.replace('px', ''), 10);
- }
- if (pageCount > 1) {
- panelHeight -= 28;
- }
-
- return (panelHeight - 60) + 'px';
+ function getTableHeight() {
+ var panelHeight = ctrl.height || ctrl.panel.height || ctrl.row.height;
+ if (_.isString(panelHeight)) {
+ panelHeight = parseInt(panelHeight.replace('px', ''), 10);
+ }
+ if (pageCount > 1) {
+ panelHeight -= 28;
}
- function appendTableRows(tbodyElem) {
- var renderer = new TableRenderer(panel, data, scope.dashboard.timezone);
- tbodyElem.empty();
- tbodyElem.html(renderer.render(scope.pageIndex));
- }
-
- function switchPage(e) {
- var el = $(e.currentTarget);
- scope.pageIndex = (parseInt(el.text(), 10)-1);
- renderPanel();
- }
-
- function appendPaginationControls(footerElem) {
- footerElem.empty();
-
- var pageSize = panel.pageSize || 100;
- pageCount = Math.ceil(data.rows.length / pageSize);
- if (pageCount === 1) {
- return;
- }
-
- var startPage = Math.max(scope.pageIndex - 3, 0);
- var endPage = Math.min(pageCount, startPage + 9);
-
- var paginationList = $('
');
-
- for (var i = startPage; i < endPage; i++) {
- var activeClass = i === scope.pageIndex ? 'active' : '';
- var pageLinkElem = $('
' + (i+1) + '');
- paginationList.append(pageLinkElem);
- }
-
- footerElem.append(paginationList);
- }
-
- function renderPanel() {
- var container = elem.find('.table-panel-container');
- var rootElem = elem.find('.table-panel-scroll');
- var tbodyElem = elem.find('tbody');
- var footerElem = elem.find('.table-panel-footer');
-
- appendTableRows(tbodyElem);
-
- container.css({'font-size': panel.fontSize});
- appendPaginationControls(footerElem);
-
- rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });
- }
-
- elem.on('click', '.table-panel-page-link', switchPage);
-
- scope.$on('$destroy', function() {
- elem.off('click', '.table-panel-page-link');
- });
-
- scope.$on('render', function(event, renderData) {
- data = renderData || data;
- if (!data) {
- scope.get_data();
- return;
- }
-
- renderPanel();
- });
+ return (panelHeight - 60) + 'px';
}
- };
+
+ function appendTableRows(tbodyElem) {
+ var renderer = new TableRenderer(panel, data, ctrl.dashboard.timezone);
+ tbodyElem.empty();
+ tbodyElem.html(renderer.render(ctrl.pageIndex));
+ }
+
+ function switchPage(e) {
+ var el = $(e.currentTarget);
+ ctrl.pageIndex = (parseInt(el.text(), 10)-1);
+ renderPanel();
+ }
+
+ function appendPaginationControls(footerElem) {
+ footerElem.empty();
+
+ var pageSize = panel.pageSize || 100;
+ pageCount = Math.ceil(data.rows.length / pageSize);
+ if (pageCount === 1) {
+ return;
+ }
+
+ var startPage = Math.max(ctrl.pageIndex - 3, 0);
+ var endPage = Math.min(pageCount, startPage + 9);
+
+ var paginationList = $('
');
+
+ for (var i = startPage; i < endPage; i++) {
+ var activeClass = i === ctrl.pageIndex ? 'active' : '';
+ var pageLinkElem = $('
' + (i+1) + '');
+ paginationList.append(pageLinkElem);
+ }
+
+ footerElem.append(paginationList);
+ }
+
+ function renderPanel() {
+ var panelElem = elem.parents('.panel');
+ var rootElem = elem.find('.table-panel-scroll');
+ var tbodyElem = elem.find('tbody');
+ var footerElem = elem.find('.table-panel-footer');
+
+ elem.css({'font-size': panel.fontSize});
+ panelElem.addClass('table-panel-wrapper');
+
+ appendTableRows(tbodyElem);
+ appendPaginationControls(footerElem);
+
+ rootElem.css({'max-height': panel.scroll ? getTableHeight() : '' });
+ }
+
+ elem.on('click', '.table-panel-page-link', switchPage);
+
+ scope.$on('$destroy', function() {
+ elem.off('click', '.table-panel-page-link');
+ });
+
+ scope.$on('render', function(event, renderData) {
+ data = renderData || data;
+ renderPanel();
+ });
+ }
}
-export {tablePanel as panel};
+export {
+ TablePanel,
+ TablePanel as Panel
+};