Commit e83d1384 by Torkel Ödegaard

Merge branch 'master' into export-dashboard

Conflicts:
	public/app/features/dashboard/submenu/submenu.ts
parents 201d30a9 696fad70
...@@ -117,6 +117,7 @@ func Register(r *macaron.Macaron) { ...@@ -117,6 +117,7 @@ func Register(r *macaron.Macaron) {
r.Get("/:id", wrap(GetUserById)) r.Get("/:id", wrap(GetUserById))
r.Get("/:id/orgs", wrap(GetUserOrgList)) r.Get("/:id/orgs", wrap(GetUserOrgList))
r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser)) r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser))
r.Post("/:id/using/:orgId", wrap(UpdateUserActiveOrg))
}, reqGrafanaAdmin) }, reqGrafanaAdmin)
// org information available to all users. // org information available to all users.
......
...@@ -55,6 +55,13 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *ht ...@@ -55,6 +55,13 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string, targetUrl *url.URL) *ht
req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword)) req.Header.Add("Authorization", util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword))
} }
dsAuth := req.Header.Get("X-DS-Authorization")
if len(dsAuth) > 0 {
req.Header.Del("X-DS-Authorization")
req.Header.Del("Authorization")
req.Header.Add("Authorization", dsAuth)
}
// clear cookie headers // clear cookie headers
req.Header.Del("Cookie") req.Header.Del("Cookie")
req.Header.Del("Set-Cookie") req.Header.Del("Set-Cookie")
......
...@@ -40,6 +40,24 @@ func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) Response { ...@@ -40,6 +40,24 @@ func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) Response {
return handleUpdateUser(cmd) return handleUpdateUser(cmd)
} }
//POST /api/users/:id/using/:orgId
func UpdateUserActiveOrg(c *middleware.Context) Response {
userId := c.ParamsInt64(":id")
orgId := c.ParamsInt64(":orgId")
if !validateUsingOrg(userId, orgId) {
return ApiError(401, "Not a valid organization", nil)
}
cmd := m.SetUsingOrgCommand{UserId: userId, OrgId: orgId}
if err := bus.Dispatch(&cmd); err != nil {
return ApiError(500, "Failed change active organization", err)
}
return ApiSuccess("Active organization changed")
}
func handleUpdateUser(cmd m.UpdateUserCommand) Response { func handleUpdateUser(cmd m.UpdateUserCommand) Response {
if len(cmd.Login) == 0 { if len(cmd.Login) == 0 {
cmd.Login = cmd.Email cmd.Login = cmd.Email
......
...@@ -96,6 +96,11 @@ function (angular, _, coreModule, config) { ...@@ -96,6 +96,11 @@ function (angular, _, coreModule, config) {
var requestIsLocal = options.url.indexOf('/') === 0; var requestIsLocal = options.url.indexOf('/') === 0;
var firstAttempt = options.retry === 0; var firstAttempt = options.retry === 0;
if (requestIsLocal && options.headers && options.headers.Authorization) {
options.headers['X-DS-Authorization'] = options.headers.Authorization;
delete options.headers.Authorization;
}
return $http(options).then(null, function(err) { return $http(options).then(null, function(err) {
// handle unauthorized for backend requests // handle unauthorized for backend requests
if (requestIsLocal && firstAttempt && err.status === 401) { if (requestIsLocal && firstAttempt && err.status === 401) {
......
...@@ -26,25 +26,8 @@ export class SubmenuCtrl { ...@@ -26,25 +26,8 @@ export class SubmenuCtrl {
return this.templateValuesSrv.getValuesForTag(variable, tagKey); return this.templateValuesSrv.getValuesForTag(variable, tagKey);
} }
updateUrlParamsWithCurrentVariables() {
// update url
var params = this.$location.search();
// remove variable params
_.each(params, function(value, key) {
if (key.indexOf('var-') === 0) {
delete params[key];
}
});
// add new values
this.templateSrv.fillVariableValuesForUrl(params);
// update url
this.$location.search(params);
}
variableUpdated(variable) { variableUpdated(variable) {
this.templateValuesSrv.variableUpdated(variable).then(() => { this.templateValuesSrv.variableUpdated(variable).then(() => {
this.updateUrlParamsWithCurrentVariables();
this.$rootScope.$emit('template-variable-value-updated'); this.$rootScope.$emit('template-variable-value-updated');
this.$rootScope.$broadcast('refresh'); this.$rootScope.$broadcast('refresh');
}); });
......
...@@ -10,7 +10,7 @@ define([ ...@@ -10,7 +10,7 @@ define([
var module = angular.module('grafana.services'); var module = angular.module('grafana.services');
module.service('timeSrv', function($rootScope, $timeout, $routeParams, timer, $location) { module.service('timeSrv', function($rootScope, $timeout, $routeParams, timer) {
var self = this; var self = this;
this.init = function(dashboard) { this.init = function(dashboard) {
...@@ -108,13 +108,6 @@ define([ ...@@ -108,13 +108,6 @@ define([
this.old_refresh = null; this.old_refresh = null;
} }
// update url params
var urlParams = $location.search();
var urlRange = this.timeRangeForUrl();
urlParams.from = urlRange.from;
urlParams.to = urlRange.to;
$location.search(urlParams);
$rootScope.appEvent('time-range-changed', this.time); $rootScope.appEvent('time-range-changed', this.time);
$timeout(this.refreshDashboard, 0); $timeout(this.refreshDashboard, 0);
}; };
......
...@@ -8,7 +8,7 @@ function (angular, _, $) { ...@@ -8,7 +8,7 @@ function (angular, _, $) {
var module = angular.module('grafana.services'); var module = angular.module('grafana.services');
module.factory('dashboardViewStateSrv', function($location, $timeout) { module.factory('dashboardViewStateSrv', function($location, $timeout, templateSrv, contextSrv, timeSrv) {
// represents the transient view state // represents the transient view state
// like fullscreen panel & edit // like fullscreen panel & edit
...@@ -25,6 +25,19 @@ function (angular, _, $) { ...@@ -25,6 +25,19 @@ function (angular, _, $) {
} }
}; };
// update url on time range change
$scope.onAppEvent('time-range-changed', function() {
var urlParams = $location.search();
var urlRange = timeSrv.timeRangeForUrl();
urlParams.from = urlRange.from;
urlParams.to = urlRange.to;
$location.search(urlParams);
});
$scope.onAppEvent('template-variable-value-updated', function() {
self.updateUrlParamsWithCurrentVariables();
});
$scope.onAppEvent('$routeUpdate', function() { $scope.onAppEvent('$routeUpdate', function() {
var urlState = self.getQueryStringState(); var urlState = self.getQueryStringState();
if (self.needsSync(urlState)) { if (self.needsSync(urlState)) {
...@@ -40,10 +53,26 @@ function (angular, _, $) { ...@@ -40,10 +53,26 @@ function (angular, _, $) {
self.registerPanel(payload.scope); self.registerPanel(payload.scope);
}); });
this.update(this.getQueryStringState(), true); this.update(this.getQueryStringState());
this.expandRowForPanel(); this.expandRowForPanel();
} }
DashboardViewState.prototype.updateUrlParamsWithCurrentVariables = function() {
// update url
var params = $location.search();
// remove variable params
_.each(params, function(value, key) {
if (key.indexOf('var-') === 0) {
delete params[key];
}
});
// add new values
templateSrv.fillVariableValuesForUrl(params);
// update url
$location.search(params);
};
DashboardViewState.prototype.expandRowForPanel = function() { DashboardViewState.prototype.expandRowForPanel = function() {
if (!this.state.panelId) { return; } if (!this.state.panelId) { return; }
...@@ -63,6 +92,7 @@ function (angular, _, $) { ...@@ -63,6 +92,7 @@ function (angular, _, $) {
state.fullscreen = state.fullscreen ? true : null; state.fullscreen = state.fullscreen ? true : null;
state.edit = (state.edit === "true" || state.edit === true) || null; state.edit = (state.edit === "true" || state.edit === true) || null;
state.editview = state.editview || null; state.editview = state.editview || null;
state.org = contextSrv.user.orgId;
return state; return state;
}; };
...@@ -70,10 +100,11 @@ function (angular, _, $) { ...@@ -70,10 +100,11 @@ function (angular, _, $) {
var urlState = _.clone(this.state); var urlState = _.clone(this.state);
urlState.fullscreen = this.state.fullscreen ? true : null; urlState.fullscreen = this.state.fullscreen ? true : null;
urlState.edit = this.state.edit ? true : null; urlState.edit = this.state.edit ? true : null;
urlState.org = contextSrv.user.orgId;
return urlState; return urlState;
}; };
DashboardViewState.prototype.update = function(state, skipUrlSync) { DashboardViewState.prototype.update = function(state) {
_.extend(this.state, state); _.extend(this.state, state);
this.dashboard.meta.fullscreen = this.state.fullscreen; this.dashboard.meta.fullscreen = this.state.fullscreen;
...@@ -83,10 +114,7 @@ function (angular, _, $) { ...@@ -83,10 +114,7 @@ function (angular, _, $) {
this.state.edit = null; this.state.edit = null;
} }
if (!skipUrlSync) { $location.search(this.serializeToUrl());
$location.search(this.serializeToUrl());
}
this.syncState(); this.syncState();
}; };
......
<div class="main"> <div class="panel nospace" ng-if="panel" style="width: 100%">
<div class="row-fluid"> <plugin-component type="panel">
<div class="span12"> </plugin-component>
<div class="panel nospace" ng-if="panel" style="width: 100%">
<plugin-component type="panel">
</plugin-component>
</div>
</div>
</div> </div>
<div class="clearfix"></div>
...@@ -17,6 +17,10 @@ function (angular, $) { ...@@ -17,6 +17,10 @@ function (angular, $) {
var params = $location.search(); var params = $location.search();
panelId = parseInt(params.panelId); panelId = parseInt(params.panelId);
// add fullscreen param;
params.fullscreen = true;
$location.search(params);
dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug).then(function(result) { dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug).then(function(result) {
$scope.initDashboard(result, $scope); $scope.initDashboard(result, $scope);
}); });
......
...@@ -105,8 +105,6 @@ function (angular, _, kbn) { ...@@ -105,8 +105,6 @@ function (angular, _, kbn) {
return op.text === urlValue || op.value === urlValue; return op.text === urlValue || op.value === urlValue;
}); });
option = option || { text: urlValue, value: urlValue };
self.updateAutoInterval(variable); self.updateAutoInterval(variable);
return self.setVariableValue(variable, option, true); return self.setVariableValue(variable, option, true);
}); });
...@@ -127,8 +125,8 @@ function (angular, _, kbn) { ...@@ -127,8 +125,8 @@ function (angular, _, kbn) {
this.setVariableValue = function(variable, option, initPhase) { this.setVariableValue = function(variable, option, initPhase) {
variable.current = angular.copy(option); variable.current = angular.copy(option);
if (_.isArray(variable.current.value)) { if (_.isArray(variable.current.text)) {
variable.current.text = variable.current.value.join(' + '); variable.current.text = variable.current.text.join(' + ');
} }
self.selectOptionsForCurrentValue(variable); self.selectOptionsForCurrentValue(variable);
...@@ -226,6 +224,7 @@ function (angular, _, kbn) { ...@@ -226,6 +224,7 @@ function (angular, _, kbn) {
this.selectOptionsForCurrentValue = function(variable) { this.selectOptionsForCurrentValue = function(variable) {
var i, y, value, option; var i, y, value, option;
var selected = [];
for (i = 0; i < variable.options.length; i++) { for (i = 0; i < variable.options.length; i++) {
option = variable.options[i]; option = variable.options[i];
...@@ -235,12 +234,16 @@ function (angular, _, kbn) { ...@@ -235,12 +234,16 @@ function (angular, _, kbn) {
value = variable.current.value[y]; value = variable.current.value[y];
if (option.value === value) { if (option.value === value) {
option.selected = true; option.selected = true;
selected.push(option);
} }
} }
} else if (option.value === variable.current.value) { } else if (option.value === variable.current.value) {
option.selected = true; option.selected = true;
selected.push(option);
} }
} }
return selected;
}; };
this.validateVariableSelectionState = function(variable) { this.validateVariableSelectionState = function(variable) {
...@@ -250,17 +253,18 @@ function (angular, _, kbn) { ...@@ -250,17 +253,18 @@ function (angular, _, kbn) {
} }
if (_.isArray(variable.current.value)) { if (_.isArray(variable.current.value)) {
self.selectOptionsForCurrentValue(variable); var selected = self.selectOptionsForCurrentValue(variable);
// updated selected value
var selected = {
value: _.map(_.filter(variable.options, {selected: true}), function(op) {
return op.value;
})
};
// if none pick first // if none pick first
if (selected.value.length === 0) { if (selected.length === 0) {
selected = variable.options[0]; selected = variable.options[0];
} else {
selected = {
value: _.map(selected, function(val) {return val.value;}),
text: _.map(selected, function(val) {return val.text;}).join(' + '),
};
} }
return self.setVariableValue(variable, selected, false); return self.setVariableValue(variable, selected, false);
} else { } else {
var currentOption = _.findWhere(variable.options, {text: variable.current.text}); var currentOption = _.findWhere(variable.options, {text: variable.current.text});
......
...@@ -5,8 +5,20 @@ define([ ...@@ -5,8 +5,20 @@ define([
describe('when updating view state', function() { describe('when updating view state', function() {
var viewState, location; var viewState, location;
var timeSrv = {};
var templateSrv = {};
var contextSrv = {
user: {
orgId: 19
}
};
beforeEach(module('grafana.services')); beforeEach(module('grafana.services'));
beforeEach(module(function($provide) {
$provide.value('timeSrv', timeSrv);
$provide.value('templateSrv', templateSrv);
$provide.value('contextSrv', contextSrv);
}));
beforeEach(inject(function(dashboardViewStateSrv, $location, $rootScope) { beforeEach(inject(function(dashboardViewStateSrv, $location, $rootScope) {
$rootScope.onAppEvent = function() {}; $rootScope.onAppEvent = function() {};
...@@ -17,9 +29,9 @@ define([ ...@@ -17,9 +29,9 @@ define([
describe('to fullscreen true and edit true', function() { describe('to fullscreen true and edit true', function() {
it('should update querystring and view state', function() { it('should update querystring and view state', function() {
var updateState = { fullscreen: true, edit: true, panelId: 1 }; var updateState = {fullscreen: true, edit: true, panelId: 1};
viewState.update(updateState); viewState.update(updateState);
expect(location.search()).to.eql(updateState); expect(location.search()).to.eql({fullscreen: true, edit: true, panelId: 1, org: 19});
expect(viewState.dashboard.meta.fullscreen).to.be(true); expect(viewState.dashboard.meta.fullscreen).to.be(true);
expect(viewState.state.fullscreen).to.be(true); expect(viewState.state.fullscreen).to.be(true);
}); });
...@@ -29,7 +41,7 @@ define([ ...@@ -29,7 +41,7 @@ define([
it('should remove params from query string', function() { it('should remove params from query string', function() {
viewState.update({fullscreen: true, panelId: 1, edit: true}); viewState.update({fullscreen: true, panelId: 1, edit: true});
viewState.update({fullscreen: false}); viewState.update({fullscreen: false});
expect(location.search()).to.eql({}); expect(location.search()).to.eql({org: 19});
expect(viewState.dashboard.meta.fullscreen).to.be(false); expect(viewState.dashboard.meta.fullscreen).to.be(false);
expect(viewState.state.fullscreen).to.be(null); expect(viewState.state.fullscreen).to.be(null);
}); });
......
...@@ -166,6 +166,27 @@ define([ ...@@ -166,6 +166,27 @@ define([
}); });
}); });
describeUpdateVariable('query variable with multi select and $__all selected', function(scenario) {
scenario.setup(function() {
scenario.variable = {
type: 'query',
query: '',
name: 'test',
includeAll: true,
current: {
value: ['$__all'],
text: 'All'
}
};
scenario.queryResult = [{text: 'val5'}, {text: 'val6'}];
});
it('should keep current All value', function() {
expect(scenario.variable.current.value).to.eql(['$__all']);
expect(scenario.variable.current.text).to.eql('All');
});
});
describeUpdateVariable('query variable with numeric results', function(scenario) { describeUpdateVariable('query variable with numeric results', function(scenario) {
scenario.setup(function() { scenario.setup(function() {
scenario.variable = { type: 'query', query: '', name: 'test', current: {} }; scenario.variable = { type: 'query', query: '', name: 'test', current: {} };
......
...@@ -39,7 +39,8 @@ ...@@ -39,7 +39,8 @@
var canvas = page.evaluate(function() { var canvas = page.evaluate(function() {
if (!window.angular) { return false; } if (!window.angular) { return false; }
var body = window.angular.element(document.body); var body = window.angular.element(document.body);
if (!body.scope) { return false; } if (!body.injector) { return false; }
if (!body.injector()) { return false; }
var rootScope = body.injector().get('$rootScope'); var rootScope = body.injector().get('$rootScope');
if (!rootScope) {return false;} if (!rootScope) {return false;}
...@@ -59,6 +60,7 @@ ...@@ -59,6 +60,7 @@
width: bb.width, width: bb.width,
height: bb.height height: bb.height
}; };
page.render(params.png); page.render(params.png);
phantom.exit(); phantom.exit();
} }
......
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