Merge branch 'pro' of github.com:torkelo/grafana-private into pro

Conflicts:
	src/css/less/grafana.less
	src/test/test-main.js
This commit is contained in:
Torkel Ödegaard
2014-09-20 08:57:40 +02:00
36 changed files with 294 additions and 133 deletions
+5 -2
View File
@@ -1,7 +1,10 @@
# 1.8.0 (2014-09-12)
# 1.8.0 (unreleased)
**Fixes**
- [Issue #802](https://github.com/grafana/grafana/issues/802). Annotations: Fix when using InfluxDB datasource
- [Issue #795](https://github.com/grafana/grafana/issues/795). Chrome: Fix for display issue in chrome beta & chrome canary when entering edit mode
- [Issue #818](https://github.com/grafana/grafana/issues/818). Graph: Added percent y-axis format
- [Issue #828](https://github.com/grafana/grafana/issues/828). Elasticsearch: saving new dashboard with title equal to slugified url would cause it to deleted.
# 1.8.0-RC1 (2014-09-12)
@@ -244,7 +247,7 @@ Read this for more info:
- More graphite function definitions
- Make "ms" axis format include hour, day, weeks, month and year ([Issue #149](https://github.com/grafana/grafana/issues/149))
- Microsecond axis format ([Issue #146](https://github.com/grafana/grafana/issues/146))
- Specify template paramaters in URL ([Issue #123](https://github.com/grafana/grafana/issues/123))
- Specify template parameters in URL ([Issue #123](https://github.com/grafana/grafana/issues/123))
### Fixes
- Basic Auth fix ([Issue #152](https://github.com/grafana/grafana/issues/152))
+8 -4
View File
@@ -531,6 +531,10 @@ function($, _, moment) {
return function(val) {
return kbn.nanosFormat(val, decimals);
};
case 'percent':
return function(val, axis) {
return kbn.noneFormat(val, axis ? axis.tickDecimals : null) + ' %';
};
default:
return function(val, axis) {
return kbn.noneFormat(val, axis ? axis.tickDecimals : null);
@@ -563,8 +567,8 @@ function($, _, moment) {
kbn.msFormat = function(size, decimals) {
// Less than 1 milli, downscale to micro
if (Math.abs(size) < 1) {
return kbn.microsFormat(size * 1000,decimals);
if (size !== 0 && Math.abs(size) < 1) {
return kbn.microsFormat(size * 1000, decimals);
}
else if (Math.abs(size) < 1000) {
return size.toFixed(decimals) + " ms";
@@ -591,7 +595,7 @@ function($, _, moment) {
kbn.sFormat = function(size, decimals) {
// Less than 1 sec, downscale to milli
if (Math.abs(size) < 1) {
if (size !== 0 && Math.abs(size) < 1) {
return kbn.msFormat(size * 1000, decimals);
}
// Less than 10 min, use seconds
@@ -620,7 +624,7 @@ function($, _, moment) {
kbn.microsFormat = function(size, decimals) {
// Less than 1 micro, downscale to nano
if (Math.abs(size) < 1) {
if (size !== 0 && Math.abs(size) < 1) {
return kbn.nanosFormat(size * 1000, decimals);
}
else if (Math.abs(size) < 1000) {
+1 -1
View File
@@ -1,5 +1,5 @@
define([
'./p_grafanaCtrl',
'./pro/grafanaCtrl',
'./dashboardCtrl',
'./dashboardNavCtrl',
'./row',
+2 -2
View File
@@ -78,7 +78,7 @@ function (angular, _, moment, config, store) {
var clone = angular.copy($scope.dashboard);
$scope.db.saveDashboard(clone)
.then(function(result) {
alertSrv.set('Dashboard Saved', 'Dashboard has been saved as "' + result.title + '"','success', 5000);
alertSrv.set('Dashboard Saved', 'Saved as "' + result.title + '"','success', 3000);
if (result.url !== $location.path()) {
$location.search({});
@@ -88,7 +88,7 @@ function (angular, _, moment, config, store) {
$rootScope.$emit('dashboard-saved', $scope.dashboard);
}, function(err) {
alertSrv.set('Save failed', err, 'error',5000);
alertSrv.set('Save failed', err, 'error', 5000);
});
};
@@ -11,10 +11,8 @@ function (angular, config, _, $, store) {
var module = angular.module('grafana.controllers');
module.controller('GrafanaCtrl', function($scope, alertSrv, grafanaVersion, $rootScope) {
$scope.grafanaVersion = grafanaVersion[0] === '@' ? 'master' : grafanaVersion;
$scope.consoleEnabled = store.getBool('grafanaConsole');
//$scope.showProSideMenu = store.getBool('grafanaProSideMenu');
$scope.grafana = {};
$rootScope.profilingEnabled = store.getBool('profilingEnabled');
$rootScope.performance = { loadStart: new Date().getTime() };
@@ -25,25 +23,27 @@ function (angular, config, _, $, store) {
if ($rootScope.profilingEnabled) { $scope.initProfiling(); }
$scope.dashAlerts = alertSrv;
$scope.grafana = { style: 'dark' };
$scope.grafana.style = 'dark';
$scope.grafana.sidemenu = store.getBool('grafana.sidemenu');
if (window.grafanaBootData.user.login) {
$scope.grafana.user = window.grafanaBootData.user;
}
$scope.onAppEvent('logged-out', function() {
$scope.showProSideMenu = false;
$scope.grafana.user = {};
});
$scope.onAppEvent('logged-in', function() {
$scope.showProSideMenu = store.getBool('grafanaProSideMenu');
$scope.onAppEvent('logged-in', function(evt, user) {
$scope.grafana.sidemenu = store.getBool('grafana.sidemenu');
$scope.grafana.user = user;
});
};
$scope.toggleProSideMenu = function() {
$scope.showProSideMenu = !$scope.showProSideMenu;
store.set('grafanaProSideMenu', $scope.showProSideMenu);
};
$scope.toggleConsole = function() {
$scope.consoleEnabled = !$scope.consoleEnabled;
store.set('grafanaConsole', $scope.consoleEnabled);
$scope.grafana.sidemenu = !$scope.grafana.sidemenu;
store.set('grafana.sidemenu', $scope.grafana.sidemenu);
};
$rootScope.onAppEvent = function(name, callback) {
@@ -8,6 +8,7 @@ function (angular) {
module.controller('LoginCtrl', function($scope, $http, $location, $routeParams, alertSrv) {
$scope.loginModel = {};
$scope.grafana.sidemenu = false;
$scope.init = function() {
if ($routeParams.logout) {
@@ -20,6 +21,7 @@ function (angular) {
alertSrv.set('Logged out!', '', 'success', 3000);
$scope.emitAppEvent('logged-out');
$location.search({});
}, function() {
alertSrv.set('Logout failed:', 'Unexpected error', 'error', 3000);
@@ -33,8 +35,8 @@ function (angular) {
return;
}
$http.post('/login', $scope.loginModel).then(function() {
$scope.emitAppEvent('logged-in');
$http.post('/login', $scope.loginModel).then(function(results) {
$scope.emitAppEvent('logged-in', results.data.user);
$location.path('/');
}, function(err) {
if (err.status === 401) {
+3 -2
View File
@@ -119,9 +119,10 @@ function (angular, _, config, $) {
$scope.searchDashboards($scope.query.query);
};
$scope.deleteDashboard = function(id, evt) {
$scope.deleteDashboard = function(dash, evt) {
evt.stopPropagation();
$scope.emitAppEvent('delete-dashboard', { id: id });
$scope.emitAppEvent('delete-dashboard', { id: dash.id });
$scope.results.dashboards = _.without($scope.results.dashboards, dash);
};
$scope.addMetricToCurrentDashboard = function (metricId) {
+1 -1
View File
@@ -17,7 +17,7 @@
"editable": true,
"type": "text",
"mode": "html",
"content": "<div class=\"text-center\" style=\"padding-top: 15px\">\n<img src=\"http://grafana.org/assets/img/logo_transparent_200x75.png\"> \n</div>",
"content": "<div class=\"text-center\" style=\"padding-top: 15px\">\n<img src=\"//grafana.org/assets/img/logo_transparent_200x75.png\"> \n</div>",
"style": {},
"title": "Welcome to"
}
+5
View File
@@ -110,6 +110,11 @@ function (angular, $, kbn, moment, _) {
// Populate element
var options = {
hooks: {
drawSeries: [function() {
console.log('drawSeries', arguments);
}]
},
legend: { show: false },
series: {
stackpercent: panel.stack ? panel.percentage : false,
+2 -2
View File
@@ -4,7 +4,7 @@
<h5>Left Y Axis</h5>
<div class="editor-option">
<label class="small">Format <tip>Y-axis formatting</tip></label>
<select class="input-small" ng-model="panel.y_formats[0]" ng-options="f for f in ['none','short','bytes', 'bits', 'bps', 's', 'ms', 'µs', 'ns']" ng-change="render()"></select>
<select class="input-small" ng-model="panel.y_formats[0]" ng-options="f for f in ['none','short','bytes', 'bits', 'bps', 's', 'ms', 'µs', 'ns', 'percent']" ng-change="render()"></select>
</div>
<div class="editor-option">
<label class="small">Min / <a ng-click="toggleGridMinMax('leftMin')">Auto <i class="icon-star" ng-show="_.isNull(panel.grid.leftMin)"></i></a></label>
@@ -23,7 +23,7 @@
<h5>Right Y Axis</h5>
<div class="editor-option">
<label class="small">Format <tip>Y-axis formatting</tip></label>
<select class="input-small" ng-model="panel.y_formats[1]" ng-options="f for f in ['none','short','bytes', 'bits', 'bps', 's', 'ms', 'µs', 'ns']" ng-change="render()"></select>
<select class="input-small" ng-model="panel.y_formats[1]" ng-options="f for f in ['none','short','bytes', 'bits', 'bps', 's', 'ms', 'µs', 'ns', 'percent']" ng-change="render()"></select>
</div>
<div class="editor-option">
<label class="small">Min / <a ng-click="toggleGridMinMax('rightMin')">Auto <i class="icon-star" ng-show="_.isNull(panel.grid.rightMin)"></i></a></label>
+1 -1
View File
@@ -70,7 +70,7 @@ define([
$scope.addOverrideOption('Staircase line', 'steppedLine', [true, false]);
$scope.addOverrideOption('Points', 'points', [true, false]);
$scope.addOverrideOption('Points Radius', 'pointradius', [1,2,3,4,5]);
$scope.addOverrideOption('Stack', 'stack', [true, false]);
$scope.addOverrideOption('Stack', 'stack', [true, false, 2, 3, 4, 5]);
$scope.addOverrideOption('Y-axis', 'yaxis', [1, 2]);
$scope.addOverrideOption('Z-index', 'zindex', [-1,-2,-3,0,1,2,3]);
$scope.updateCurrentOverrides();
+4 -1
View File
@@ -1,7 +1,10 @@
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<span class="brand"><img src="img/small.png" bs-tooltip="'Grafana'" data-placement="bottom"> {{dashboard.title}}</span>
<span class="brand">
<img class="logo-icon" src="img/fav32.png" bs-tooltip="'Grafana'" data-placement="bottom"></img>
<span class="page-title">{{dashboard.title}}</span>
</span>
<ul class="nav pull-right" ng-controller='DashboardNavCtrl' ng-init="init()">
<li ng-show="dashboardViewState.fullscreen">
+1 -1
View File
@@ -108,7 +108,7 @@
</li>
<li class="grafana-target-segment">
<a ng-click="toggleEditorHelp(2);" bs-tooltip="'click to show helpful info'" data-placement="bottom">
series as paramaters
series as parameters
</a>
</li>
<li class="grafana-target-segment">
+1 -1
View File
@@ -38,7 +38,7 @@
<div class="editor-option">
<div class="span4">
<span><i class="icon-question-sign"></i>
dashboards available in the playlist are only the once marked as favorites (stored in local browser storage).
dashboards available in the playlist are only the ones marked as favorites (stored in local browser storage).
to mark a dashboard as favorite, use save icon in the menu and in the dropdown select mark as favorite
<br/><br/>
</span>
+73
View File
@@ -0,0 +1,73 @@
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<span class="brand">
<a ng-click="toggleProSideMenu()">
<img class="logo-icon" src="img/fav32.png" bs-tooltip="'Grafana'" data-placement="bottom"></img>
</a>
<span class="page-title">Account Settings</span>
</span>
</div>
</div>
</div>
<div class="dashboard-edit-view">
<div class="dashboard-editor-header">
<div class="dashboard-editor-title">
<i class="icon icon-user"></i>
Personal information
</div>
</div>
<div class="dashboard-editor-body">
<div class="editor-row">
<div class="editor-option">
<label class="small">Name</label>
<input type="text" class="input-xxlarge" ng-model='currentAnnotation.name' placeholder="name"></input>
</div>
</div>
<div class="editor-row">
<div class="editor-option">
<label class="small">Email</label>
<input type="text" class="input-xxlarge" ng-model='currentAnnotation.name' placeholder="name"></input>
</div>
</div>
<div class="editor-row">
<div class="editor-option">
<label class="small">Account Name</label>
<input type="text" class="input-xxlarge" ng-model='currentAnnotation.name' placeholder="name"></input>
</div>
</div>
</div>
<div class="dashboard-editor-footer">
<button class="btn btn-success">Update</button>
</div>
</div>
<div class="dashboard-edit-view" style="border-top: solid 1px black;">
<div class="dashboard-editor-header">
<div class="dashboard-editor-title">
<i class="icon icon-eye-open"></i>
Collaborators
</div>
</div>
<div class="dashboard-editor-body">
<div class="editor-row">
<div class="editor-option">
<form name="addCollaboratorForm" class="form-inline">
<label class="small">Add a collaborator</label>
<input type="text" class="input-xxlarge" ng-model='collaborator.email' placeholder="collaborator@email.com"></input>
<button class="btn btn-success" ng-click="addCollaborator()">Add</button>
</form>
</div>
</div>
</div>
</div>
+2 -2
View File
@@ -3,9 +3,9 @@
<div class="container-fluid">
<span class="brand">
<a ng-click="toggleProSideMenu()">
<img src="img/small.png">
<img class="logo-icon" src="img/fav32.png" bs-tooltip="'Grafana'" data-placement="bottom"></img>
</a>
{{dashboard.title}}
<span class="page-title">{{dashboard.title}}</span>
</span>
<ul class="nav pull-right" ng-controller='DashboardNavCtrl' ng-init="init()">
+16 -19
View File
@@ -1,22 +1,14 @@
<div class="navbar navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<span class="brand">
<i class="icon-gears" style=""></i>
<span style="color: white; padding-left: 4px;">Grafana</span>
<ul class="nav" ng-controller='DashboardNavCtrl' ng-init="init()">
</span>
</ul>
</div>
</div>
</div>
<section class="pro-sidemenu-items">
<a class="pro-sidemenu-link pro-side-menu-user" href="/login?logout">
<img src="https://secure.gravatar.com/avatar/c8656e8972626f01e1703681d5e55f92?s=90&default=blank">
logout
</a>
<a class="pro-sidemenu-link" href="/dashboard/db/home">
<div class="dropdown">
<a class="pro-sidemenu-link pointer" data-toggle="dropdown">
<i class="icon-user"></i>
{{grafana.user.login}}
</a>
<ul class="dropdown-menu">
<li><a href="/login?logout">Logout</a>
</ul>
</div>
<a class="pro-sidemenu-link" href="/">
<i class="icon-th-large"></i>
Dashboards
</a>
@@ -36,10 +28,15 @@
<i class="icon-tasks"></i>
Global options
</a>
<a class="pro-sidemenu-link" href="/admin">
<a class="pro-sidemenu-link" href="/account">
<i class="icon-user"></i>
User accounts
</a>
<a class="pro-sidemenu-link" href="/login?logout">
<i class="icon-signout"></i>
Sign out
</a>
</section>
</div>
+1 -1
View File
@@ -54,7 +54,7 @@
<a ng-click="shareDashboard(row.id, row.id, $event)" config-modal="app/partials/dashLoaderShare.html">
<i class="icon-share"></i> share &nbsp;&nbsp;&nbsp;
</a>
<a ng-click="deleteDashboard(row.id, $event)">
<a ng-click="deleteDashboard(row, $event)">
<i class="icon-remove"></i> delete
</a>
</div>
+32
View File
@@ -14,8 +14,40 @@ function (angular) {
});
});
module.config(function($routeProvider) {
$routeProvider
.when('/account', {
templateUrl: 'app/partials/pro/account.html',
controller : 'AccountCtrl',
});
});
module.controller('AdminCtrl', function() {
});
module.controller('AccountCtrl', function($scope, $http, alertSrv) {
$scope.collaborator = {};
$scope.addCollaborator = function() {
if (!$scope.addCollaboratorForm.$valid) {
return;
}
$http.post('/api/account/collaborators/add', $scope.collaborator).then(function() {
alertSrv.set('Collaborator added', '', 'success', 3000);
}, function(err) {
if (err.data && err.data.status) {
alertSrv.set('Could not add collaborator', err.data.status, 'warning', 10000);
}
else if (err.statusText) {
alertSrv.set('Could not add collaborator', err.data.status, 'warning', 10000);
}
console.log("value", err);
});
};
});
});
+21 -3
View File
@@ -1,7 +1,8 @@
define([
'angular',
'store',
],
function (angular) {
function (angular, store) {
"use strict";
var module = angular.module('grafana.routes');
@@ -25,12 +26,29 @@ function (angular) {
});
});
module.controller('DashFromDBProvider', function($scope, $rootScope, datasourceSrv, $routeParams, alertSrv) {
module.controller('DashFromDBProvider', function(
$scope, $rootScope, datasourceSrv, $routeParams,
alertSrv, $http, $location) {
var db = datasourceSrv.getGrafanaDB();
var isTemp = window.location.href.indexOf('dashboard/temp') !== -1;
if (!$routeParams.id) {
$routeParams.id = 'default';
var savedRoute = store.get('grafanaDashboardDefault');
if (!savedRoute) {
$http.get("app/dashboards/default.json?" + new Date().getTime()).then(function(result) {
var dashboard = angular.fromJson(result.data);
$scope.emitAppEvent('setup-dashboard', dashboard);
},function() {
alertSrv.set('Error',"Could not load default dashboard", 'error');
});
return;
}
else {
$location.path(savedRoute);
return;
}
}
db.getDashboard($routeParams.id, isTemp)
+3 -52
View File
@@ -1,5 +1,6 @@
define([
'angular',
'../controllers/pro/loginCtrl',
],
function (angular) {
"use strict";
@@ -18,14 +19,9 @@ function (angular) {
});
});
module.controller('RegisterCtrl', function($scope, $http, $location, $routeParams) {
module.controller('RegisterCtrl', function($scope, $http, $location) {
$scope.loginModel = {};
$scope.init = function() {
if ($routeParams.logout) {
$scope.logout();
}
};
$scope.grafana.sidemenu = false;
$scope.register = function() {
delete $scope.registerError;
@@ -43,51 +39,6 @@ function (angular) {
});
};
$scope.init();
});
module.controller('LoginCtrl', function($scope, $http, $location, $routeParams, alertSrv) {
$scope.loginModel = {};
$scope.init = function() {
if ($routeParams.logout) {
$scope.logout();
}
};
$scope.logout = function() {
$http.post('/logout').then(function() {
alertSrv.set('Logged out!', '', 'success', 3000);
$scope.emitAppEvent('logged-out');
}, function() {
alertSrv.set('Logout failed:', 'Unexpected error', 'error', 3000);
});
};
$scope.login = function() {
delete $scope.loginError;
if (!$scope.loginForm.$valid) {
return;
}
$http.post('/login', $scope.loginModel).then(function() {
$scope.emitAppEvent('logged-in');
$location.path('/');
}, function(err) {
if (err.status === 401) {
$scope.loginError = "Username or password is incorrect";
}
else {
$scope.loginError = "Unexpected error";
}
});
};
$scope.init();
});
});
+1 -1
View File
@@ -131,7 +131,7 @@ function (angular, $, kbn, _, moment) {
if (old.services) {
if (old.services.filter) {
this.time = old.services.filter.time;
this.templating.list = old.services.filter.list;
this.templating.list = old.services.filter.list || [];
}
delete this.services;
}
@@ -37,6 +37,7 @@ function (angular, _, config, kbn, moment) {
};
if (this.basicAuth) {
options.withCredentials = true;
options.headers = {
"Authorization": "Basic " + this.basicAuth
};
@@ -168,7 +169,7 @@ function (angular, _, config, kbn, moment) {
return this._request('PUT', '/dashboard/' + id, this.index, data)
.then(function(results) {
self._removeUnslugifiedDashboard(results, title);
self._removeUnslugifiedDashboard(results, title, id);
return { title: title, url: '/dashboard/db/' + id };
}, function() {
throw 'Failed to save to elasticsearch';
@@ -176,8 +177,9 @@ function (angular, _, config, kbn, moment) {
}
};
ElasticDatasource.prototype._removeUnslugifiedDashboard = function(saveResult, title) {
ElasticDatasource.prototype._removeUnslugifiedDashboard = function(saveResult, title, id) {
if (saveResult.statusText !== 'Created') { return; }
if (title === id) { return; }
var self = this;
this._get('/dashboard/' + title).then(function() {
@@ -55,6 +55,15 @@ function (angular) {
});
};
GrafanaDatasource.prototype.deleteDashboard = function(id) {
return $http({ method: 'DELETE', url: '/api/dashboard/' + id })
.then(function(result) {
return result.data.title;
}, function(err) {
throw err.data;
});
};
GrafanaDatasource.prototype.searchDashboards = function(query) {
return $http.get('/api/search/', { params: { q: query } })
.then(function(results) {
+7
View File
@@ -86,6 +86,13 @@ function (_) {
category: categories.Calculate,
});
addFuncDef({
name: 'group',
params: optionalSeriesRefArgs,
defaultParams: ['#A', '#B'],
category: categories.Combine,
});
addFuncDef({
name: 'sumSeries',
shortName: 'sum',
+1 -1
View File
@@ -56,7 +56,7 @@ hr {
}
.brand {
padding: 15px 20px 15px;
padding: 0px 15px;
color: @grayLighter;
font-weight: normal;
text-shadow: none;
+1 -1
View File
@@ -59,6 +59,7 @@ a.text-success:hover { color: darken(@green, 10%); }
}
.brand {
padding: 0px 15px;
&:hover {
color: @navbarLinkColorHover;
@@ -461,7 +462,6 @@ legend {
// -----------------------------------------------------
.alert {
.border-radius(0);
text-shadow: none;
&-heading, h1, h2, h3, h4, h5, h6 {
+21 -6
View File
@@ -3,6 +3,9 @@
@import "graph.less";
@import "console.less";
@import "bootstrap-tagsinput.less";
@import "tables_lists.less";
@import "search.less";
@import "panel.less";
.hide-controls {
padding: 0;
@@ -33,6 +36,19 @@
}
}
.logo-icon {
width: 24px;
padding: 13px 11px 0 0;
display: block;
float: left;
}
.page-title {
padding: 15px 0;
display: block;
float: left;
}
.row-button {
width: 24px;
}
@@ -85,7 +101,7 @@
.panel-fullscreen {
z-index: 100;
display: block !important;
display: block;
position: fixed;
left: 0px;
right: 0px;
@@ -101,11 +117,10 @@
}
}
.dashboard-fullscreen .main-view-container {
height: 0px;
width: 0px;
position: fixed;
right: -10000px;
.dashboard-fullscreen {
.row-control-inner {
display: none;
}
}
.histogram-chart {
+31 -6
View File
@@ -317,13 +317,38 @@ div.flot-text {
color: @textColor !important;
}
.dashboard-notice {
.page-alert-list {
z-index:8000;
margin-left:0px;
padding:3px 0px 3px 0px;
width:100%;
padding-left:20px;
color: @white;
min-width: 300px;
max-width: 300px;
position: fixed;
right: 20px;
top: 56px;
.alert {
color: @white;
padding-bottom: 13px;
position: relative;
}
.alert-close {
position: absolute;
top: -4px;
right: -2px;
width: 19px;
height: 19px;
padding: 0;
background: @grayLighter;
border-radius: 50%;
border: none;
font-size: 1.1rem;
color: @grayDarker;
}
.alert-title {
font-weight: bold;
padding-bottom: 2px;
}
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

+13 -6
View File
@@ -5,9 +5,11 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<meta name="google" value="notranslate">
<title>Grafana</title>
<link rel="stylesheet" href="css/grafana.dark.min.css" title="Dark">
<link rel="icon" type="image/png" href="img/fav32.png">
<!-- build:js app/app.js -->
<script src="vendor/require/require.js"></script>
@@ -22,12 +24,17 @@
<link rel="stylesheet" href="css/grafana.light.min.css" ng-if="grafana.style === 'light'">
<div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} dashboard-notice" ng-show="$last">
<button type="button" class="close" ng-click="dashAlerts.clear(alert)" style="padding-right:50px">&times;</button>
<strong>{{alert.title}}</strong> <span ng-bind-html='alert.text'></span> <div style="padding-right:10px" class='pull-right small'> {{$index + 1}} alert(s) </div>
</div>
<div class="page-alert-list">
<div ng-repeat='alert in dashAlerts.list' class="alert-{{alert.severity}} alert">
<button type="button" class="alert-close" ng-click="dashAlerts.clear(alert)">
<i class="icon-remove-sign"></i>
</button>
<div class="alert-title">{{alert.title}}</div>
<div ng-bind-html='alert.text'></div>
</div>
</div>
<div ng-view></div>
<div ng-view></div>
</body>
</body>
</html>
+6
View File
@@ -15,6 +15,12 @@ define([
expect(str).to.be('1.02 hour');
});
it('should not downscale when value is zero', function() {
var str = kbn.msFormat(0, 2);
expect(str).to.be('0.00 ms');
});
it('should translate 365445 as 6.09 min', function() {
var str = kbn.msFormat(365445, 2);
expect(str).to.be('6.09 min');
+1
View File
@@ -135,6 +135,7 @@ require([
'specs/kbn-format-specs',
'specs/dashboardSrv-specs',
'specs/dashboardViewStateSrv-specs',
'specs/overview-ctrl-specs',
], function () {
window.__karma__.start();
});