From 5da3da596250908b9f94bce5d6f38c0e35998bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 11 Nov 2014 11:48:27 +0100 Subject: [PATCH] PanelLinks: began work on drilldown panel links feature, #1041 --- src/app/components/panellinkeditor/linkSrv.js | 39 ++++++++++++++++ .../components/panellinkeditor/module.html | 46 +++++++++++++++++++ src/app/components/panellinkeditor/module.js | 38 +++++++++++++++ src/app/controllers/sharePanelCtrl.js | 9 +--- src/app/directives/all.js | 1 + src/app/directives/panelMenu.js | 16 ++++++- src/app/partials/panelgeneral.html | 4 ++ src/app/services/timeSrv.js | 12 +++++ src/test/specs/sharePanelCtrl-specs.js | 25 +++++----- 9 files changed, 167 insertions(+), 23 deletions(-) create mode 100644 src/app/components/panellinkeditor/linkSrv.js create mode 100644 src/app/components/panellinkeditor/module.html create mode 100644 src/app/components/panellinkeditor/module.js diff --git a/src/app/components/panellinkeditor/linkSrv.js b/src/app/components/panellinkeditor/linkSrv.js new file mode 100644 index 00000000000..8737814556d --- /dev/null +++ b/src/app/components/panellinkeditor/linkSrv.js @@ -0,0 +1,39 @@ +define([ + 'angular', + 'kbn', +], +function (angular, kbn) { + 'use strict'; + + angular + .module('grafana.services') + .service('linkSrv', function(templateSrv, timeSrv) { + + this.getPanelLinkAnchorInfo = function(link) { + var info = {}; + if (link.type === 'absolute') { + info.target = '_blank'; + info.href = templateSrv.replace(link.url); + info.title = templateSrv.replace(link.title); + info.href += '?'; + + } + else { + info.title = templateSrv.replace(link.title); + var slug = kbn.slugifyForUrl(link.dashboard); + info.href = '#dashboard/db/' + slug + '?'; + } + + var range = timeSrv.timeRangeForUrl(); + info.href += 'from=' + range.from; + info.href += '&to=' + range.to; + + if (link.params) { + info.href += "&" + link.params; + } + + return info; + }; + + }); +}); diff --git a/src/app/components/panellinkeditor/module.html b/src/app/components/panellinkeditor/module.html new file mode 100644 index 00000000000..2cbdc50e49b --- /dev/null +++ b/src/app/components/panellinkeditor/module.html @@ -0,0 +1,46 @@ +
+
+
Drilldown / detail linkThese links appear in the dropdown menu in the panel menu
+ +
+
+
    +
  • + +
  • + +
  • title
  • +
  • + +
  • + +
  • type
  • +
  • + +
  • + +
  • dashboard
  • +
  • + +
  • + +
  • url
  • +
  • + +
  • + +
  • params
  • +
  • + +
  • +
+
+
+
+
+
+ +
+
+ +
diff --git a/src/app/components/panellinkeditor/module.js b/src/app/components/panellinkeditor/module.js new file mode 100644 index 00000000000..fe6f9684f7f --- /dev/null +++ b/src/app/components/panellinkeditor/module.js @@ -0,0 +1,38 @@ +define([ + 'angular', + 'lodash', + './linkSrv', +], +function (angular, _) { + 'use strict'; + + angular + .module('grafana.directives') + .directive('panelLinkEditor', function() { + return { + scope: { + panel: "=" + }, + restrict: 'E', + controller: 'PanelLinkEditorCtrl', + templateUrl: 'app/components/panellinkeditor/module.html', + link: function() { + } + }; + }).controller('PanelLinkEditorCtrl', function($scope) { + + $scope.panel.links = $scope.panel.links || []; + + $scope.addLink = function() { + $scope.panel.links.push({ + type: 'dashboard', + name: 'Drilldown dashboard' + }); + }; + + $scope.deleteLink = function(link) { + $scope.panel.links = _.without($scope.panel.links, link); + }; + + }); +}); diff --git a/src/app/controllers/sharePanelCtrl.js b/src/app/controllers/sharePanelCtrl.js index cef550b8bd1..39909b20e19 100644 --- a/src/app/controllers/sharePanelCtrl.js +++ b/src/app/controllers/sharePanelCtrl.js @@ -27,19 +27,12 @@ function (angular, _) { } var panelId = $scope.panel.id; - var range = timeSrv.timeRange(false); var params = angular.copy($location.search()); - if (_.isString(range.to) && range.to.indexOf('now')) { - range = timeSrv.timeRange(); - } - + var range = timeSrv.timeRangeForUrl(); params.from = range.from; params.to = range.to; - if (_.isDate(params.from)) { params.from = params.from.getTime(); } - if (_.isDate(params.to)) { params.to = params.to.getTime(); } - if ($scope.includeTemplateVars) { _.each(templateSrv.variables, function(variable) { params['var-' + variable.name] = variable.current.text; diff --git a/src/app/directives/all.js b/src/app/directives/all.js index 7f7836728a6..15c2a5c80f7 100644 --- a/src/app/directives/all.js +++ b/src/app/directives/all.js @@ -19,5 +19,6 @@ define([ './graphiteSegment', './grafanaVersionCheck', './dropdown.typeahead', + 'components/panellinkeditor/module', './influxdbFuncEditor' ], function () {}); diff --git a/src/app/directives/panelMenu.js b/src/app/directives/panelMenu.js index b7318f7b9b3..13aed5f6f3e 100644 --- a/src/app/directives/panelMenu.js +++ b/src/app/directives/panelMenu.js @@ -8,7 +8,7 @@ function (angular, $, _) { angular .module('grafana.directives') - .directive('panelMenu', function($compile) { + .directive('panelMenu', function($compile, linkSrv) { var linkTemplate = '{{panel.title | interpolateTemplateVars}}'; function createMenuTemplate($scope) { @@ -22,7 +22,7 @@ function (angular, $, _) { template += ''; template += '
'; - template += ''; + template += ''; _.each($scope.panelMeta.menu, function(item) { template += '
+ + + + diff --git a/src/app/services/timeSrv.js b/src/app/services/timeSrv.js index 5a28532eb5a..564f30de7fd 100644 --- a/src/app/services/timeSrv.js +++ b/src/app/services/timeSrv.js @@ -95,6 +95,18 @@ define([ $timeout(this.refreshDashboard, 0); }; + this.timeRangeForUrl = function() { + var range = this.timeRange(false); + if (_.isString(range.to) && range.to.indexOf('now')) { + range = this.timeRange(); + } + + if (_.isDate(range.from)) { range.from = range.from.getTime(); } + if (_.isDate(range.to)) { range.to = range.to.getTime(); } + + return range; + }; + this.timeRange = function(parse) { var _t = this.time; if(_.isUndefined(_t) || _.isUndefined(_t.from)) { diff --git a/src/test/specs/sharePanelCtrl-specs.js b/src/test/specs/sharePanelCtrl-specs.js index 8c4eb2a2443..8c83f008ed5 100644 --- a/src/test/specs/sharePanelCtrl-specs.js +++ b/src/test/specs/sharePanelCtrl-specs.js @@ -7,6 +7,12 @@ define([ describe('SharePanelCtrl', function() { var ctx = new helpers.ControllerTestContext(); + function setTime(range) { + ctx.timeSrv.timeRangeForUrl = sinon.stub().returns(range); + } + + setTime({ from: 'now-1h', to: 'now' }); + beforeEach(module('grafana.controllers')); beforeEach(ctx.providePhase()); @@ -14,10 +20,12 @@ define([ describe('shareUrl with current time range and panel', function() { + it('should generate share url relative time', function() { ctx.$location.path('/test'); ctx.scope.panel = { id: 22 }; - ctx.timeSrv.time = { from: 'now-1h', to: 'now' }; + + setTime({ from: 'now-1h', to: 'now' }); ctx.scope.buildUrl(); expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now&panelId=22&fullscreen'); @@ -26,26 +34,17 @@ define([ it('should generate share url absolute time', function() { ctx.$location.path('/test'); ctx.scope.panel = { id: 22 }; - ctx.timeSrv.time = { from: new Date(1362178800000), to: new Date(1396648800000) }; + setTime({ from: 1362178800000, to: 1396648800000 }); ctx.scope.buildUrl(); expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=1362178800000&to=1396648800000&panelId=22&fullscreen'); }); - it('should generate share url with time as JSON strings', function() { - ctx.$location.path('/test'); - ctx.scope.panel = { id: 22 }; - ctx.timeSrv.time = { from: "2012-01-31T23:00:00.000Z", to: "2014-04-04T22:00:00.000Z" }; - - ctx.scope.buildUrl(); - expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=1328050800000&to=1396648800000&panelId=22&fullscreen'); - }); - it('should remove panel id when toPanel is false', function() { ctx.$location.path('/test'); ctx.scope.panel = { id: 22 }; ctx.scope.toPanel = false; - ctx.timeSrv.time = { from: 'now-1h', to: 'now' }; + setTime({ from: 'now-1h', to: 'now' }); ctx.scope.buildUrl(); expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now'); @@ -57,7 +56,7 @@ define([ ctx.scope.includeTemplateVars = true; ctx.scope.toPanel = false; ctx.templateSrv.variables = [{ name: 'app', current: {text: 'mupp' }}, {name: 'server', current: {text: 'srv-01'}}]; - ctx.timeSrv.time = { from: 'now-1h', to: 'now' }; + setTime({ from: 'now-1h', to: 'now' }); ctx.scope.buildUrl(); expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now&var-app=mupp&var-server=srv-01');