Commit 0bde1bb8 by Torkel Ödegaard

Dashboard and nav links are near completion now, #1944

parent 4b4f398e
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
</div> </div>
<div ng-if="editor.index == 2"> <div ng-if="editor.index == 2">
<dash-links-editor dashboard="dashboard"></dash-links-editor> <dash-links-editor></dash-links-editor>
</div> </div>
<div ng-repeat="pulldown in dashboard.nav" ng-controller="SubmenuCtrl" ng-show="editor.index == 3+$index"> <div ng-repeat="pulldown in dashboard.nav" ng-controller="SubmenuCtrl" ng-show="editor.index == 3+$index">
......
...@@ -9,7 +9,8 @@ function (angular, _, require, config) { ...@@ -9,7 +9,8 @@ function (angular, _, require, config) {
var module = angular.module('grafana.controllers'); 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.options = { forCurrent: true, includeTemplateVars: true, theme: 'current' };
$scope.editor = { index: 0 }; $scope.editor = { index: 0 };
...@@ -47,14 +48,7 @@ function (angular, _, require, config) { ...@@ -47,14 +48,7 @@ function (angular, _, require, config) {
params.to = range.to; params.to = range.to;
if ($scope.options.includeTemplateVars) { if ($scope.options.includeTemplateVars) {
_.each(templateSrv.variables, function(variable) { templateSrv.fillVariableValuesForUrl(params);
params['var-' + variable.name] = variable.current.text;
});
}
else {
_.each(templateSrv.variables, function(variable) {
delete params['var-' + variable.name];
});
} }
if (!$scope.options.forCurrent) { if (!$scope.options.forCurrent) {
...@@ -74,19 +68,7 @@ function (angular, _, require, config) { ...@@ -74,19 +68,7 @@ function (angular, _, require, config) {
delete params.fullscreen; delete params.fullscreen;
} }
var paramsArray = []; $scope.shareUrl = linkSrv.addParamsToUrl(baseUrl, params);
_.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;
var soloUrl = $scope.shareUrl; var soloUrl = $scope.shareUrl;
soloUrl = soloUrl.replace('/dashboard/db/', '/dashboard/solo/db/'); soloUrl = soloUrl.replace('/dashboard/db/', '/dashboard/solo/db/');
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<i ng-click="moveLink($index, 1)" ng-hide="$last" class="pointer fa fa-fw fa-arrow-down"></i> <i ng-click="moveLink($index, 1)" ng-hide="$last" class="pointer fa fa-fw fa-arrow-down"></i>
</li> </li>
<li class="tight-form-item last"> <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> </li>
</ul> </ul>
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
<li ng-show="link.type === 'dashboards' && link.asDropdown"> <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()"> <input type="text" ng-model="link.title" class="input-medium tight-form-input" ng-model-onblur ng-change="updated()">
</li> </li>
<li class="tight-form-item" ng-show="link.type === 'link'" style="width: 51px">Url</li> <li class="tight-form-item" ng-show="link.type === 'link'" style="width: 51px">Url</li>
<li ng-show="link.type === 'link'"> <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()"> <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 @@ ...@@ -68,24 +66,22 @@
</ul> </ul>
<div class="clearfix"></div> <div class="clearfix"></div>
</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> </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"> <div class="editor-row">
<br> <br>
<button class="btn btn-inverse" ng-click="addLink()"><i class="fa fa-plus"></i> Add link</button> <button class="btn btn-inverse" ng-click="addLink()"><i class="fa fa-plus"></i> Add link</button>
......
...@@ -19,9 +19,6 @@ function (angular, _) { ...@@ -19,9 +19,6 @@ function (angular, _) {
module.directive('dashLinksEditor', function() { module.directive('dashLinksEditor', function() {
return { return {
scope: {
dashboard: "="
},
restrict: 'E', restrict: 'E',
controller: 'DashLinkEditorCtrl', controller: 'DashLinkEditorCtrl',
templateUrl: 'app/features/dashlinks/editor.html', templateUrl: 'app/features/dashlinks/editor.html',
...@@ -76,6 +73,11 @@ function (angular, _) { ...@@ -76,6 +73,11 @@ function (angular, _) {
icon.attr('class', 'fa fa-fw ' + scope.link.icon); icon.attr('class', 'fa fa-fw ' + scope.link.icon);
anchor.attr('target', scope.link.target); 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(); update();
scope.$on('refresh', update); scope.$on('refresh', update);
} }
...@@ -96,12 +98,14 @@ function (angular, _) { ...@@ -96,12 +98,14 @@ function (angular, _) {
return $q.when([{ return $q.when([{
title: linkDef.title, title: linkDef.title,
tag: linkDef.tag, tag: linkDef.tag,
keepTime: linkDef.keepTime,
includeVars: linkDef.includeVars,
icon: "fa fa-bars", icon: "fa fa-bars",
asDropdown: true asDropdown: true
}]); }]);
} }
return $scope.searchDashboards(linkDef.tag); return $scope.searchDashboards(linkDef);
} }
if (linkDef.type === 'link') { if (linkDef.type === 'link') {
...@@ -111,6 +115,8 @@ function (angular, _) { ...@@ -111,6 +115,8 @@ function (angular, _) {
icon: iconMap[linkDef.icon], icon: iconMap[linkDef.icon],
tooltip: linkDef.tooltip, tooltip: linkDef.tooltip,
target: linkDef.targetBlank ? "_blank" : "", target: linkDef.targetBlank ? "_blank" : "",
keepTime: linkDef.keepTime,
includeVars: linkDef.includeVars,
}]); }]);
} }
...@@ -125,12 +131,18 @@ function (angular, _) { ...@@ -125,12 +131,18 @@ function (angular, _) {
}); });
} }
$scope.searchDashboards = function(tag) { $scope.searchDashboards = function(link) {
return backendSrv.search({tag: tag}).then(function(results) { return backendSrv.search({tag: link.tag}).then(function(results) {
return _.reduce(results.dashboards, function(memo, dash) { return _.reduce(results.dashboards, function(memo, dash) {
// do not add current dashboard // do not add current dashboard
if (dash.id !== currentDashId) { 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; return memo;
}, []); }, []);
...@@ -138,7 +150,7 @@ function (angular, _) { ...@@ -138,7 +150,7 @@ function (angular, _) {
}; };
$scope.fillDropdown = function(link) { $scope.fillDropdown = function(link) {
$scope.searchDashboards(link.tag).then(function(results) { $scope.searchDashboards(link).then(function(results) {
_.each(results, function(hit) { _.each(results, function(hit) {
hit.url = linkSrv.getLinkUrl(hit); hit.url = linkSrv.getLinkUrl(hit);
}); });
...@@ -154,8 +166,11 @@ function (angular, _) { ...@@ -154,8 +166,11 @@ function (angular, _) {
$scope.iconMap = iconMap; $scope.iconMap = iconMap;
$scope.dashboard.links = $scope.dashboard.links || []; $scope.dashboard.links = $scope.dashboard.links || [];
$scope.addLink = function() { $scope.addLink = function() {
$scope.dashboard.links.push({ type: 'dashboards', icon: 'external link' }); $scope.dashboard.links.push({ type: 'dashboards', icon: 'external link' });
$scope.updateSubmenuVisibility();
$scope.updated();
}; };
$scope.moveLink = function(index, dir) { $scope.moveLink = function(index, dir) {
...@@ -167,8 +182,10 @@ function (angular, _) { ...@@ -167,8 +182,10 @@ function (angular, _) {
$rootScope.appEvent('dash-links-updated'); $rootScope.appEvent('dash-links-updated');
}; };
$scope.deleteLink = function(link) { $scope.deleteLink = function(index) {
$scope.dashboard.links = _.without($scope.dashboard.links, link); $scope.dashboard.links.splice(index, 1);
$scope.updateSubmenuVisibility();
$scope.updated();
}; };
}); });
......
define([ define([
'angular', 'angular',
'kbn', 'kbn',
'lodash',
], ],
function (angular, kbn) { function (angular, kbn, _) {
'use strict'; 'use strict';
angular angular
.module('grafana.services') .module('grafana.services')
.service('linkSrv', function(templateSrv, timeSrv) { .service('linkSrv', function(templateSrv, timeSrv) {
// parseUri 1.2.2 this.getLinkUrl = function(link) {
// (c) Steven Levithan <stevenlevithan.com> var url = templateSrv.replace(link.url || '');
// MIT License var params = {};
function parseUri (str) { if (link.keepTime) {
var o = parseUri.options, var range = timeSrv.timeRangeForUrl();
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), params['from'] = range.from;
uri = {}, params['to'] = range.to;
i = 14; }
while (i--) { if (link.includeVars) {
uri[o.key[i]] = m[i] || ""; templateSrv.fillVariableValuesForUrl(params);
} }
uri[o.q.name] = {}; return this.addParamsToUrl(url, params);
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { };
if ($1) {
uri[o.q.name][$1] = $2; 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));
}); });
return uri;
} }
else {
parseUri.options = { paramsArray.push(key + '=' + encodeURIComponent(value));
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*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
} }
/* jshint ignore:end */ });
};
this.getLinkUrl = function(link) { if (paramsArray.length === 0) {
var href = templateSrv.replace(link.url || ''); return 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) { this.getAnchorInfo = function(link) {
......
...@@ -76,7 +76,7 @@ function (angular, _) { ...@@ -76,7 +76,7 @@ function (angular, _) {
}; };
this.replace = function(target, scopedVars) { this.replace = function(target, scopedVars) {
if (!target) { return; } if (!target) { return target; }
var value; var value;
this._regex.lastIndex = 0; this._regex.lastIndex = 0;
...@@ -95,7 +95,7 @@ function (angular, _) { ...@@ -95,7 +95,7 @@ function (angular, _) {
}; };
this.replaceWithText = function(target, scopedVars) { this.replaceWithText = function(target, scopedVars) {
if (!target) { return; } if (!target) { return target; }
var value; var value;
var text; var text;
...@@ -115,6 +115,12 @@ function (angular, _) { ...@@ -115,6 +115,12 @@ function (angular, _) {
}); });
}; };
this.fillVariableValuesForUrl = function(params) {
_.each(this.variables, function(variable) {
params['var-' + variable.name] = variable.current.value;
});
};
}); });
}); });
...@@ -94,4 +94,5 @@ ...@@ -94,4 +94,5 @@
} }
.dash-nav-link { .dash-nav-link {
color: @textColor;
} }
...@@ -131,6 +131,7 @@ define([ ...@@ -131,6 +131,7 @@ define([
return _.template(text, this.data, this.templateSettings); return _.template(text, this.data, this.templateSettings);
}; };
this.init = function() {}; this.init = function() {};
this.fillVariableValuesForUrl = function() {};
this.updateTemplateData = function() { }; this.updateTemplateData = function() { };
this.variableExists = function() { return false; }; this.variableExists = function() { return false; };
this.highlightVariablesAsHtml = function(str) { return str; }; this.highlightVariablesAsHtml = function(str) { return str; };
......
define([ define([
'helpers', 'helpers',
'features/dashboard/shareModalCtrl' 'features/dashboard/shareModalCtrl',
'features/panellinks/linkSrv',
], function(helpers) { ], function(helpers) {
'use strict'; 'use strict';
...@@ -14,8 +15,10 @@ define([ ...@@ -14,8 +15,10 @@ define([
setTime({ from: 'now-1h', to: 'now' }); setTime({ from: 'now-1h', to: 'now' });
beforeEach(module('grafana.controllers')); beforeEach(module('grafana.controllers'));
beforeEach(module('grafana.services'));
beforeEach(ctx.providePhase()); beforeEach(ctx.providePhase());
beforeEach(ctx.createControllerPhase('ShareModalCtrl')); beforeEach(ctx.createControllerPhase('ShareModalCtrl'));
describe('shareUrl with current time range and panel', function() { describe('shareUrl with current time range and panel', function() {
...@@ -63,8 +66,11 @@ define([ ...@@ -63,8 +66,11 @@ define([
ctx.$location.path('/test'); ctx.$location.path('/test');
ctx.scope.options.includeTemplateVars = true; 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' }); setTime({ from: 'now-1h', to: 'now' });
ctx.templateSrv.fillVariableValuesForUrl = function(params) {
params['var-app'] = 'mupp';
params['var-server'] = 'srv-01';
};
ctx.scope.buildUrl(); ctx.scope.buildUrl();
expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now&var-app=mupp&var-server=srv-01'); expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now&var-app=mupp&var-server=srv-01');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment