mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(panels): more panel refactoring, using events instead of overriding base class methods
This commit is contained in:
parent
6a42b95d39
commit
b3c073ab6c
@ -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') {
|
||||
|
30
public/test/core/utils/emitter_specs.ts
Normal file
30
public/test/core/utils/emitter_specs.ts
Normal file
@ -0,0 +1,30 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user