mirror of https://github.com/grafana/grafana.git
				
				
				
			Merge branch 'master' into export-dashboard
Conflicts: public/app/features/dashboard/submenu/submenu.ts
This commit is contained in:
		
						commit
						e83d13848e
					
				|  | @ -117,6 +117,7 @@ func Register(r *macaron.Macaron) { | |||
| 			r.Get("/:id", wrap(GetUserById)) | ||||
| 			r.Get("/:id/orgs", wrap(GetUserOrgList)) | ||||
| 			r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser)) | ||||
| 			r.Post("/:id/using/:orgId", wrap(UpdateUserActiveOrg)) | ||||
| 		}, reqGrafanaAdmin) | ||||
| 
 | ||||
| 		// org information available to all users.
 | ||||
|  |  | |||
|  | @ -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)) | ||||
| 		} | ||||
| 
 | ||||
| 		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
 | ||||
| 		req.Header.Del("Cookie") | ||||
| 		req.Header.Del("Set-Cookie") | ||||
|  |  | |||
|  | @ -40,6 +40,24 @@ func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) Response { | |||
| 	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 { | ||||
| 	if len(cmd.Login) == 0 { | ||||
| 		cmd.Login = cmd.Email | ||||
|  |  | |||
|  | @ -96,6 +96,11 @@ function (angular, _, coreModule, config) { | |||
|       var requestIsLocal = options.url.indexOf('/') === 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) { | ||||
|         // handle unauthorized for backend requests
 | ||||
|         if (requestIsLocal && firstAttempt  && err.status === 401) { | ||||
|  |  | |||
|  | @ -26,25 +26,8 @@ export class SubmenuCtrl { | |||
|     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) { | ||||
|     this.templateValuesSrv.variableUpdated(variable).then(() => { | ||||
|       this.updateUrlParamsWithCurrentVariables(); | ||||
|       this.$rootScope.$emit('template-variable-value-updated'); | ||||
|       this.$rootScope.$broadcast('refresh'); | ||||
|     }); | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ define([ | |||
| 
 | ||||
|   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; | ||||
| 
 | ||||
|     this.init = function(dashboard) { | ||||
|  | @ -108,13 +108,6 @@ define([ | |||
|         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); | ||||
|       $timeout(this.refreshDashboard, 0); | ||||
|     }; | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ function (angular, _, $) { | |||
| 
 | ||||
|   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
 | ||||
|     // like fullscreen panel & edit
 | ||||
|  | @ -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() { | ||||
|         var urlState = self.getQueryStringState(); | ||||
|         if (self.needsSync(urlState)) { | ||||
|  | @ -40,10 +53,26 @@ function (angular, _, $) { | |||
|         self.registerPanel(payload.scope); | ||||
|       }); | ||||
| 
 | ||||
|       this.update(this.getQueryStringState(), true); | ||||
|       this.update(this.getQueryStringState()); | ||||
|       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() { | ||||
|       if (!this.state.panelId) { return; } | ||||
| 
 | ||||
|  | @ -63,6 +92,7 @@ function (angular, _, $) { | |||
|       state.fullscreen = state.fullscreen ? true : null; | ||||
|       state.edit =  (state.edit === "true" || state.edit === true) || null; | ||||
|       state.editview = state.editview || null; | ||||
|       state.org = contextSrv.user.orgId; | ||||
|       return state; | ||||
|     }; | ||||
| 
 | ||||
|  | @ -70,10 +100,11 @@ function (angular, _, $) { | |||
|       var urlState = _.clone(this.state); | ||||
|       urlState.fullscreen = this.state.fullscreen ? true : null; | ||||
|       urlState.edit = this.state.edit ? true : null; | ||||
|       urlState.org = contextSrv.user.orgId; | ||||
|       return urlState; | ||||
|     }; | ||||
| 
 | ||||
|     DashboardViewState.prototype.update = function(state, skipUrlSync) { | ||||
|     DashboardViewState.prototype.update = function(state) { | ||||
|       _.extend(this.state, state); | ||||
|       this.dashboard.meta.fullscreen = this.state.fullscreen; | ||||
| 
 | ||||
|  | @ -83,10 +114,7 @@ function (angular, _, $) { | |||
|         this.state.edit = null; | ||||
|       } | ||||
| 
 | ||||
|       if (!skipUrlSync) { | ||||
|       $location.search(this.serializeToUrl()); | ||||
|       } | ||||
| 
 | ||||
|       this.syncState(); | ||||
|     }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,9 +1,5 @@ | |||
| <div class="main"> | ||||
| 	<div class="row-fluid"> | ||||
| 		<div class="span12"> | ||||
| 			<div class="panel nospace" ng-if="panel" style="width: 100%"> | ||||
| <div class="panel nospace" ng-if="panel" style="width: 100%"> | ||||
| 	<plugin-component type="panel"> | ||||
| 	</plugin-component> | ||||
| 			</div> | ||||
| 		</div> | ||||
| </div> | ||||
| <div class="clearfix"></div> | ||||
|  |  | |||
|  | @ -17,6 +17,10 @@ function (angular, $) { | |||
|       var params = $location.search(); | ||||
|       panelId = parseInt(params.panelId); | ||||
| 
 | ||||
|       // add fullscreen param;
 | ||||
|       params.fullscreen = true; | ||||
|       $location.search(params); | ||||
| 
 | ||||
|       dashboardLoaderSrv.loadDashboard($routeParams.type, $routeParams.slug).then(function(result) { | ||||
|         $scope.initDashboard(result, $scope); | ||||
|       }); | ||||
|  |  | |||
|  | @ -105,8 +105,6 @@ function (angular, _, kbn) { | |||
|           return op.text === urlValue || op.value === urlValue; | ||||
|         }); | ||||
| 
 | ||||
|         option = option || { text: urlValue, value: urlValue }; | ||||
| 
 | ||||
|         self.updateAutoInterval(variable); | ||||
|         return self.setVariableValue(variable, option, true); | ||||
|       }); | ||||
|  | @ -127,8 +125,8 @@ function (angular, _, kbn) { | |||
|     this.setVariableValue = function(variable, option, initPhase) { | ||||
|       variable.current = angular.copy(option); | ||||
| 
 | ||||
|       if (_.isArray(variable.current.value)) { | ||||
|         variable.current.text = variable.current.value.join(' + '); | ||||
|       if (_.isArray(variable.current.text)) { | ||||
|         variable.current.text = variable.current.text.join(' + '); | ||||
|       } | ||||
| 
 | ||||
|       self.selectOptionsForCurrentValue(variable); | ||||
|  | @ -226,6 +224,7 @@ function (angular, _, kbn) { | |||
| 
 | ||||
|     this.selectOptionsForCurrentValue = function(variable) { | ||||
|       var i, y, value, option; | ||||
|       var selected = []; | ||||
| 
 | ||||
|       for (i = 0; i < variable.options.length; i++) { | ||||
|         option = variable.options[i]; | ||||
|  | @ -235,12 +234,16 @@ function (angular, _, kbn) { | |||
|             value = variable.current.value[y]; | ||||
|             if (option.value === value) { | ||||
|               option.selected = true; | ||||
|               selected.push(option); | ||||
|             } | ||||
|           } | ||||
|         } else if (option.value === variable.current.value) { | ||||
|           option.selected = true; | ||||
|           selected.push(option); | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       return selected; | ||||
|     }; | ||||
| 
 | ||||
|     this.validateVariableSelectionState = function(variable) { | ||||
|  | @ -250,17 +253,18 @@ function (angular, _, kbn) { | |||
|       } | ||||
| 
 | ||||
|       if (_.isArray(variable.current.value)) { | ||||
|         self.selectOptionsForCurrentValue(variable); | ||||
|         // updated selected value
 | ||||
|         var selected = { | ||||
|           value: _.map(_.filter(variable.options, {selected: true}), function(op) { | ||||
|             return op.value; | ||||
|           }) | ||||
|         }; | ||||
|         var selected = self.selectOptionsForCurrentValue(variable); | ||||
| 
 | ||||
|         // if none pick first
 | ||||
|         if (selected.value.length === 0) { | ||||
|         if (selected.length === 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); | ||||
|       } else { | ||||
|         var currentOption = _.findWhere(variable.options, {text: variable.current.text}); | ||||
|  |  | |||
|  | @ -5,8 +5,20 @@ define([ | |||
| 
 | ||||
|   describe('when updating view state', function() { | ||||
|     var viewState, location; | ||||
|     var timeSrv = {}; | ||||
|     var templateSrv = {}; | ||||
|     var contextSrv = { | ||||
|       user: { | ||||
|         orgId: 19 | ||||
|       } | ||||
|     }; | ||||
| 
 | ||||
|     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) { | ||||
|       $rootScope.onAppEvent = function() {}; | ||||
|  | @ -17,9 +29,9 @@ define([ | |||
| 
 | ||||
|     describe('to fullscreen true and edit true', 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); | ||||
|         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.state.fullscreen).to.be(true); | ||||
|       }); | ||||
|  | @ -29,7 +41,7 @@ define([ | |||
|       it('should remove params from query string', function() { | ||||
|         viewState.update({fullscreen: true, panelId: 1, edit: true}); | ||||
|         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.state.fullscreen).to.be(null); | ||||
|       }); | ||||
|  |  | |||
|  | @ -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) { | ||||
|       scenario.setup(function() { | ||||
|         scenario.variable = { type: 'query', query: '', name: 'test', current: {} }; | ||||
|  |  | |||
|  | @ -39,7 +39,8 @@ | |||
|       var canvas = page.evaluate(function() { | ||||
|         if (!window.angular) { return false; } | ||||
|         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'); | ||||
|         if (!rootScope) {return false;} | ||||
|  | @ -59,6 +60,7 @@ | |||
|           width:  bb.width, | ||||
|           height: bb.height | ||||
|         }; | ||||
| 
 | ||||
|         page.render(params.png); | ||||
|         phantom.exit(); | ||||
|       } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue