Commit b0fe6982 by Torkel Ödegaard

Merge branch 'master' into alerting

Conflicts:
	public/app/core/services/alert_srv.ts
	public/app/partials/confirm_modal.html
parents f13b869a 3f861dd0
......@@ -5,8 +5,13 @@
* **SingleStat**: Add seriename as option in singlestat panel, closes [#4740](https://github.com/grafana/grafana/issues/4740)
* **Localization**: Week start day now dependant on browser locale setting, closes [#3003](https://github.com/grafana/grafana/issues/3003)
* **Templating**: Update panel repeats for variables that change on time refresh, closes [#5021](https://github.com/grafana/grafana/issues/5021)
* **Elasticsearch**: Support to set Precision Threshold for Unique Count metric, closes [#4689](https://github.com/grafana/grafana/issues/4689)
# 3.1.0 stable (unreleased)
# 3.1.1 (unreleased / v3.1.x branch)
* **IFrame embedding**: Fixed issue of using full iframe height, fixes [#5605](https://github.com/grafana/grafana/issues/5606)
* **Panel PNG rendering**: Fixed issue detecting render completion, fixes [#5605](https://github.com/grafana/grafana/issues/5606)
# 3.1.0 stable (2016-07-12)
### Bugfixes & Enhancements,
* **User Alert Notices**: Backend error alert popups did not show properly, fixes [#5435](https://github.com/grafana/grafana/issues/5435)
......
......@@ -10,20 +10,13 @@ page_keywords: grafana, installation, debian, ubuntu, guide
Description | Download
------------ | -------------
Stable .deb for Debian-based Linux | [3.0.4](https://grafanarel.s3.amazonaws.com/builds/grafana_3.0.4-1464167696_amd64.deb)
Beta .deb for Debian-based Linux | [3.1.0-beta1](https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.0-1466666977beta1_amd64.deb)
Stable .deb for Debian-based Linux | [3.1.0](https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.0-1468321182_amd64.deb)
## Install Stable
$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_3.0.4-1464167696_amd64.deb
$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.0-1468321182_amd64.deb
$ sudo apt-get install -y adduser libfontconfig
$ sudo dpkg -i grafana_3.0.4-1464167696_amd64.deb
## Install 3.1 beta
$ wget https://grafanarel.s3.amazonaws.com/builds/grafana_3.1.0-1466666977beta1_amd64.deb
$ sudo apt-get install -y adduser libfontconfig
$ sudo dpkg -i grafana_3.1.0-1466666977beta1_amd64.deb
$ sudo dpkg -i grafana_3.1.0-1468321182_amd64.deb
## APT Repository
......
......@@ -10,42 +10,24 @@ page_keywords: grafana, installation, centos, fedora, opensuse, redhat, guide
Description | Download
------------ | -------------
Stable .RPM for CentOS / Fedora / OpenSuse / Redhat Linux | [3.0.4 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-3.0.4-1464167696.x86_64.rpm)
Beta .RPM for CentOS / Fedora / OpenSuse / Redhat Linux | [3.1.0-beta1 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm)
Stable .RPM for CentOS / Fedora / OpenSuse / Redhat Linux | [3.1.0 (x86-64 rpm)](https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1468321182.x86_64.rpm)
## Install Latest Stable
You can install Grafana using Yum directly.
$ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-3.0.4-1464167696.x86_64.rpm
$ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1468321182.x86_64.rpm
Or install manually using `rpm`.
#### On CentOS / Fedora / Redhat:
$ sudo yum install initscripts fontconfig
$ sudo rpm -Uvh grafana-3.0.4-1464167696.x86_64.rpm
$ sudo rpm -Uvh grafana-3.1.0-1468321182.x86_64.rpm
#### On OpenSuse:
$ sudo rpm -i --nodeps grafana-3.0.4-1464167696.x86_64.rpm
## Install 3.1 Beta
You can install Grafana using Yum directly.
$ sudo yum install https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm
Or install manually using `rpm`.
#### On CentOS / Fedora / Redhat:
$ sudo yum install initscripts fontconfig
$ sudo rpm -Uvh https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm
#### On OpenSuse:
$ sudo rpm -i --nodeps https://grafanarel.s3.amazonaws.com/builds/grafana-3.1.0-1466666977beta1.x86_64.rpm
$ sudo rpm -i --nodeps grafana-3.1.0-1468321182.x86_64.rpm
## Install via YUM Repository
......
......@@ -10,7 +10,7 @@ page_keywords: grafana, installation, windows guide
Description | Download
------------ | -------------
Stable Zip package for Windows | [grafana.3.0.4.windows-x64.zip](https://grafanarel.s3.amazonaws.com/winbuilds/dist/grafana-3.0.4.windows-x64.zip)
Stable Zip package for Windows | [grafana.3.1.0.windows-x64.zip](https://grafanarel.s3.amazonaws.com/winbuilds/dist/grafana-3.1.0.windows-x64.zip)
## Configure
......
{
"stable": "3.0.4",
"testing": "3.1.0-beta1"
"stable": "3.1.0",
"testing": "3.1.0"
}
......@@ -140,10 +140,10 @@ func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) Response {
return Json(412, util.DynMap{"status": "version-mismatch", "message": err.Error()})
}
if pluginErr, ok := err.(m.UpdatePluginDashboardError); ok {
message := "Dashboard is belongs to plugin " + pluginErr.PluginId + "."
message := "The dashboard belongs to plugin " + pluginErr.PluginId + "."
// look up plugin name
if pluginDef, exist := plugins.Plugins[pluginErr.PluginId]; exist {
message = "Dashboard is belongs to plugin " + pluginDef.Name + "."
message = "The dashboard belongs to plugin " + pluginDef.Name + "."
}
return Json(412, util.DynMap{"status": "plugin-dashboard", "message": message})
}
......
......@@ -72,8 +72,8 @@
Import
</a>
<a class="pull-right small muted" target="_blank" href="https://grafana.net/dashboards?utm_source=grafana_search">
Explore ready made dashboards on Grafana.net
<a class="pull-right search-button-row-explore-link" target="_blank" href="https://grafana.net/dashboards?utm_source=grafana_search">
Find dashboards on
</a>
<div class="clearfix"></div>
......
......@@ -101,7 +101,7 @@ export class Profiler {
renderingCompleted(panelId, panelTimings) {
// add render counter to root scope
// used by phantomjs render.js to know when panel has rendered
this.$rootScope.panelsRendered = this.panelsRendered++;
this.$rootScope.panelsRendered = this.panelsRendered + 1;
if (this.enabled) {
panelTimings.renderEnd = new Date().getTime();
......
......@@ -85,6 +85,9 @@ export class AlertSrv {
scope.confirmTextValid = payload.confirmText.toLowerCase() === value.toLowerCase();
};
scope.onConfirm = payload.onConfirm;
scope.onAltAction = payload.onAltAction;
scope.altActionText = payload.altActionText;
scope.icon = payload.icon || "fa-check";
scope.yesText = payload.yesText || "Yes";
scope.noText = payload.noText || "Cancel";
......
......@@ -141,9 +141,13 @@ export class DashNavCtrl {
$scope.appEvent('confirm-modal', {
title: 'Plugin Dashboard',
text: err.data.message,
text2: 'Your changes will be overwritten next time you update the plugin. Use Save As to create custom version.',
yesText: "Save & Overwrite",
text2: 'Your changes will be lost when you update the plugin. Use Save As to create custom version.',
yesText: "Overwrite",
icon: "fa-warning",
altActionText: "Save As",
onAltAction: function() {
$scope.saveDashboardAs();
},
onConfirm: function() {
$scope.saveDashboard({overwrite: true});
}
......
......@@ -107,9 +107,12 @@ function (angular, _, $) {
this.dashboard.meta.fullscreen = this.state.fullscreen;
if (!this.state.fullscreen) {
this.state.panelId = null;
this.state.fullscreen = null;
this.state.edit = null;
// clear panel id unless in solo mode
if (!this.dashboard.meta.soloMode) {
this.state.panelId = null;
}
}
$location.search(this.serializeToUrl());
......@@ -196,11 +199,13 @@ function (angular, _, $) {
var self = this;
self.panelScopes.push(panelScope);
if (self.state.panelId === panelScope.ctrl.panel.id) {
if (self.state.edit) {
panelScope.ctrl.editPanel();
} else {
panelScope.ctrl.viewPanel();
if (!self.dashboard.meta.soloMode) {
if (self.state.panelId === panelScope.ctrl.panel.id) {
if (self.state.edit) {
panelScope.ctrl.editPanel();
} else {
panelScope.ctrl.viewPanel();
}
}
}
......
......@@ -17,15 +17,12 @@ function (angular, $) {
var params = $location.search();
panelId = parseInt(params.panelId);
// add fullscreen param;
params.fullscreen = true;
$location.search(params);
$scope.onAppEvent("dashboard-initialized", $scope.initPanelScope);
dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug).then(function(result) {
result.meta.soloMode = true;
$scope.initDashboard(result, $scope);
});
$scope.onAppEvent("dashboard-initialized", $scope.initPanelScope);
};
$scope.initPanelScope = function() {
......
......@@ -5,9 +5,9 @@
<div class="page-header">
<h1>Plugins</h1>
<a class="btn btn-inverse" href="https://grafana.net/plugins?utm_source=grafana_plugin_list" target="_blank">
Explore plugins on Grafana.net
</a>
<!-- <a class="btn btn&#45;inverse" href="https://grafana.net/plugins?utm_source=grafana_plugin_list" target="_blank"> -->
<!-- Explore plugins on Grafana.net -->
<!-- </a> -->
<div class="page-header-tabs">
<ul class="gf-tabs">
......@@ -27,36 +27,40 @@
</a>
</li>
</ul>
</div>
</div>
<section class="card-section" layout-mode>
<a class="get-more-plugins-link" href="https://grafana.net/plugins?utm_source=grafana_plugin_list" target="_blank">
Find plugins on
</a>
</div>
</div>
<section class="card-section" layout-mode>
<layout-selector></layout-selector>
<ol class="card-list" >
<li class="card-item-wrapper" ng-repeat="plugin in ctrl.plugins">
<a class="card-item" href="plugins/{{plugin.id}}/edit">
<div class="card-item-header">
<div class="card-item-type">
<i class="icon-gf icon-gf-{{plugin.type}}"></i>
{{plugin.type}}
</div>
<div class="card-item-notice" ng-show="plugin.hasUpdate">
<span bs-tooltip="plugin.latestVersion">Update available!</span>
</div>
</div>
<div class="card-item-body">
<figure class="card-item-figure">
<img ng-src="{{plugin.info.logos.small}}">
</figure>
<div class="card-item-details">
<div class="card-item-name">{{plugin.name}}</div>
<div class="card-item-sub-name">By {{plugin.info.author.name}}</div>
</div>
</div>
</a>
</li>
</ol>
</section>
<ol class="card-list" >
<li class="card-item-wrapper" ng-repeat="plugin in ctrl.plugins">
<a class="card-item" href="plugins/{{plugin.id}}/edit">
<div class="card-item-header">
<div class="card-item-type">
<i class="icon-gf icon-gf-{{plugin.type}}"></i>
{{plugin.type}}
</div>
<div class="card-item-notice" ng-show="plugin.hasUpdate">
<span bs-tooltip="plugin.latestVersion">Update available!</span>
</div>
</div>
<div class="card-item-body">
<figure class="card-item-figure">
<img ng-src="{{plugin.info.logos.small}}">
</figure>
<div class="card-item-details">
<div class="card-item-name">{{plugin.name}}</div>
<div class="card-item-sub-name">By {{plugin.info.author.name}}</div>
</div>
</div>
</a>
</li>
</ol>
</section>
</div>
<div class="modal-body">
<div class="modal-body" ng-cloak>
<div class="modal-header">
<h2 class="modal-header-title">
<i class="fa {{icon}}"></i>
......@@ -29,7 +29,8 @@
<div class="confirm-modal-buttons">
<button type="button" class="btn btn-inverse" ng-click="dismiss()">{{noText}}</button>
<button type="button" class="btn btn-danger" ng-click="onConfirm();" ng-class="{'btn-inverse': !confirmTextValid, 'btn-primary': confirmTextValid}">{{yesText}}</button>
<button type="button" class="btn btn-danger" ng-click="onConfirm();dismiss();">{{yesText}}</button>
<button ng-show="onAltAction" type="button" class="btn btn-success" ng-click="dismiss();onAltAction();">{{altActionText}}</button>
</div>
</div>
......
......@@ -68,6 +68,11 @@ function (angular, _, queryDef) {
}
switch($scope.agg.type) {
case 'cardinality': {
var precision_threshold = $scope.agg.settings.precision_threshold || '';
$scope.settingsLinkText = 'Precision threshold: ' + precision_threshold;
break;
}
case 'percentiles': {
$scope.agg.settings.percents = $scope.agg.settings.percents || [25,50,75,95,99];
$scope.settingsLinkText = 'Values: ' + $scope.agg.settings.percents.join(',');
......
......@@ -58,6 +58,11 @@
<input type="text" class="gf-form-input max-width-12" ng-model="agg.settings.percents" array-join ng-blur="onChange()"></input>
</div>
<div class="gf-form offset-width-7" ng-if="agg.type === 'cardinality'">
<label class="gf-form-label width-10">Precision threshold</label>
<input type="number" class="gf-form-input max-width-12" ng-model="agg.settings.precision_threshold" ng-blur="onChange()"></input>
</div>
<div ng-if="agg.type === 'extended_stats'">
<gf-form-switch ng-repeat="stat in extendedStats" class="gf-form offset-width-7" label="{{stat.text}}" label-class="width-10" checked="agg.meta[stat.value]" on-change="onChangeInternal()"></gf-form-switch>
......
......@@ -228,7 +228,7 @@ export function GraphiteDatasource(instanceSettings, $q, backendSrv, templateSrv
}
function nestedSeriesRegexReplacer(match, g1) {
return targets[g1];
return targets[g1] || match;
}
for (i = 0; i < options.targets.length; i++) {
......
......@@ -167,7 +167,7 @@
"valueName": "current"
},
{
"content": "<img src=\"http://prometheus.io/assets/prometheus_logo_grey.svg\" alt=\"Prometheus logo\" style=\"height: 40px;\">\n<span style=\"font-family: 'Open Sans', 'Helvetica Neue', Helvetica; font-size: 25px;vertical-align: text-top;color: #bbbfc2;margin-left: 10px;\">Prometheus</span>\n\n<p style=\"margin-top: 10px;\">You're using Prometheus, an open-source systems monitoring and alerting toolkit originally built at SoundCloud. For more information, check out the <a href=\"http://www.grafana.org/\">Grafana</a> and <a href=\"http://prometheus.io/\">Prometheus</a> projects.</p>",
"content": "<img src=\"public/app/plugins/datasource/prometheus/img/prometheus_logo.svg\" alt=\"Prometheus logo\" style=\"height: 40px;\">\n<span style=\"font-family: 'Open Sans', 'Helvetica Neue', Helvetica; font-size: 25px;vertical-align: text-top;color: #bbbfc2;margin-left: 10px;\">Prometheus</span>\n\n<p style=\"margin-top: 10px;\">You're using Prometheus, an open-source systems monitoring and alerting toolkit originally built at SoundCloud. For more information, check out the <a href=\"http://www.grafana.org/\">Grafana</a> and <a href=\"http://prometheus.io/\">Prometheus</a> projects.</p>",
"editable": true,
"error": false,
"id": 9,
......
......@@ -67,12 +67,10 @@
dropdown-typeahead="ctrl.unitFormats"
dropdown-typeahead-on-select="ctrl.setUnitFormat($subItem)">
</li>
<li class="tight-form-item">
Decimals
</li>
<li class="tight-form-item">Decimals</li>
<li>
<input type="number" class="input-small tight-form-input last" placeholder="auto" bs-tooltip="'Override automatic decimal precision for legend and tooltips'" data-placement="right"
ng-model="ctrl.panel.decimals" ng-change="ctrl.render()" ng-model-onblur>
ng-model="ctrl.panel.decimals" ng-change="ctrl.refresh()" ng-model-onblur>
</li>
</ul>
<div class="clearfix"></div>
......
......@@ -538,7 +538,9 @@ class SingleStatCtrl extends MetricsPanelCtrl {
elem.mouseleave(function() {
if (panel.links.length === 0) { return;}
drilldownTooltip.detach();
$timeout(function() {
drilldownTooltip.detach();
});
});
elem.click(function(evt) {
......
......@@ -101,9 +101,24 @@
.search-button-row {
padding-top: 20px;
line-height: 2.5rem;
button, a {
margin-right: 10px;
}
.search-button-row-explore-link {
color: $text-muted;
font-size: $font-size-sm;
padding-right: 7rem;
background: url(../img/grafana_net_logo.svg);
background-size: 6.5rem 3rem;
background-repeat: no-repeat;
background-position: right;
position: relative;
top: 0.8rem;
&:hover {
color: $link-hover-color;
}
}
}
......@@ -63,28 +63,23 @@
}
}
// .app-edit-logo-box {
// padding: 1.2rem;
// background: $panel-bg;
// text-align: center;
// img {
// max-width: 7rem;
// }
// margin-right: 2rem;
// }
//
// .app-edit-links {
// list-style: none;
// margin: 0 0 0 2rem;
//
// li {
// background: $panel-bg;
// margin-top: 4px;
// padding: 0.2rem 1rem;
// }
// }
//
// .app-edit-description {
// font-style: italic;
// margin-bottom: 1.5rem;
// }
.get-more-plugins-link {
color: $text-muted;
font-size: $font-size-sm;
padding-right: 7rem;
background: url(../img/grafana_net_logo.svg);
background-size: 6.5rem 3rem;
background-repeat: no-repeat;
background-position: right;
position: relative;
top: 1.2rem;
&:hover {
color: $link-hover-color;
}
}
@include media-breakpoint-down(sm) {
.get-more-plugins-link {
display: none;
}
}
......@@ -94,11 +94,11 @@ The plugin allso adds the following methods to the plot object:
var savedhandlers = {};
var mouseUpHandler = null;
function onMouseMove(e) {
if (selection.active) {
updateSelection(e);
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
}
}
......@@ -106,7 +106,7 @@ The plugin allso adds the following methods to the plot object:
function onMouseDown(e) {
if (e.which != 1) // only accept left-click
return;
// cancel out any text selections
document.body.focus();
......@@ -127,13 +127,13 @@ The plugin allso adds the following methods to the plot object:
// this is a bit silly, but we have to use a closure to be
// able to whack the same handler again
mouseUpHandler = function (e) { onMouseUp(e); };
$(document).one("mouseup", mouseUpHandler);
}
function onMouseUp(e) {
mouseUpHandler = null;
// revert drag stuff for old-school browsers
if (document.onselectstart !== undefined)
document.onselectstart = savedhandlers.onselectstart;
......@@ -158,13 +158,22 @@ The plugin allso adds the following methods to the plot object:
function getSelection() {
if (!selectionIsSane())
return null;
if (!selection.show) return null;
var r = {}, c1 = selection.first, c2 = selection.second;
$.each(plot.getAxes(), function (name, axis) {
if (axis.used) {
var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
var axes = plot.getAxes();
// look if no axis is used
var noAxisInUse = true;
$.each(axes, function (name, axis) {
if (axis.used) {
anyUsed = false;
}
})
$.each(axes, function (name, axis) {
if (axis.used || noAxisInUse) {
var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
}
});
......@@ -252,10 +261,10 @@ The plugin allso adds the following methods to the plot object:
from = to;
to = tmp;
}
return { from: from, to: to, axis: axis };
}
function setSelection(ranges, preventEvent) {
var axis, range, o = plot.getOptions();
......@@ -333,11 +342,11 @@ The plugin allso adds the following methods to the plot object:
ctx.restore();
}
});
plot.hooks.shutdown.push(function (plot, eventHolder) {
eventHolder.unbind("mousemove", onMouseMove);
eventHolder.unbind("mousedown", onMouseDown);
if (mouseUpHandler)
$(document).unbind("mouseup", mouseUpHandler);
});
......
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