mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SharePanelModal: working on share feature, #864
This commit is contained in:
parent
2d866b9298
commit
2c85205259
21
.jsfmtrc
Normal file
21
.jsfmtrc
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"preset" : "default",
|
||||||
|
|
||||||
|
"lineBreak" : {
|
||||||
|
"before" : {
|
||||||
|
"VariableDeclarationWithoutInit" : 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
"after": {
|
||||||
|
"AssignmentOperator": -1,
|
||||||
|
"ArgumentListArrayExpression": ">=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"whiteSpace" : {
|
||||||
|
"before" : {
|
||||||
|
},
|
||||||
|
"after" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,31 +11,64 @@ function (angular, _) {
|
|||||||
|
|
||||||
$scope.init = function() {
|
$scope.init = function() {
|
||||||
$scope.editor = { index: 0 };
|
$scope.editor = { index: 0 };
|
||||||
|
|
||||||
var currentUrl = $location.absUrl();
|
|
||||||
var panelId = $scope.panel.id;
|
|
||||||
var range = timeSrv.timeRange(false);
|
|
||||||
var from = range.from;
|
|
||||||
var to = range.to;
|
|
||||||
if (_.isDate(from)) {
|
|
||||||
from = from.getTime();
|
|
||||||
}
|
|
||||||
if (_.isDate(to)) {
|
|
||||||
to = to.getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.shareUrl = currentUrl + "?panelId=" + panelId + "&fullscreen";
|
|
||||||
$scope.shareUrl += "&from=" + from;
|
|
||||||
$scope.shareUrl += "&to=" + to;
|
|
||||||
|
|
||||||
$scope.forCurrent = true;
|
$scope.forCurrent = true;
|
||||||
$scope.toPanel = true;
|
$scope.toPanel = true;
|
||||||
|
|
||||||
|
$scope.buildUrl();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.buildUrl = function() {
|
||||||
|
var baseUrl = $location.absUrl();
|
||||||
|
var queryStart = baseUrl.indexOf('?');
|
||||||
|
|
||||||
|
if (queryStart !== -1) {
|
||||||
|
baseUrl = baseUrl.substring(0, queryStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
var panelId = $scope.panel.id;
|
||||||
|
var range = timeSrv.timeRange(false);
|
||||||
|
var params = $location.search();
|
||||||
|
|
||||||
|
if (_.isString(range.to) && range.to.indexOf('now')) {
|
||||||
|
range = timeSrv.timeRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
params.from = range.from;
|
||||||
|
params.to = range.to;
|
||||||
|
|
||||||
|
if (_.isDate(params.from)) { params.from = params.from.getTime(); }
|
||||||
|
if (_.isDate(params.to)) { params.to = params.to.getTime(); }
|
||||||
|
|
||||||
|
if (!$scope.forCurrent) {
|
||||||
|
delete params.from;
|
||||||
|
delete params.to;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($scope.toPanel) {
|
||||||
|
params.panelId = panelId;
|
||||||
|
params.fullscreen = true;
|
||||||
|
} else {
|
||||||
|
delete params.panelId;
|
||||||
|
delete params.fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
var paramsArray = [];
|
||||||
|
_.each(params, function(value, key) {
|
||||||
|
var str = key;
|
||||||
|
if (value !== true) {
|
||||||
|
str += '=' + encodeURIComponent(value);
|
||||||
|
}
|
||||||
|
paramsArray.push(str);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.shareUrl = baseUrl + "?" + paramsArray.join('&') ;
|
||||||
|
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
var input = $element.find('[data-share-panel-url]');
|
var input = $element.find('[data-share-panel-url]');
|
||||||
input.focus();
|
input.focus();
|
||||||
input.select();
|
input.select();
|
||||||
});
|
}, 10);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.init();
|
$scope.init();
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
</bootstrap-tagsinput>
|
</bootstrap-tagsinput>
|
||||||
<tip>Press enter to a add tag</tip>
|
<tip>Press enter to a add tag</tip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,13 +15,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
<div class="editor-row">
|
<div class="editor-row">
|
||||||
<editor-opt-bool name="currentTime" text="Current time range" model="forCurrent"></editor-opt-bool>
|
<editor-opt-bool name="currentTime" text="Current time range" model="forCurrent" change="buildUrl()"></editor-opt-bool>
|
||||||
<editor-opt-bool name="toPanel" text="To this panel only" model="toPanel"></editor-opt-bool>
|
<editor-opt-bool name="toPanel" text="To this panel only" model="toPanel" change="buildUrl()"></editor-opt-bool>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="editor-row" style="margin-top: 20px;">
|
<div class="editor-row" style="margin-top: 20px;">
|
||||||
<input type="text" data-share-panel-url ng-model="shareUrl" class="input input-fluid"></input>
|
<input type="text" data-share-panel-url class="input input-fluid" ng-model='shareUrl'></input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -2,108 +2,110 @@
|
|||||||
// config.js is where you will find the core Grafana configuration. This file contains parameter that
|
// config.js is where you will find the core Grafana configuration. This file contains parameter that
|
||||||
// must be set before Grafana is run for the first time.
|
// must be set before Grafana is run for the first time.
|
||||||
|
|
||||||
define(['settings'],
|
define(['settings'], function(Settings) {
|
||||||
function (Settings) {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
return new Settings({
|
return new Settings({
|
||||||
|
|
||||||
/* Data sources
|
/* Data sources
|
||||||
* ========================================================
|
* ========================================================
|
||||||
* Datasources are used to fetch metrics, annotations, and serve as dashboard storage
|
* Datasources are used to fetch metrics, annotations, and serve as dashboard storage
|
||||||
* - You can have multiple of the same type.
|
* - You can have multiple of the same type.
|
||||||
* - grafanaDB: true marks it for use for dashboard storage
|
* - grafanaDB: true marks it for use for dashboard storage
|
||||||
* - default: true marks the datasource as the default metric source (if you have multiple)
|
* - default: true marks the datasource as the default metric source (if you have multiple)
|
||||||
* - basic authentication: use url syntax http://username:password@domain:port
|
* - basic authentication: use url syntax http://username:password@domain:port
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// InfluxDB example setup (the InfluxDB databases specified need to exist)
|
// InfluxDB example setup (the InfluxDB databases specified need to exist)
|
||||||
/*
|
/*
|
||||||
datasources: {
|
datasources: {
|
||||||
influxdb: {
|
influxdb: {
|
||||||
type: 'influxdb',
|
type: 'influxdb',
|
||||||
url: "http://my_influxdb_server:8086/db/database_name",
|
url: "http://my_influxdb_server:8086/db/database_name",
|
||||||
username: 'admin',
|
username: 'admin',
|
||||||
password: 'admin',
|
password: 'admin',
|
||||||
|
},
|
||||||
|
grafana: {
|
||||||
|
type: 'influxdb',
|
||||||
|
url: "http://my_influxdb_server:8086/db/grafana",
|
||||||
|
username: 'admin',
|
||||||
|
password: 'admin',
|
||||||
|
grafanaDB: true
|
||||||
|
},
|
||||||
},
|
},
|
||||||
grafana: {
|
*/
|
||||||
type: 'influxdb',
|
|
||||||
url: "http://my_influxdb_server:8086/db/grafana",
|
|
||||||
username: 'admin',
|
|
||||||
password: 'admin',
|
|
||||||
grafanaDB: true
|
|
||||||
},
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Graphite & Elasticsearch example setup
|
// Graphite & Elasticsearch example setup
|
||||||
/*
|
/*
|
||||||
datasources: {
|
datasources: {
|
||||||
graphite: {
|
graphite: {
|
||||||
type: 'graphite',
|
type: 'graphite',
|
||||||
url: "http://my.graphite.server.com:8080",
|
url: "http://my.graphite.server.com:8080",
|
||||||
|
},
|
||||||
|
elasticsearch: {
|
||||||
|
type: 'elasticsearch',
|
||||||
|
url: "http://my.elastic.server.com:9200",
|
||||||
|
index: 'grafana-dash',
|
||||||
|
grafanaDB: true,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
elasticsearch: {
|
*/
|
||||||
type: 'elasticsearch',
|
|
||||||
url: "http://my.elastic.server.com:9200",
|
// OpenTSDB & Elasticsearch example setup
|
||||||
index: 'grafana-dash',
|
/*
|
||||||
grafanaDB: true,
|
datasources: {
|
||||||
|
opentsdb: {
|
||||||
|
type: 'opentsdb',
|
||||||
|
url: "http://opentsdb.server:4242",
|
||||||
|
},
|
||||||
|
elasticsearch: {
|
||||||
|
type: 'elasticsearch',
|
||||||
|
url: "http://my.elastic.server.com:9200",
|
||||||
|
index: 'grafana-dash',
|
||||||
|
grafanaDB: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Global configuration options
|
||||||
|
* ========================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
// specify the limit for dashboard search results
|
||||||
|
search: {
|
||||||
|
max_results: 20
|
||||||
|
},
|
||||||
|
|
||||||
|
// default home dashboard
|
||||||
|
default_route: '/dashboard/file/default.json',
|
||||||
|
|
||||||
|
// set to false to disable unsaved changes warning
|
||||||
|
unsaved_changes_warning: true,
|
||||||
|
|
||||||
|
// set the default timespan for the playlist feature
|
||||||
|
// Example: "1m", "1h"
|
||||||
|
playlist_timespan: "1m",
|
||||||
|
|
||||||
|
// If you want to specify password before saving, please specify it below
|
||||||
|
// The purpose of this password is not security, but to stop some users from accidentally changing dashboards
|
||||||
|
admin: {
|
||||||
|
password: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// Change window title prefix from 'Grafana - <dashboard title>'
|
||||||
|
window_title_prefix: 'Grafana - ',
|
||||||
|
|
||||||
|
// Add your own custom panels
|
||||||
|
plugins: {
|
||||||
|
// list of plugin panels
|
||||||
|
panels: [],
|
||||||
|
// requirejs modules in plugins folder that should be loaded
|
||||||
|
// for example custom datasources
|
||||||
|
dependencies: [],
|
||||||
}
|
}
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
// OpenTSDB & Elasticsearch example setup
|
});
|
||||||
/*
|
|
||||||
datasources: {
|
|
||||||
opentsdb: {
|
|
||||||
type: 'opentsdb',
|
|
||||||
url: "http://opentsdb.server:4242",
|
|
||||||
},
|
|
||||||
elasticsearch: {
|
|
||||||
type: 'elasticsearch',
|
|
||||||
url: "http://my.elastic.server.com:9200",
|
|
||||||
index: 'grafana-dash',
|
|
||||||
grafanaDB: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Global configuration options
|
|
||||||
* ========================================================
|
|
||||||
*/
|
|
||||||
|
|
||||||
// specify the limit for dashboard search results
|
|
||||||
search: {
|
|
||||||
max_results: 20
|
|
||||||
},
|
|
||||||
|
|
||||||
// default home dashboard
|
|
||||||
default_route: '/dashboard/file/default.json',
|
|
||||||
|
|
||||||
// set to false to disable unsaved changes warning
|
|
||||||
unsaved_changes_warning: true,
|
|
||||||
|
|
||||||
// set the default timespan for the playlist feature
|
|
||||||
// Example: "1m", "1h"
|
|
||||||
playlist_timespan: "1m",
|
|
||||||
|
|
||||||
// If you want to specify password before saving, please specify it below
|
|
||||||
// The purpose of this password is not security, but to stop some users from accidentally changing dashboards
|
|
||||||
admin: {
|
|
||||||
password: ''
|
|
||||||
},
|
|
||||||
|
|
||||||
// Change window title prefix from 'Grafana - <dashboard title>'
|
|
||||||
window_title_prefix: 'Grafana - ',
|
|
||||||
|
|
||||||
// Add your own custom panels
|
|
||||||
plugins: {
|
|
||||||
// list of plugin panels
|
|
||||||
panels: [],
|
|
||||||
// requirejs modules in plugins folder that should be loaded
|
|
||||||
// for example custom datasources
|
|
||||||
dependencies: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ input[type=text].input-fluid {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"].cr1 {
|
input[type="checkbox"].cr1 {
|
||||||
|
@ -8,6 +8,7 @@ define([
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.datasource = {};
|
this.datasource = {};
|
||||||
|
this.$element = {};
|
||||||
this.annotationsSrv = {};
|
this.annotationsSrv = {};
|
||||||
this.timeSrv = new TimeSrvStub();
|
this.timeSrv = new TimeSrvStub();
|
||||||
this.templateSrv = new TemplateSrvStub();
|
this.templateSrv = new TemplateSrvStub();
|
||||||
@ -16,18 +17,23 @@ define([
|
|||||||
get: function() { return self.datasource; }
|
get: function() { return self.datasource; }
|
||||||
};
|
};
|
||||||
|
|
||||||
this.providePhase = function() {
|
this.providePhase = function(mocks) {
|
||||||
return module(function($provide) {
|
return module(function($provide) {
|
||||||
$provide.value('datasourceSrv', self.datasourceSrv);
|
$provide.value('datasourceSrv', self.datasourceSrv);
|
||||||
$provide.value('annotationsSrv', self.annotationsSrv);
|
$provide.value('annotationsSrv', self.annotationsSrv);
|
||||||
$provide.value('timeSrv', self.timeSrv);
|
$provide.value('timeSrv', self.timeSrv);
|
||||||
$provide.value('templateSrv', self.templateSrv);
|
$provide.value('templateSrv', self.templateSrv);
|
||||||
|
$provide.value('$element', self.$element);
|
||||||
|
_.each(mocks, function(key, value) {
|
||||||
|
$provide.value(key, value);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.createControllerPhase = function(controllerName) {
|
this.createControllerPhase = function(controllerName) {
|
||||||
return inject(function($controller, $rootScope, $q) {
|
return inject(function($controller, $rootScope, $q, $location) {
|
||||||
self.scope = $rootScope.$new();
|
self.scope = $rootScope.$new();
|
||||||
|
self.$location = $location;
|
||||||
self.scope.panel = {};
|
self.scope.panel = {};
|
||||||
self.scope.row = { panels:[] };
|
self.scope.row = { panels:[] };
|
||||||
self.scope.dashboard = {};
|
self.scope.dashboard = {};
|
||||||
|
59
src/test/specs/sharePanelCtrl-specs.js
Normal file
59
src/test/specs/sharePanelCtrl-specs.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
define([
|
||||||
|
'./helpers',
|
||||||
|
'controllers/sharePanelCtrl'
|
||||||
|
], function(helpers) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('SharePanelCtrl', function() {
|
||||||
|
var ctx = new helpers.ControllerTestContext();
|
||||||
|
|
||||||
|
beforeEach(module('grafana.controllers'));
|
||||||
|
|
||||||
|
beforeEach(ctx.providePhase());
|
||||||
|
beforeEach(ctx.createControllerPhase('SharePanelCtrl'));
|
||||||
|
|
||||||
|
describe('shareUrl with current time range and panel', function() {
|
||||||
|
|
||||||
|
it('should generate share url relative time', function() {
|
||||||
|
ctx.$location.path('/test');
|
||||||
|
ctx.scope.panel = { id: 22 };
|
||||||
|
ctx.timeSrv.time = { from: 'now-1h', to: 'now' };
|
||||||
|
|
||||||
|
ctx.scope.buildUrl();
|
||||||
|
expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now&panelId=22&fullscreen');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate share url absolute time', function() {
|
||||||
|
ctx.$location.path('/test');
|
||||||
|
ctx.scope.panel = { id: 22 };
|
||||||
|
ctx.timeSrv.time = { from: new Date(2012,1,1), to: new Date(2014,3,5) };
|
||||||
|
|
||||||
|
ctx.scope.buildUrl();
|
||||||
|
expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=1328050800000&to=1396648800000&panelId=22&fullscreen');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate share url with time as JSON strings', function() {
|
||||||
|
ctx.$location.path('/test');
|
||||||
|
ctx.scope.panel = { id: 22 };
|
||||||
|
ctx.timeSrv.time = { from: new Date(2012,1,1).toJSON(), to: new Date(2014,3,5).toJSON() };
|
||||||
|
|
||||||
|
ctx.scope.buildUrl();
|
||||||
|
expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=1328050800000&to=1396648800000&panelId=22&fullscreen');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove panel id when toPanel is false', function() {
|
||||||
|
ctx.$location.path('/test');
|
||||||
|
ctx.scope.panel = { id: 22 };
|
||||||
|
ctx.scope.toPanel = false;
|
||||||
|
ctx.timeSrv.time = { from: 'now-1h', to: 'now' };
|
||||||
|
|
||||||
|
ctx.scope.buildUrl();
|
||||||
|
expect(ctx.scope.shareUrl).to.be('http://server/#/test?from=now-1h&to=now');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -131,6 +131,7 @@ require([
|
|||||||
'specs/grafanaGraph-specs',
|
'specs/grafanaGraph-specs',
|
||||||
'specs/graph-tooltip-specs',
|
'specs/graph-tooltip-specs',
|
||||||
'specs/seriesOverridesCtrl-specs',
|
'specs/seriesOverridesCtrl-specs',
|
||||||
|
'specs/sharePanelCtrl-specs',
|
||||||
'specs/timeSrv-specs',
|
'specs/timeSrv-specs',
|
||||||
'specs/templateSrv-specs',
|
'specs/templateSrv-specs',
|
||||||
'specs/templateValuesSrv-specs',
|
'specs/templateValuesSrv-specs',
|
||||||
|
Loading…
Reference in New Issue
Block a user