| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | ///<reference path="../../headers/common.d.ts" />
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import angular from 'angular'; | 
					
						
							|  |  |  | import _ from 'lodash'; | 
					
						
							|  |  |  | import coreModule from 'app/core/core_module'; | 
					
						
							| 
									
										
										
										
											2016-09-20 00:32:09 +08:00
										 |  |  | import {Variable, variableTypes} from './variable'; | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class VariableSrv { | 
					
						
							|  |  |  |   dashboard: any; | 
					
						
							|  |  |  |   variables: any; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** @ngInject */ | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |   constructor(private $rootScope, private $q, private $location, private $injector, private templateSrv) { | 
					
						
							|  |  |  |     // update time variant variables
 | 
					
						
							| 
									
										
										
										
											2016-09-20 00:06:36 +08:00
										 |  |  |     $rootScope.$on('refresh', this.onDashboardRefresh.bind(this), $rootScope); | 
					
						
							| 
									
										
										
										
											2016-09-20 17:57:43 +08:00
										 |  |  |     $rootScope.$on('template-variable-value-updated', this.updateUrlParamsWithCurrentVariables.bind(this), $rootScope); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |   init(dashboard) { | 
					
						
							|  |  |  |     this.dashboard = dashboard; | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     // create working class models representing variables
 | 
					
						
							| 
									
										
										
										
											2016-11-17 18:28:33 +08:00
										 |  |  |     this.variables = dashboard.templating.list = dashboard.templating.list.map(this.createVariableFromModel.bind(this)); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     this.templateSrv.init(this.variables); | 
					
						
							| 
									
										
										
										
											2016-09-16 22:50:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     // init variables
 | 
					
						
							|  |  |  |     for (let variable of this.variables) { | 
					
						
							| 
									
										
										
										
											2016-09-23 03:49:41 +08:00
										 |  |  |       variable.initLock = this.$q.defer(); | 
					
						
							| 
									
										
										
										
											2016-09-16 22:50:30 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     var queryParams = this.$location.search(); | 
					
						
							|  |  |  |     return this.$q.all(this.variables.map(variable => { | 
					
						
							|  |  |  |       return this.processVariable(variable, queryParams); | 
					
						
							| 
									
										
										
										
											2016-09-22 15:00:15 +08:00
										 |  |  |     })).then(() => { | 
					
						
							|  |  |  |       this.templateSrv.updateTemplateData(); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onDashboardRefresh() { | 
					
						
							| 
									
										
										
										
											2016-09-20 00:06:36 +08:00
										 |  |  |     var promises = this.variables | 
					
						
							|  |  |  |     .filter(variable => variable.refresh === 2) | 
					
						
							|  |  |  |     .map(variable => { | 
					
						
							|  |  |  |       var previousOptions = variable.options.slice(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return variable.updateOptions() | 
					
						
							|  |  |  |       .then(this.variableUpdated.bind(this, variable)) | 
					
						
							|  |  |  |       .then(() => { | 
					
						
							|  |  |  |         if (angular.toJson(previousOptions) !== angular.toJson(variable.options)) { | 
					
						
							|  |  |  |           this.$rootScope.$emit('template-variable-value-updated'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return this.$q.all(promises); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   processVariable(variable, queryParams) { | 
					
						
							|  |  |  |     var dependencies = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (let otherVariable of this.variables) { | 
					
						
							|  |  |  |       if (variable.dependsOn(otherVariable)) { | 
					
						
							| 
									
										
										
										
											2016-09-23 03:49:41 +08:00
										 |  |  |         dependencies.push(otherVariable.initLock.promise); | 
					
						
							| 
									
										
										
										
											2016-09-16 22:50:30 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     return this.$q.all(dependencies).then(() => { | 
					
						
							|  |  |  |       var urlValue = queryParams['var-' + variable.name]; | 
					
						
							|  |  |  |       if (urlValue !== void 0) { | 
					
						
							| 
									
										
										
										
											2016-09-23 03:49:41 +08:00
										 |  |  |         return variable.setValueFromUrl(urlValue).then(variable.initLock.resolve); | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |       if (variable.refresh === 1 || variable.refresh === 2) { | 
					
						
							| 
									
										
										
										
											2016-09-23 03:49:41 +08:00
										 |  |  |         return variable.updateOptions().then(variable.initLock.resolve); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 03:49:41 +08:00
										 |  |  |       variable.initLock.resolve(); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     }).finally(() => { | 
					
						
							| 
									
										
										
										
											2016-09-23 03:49:41 +08:00
										 |  |  |       this.templateSrv.variableInitialized(variable); | 
					
						
							|  |  |  |       delete variable.initLock; | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |   createVariableFromModel(model) { | 
					
						
							| 
									
										
										
										
											2016-09-20 00:32:09 +08:00
										 |  |  |     var ctor = variableTypes[model.type].ctor; | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     if (!ctor) { | 
					
						
							|  |  |  |       throw "Unable to find variable constructor for " + model.type; | 
					
						
							| 
									
										
										
										
											2016-09-17 21:27:53 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     var variable = this.$injector.instantiate(ctor, {model: model}); | 
					
						
							|  |  |  |     return variable; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   addVariable(model) { | 
					
						
							|  |  |  |     var variable = this.createVariableFromModel(model); | 
					
						
							| 
									
										
										
										
											2017-04-24 23:06:58 +08:00
										 |  |  |     this.variables.push(variable); | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     return variable; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateOptions(variable) { | 
					
						
							|  |  |  |     return variable.updateOptions(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   variableUpdated(variable) { | 
					
						
							|  |  |  |     // if there is a variable lock ignore cascading update because we are in a boot up scenario
 | 
					
						
							| 
									
										
										
										
											2016-09-23 03:49:41 +08:00
										 |  |  |     if (variable.initLock) { | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |       return this.$q.when(); | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 17:34:08 +08:00
										 |  |  |     // cascade updates to variables that use this variable
 | 
					
						
							|  |  |  |     var promises = _.map(this.variables, otherVariable => { | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |       if (otherVariable === variable) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |       if (otherVariable.dependsOn(variable)) { | 
					
						
							|  |  |  |         return this.updateOptions(otherVariable); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |     return this.$q.all(promises); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |   selectOptionsForCurrentValue(variable) { | 
					
						
							|  |  |  |     var i, y, value, option; | 
					
						
							|  |  |  |     var selected: any = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < variable.options.length; i++) { | 
					
						
							|  |  |  |       option = variable.options[i]; | 
					
						
							|  |  |  |       option.selected = false; | 
					
						
							|  |  |  |       if (_.isArray(variable.current.value)) { | 
					
						
							|  |  |  |         for (y = 0; y < variable.current.value.length; y++) { | 
					
						
							|  |  |  |           value = variable.current.value[y]; | 
					
						
							|  |  |  |           if (option.value === value) { | 
					
						
							|  |  |  |             option.selected = true; | 
					
						
							|  |  |  |             selected.push(option); | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |       } else if (option.value === variable.current.value) { | 
					
						
							|  |  |  |         option.selected = true; | 
					
						
							|  |  |  |         selected.push(option); | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return selected; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |   validateVariableSelectionState(variable) { | 
					
						
							|  |  |  |     if (!variable.current) { | 
					
						
							| 
									
										
										
										
											2016-09-22 15:00:15 +08:00
										 |  |  |       variable.current = {}; | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |     if (_.isArray(variable.current.value)) { | 
					
						
							|  |  |  |       var selected = this.selectOptionsForCurrentValue(variable); | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |       // if none pick first
 | 
					
						
							|  |  |  |       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(' + '), | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |       return variable.setValue(selected); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       var currentOption = _.find(variable.options, {text: variable.current.text}); | 
					
						
							|  |  |  |       if (currentOption) { | 
					
						
							|  |  |  |         return variable.setValue(currentOption); | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |         if (!variable.options.length) { return Promise.resolve(); } | 
					
						
							|  |  |  |         return variable.setValue(variable.options[0]); | 
					
						
							| 
									
										
										
										
											2016-09-16 16:48:03 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-16 22:50:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |   setOptionFromUrl(variable, urlValue) { | 
					
						
							|  |  |  |     var promise = this.$q.when(); | 
					
						
							| 
									
										
										
										
											2016-09-17 17:28:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |     if (variable.refresh) { | 
					
						
							|  |  |  |       promise = variable.updateOptions(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-17 17:28:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |     return promise.then(() => { | 
					
						
							|  |  |  |       var option = _.find(variable.options, op => { | 
					
						
							|  |  |  |         return op.text === urlValue || op.value === urlValue; | 
					
						
							| 
									
										
										
										
											2016-09-17 17:28:45 +08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |       option = option || {text: urlValue, value: urlValue}; | 
					
						
							|  |  |  |       return variable.setValue(option); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-17 17:28:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |   setOptionAsCurrent(variable, option) { | 
					
						
							|  |  |  |     variable.current = _.cloneDeep(option); | 
					
						
							| 
									
										
										
										
											2016-09-17 17:28:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  |     if (_.isArray(variable.current.text)) { | 
					
						
							|  |  |  |       variable.current.text = variable.current.text.join(' + '); | 
					
						
							| 
									
										
										
										
											2016-09-17 17:28:45 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-19 21:15:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     this.selectOptionsForCurrentValue(variable); | 
					
						
							|  |  |  |     return this.variableUpdated(variable); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-20 17:57:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-09-15 20:53:36 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | coreModule.service('variableSrv', VariableSrv); |