Pārlūkot izejas kodu

Dashboard and nav links are near completion now, #1944

Torkel Ödegaard 10 gadi atpakaļ
vecāks
revīzija
0bde1bb857

+ 1 - 1
public/app/features/dashboard/partials/settings.html

@@ -107,7 +107,7 @@
 	</div>
 
 	<div ng-if="editor.index == 2">
-		<dash-links-editor dashboard="dashboard"></dash-links-editor>
+		<dash-links-editor></dash-links-editor>
 	</div>
 
 	<div ng-repeat="pulldown in dashboard.nav" ng-controller="SubmenuCtrl" ng-show="editor.index == 3+$index">

+ 4 - 22
public/app/features/dashboard/shareModalCtrl.js

@@ -9,7 +9,8 @@ function (angular, _, require, config) {
 
   var module = angular.module('grafana.controllers');
 
-  module.controller('ShareModalCtrl', function($scope, $rootScope, $location, $timeout, timeSrv, $element, templateSrv) {
+  module.controller('ShareModalCtrl', function($scope, $rootScope, $location, $timeout, timeSrv, $element, templateSrv, linkSrv) {
+
     $scope.options = { forCurrent: true, includeTemplateVars: true, theme: 'current' };
     $scope.editor = { index: 0 };
 
@@ -47,14 +48,7 @@ function (angular, _, require, config) {
       params.to = range.to;
 
       if ($scope.options.includeTemplateVars) {
-        _.each(templateSrv.variables, function(variable) {
-          params['var-' + variable.name] = variable.current.text;
-        });
-      }
-      else {
-        _.each(templateSrv.variables, function(variable) {
-          delete params['var-' + variable.name];
-        });
+        templateSrv.fillVariableValuesForUrl(params);
       }
 
       if (!$scope.options.forCurrent) {
@@ -74,19 +68,7 @@ function (angular, _, require, config) {
         delete params.fullscreen;
       }
 
-      var paramsArray = [];
-      _.each(params, function(value, key) {
-        if (value === null) { return; }
-        if (value === true) {
-          paramsArray.push(key);
-        } else {
-          key += '=' + encodeURIComponent(value);
-          paramsArray.push(key);
-        }
-      });
-
-      var queryParams = "?" + paramsArray.join('&');
-      $scope.shareUrl = baseUrl + queryParams;
+      $scope.shareUrl = linkSrv.addParamsToUrl(baseUrl, params);
 
       var soloUrl = $scope.shareUrl;
       soloUrl = soloUrl.replace('/dashboard/db/', '/dashboard/solo/db/');

+ 15 - 19
public/app/features/dashlinks/editor.html

@@ -9,7 +9,7 @@
 					<i ng-click="moveLink($index, 1)" ng-hide="$last" class="pointer fa fa-fw fa-arrow-down"></i>
 				</li>
 				<li class="tight-form-item last">
-					<i class="fa fa-remove pointer" ng-click="deleteLink(link)"></i>
+					<i class="fa fa-remove pointer" ng-click="deleteLink($index)"></i>
 				</li>
 			</ul>
 
@@ -36,8 +36,6 @@
 				<li ng-show="link.type === 'dashboards' && link.asDropdown">
 					<input type="text" ng-model="link.title" class="input-medium tight-form-input" ng-model-onblur ng-change="updated()">
 				</li>
-
-
 				<li class="tight-form-item" ng-show="link.type === 'link'" style="width: 51px">Url</li>
 				<li ng-show="link.type === 'link'">
 					<input type="text" ng-model="link.url" class="input-xlarge tight-form-input" style="width: 302px;" ng-model-onblur ng-change="updated()">
@@ -68,24 +66,22 @@
 			</ul>
 			<div class="clearfix"></div>
 		</div>
+		<div class="tight-form">
+			<ul class="tight-form-list">
+				<li class="tight-form-item" style="width: 20px">
+					<i class="fa fa-fw fa-unlink invisible"></i>
+				</li>
+				<li class="tight-form-item">
+					<editor-checkbox text="Keep current time range" model="link.keepTime" change="updated()"></editor-checkbox>
+				</li>
+				<li class="tight-form-item">
+					<editor-checkbox text="Add current variable values" model="link.includeVars" change="updated()"></editor-checkbox>
+				</li>
+			</ul>
+			<div class="clearfix"></div>
+		</div>
 	</div>
 </div>
-<!-- <div class="tight&#45;form"> -->
-	<!-- 	<ul class="tight&#45;form&#45;list" role="menu"> -->
-		<!-- 		<li class="tight&#45;form&#45;item"> -->
-			<!-- 			<i class="fa fa&#45;remove invisible"></i> -->
-			<!-- 		</li> -->
-		<!-- 		<li class="tight&#45;form&#45;item" style="width: 80px;"> -->
-			<!-- 			Params -->
-			<!-- 			<tip>Use var&#45;variableName=value to pass templating variables.</tip> -->
-			<!-- 		</li> -->
-		<!-- 		<li> -->
-			<!-- 			<input type="text" ng&#45;model="link.params" class="input&#45;xxlarge tight&#45;form&#45;input"> -->
-			<!-- 		</li> -->
-		<!-- 	</ul> -->
-	<!-- 	<div class="clearfix"></div> -->
-	<!-- </div> -->
-
 <div class="editor-row">
 	<br>
 	<button class="btn btn-inverse" ng-click="addLink()"><i class="fa fa-plus"></i> Add link</button>

+ 27 - 10
public/app/features/dashlinks/module.js

@@ -19,9 +19,6 @@ function (angular, _) {
 
   module.directive('dashLinksEditor', function() {
     return {
-      scope: {
-        dashboard: "="
-      },
       restrict: 'E',
       controller: 'DashLinkEditorCtrl',
       templateUrl: 'app/features/dashlinks/editor.html',
@@ -76,6 +73,11 @@ function (angular, _) {
         icon.attr('class', 'fa fa-fw ' + scope.link.icon);
         anchor.attr('target', scope.link.target);
 
+        // fix for menus on the far right
+        if (link.asDropdown && scope.$last) {
+          elem.find('.dropdown-menu').addClass('pull-right');
+        }
+
         update();
         scope.$on('refresh', update);
       }
@@ -96,12 +98,14 @@ function (angular, _) {
           return $q.when([{
             title: linkDef.title,
             tag: linkDef.tag,
+            keepTime: linkDef.keepTime,
+            includeVars: linkDef.includeVars,
             icon: "fa fa-bars",
             asDropdown: true
           }]);
         }
 
-        return $scope.searchDashboards(linkDef.tag);
+        return $scope.searchDashboards(linkDef);
       }
 
       if (linkDef.type === 'link') {
@@ -111,6 +115,8 @@ function (angular, _) {
           icon: iconMap[linkDef.icon],
           tooltip: linkDef.tooltip,
           target: linkDef.targetBlank ? "_blank" : "",
+          keepTime: linkDef.keepTime,
+          includeVars: linkDef.includeVars,
         }]);
       }
 
@@ -125,12 +131,18 @@ function (angular, _) {
       });
     }
 
-    $scope.searchDashboards = function(tag) {
-      return backendSrv.search({tag: tag}).then(function(results) {
+    $scope.searchDashboards = function(link) {
+      return backendSrv.search({tag: link.tag}).then(function(results) {
         return _.reduce(results.dashboards, function(memo, dash) {
           // do not add current dashboard
           if (dash.id !== currentDashId) {
-            memo.push({ title: dash.title, url: 'dashboard/db/'+ dash.slug, icon: 'fa fa-th-large', addTime: true });
+            memo.push({
+              title: dash.title,
+              url: 'dashboard/db/'+ dash.slug,
+              icon: 'fa fa-th-large',
+              keepTime: link.keepTime,
+              includeVars: link.includeVars
+            });
           }
           return memo;
         }, []);
@@ -138,7 +150,7 @@ function (angular, _) {
     };
 
     $scope.fillDropdown = function(link) {
-      $scope.searchDashboards(link.tag).then(function(results) {
+      $scope.searchDashboards(link).then(function(results) {
         _.each(results, function(hit) {
           hit.url = linkSrv.getLinkUrl(hit);
         });
@@ -154,8 +166,11 @@ function (angular, _) {
 
     $scope.iconMap = iconMap;
     $scope.dashboard.links = $scope.dashboard.links || [];
+
     $scope.addLink = function() {
       $scope.dashboard.links.push({ type: 'dashboards', icon: 'external link' });
+      $scope.updateSubmenuVisibility();
+      $scope.updated();
     };
 
     $scope.moveLink = function(index, dir) {
@@ -167,8 +182,10 @@ function (angular, _) {
       $rootScope.appEvent('dash-links-updated');
     };
 
-    $scope.deleteLink = function(link) {
-      $scope.dashboard.links = _.without($scope.dashboard.links, link);
+    $scope.deleteLink = function(index) {
+      $scope.dashboard.links.splice(index, 1);
+      $scope.updateSubmenuVisibility();
+      $scope.updated();
     };
 
   });

+ 33 - 41
public/app/features/panellinks/linkSrv.js

@@ -1,63 +1,55 @@
 define([
   'angular',
   'kbn',
+  'lodash',
 ],
-function (angular, kbn) {
+function (angular, kbn, _) {
   'use strict';
 
   angular
     .module('grafana.services')
     .service('linkSrv', function(templateSrv, timeSrv) {
 
-      // parseUri 1.2.2
-      // (c) Steven Levithan <stevenlevithan.com>
-      // MIT License
+      this.getLinkUrl = function(link) {
+        var url = templateSrv.replace(link.url || '');
+        var params = {};
 
-      function parseUri (str) {
-        var	o   = parseUri.options,
-          m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
-          uri = {},
-          i   = 14;
+        if (link.keepTime) {
+          var range = timeSrv.timeRangeForUrl();
+          params['from'] = range.from;
+          params['to'] = range.to;
+        }
 
-        while (i--) {
-          uri[o.key[i]] = m[i] || "";
+        if (link.includeVars) {
+          templateSrv.fillVariableValuesForUrl(params);
         }
 
-        uri[o.q.name] = {};
-        uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
-          if ($1) {
-            uri[o.q.name][$1] = $2;
+        return this.addParamsToUrl(url, params);
+      };
+
+      this.addParamsToUrl = function(url, params) {
+        var paramsArray = [];
+        _.each(params, function(value, key) {
+          if (value === null) { return; }
+          if (value === true) {
+            paramsArray.push(key);
+          }
+          else if (_.isArray(value)) {
+            _.each(value, function(instance) {
+              paramsArray.push(key + '=' + encodeURIComponent(instance));
+            });
+          }
+          else {
+            paramsArray.push(key + '=' + encodeURIComponent(value));
           }
         });
 
-        return uri;
-      }
-
-      parseUri.options = {
-        strictMode: false,
-        key: ["source","protocol","authority","userInfo","user","password","host",
-              "port","relative","path","directory","file","query","anchor"],
-        q:   {
-          name:   "queryKey",
-          parser: /(?:^|&)([^&=]*)=?([^&]*)/g
-        },
-        /* jshint ignore:start */
-        parser: {
-          strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
-          loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
+        if (paramsArray.length === 0) {
+          return url;
         }
-        /* jshint ignore:end */
-      };
 
-      this.getLinkUrl = function(link) {
-        var href = templateSrv.replace(link.url || '');
-        if (link.addTime) {
-          var range = timeSrv.timeRangeForUrl();
-          href += (href.indexOf('?') !== -1 ? '&' : '?');
-          href += 'from=' + range.from;
-          href += '&to=' + range.to;
-        }
-        return href;
+        url += (url.indexOf('?') !== -1 ? '&' : '?');
+        return url + paramsArray.join('&');
       };
 
       this.getAnchorInfo = function(link) {

+ 8 - 2
public/app/features/templating/templateSrv.js

@@ -76,7 +76,7 @@ function (angular, _) {
     };
 
     this.replace = function(target, scopedVars) {
-      if (!target) { return; }
+      if (!target) { return target; }
 
       var value;
       this._regex.lastIndex = 0;
@@ -95,7 +95,7 @@ function (angular, _) {
     };
 
     this.replaceWithText = function(target, scopedVars) {
-      if (!target) { return; }
+      if (!target) { return target; }
 
       var value;
       var text;
@@ -115,6 +115,12 @@ function (angular, _) {
       });
     };
 
+    this.fillVariableValuesForUrl = function(params) {
+      _.each(this.variables, function(variable) {
+        params['var-' + variable.name] = variable.current.value;
+      });
+    };
+
   });
 
 });

+ 1 - 0
public/css/less/submenu.less

@@ -94,4 +94,5 @@
 }
 
 .dash-nav-link {
+  color: @textColor;
 }

+ 1 - 0
public/test/specs/helpers.js

@@ -131,6 +131,7 @@ define([
       return _.template(text, this.data,  this.templateSettings);
     };
     this.init = function() {};
+    this.fillVariableValuesForUrl = function() {};
     this.updateTemplateData = function() { };
     this.variableExists = function() { return false; };
     this.highlightVariablesAsHtml = function(str) { return str; };

+ 8 - 2
public/test/specs/shareModalCtrl-specs.js

@@ -1,6 +1,7 @@
 define([
   'helpers',
-  'features/dashboard/shareModalCtrl'
+  'features/dashboard/shareModalCtrl',
+  'features/panellinks/linkSrv',
 ], function(helpers) {
   'use strict';
 
@@ -14,8 +15,10 @@ define([
     setTime({ from: 'now-1h', to: 'now' });
 
     beforeEach(module('grafana.controllers'));
+    beforeEach(module('grafana.services'));
 
     beforeEach(ctx.providePhase());
+
     beforeEach(ctx.createControllerPhase('ShareModalCtrl'));
 
     describe('shareUrl with current time range and panel', function() {
@@ -63,8 +66,11 @@ define([
         ctx.$location.path('/test');
         ctx.scope.options.includeTemplateVars = true;
 
-        ctx.templateSrv.variables = [{ name: 'app', current: {text: 'mupp' }}, {name: 'server', current: {text: 'srv-01'}}];
         setTime({ from: 'now-1h', to: 'now' });
+        ctx.templateSrv.fillVariableValuesForUrl = function(params) {
+          params['var-app'] = 'mupp';
+          params['var-server'] = 'srv-01';
+        };
 
         ctx.scope.buildUrl();
         expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now&var-app=mupp&var-server=srv-01');