Commit b3c073ab by Torkel Ödegaard

feat(panels): more panel refactoring, using events instead of overriding base class methods

parent 6a42b95d
......@@ -14,7 +14,7 @@ export class Emitter {
this.subjects = {};
}
emit(name, data) {
emit(name, data?) {
var fnName = createName(name);
this.subjects[fnName] || (this.subjects[fnName] = new Subject());
this.subjects[fnName].next(data);
......
......@@ -139,7 +139,7 @@ function (angular, _, $) {
self.$scope.broadcastRefresh();
}
else {
self.fullscreenPanel.$broadcast('render');
ctrl.render();
}
delete self.fullscreenPanel;
});
......@@ -159,7 +159,7 @@ function (angular, _, $) {
this.$scope.appEvent('panel-fullscreen-enter', {panelId: ctrl.panel.id});
$timeout(function() {
panelScope.$broadcast('render');
ctrl.render();
});
};
......
......@@ -44,16 +44,18 @@ class MetricsPanelCtrl extends PanelCtrl {
if (!this.panel.targets) {
this.panel.targets = [{}];
}
this.events.on('refresh', this.onMetricsPanelRefresh.bind(this));
this.events.on('init-edit-mode', this.onInitMetricsPanelEditMode.bind(this));
}
initEditMode() {
super.initEditMode();
private onInitMetricsPanelEditMode() {
this.addEditorTab('Metrics', 'public/app/partials/metrics.html');
this.addEditorTab('Time range', 'public/app/features/panel/partials/panelTime.html');
this.datasources = this.datasourceSrv.getMetricSources();
}
refresh() {
private onMetricsPanelRefresh() {
// ignore fetching data if another panel is in fullscreen
if (this.otherPanelInFullscreenMode()) { return; }
......
......@@ -18,7 +18,6 @@ export class PanelCtrl {
editorTabIndex: number;
pluginName: string;
pluginId: string;
icon: string;
editorTabs: any;
$scope: any;
$injector: any;
......@@ -60,7 +59,7 @@ export class PanelCtrl {
}
refresh() {
this.render();
this.events.emit('refresh', null);
}
publishAppEvent(evtName, evt) {
......@@ -89,6 +88,7 @@ export class PanelCtrl {
this.editorTabs = [];
this.addEditorTab('General', 'public/app/partials/panelgeneral.html');
this.editModeInitiated = true;
this.events.emit('init-edit-mode', null);
}
addEditorTab(title, directiveFn, index?) {
......@@ -118,7 +118,9 @@ export class PanelCtrl {
}
getExtendedMenu() {
return [{text: 'Panel JSON', click: 'ctrl.editPanelJson(); dismiss();'}];
var actions = [{text: 'Panel JSON', click: 'ctrl.editPanelJson(); dismiss();'}];
this.events.emit('init-panel-actions', actions);
return actions;
}
otherPanelInFullscreenMode() {
......@@ -126,7 +128,6 @@ export class PanelCtrl {
}
calculatePanelHeight() {
if (this.fullscreen) {
var docHeight = $(window).height();
var editHeight = Math.floor(docHeight * 0.3);
......@@ -142,8 +143,13 @@ export class PanelCtrl {
this.height = this.containerHeight - (PANEL_PADDING + (this.panel.title ? TITLE_HEIGHT : EMPTY_TITLE_HEIGHT));
}
render(arg1?, arg2?) {
this.$scope.$broadcast('render', arg1, arg2);
render(payload?) {
// ignore if other panel is in fullscreen mode
if (this.otherPanelInFullscreenMode()) {
return;
}
this.events.emit('render', payload);
}
toggleEditorHelp(index) {
......
......@@ -28,18 +28,18 @@ class DashListCtrl extends PanelCtrl {
this.panel.tags = [$scope.panel.tag];
delete this.panel.tag;
}
this.events.on('refresh', this.onRefresh.bind(this));
this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
}
initEditMode() {
super.initEditMode();
onInitEditMode() {
this.editorTabIndex = 1;
this.modes = ['starred', 'search', 'recently viewed'];
this.icon = "fa fa-star";
this.addEditorTab('Options', () => {
return {templateUrl: 'public/app/plugins/panel/dashlist/editor.html'};
});
this.addEditorTab('Options', 'public/app/plugins/panel/dashlist/editor.html');
}
refresh() {
onRefresh() {
var params: any = {limit: this.panel.limit};
if (this.panel.mode === 'recently viewed') {
......
......@@ -54,7 +54,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
}, scope);
// Receive render events
scope.$on('render',function(event, renderData) {
ctrl.events.on('render', function(renderData) {
data = renderData || data;
if (!data) {
ctrl.refresh();
......@@ -97,10 +97,6 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
return true;
}
if (ctrl.otherPanelInFullscreenMode()) {
return true;
}
if (!setElementHeight()) { return true; }
if(_.isString(data)) {
......
......@@ -22,7 +22,7 @@ function (angular, _, $) {
var seriesList;
var i;
scope.$on('render', function() {
ctrl.events.on('render', function() {
data = ctrl.seriesList;
if (data) {
render();
......
......@@ -110,12 +110,11 @@ class GraphCtrl extends MetricsPanelCtrl {
this.events.on('data-received', this.onDataReceived.bind(this));
this.events.on('data-error', this.onDataError.bind(this));
this.events.on('data-snapshot-load', this.onDataSnapshotLoad.bind(this));
this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
this.events.on('init-panel-actions', this.onInitPanelActions.bind(this));
}
initEditMode() {
super.initEditMode();
this.icon = "fa fa-bar-chart";
onInitEditMode() {
this.addEditorTab('Axes & Grid', 'public/app/plugins/panel/graph/axisEditor.html', 2);
this.addEditorTab('Display Styles', 'public/app/plugins/panel/graph/styleEditor.html', 3);
......@@ -129,12 +128,10 @@ class GraphCtrl extends MetricsPanelCtrl {
this.unitFormats = kbn.getUnitFormats();
}
getExtendedMenu() {
var menu = super.getExtendedMenu();
menu.push({text: 'Export CSV (series as rows)', click: 'ctrl.exportCsv()'});
menu.push({text: 'Export CSV (series as columns)', click: 'ctrl.exportCsvColumns()'});
menu.push({text: 'Toggle legend', click: 'ctrl.toggleLegend()'});
return menu;
onInitPanelActions(actions) {
actions.push({text: 'Export CSV (series as rows)', click: 'ctrl.exportCsv()'});
actions.push({text: 'Export CSV (series as columns)', click: 'ctrl.exportCsvColumns()'});
actions.push({text: 'Toggle legend', click: 'ctrl.toggleLegend()'});
}
setUnitFormat(axis, subItem) {
......
......@@ -8,6 +8,7 @@ import $ from 'jquery';
import helpers from 'test/specs/helpers';
import TimeSeries from 'app/core/time_series2';
import moment from 'moment';
import {Emitter} from 'app/core/core';
describe('grafanaGraph', function() {
......@@ -24,31 +25,33 @@ describe('grafanaGraph', function() {
}));
beforeEach(angularMocks.inject(function($rootScope, $compile) {
var ctrl: any = {};
var ctrl: any = {
events: new Emitter(),
height: 200,
panel: {
legend: {},
grid: { },
y_formats: [],
seriesOverrides: [],
tooltip: {
shared: true
}
},
renderingCompleted: sinon.spy(),
hiddenSeries: {},
dashboard: {timezone: 'browser'},
range: {
from: moment([2015, 1, 1, 10]),
to: moment([2015, 1, 1, 22]),
},
};
var scope = $rootScope.$new();
scope.ctrl = ctrl;
var element = angular.element("<div style='width:" + elementWidth + "px' grafana-graph><div>");
ctrl.height = '200px';
ctrl.panel = {
legend: {},
grid: { },
y_formats: [],
seriesOverrides: [],
tooltip: {
shared: true
}
};
$rootScope.onAppEvent = sinon.spy();
ctrl.otherPanelInFullscreenMode = sinon.spy();
ctrl.renderingCompleted = sinon.spy();
ctrl.hiddenSeries = {};
ctrl.dashboard = { timezone: 'browser' };
ctrl.range = {
from: moment([2015, 1, 1, 10]),
to: moment([2015, 1, 1, 22]),
};
ctx.data = [];
ctx.data.push(new TimeSeries({
datapoints: [[1,1],[2,2]],
......@@ -61,11 +64,12 @@ describe('grafanaGraph', function() {
setupFunc(ctrl, ctx.data);
var element = angular.element("<div style='width:" + elementWidth + "px' grafana-graph><div>");
$compile(element)(scope);
scope.$digest();
$.plot = ctx.plotSpy = sinon.spy();
scope.$emit('render', ctx.data);
$.plot = ctx.plotSpy = sinon.spy();
ctrl.events.emit('render', ctx.data);
ctx.plotData = ctx.plotSpy.getCall(0).args[1];
ctx.plotOptions = ctx.plotSpy.getCall(0).args[2];
}));
......
......@@ -235,14 +235,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
var templateSrv = this.templateSrv;
var data, linkInfo;
var $panelContainer = elem.find('.panel-container');
// change elem to singlestat panel
elem = elem.find('.singlestat-panel');
hookupDrilldownLinkTooltip();
scope.$on('render', function() {
render();
ctrl.renderingCompleted();
});
function setElementHeight() {
elem.css('height', ctrl.height + 'px');
......@@ -417,6 +410,13 @@ class SingleStatCtrl extends MetricsPanelCtrl {
drilldownTooltip.place_tt(e.pageX+20, e.pageY-15);
});
}
hookupDrilldownLinkTooltip();
this.events.on('render', function() {
render();
ctrl.renderingCompleted();
});
}
}
......
......@@ -61,17 +61,16 @@ class TablePanelCtrl extends MetricsPanelCtrl {
this.events.on('data-received', this.onDataReceived.bind(this));
this.events.on('data-error', this.onDataError.bind(this));
this.events.on('data-snapshot-load', this.onDataSnapshotLoad.bind(this));
this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
this.events.on('init-panel-actions', this.onInitPanelActions.bind(this));
}
initEditMode() {
super.initEditMode();
onInitEditMode() {
this.addEditorTab('Options', tablePanelEditor, 2);
}
getExtendedMenu() {
var menu = super.getExtendedMenu();
menu.push({text: 'Export CSV', click: 'ctrl.exportCsv()'});
return menu;
onInitPanelActions(actions) {
actions.push({text: 'Export CSV', click: 'ctrl.exportCsv()'});
}
issueQueries(datasource) {
......@@ -211,7 +210,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
elem.off('click', '.table-panel-page-link');
});
scope.$on('render', function(event, renderData) {
ctrl.events.on('render', function(renderData) {
data = renderData || data;
if (data) {
renderPanel();
......
......@@ -20,18 +20,18 @@ export class TextPanelCtrl extends PanelCtrl {
super($scope, $injector);
_.defaults(this.panel, panelDefaults);
this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
this.events.on('refresh', this.onRender.bind(this));
this.events.on('render', this.onRender.bind(this));
}
initEditMode() {
super.initEditMode();
this.icon = 'fa fa-text-width';
onInitEditMode() {
this.addEditorTab('Options', 'public/app/plugins/panel/text/editor.html');
this.editorTabIndex = 1;
}
render() {
super.render();
onRender() {
if (this.panel.mode === 'markdown') {
this.renderMarkdown(this.panel.content);
} else if (this.panel.mode === 'html') {
......
import {describe, beforeEach, it, sinon, expect} from 'test/lib/common'
import {Emitter} from 'app/core/core';
describe("Emitter", () => {
describe('given 2 subscribers', () => {
it('should notfiy subscribers', () => {
var events = new Emitter();
var sub1Called = false;
var sub2Called = false;
events.on('test', () => {
sub1Called = true;
});
events.on('test', () => {
sub2Called = true;
});
events.emit('test', null);
expect(sub1Called).to.be(true);
expect(sub2Called).to.be(true);
});
});
});
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