Commit ebba7a03 by Torkel Ödegaard

feat(graph): updating graph panel to new format progress

parent aa251fc9
...@@ -49,9 +49,7 @@ class MetricsPanelCtrl extends PanelCtrl { ...@@ -49,9 +49,7 @@ class MetricsPanelCtrl extends PanelCtrl {
} }
initEditMode() { initEditMode() {
this.addEditorTab('Metrics', () => { this.addEditorTab('Metrics', 'public/app/partials/metrics.html');
return { templateUrl: 'public/app/partials/metrics.html' };
});
this.datasources = this.datasourceSrv.getMetricSources(); this.datasources = this.datasourceSrv.getMetricSources();
} }
...@@ -108,15 +106,6 @@ class MetricsPanelCtrl extends PanelCtrl { ...@@ -108,15 +106,6 @@ class MetricsPanelCtrl extends PanelCtrl {
this.timing.queryEnd = new Date().getTime(); this.timing.queryEnd = new Date().getTime();
} }
setTimeRenderStart() {
this.timing = this.timing || {};
this.timing.renderStart = new Date().getTime();
}
setTimeRenderEnd() {
this.timing.renderEnd = new Date().getTime();
}
updateTimeRange() { updateTimeRange() {
this.range = this.timeSrv.timeRange(); this.range = this.timeSrv.timeRange();
this.rangeRaw = this.timeSrv.timeRange(false); this.rangeRaw = this.timeSrv.timeRange(false);
......
...@@ -2,29 +2,28 @@ ...@@ -2,29 +2,28 @@
import config from 'app/core/config'; import config from 'app/core/config';
function generalOptionsTabEditorTab() {
return {templateUrl: 'public/app/partials/panelgeneral.html'};
}
export class PanelCtrl { export class PanelCtrl {
panel: any; panel: any;
row: any; row: any;
dashboard: any; dashboard: any;
editorTabIndex: number; editorTabIndex: number;
name: string; pluginName: string;
pluginId: string;
icon: string; icon: string;
editorTabs: any; editorTabs: any;
$scope: any; $scope: any;
$injector: any; $injector: any;
fullscreen: boolean; fullscreen: boolean;
inspector: any; inspector: any;
editModeInitiated: boolean;
constructor($scope, $injector) { constructor($scope, $injector) {
var plugin = config.panels[this.panel.type]; var plugin = config.panels[this.panel.type];
this.$injector = $injector; this.$injector = $injector;
this.$scope = $scope; this.$scope = $scope;
this.name = plugin.name; this.pluginName = plugin.name;
this.pluginId = plugin.id;
this.icon = plugin.info.icon; this.icon = plugin.info.icon;
this.editorTabIndex = 0; this.editorTabIndex = 0;
...@@ -59,9 +58,9 @@ export class PanelCtrl { ...@@ -59,9 +58,9 @@ export class PanelCtrl {
} }
editPanel() { editPanel() {
if (!this.editorTabs) { if (!this.editModeInitiated) {
this.editorTabs = []; this.editorTabs = [];
this.editorTabs.push({title: 'General', directiveFn: generalOptionsTabEditorTab}); this.addEditorTab('General', 'public/app/partials/panelgeneral.html');
this.initEditMode(); this.initEditMode();
} }
...@@ -76,8 +75,13 @@ export class PanelCtrl { ...@@ -76,8 +75,13 @@ export class PanelCtrl {
return; return;
} }
addEditorTab(title, directiveFn) { addEditorTab(title, templateUrl) {
this.editorTabs.push({title: title, directiveFn: directiveFn}); this.editorTabs.push({
title: title,
directiveFn: function() {
return {templateUrl: templateUrl};
}
});
} }
getMenu() { getMenu() {
...@@ -92,4 +96,8 @@ export class PanelCtrl { ...@@ -92,4 +96,8 @@ export class PanelCtrl {
otherPanelInFullscreenMode() { otherPanelInFullscreenMode() {
return this.dashboard.meta.fullscreen && !this.fullscreen; return this.dashboard.meta.fullscreen && !this.fullscreen;
} }
broadcastRender(arg1?, arg2?) {
this.$scope.$broadcast('render', arg1, arg2);
}
} }
...@@ -11,10 +11,14 @@ function panelEditorTab(dynamicDirectiveSrv) { ...@@ -11,10 +11,14 @@ function panelEditorTab(dynamicDirectiveSrv) {
scope: { scope: {
ctrl: "=", ctrl: "=",
editorTab: "=", editorTab: "=",
index: "=",
}, },
directive: scope => { directive: scope => {
var pluginId = scope.ctrl.pluginId;
var tabIndex = scope.index;
return Promise.resolve({ return Promise.resolve({
name: 'panel-editor-tab-' + scope.editorTab.title, name: `panel-editor-tab-${pluginId}${tabIndex}`,
fn: scope.editorTab.directiveFn, fn: scope.editorTab.directiveFn,
}); });
} }
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
<div class="gf-box-body"> <div class="gf-box-body">
<div ng-repeat="tab in ctrl.editorTabs" ng-if="ctrl.editorTabIndex === $index"> <div ng-repeat="tab in ctrl.editorTabs" ng-if="ctrl.editorTabIndex === $index">
<panel-editor-tab editor-tab="tab" ctrl="ctrl"></panel-editor-tab> <panel-editor-tab editor-tab="tab" ctrl="ctrl" index="$index"></panel-editor-tab>
</div> </div>
</div> </div>
</div> </div>
......
///<reference path="../../../headers/common.d.ts" />
import moment from 'moment';
import kbn from 'app/core/utils/kbn';
import _ from 'lodash';
import TimeSeries from '../../../core/time_series2';
import * as fileExport from '../../../core/utils/file_export';
import {MetricsPanelCtrl} from '../../../features/panel/panel';
var panelDefaults = {
// datasource name, null = default datasource
datasource: null,
// sets client side (flot) or native graphite png renderer (png)
renderer: 'flot',
// Show/hide the x-axis
'x-axis' : true,
// Show/hide y-axis
'y-axis' : true,
// y axis formats, [left axis,right axis]
y_formats : ['short', 'short'],
// grid options
grid : {
leftLogBase: 1,
leftMax: null,
rightMax: null,
leftMin: null,
rightMin: null,
rightLogBase: 1,
threshold1: null,
threshold2: null,
threshold1Color: 'rgba(216, 200, 27, 0.27)',
threshold2Color: 'rgba(234, 112, 112, 0.22)'
},
// show/hide lines
lines : true,
// fill factor
fill : 1,
// line width in pixels
linewidth : 2,
// show hide points
points : false,
// point radius in pixels
pointradius : 5,
// show hide bars
bars : false,
// enable/disable stacking
stack : false,
// stack percentage mode
percentage : false,
// legend options
legend: {
show: true, // disable/enable legend
values: false, // disable/enable legend values
min: false,
max: false,
current: false,
total: false,
avg: false
},
// how null points should be handled
nullPointMode : 'connected',
// staircase line mode
steppedLine: false,
// tooltip options
tooltip : {
value_type: 'cumulative',
shared: true,
},
// time overrides
timeFrom: null,
timeShift: null,
// metric queries
targets: [{}],
// series color overrides
aliasColors: {},
// other style overrides
seriesOverrides: [],
};
class GraphCtrl extends MetricsPanelCtrl {
hiddenSeries: any = {};
seriesList: any = [];
logScales: any;
unitFormats: any;
annotationsPromise: any;
datapointsCount: number;
datapointsOutside: boolean;
datapointsWarning: boolean;
colors: any = [];
/** @ngInject */
constructor($scope, $injector, private annotationsSrv) {
super($scope, $injector);
_.defaults(this.panel, panelDefaults);
_.defaults(this.panel.tooltip, panelDefaults.tooltip);
_.defaults(this.panel.grid, panelDefaults.grid);
_.defaults(this.panel.legend, panelDefaults.legend);
this.colors = $scope.$root.colors;
}
initEditMode() {
super.initEditMode();
this.icon = "fa fa-bar-chart";
this.addEditorTab('Axes & Grid', 'public/app/plugins/panel/graph/axisEditor.html');
this.addEditorTab('Display Styles', 'public/app/plugins/panel/graph/styleEditor.html');
// $scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
// $scope.panelMeta.addExtendedMenuItem('Export CSV', '', 'exportCsv()');
// $scope.panelMeta.addExtendedMenuItem('Toggle legend', '', 'toggleLegend()');
//
this.logScales = {
'linear': 1,
'log (base 2)': 2,
'log (base 10)': 10,
'log (base 32)': 32,
'log (base 1024)': 1024
};
this.unitFormats = kbn.getUnitFormats();
}
setUnitFormat(axis, subItem) {
this.panel.y_formats[axis] = subItem.value;
this.render();
}
refreshData(datasource) {
this.annotationsPromise = this.annotationsSrv.getAnnotations(this.dashboard);
return this.issueQueries()
.then(res => this.dataHandler(res))
.catch(err => {
this.seriesList = [];
this.render([]);
throw err;
});
}
zoomOut(evt) {
this.publishAppEvent('zoom-out', evt);
}
loadSnapshot(snapshotData) {
this.updateTimeRange();
this.annotationsPromise = this.annotationsSrv.getAnnotations(this.dashboard);
this.dataHandler(snapshotData);
}
dataHandler(results) {
// png renderer returns just a url
if (_.isString(results)) {
this.render(results);
return;
}
this.datapointsWarning = false;
this.datapointsCount = 0;
this.datapointsOutside = false;
this.seriesList = _.map(results.data, (series, i) => this.seriesHandler(series, i));
this.datapointsWarning = this.datapointsCount === 0 || this.datapointsOutside;
this.annotationsPromise.then(annotations => {
this.loading = false;
this.seriesList.annotations = annotations;
this.render(this.seriesList);
}, () => {
this.loading = false;
this.render(this.seriesList);
});
};
seriesHandler(seriesData, index) {
var datapoints = seriesData.datapoints;
var alias = seriesData.target;
var colorIndex = index % this.colors.length;
var color = this.panel.aliasColors[alias] || this.colors[colorIndex];
var series = new TimeSeries({
datapoints: datapoints,
alias: alias,
color: color,
});
if (datapoints && datapoints.length > 0) {
var last = moment.utc(datapoints[datapoints.length - 1][1]);
var from = moment.utc(this.range.from);
if (last - from < -10000) {
this.datapointsOutside = true;
}
this.datapointsCount += datapoints.length;
}
return series;
}
render(data?: any) {
this.broadcastRender(data);
}
changeSeriesColor(series, color) {
series.color = color;
this.panel.aliasColors[series.alias] = series.color;
this.render();
}
toggleSeries(serie, event) {
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if (this.hiddenSeries[serie.alias]) {
delete this.hiddenSeries[serie.alias];
} else {
this.hiddenSeries[serie.alias] = true;
}
} else {
this.toggleSeriesExclusiveMode(serie);
}
this.render();
}
toggleSeriesExclusiveMode (serie) {
var hidden = this.hiddenSeries;
if (hidden[serie.alias]) {
delete hidden[serie.alias];
}
// check if every other series is hidden
var alreadyExclusive = _.every(this.seriesList, value => {
if (value.alias === serie.alias) {
return true;
}
return hidden[value.alias];
});
if (alreadyExclusive) {
// remove all hidden series
_.each(this.seriesList, value => {
delete this.hiddenSeries[value.alias];
});
} else {
// hide all but this serie
_.each(this.seriesList, value => {
if (value.alias === serie.alias) {
return;
}
this.hiddenSeries[value.alias] = true;
});
}
}
toggleYAxis(info) {
var override = _.findWhere(this.panel.seriesOverrides, { alias: info.alias });
if (!override) {
override = { alias: info.alias };
this.panel.seriesOverrides.push(override);
}
override.yaxis = info.yaxis === 2 ? 1 : 2;
this.render();
};
addSeriesOverride(override) {
this.panel.seriesOverrides.push(override || {});
}
removeSeriesOverride(override) {
this.panel.seriesOverrides = _.without(this.panel.seriesOverrides, override);
this.render();
}
// Called from panel menu
toggleLegend() {
this.panel.legend.show = !this.panel.legend.show;
this.refresh();
}
legendValuesOptionChanged() {
var legend = this.panel.legend;
legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
this.render();
}
exportCsv() {
fileExport.exportSeriesListToCsv(this.seriesList);
}
}
export {GraphCtrl}
...@@ -6,6 +6,8 @@ function ($) { ...@@ -6,6 +6,8 @@ function ($) {
function GraphTooltip(elem, dashboard, scope, getSeriesFn) { function GraphTooltip(elem, dashboard, scope, getSeriesFn) {
var self = this; var self = this;
var ctrl = scope.ctrl;
var panel = ctrl.panel;
var $tooltip = $('<div id="tooltip">'); var $tooltip = $('<div id="tooltip">');
...@@ -47,12 +49,12 @@ function ($) { ...@@ -47,12 +49,12 @@ function ($) {
for (i = 0; i < seriesList.length; i++) { for (i = 0; i < seriesList.length; i++) {
series = seriesList[i]; series = seriesList[i];
if (!series.data.length || (scope.panel.legend.hideEmpty && series.allIsNull)) { if (!series.data.length || (panel.legend.hideEmpty && series.allIsNull)) {
results.push({ hidden: true }); results.push({ hidden: true });
continue; continue;
} }
if (!series.data.length || (scope.panel.legend.hideZero && series.allIsZero)) { if (!series.data.length || (panel.legend.hideZero && series.allIsZero)) {
results.push({ hidden: true }); results.push({ hidden: true });
continue; continue;
} }
...@@ -61,7 +63,7 @@ function ($) { ...@@ -61,7 +63,7 @@ function ($) {
results.time = series.data[hoverIndex][0]; results.time = series.data[hoverIndex][0];
if (series.stack) { if (series.stack) {
if (scope.panel.tooltip.value_type === 'individual') { if (panel.tooltip.value_type === 'individual') {
value = series.data[hoverIndex][1]; value = series.data[hoverIndex][1];
} else if (!series.stack) { } else if (!series.stack) {
value = series.data[hoverIndex][1]; value = series.data[hoverIndex][1];
...@@ -89,7 +91,7 @@ function ($) { ...@@ -89,7 +91,7 @@ function ($) {
}; };
elem.mouseleave(function () { elem.mouseleave(function () {
if (scope.panel.tooltip.shared) { if (panel.tooltip.shared) {
var plot = elem.data().plot; var plot = elem.data().plot;
if (plot) { if (plot) {
$tooltip.detach(); $tooltip.detach();
...@@ -98,7 +100,7 @@ function ($) { ...@@ -98,7 +100,7 @@ function ($) {
} }
if (dashboard.sharedCrosshair) { if (dashboard.sharedCrosshair) {
scope.appEvent('clearCrosshair'); ctrl.publishAppEvent('clearCrosshair');
} }
}); });
...@@ -108,15 +110,15 @@ function ($) { ...@@ -108,15 +110,15 @@ function ($) {
var seriesList = getSeriesFn(); var seriesList = getSeriesFn();
var group, value, absoluteTime, relativeTime, hoverInfo, i, series, seriesHtml; var group, value, absoluteTime, relativeTime, hoverInfo, i, series, seriesHtml;
if(dashboard.sharedCrosshair){ if (dashboard.sharedCrosshair) {
scope.appEvent('setCrosshair', { pos: pos, scope: scope }); ctrl.publishAppEvent('setCrosshair', { pos: pos, scope: scope });
} }
if (seriesList.length === 0) { if (seriesList.length === 0) {
return; return;
} }
if (scope.panel.tooltip.shared) { if (panel.tooltip.shared) {
plot.unhighlight(); plot.unhighlight();
var seriesHoverInfo = self.getMultiSeriesPlotHoverInfo(plotData, pos); var seriesHoverInfo = self.getMultiSeriesPlotHoverInfo(plotData, pos);
...@@ -153,7 +155,7 @@ function ($) { ...@@ -153,7 +155,7 @@ function ($) {
group = '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">'; group = '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">';
group += '<i class="fa fa-minus" style="color:' + item.series.color +';"></i> ' + series.label + ':</div>'; group += '<i class="fa fa-minus" style="color:' + item.series.color +';"></i> ' + series.label + ':</div>';
if (scope.panel.stack && scope.panel.tooltip.value_type === 'individual') { if (panel.stack && panel.tooltip.value_type === 'individual') {
value = item.datapoint[1] - item.datapoint[2]; value = item.datapoint[1] - item.datapoint[2];
} }
else { else {
......
declare var panel: any;
declare var GraphCtrl: any;
export {panel, GraphCtrl};
<grafana-panel> <div class="graph-wrapper" ng-class="{'graph-legend-rightside': panel.legend.rightSide}">
<div class="graph-canvas-wrapper">
<div class="graph-wrapper" ng-class="{'graph-legend-rightside': panel.legend.rightSide}">
<div class="graph-canvas-wrapper"> <div ng-if="datapointsWarning" class="datapoints-warning">
<span class="small" ng-show="!datapointsCount">
<div ng-if="datapointsWarning" class="datapoints-warning"> No datapoints <tip>No datapoints returned from metric query</tip>
<span class="small" ng-show="!datapointsCount"> </span>
No datapoints <tip>No datapoints returned from metric query</tip> <span class="small" ng-show="datapointsOutside">Datapoints outside time range <tip>Can be caused by timezone mismatch between browser and graphite server</tip></span>
</span> </div>
<span class="small" ng-show="datapointsOutside">Datapoints outside time range <tip>Can be caused by timezone mismatch between browser and graphite server</tip></span>
</div>
<div grafana-graph class="histogram-chart" ng-dblclick="zoomOut()">
</div>
<div grafana-graph class="histogram-chart" ng-dblclick="zoomOut()">
</div> </div>
<div class="graph-legend-wrapper" ng-if="panel.legend.show" graph-legend></div>
</div> </div>
<div class="clearfix"></div> <div class="graph-legend-wrapper" ng-if="panel.legend.show" graph-legend></div>
</div>
<div class="clearfix"></div>
</grafana-panel>
define([
'angular',
'lodash',
'moment',
'app/core/utils/kbn',
'app/core/utils/file_export',
'app/core/time_series',
'app/features/panel/panel_meta',
'./seriesOverridesCtrl',
'./graph',
'./legend',
],
function (angular, _, moment, kbn, fileExport, TimeSeries, PanelMeta) {
'use strict';
/** @ngInject */
function GraphCtrl($scope, $rootScope, panelSrv, annotationsSrv, panelHelper) {
$scope.panelMeta = new PanelMeta({
panelName: 'Graph',
editIcon: "fa fa-bar-chart",
fullscreen: true,
metricsEditor: true,
});
$scope.panelMeta.addEditorTab('Axes & Grid', 'app/plugins/panel/graph/axisEditor.html');
$scope.panelMeta.addEditorTab('Display Styles', 'app/plugins/panel/graph/styleEditor.html');
$scope.panelMeta.addEditorTab('Time range', 'app/features/panel/partials/panelTime.html');
$scope.panelMeta.addExtendedMenuItem('Export CSV', '', 'exportCsv()');
$scope.panelMeta.addExtendedMenuItem('Toggle legend', '', 'toggleLegend()');
// Set and populate defaults
var _d = {
// datasource name, null = default datasource
datasource: null,
// sets client side (flot) or native graphite png renderer (png)
renderer: 'flot',
// Show/hide the x-axis
'x-axis' : true,
// Show/hide y-axis
'y-axis' : true,
// y axis formats, [left axis,right axis]
y_formats : ['short', 'short'],
// grid options
grid : {
leftLogBase: 1,
leftMax: null,
rightMax: null,
leftMin: null,
rightMin: null,
rightLogBase: 1,
threshold1: null,
threshold2: null,
threshold1Color: 'rgba(216, 200, 27, 0.27)',
threshold2Color: 'rgba(234, 112, 112, 0.22)'
},
// show/hide lines
lines : true,
// fill factor
fill : 1,
// line width in pixels
linewidth : 2,
// show hide points
points : false,
// point radius in pixels
pointradius : 5,
// show hide bars
bars : false,
// enable/disable stacking
stack : false,
// stack percentage mode
percentage : false,
// legend options
legend: {
show: true, // disable/enable legend
values: false, // disable/enable legend values
min: false,
max: false,
current: false,
total: false,
avg: false
},
// how null points should be handled
nullPointMode : 'connected',
// staircase line mode
steppedLine: false,
// tooltip options
tooltip : {
value_type: 'cumulative',
shared: true,
},
// time overrides
timeFrom: null,
timeShift: null,
// metric queries
targets: [{}],
// series color overrides
aliasColors: {},
// other style overrides
seriesOverrides: [],
};
_.defaults($scope.panel,_d);
_.defaults($scope.panel.tooltip, _d.tooltip);
_.defaults($scope.panel.annotate, _d.annotate);
_.defaults($scope.panel.grid, _d.grid);
_.defaults($scope.panel.legend, _d.legend);
$scope.logScales = {'linear': 1, 'log (base 2)': 2, 'log (base 10)': 10, 'log (base 32)': 32, 'log (base 1024)': 1024};
$scope.hiddenSeries = {};
$scope.seriesList = [];
$scope.unitFormats = kbn.getUnitFormats();
$scope.setUnitFormat = function(axis, subItem) {
$scope.panel.y_formats[axis] = subItem.value;
$scope.render();
};
$scope.refreshData = function(datasource) {
panelHelper.updateTimeRange($scope);
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.dashboard);
return panelHelper.issueMetricQuery($scope, datasource)
.then($scope.dataHandler, function(err) {
$scope.seriesList = [];
$scope.render([]);
throw err;
});
};
$scope.zoomOut = function(evt) {
$scope.appEvent('zoom-out', evt);
};
$scope.loadSnapshot = function(snapshotData) {
panelHelper.updateTimeRange($scope);
$scope.annotationsPromise = annotationsSrv.getAnnotations($scope.dashboard);
$scope.dataHandler(snapshotData);
};
$scope.dataHandler = function(results) {
// png renderer returns just a url
if (_.isString(results)) {
$scope.render(results);
return;
}
$scope.datapointsWarning = false;
$scope.datapointsCount = 0;
$scope.datapointsOutside = false;
$scope.seriesList = _.map(results.data, $scope.seriesHandler);
$scope.datapointsWarning = $scope.datapointsCount === 0 || $scope.datapointsOutside;
$scope.annotationsPromise
.then(function(annotations) {
$scope.panelMeta.loading = false;
$scope.seriesList.annotations = annotations;
$scope.render($scope.seriesList);
}, function() {
$scope.panelMeta.loading = false;
$scope.render($scope.seriesList);
});
};
$scope.seriesHandler = function(seriesData, index) {
var datapoints = seriesData.datapoints;
var alias = seriesData.target;
var colorIndex = index % $rootScope.colors.length;
var color = $scope.panel.aliasColors[alias] || $rootScope.colors[colorIndex];
var series = new TimeSeries({
datapoints: datapoints,
alias: alias,
color: color,
});
if (datapoints && datapoints.length > 0) {
var last = moment.utc(datapoints[datapoints.length - 1][1]);
var from = moment.utc($scope.range.from);
if (last - from < -10000) {
$scope.datapointsOutside = true;
}
$scope.datapointsCount += datapoints.length;
}
return series;
};
$scope.render = function(data) {
panelHelper.broadcastRender($scope, data);
};
$scope.changeSeriesColor = function(series, color) {
series.color = color;
$scope.panel.aliasColors[series.alias] = series.color;
$scope.render();
};
$scope.toggleSeries = function(serie, event) {
if (event.ctrlKey || event.metaKey || event.shiftKey) {
if ($scope.hiddenSeries[serie.alias]) {
delete $scope.hiddenSeries[serie.alias];
}
else {
$scope.hiddenSeries[serie.alias] = true;
}
} else {
$scope.toggleSeriesExclusiveMode(serie);
}
$scope.render();
};
$scope.toggleSeriesExclusiveMode = function(serie) {
var hidden = $scope.hiddenSeries;
if (hidden[serie.alias]) {
delete hidden[serie.alias];
}
// check if every other series is hidden
var alreadyExclusive = _.every($scope.seriesList, function(value) {
if (value.alias === serie.alias) {
return true;
}
return hidden[value.alias];
});
if (alreadyExclusive) {
// remove all hidden series
_.each($scope.seriesList, function(value) {
delete $scope.hiddenSeries[value.alias];
});
}
else {
// hide all but this serie
_.each($scope.seriesList, function(value) {
if (value.alias === serie.alias) {
return;
}
$scope.hiddenSeries[value.alias] = true;
});
}
};
$scope.toggleYAxis = function(info) {
var override = _.findWhere($scope.panel.seriesOverrides, { alias: info.alias });
if (!override) {
override = { alias: info.alias };
$scope.panel.seriesOverrides.push(override);
}
override.yaxis = info.yaxis === 2 ? 1 : 2;
$scope.render();
};
$scope.addSeriesOverride = function(override) {
$scope.panel.seriesOverrides.push(override || {});
};
$scope.removeSeriesOverride = function(override) {
$scope.panel.seriesOverrides = _.without($scope.panel.seriesOverrides, override);
$scope.render();
};
// Called from panel menu
$scope.toggleLegend = function() {
$scope.panel.legend.show = !$scope.panel.legend.show;
$scope.get_data();
};
$scope.legendValuesOptionChanged = function() {
var legend = $scope.panel.legend;
legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
$scope.render();
};
$scope.exportCsv = function() {
fileExport.exportSeriesListToCsv($scope.seriesList);
};
panelSrv.init($scope);
}
function graphPanelDirective() {
return {
controller: GraphCtrl,
templateUrl: 'app/plugins/panel/graph/module.html',
};
}
return {
GraphCtrl: GraphCtrl,
panel: graphPanelDirective,
};
});
import {PanelDirective} from '../../../features/panel/panel';
import {GraphCtrl} from './graph_ctrl';
import './graph';
class GraphPanel extends PanelDirective {
controller = GraphCtrl;
templateUrl = 'public/app/plugins/panel/graph/module.html';
}
export {
GraphPanel,
GraphPanel as Panel
}
<div class="editor-row"> <div class="editor-row">
<div class="section"> <div class="section">
<h5>Chart Options</h5> <h5>Chart Options</h5>
<editor-opt-bool text="Bars" model="panel.bars" change="render()"></editor-opt-bool> <editor-opt-bool text="Bars" model="ctrl.panel.bars" change="ctrl.render()"></editor-opt-bool>
<editor-opt-bool text="Lines" model="panel.lines" change="render()"></editor-opt-bool> <editor-opt-bool text="Lines" model="ctrl.panel.lines" change="ctrl.render()"></editor-opt-bool>
<editor-opt-bool text="Points" model="panel.points" change="render()"></editor-opt-bool> <editor-opt-bool text="Points" model="ctrl.panel.points" change="ctrl.render()"></editor-opt-bool>
</div> </div>
<div class="section"> <div class="section">
<h5>Line options</h5> <h5>Line options</h5>
<div class="editor-option" ng-show="panel.lines"> <div class="editor-option" ng-show="ctrl.panel.lines">
<label class="small">Line Fill</label> <label class="small">Line Fill</label>
<select class="input-mini" ng-model="panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]" ng-change="render()"></select> <select class="input-mini" ng-model="ctrl.panel.fill" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]" ng-change="ctrl.render()"></select>
</div> </div>
<div class="editor-option" ng-show="panel.lines"> <div class="editor-option" ng-show="ctrl.panel.lines">
<label class="small">Line Width</label> <label class="small">Line Width</label>
<select class="input-mini" ng-model="panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]" ng-change="render()"></select> <select class="input-mini" ng-model="ctrl.panel.linewidth" ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]" ng-change="ctrl.render()"></select>
</div> </div>
<div class="editor-option" ng-show="panel.points"> <div class="editor-option" ng-show="ctrl.panel.points">
<label class="small">Point Radius</label> <label class="small">Point Radius</label>
<select class="input-mini" ng-model="panel.pointradius" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10]" ng-change="render()"></select> <select class="input-mini" ng-model="ctrl.panel.pointradius" ng-options="f for f in [1,2,3,4,5,6,7,8,9,10]" ng-change="ctrl.render()"></select>
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Null point mode<tip>Define how null values should be drawn</tip></label> <label class="small">Null point mode<tip>Define how null values should be drawn</tip></label>
<select class="input-medium" ng-model="panel.nullPointMode" ng-options="f for f in ['connected', 'null', 'null as zero']" ng-change="render()"></select> <select class="input-medium" ng-model="ctrl.panel.nullPointMode" ng-options="f for f in ['connected', 'null', 'null as zero']" ng-change="ctrl.render()"></select>
</div> </div>
<editor-opt-bool text="Staircase line" model="panel.steppedLine" change="render()"></editor-opt-bool> <editor-opt-bool text="Staircase line" model="ctrl.panel.steppedLine" change="ctrl.render()"></editor-opt-bool>
</div> </div>
<div class="section"> <div class="section">
<h5>Multiple Series</h5> <h5>Multiple Series</h5>
<editor-opt-bool text="Stack" model="panel.stack" change="render()"></editor-opt-bool> <editor-opt-bool text="Stack" model="ctrl.panel.stack" change="ctrl.render()"></editor-opt-bool>
<editor-opt-bool text="Percent" model="panel.percentage" change="render()" tip="Stack as a percentage of total"></editor-opt-bool> <editor-opt-bool text="Percent" model="ctrl.panel.percentage" change="ctrl.render()" tip="Stack as a percentage of total"></editor-opt-bool>
</div> </div>
<div class="section"> <div class="section">
<h5>Rendering</h5> <h5>Rendering</h5>
<div class="editor-option"> <div class="editor-option">
<label class="small">Flot <tip>client side</tip></label> <label class="small">Flot <tip>client side</tip></label>
<input type="radio" class="input-small" ng-model="panel.renderer" value="flot" ng-change="get_data()" /> <input type="radio" class="input-small" ng-model="ctrl.panel.renderer" value="flot" ng-change="ctrl.refresh()" />
</div> </div>
<div class="editor-option"> <div class="editor-option">
<label class="small">Graphite PNG <tip>server side</tip></label> <label class="small">Graphite PNG <tip>server side</tip></label>
<input type="radio" class="input-small" ng-model="panel.renderer" value="png" ng-change="get_data()" /> <input type="radio" class="input-small" ng-model="ctrl.panel.renderer" value="png" ng-change="ctr.refresh()" />
</div> </div>
</div> </div>
<div class="section"> <div class="section">
<h5>Tooltip</h5> <h5>Tooltip</h5>
<editor-opt-bool <editor-opt-bool
text="All series" model="panel.tooltip.shared" change="render()" text="All series" model="ctrl.panel.tooltip.shared" change="ctrl.render()"
tip="Show all series on same tooltip and a x croshair to help follow all series"> tip="Show all series on same tooltip and a x croshair to help follow all series">
</editor-opt-bool> </editor-opt-bool>
<div class="editor-option" ng-show="panel.stack"> <div class="editor-option" ng-show="ctrl.panel.stack">
<label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label> <label class="small">Stacked Values <tip>How should the values in stacked charts to be calculated?</tip></label>
<select class="input-small" ng-model="panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']" ng-change="render()"></select> <select class="input-small" ng-model="ctrl.panel.tooltip.value_type" ng-options="f for f in ['cumulative','individual']" ng-change="ctrl.render()"></select>
</div> </div>
</div> </div>
</div> </div>
...@@ -64,10 +64,10 @@ ...@@ -64,10 +64,10 @@
<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 class="tight-form-container"> <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 ctrl.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">
<i class="fa fa-remove pointer" ng-click="removeSeriesOverride(override)"></i> <i class="fa fa-remove pointer" ng-click="ctrl.removeSeriesOverride(override)"></i>
</li> </li>
<li class="tight-form-item"> <li class="tight-form-item">
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
</li> </li>
<li> <li>
<input type="text" ng-model="override.alias" bs-typeahead="getSeriesNames" ng-blur="render()" data-min-length=0 data-items=100 class="input-medium tight-form-input" > <input type="text" ng-model="override.alias" bs-typeahead="getSeriesNames" ng-blur="ctrl.render()" data-min-length=0 data-items=100 class="input-medium tight-form-input" >
</li> </li>
<li class="tight-form-item" ng-repeat="option in currentOverrides"> <li class="tight-form-item" ng-repeat="option in currentOverrides">
...@@ -95,7 +95,7 @@ ...@@ -95,7 +95,7 @@
</div> </div>
</div> </div>
<button class="btn btn-inverse" style="margin-top: 20px" ng-click="addSeriesOverride()"> <button class="btn btn-inverse" style="margin-top: 20px" ng-click="ctrl.addSeriesOverride()">
Add series specific option Add series specific option
</button> </button>
</div> </div>
......
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