mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 18:09:57 -03:30
initial files for license diff directive
awLicenseFeature with show/hide changed file locations changing file location adjusting controller logic to only return list of features leveraging $rootScope instead of local storage adding awFeature directive for lists/forms for activity stream button Adding route resolvers and service for getting license In order to get the license info from the API and not from local storage, the UI needs to hit hte API before loading any pages, therefore I've added route resolvers that will ensure that we have the appropriate data (license features) before navigating to a new page. I've also added the awFeature directive to the organizations list -> add-button and the ldap checkbox on the user form page. adjusting alignment fixing jshint errors commting file for testings adding tests for features service and features controller adding features controller unit test
This commit is contained in:
parent
9d1dc55c5d
commit
79b79f0481
@ -33,7 +33,6 @@ import {PortalController} from 'tower/controllers/Portal';
|
||||
import dataServices from 'tower/services/_data-services';
|
||||
import dashboardGraphs from 'tower/directives/_dashboard-graphs';
|
||||
|
||||
|
||||
import {JobDetailController} from 'tower/controllers/JobDetail';
|
||||
import {JobStdoutController} from 'tower/controllers/JobStdout';
|
||||
import {JobTemplatesList, JobTemplatesAdd, JobTemplatesEdit} from 'tower/controllers/JobTemplates';
|
||||
@ -58,6 +57,7 @@ import 'tower/shared/Timer';
|
||||
import 'tower/shared/Socket';
|
||||
|
||||
import 'tower/job-templates/main';
|
||||
import 'tower/shared/features/main';
|
||||
|
||||
/*#if DEBUG#*/
|
||||
import {__deferLoadIfEnabled} from 'tower/debug';
|
||||
@ -171,7 +171,8 @@ var tower = angular.module('Tower', [
|
||||
'ConfigureTowerJobsListDefinition',
|
||||
'CreateCustomInventoryHelper',
|
||||
'CustomInventoryListDefinition',
|
||||
'AdhocHelper'
|
||||
'AdhocHelper',
|
||||
'features'
|
||||
])
|
||||
|
||||
.constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/')
|
||||
@ -184,277 +185,552 @@ var tower = angular.module('Tower', [
|
||||
|
||||
when('/jobs', {
|
||||
templateUrl: urlPrefix + 'partials/jobs.html',
|
||||
controller: JobsListController
|
||||
controller: JobsListController,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/portal', {
|
||||
templateUrl: urlPrefix + 'partials/portal.html',
|
||||
controller: PortalController
|
||||
controller: PortalController,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/jobs/:id', {
|
||||
templateUrl: urlPrefix + 'partials/job_detail.html',
|
||||
controller: JobDetailController
|
||||
controller: JobDetailController,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/jobs/:id/stdout', {
|
||||
templateUrl: urlPrefix + 'partials/job_stdout.html',
|
||||
controller: JobStdoutController
|
||||
controller: JobStdoutController,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/ad_hoc_commands/:id', {
|
||||
templateUrl: urlPrefix + 'partials/job_stdout_adhoc.html',
|
||||
controller: JobStdoutController
|
||||
controller: JobStdoutController,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/job_templates', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: JobTemplatesList
|
||||
controller: JobTemplatesList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/job_templates/add', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: JobTemplatesAdd
|
||||
controller: JobTemplatesAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/job_templates/:template_id', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: JobTemplatesEdit
|
||||
controller: JobTemplatesEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/job_templates/:id/schedules', {
|
||||
templateUrl: urlPrefix + 'partials/schedule_detail.html',
|
||||
controller: ScheduleEditController
|
||||
controller: ScheduleEditController,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/projects', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: ProjectsList
|
||||
controller: ProjectsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/projects/add', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: ProjectsAdd
|
||||
controller: ProjectsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/projects/:id', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: ProjectsEdit
|
||||
controller: ProjectsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/projects/:id/schedules', {
|
||||
templateUrl: urlPrefix + 'partials/schedule_detail.html',
|
||||
controller: ScheduleEditController
|
||||
controller: ScheduleEditController,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/projects/:project_id/organizations', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: OrganizationsList
|
||||
controller: OrganizationsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/projects/:project_id/organizations/add', {
|
||||
templateUrl: urlPrefix + 'partials/projects.html',
|
||||
controller: OrganizationsAdd
|
||||
controller: OrganizationsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories', {
|
||||
templateUrl: urlPrefix + 'partials/inventories.html',
|
||||
controller: InventoriesList
|
||||
controller: InventoriesList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories/add', {
|
||||
templateUrl: urlPrefix + 'partials/inventories.html',
|
||||
controller: InventoriesAdd
|
||||
controller: InventoriesAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories/:inventory_id', {
|
||||
templateUrl: urlPrefix + 'partials/inventories.html',
|
||||
controller: InventoriesEdit
|
||||
controller: InventoriesEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories/:inventory_id/job_templates/add', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: JobTemplatesAdd
|
||||
controller: JobTemplatesAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories/:inventory_id/job_templates/:template_id', {
|
||||
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||
controller: JobTemplatesEdit
|
||||
controller: JobTemplatesEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories/:inventory_id/manage', {
|
||||
templateUrl: urlPrefix + 'partials/inventory-manage.html',
|
||||
controller: InventoriesManage
|
||||
controller: InventoriesManage,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories/:inventory_id/adhoc', {
|
||||
templateUrl: urlPrefix + 'partials/adhoc.html',
|
||||
controller: AdhocCtrl
|
||||
controller: AdhocCtrl,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsList
|
||||
controller: OrganizationsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations/add', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsAdd
|
||||
controller: OrganizationsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: OrganizationsEdit
|
||||
controller: OrganizationsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/admins', {
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
controller: AdminsList
|
||||
controller: AdminsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/users', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersList
|
||||
controller: UsersList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/users/add', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersAdd
|
||||
controller: UsersAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations/:organization_id/users/:user_id', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersEdit
|
||||
controller: UsersEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsList
|
||||
controller: TeamsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsAdd
|
||||
controller: TeamsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: TeamsEdit
|
||||
controller: TeamsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/permissions/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: PermissionsAdd
|
||||
controller: PermissionsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/permissions', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: PermissionsList
|
||||
controller: PermissionsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/permissions/:permission_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: PermissionsEdit
|
||||
controller: PermissionsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/users', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: UsersList
|
||||
controller: UsersList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/users/:user_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: UsersEdit
|
||||
controller: UsersEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/projects', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: ProjectsList
|
||||
controller: ProjectsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/projects/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: ProjectsAdd
|
||||
controller: ProjectsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/projects/:project_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: ProjectsEdit
|
||||
controller: ProjectsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/credentials', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsList
|
||||
controller: CredentialsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/credentials/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsAdd
|
||||
controller: CredentialsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:team_id/credentials/:credential_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsEdit
|
||||
controller: CredentialsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/credentials', {
|
||||
templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsList
|
||||
controller: CredentialsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/credentials/add', {
|
||||
templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsAdd
|
||||
controller: CredentialsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/credentials/:credential_id', {
|
||||
templateUrl: urlPrefix + 'partials/credentials.html',
|
||||
controller: CredentialsEdit
|
||||
controller: CredentialsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersList
|
||||
controller: UsersList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users/add', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersAdd
|
||||
controller: UsersAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users/:user_id', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: UsersEdit
|
||||
controller: UsersEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users/:user_id/credentials', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: CredentialsList
|
||||
controller: CredentialsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users/:user_id/permissions/add', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: PermissionsAdd
|
||||
controller: PermissionsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users/:user_id/permissions', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: PermissionsList
|
||||
controller: PermissionsList,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users/:user_id/permissions/:permission_id', {
|
||||
templateUrl: urlPrefix + 'partials/users.html',
|
||||
controller: PermissionsEdit
|
||||
controller: PermissionsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/users/:user_id/credentials/add', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsAdd
|
||||
controller: CredentialsAdd,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/teams/:user_id/credentials/:credential_id', {
|
||||
templateUrl: urlPrefix + 'partials/teams.html',
|
||||
controller: CredentialsEdit
|
||||
controller: CredentialsEdit,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/login', {
|
||||
@ -464,17 +740,23 @@ var tower = angular.module('Tower', [
|
||||
|
||||
when('/logout', {
|
||||
templateUrl: urlPrefix + 'partials/blank.html',
|
||||
controller: Authenticate
|
||||
controller: Authenticate,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/home', {
|
||||
templateUrl: urlPrefix + 'partials/home.html',
|
||||
controller: Home,
|
||||
resolve: {
|
||||
graphData: ['$q', 'jobStatusGraphData', 'hostCountGraphData', function($q, jobStatusGraphData, hostCountGraphData) {
|
||||
graphData: ['$q', 'jobStatusGraphData', 'hostCountGraphData', 'FeaturesService', function($q, jobStatusGraphData, hostCountGraphData, FeaturesService) {
|
||||
return $q.all({
|
||||
jobStatus: jobStatusGraphData.get("month", "all"),
|
||||
hostCounts: hostCountGraphData.get()
|
||||
hostCounts: hostCountGraphData.get(),
|
||||
features: FeaturesService.get()
|
||||
});
|
||||
}]
|
||||
}
|
||||
@ -482,12 +764,22 @@ var tower = angular.module('Tower', [
|
||||
|
||||
when('/home/groups', {
|
||||
templateUrl: urlPrefix + 'partials/subhome.html',
|
||||
controller: HomeGroups
|
||||
controller: HomeGroups,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/home/hosts', {
|
||||
templateUrl: urlPrefix + 'partials/subhome.html',
|
||||
controller: HomeHosts
|
||||
controller: HomeHosts,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/sockets', {
|
||||
@ -684,7 +976,6 @@ var tower = angular.module('Tower', [
|
||||
if($location.$$url !== '/login'){
|
||||
$rootScope.$emit('OpenSocket');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
activateTab();
|
||||
|
||||
@ -25,7 +25,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ export default
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
awFeature: 'activity_streams',
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
|
||||
@ -40,6 +40,7 @@ export default
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
awFeature: 'activity_streams',
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
@ -258,27 +259,12 @@ export default
|
||||
dataTitle: 'Prompt for Extra Variables',
|
||||
dataContainer: "body"
|
||||
},
|
||||
// survey_enabled: {
|
||||
// type: 'custom',
|
||||
// column: 2,
|
||||
// control: '<div class="form-group">'+
|
||||
// '<div class="checkbox">'+
|
||||
// '<label><input type="checkbox" ng-model="survey_enabled" name="survey_enabled" id="job_templates_survey_enabled_chbox" class="ng-valid ng-valid-api-error ng-dirty" ng-true-value="true" ng-false-value="false">'+
|
||||
// '<span class="label-text">Enable Survey</span><a id="awp-survey_enabled" href="" aw-pop-over="<p>If checked, user will be prompted at job launch with a survey of questions related to the job.</p>'+
|
||||
// '<div class="popover-footer"><span class="key">esc</span> or click to close</div>" data-placement="right" data-container="body" data-title="Enable Survey" class="help-link" data-original-title="" title="" tabindex="-1">'+
|
||||
// '<i class="fa fa-question-circle"></i></a> </label>'+
|
||||
// '<div class="error api-error ng-binding" id="job_templates-survey_enabled-api-error" ng-bind="survey_enabled_api_error"></div>'+
|
||||
// '<button type="button" class="btn btn-sm btn-default" id="job_templates_edit_survey_btn" ng-click="navigateToSurvey()"><i class="fa fa-pencil"></i> Create Survey</button>'+
|
||||
// '</div>'+
|
||||
// '</div>'
|
||||
// },
|
||||
survey_enabled: {
|
||||
label: 'Enable Survey',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
// trueValue: true,
|
||||
// falseValue: false,
|
||||
awFeature: 'surveys',
|
||||
ngChange: "surveyEnabled()",
|
||||
column: 2,
|
||||
awPopOver: "<p>If checked, user will be prompted at job launch with a series of questions related to the job.</p>",
|
||||
|
||||
@ -30,6 +30,7 @@ export default
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
awFeature: 'activity_streams',
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
|
||||
@ -27,6 +27,7 @@ export default
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
awFeature: 'activity_streams',
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
|
||||
@ -41,6 +41,7 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
awFeature: 'activity_streams',
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
|
||||
@ -30,6 +30,7 @@ export default
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
awFeature: 'activity_streams',
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
|
||||
@ -31,6 +31,7 @@ export default
|
||||
'class': "btn-primary btn-xs activity-btn",
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
awFeature: 'activity_streams',
|
||||
dataPlacement: "top",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
@ -114,7 +115,8 @@ export default
|
||||
ldap_user: {
|
||||
label: 'Created by LDAP',
|
||||
type: 'checkbox',
|
||||
readonly: true
|
||||
readonly: true,
|
||||
awFeature: 'ldap'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -53,7 +53,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -169,7 +169,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
mode: 'all',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -102,7 +102,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
mode: 'all',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -92,7 +92,8 @@ export default
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -112,7 +112,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showGroupActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
mode: 'all',
|
||||
awFeature: 'activity_streams'
|
||||
},
|
||||
help: {
|
||||
mode: 'all',
|
||||
|
||||
@ -101,7 +101,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showHostActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'all'
|
||||
mode: 'all',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -54,6 +54,7 @@ export default
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
icon: "icon-comments-alt",
|
||||
awFeature: 'activity_streams',
|
||||
mode: 'edit',
|
||||
ngHide: 'portalMode===true'
|
||||
}
|
||||
|
||||
@ -40,12 +40,14 @@ export default
|
||||
add: {
|
||||
mode: 'all', // One of: edit, select, all
|
||||
ngClick: 'addOrganization()',
|
||||
awToolTip: 'Create a new organization'
|
||||
awToolTip: 'Create a new organization',
|
||||
awFeature: 'multiple_organizations'
|
||||
},
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -56,7 +56,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -75,7 +75,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -48,7 +48,8 @@ export default
|
||||
awToolTip: "View Activity Stream",
|
||||
icon: "icon-comments-alt",
|
||||
mode: 'edit',
|
||||
ngHide: 'portalMode===true'
|
||||
ngHide: 'portalMode===true',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -67,7 +67,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -52,7 +52,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -50,7 +50,8 @@ export default
|
||||
stream: {
|
||||
ngClick: "showActivity()",
|
||||
awToolTip: "View Activity Stream",
|
||||
mode: 'edit'
|
||||
mode: 'edit',
|
||||
awFeature: 'activity_streams'
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -95,6 +95,7 @@ angular.module('AuthService', ['ngCookies', Utilities.name])
|
||||
},
|
||||
|
||||
getLicense: function () {
|
||||
//check in here first to see if license is already obtained, if we do have it, then rootScope.license
|
||||
return $http({
|
||||
method: 'GET',
|
||||
url: GetBasePath('config'),
|
||||
@ -109,6 +110,7 @@ angular.module('AuthService', ['ngCookies', Utilities.name])
|
||||
license.version = data.version;
|
||||
license.tested = false;
|
||||
Store('license', license);
|
||||
$rootScope.features = Store('license').features;
|
||||
},
|
||||
|
||||
licenseTested: function () {
|
||||
|
||||
10
awx/ui/static/js/shared/features/features.controller.js
Normal file
10
awx/ui/static/js/shared/features/features.controller.js
Normal file
@ -0,0 +1,10 @@
|
||||
export default ['$rootScope', function ($rootScope) {
|
||||
|
||||
this.isFeatureEnabled = function(feature){
|
||||
if($rootScope.features[feature] === false){
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}];
|
||||
15
awx/ui/static/js/shared/features/features.directive.js
Normal file
15
awx/ui/static/js/shared/features/features.directive.js
Normal file
@ -0,0 +1,15 @@
|
||||
import featureController from 'tower/shared/features/features.controller';
|
||||
export default [ function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
controller: featureController,
|
||||
link: function (scope, element, attrs, controller){
|
||||
if(attrs.awFeature.length > 0){
|
||||
if(!controller.isFeatureEnabled(attrs.awFeature)){
|
||||
element.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}];
|
||||
30
awx/ui/static/js/shared/features/features.service.js
Normal file
30
awx/ui/static/js/shared/features/features.service.js
Normal file
@ -0,0 +1,30 @@
|
||||
export default ['$rootScope', 'Rest', 'GetBasePath', 'ProcessErrors', '$http', '$q',
|
||||
function ($rootScope, Rest, GetBasePath, ProcessErrors, $http, $q) {
|
||||
return {
|
||||
getFeatures: function(){
|
||||
var promise;
|
||||
Rest.setUrl(GetBasePath('config'));
|
||||
promise = Rest.get();
|
||||
return promise.then(function (data) {
|
||||
$rootScope.features = data.data.license_info.features;
|
||||
return $rootScope.features;
|
||||
}).catch(function (response) {
|
||||
ProcessErrors($rootScope, response.data, response.status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get license info. GET returned status: ' +
|
||||
response.status
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
get: function(){
|
||||
if(_.isEmpty($rootScope.features)){
|
||||
return this.getFeatures();
|
||||
} else {
|
||||
// $q.when will ensure that the result is returned
|
||||
// as a resovled promise.
|
||||
return $q.when($rootScope.features);
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
6
awx/ui/static/js/shared/features/main.js
Normal file
6
awx/ui/static/js/shared/features/main.js
Normal file
@ -0,0 +1,6 @@
|
||||
import awFeatureDirective from 'tower/shared/features/features.directive';
|
||||
import FeaturesService from 'tower/shared/features/features.service';
|
||||
export default
|
||||
angular.module('features', [])
|
||||
.directive('awFeature', awFeatureDirective)
|
||||
.service('FeaturesService', FeaturesService);
|
||||
@ -752,6 +752,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
||||
html += "'";
|
||||
html += (field.ngShow) ? this.attr(field, 'ngShow') : "";
|
||||
html += (field.ngHide) ? this.attr(field, 'ngHide') : "";
|
||||
html += (field.awFeature) ? "aw-feature=\"" + field.awFeature + "\" " : "";
|
||||
html += ">\n";
|
||||
|
||||
//text fields
|
||||
|
||||
@ -16,8 +16,10 @@
|
||||
ng-hide="isHiddenByOptions(options) ||
|
||||
hiddenOnCurrentPage(options.basePaths) ||
|
||||
hiddenInCurrentMode(options.mode)"
|
||||
toolbar="true">
|
||||
toolbar="true"
|
||||
aw-feature="{{options.awFeature}}">
|
||||
</button>
|
||||
|
||||
</span>
|
||||
<button
|
||||
toolbar-button
|
||||
|
||||
@ -19,7 +19,8 @@
|
||||
ng-click="showActivity()"
|
||||
aw-tool-tip="View Activity Stream"
|
||||
icon-name="stream"
|
||||
toolbar="true">
|
||||
toolbar="true"
|
||||
aw-feature="activity_stream">
|
||||
</button>
|
||||
|
||||
<!-- <button type="button" class="btn btn-xs btn-primary ng-hide" ng-click="refreshJobs()" id="refresh_btn" aw-tool-tip="Refresh the page" data-placement="top" ng-show="socketStatus == 'error'" data-original-title="" title=""><i class="fa fa-refresh fa-lg"></i> </button></div> -->
|
||||
|
||||
25
awx/ui/tests/unit/features/features.controller-test.js
Normal file
25
awx/ui/tests/unit/features/features.controller-test.js
Normal file
@ -0,0 +1,25 @@
|
||||
import featuresController from 'tower/shared/features/features.controller';
|
||||
|
||||
describe('featuresController', function() {
|
||||
|
||||
it('checks if a feature is enabled', inject(['$rootScope', function($rootScope) {
|
||||
var actual;
|
||||
|
||||
$rootScope.features = {
|
||||
activity_streams: true,
|
||||
ldap: false
|
||||
};
|
||||
|
||||
// TODO: extract into test controller in describeModule
|
||||
var Controller = featuresController[1];
|
||||
var controller = new Controller($rootScope);
|
||||
|
||||
actual = controller.isFeatureEnabled('activity_streams');
|
||||
expect(actual).to.be.true;
|
||||
|
||||
actual = controller.isFeatureEnabled('ldap');
|
||||
expect(actual).to.be.false;
|
||||
|
||||
|
||||
}]));
|
||||
})
|
||||
55
awx/ui/tests/unit/features/features.service-test.js
Normal file
55
awx/ui/tests/unit/features/features.service-test.js
Normal file
@ -0,0 +1,55 @@
|
||||
import features from 'tower/shared/features/main';
|
||||
import {describeModule} from '../describe-module';
|
||||
|
||||
//test that it returns features, as well as test that it is returned in rootScope
|
||||
|
||||
describeModule(features.name)
|
||||
.testService('FeaturesService', function(test, restStub) {
|
||||
|
||||
var service;
|
||||
|
||||
test.withService(function(_service) {
|
||||
service = _service;
|
||||
});
|
||||
|
||||
it('returns list of features', function() {
|
||||
var features = {},
|
||||
result = {
|
||||
data: {
|
||||
license_info: {
|
||||
features: features
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var actual = service.get();
|
||||
|
||||
restStub.succeed(result);
|
||||
restStub.flush();
|
||||
|
||||
return expect(actual).to.eventually.equal(features);
|
||||
|
||||
});
|
||||
|
||||
it('caches in rootScope', inject(['$rootScope',
|
||||
function($rootScope){
|
||||
var features = {},
|
||||
result = {
|
||||
data: {
|
||||
license_info: {
|
||||
features: features
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var actual = service.get();
|
||||
|
||||
restStub.succeed(result);
|
||||
restStub.flush();
|
||||
|
||||
return actual.then(function(){
|
||||
expect($rootScope.features).to.equal(features);
|
||||
});
|
||||
}]));
|
||||
|
||||
});
|
||||
@ -6,7 +6,8 @@
|
||||
"awx/ui/static/docs/**/*"
|
||||
],
|
||||
"watch": [
|
||||
"awx/ui/static"
|
||||
"awx/ui/static",
|
||||
"awx/ui/tests"
|
||||
],
|
||||
"ext": "js json less html"
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user