Fixes namespace collision & allows command-line options to be passed to UI build system (#3876)

* Fixes BrowserSync window.name namespace collision #3872

* Allow command-line arguments to be passed to development UI builds.
Add support for --ng-debug and --router-debug flags to turn on Angular's
$log service and ui-router's trace utility.
Cleans up development debug settings & defunct websocket configuration.

Resolves lingering issues raised by trying read asynchronously-loaded config file during AngularJS config phase. #3872

* shrinkwrap updated minimist

* update CONTRIBUTING.md to include UI build options

* feedback/review
This commit is contained in:
Leigh Johnson 2016-11-09 12:49:18 -05:00 committed by GitHub
parent fe24d0fe0f
commit 0d3eb67bd0
8 changed files with 431 additions and 442 deletions

View File

@ -569,14 +569,15 @@ $(UI_DEPS_FLAG_FILE): awx/ui/package.json
touch $(UI_DEPS_FLAG_FILE)
ui-docker-machine: $(UI_DEPS_FLAG_FILE)
$(NPM_BIN) --prefix awx/ui run build-docker-machine
$(NPM_BIN) --prefix awx/ui run build-docker-machine -- $(MAKEFLAGS)
# Native docker. Builds UI and raises BrowserSync & filesystem polling.
ui-docker: $(UI_DEPS_FLAG_FILE)
$(NPM_BIN) --prefix awx/ui run build-docker-cid
$(NPM_BIN) --prefix awx/ui run build-docker-cid -- $(MAKEFLAGS)
# Builds UI with development/debug settings enabled. Does not raise browser-sync or filesystem polling.
# Builds UI with development UI without raising browser-sync or filesystem polling.
ui-devel: $(UI_DEPS_FLAG_FILE)
$(NPM_BIN) --prefix awx/ui run build-devel
$(NPM_BIN) --prefix awx/ui run build-devel -- $(MAKEFLAGS)
ui-release: $(UI_RELEASE_FLAG_FILE)

View File

@ -30,6 +30,7 @@ module.exports = function(grunt) {
'clean:tmp',
'clean:static',
'concurrent:dev',
'sync',
]);
grunt.registerTask('devNoSync', [

View File

@ -18,12 +18,17 @@ import 'select2';
import uiRouter from 'angular-ui-router';
// backwards compatibility for $stateChange* events
import 'angular-ui-router/release/stateEvents';
// ui-router debugging
//import { trace } from 'angular-ui-router';
//trace.enable();
// Configuration dependencies
global.$AnsibleConfig = null;
// Provided via Webpack DefinePlugin in webpack.config.js
global.$ENV = $ENV || null;
// ui-router debugging
if ($ENV['route-debug']){
let trace = require('angular-ui-router').trace;
trace.enable();
}
var urlPrefix;
@ -203,6 +208,9 @@ var tower = angular.module('Tower', [
.constant('AngularScheduler.useTimezone', true)
.constant('AngularScheduler.showUTCField', true)
.constant('$timezones.definitions.location', urlPrefix + 'lib/angular-tz-extensions/tz/data')
.config(['$logProvider', function($logProvider) {
$logProvider.debugEnabled($ENV['ng-debug'] || false);
}])
.config(['$pendolyticsProvider', function($pendolyticsProvider) {
$pendolyticsProvider.doNotAutoStart();
}])
@ -214,11 +222,10 @@ var tower = angular.module('Tower', [
});
}])
.config(['$urlRouterProvider', '$breadcrumbProvider', 'QuerySetProvider',
'$urlMatcherFactoryProvider', 'stateDefinitionsProvider', '$stateProvider', '$stateExtenderProvider',
'$urlMatcherFactoryProvider', 'stateDefinitionsProvider', '$stateProvider',
function($urlRouterProvider, $breadcrumbProvider, QuerySet,
$urlMatcherFactoryProvider, stateDefinitionsProvider, $stateProvider, $stateExtenderProvider) {
let $stateExtender = $stateExtenderProvider.$get(),
stateDefinitions = stateDefinitionsProvider.$get();
$urlMatcherFactoryProvider, stateDefinitionsProvider, $stateProvider) {
let stateDefinitions = stateDefinitionsProvider.$get();
$urlMatcherFactoryProvider.strictMode(false);
$breadcrumbProvider.setOptions({
templateUrl: urlPrefix + 'partials/breadcrumb.html'
@ -356,441 +363,427 @@ var tower = angular.module('Tower', [
});
}
])
.run(['$stateExtender', '$q', '$compile', '$cookieStore', '$rootScope', '$log', '$stateParams',
'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer',
'ClearScope', 'LoadConfig', 'Store', 'pendoService', 'Prompt', 'Rest',
'Wait', 'ProcessErrors', '$state', 'GetBasePath', 'ConfigService',
'FeaturesService', '$filter', 'SocketService', 'I18NInit',
function($stateExtender, $q, $compile, $cookieStore, $rootScope, $log, $stateParams,
CheckLicense, $location, Authorization, LoadBasePaths, Timer,
ClearScope, LoadConfig, Store, pendoService, Prompt, Rest, Wait,
ProcessErrors, $state, GetBasePath, ConfigService, FeaturesService,
$filter, SocketService, I18NInit) {
.config(['$provide', function($provide) {
$provide.decorator('$log', ['$delegate', function($delegate) {
var _debug = $delegate.debug;
$delegate.debug = function(msg) {
// only show debug messages when debug_mode set to true in config
if ($AnsibleConfig && $AnsibleConfig.debug_mode) {
_debug(msg);
}
};
return $delegate;
}]);
}])
$rootScope.$state = $state;
$rootScope.$state.matches = function(stateName) {
return $state.current.name.search(stateName) > 0;
};
$rootScope.$stateParams = $stateParams;
.run(['$stateExtender', '$q', '$compile', '$cookieStore', '$rootScope', '$log', '$stateParams',
'CheckLicense', '$location', 'Authorization', 'LoadBasePaths', 'Timer',
'ClearScope', 'LoadConfig', 'Store', 'pendoService', 'Prompt', 'Rest',
'Wait', 'ProcessErrors', '$state', 'GetBasePath', 'ConfigService',
'FeaturesService', '$filter', 'SocketService', 'I18NInit',
function($stateExtender, $q, $compile, $cookieStore, $rootScope, $log, $stateParams,
CheckLicense, $location, Authorization, LoadBasePaths, Timer,
ClearScope, LoadConfig, Store, pendoService, Prompt, Rest, Wait,
ProcessErrors, $state, GetBasePath, ConfigService, FeaturesService,
$filter, SocketService, I18NInit) {
I18NInit();
$stateExtender.addState({
name: 'dashboard',
url: '/home',
templateUrl: urlPrefix + 'partials/home.html',
controller: Home,
params: { licenseMissing: null },
data: {
activityStream: true,
refreshButton: true,
socket: {
"groups": {
"jobs": ["status_changed"]
}
},
},
ncyBreadcrumb: {
label: N_("DASHBOARD")
},
resolve: {
graphData: ['$q', 'jobStatusGraphData', '$rootScope',
function($q, jobStatusGraphData, $rootScope) {
return $rootScope.featuresConfigured.promise.then(function() {
return $q.all({
jobStatus: jobStatusGraphData.get("month", "all"),
});
});
}
]
}
});
$rootScope.$state = $state;
$rootScope.$state.matches = function(stateName) {
return $state.current.name.search(stateName) > 0;
};
$rootScope.$stateParams = $stateParams;
I18NInit();
$stateExtender.addState({
name: 'dashboard',
url: '/home',
templateUrl: urlPrefix + 'partials/home.html',
controller: Home,
params: { licenseMissing: null },
data: {
activityStream: true,
refreshButton: true,
socket: {
"groups": {
"jobs": ["status_changed"]
$stateExtender.addState({
searchPrefix: 'job',
name: 'jobs',
url: '/jobs',
ncyBreadcrumb: {
label: N_("JOBS")
},
params: {
job_search: {
value: { order_by: '-finished' }
}
},
},
ncyBreadcrumb: {
label: N_("DASHBOARD")
},
resolve: {
graphData: ['$q', 'jobStatusGraphData', '$rootScope',
function($q, jobStatusGraphData, $rootScope) {
return $rootScope.featuresConfigured.promise.then(function() {
return $q.all({
jobStatus: jobStatusGraphData.get("month", "all"),
data: {
socket: {
"groups": {
"jobs": ["status_changed"],
"schedules": ["changed"]
}
}
},
resolve: {
Dataset: ['AllJobsList', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}]
},
views: {
'@': {
templateUrl: urlPrefix + 'partials/jobs.html',
},
'list@jobs': {
templateProvider: function(AllJobsList, generateList) {
let html = generateList.build({
list: AllJobsList,
mode: 'edit'
});
return html;
},
controller: JobsListController
}
}
});
$stateExtender.addState({
name: 'teamUsers',
url: '/teams/:team_id/users',
templateUrl: urlPrefix + 'partials/teams.html',
controller: UsersList,
resolve: {
Users: ['UsersList', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}]
}
});
$stateExtender.addState({
name: 'userCredentials',
url: '/users/:user_id/credentials',
templateUrl: urlPrefix + 'partials/users.html',
controller: CredentialsList
});
$stateExtender.addState({
name: 'userCredentialAdd',
url: '/users/:user_id/credentials/add',
templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsAdd
});
$stateExtender.addState({
name: 'teamUserCredentialEdit',
url: '/teams/:user_id/credentials/:credential_id',
templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsEdit
});
$stateExtender.addState({
name: 'sockets',
url: '/sockets',
templateUrl: urlPrefix + 'partials/sockets.html',
controller: SocketsController,
ncyBreadcrumb: {
label: 'SOCKETS'
}
});
$rootScope.addPermission = function(scope) {
$compile("<add-permissions class='AddPermissions'></add-permissions>")(scope);
};
$rootScope.addPermissionWithoutTeamTab = function(scope) {
$compile("<add-permissions class='AddPermissions' without-team-permissions='true'></add-permissions>")(scope);
};
$rootScope.deletePermission = function(user, accessListEntry) {
let entry = accessListEntry;
let action = function() {
$('#prompt-modal').modal('hide');
Wait('start');
let url;
if (entry.team_id) {
url = GetBasePath("teams") + entry.team_id + "/roles/";
} else {
url = GetBasePath("users") + user.id + "/roles/";
}
Rest.setUrl(url);
Rest.post({ "disassociate": true, "id": entry.id })
.success(function() {
Wait('stop');
$state.go('.', null, { reload: true });
})
.error(function(data, status) {
ProcessErrors($rootScope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to remove access. Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
}
]
}
});
};
$stateExtender.addState({
searchPrefix: 'job',
name: 'jobs',
url: '/jobs',
ncyBreadcrumb: {
label: N_("JOBS")
},
params: {
job_search: {
value: { order_by: '-finished' }
}
},
data: {
socket: {
"groups": {
"jobs": ["status_changed"],
"schedules": ["changed"]
}
}
},
resolve: {
Dataset: ['AllJobsList', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}]
},
views: {
'@': {
templateUrl: urlPrefix + 'partials/jobs.html',
},
'list@jobs': {
templateProvider: function(AllJobsList, generateList) {
let html = generateList.build({
list: AllJobsList,
mode: 'edit'
});
return html;
},
controller: JobsListController
}
}
});
$stateExtender.addState({
name: 'teamUsers',
url: '/teams/:team_id/users',
templateUrl: urlPrefix + 'partials/teams.html',
controller: UsersList,
resolve: {
Users: ['UsersList', 'QuerySet', '$stateParams', 'GetBasePath', (list, qs, $stateParams, GetBasePath) => {
let path = GetBasePath(list.basePath) || GetBasePath(list.name);
return qs.search(path, $stateParams[`${list.iterator}_search`]);
}]
}
});
$stateExtender.addState({
name: 'userCredentials',
url: '/users/:user_id/credentials',
templateUrl: urlPrefix + 'partials/users.html',
controller: CredentialsList
});
$stateExtender.addState({
name: 'userCredentialAdd',
url: '/users/:user_id/credentials/add',
templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsAdd
});
$stateExtender.addState({
name: 'teamUserCredentialEdit',
url: '/teams/:user_id/credentials/:credential_id',
templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsEdit
});
$stateExtender.addState({
name: 'sockets',
url: '/sockets',
templateUrl: urlPrefix + 'partials/sockets.html',
controller: SocketsController,
ncyBreadcrumb: {
label: 'SOCKETS'
}
});
$rootScope.addPermission = function(scope) {
$compile("<add-permissions class='AddPermissions'></add-permissions>")(scope);
};
$rootScope.addPermissionWithoutTeamTab = function(scope) {
$compile("<add-permissions class='AddPermissions' without-team-permissions='true'></add-permissions>")(scope);
};
$rootScope.deletePermission = function(user, accessListEntry) {
let entry = accessListEntry;
let action = function() {
$('#prompt-modal').modal('hide');
Wait('start');
let url;
if (entry.team_id) {
url = GetBasePath("teams") + entry.team_id + "/roles/";
if (accessListEntry.team_id) {
Prompt({
hdr: `Team access removal`,
body: `<div class="Prompt-bodyQuery">Please confirm that you would like to remove <span class="Prompt-emphasis">${entry.name}</span> access from the team <span class="Prompt-emphasis">${$filter('sanitize')(entry.team_name)}</span>. This will affect all members of the team. If you would like to only remove access for this particular user, please remove them from the team.</div>`,
action: action,
actionText: 'REMOVE TEAM ACCESS'
});
} else {
url = GetBasePath("users") + user.id + "/roles/";
Prompt({
hdr: `User access removal`,
body: `<div class="Prompt-bodyQuery">Please confirm that you would like to remove <span class="Prompt-emphasis">${entry.name}</span> access from <span class="Prompt-emphasis">${user.username}</span>.</div>`,
action: action,
actionText: 'REMOVE'
});
}
Rest.setUrl(url);
Rest.post({ "disassociate": true, "id": entry.id })
.success(function() {
Wait('stop');
$state.go('.', null, { reload: true });
})
.error(function(data, status) {
ProcessErrors($rootScope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to remove access. Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
};
if (accessListEntry.team_id) {
Prompt({
hdr: `Team access removal`,
body: `<div class="Prompt-bodyQuery">Please confirm that you would like to remove <span class="Prompt-emphasis">${entry.name}</span> access from the team <span class="Prompt-emphasis">${$filter('sanitize')(entry.team_name)}</span>. This will affect all members of the team. If you would like to only remove access for this particular user, please remove them from the team.</div>`,
action: action,
actionText: 'REMOVE TEAM ACCESS'
});
} else {
Prompt({
hdr: `User access removal`,
body: `<div class="Prompt-bodyQuery">Please confirm that you would like to remove <span class="Prompt-emphasis">${entry.name}</span> access from <span class="Prompt-emphasis">${user.username}</span>.</div>`,
action: action,
actionText: 'REMOVE'
});
}
};
$rootScope.deletePermissionFromUser = function(userId, userName, roleName, roleType, url) {
var action = function() {
$('#prompt-modal').modal('hide');
Wait('start');
Rest.setUrl(url);
Rest.post({ "disassociate": true, "id": userId })
.success(function() {
Wait('stop');
$rootScope.$broadcast("refreshList", "permission");
})
.error(function(data, status) {
ProcessErrors($rootScope, data, status, null, {
hdr: 'Error!',
msg: 'Could not disassociate user from role. Call to ' + url + ' failed. DELETE returned status: ' + status
$rootScope.deletePermissionFromUser = function(userId, userName, roleName, roleType, url) {
var action = function() {
$('#prompt-modal').modal('hide');
Wait('start');
Rest.setUrl(url);
Rest.post({ "disassociate": true, "id": userId })
.success(function() {
Wait('stop');
$rootScope.$broadcast("refreshList", "permission");
})
.error(function(data, status) {
ProcessErrors($rootScope, data, status, null, {
hdr: 'Error!',
msg: 'Could not disassociate user from role. Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
});
};
};
Prompt({
hdr: `Remove role`,
body: `
Prompt({
hdr: `Remove role`,
body: `
<div class="Prompt-bodyQuery">
Confirm the removal of the ${roleType}
<span class="Prompt-emphasis"> ${roleName} </span>
role associated with ${userName}.
</div>
`,
action: action,
actionText: 'REMOVE'
});
};
$rootScope.deletePermissionFromTeam = function(teamId, teamName, roleName, roleType, url) {
var action = function() {
$('#prompt-modal').modal('hide');
Wait('start');
Rest.setUrl(url);
Rest.post({ "disassociate": true, "id": teamId })
.success(function() {
Wait('stop');
$rootScope.$broadcast("refreshList", "role");
})
.error(function(data, status) {
ProcessErrors($rootScope, data, status, null, {
hdr: 'Error!',
msg: 'Could not disassociate team from role. Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
action: action,
actionText: 'REMOVE'
});
};
Prompt({
hdr: `Remove role`,
body: `
$rootScope.deletePermissionFromTeam = function(teamId, teamName, roleName, roleType, url) {
var action = function() {
$('#prompt-modal').modal('hide');
Wait('start');
Rest.setUrl(url);
Rest.post({ "disassociate": true, "id": teamId })
.success(function() {
Wait('stop');
$rootScope.$broadcast("refreshList", "role");
})
.error(function(data, status) {
ProcessErrors($rootScope, data, status, null, {
hdr: 'Error!',
msg: 'Could not disassociate team from role. Call to ' + url + ' failed. DELETE returned status: ' + status
});
});
};
Prompt({
hdr: `Remove role`,
body: `
<div class="Prompt-bodyQuery">
Confirm the removal of the ${roleType}
<span class="Prompt-emphasis"> ${roleName} </span>
role associated with the ${teamName} team.
</div>
`,
action: action,
actionText: 'REMOVE'
});
};
action: action,
actionText: 'REMOVE'
});
};
function activateTab() {
// Make the correct tab active
var base = $location.path().replace(/^\//, '').split('/')[0];
function activateTab() {
// Make the correct tab active
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === '') {
base = 'home';
} else {
//base.replace(/\_/g, ' ');
base = (base === 'job_events' || base === 'job_host_summaries') ? 'jobs' : base;
}
//make sure that the tower icon works when not in portal mode
$('.navbar-brand').attr('href', '/#/home');
$rootScope.portalMode = false;
if (base === 'portal') {
$rootScope.portalMode = true;
//in portal mode we don't want the tower icon to lead anywhere
$('.navbar-brand').removeAttr('href');
}
$('#ansible-list-title').html('<strong>' + base.replace(/\_/, ' ') + '</strong>');
$('#ansible-main-menu li').each(function() {
$(this).removeClass('active');
});
$('#ansible-main-menu #' + base).addClass('active');
// Apply to mobile menu as well
$('#ansible-mobile-menu a').each(function() {
$(this).removeClass('active');
});
$('#ansible-mobile-menu a[href="#' + base + '"]').addClass('active');
}
if ($rootScope.removeConfigReady) {
$rootScope.removeConfigReady();
}
$rootScope.removeConfigReady = $rootScope.$on('ConfigReady', function() {
var list, id;
// initially set row edit indicator for crud pages
if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {
list = $location.$$path.split("/")[3];
id = $location.$$path.split("/")[4];
$rootScope.listBeingEdited = list;
$rootScope.rowBeingEdited = id;
$rootScope.initialIndicatorLoad = true;
} else if ($location.$$path.split("/")[2]) {
list = $location.$$path.split("/")[1];
id = $location.$$path.split("/")[2];
$rootScope.listBeingEdited = list;
$rootScope.rowBeingEdited = id;
}
LoadBasePaths();
$rootScope.crumbCache = [];
// $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) {
// SocketService.subscribe(toState, toParams);
// });
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState) {
if (fromState.name === 'license' && toParams.hasOwnProperty('licenseMissing')) {
$rootScope.licenseMissing = toParams.licenseMissing;
if (base === '') {
base = 'home';
} else {
//base.replace(/\_/g, ' ');
base = (base === 'job_events' || base === 'job_host_summaries') ? 'jobs' : base;
}
//make sure that the tower icon works when not in portal mode
$('.navbar-brand').attr('href', '/#/home');
$rootScope.portalMode = false;
if (base === 'portal') {
$rootScope.portalMode = true;
//in portal mode we don't want the tower icon to lead anywhere
$('.navbar-brand').removeAttr('href');
}
$('#ansible-list-title').html('<strong>' + base.replace(/\_/, ' ') + '</strong>');
$('#ansible-main-menu li').each(function() {
$(this).removeClass('active');
});
$('#ansible-main-menu #' + base).addClass('active');
// Apply to mobile menu as well
$('#ansible-mobile-menu a').each(function() {
$(this).removeClass('active');
});
$('#ansible-mobile-menu a[href="#' + base + '"]').addClass('active');
}
if ($rootScope.removeConfigReady) {
$rootScope.removeConfigReady();
}
$rootScope.removeConfigReady = $rootScope.$on('ConfigReady', function() {
var list, id;
// broadcast event change if editing crud object
// initially set row edit indicator for crud pages
if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {
list = $location.$$path.split("/")[3];
id = $location.$$path.split("/")[4];
if (!$rootScope.initialIndicatorLoad) {
delete $rootScope.listBeingEdited;
delete $rootScope.rowBeingEdited;
} else {
delete $rootScope.initialIndicatorLoad;
}
$rootScope.$broadcast("EditIndicatorChange", list, id);
$rootScope.listBeingEdited = list;
$rootScope.rowBeingEdited = id;
$rootScope.initialIndicatorLoad = true;
} else if ($location.$$path.split("/")[2]) {
list = $location.$$path.split("/")[1];
id = $location.$$path.split("/")[2];
delete $rootScope.listBeingEdited;
delete $rootScope.rowBeingEdited;
$rootScope.$broadcast("EditIndicatorChange", list, id);
} else if ($rootScope.addedAnItem) {
delete $rootScope.addedAnItem;
$rootScope.$broadcast("RemoveIndicator");
} else {
$rootScope.$broadcast("RemoveIndicator");
$rootScope.listBeingEdited = list;
$rootScope.rowBeingEdited = id;
}
});
if (!Authorization.getToken() || !Authorization.isUserLoggedIn()) {
// User not authenticated, redirect to login page
$location.path('/login');
} else {
var lastUser = $cookieStore.get('current_user'),
timestammp = Store('sessionTime');
if (lastUser && lastUser.id && timestammp && timestammp[lastUser.id] && timestammp[lastUser.id].loggedIn) {
var stime = timestammp[lastUser.id].time,
now = new Date().getTime();
if ((stime - now) <= 0) {
$location.path('/login');
LoadBasePaths();
$rootScope.crumbCache = [];
// $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) {
// SocketService.subscribe(toState, toParams);
// });
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState) {
if (fromState.name === 'license' && toParams.hasOwnProperty('licenseMissing')) {
$rootScope.licenseMissing = toParams.licenseMissing;
}
var list, id;
// broadcast event change if editing crud object
if ($location.$$path && $location.$$path.split("/")[3] && $location.$$path.split("/")[3] === "schedules") {
list = $location.$$path.split("/")[3];
id = $location.$$path.split("/")[4];
if (!$rootScope.initialIndicatorLoad) {
delete $rootScope.listBeingEdited;
delete $rootScope.rowBeingEdited;
} else {
delete $rootScope.initialIndicatorLoad;
}
$rootScope.$broadcast("EditIndicatorChange", list, id);
} else if ($location.$$path.split("/")[2]) {
list = $location.$$path.split("/")[1];
id = $location.$$path.split("/")[2];
delete $rootScope.listBeingEdited;
delete $rootScope.rowBeingEdited;
$rootScope.$broadcast("EditIndicatorChange", list, id);
} else if ($rootScope.addedAnItem) {
delete $rootScope.addedAnItem;
$rootScope.$broadcast("RemoveIndicator");
} else {
$rootScope.$broadcast("RemoveIndicator");
}
});
if (!Authorization.getToken() || !Authorization.isUserLoggedIn()) {
// User not authenticated, redirect to login page
$location.path('/login');
} else {
var lastUser = $cookieStore.get('current_user'),
timestammp = Store('sessionTime');
if (lastUser && lastUser.id && timestammp && timestammp[lastUser.id] && timestammp[lastUser.id].loggedIn) {
var stime = timestammp[lastUser.id].time,
now = new Date().getTime();
if ((stime - now) <= 0) {
$location.path('/login');
}
}
// If browser refresh, set the user_is_superuser value
$rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
$rootScope.user_is_system_auditor = Authorization.getUserInfo('is_system_auditor');
// state 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 (!_.contains($location.$$url, '/login')) {
ConfigService.getConfig().then(function() {
Timer.init().then(function(timer) {
$rootScope.sessionTimer = timer;
SocketService.init();
pendoService.issuePendoIdentity();
CheckLicense.test();
FeaturesService.get();
if ($location.$$path === "/home" && $state.current && $state.current.name === "") {
$state.go('dashboard');
} else if ($location.$$path === "/portal" && $state.current && $state.current.name === "") {
$state.go('portalMode');
}
});
});
}
}
// If browser refresh, set the user_is_superuser value
$rootScope.user_is_superuser = Authorization.getUserInfo('is_superuser');
$rootScope.user_is_system_auditor = Authorization.getUserInfo('is_system_auditor');
// state 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 (!_.contains($location.$$url, '/login')) {
ConfigService.getConfig().then(function() {
Timer.init().then(function(timer) {
$rootScope.sessionTimer = timer;
SocketService.init();
pendoService.issuePendoIdentity();
CheckLicense.test();
FeaturesService.get();
if ($location.$$path === "/home" && $state.current && $state.current.name === "") {
$state.go('dashboard');
} else if ($location.$$path === "/portal" && $state.current && $state.current.name === "") {
$state.go('portalMode');
}
});
});
}
activateTab();
$rootScope.viewCurrentUser = function() {
$location.path('/users/' + $rootScope.current_user.id);
};
$rootScope.viewLicense = function() {
$location.path('/license');
};
$rootScope.toggleTab = function(e, tab, tabs) {
e.preventDefault();
$('#' + tabs + ' #' + tab).tab('show');
};
$rootScope.leavePortal = function() {
$rootScope.portalMode = false;
$location.path('/home/');
};
}); // end of 'ConfigReady'
if (!$AnsibleConfig) {
// create a promise that will resolve state $AnsibleConfig is loaded
$rootScope.loginConfig = $q.defer();
}
if (!$rootScope.featuresConfigured) {
// create a promise that will resolve when features are loaded
$rootScope.featuresConfigured = $q.defer();
}
$rootScope.licenseMissing = true;
//the authorization controller redirects to the home page automatcially if there is no last path defined. in order to override
// this, set the last path to /portal for instances where portal is visited for the first time.
$rootScope.lastPath = ($location.path() === "/portal") ? 'portal' : undefined;
activateTab();
$rootScope.viewCurrentUser = function() {
$location.path('/users/' + $rootScope.current_user.id);
};
$rootScope.viewLicense = function() {
$location.path('/license');
};
$rootScope.toggleTab = function(e, tab, tabs) {
e.preventDefault();
$('#' + tabs + ' #' + tab).tab('show');
};
$rootScope.leavePortal = function() {
$rootScope.portalMode = false;
$location.path('/home/');
};
}); // end of 'ConfigReady'
if (!$AnsibleConfig) {
// create a promise that will resolve state $AnsibleConfig is loaded
$rootScope.loginConfig = $q.defer();
LoadConfig();
}
if (!$rootScope.featuresConfigured) {
// create a promise that will resolve when features are loaded
$rootScope.featuresConfigured = $q.defer();
}
$rootScope.licenseMissing = true;
//the authorization controller redirects to the home page automatcially if there is no last path defined. in order to override
// this, set the last path to /portal for instances where portal is visited for the first time.
$rootScope.lastPath = ($location.path() === "/portal") ? 'portal' : undefined;
LoadConfig();
}
]);
]);
export default tower;

View File

@ -28,8 +28,6 @@
// custom_login_info: "example notice" // have a notice displayed in the login modal for users. note that, as a security measure, custom html is not supported and will be escaped.
tooltip_delay: { show: 500, hide: 100 }, // Default number of milliseconds to delay displaying/hiding tooltips
debug_mode: false, // Enable console logging messages
password_length: 8, // Minimum user password length. Set to 0 to not set a limit
password_hasLowercase: true, // require a lowercase letter in the password
password_hasUppercase: false, // require an uppercase letter in the password
@ -58,7 +56,5 @@
}
},
websocket_port: 8080
};
})();

View File

@ -17,7 +17,13 @@ module.exports = {
ws: true
},
keepalive: false,
watchTask: true
watchTask: true,
// The browser-sync-client lib will write your current scroll position to window.name
// https://github.com/BrowserSync/browser-sync-client/blob/a2718faa91e11553feca7a3962313bf1ec6ba3e5/dist/index.js#L500
// This strategy is enabled in the core browser-sync lib, and not externally documented as an option. Yay!
// https://github.com/BrowserSync/browser-sync/blob/a522aaf12b6167d5591ed285eb3086f43a4d9ac2/lib/default-config.js#L312
scrollRestoreTechnique: null,
injectChanges: true
}
}
};

View File

@ -333,9 +333,9 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
},
"autoprefixer": {
"version": "6.5.2",
"version": "6.5.1",
"from": "autoprefixer@>=6.0.0 <7.0.0",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.5.2.tgz"
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.5.1.tgz"
},
"aws-sign2": {
"version": "0.6.0",
@ -872,9 +872,9 @@
}
},
"caniuse-db": {
"version": "1.0.30000578",
"from": "caniuse-db@>=1.0.30000576 <2.0.0",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000578.tgz"
"version": "1.0.30000576",
"from": "caniuse-db@>=1.0.30000554 <2.0.0",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000576.tgz"
},
"caseless": {
"version": "0.11.0",
@ -2904,18 +2904,6 @@
"from": "jsesc@>=1.3.0 <2.0.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz"
},
"jshint": {
"version": "2.9.4",
"from": "jshint@>=2.9.4 <3.0.0",
"resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.4.tgz",
"dependencies": {
"lodash": {
"version": "3.7.0",
"from": "lodash@>=3.7.0 <3.8.0",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz"
}
}
},
"json-schema": {
"version": "0.2.3",
"from": "json-schema@0.2.3",
@ -3150,14 +3138,7 @@
"meow": {
"version": "3.7.0",
"from": "meow@>=3.3.0 <4.0.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
"dependencies": {
"minimist": {
"version": "1.2.0",
"from": "minimist@>=1.1.3 <2.0.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz"
}
}
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz"
},
"merge-descriptors": {
"version": "1.0.1",
@ -3195,9 +3176,9 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz"
},
"minimist": {
"version": "0.0.10",
"from": "minimist@>=0.0.1 <0.1.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
"version": "1.2.0",
"from": "minimist@>=1.2.0 <2.0.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz"
},
"mkdirp": {
"version": "0.3.0",

View File

@ -16,8 +16,8 @@
"npm": "3.10.7"
},
"scripts": {
"build-docker-machine": "grunt dev; ip=$(docker-machine ip $DOCKER_MACHINE_NAME); npm set ansible-tower:django_host ${ip}; grunt sync",
"build-docker-cid": "grunt dev; ip=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $DOCkER_CID` | npm set config ansible-tower:django_host ${ip}; grunt sync",
"build-docker-machine": "ip=$(docker-machine ip $DOCKER_MACHINE_NAME); npm set ansible-tower:django_host ${ip}; grunt dev;",
"build-docker-cid": "ip=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' $DOCkER_CID` | npm set config ansible-tower:django_host ${ip}; grunt dev;",
"build-devel": "grunt devNoSync",
"pot": "grunt nggettext_extract",
"languages": "grunt nggettext_compile",
@ -73,6 +73,7 @@
"less-plugin-autoprefix": "^1.4.2",
"load-grunt-configs": "^1.0.0",
"load-grunt-tasks": "^3.5.0",
"minimist": "^1.2.0",
"phantomjs-prebuilt": "^2.1.12",
"time-grunt": "^1.4.0",
"webpack": "^1.13.1"

View File

@ -1,5 +1,16 @@
var path = require('path'),
webpack = require('webpack');
var awx_env,
path = require('path'),
webpack = require('webpack'),
options = require('minimist')(JSON.parse(process.env.npm_config_argv).remain),
merge = require('lodash').merge;
awx_env = {
'proxy': {
'django_host': process.env.npm_package_config_django_host,
'django_port': process.env.npm_package_config_django_port
}
};
merge(awx_env, options);
var vendorPkgs = [
'angular',
@ -54,6 +65,7 @@ var dev = {
}),
// (chunkName, outfileName)
new webpack.optimize.CommonsChunkPlugin('vendor', 'tower.vendor.js'),
new webpack.DefinePlugin({ $ENV: JSON.stringify(awx_env) })
],
module: {
preLoaders: [{
@ -65,8 +77,7 @@ var dev = {
emitErrors: true
}
}],
loaders: [
{
loaders: [{
// disable AMD loading (broken in this lib) and default to CommonJS (not broken)
test: /\.angular-tz-extensions.js$/,
loader: 'imports?define=>false'
@ -118,8 +129,7 @@ var release = {
})
],
module: {
loaders: [
{
loaders: [{
// disable AMD loading (broken in this lib) and default to CommonJS (not broken)
test: /\.angular-tz-extensions.js$/,
loader: 'imports?define=>false!'