Browse Source

Merge branch 'master' of github.com:grafana/grafana

Torkel Ödegaard 9 years ago
parent
commit
5a81cf6c17

+ 17 - 1
CHANGELOG.md

@@ -1,4 +1,20 @@
-# 3.0.0-beta2 (unreleased)
+# 3.0.0-beta3 (unreleased)
+
+### Enhancements
+* **InfluxDB**: Changed multi query encoding to work with InfluxDB 0.11 & 0.12, closes [#4533](https://github.com/grafana/grafana/issues/4533)
+
+### Bug fixes
+* **Postgres**: Fixed page render crash when using postgres, fixes [#4558](https://github.com/grafana/grafana/issues/4558)
+* **Table panel**: Fixed table panel bug when trying to show annotations in table panel, fixes [#4563](https://github.com/grafana/grafana/issues/4563)
+* **App Config**: Fixed app config issue showing content of other app config, fixes [#4575](https://github.com/grafana/grafana/issues/4575)
+* **Graph Panel**: Fixed legend option max not updating, fixes [#4601](https://github.com/grafana/grafana/issues/4601)
+* **Graph Panel**: Fixed issue where newly added graph panels shared same axes config, fixes [#4582](https://github.com/grafana/grafana/issues/4582)
+* **Graph Panel**: Fixed issue with axis labels overlapping Y-axis, fixes [#4626](https://github.com/grafana/grafana/issues/4626)
+* **InfluxDB**: Fixed issue with templating query containing template variable, fixes [#4602](https://github.com/grafana/grafana/issues/4602)
+* **Graph Panel**: Fixed issue with hiding series and stacking, fixes [#4557](https://github.com/grafana/grafana/issues/4557)
+* **Graph Panel**: Fixed issue with legend height in table mode with few series, affected iframe embedding as well, fixes [#4640](https://github.com/grafana/grafana/issues/4640)
+
+# 3.0.0-beta2 (2016-04-04)
 
 ### New Features (introduces since 3.0-beta1)
 * **Preferences**: Set home dashboard on user and org level, closes [#1678](https://github.com/grafana/grafana/issues/1678)

+ 1 - 0
pkg/api/api.go

@@ -30,6 +30,7 @@ func Register(r *macaron.Macaron) {
 	// authed views
 	r.Get("/profile/", reqSignedIn, Index)
 	r.Get("/profile/password", reqSignedIn, Index)
+	r.Get("/profile/switch-org/:id", reqSignedIn, ChangeActiveOrgAndRedirectToHome)
 	r.Get("/org/", reqSignedIn, Index)
 	r.Get("/org/new", reqSignedIn, Index)
 	r.Get("/datasources/", reqSignedIn, Index)

+ 18 - 0
pkg/api/user.go

@@ -4,6 +4,7 @@ import (
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/middleware"
 	m "github.com/grafana/grafana/pkg/models"
+	"github.com/grafana/grafana/pkg/setting"
 	"github.com/grafana/grafana/pkg/util"
 )
 
@@ -109,6 +110,23 @@ func UserSetUsingOrg(c *middleware.Context) Response {
 	return ApiSuccess("Active organization changed")
 }
 
+// GET /profile/switch-org/:id
+func ChangeActiveOrgAndRedirectToHome(c *middleware.Context) {
+	orgId := c.ParamsInt64(":id")
+
+	if !validateUsingOrg(c.UserId, orgId) {
+		NotFoundHandler(c)
+	}
+
+	cmd := m.SetUsingOrgCommand{UserId: c.UserId, OrgId: orgId}
+
+	if err := bus.Dispatch(&cmd); err != nil {
+		NotFoundHandler(c)
+	}
+
+	c.Redirect(setting.AppSubUrl + "/")
+}
+
 func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) Response {
 	userQuery := m.GetUserByIdQuery{Id: c.UserId}
 

+ 7 - 3
pkg/cmd/grafana-cli/commands/commands.go

@@ -25,7 +25,7 @@ func runCommand(command func(commandLine CommandLine) error) func(context *cli.C
 var pluginCommands = []cli.Command{
 	{
 		Name:   "install",
-		Usage:  "install <plugin name>",
+		Usage:  "install <plugin id>",
 		Action: runCommand(installCommand),
 	}, {
 		Name:   "list-remote",
@@ -33,7 +33,7 @@ var pluginCommands = []cli.Command{
 		Action: runCommand(listremoteCommand),
 	}, {
 		Name:   "upgrade",
-		Usage:  "upgrade <plugin name>",
+		Usage:  "upgrade <plugin id>",
 		Action: runCommand(upgradeCommand),
 	}, {
 		Name:   "upgrade-all",
@@ -43,9 +43,13 @@ var pluginCommands = []cli.Command{
 		Name:   "ls",
 		Usage:  "list all installed plugins",
 		Action: runCommand(lsCommand),
+	}, {
+		Name:   "uninstall",
+		Usage:  "uninstall <plugin id>",
+		Action: runCommand(removeCommand),
 	}, {
 		Name:   "remove",
-		Usage:  "remove <plugin name>",
+		Usage:  "remove <plugin id>",
 		Action: runCommand(removeCommand),
 	},
 }

+ 4 - 0
pkg/metrics/report_usage.go

@@ -10,6 +10,7 @@ import (
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/log"
 	m "github.com/grafana/grafana/pkg/models"
+	"github.com/grafana/grafana/pkg/plugins"
 	"github.com/grafana/grafana/pkg/setting"
 )
 
@@ -56,6 +57,9 @@ func sendUsageStats() {
 	metrics["stats.users.count"] = statsQuery.Result.UserCount
 	metrics["stats.orgs.count"] = statsQuery.Result.OrgCount
 	metrics["stats.playlist.count"] = statsQuery.Result.PlaylistCount
+	metrics["stats.plugins.apps.count"] = len(plugins.Apps)
+	metrics["stats.plugins.panels.count"] = len(plugins.Panels)
+	metrics["stats.plugins.datasources.count"] = len(plugins.DataSources)
 
 	dsStats := m.GetDataSourceStatsQuery{}
 	if err := bus.Dispatch(&dsStats); err != nil {

+ 0 - 4
public/app/core/components/sidemenu/sidemenu.html

@@ -21,10 +21,6 @@
 					<i class="{{::menuItem.icon}}" ng-show="::menuItem.icon"></i>
 					{{::menuItem.text}}
 				</a>
-				<a ng-click="menuItem.click()" ng-show="::menuItem.click">
-					<i class="{{::menuItem.icon}}"></i>
-					{{::menuItem.text}}
-				</a>
 			</li>
 		</ul>
 	</li>

+ 2 - 9
public/app/core/components/sidemenu/sidemenu.ts

@@ -72,9 +72,8 @@ export class SideMenuCtrl {
        this.orgMenu.push({
          text: "Switch to " + org.name,
          icon: "fa fa-fw fa-random",
-         click: () => {
-           this.switchOrg(org.orgId);
-         }
+         url: this.getUrl('/profile/switch-org/' + org.orgId),
+         target: '_self'
        });
      });
 
@@ -83,12 +82,6 @@ export class SideMenuCtrl {
      }
    });
  }
-
- switchOrg(orgId) {
-   this.backendSrv.post('/api/user/using/' + orgId).then(() => {
-     window.location.href = `${config.appSubUrl}/`;
-   });
- };
 }
 
 export function sideMenuDirective() {

+ 2 - 2
public/app/core/components/switch.ts

@@ -21,14 +21,14 @@ export class SwitchCtrl {
   id: any;
 
   /** @ngInject */
-  constructor($scope) {
+  constructor($scope, private $timeout) {
     this.show = true;
     this.id = $scope.$id;
   }
 
   internalOnChange() {
     return new Promise(resolve => {
-      setTimeout(() => {
+      this.$timeout(() => {
         this.onChange();
         resolve();
       });

+ 4 - 1
public/app/core/services/popover_srv.ts

@@ -46,9 +46,12 @@ function popoverSrv($compile, $rootScope) {
     drop.on('close', () => {
       popoverScope.dismiss({fromDropClose: true});
       destroyDrop();
+      if (options.onClose) {
+        options.onClose();
+      }
     });
 
-    drop.open();
+    setTimeout(() => { drop.open(); }, 10);
   };
 }
 

+ 24 - 28
public/app/features/dashboard/partials/shareModal.html

@@ -38,31 +38,26 @@
 
 	<div ng-include src="'shareLinkOptions.html'"></div>
 
-	<div class="gf-form-group position-center">
-		<div class="gf-form width-30" >
+	<div class="gf-form-group section">
+		<div class="gf-form width-30">
 			<textarea rows="5" data-share-panel-url class="gf-form-input width-30" ng-model='iframeHtml'></textarea>
 		</div>
 	</div>
-	<div class="gf-form-group">
-		<div class="gf-form position-center">
-			<button class="btn btn-inverse" data-clipboard-text="{{iframeHtml}}" clipboard-button><i class="fa fa-clipboard"></i> Copy</button>
-		</div>
-	</div>
 </script>
 
 <script type="text/ng-template" id="shareLinkOptions.html">
-	<div class="gf-form-group position-center">
-		<div class="gf-form">
-			<span class="gf-form-label width-5">Include</span>
-			<editor-checkbox text="Current time range" model="options.forCurrent" change="buildUrl()"></editor-checkbox>
-		</div>
-		<div class="gf-form">
-			<span class="gf-form-label width-5">Include</span>
-			<editor-checkbox text="Template variables" model="options.includeTemplateVars" change="buildUrl()"></editor-checkbox>
-		</div>
+	<div class="gf-form-group section">
+		<gf-form-switch class="gf-form"
+			label="Current time range" label-class="width-12" switch-class="max-width-6"
+			checked="options.forCurrent" on-change="buildUrl()">
+		</gf-form-switch>
+		<gf-form-switch class="gf-form"
+			label="Template variables" label-class="width-12" switch-class="max-width-6"
+			checked="options.includeTemplateVars" on-change="buildUrl()">
+		</gf-form-switch>
 		<div class="gf-form">
-			<span class="gf-form-label width-5">Theme</span>
-			<div class="gf-form-select-wrapper max-width-10">
+			<span class="gf-form-label width-12">Theme</span>
+			<div class="gf-form-select-wrapper width-6">
 				<select class="gf-form-input" ng-model="options.theme" ng-options="f as f for f in ['current', 'dark', 'light']" ng-change="buildUrl()"></select>
 			</div>
 		</div>
@@ -75,18 +70,19 @@
 	</div>
 
 	<div ng-include src="'shareLinkOptions.html'"></div>
-	<div class="gf-form-group position-center">
-		<div class="gf-form-inline">
-
-			<div class="gf-form width-30">
-				<input type="text" data-share-panel-url class="gf-form-input" ng-model="shareUrl"></input>
-			</div>
-			<div class="gf-form pull-right">
-				<button class="btn btn-inverse pull-right" data-clipboard-text="{{shareUrl}}" clipboard-button><i class="fa fa-clipboard"></i> Copy</button>
+	<div>
+		<div class="gf-form-group section">
+			<div class="gf-form-inline">
+				<div class="gf-form width-30">
+					<input type="text" data-share-panel-url class="gf-form-input" ng-model="shareUrl"></input>
+				</div>
+				<div class="gf-form pull-right">
+					<button class="btn btn-inverse pull-right" data-clipboard-text="{{shareUrl}}" clipboard-button><i class="fa fa-clipboard"></i> Copy</button>
+				</div>
 			</div>
 		</div>
 	</div>
-	<div class="gf-form position-center" ng-show="modeSharePanel">
+	<div class="gf-form section" ng-show="modeSharePanel">
 		<a href="{{imageUrl}}" target="_blank"><i class="fa fa-camera"></i> Direct link rendered image</a>
 	</div>
 </script>
@@ -117,7 +113,7 @@
 			</p>
 		</div>
 
-		<div class="gf-form-group share-modal-options position-center">
+		<div class="gf-form-group share-modal-options">
 			<div class="gf-form" ng-if="step === 1">
 				<span class="gf-form-label width-12">Snapshot name</span>
 				<input type="text" ng-model="snapshot.name" class="gf-form-input max-width-15" >

+ 6 - 3
public/app/features/panel/metrics_panel_ctrl.ts

@@ -184,7 +184,6 @@ class MetricsPanelCtrl extends PanelCtrl {
       cacheTimeout: this.panel.cacheTimeout
     };
 
-    this.setTimeQueryStart();
     return datasource.query(metricsQuery);
   }
 
@@ -252,8 +251,12 @@ class MetricsPanelCtrl extends PanelCtrl {
   }
 
   addDataQuery(datasource) {
-    var target = {
-    };
+    var target: any = {};
+
+    if (datasource) {
+      target.datasource = datasource.name;
+    }
+
     this.panel.targets.push(target);
   }
 }

+ 14 - 2
public/app/plugins/datasource/influxdb/datasource.ts

@@ -55,7 +55,7 @@ export default class InfluxDatasource {
       query = query.replace(/\$interval/g, (target.interval || options.interval));
       return query;
 
-    }).join("\n");
+    }).join(";");
 
     // replace grafana variables
     allQueries = allQueries.replace(/\$timeFilter/g, timeFilter);
@@ -107,7 +107,7 @@ export default class InfluxDatasource {
 
     var timeFilter = this.getTimeFilter({rangeRaw: options.rangeRaw});
     var query = options.annotation.query.replace('$timeFilter', timeFilter);
-    query = this.templateSrv.replace(query);
+    query = this.templateSrv.replace(query, null, 'regex');
 
     return this._seriesQuery(query).then(data => {
       if (!data || !data.results || !data.results[0]) {
@@ -133,6 +133,17 @@ export default class InfluxDatasource {
     return this._influxRequest('GET', '/query', {q: query, epoch: 'ms'});
   }
 
+
+  serializeParams(params) {
+    if (!params) { return '';}
+
+    return _.reduce(params, (memo, value, key) => {
+      if (value === null || value === undefined) { return memo; }
+      memo.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
+      return memo;
+    }, []).join("&");
+  }
+
   testDatasource() {
     return this.metricFindQuery('SHOW MEASUREMENTS LIMIT 1').then(() => {
       return { status: "success", message: "Data source is working", title: "Success" };
@@ -166,6 +177,7 @@ export default class InfluxDatasource {
       data:   data,
       precision: "ms",
       inspect: { type: 'influxdb' },
+      paramSerializer: this.serializeParams,
     };
 
     options.headers = options.headers || {};

+ 1 - 1
public/app/plugins/datasource/opentsdb/config_ctrl.ts

@@ -16,7 +16,7 @@ export class OpenTsConfigCtrl {
 
   tsdbVersions = [
     {name: '<=2.1', value: 1},
-    {name: '2.2', value: 2},
+    {name: '>=2.2', value: 2},
   ];
 
   tsdbResolutions = [

+ 4 - 2
public/app/plugins/panel/graph/graph.js

@@ -151,8 +151,10 @@ function (angular, $, moment, _, kbn, GraphTooltip) {
         }
 
         function processOffsetHook(plot, gridMargin) {
-          if (panel.yaxis) { gridMargin.left = 20; }
-          if (panel.rightYAxisLabel) { gridMargin.right = 20; }
+          var left = panel.yaxes[0];
+          var right = panel.yaxes[1];
+          if (left.show && left.label) { gridMargin.left = 20; }
+          if (right.show && right.label) { gridMargin.right = 20; }
         }
 
         // Function for rendering panel

+ 11 - 9
public/app/plugins/panel/graph/graph_tooltip.js

@@ -33,9 +33,8 @@ function ($) {
       return j - 1;
     };
 
-    this.showTooltip = function(absoluteTime, relativeTime, innerHtml, pos) {
-      var body = '<div class="graph-tooltip small"><div class="graph-tooltip-time">'+ absoluteTime +
-        ' <span class="tone-down">(' + relativeTime + ')</span></div> ';
+    this.showTooltip = function(absoluteTime, innerHtml, pos) {
+      var body = '<div class="graph-tooltip small"><div class="graph-tooltip-time">'+ absoluteTime + '</div> ';
       body += innerHtml + '</div>';
       $tooltip.html(body).place_tt(pos.pageX + 20, pos.pageY);
     };
@@ -109,7 +108,7 @@ function ($) {
       var plot = elem.data().plot;
       var plotData = plot.getData();
       var seriesList = getSeriesFn();
-      var group, value, absoluteTime, relativeTime, hoverInfo, i, series, seriesHtml, tooltipFormat;
+      var group, value, absoluteTime, hoverInfo, i, series, seriesHtml, tooltipFormat;
 
       if (panel.tooltip.msResolution) {
         tooltipFormat = 'YYYY-MM-DD HH:mm:ss.SSS';
@@ -132,7 +131,6 @@ function ($) {
 
         seriesHtml = '';
 
-        relativeTime = dashboard.getRelativeTime(seriesHoverInfo.time);
         absoluteTime = dashboard.formatDate(seriesHoverInfo.time, tooltipFormat);
 
         for (i = 0; i < seriesHoverInfo.length; i++) {
@@ -142,17 +140,22 @@ function ($) {
             continue;
           }
 
+          var highlightClass = '';
+          if (item && i === item.seriesIndex) {
+            highlightClass = 'graph-tooltip-list-item--highlight';
+          }
+
           series = seriesList[i];
 
           value = series.formatValue(hoverInfo.value);
 
-          seriesHtml += '<div class="graph-tooltip-list-item"><div class="graph-tooltip-series-name">';
+          seriesHtml += '<div class="graph-tooltip-list-item ' + highlightClass + '"><div class="graph-tooltip-series-name">';
           seriesHtml += '<i class="fa fa-minus" style="color:' + series.color +';"></i> ' + series.label + ':</div>';
           seriesHtml += '<div class="graph-tooltip-value">' + value + '</div></div>';
           plot.highlight(i, hoverInfo.hoverIndex);
         }
 
-        self.showTooltip(absoluteTime, relativeTime, seriesHtml, pos);
+        self.showTooltip(absoluteTime, seriesHtml, pos);
       }
       // single series tooltip
       else if (item) {
@@ -169,12 +172,11 @@ function ($) {
 
         value = series.formatValue(value);
 
-        relativeTime = dashboard.getRelativeTime(item.datapoint[0]);
         absoluteTime = dashboard.formatDate(item.datapoint[0], tooltipFormat);
 
         group += '<div class="graph-tooltip-value">' + value + '</div>';
 
-        self.showTooltip(absoluteTime, relativeTime, group, pos);
+        self.showTooltip(absoluteTime, group, pos);
       }
       // no hit
       else {

+ 2 - 2
public/app/plugins/panel/graph/legend.js

@@ -194,9 +194,9 @@ function (angular, _, $) {
             }
 
             var topPadding = 6;
-            $container.css("height", maxHeight - topPadding);
+            $container.css("max-height", maxHeight - topPadding);
           } else {
-            $container.css("height", "");
+            $container.css("max-height", "");
           }
         }
       }

+ 9 - 3
public/app/plugins/panel/graph/module.ts

@@ -116,6 +116,7 @@ class GraphCtrl extends MetricsPanelCtrl {
 
     this.colors = $scope.$root.colors;
 
+    this.events.on('render', this.onRender.bind(this));
     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));
@@ -215,8 +216,6 @@ class GraphCtrl extends MetricsPanelCtrl {
       this.panel.tooltip.msResolution = this.panel.tooltip.msResolution || series.isMsResolutionNeeded();
     }
 
-    series.applySeriesOverrides(this.panel.seriesOverrides);
-
     if (seriesData.unit) {
       this.panel.yaxes[series.yaxis-1].format = seriesData.unit;
     }
@@ -224,6 +223,14 @@ class GraphCtrl extends MetricsPanelCtrl {
     return series;
   }
 
+  onRender() {
+    if (!this.seriesList) { return; }
+
+    for (let series of this.seriesList) {
+      series.applySeriesOverrides(this.panel.seriesOverrides);
+    }
+  }
+
   changeSeriesColor(series, color) {
     series.color = color;
     this.panel.aliasColors[series.alias] = series.color;
@@ -240,7 +247,6 @@ class GraphCtrl extends MetricsPanelCtrl {
     } else {
       this.toggleSeriesExclusiveMode(serie);
     }
-
     this.render();
   }
 

+ 3 - 0
public/app/plugins/panel/graph/series_overrides_ctrl.js

@@ -60,6 +60,9 @@ define([
         template: '<gf-color-picker></gf-color-picker>',
         model: {
           colorSelected: $scope.colorSelected,
+        },
+        onClose: function() {
+          $scope.ctrl.render();
         }
       });
     };

+ 1 - 0
public/app/plugins/panel/table/module.ts

@@ -218,6 +218,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
       if (data) {
         renderPanel();
       }
+      ctrl.renderingCompleted();
     });
   }
 }

+ 3 - 2
public/sass/_variables.dark.scss

@@ -39,6 +39,7 @@ $brand-primary:         $orange;
 $brand-success:         $green;
 $brand-warning:         $brand-primary;
 $brand-danger:          $red;
+$brand-text-highlight:  #f7941d;
 
 // Status colors
 // -------------------------
@@ -242,8 +243,8 @@ $infoBackground:          $blue-dark;
 
 // Tooltips and popovers
 // -------------------------
-$tooltipColor:            $white;
-$tooltipBackground:       rgb(58, 57, 57);
+$tooltipColor:            $text-color;
+$tooltipBackground:       $dark-4;
 $tooltipArrowWidth:       5px;
 $tooltipArrowColor:       $tooltipBackground;
 $tooltipLinkColor:        $link-color;

+ 1 - 0
public/sass/_variables.light.scss

@@ -44,6 +44,7 @@ $brand-primary:         $orange;
 $brand-success:         $green;
 $brand-warning:         $orange;
 $brand-danger:          $red;
+$brand-text-highlight:  #f7941d;
 
 // Status colors
 // -------------------------

+ 1 - 5
public/sass/components/_modals.scss

@@ -127,6 +127,7 @@
 
   .share-modal-options {
     margin: 11px 20px 33px 20px;
+    display: inline-block;
   }
 
   .share-modal-big-icon {
@@ -162,8 +163,3 @@
   }
 }
 
-.modal-body {
-  .position-center {
-    display: inline-block;
-  }
-}

+ 7 - 6
public/sass/components/_panel_graph.scss

@@ -237,27 +237,28 @@
 
   .graph-tooltip-time {
     text-align: center;
-    font-weight: $font-weight-semi-bold;
     position: relative;
     top: -3px;
-  }
-
-  .tone-down {
-    opacity: 0.7;
+    padding: 0.2rem;
   }
 
   .graph-tooltip-list-item {
     display: table-row;
+
+    &--highlight {
+      color: $brand-text-highlight;
+    }
   }
 
   .graph-tooltip-series-name {
     display: table-cell;
+    padding: 0.15rem;
   }
 
   .graph-tooltip-value {
     display: table-cell;
     font-weight: bold;
-    padding-left: 10px;
+    padding-left: 15px;
     text-align: right;
   }
 }

+ 0 - 7
public/sass/components/_tooltip.scss

@@ -88,13 +88,6 @@
   }
 }
 
-.grafana-tooltip hr {
- padding: 2px;
- color: #c8c8c8;
- margin: 0px;
- border-bottom: 0px solid #c8c8c8;
-}
-
 .grafana-tip {
   padding-left: 5px;
 }