From ebba7a0327ed1f8feed9a458789f33ede05b346b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 26 Jan 2016 17:28:07 -0500 Subject: [PATCH] feat(graph): updating graph panel to new format progress --- .../app/features/panel/metrics_panel_ctrl.ts | 13 +- public/app/features/panel/panel_ctrl.ts | 28 +- public/app/features/panel/panel_editor_tab.ts | 6 +- public/app/features/panel/partials/panel.html | 2 +- public/app/plugins/panel/graph/graph.js | 104 +++--- public/app/plugins/panel/graph/graph_ctrl.ts | 292 +++++++++++++++++ .../app/plugins/panel/graph/graph_tooltip.js | 20 +- public/app/plugins/panel/graph/module.d.ts | 3 - public/app/plugins/panel/graph/module.html | 31 +- public/app/plugins/panel/graph/module.js | 303 ------------------ public/app/plugins/panel/graph/module.ts | 15 + .../app/plugins/panel/graph/styleEditor.html | 44 +-- 12 files changed, 431 insertions(+), 430 deletions(-) create mode 100644 public/app/plugins/panel/graph/graph_ctrl.ts delete mode 100644 public/app/plugins/panel/graph/module.d.ts delete mode 100644 public/app/plugins/panel/graph/module.js create mode 100644 public/app/plugins/panel/graph/module.ts diff --git a/public/app/features/panel/metrics_panel_ctrl.ts b/public/app/features/panel/metrics_panel_ctrl.ts index 093eebde694..795afb41bf6 100644 --- a/public/app/features/panel/metrics_panel_ctrl.ts +++ b/public/app/features/panel/metrics_panel_ctrl.ts @@ -49,9 +49,7 @@ class MetricsPanelCtrl extends PanelCtrl { } initEditMode() { - this.addEditorTab('Metrics', () => { - return { templateUrl: 'public/app/partials/metrics.html' }; - }); + this.addEditorTab('Metrics', 'public/app/partials/metrics.html'); this.datasources = this.datasourceSrv.getMetricSources(); } @@ -108,15 +106,6 @@ class MetricsPanelCtrl extends PanelCtrl { 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() { this.range = this.timeSrv.timeRange(); this.rangeRaw = this.timeSrv.timeRange(false); diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts index c53bfda68bd..ac12bac53ba 100644 --- a/public/app/features/panel/panel_ctrl.ts +++ b/public/app/features/panel/panel_ctrl.ts @@ -2,29 +2,28 @@ import config from 'app/core/config'; -function generalOptionsTabEditorTab() { - return {templateUrl: 'public/app/partials/panelgeneral.html'}; -} - export class PanelCtrl { panel: any; row: any; dashboard: any; editorTabIndex: number; - name: string; + pluginName: string; + pluginId: string; icon: string; editorTabs: any; $scope: any; $injector: any; fullscreen: boolean; inspector: any; + editModeInitiated: boolean; constructor($scope, $injector) { var plugin = config.panels[this.panel.type]; this.$injector = $injector; this.$scope = $scope; - this.name = plugin.name; + this.pluginName = plugin.name; + this.pluginId = plugin.id; this.icon = plugin.info.icon; this.editorTabIndex = 0; @@ -59,9 +58,9 @@ export class PanelCtrl { } editPanel() { - if (!this.editorTabs) { + if (!this.editModeInitiated) { this.editorTabs = []; - this.editorTabs.push({title: 'General', directiveFn: generalOptionsTabEditorTab}); + this.addEditorTab('General', 'public/app/partials/panelgeneral.html'); this.initEditMode(); } @@ -76,8 +75,13 @@ export class PanelCtrl { return; } - addEditorTab(title, directiveFn) { - this.editorTabs.push({title: title, directiveFn: directiveFn}); + addEditorTab(title, templateUrl) { + this.editorTabs.push({ + title: title, + directiveFn: function() { + return {templateUrl: templateUrl}; + } + }); } getMenu() { @@ -92,4 +96,8 @@ export class PanelCtrl { otherPanelInFullscreenMode() { return this.dashboard.meta.fullscreen && !this.fullscreen; } + + broadcastRender(arg1?, arg2?) { + this.$scope.$broadcast('render', arg1, arg2); + } } diff --git a/public/app/features/panel/panel_editor_tab.ts b/public/app/features/panel/panel_editor_tab.ts index 68b1e67c01c..f6c11306678 100644 --- a/public/app/features/panel/panel_editor_tab.ts +++ b/public/app/features/panel/panel_editor_tab.ts @@ -11,10 +11,14 @@ function panelEditorTab(dynamicDirectiveSrv) { scope: { ctrl: "=", editorTab: "=", + index: "=", }, directive: scope => { + var pluginId = scope.ctrl.pluginId; + var tabIndex = scope.index; + return Promise.resolve({ - name: 'panel-editor-tab-' + scope.editorTab.title, + name: `panel-editor-tab-${pluginId}${tabIndex}`, fn: scope.editorTab.directiveFn, }); } diff --git a/public/app/features/panel/partials/panel.html b/public/app/features/panel/partials/panel.html index 55ed28eafc4..13c2178e0b4 100644 --- a/public/app/features/panel/partials/panel.html +++ b/public/app/features/panel/partials/panel.html @@ -39,7 +39,7 @@
- +
diff --git a/public/app/plugins/panel/graph/graph.js b/public/app/plugins/panel/graph/graph.js index 1ebf75d9e73..59089848cd8 100755 --- a/public/app/plugins/panel/graph/graph.js +++ b/public/app/plugins/panel/graph/graph.js @@ -24,14 +24,16 @@ function (angular, $, moment, _, kbn, GraphTooltip) { restrict: 'A', template: '
', link: function(scope, elem) { - var dashboard = scope.dashboard; + var ctrl = scope.ctrl; + var dashboard = ctrl.dashboard; + var panel = ctrl.panel; var data, annotations; var sortedSeries; var graphHeight; var legendSideLastValue = null; - scope.crosshairEmiter = false; + var rootScope = scope.$root; - scope.onAppEvent('setCrosshair', function(event, info) { + rootScope.onAppEvent('setCrosshair', function(event, info) { // do not need to to this if event is from this panel if (info.scope === scope) { return; @@ -43,20 +45,20 @@ function (angular, $, moment, _, kbn, GraphTooltip) { plot.setCrosshair({ x: info.pos.x, y: info.pos.y }); } } - }); + }, scope); - scope.onAppEvent('clearCrosshair', function() { + rootScope.onAppEvent('clearCrosshair', function() { var plot = elem.data().plot; if (plot) { plot.clearCrosshair(); } - }); + }, scope); // Receive render events scope.$on('render',function(event, renderData) { data = renderData || data; if (!data) { - scope.get_data(); + ctrl.refresh(); return; } annotations = data.annotations || annotations; @@ -64,10 +66,10 @@ function (angular, $, moment, _, kbn, GraphTooltip) { }); function getLegendHeight(panelHeight) { - if (!scope.panel.legend.show || scope.panel.legend.rightSide) { + if (!panel.legend.show || panel.legend.rightSide) { return 0; } - if (scope.panel.legend.alignAsTable) { + if (panel.legend.alignAsTable) { var total = 30 + (25 * data.length); return Math.min(total, Math.floor(panelHeight/2)); } else { @@ -77,14 +79,13 @@ function (angular, $, moment, _, kbn, GraphTooltip) { function setElementHeight() { try { - graphHeight = scope.height || scope.panel.height || scope.row.height; + graphHeight = ctrl.height || panel.height || ctrl.row.height; if (_.isString(graphHeight)) { graphHeight = parseInt(graphHeight.replace('px', ''), 10); } graphHeight -= 5; // padding - graphHeight -= scope.panel.title ? 24 : 9; // subtract panel title bar - + graphHeight -= panel.title ? 24 : 9; // subtract panel title bar graphHeight = graphHeight - getLegendHeight(graphHeight); // subtract one line legend elem.css('height', graphHeight + 'px'); @@ -100,7 +101,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) { return true; } - if ($rootScope.fullscreen && !scope.fullscreen) { + if (ctrl.otherPanelInFullscreenMode()) { return true; } @@ -122,11 +123,11 @@ function (angular, $, moment, _, kbn, GraphTooltip) { for (var i = 0; i < data.length; i++) { var series = data[i]; var axis = yaxis[series.yaxis - 1]; - var formater = kbn.valueFormats[scope.panel.y_formats[series.yaxis - 1]]; + var formater = kbn.valueFormats[panel.y_formats[series.yaxis - 1]]; // decimal override - if (_.isNumber(scope.panel.decimals)) { - series.updateLegendValues(formater, scope.panel.decimals, null); + if (_.isNumber(panel.decimals)) { + series.updateLegendValues(formater, panel.decimals, null); } else { // auto decimals // legend and tooltip gets one more decimal precision @@ -135,22 +136,22 @@ function (angular, $, moment, _, kbn, GraphTooltip) { series.updateLegendValues(formater, tickDecimals, axis.scaledDecimals + 2); } - if(!scope.$$phase) { scope.$digest(); } + if(!rootScope.$$phase) { scope.$digest(); } } // add left axis labels - if (scope.panel.leftYAxisLabel) { + if (panel.leftYAxisLabel) { var yaxisLabel = $("
") - .text(scope.panel.leftYAxisLabel) + .text(panel.leftYAxisLabel) .appendTo(elem); yaxisLabel.css("margin-top", yaxisLabel.width() / 2); } // add right axis labels - if (scope.panel.rightYAxisLabel) { + if (panel.rightYAxisLabel) { var rightLabel = $("
") - .text(scope.panel.rightYAxisLabel) + .text(panel.rightYAxisLabel) .appendTo(elem); rightLabel.css("margin-top", rightLabel.width() / 2); @@ -158,8 +159,8 @@ function (angular, $, moment, _, kbn, GraphTooltip) { } function processOffsetHook(plot, gridMargin) { - if (scope.panel.leftYAxisLabel) { gridMargin.left = 20; } - if (scope.panel.rightYAxisLabel) { gridMargin.right = 20; } + if (panel.leftYAxisLabel) { gridMargin.left = 20; } + if (panel.rightYAxisLabel) { gridMargin.right = 20; } } // Function for rendering panel @@ -168,7 +169,6 @@ function (angular, $, moment, _, kbn, GraphTooltip) { return; } - var panel = scope.panel; var stack = panel.stack ? true : null; // Populate element @@ -230,7 +230,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) { series.data = series.getFlotPairs(series.nullPointMode || panel.nullPointMode, panel.y_formats); // if hidden remove points and disable stack - if (scope.hiddenSeries[series.alias]) { + if (ctrl.hiddenSeries[series.alias]) { series.data = []; series.stack = false; } @@ -255,7 +255,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) { } if (incrementRenderCounter) { - scope.panelRenderingComplete(); + ctrl.renderingCompleted(); } } @@ -285,18 +285,18 @@ function (angular, $, moment, _, kbn, GraphTooltip) { function addTimeAxis(options) { var ticks = elem.width() / 100; - var min = _.isUndefined(scope.range.from) ? null : scope.range.from.valueOf(); - var max = _.isUndefined(scope.range.to) ? null : scope.range.to.valueOf(); + var min = _.isUndefined(ctrl.range.from) ? null : ctrl.range.from.valueOf(); + var max = _.isUndefined(ctrl.range.to) ? null : ctrl.range.to.valueOf(); options.xaxis = { timezone: dashboard.timezone, - show: scope.panel['x-axis'], + show: panel['x-axis'], mode: "time", min: min, max: max, label: "Datetime", ticks: ticks, - timeformat: time_format(scope.interval, ticks, min, max), + timeformat: time_format(ctrl.interval, ticks, min, max), }; } @@ -361,11 +361,11 @@ function (angular, $, moment, _, kbn, GraphTooltip) { function configureAxisOptions(data, options) { var defaults = { position: 'left', - show: scope.panel['y-axis'], - min: scope.panel.grid.leftMin, + show: panel['y-axis'], + min: panel.grid.leftMin, index: 1, - logBase: scope.panel.grid.leftLogBase || 1, - max: scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.leftMax, + logBase: panel.grid.leftLogBase || 1, + max: panel.percentage && panel.stack ? 100 : panel.grid.leftMax, }; options.yaxes.push(defaults); @@ -373,18 +373,18 @@ function (angular, $, moment, _, kbn, GraphTooltip) { if (_.findWhere(data, {yaxis: 2})) { var secondY = _.clone(defaults); secondY.index = 2, - secondY.logBase = scope.panel.grid.rightLogBase || 1, + secondY.logBase = panel.grid.rightLogBase || 1, secondY.position = 'right'; - secondY.min = scope.panel.grid.rightMin; - secondY.max = scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.rightMax; + secondY.min = panel.grid.rightMin; + secondY.max = panel.percentage && panel.stack ? 100 : panel.grid.rightMax; options.yaxes.push(secondY); applyLogScale(options.yaxes[1], data); - configureAxisMode(options.yaxes[1], scope.panel.percentage && scope.panel.stack ? "percent" : scope.panel.y_formats[1]); + configureAxisMode(options.yaxes[1], panel.percentage && panel.stack ? "percent" : panel.y_formats[1]); } applyLogScale(options.yaxes[0], data); - configureAxisMode(options.yaxes[0], scope.panel.percentage && scope.panel.stack ? "percent" : scope.panel.y_formats[0]); + configureAxisMode(options.yaxes[0], panel.percentage && panel.stack ? "percent" : panel.y_formats[0]); } function applyLogScale(axis, data) { @@ -463,18 +463,18 @@ function (angular, $, moment, _, kbn, GraphTooltip) { url += '&height=' + elem.css('height').replace('px', ''); url += '&bgcolor=1f1f1f'; // @grayDarker & @grafanaPanelBackground url += '&fgcolor=BBBFC2'; // @textColor & @grayLighter - url += scope.panel.stack ? '&areaMode=stacked' : ''; - url += scope.panel.fill !== 0 ? ('&areaAlpha=' + (scope.panel.fill/10).toFixed(1)) : ''; - url += scope.panel.linewidth !== 0 ? '&lineWidth=' + scope.panel.linewidth : ''; - url += scope.panel.legend.show ? '&hideLegend=false' : '&hideLegend=true'; - url += scope.panel.grid.leftMin !== null ? '&yMin=' + scope.panel.grid.leftMin : ''; - url += scope.panel.grid.leftMax !== null ? '&yMax=' + scope.panel.grid.leftMax : ''; - url += scope.panel.grid.rightMin !== null ? '&yMin=' + scope.panel.grid.rightMin : ''; - url += scope.panel.grid.rightMax !== null ? '&yMax=' + scope.panel.grid.rightMax : ''; - url += scope.panel['x-axis'] ? '' : '&hideAxes=true'; - url += scope.panel['y-axis'] ? '' : '&hideYAxis=true'; + url += panel.stack ? '&areaMode=stacked' : ''; + url += panel.fill !== 0 ? ('&areaAlpha=' + (panel.fill/10).toFixed(1)) : ''; + url += panel.linewidth !== 0 ? '&lineWidth=' + panel.linewidth : ''; + url += panel.legend.show ? '&hideLegend=false' : '&hideLegend=true'; + url += panel.grid.leftMin !== null ? '&yMin=' + panel.grid.leftMin : ''; + url += panel.grid.leftMax !== null ? '&yMax=' + panel.grid.leftMax : ''; + url += panel.grid.rightMin !== null ? '&yMin=' + panel.grid.rightMin : ''; + url += panel.grid.rightMax !== null ? '&yMax=' + panel.grid.rightMax : ''; + url += panel['x-axis'] ? '' : '&hideAxes=true'; + url += panel['y-axis'] ? '' : '&hideYAxis=true'; - switch(scope.panel.y_formats[0]) { + switch(panel.y_formats[0]) { case 'bytes': url += '&yUnitSystem=binary'; break; @@ -507,7 +507,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) { break; } - switch(scope.panel.nullPointMode) { + switch(panel.nullPointMode) { case 'connected': url += '&lineMode=connected'; break; @@ -518,7 +518,7 @@ function (angular, $, moment, _, kbn, GraphTooltip) { break; } - url += scope.panel.steppedLine ? '&lineMode=staircase' : ''; + url += panel.steppedLine ? '&lineMode=staircase' : ''; elem.html(''); } diff --git a/public/app/plugins/panel/graph/graph_ctrl.ts b/public/app/plugins/panel/graph/graph_ctrl.ts new file mode 100644 index 00000000000..c242c0ae537 --- /dev/null +++ b/public/app/plugins/panel/graph/graph_ctrl.ts @@ -0,0 +1,292 @@ +/// + +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} diff --git a/public/app/plugins/panel/graph/graph_tooltip.js b/public/app/plugins/panel/graph/graph_tooltip.js index 99fb20b2ed5..452d490f418 100644 --- a/public/app/plugins/panel/graph/graph_tooltip.js +++ b/public/app/plugins/panel/graph/graph_tooltip.js @@ -6,6 +6,8 @@ function ($) { function GraphTooltip(elem, dashboard, scope, getSeriesFn) { var self = this; + var ctrl = scope.ctrl; + var panel = ctrl.panel; var $tooltip = $('
'); @@ -47,12 +49,12 @@ function ($) { for (i = 0; i < seriesList.length; 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 }); continue; } - if (!series.data.length || (scope.panel.legend.hideZero && series.allIsZero)) { + if (!series.data.length || (panel.legend.hideZero && series.allIsZero)) { results.push({ hidden: true }); continue; } @@ -61,7 +63,7 @@ function ($) { results.time = series.data[hoverIndex][0]; if (series.stack) { - if (scope.panel.tooltip.value_type === 'individual') { + if (panel.tooltip.value_type === 'individual') { value = series.data[hoverIndex][1]; } else if (!series.stack) { value = series.data[hoverIndex][1]; @@ -89,7 +91,7 @@ function ($) { }; elem.mouseleave(function () { - if (scope.panel.tooltip.shared) { + if (panel.tooltip.shared) { var plot = elem.data().plot; if (plot) { $tooltip.detach(); @@ -98,7 +100,7 @@ function ($) { } if (dashboard.sharedCrosshair) { - scope.appEvent('clearCrosshair'); + ctrl.publishAppEvent('clearCrosshair'); } }); @@ -108,15 +110,15 @@ function ($) { var seriesList = getSeriesFn(); var group, value, absoluteTime, relativeTime, hoverInfo, i, series, seriesHtml; - if(dashboard.sharedCrosshair){ - scope.appEvent('setCrosshair', { pos: pos, scope: scope }); + if (dashboard.sharedCrosshair) { + ctrl.publishAppEvent('setCrosshair', { pos: pos, scope: scope }); } if (seriesList.length === 0) { return; } - if (scope.panel.tooltip.shared) { + if (panel.tooltip.shared) { plot.unhighlight(); var seriesHoverInfo = self.getMultiSeriesPlotHoverInfo(plotData, pos); @@ -153,7 +155,7 @@ function ($) { group = '
'; group += ' ' + series.label + ':
'; - 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]; } else { diff --git a/public/app/plugins/panel/graph/module.d.ts b/public/app/plugins/panel/graph/module.d.ts deleted file mode 100644 index f3fe6043d65..00000000000 --- a/public/app/plugins/panel/graph/module.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare var panel: any; -declare var GraphCtrl: any; -export {panel, GraphCtrl}; diff --git a/public/app/plugins/panel/graph/module.html b/public/app/plugins/panel/graph/module.html index 068223a5366..66d77a4ae53 100644 --- a/public/app/plugins/panel/graph/module.html +++ b/public/app/plugins/panel/graph/module.html @@ -1,25 +1,22 @@ - - -
-
- -
- - No datapoints No datapoints returned from metric query - - Datapoints outside time range Can be caused by timezone mismatch between browser and graphite server -
- -
-
+
+
+
+ + No datapoints No datapoints returned from metric query + + Datapoints outside time range Can be caused by timezone mismatch between browser and graphite server +
+ +
-
-
+
+
+ +
- diff --git a/public/app/plugins/panel/graph/module.js b/public/app/plugins/panel/graph/module.js deleted file mode 100644 index c1039e394a3..00000000000 --- a/public/app/plugins/panel/graph/module.js +++ /dev/null @@ -1,303 +0,0 @@ -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, - }; -}); diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts new file mode 100644 index 00000000000..b6a5368c6ac --- /dev/null +++ b/public/app/plugins/panel/graph/module.ts @@ -0,0 +1,15 @@ + +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 +} diff --git a/public/app/plugins/panel/graph/styleEditor.html b/public/app/plugins/panel/graph/styleEditor.html index f692328a0fd..82cf31dd0d1 100644 --- a/public/app/plugins/panel/graph/styleEditor.html +++ b/public/app/plugins/panel/graph/styleEditor.html @@ -1,60 +1,60 @@
Chart Options
- - - + + +
Line options
-
+
- +
-
+
- +
-
+
- +
- +
- +
Multiple Series
- - + +
Rendering
- +
- +
Tooltip
-
+
- +
@@ -64,10 +64,10 @@
Series specific overrides Regex match example: /server[0-3]/i
-
+
  • - +
  • @@ -75,7 +75,7 @@
  • - +
  • @@ -95,7 +95,7 @@
-