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:
Jared Tabor
2015-04-21 09:09:20 -04:00
parent 9d1dc55c5d
commit 79b79f0481
34 changed files with 546 additions and 98 deletions

View File

@@ -33,7 +33,6 @@ import {PortalController} from 'tower/controllers/Portal';
import dataServices from 'tower/services/_data-services'; import dataServices from 'tower/services/_data-services';
import dashboardGraphs from 'tower/directives/_dashboard-graphs'; import dashboardGraphs from 'tower/directives/_dashboard-graphs';
import {JobDetailController} from 'tower/controllers/JobDetail'; import {JobDetailController} from 'tower/controllers/JobDetail';
import {JobStdoutController} from 'tower/controllers/JobStdout'; import {JobStdoutController} from 'tower/controllers/JobStdout';
import {JobTemplatesList, JobTemplatesAdd, JobTemplatesEdit} from 'tower/controllers/JobTemplates'; import {JobTemplatesList, JobTemplatesAdd, JobTemplatesEdit} from 'tower/controllers/JobTemplates';
@@ -58,6 +57,7 @@ import 'tower/shared/Timer';
import 'tower/shared/Socket'; import 'tower/shared/Socket';
import 'tower/job-templates/main'; import 'tower/job-templates/main';
import 'tower/shared/features/main';
/*#if DEBUG#*/ /*#if DEBUG#*/
import {__deferLoadIfEnabled} from 'tower/debug'; import {__deferLoadIfEnabled} from 'tower/debug';
@@ -171,7 +171,8 @@ var tower = angular.module('Tower', [
'ConfigureTowerJobsListDefinition', 'ConfigureTowerJobsListDefinition',
'CreateCustomInventoryHelper', 'CreateCustomInventoryHelper',
'CustomInventoryListDefinition', 'CustomInventoryListDefinition',
'AdhocHelper' 'AdhocHelper',
'features'
]) ])
.constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/') .constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/')
@@ -184,277 +185,552 @@ var tower = angular.module('Tower', [
when('/jobs', { when('/jobs', {
templateUrl: urlPrefix + 'partials/jobs.html', templateUrl: urlPrefix + 'partials/jobs.html',
controller: JobsListController controller: JobsListController,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/portal', { when('/portal', {
templateUrl: urlPrefix + 'partials/portal.html', templateUrl: urlPrefix + 'partials/portal.html',
controller: PortalController controller: PortalController,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/jobs/:id', { when('/jobs/:id', {
templateUrl: urlPrefix + 'partials/job_detail.html', templateUrl: urlPrefix + 'partials/job_detail.html',
controller: JobDetailController controller: JobDetailController,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/jobs/:id/stdout', { when('/jobs/:id/stdout', {
templateUrl: urlPrefix + 'partials/job_stdout.html', templateUrl: urlPrefix + 'partials/job_stdout.html',
controller: JobStdoutController controller: JobStdoutController,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/ad_hoc_commands/:id', { when('/ad_hoc_commands/:id', {
templateUrl: urlPrefix + 'partials/job_stdout_adhoc.html', templateUrl: urlPrefix + 'partials/job_stdout_adhoc.html',
controller: JobStdoutController controller: JobStdoutController,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/job_templates', { when('/job_templates', {
templateUrl: urlPrefix + 'partials/job_templates.html', templateUrl: urlPrefix + 'partials/job_templates.html',
controller: JobTemplatesList controller: JobTemplatesList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/job_templates/add', { when('/job_templates/add', {
templateUrl: urlPrefix + 'partials/job_templates.html', templateUrl: urlPrefix + 'partials/job_templates.html',
controller: JobTemplatesAdd controller: JobTemplatesAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/job_templates/:template_id', { when('/job_templates/:template_id', {
templateUrl: urlPrefix + 'partials/job_templates.html', templateUrl: urlPrefix + 'partials/job_templates.html',
controller: JobTemplatesEdit controller: JobTemplatesEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/job_templates/:id/schedules', { when('/job_templates/:id/schedules', {
templateUrl: urlPrefix + 'partials/schedule_detail.html', templateUrl: urlPrefix + 'partials/schedule_detail.html',
controller: ScheduleEditController controller: ScheduleEditController,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/projects', { when('/projects', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: ProjectsList controller: ProjectsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/projects/add', { when('/projects/add', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: ProjectsAdd controller: ProjectsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/projects/:id', { when('/projects/:id', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: ProjectsEdit controller: ProjectsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/projects/:id/schedules', { when('/projects/:id/schedules', {
templateUrl: urlPrefix + 'partials/schedule_detail.html', templateUrl: urlPrefix + 'partials/schedule_detail.html',
controller: ScheduleEditController controller: ScheduleEditController,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/projects/:project_id/organizations', { when('/projects/:project_id/organizations', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: OrganizationsList controller: OrganizationsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/projects/:project_id/organizations/add', { when('/projects/:project_id/organizations/add', {
templateUrl: urlPrefix + 'partials/projects.html', templateUrl: urlPrefix + 'partials/projects.html',
controller: OrganizationsAdd controller: OrganizationsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/inventories', { when('/inventories', {
templateUrl: urlPrefix + 'partials/inventories.html', templateUrl: urlPrefix + 'partials/inventories.html',
controller: InventoriesList controller: InventoriesList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/inventories/add', { when('/inventories/add', {
templateUrl: urlPrefix + 'partials/inventories.html', templateUrl: urlPrefix + 'partials/inventories.html',
controller: InventoriesAdd controller: InventoriesAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/inventories/:inventory_id', { when('/inventories/:inventory_id', {
templateUrl: urlPrefix + 'partials/inventories.html', templateUrl: urlPrefix + 'partials/inventories.html',
controller: InventoriesEdit controller: InventoriesEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/inventories/:inventory_id/job_templates/add', { when('/inventories/:inventory_id/job_templates/add', {
templateUrl: urlPrefix + 'partials/job_templates.html', 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', { when('/inventories/:inventory_id/job_templates/:template_id', {
templateUrl: urlPrefix + 'partials/job_templates.html', templateUrl: urlPrefix + 'partials/job_templates.html',
controller: JobTemplatesEdit controller: JobTemplatesEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/inventories/:inventory_id/manage', { when('/inventories/:inventory_id/manage', {
templateUrl: urlPrefix + 'partials/inventory-manage.html', templateUrl: urlPrefix + 'partials/inventory-manage.html',
controller: InventoriesManage controller: InventoriesManage,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/inventories/:inventory_id/adhoc', { when('/inventories/:inventory_id/adhoc', {
templateUrl: urlPrefix + 'partials/adhoc.html', templateUrl: urlPrefix + 'partials/adhoc.html',
controller: AdhocCtrl controller: AdhocCtrl,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/organizations', { when('/organizations', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsList controller: OrganizationsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/organizations/add', { when('/organizations/add', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsAdd controller: OrganizationsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/organizations/:organization_id', { when('/organizations/:organization_id', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: OrganizationsEdit controller: OrganizationsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/organizations/:organization_id/admins', { when('/organizations/:organization_id/admins', {
templateUrl: urlPrefix + 'partials/organizations.html', templateUrl: urlPrefix + 'partials/organizations.html',
controller: AdminsList controller: AdminsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/organizations/:organization_id/users', { when('/organizations/:organization_id/users', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: UsersList controller: UsersList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/organizations/:organization_id/users/add', { when('/organizations/:organization_id/users/add', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: UsersAdd controller: UsersAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/organizations/:organization_id/users/:user_id', { when('/organizations/:organization_id/users/:user_id', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: UsersEdit controller: UsersEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams', { when('/teams', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: TeamsList controller: TeamsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/add', { when('/teams/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: TeamsAdd controller: TeamsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id', { when('/teams/:team_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: TeamsEdit controller: TeamsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/permissions/add', { when('/teams/:team_id/permissions/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: PermissionsAdd controller: PermissionsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/permissions', { when('/teams/:team_id/permissions', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: PermissionsList controller: PermissionsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/permissions/:permission_id', { when('/teams/:team_id/permissions/:permission_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: PermissionsEdit controller: PermissionsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/users', { when('/teams/:team_id/users', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: UsersList controller: UsersList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/users/:user_id', { when('/teams/:team_id/users/:user_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: UsersEdit controller: UsersEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/projects', { when('/teams/:team_id/projects', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: ProjectsList controller: ProjectsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/projects/add', { when('/teams/:team_id/projects/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: ProjectsAdd controller: ProjectsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/projects/:project_id', { when('/teams/:team_id/projects/:project_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: ProjectsEdit controller: ProjectsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/credentials', { when('/teams/:team_id/credentials', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsList controller: CredentialsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/credentials/add', { when('/teams/:team_id/credentials/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsAdd controller: CredentialsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:team_id/credentials/:credential_id', { when('/teams/:team_id/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsEdit controller: CredentialsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/credentials', { when('/credentials', {
templateUrl: urlPrefix + 'partials/credentials.html', templateUrl: urlPrefix + 'partials/credentials.html',
controller: CredentialsList controller: CredentialsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/credentials/add', { when('/credentials/add', {
templateUrl: urlPrefix + 'partials/credentials.html', templateUrl: urlPrefix + 'partials/credentials.html',
controller: CredentialsAdd controller: CredentialsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/credentials/:credential_id', { when('/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/credentials.html', templateUrl: urlPrefix + 'partials/credentials.html',
controller: CredentialsEdit controller: CredentialsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users', { when('/users', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: UsersList controller: UsersList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users/add', { when('/users/add', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: UsersAdd controller: UsersAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users/:user_id', { when('/users/:user_id', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: UsersEdit controller: UsersEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users/:user_id/credentials', { when('/users/:user_id/credentials', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: CredentialsList controller: CredentialsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users/:user_id/permissions/add', { when('/users/:user_id/permissions/add', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: PermissionsAdd controller: PermissionsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users/:user_id/permissions', { when('/users/:user_id/permissions', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: PermissionsList controller: PermissionsList,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users/:user_id/permissions/:permission_id', { when('/users/:user_id/permissions/:permission_id', {
templateUrl: urlPrefix + 'partials/users.html', templateUrl: urlPrefix + 'partials/users.html',
controller: PermissionsEdit controller: PermissionsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/users/:user_id/credentials/add', { when('/users/:user_id/credentials/add', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsAdd controller: CredentialsAdd,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/teams/:user_id/credentials/:credential_id', { when('/teams/:user_id/credentials/:credential_id', {
templateUrl: urlPrefix + 'partials/teams.html', templateUrl: urlPrefix + 'partials/teams.html',
controller: CredentialsEdit controller: CredentialsEdit,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/login', { when('/login', {
@@ -464,17 +740,23 @@ var tower = angular.module('Tower', [
when('/logout', { when('/logout', {
templateUrl: urlPrefix + 'partials/blank.html', templateUrl: urlPrefix + 'partials/blank.html',
controller: Authenticate controller: Authenticate,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/home', { when('/home', {
templateUrl: urlPrefix + 'partials/home.html', templateUrl: urlPrefix + 'partials/home.html',
controller: Home, controller: Home,
resolve: { resolve: {
graphData: ['$q', 'jobStatusGraphData', 'hostCountGraphData', function($q, jobStatusGraphData, hostCountGraphData) { graphData: ['$q', 'jobStatusGraphData', 'hostCountGraphData', 'FeaturesService', function($q, jobStatusGraphData, hostCountGraphData, FeaturesService) {
return $q.all({ return $q.all({
jobStatus: jobStatusGraphData.get("month", "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', { when('/home/groups', {
templateUrl: urlPrefix + 'partials/subhome.html', templateUrl: urlPrefix + 'partials/subhome.html',
controller: HomeGroups controller: HomeGroups,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/home/hosts', { when('/home/hosts', {
templateUrl: urlPrefix + 'partials/subhome.html', templateUrl: urlPrefix + 'partials/subhome.html',
controller: HomeHosts controller: HomeHosts,
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}). }).
when('/sockets', { when('/sockets', {
@@ -684,7 +976,6 @@ var tower = angular.module('Tower', [
if($location.$$url !== '/login'){ if($location.$$url !== '/login'){
$rootScope.$emit('OpenSocket'); $rootScope.$emit('OpenSocket');
} }
} }
activateTab(); activateTab();

View File

@@ -25,7 +25,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -30,6 +30,7 @@ export default
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
awFeature: 'activity_streams',
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',

View File

@@ -40,6 +40,7 @@ export default
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
awFeature: 'activity_streams',
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',
@@ -258,27 +259,12 @@ export default
dataTitle: 'Prompt for Extra Variables', dataTitle: 'Prompt for Extra Variables',
dataContainer: "body" 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=&quot;popover-footer&quot;><span class=&quot;key&quot;>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: { survey_enabled: {
label: 'Enable Survey', label: 'Enable Survey',
type: 'checkbox', type: 'checkbox',
addRequired: false, addRequired: false,
editRequird: false, editRequird: false,
// trueValue: true, awFeature: 'surveys',
// falseValue: false,
ngChange: "surveyEnabled()", ngChange: "surveyEnabled()",
column: 2, column: 2,
awPopOver: "<p>If checked, user will be prompted at job launch with a series of questions related to the job.</p>", awPopOver: "<p>If checked, user will be prompted at job launch with a series of questions related to the job.</p>",

View File

@@ -30,6 +30,7 @@ export default
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
awFeature: 'activity_streams',
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',

View File

@@ -27,6 +27,7 @@ export default
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
awFeature: 'activity_streams',
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',

View File

@@ -41,6 +41,7 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition'])
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
awFeature: 'activity_streams',
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',

View File

@@ -30,6 +30,7 @@ export default
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
awFeature: 'activity_streams',
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',

View File

@@ -31,6 +31,7 @@ export default
'class': "btn-primary btn-xs activity-btn", 'class': "btn-primary btn-xs activity-btn",
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
awFeature: 'activity_streams',
dataPlacement: "top", dataPlacement: "top",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',
@@ -114,7 +115,8 @@ export default
ldap_user: { ldap_user: {
label: 'Created by LDAP', label: 'Created by LDAP',
type: 'checkbox', type: 'checkbox',
readonly: true readonly: true,
awFeature: 'ldap'
} }
}, },

View File

@@ -53,7 +53,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -169,7 +169,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'all' mode: 'all',
awFeature: 'activity_streams'
} }
} }

View File

@@ -102,7 +102,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'all' mode: 'all',
awFeature: 'activity_streams'
} }
} }

View File

@@ -92,7 +92,8 @@ export default
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -112,7 +112,8 @@ export default
stream: { stream: {
ngClick: "showGroupActivity()", ngClick: "showGroupActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'all' mode: 'all',
awFeature: 'activity_streams'
}, },
help: { help: {
mode: 'all', mode: 'all',

View File

@@ -101,7 +101,8 @@ export default
stream: { stream: {
ngClick: "showHostActivity()", ngClick: "showHostActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'all' mode: 'all',
awFeature: 'activity_streams'
} }
} }

View File

@@ -54,6 +54,7 @@ export default
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
icon: "icon-comments-alt", icon: "icon-comments-alt",
awFeature: 'activity_streams',
mode: 'edit', mode: 'edit',
ngHide: 'portalMode===true' ngHide: 'portalMode===true'
} }

View File

@@ -40,12 +40,14 @@ export default
add: { add: {
mode: 'all', // One of: edit, select, all mode: 'all', // One of: edit, select, all
ngClick: 'addOrganization()', ngClick: 'addOrganization()',
awToolTip: 'Create a new organization' awToolTip: 'Create a new organization',
awFeature: 'multiple_organizations'
}, },
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -56,7 +56,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -75,7 +75,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -48,7 +48,8 @@ export default
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
icon: "icon-comments-alt", icon: "icon-comments-alt",
mode: 'edit', mode: 'edit',
ngHide: 'portalMode===true' ngHide: 'portalMode===true',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -67,7 +67,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -52,7 +52,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -50,7 +50,8 @@ export default
stream: { stream: {
ngClick: "showActivity()", ngClick: "showActivity()",
awToolTip: "View Activity Stream", awToolTip: "View Activity Stream",
mode: 'edit' mode: 'edit',
awFeature: 'activity_streams'
} }
}, },

View File

@@ -95,6 +95,7 @@ angular.module('AuthService', ['ngCookies', Utilities.name])
}, },
getLicense: function () { getLicense: function () {
//check in here first to see if license is already obtained, if we do have it, then rootScope.license
return $http({ return $http({
method: 'GET', method: 'GET',
url: GetBasePath('config'), url: GetBasePath('config'),
@@ -109,6 +110,7 @@ angular.module('AuthService', ['ngCookies', Utilities.name])
license.version = data.version; license.version = data.version;
license.tested = false; license.tested = false;
Store('license', license); Store('license', license);
$rootScope.features = Store('license').features;
}, },
licenseTested: function () { licenseTested: function () {

View File

@@ -0,0 +1,10 @@
export default ['$rootScope', function ($rootScope) {
this.isFeatureEnabled = function(feature){
if($rootScope.features[feature] === false){
return false;
} else {
return true;
}
};
}];

View 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();
}
}
}
};
}];

View 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);
}
}
};
}];

View 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);

View File

@@ -752,6 +752,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
html += "'"; html += "'";
html += (field.ngShow) ? this.attr(field, 'ngShow') : ""; html += (field.ngShow) ? this.attr(field, 'ngShow') : "";
html += (field.ngHide) ? this.attr(field, 'ngHide') : ""; html += (field.ngHide) ? this.attr(field, 'ngHide') : "";
html += (field.awFeature) ? "aw-feature=\"" + field.awFeature + "\" " : "";
html += ">\n"; html += ">\n";
//text fields //text fields

View File

@@ -16,8 +16,10 @@
ng-hide="isHiddenByOptions(options) || ng-hide="isHiddenByOptions(options) ||
hiddenOnCurrentPage(options.basePaths) || hiddenOnCurrentPage(options.basePaths) ||
hiddenInCurrentMode(options.mode)" hiddenInCurrentMode(options.mode)"
toolbar="true"> toolbar="true"
aw-feature="{{options.awFeature}}">
</button> </button>
</span> </span>
<button <button
toolbar-button toolbar-button

View File

@@ -19,7 +19,8 @@
ng-click="showActivity()" ng-click="showActivity()"
aw-tool-tip="View Activity Stream" aw-tool-tip="View Activity Stream"
icon-name="stream" icon-name="stream"
toolbar="true"> toolbar="true"
aw-feature="activity_stream">
</button> </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> --> <!-- <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> -->

View 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;
}]));
})

View 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);
});
}]));
});

View File

@@ -6,7 +6,8 @@
"awx/ui/static/docs/**/*" "awx/ui/static/docs/**/*"
], ],
"watch": [ "watch": [
"awx/ui/static" "awx/ui/static",
"awx/ui/tests"
], ],
"ext": "js json less html" "ext": "js json less html"
} }