diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ade6b78d33..15e1527ad8c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,13 +1,14 @@
# 2.0.0 (unreleased)
**New features**
+- [Issue #1622](https://github.com/grafana/grafana/issues/1622). Share Panel: The share modal now has an embed option, gives you an iframe that you can use to embedd a single graph on another web site
- [Issue #718](https://github.com/grafana/grafana/issues/718). Dashboard: When saving a dashboard and another user has made changes inbetween the user is promted with a warning if he really wants to overwrite the other's changes
- [Issue #1331](https://github.com/grafana/grafana/issues/1331). Graph & Singlestat: New axis/unit format selector and more units (kbytes, Joule, Watt, eV), and new design for graph axis & grid tab and single stat options tab views
- [Issue #1241](https://github.com/grafana/grafana/issues/1242). Timepicker: New option in timepicker (under dashboard settings), to change ``now`` to be for example ``now-1m``, usefull when you want to ignore last minute because it contains incomplete data
- [Issue #171](https://github.com/grafana/grafana/issues/171). Panel: Different time periods, panels can override dashboard relative time and/or add a time shift
- [Issue #1488](https://github.com/grafana/grafana/issues/1488). Dashboard: Clone dashboard / Save as
- [Issue #1458](https://github.com/grafana/grafana/issues/1458). User: persisted user option for dark or light theme (no longer an option on a dashboard)
-- [Issue #452](https://github.com/grafana/grafana/issues/452). Graph: Adds logarithmic scale option (log base 10)
+- [Issue #452](https://github.com/grafana/grafana/issues/452). Graph: Adds logarithmic scale option for base 10, base 16 and base 1024
**Enhancements**
- [Issue #1366](https://github.com/grafana/grafana/issues/1366). Graph & Singlestat: Support for additional units, Fahrenheit (°F) and Celsius (°C), Humidity (%H), kW, watt-hour (Wh), kilowatt-hour (kWh), velocities (m/s, km/h, mpg, knot)
diff --git a/pkg/api/render.go b/pkg/api/render.go
index 8649dfe4c6b..0398d455cc8 100644
--- a/pkg/api/render.go
+++ b/pkg/api/render.go
@@ -12,12 +12,13 @@ import (
func RenderToPng(c *middleware.Context) {
queryReader := util.NewUrlQueryReader(c.Req.URL)
- queryParams := fmt.Sprintf("?render=1&%s=%d&%s", middleware.SESS_KEY_USERID, c.UserId, c.Req.URL.RawQuery)
+ queryParams := fmt.Sprintf("?%s", c.Req.URL.RawQuery)
renderOpts := &renderer.RenderOpts{
- Url: c.Params("*") + queryParams,
- Width: queryReader.Get("width", "800"),
- Height: queryReader.Get("height", "400"),
+ Url: c.Params("*") + queryParams,
+ Width: queryReader.Get("width", "800"),
+ Height: queryReader.Get("height", "400"),
+ SessionId: c.Session.ID(),
}
renderOpts.Url = setting.ToAbsUrl(renderOpts.Url)
diff --git a/pkg/components/renderer/renderer.go b/pkg/components/renderer/renderer.go
index cd8979a57bc..054632395ce 100644
--- a/pkg/components/renderer/renderer.go
+++ b/pkg/components/renderer/renderer.go
@@ -14,9 +14,10 @@ import (
)
type RenderOpts struct {
- Url string
- Width string
- Height string
+ Url string
+ Width string
+ Height string
+ SessionId string
}
func RenderToPng(params *RenderOpts) (string, error) {
@@ -26,7 +27,9 @@ func RenderToPng(params *RenderOpts) (string, error) {
pngPath, _ := filepath.Abs(filepath.Join(setting.ImagesDir, getHash(params.Url)))
pngPath = pngPath + ".png"
- cmd := exec.Command(binPath, scriptPath, "url="+params.Url, "width="+params.Width, "height="+params.Height, "png="+pngPath)
+ cmd := exec.Command(binPath, scriptPath, "url="+params.Url, "width="+params.Width,
+ "height="+params.Height, "png="+pngPath, "cookiename="+setting.SessionOptions.CookieName,
+ "domain="+setting.Domain, "sessionid="+params.SessionId)
stdout, err := cmd.StdoutPipe()
if err != nil {
diff --git a/pkg/middleware/auth.go b/pkg/middleware/auth.go
index 7c8f8f30087..53b554942a6 100644
--- a/pkg/middleware/auth.go
+++ b/pkg/middleware/auth.go
@@ -22,13 +22,6 @@ func getRequestUserId(c *Context) int64 {
return userId.(int64)
}
- // TODO: figure out a way to secure this
- if c.Req.URL.Query().Get("render") == "1" {
- userId := c.QueryInt64(SESS_KEY_USERID)
- c.Session.Set(SESS_KEY_USERID, userId)
- return userId
- }
-
return 0
}
diff --git a/src/app/features/dashboard/dashboardNavCtrl.js b/src/app/features/dashboard/dashboardNavCtrl.js
index a47e19b561f..5950c504a3a 100644
--- a/src/app/features/dashboard/dashboardNavCtrl.js
+++ b/src/app/features/dashboard/dashboardNavCtrl.js
@@ -42,7 +42,7 @@ function (angular, _, moment) {
$scope.shareDashboard = function() {
$scope.appEvent('show-modal', {
- src: './app/features/dashboard/partials/shareModal.html',
+ src: './app/features/dashboard/partials/shareDashboard.html',
scope: $scope.$new(),
});
};
diff --git a/src/app/features/dashboard/partials/shareDashboard.html b/src/app/features/dashboard/partials/shareDashboard.html
new file mode 100644
index 00000000000..e052c5b298f
--- /dev/null
+++ b/src/app/features/dashboard/partials/shareDashboard.html
@@ -0,0 +1,48 @@
+
-
-
-
diff --git a/src/app/features/dashboard/partials/sharePanel.html b/src/app/features/dashboard/partials/sharePanel.html
new file mode 100644
index 00000000000..e56fe89be59
--- /dev/null
+++ b/src/app/features/dashboard/partials/sharePanel.html
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
IFrame embedding
+
The html code below can be pasted and included in another web page. Unless anonymous access
+ is enabled the user viewing that page need to be signed into grafana for the graph to load.
+
+
+
+
+
diff --git a/src/app/features/dashboard/sharePanelCtrl.js b/src/app/features/dashboard/sharePanelCtrl.js
index eca10678806..40c7ba45a90 100644
--- a/src/app/features/dashboard/sharePanelCtrl.js
+++ b/src/app/features/dashboard/sharePanelCtrl.js
@@ -72,8 +72,11 @@ function (angular, _, require, config) {
});
$scope.shareUrl = baseUrl + "?" + paramsArray.join('&');
- $scope.imageUrl = $scope.shareUrl.replace('/dashboard/db/', '/render/dashboard/solo/');
+ $scope.soloUrl = $scope.shareUrl.replace('/dashboard/db/', '/dashboard/solo/');
+ $scope.iframeHtml = '
';
+
+ $scope.imageUrl = $scope.shareUrl.replace('/dashboard/db/', '/render/dashboard/solo/');
$scope.imageUrl += '&width=1000';
$scope.imageUrl += '&height=500';
};
diff --git a/src/app/features/panel/panelSrv.js b/src/app/features/panel/panelSrv.js
index 4ffebe67f18..721167491ce 100644
--- a/src/app/features/panel/panelSrv.js
+++ b/src/app/features/panel/panelSrv.js
@@ -27,7 +27,7 @@ function (angular, _, config) {
$scope.sharePanel = function() {
$scope.appEvent('show-modal', {
- src: './app/features/dashboard/partials/shareModal.html',
+ src: './app/features/dashboard/partials/sharePanel.html',
scope: $scope.$new()
});
};
diff --git a/src/app/features/panel/soloPanelCtrl.js b/src/app/features/panel/soloPanelCtrl.js
index 1d134a73827..c6a01d9ccfe 100644
--- a/src/app/features/panel/soloPanelCtrl.js
+++ b/src/app/features/panel/soloPanelCtrl.js
@@ -7,10 +7,22 @@ function (angular, $) {
var module = angular.module('grafana.routes');
- module.controller('SoloPanelCtrl', function($scope, backendSrv, $routeParams, dashboardSrv, timeSrv, $location, templateValuesSrv) {
+ module.controller('SoloPanelCtrl',
+ function(
+ $scope,
+ backendSrv,
+ $routeParams,
+ dashboardSrv,
+ timeSrv,
+ $location,
+ templateValuesSrv,
+ contextSrv) {
+
var panelId;
$scope.init = function() {
+ contextSrv.sidemenu = false;
+
var params = $location.search();
panelId = parseInt(params.panelId);
@@ -26,7 +38,7 @@ function (angular, $) {
$scope.dashboard = dashboardSrv.create(dashboard.model);
$scope.row = {
- height: $(window).height() + 'px',
+ height: ($(window).height() - 10) + 'px',
};
$scope.test = "Hej";
diff --git a/src/app/features/panellinkeditor/module.html b/src/app/features/panellinkeditor/module.html
index 7d79eff5a6b..4aacb6675fc 100644
--- a/src/app/features/panellinkeditor/module.html
+++ b/src/app/features/panellinkeditor/module.html
@@ -2,23 +2,23 @@
Drilldown / detail linkThese links appear in the dropdown menu in the panel menu.
-
diff --git a/src/app/panels/graph/graph.js b/src/app/panels/graph/graph.js
index e7cdba21dd2..5e8bcb2d964 100755
--- a/src/app/panels/graph/graph.js
+++ b/src/app/panels/graph/graph.js
@@ -351,7 +351,7 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
show: scope.panel['y-axis'],
min: scope.panel.grid.leftMin,
index: 1,
- logBase: scope.panel.grid.leftLogBase,
+ logBase: scope.panel.grid.leftLogBase || 1,
max: scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.leftMax,
};
@@ -360,7 +360,7 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
if (_.findWhere(data, {yaxis: 2})) {
var secondY = _.clone(defaults);
secondY.index = 2,
- secondY.logBase = scope.panel.grid.rightLogBase;
+ secondY.logBase = scope.panel.grid.rightLogBase || 2,
secondY.position = 'right';
secondY.min = scope.panel.grid.rightMin;
secondY.max = scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.rightMax;
@@ -375,7 +375,7 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
}
function applyLogScale(axis, data) {
- if (axis.logBase !== 10) {
+ if (axis.logBase === 1) {
return;
}
@@ -391,26 +391,30 @@ function (angular, $, kbn, moment, _, GraphTooltip) {
}
}
}
-
- if (max === null) {
+ if (max === void 0) {
max = Number.MAX_VALUE;
}
}
- axis.min = axis.min !== null ? axis.min : 1;
- axis.ticks = [1];
- var tick = 1;
+ axis.min = axis.min !== null ? axis.min : 0;
+ axis.ticks = [0, 1];
+ var nextTick = 1;
while (true) {
- tick = tick * axis.logBase;
- axis.ticks.push(tick);
- if (tick > max) {
+ nextTick = nextTick * axis.logBase;
+ axis.ticks.push(nextTick);
+ if (nextTick > max) {
break;
}
}
- axis.transform = function(v) { return Math.log(v+0.001); };
- axis.inverseTransform = function (v) { return Math.pow(10,v); };
+ if (axis.logBase === 10) {
+ axis.transform = function(v) { return Math.log(v+0.1); };
+ axis.inverseTransform = function (v) { return Math.pow(10,v); };
+ } else {
+ axis.transform = function(v) { return Math.log(v+0.1) / Math.log(axis.logBase); };
+ axis.inverseTransform = function (v) { return Math.pow(axis.logBase,v); };
+ }
}
function configureAxisMode(axis, format) {
diff --git a/src/app/panels/graph/module.js b/src/app/panels/graph/module.js
index 98e5baf1e55..3af9f59eb9b 100644
--- a/src/app/panels/graph/module.js
+++ b/src/app/panels/graph/module.js
@@ -116,7 +116,7 @@ function (angular, app, $, _, kbn, moment, TimeSeries, PanelMeta) {
_.defaults($scope.panel.grid, _d.grid);
_.defaults($scope.panel.legend, _d.legend);
- $scope.logScales = {'linear': 1, 'log (base 10)': 10};
+ $scope.logScales = {'linear': 1, 'log (base 16)': 16, 'log (base 10)': 10, 'log (base 1024)': 1024};
$scope.hiddenSeries = {};
$scope.seriesList = [];
diff --git a/src/css/less/forms.less b/src/css/less/forms.less
index 0adc2637472..646f91b0090 100644
--- a/src/css/less/forms.less
+++ b/src/css/less/forms.less
@@ -51,5 +51,11 @@ input[type="checkbox"]:checked+label {
height: 100%;
box-sizing: border-box;
}
+ textarea {
+ width: 100%;
+ padding: 5px 6px;
+ height: 100%;
+ box-sizing: border-box;
+ }
}
diff --git a/src/test/specs/graph-specs.js b/src/test/specs/graph-specs.js
index 1a4e52ad875..7e870bfd7d0 100644
--- a/src/test/specs/graph-specs.js
+++ b/src/test/specs/graph-specs.js
@@ -28,7 +28,7 @@ define([
scope.height = '200px';
scope.panel = {
legend: {},
- grid: {},
+ grid: { },
y_formats: [],
seriesOverrides: [],
tooltip: {
@@ -140,6 +140,25 @@ define([
});
});
+ graphScenario('when logBase is log 10', function(ctx) {
+ ctx.setup(function(scope) {
+ scope.panel.grid = {
+ leftMax: null,
+ rightMax: null,
+ leftMin: null,
+ rightMin: null,
+ leftLogBase: 10,
+ };
+ });
+
+ it('should apply axis transform and ticks', function() {
+ var axis = ctx.plotOptions.yaxes[0];
+ expect(axis.transform(100)).to.be(Math.log(100+0.0001));
+ expect(axis.ticks[0]).to.be(1);
+ expect(axis.ticks[1]).to.be(10);
+ });
+ });
+
graphScenario('should use timeStep for barWidth', function(ctx) {
ctx.setup(function(scope, data) {
scope.panel.bars = true;
diff --git a/src/test/specs/soloPanelCtrl-specs.js b/src/test/specs/soloPanelCtrl-specs.js
index 533f966a040..31b45c353f2 100644
--- a/src/test/specs/soloPanelCtrl-specs.js
+++ b/src/test/specs/soloPanelCtrl-specs.js
@@ -10,11 +10,13 @@ define([
var backendSrv = {};
var routeParams = {};
var search = {};
+ var contextSrv = {};
beforeEach(module('grafana.routes'));
beforeEach(module('grafana.services'));
beforeEach(ctx.providePhase({
$routeParams: routeParams,
+ contextSrv: contextSrv,
$location: {
search: function() {
return search;
@@ -57,6 +59,10 @@ define([
expect(ctx.scope.panel.some).to.be('prop');
});
+ it('should hide sidemenu', function() {
+ expect(contextSrv.sidemenu).to.be(false);
+ });
+
});
});
diff --git a/vendor/phantomjs/render.js b/vendor/phantomjs/render.js
index b8f91e1c73b..58afcd44eba 100644
--- a/vendor/phantomjs/render.js
+++ b/vendor/phantomjs/render.js
@@ -9,13 +9,19 @@ args.forEach(function(arg) {
params[parts[1]] = parts[2];
});
-var usage = "url=
png= width= height=";
+var usage = "url= png= width= height= cookiename= sessionid= domain=";
-if (!params.url || !params.png) {
+if (!params.url || !params.png || !params.cookiename || ! params.sessionid || !params.domain) {
console.log(usage);
phantom.exit();
}
+phantom.addCookie({
+ 'name': params.cookiename,
+ 'value': params.sessionid,
+ 'domain': params.domain
+});
+
page.viewportSize = {
width: params.width || '800',
height: params.height || '400'