diff --git a/CHANGELOG.md b/CHANGELOG.md index c8f4fbef587..dcdc838115c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * **Admin**: Admin can now have global overview of Grafana setup, closes [#3812](https://github.com/grafana/grafana/issues/3812) * **graph**: Right side legend height is now fixed at row height, closes [#1277](https://github.com/grafana/grafana/issues/1277) * **Table**: All content in table panel is now html escaped, closes [#3673](https://github.com/grafana/grafana/issues/3673) +* **graph**: Template variables can now be used in TimeShift and TimeFrom, closes[#1960](https://github.com/grafana/grafana/issues/1960) ### Bug fixes * **Playlist**: Fix for memory leak when running a playlist, closes [#3794](https://github.com/grafana/grafana/pull/3794) diff --git a/pkg/api/api.go b/pkg/api/api.go index 90d613e46e0..ed029a5171a 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -43,8 +43,9 @@ func Register(r *macaron.Macaron) { r.Get("/admin/orgs/edit/:id", reqGrafanaAdmin, Index) r.Get("/admin/stats", reqGrafanaAdmin, Index) - r.Get("/apps", reqSignedIn, Index) - r.Get("/apps/edit/*", reqSignedIn, Index) + r.Get("/plugins", reqSignedIn, Index) + r.Get("/plugins/:id/edit", reqSignedIn, Index) + r.Get("/plugins/:id/page/:page", reqSignedIn, Index) r.Get("/dashboard/*", reqSignedIn, Index) r.Get("/dashboard-solo/*", reqSignedIn, Index) diff --git a/pkg/api/index.go b/pkg/api/index.go index df752109530..a5199fa79ae 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -85,13 +85,13 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { if plugin.Pinned { pageLink := &dtos.NavLink{ Text: plugin.Name, - Url: setting.AppSubUrl + "/apps/" + plugin.Id + "/edit", + Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/edit", Img: plugin.Info.Logos.Small, } for _, page := range plugin.Pages { pageLink.Children = append(pageLink.Children, &dtos.NavLink{ - Url: setting.AppSubUrl + "/apps/" + plugin.Id + "/page/" + page.Slug, + Url: setting.AppSubUrl + "/plugins/" + plugin.Id + "/page/" + page.Slug, Text: page.Name, }) } diff --git a/public/app/core/directives/ng_model_on_blur.js b/public/app/core/directives/ng_model_on_blur.js index 1e3ebc38a25..6f4a55b53f0 100644 --- a/public/app/core/directives/ng_model_on_blur.js +++ b/public/app/core/directives/ng_model_on_blur.js @@ -47,6 +47,9 @@ function (coreModule, kbn, rangeUtil) { if (ctrl.$isEmpty(modelValue)) { return true; } + if (viewValue.indexOf('$') === 0) { + return true; // allow template variable + } var info = rangeUtil.describeTextRange(viewValue); return info.invalid !== true; }; diff --git a/public/app/features/dashboard/dashboardSrv.js b/public/app/features/dashboard/dashboardSrv.js index be404dd1ce1..01c5787481b 100644 --- a/public/app/features/dashboard/dashboardSrv.js +++ b/public/app/features/dashboard/dashboardSrv.js @@ -140,7 +140,11 @@ function (angular, $, _, moment) { }; p.isSubmenuFeaturesEnabled = function() { - return this.templating.list.length > 0 || this.annotations.list.length > 0 || this.links.length > 0; + var visableTemplates = _.filter(this.templating.list, function(template) { + return template.hideVariable === undefined || template.hideVariable === false; + }); + + return visableTemplates.length > 0 || this.annotations.list.length > 0 || this.links.length > 0; }; p.getPanelInfoById = function(panelId) { diff --git a/public/app/features/dashboard/submenu/submenu.html b/public/app/features/dashboard/submenu/submenu.html index eb8de17676c..21a9744b359 100644 --- a/public/app/features/dashboard/submenu/submenu.html +++ b/public/app/features/dashboard/submenu/submenu.html @@ -1,6 +1,6 @@ -
- Label - - +
+
+ Label + +
+
+ + +
+
Value Options
diff --git a/public/app/plugins/panel/singlestat/editor.html b/public/app/plugins/panel/singlestat/editor.html index bf3227f7582..6b0806133b8 100644 --- a/public/app/plugins/panel/singlestat/editor.html +++ b/public/app/plugins/panel/singlestat/editor.html @@ -167,13 +167,13 @@
  • - +
  • - +
  • diff --git a/public/app/plugins/panel/singlestat/module.ts b/public/app/plugins/panel/singlestat/module.ts index 7f576cc3f2d..bb7b9cec0b6 100644 --- a/public/app/plugins/panel/singlestat/module.ts +++ b/public/app/plugins/panel/singlestat/module.ts @@ -50,7 +50,7 @@ class SingleStatCtrl extends MetricsPanelCtrl { unitFormats: any[]; /** @ngInject */ - constructor($scope, $injector, private $location, private linkSrv, private templateSrv) { + constructor($scope, $injector, private $location, private linkSrv) { super($scope, $injector); _.defaults(this.panel, panelDefaults); } @@ -213,7 +213,7 @@ class SingleStatCtrl extends MetricsPanelCtrl { // value/number to text mapping var value = parseFloat(map.value); - if (value === data.value) { + if (value === data.valueRounded) { data.valueFormated = map.text; return; } diff --git a/public/app/plugins/panel/singlestat/specs/singlestat-specs.ts b/public/app/plugins/panel/singlestat/specs/singlestat-specs.ts index 283389ee400..90bd5339737 100644 --- a/public/app/plugins/panel/singlestat/specs/singlestat-specs.ts +++ b/public/app/plugins/panel/singlestat/specs/singlestat-specs.ts @@ -69,14 +69,20 @@ describe('SingleStatCtrl', function() { singleStatScenario('When value to text mapping is specified', function(ctx) { ctx.setup(function() { - ctx.datapoints = [[10,1]]; + ctx.datapoints = [[9.9,1]]; ctx.ctrl.panel.valueMaps = [{value: '10', text: 'OK'}]; }); - it('Should replace value with text', function() { - expect(ctx.data.value).to.be(10); - expect(ctx.data.valueFormated).to.be('OK'); + it('value should remain', function() { + expect(ctx.data.value).to.be(9.9); }); + it('round should be rounded up', function() { + expect(ctx.data.valueRounded).to.be(10); + }); + + it('Should replace value with text', function() { + expect(ctx.data.valueFormated).to.be('OK'); + }); }); });