Pendo.io service for Tower UI

This commit integrates the pendo support for the Tower UI, which involves creating an 'options' object and registering it with the pendo service installed in the index.html file. The options object is identified each time the user logs into Tower or when the browser session is refreshed.
This commit is contained in:
Jared Tabor 2015-09-21 14:02:31 -04:00
parent 90c3ccfc8c
commit 29daee8334
6 changed files with 158 additions and 7 deletions

View File

@ -74,6 +74,7 @@ __deferLoadIfEnabled();
/*#endif#*/
var tower = angular.module('Tower', [
'pendolytics',
'ngRoute',
'ngSanitize',
'ngCookies',
@ -830,9 +831,9 @@ var tower = angular.module('Tower', [
}])
.run(['$compile', '$cookieStore', '$rootScope', '$log', 'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer', 'ClearScope', 'HideStream', 'Socket',
'LoadConfig', 'Store', 'ShowSocketHelp', 'AboutAnsibleHelp',
'LoadConfig', 'Store', 'ShowSocketHelp', 'AboutAnsibleHelp', 'pendoService',
function ($compile, $cookieStore, $rootScope, $log, CheckLicense, $location, Authorization, LoadBasePaths, Timer, ClearScope, HideStream, Socket,
LoadConfig, Store, ShowSocketHelp, AboutAnsibleHelp) {
LoadConfig, Store, ShowSocketHelp, AboutAnsibleHelp, pendoService) {
var sock;
@ -1010,6 +1011,7 @@ var tower = angular.module('Tower', [
// when the user refreshes we want to open the socket, except if the user is on the login page, which should happen after the user logs in (see the AuthService module for that call to OpenSocket)
if($location.$$url !== '/login'){
$rootScope.$emit('OpenSocket');
pendoService.issuePendoIdentity();
}
}

View File

@ -1,4 +1,4 @@
/*************************************************
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
@ -109,6 +109,7 @@ export default
setLicense: function (data) {
var license = data.license_info;
license.analytics_status = data.analytics_status;
license.version = data.version;
license.tested = false;
Store('license', license);

View File

@ -55,12 +55,11 @@
*/
export default ['$log', '$cookieStore', '$compile', '$window', '$rootScope', '$location', 'Authorization', 'ToggleClass', 'Alert', 'Wait',
'Timer', 'Empty', 'ClearScope', '$scope',
'Timer', 'Empty', 'ClearScope', '$scope', 'pendoService',
function ($log, $cookieStore, $compile, $window, $rootScope, $location, Authorization, ToggleClass, Alert, Wait,
Timer, Empty, ClearScope, scope) {
Timer, Empty, ClearScope, scope, pendoService) {
var setLoginFocus, lastPath, lastUser, sessionExpired, loginAgain,
e, html;
var setLoginFocus, lastPath, lastUser, sessionExpired, loginAgain;
setLoginFocus = function () {
// Need to clear out any open dialog windows that might be open when this modal opens.
@ -143,6 +142,7 @@ export default ['$log', '$cookieStore', '$compile', '$window', '$rootScope', '$l
Authorization.getLicense()
.success(function (data) {
Authorization.setLicense(data);
pendoService.issuePendoIdentity();
Wait("stop");
if (lastPath() && lastUser()) {
// Go back to most recent navigation path

View File

@ -9,9 +9,11 @@ import loginModal from './loginModal/main';
import loginRoute from './login.route';
import logoutRoute from './logout.route';
import pendoService from './pendo/pendo.service';
export default
angular.module('login', [authentication.name, loginModal.name])
.service('pendoService', pendoService)
.config(['$routeProvider', function($routeProvider) {
var url = loginRoute.route;
delete loginRoute.route;

View File

@ -0,0 +1,137 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default
[ '$rootScope', '$pendolytics', 'Rest', 'GetBasePath', 'ProcessErrors', '$q',
'Store', '$log',
function ($rootScope, $pendolytics, Rest, GetBasePath, ProcessErrors, $q,
Store, $log) {
return {
setPendoOptions: function (config) {
var options = {
visitor: {
id: null,
role: null,
email: null
},
account: {
id: null,
planLevel: config.license_type,
planPrice: config.instance_count,
creationDate: config.license_date,
trial: config.trial
}
};
if(config.analytics_status === 'detailed'){
this.setDetailed(options, config);
}
else if(config.analytics_status === 'anonymous'){
this.setAnonymous(options);
}
return options;
},
setDetailed: function(options, config) {
// Detailed mode
// VisitorId: username+hash of license_key
// AccountId: hash of license_key from license
// email: contact_email from license OR email from Tower account
options.visitor.id = $rootScope.current_user.username + '@' + config.deployment_id;
options.account.id = config.deployment_id;
options.visitor.email = $rootScope.current_user.email;
},
setAnonymous: function (options) {
//Anonymous mode
// VisitorId: <some hardcoded id that is the same across all anonymous>
// AccountId: <some hardcoded id that is the same across all anonymous>
// email: <blank>
options.visitor.id = 0;
options.account.id = "tower.ansible.com";
options.visitor.email = "";
},
setRole: function(options) {
var deferred = $q.defer();
if($rootScope.current_user.is_superuser === true){
options.visitor.role = 'admin';
deferred.resolve(options);
}
else{
var url = GetBasePath('users') + $rootScope.current_user.id + '/admin_of_organizations/';
Rest.setUrl(url);
var promise = Rest.get();
promise.then(function (response) {
if(response.data.count > 0 ) {
options.visitor.role = "orgadmin";
deferred.resolve(options);
}
else {
options.visitor.role = "user";
deferred.resolve(options);
}
});
promise.catch(function (response) {
ProcessErrors($rootScope, response.data, response.status, null, {
hdr: 'Error!',
msg: 'Failed to get inventory name. GET returned status: ' +
response.status });
});
}
return deferred.promise;
},
getConfig: function () {
var config = Store('license'),
deferred = $q.defer();
if(_.isEmpty(config)){
var url = GetBasePath('config');
Rest.setUrl(url);
var promise = Rest.get();
promise.then(function (response) {
config = response.license_info;
config.analytics_status = response.analytics_status;
if(config.analytics_status !== 'off'){
deferred.resolve(config);
}
else {
deferred.reject('Pendo is turned off.');
}
});
promise.catch(function (response) {
ProcessErrors($rootScope, response.data, response.status, null, {
hdr: 'Error!',
msg: 'Failed to get inventory name. GET returned status: ' +
response.status });
});
}
else if(config.analytics_status !== 'off'){
deferred.resolve(config);
}
else {
deferred.reject('Pendo is turned off.');
}
return deferred.promise;
},
issuePendoIdentity: function () {
var that = this;
this.getConfig().then(function(config){
var options = that.setPendoOptions(config);
that.setRole(options).then(function(options){
$pendolytics.identify(options);
});
}, function(reason){
$log.debug(reason);
});
}
};
}
];

View File

@ -26,6 +26,15 @@
<script src="{{ STATIC_URL }}tower.concat.js?v={{version}}"></script>
<script src="//d3accju1t3mngt.cloudfront.net/js/angular/ng-pendo.js"></script>
<script>
window.pendo_options = {
// This is required to be able to load data client side
usePendoAgentAPI: true
};
</script>
</head>
<body data-user-agent="{{userAgent}}">