mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 19:10:07 -03:30
Merge branch 'devel' into workflow-visualizer-search
This commit is contained in:
commit
f3ee93b67f
@ -13,3 +13,4 @@
|
||||
@import 'truncate/_index';
|
||||
@import 'utility/_index';
|
||||
@import 'code-mirror/_index';
|
||||
@import 'cards/_index';
|
||||
|
||||
51
awx/ui/client/lib/components/cards/_index.less
Normal file
51
awx/ui/client/lib/components/cards/_index.less
Normal file
@ -0,0 +1,51 @@
|
||||
/* Cards Group */
|
||||
.at-CardContainer {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.at-CardGroup {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
grid-gap: 20px;
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.at-Card {
|
||||
min-height: 103px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
background-color: @at-white;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
border-left: 3px solid @at-white;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
|
||||
transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.at-Card:hover {
|
||||
background-color: @at-color-body-background;
|
||||
border-left: 3px solid @at-blue;
|
||||
box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.at-Card-title {
|
||||
font-size: 14px;
|
||||
color: @at-gray-70;
|
||||
font-weight: bold;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.at-Card-text {
|
||||
font-size: 12px;
|
||||
color: @at-gray-161b1f;
|
||||
}
|
||||
|
||||
/* Spacers */
|
||||
|
||||
.at-Card--spacer {
|
||||
min-height: 15px;
|
||||
}
|
||||
14
awx/ui/client/lib/components/cards/card.directive.js
Normal file
14
awx/ui/client/lib/components/cards/card.directive.js
Normal file
@ -0,0 +1,14 @@
|
||||
const templateUrl = require('~components/cards/card.partial.html');
|
||||
|
||||
function atCard () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl,
|
||||
scope: {
|
||||
title: '@',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default atCard;
|
||||
5
awx/ui/client/lib/components/cards/card.partial.html
Normal file
5
awx/ui/client/lib/components/cards/card.partial.html
Normal file
@ -0,0 +1,5 @@
|
||||
<a class="at-Card" >
|
||||
<span class="at-Card-title" translate>{{ title }}</span>
|
||||
<span class="at-Card--spacer"></span>
|
||||
<span class="at-Card-text" ng-transclude></span>
|
||||
</a>
|
||||
11
awx/ui/client/lib/components/cards/group.directive.js
Normal file
11
awx/ui/client/lib/components/cards/group.directive.js
Normal file
@ -0,0 +1,11 @@
|
||||
const templateUrl = require('~components/cards/group.partial.html');
|
||||
|
||||
function atCardGroup () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl,
|
||||
};
|
||||
}
|
||||
|
||||
export default atCardGroup;
|
||||
4
awx/ui/client/lib/components/cards/group.partial.html
Normal file
4
awx/ui/client/lib/components/cards/group.partial.html
Normal file
@ -0,0 +1,4 @@
|
||||
<div class="at-CardContainer">
|
||||
<div class="at-CardGroup" ng-transclude>
|
||||
</div>
|
||||
</div>
|
||||
@ -37,6 +37,8 @@ import toggleTag from '~components/toggle-tag/toggle-tag.directive';
|
||||
import topNavItem from '~components/layout/top-nav-item.directive';
|
||||
import truncate from '~components/truncate/truncate.directive';
|
||||
import atCodeMirror from '~components/code-mirror';
|
||||
import card from '~components/cards/card.directive';
|
||||
import cardGroup from '~components/cards/group.directive';
|
||||
|
||||
import BaseInputController from '~components/input/base.controller';
|
||||
import ComponentsStrings from '~components/components.strings';
|
||||
@ -84,6 +86,8 @@ angular
|
||||
.directive('atToggleTag', toggleTag)
|
||||
.directive('atTopNavItem', topNavItem)
|
||||
.directive('atTruncate', truncate)
|
||||
.directive('atCard', card)
|
||||
.directive('atCardGroup', cardGroup)
|
||||
.service('BaseInputController', BaseInputController)
|
||||
.service('ComponentsStrings', ComponentsStrings);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.at-Layout {
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
|
||||
@ -82,17 +82,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-side {
|
||||
&-sideContainer {
|
||||
background: @at-color-side-nav-background;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
top: @at-height-top-side-nav-makeup;
|
||||
overflow-y: auto;
|
||||
max-height: 100vh;
|
||||
min-width: @at-width-collapsed-side-nav;
|
||||
}
|
||||
|
||||
&-side {
|
||||
margin-top: @at-height-top-side-nav-makeup;
|
||||
width: @at-width-collapsed-side-nav;
|
||||
overflow-x: hidden;
|
||||
z-index: @at-z-index-side-nav;
|
||||
|
||||
.at-Popover-container {
|
||||
margin-top: 2px;
|
||||
@ -120,6 +116,10 @@
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
i.is-no-tooltip {
|
||||
padding-left: @at-padding-left-side-nav-item-icon-no-tooltip;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.is-active {
|
||||
background: @at-color-side-nav-item-background-hover;
|
||||
@ -201,7 +201,6 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
padding-left: @at-width-collapsed-side-nav;
|
||||
padding-bottom: @at-space-4x;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
@ -254,3 +253,44 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tower Sub Nav Dropdown */
|
||||
.at-SettingsSubPane {
|
||||
position: relative;
|
||||
}
|
||||
.at-SettingsSubPane-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: @at-gray-848992;
|
||||
min-width: 140px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
bottom: 0px;
|
||||
left: @at-width-collapsed-side-nav;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.at-Layout-side--expanded + .at-SettingsSubPane {
|
||||
.at-SettingsSubPane-content {
|
||||
left: @at-width-expanded-side-nav;
|
||||
}
|
||||
}
|
||||
|
||||
.at-SettingsSubPane-content a {
|
||||
color: @at-white;
|
||||
font-size: 13px;
|
||||
padding: 10px 20px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
height: 39px;
|
||||
}
|
||||
|
||||
// hover stuff
|
||||
.at-SettingsSubPane-content a:hover {
|
||||
background-color: @at-gray-b7;
|
||||
}
|
||||
.at-SettingsSubPane.at-SettingsSubPane--visible .at-SettingsSubPane-content {
|
||||
display: block;
|
||||
}
|
||||
.at-SettingsSubPane.at-SettingsSubPane--visible .nav-button {
|
||||
background-color: @at-gray-b7;
|
||||
}
|
||||
@ -1,8 +1,12 @@
|
||||
import defaultStrings from '~assets/default.strings.json';
|
||||
|
||||
const templateUrl = require('~components/layout/layout.partial.html');
|
||||
|
||||
function AtLayoutController ($scope, $http, strings, ProcessErrors, $transitions) {
|
||||
const vm = this || {};
|
||||
|
||||
vm.product = defaultStrings.BRAND_NAME;
|
||||
|
||||
$transitions.onSuccess({}, (transition) => {
|
||||
vm.currentState = transition.to().name;
|
||||
});
|
||||
|
||||
@ -95,8 +95,8 @@
|
||||
<at-side-nav-item icon-class="fa-cubes" route="applications" name="APPLICATIONS"
|
||||
ng-show="$parent.layoutVm.isSuperUser || $parent.layoutVm.isOrgAdmin">
|
||||
</at-side-nav-item>
|
||||
<at-side-nav-item icon-class="fa-cog" route="configuration" name="SETTINGS"
|
||||
system-admin-only="true">
|
||||
<at-side-nav-item icon-class="fa-cog" route="settings" name="SETTINGS"
|
||||
system-admin-only="true" show-settings-sub-menu="true" no-tooltip-on-collapsed="true">
|
||||
</at-side-nav-item>
|
||||
</at-side-nav>
|
||||
<div class="at-Layout-main" ng-class="{'at-Layout-main--noLicense': vm.licenseIsMissing}">
|
||||
|
||||
@ -2,6 +2,20 @@ const templateUrl = require('~components/layout/side-nav-item.partial.html');
|
||||
|
||||
function atSideNavItemLink (scope, element, attrs, ctrl) {
|
||||
[scope.navVm, scope.layoutVm] = ctrl;
|
||||
|
||||
if (attrs.showSettingsSubMenu) {
|
||||
element.hover(() => {
|
||||
scope.navVm.onSettingsNavItem = true;
|
||||
scope.navVm.showSettingsSubMenu = true;
|
||||
}, () => {
|
||||
scope.navVm.onSettingsNavItem = false;
|
||||
setTimeout(() => {
|
||||
if (!scope.navVm.onSettingsSubPane) {
|
||||
scope.navVm.showSettingsSubMenu = false;
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function AtSideNavItemController ($scope, strings) {
|
||||
@ -42,11 +56,13 @@ function atSideNavItem () {
|
||||
controller: AtSideNavItemController,
|
||||
controllerAs: 'vm',
|
||||
link: atSideNavItemLink,
|
||||
transclude: true,
|
||||
scope: {
|
||||
iconClass: '@',
|
||||
name: '@',
|
||||
route: '@',
|
||||
systemAdminOnly: '@'
|
||||
systemAdminOnly: '@',
|
||||
noTooltipOnCollapsed: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
<a class="at-Layout-sideNavItem" ui-sref="{{ route }}" ng-class="{'is-active': vm.isRoute}"
|
||||
ng-show="(!systemAdminOnly || layoutVm.isSuperUser) && layoutVm.isLoggedIn &&
|
||||
!layoutVm.licenseIsMissing">
|
||||
<at-popover state="vm.tooltip" ng-if="!navVm.isExpanded"></at-popover>
|
||||
<at-popover ng-if="!noTooltipOnCollapsed && !navVm.isExpanded" state="vm.tooltip"></at-popover>
|
||||
|
||||
<i class="fa {{ iconClass }}" ng-show="navVm.isExpanded"></i>
|
||||
<i class="fa {{ iconClass }}" ng-class="{'is-no-tooltip': noTooltipOnCollapsed}"
|
||||
ng-show="noTooltipOnCollapsed || navVm.isExpanded"></i>
|
||||
<span class="at-Layout-sideNavItemName" ng-show="navVm.isExpanded">
|
||||
{{ layoutVm.getString(name) }}
|
||||
</span>
|
||||
|
||||
@ -10,6 +10,17 @@ function atSideNavLink (scope, element, attrs, ctrl) {
|
||||
scope.$emit('clickOutsideSideNav');
|
||||
}
|
||||
});
|
||||
|
||||
element.find('.at-SettingsSubPane').hover(() => {
|
||||
scope.vm.onSettingsSubPane = true;
|
||||
}, () => {
|
||||
scope.vm.onSettingsSubPane = false;
|
||||
setTimeout(() => {
|
||||
if (!scope.vm.onSettingsNavItem) {
|
||||
scope.vm.showSettingsSubMenu = false;
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
function AtSideNavController ($scope, $window) {
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
<div class="at-Layout-side"
|
||||
ng-class="{'at-Layout-side--expanded': vm.isExpanded && layoutVm.isLoggedIn}" ng-show="layoutVm.isLoggedIn && !layoutVm.licenseIsMissing">
|
||||
<div class="at-Layout-sideNavItem at-Layout-sideNavToggle" ng-click="vm.toggleExpansion()"
|
||||
ng-show="layoutVm.isLoggedIn && !layoutVm.licenseIsMissing">
|
||||
<i class="fa fa-bars"></i>
|
||||
<div class="at-Layout-sideContainer" ng-show="layoutVm.isLoggedIn && !layoutVm.licenseIsMissing">
|
||||
<div class="at-Layout-side" ng-class="{'at-Layout-side--expanded': vm.isExpanded && layoutVm.isLoggedIn}">
|
||||
<div class="at-Layout-sideNavItem at-Layout-sideNavToggle" ng-click="vm.toggleExpansion()"
|
||||
ng-show="layoutVm.isLoggedIn && !layoutVm.licenseIsMissing">
|
||||
<i class="fa fa-bars"></i>
|
||||
</div>
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
<div class="at-SettingsSubPane" ng-class="{'at-SettingsSubPane--visible': vm.showSettingsSubMenu}">
|
||||
<div class="at-SettingsSubPane-content">
|
||||
<a ui-sref="settings.form({form: 'auth'})">Authentication</a>
|
||||
<a ui-sref="settings.form({form: 'jobs'})">Jobs</a>
|
||||
<a ui-sref="settings.form({form: 'system'})">System</a>
|
||||
<a ui-sref="settings.form({form: 'ui'})">User Interface</a>
|
||||
<a ui-sref="settings.form({form: 'license'})" ng-if="vm.product === 'Tower'">License</a>
|
||||
</div>
|
||||
</div>
|
||||
<ng-transclude></ng-transclude>
|
||||
</div>
|
||||
|
||||
@ -238,6 +238,7 @@
|
||||
@at-padding-left-side-nav-toggle-icon: 15px;
|
||||
@at-padding-left-side-nav-item-icon: 10px;
|
||||
@at-padding-left-side-nav-item-icon-expanded: 15px;
|
||||
@at-padding-left-side-nav-item-icon-no-tooltip: 18px;
|
||||
@at-padding-between-side-nav-icon-text: @at-space-3x;
|
||||
@at-padding-list-empty: @at-space-2x;
|
||||
@at-padding-list-row-item-tag: 3px 9px;
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
@import '../../src/activity-stream/streamDetailModal/streamDetailModal.block.less';
|
||||
@import '../../src/activity-stream/activitystream.block.less';
|
||||
@import '../../src/bread-crumb/bread-crumb.block.less';
|
||||
@import '../../src/configuration/configuration.block.less';
|
||||
@import '../../src/configuration/settings.block.less';
|
||||
@import '../../src/credentials/ownerList.block.less';
|
||||
@import '../../src/home/dashboard/counts/dashboard-counts.block.less';
|
||||
@import '../../src/home/dashboard/graphs/dashboard-graphs.block.less';
|
||||
@ -128,7 +128,6 @@
|
||||
@import '../../src/workflow-results/workflow-status-bar/workflow-status-bar.block.less';
|
||||
@import '../../src/workflow-results/workflow-results.block.less';
|
||||
|
||||
|
||||
/**
|
||||
* App-wide style
|
||||
*
|
||||
|
||||
@ -54,14 +54,14 @@ export default function BuildAnchor($log, $filter) {
|
||||
case 'setting':
|
||||
if (activity.summary_fields.setting[0].category === 'jobs' ||
|
||||
activity.summary_fields.setting[0].category === 'ui') {
|
||||
url += `configuration/${activity.summary_fields.setting[0].category}`;
|
||||
url += `settings/${activity.summary_fields.setting[0].category}`;
|
||||
}
|
||||
else if (activity.summary_fields.setting[0].category === 'system' ||
|
||||
activity.summary_fields.setting[0].category === 'logging') {
|
||||
url += `configuration/system`;
|
||||
url += `settings/system`;
|
||||
}
|
||||
else {
|
||||
url += `configuration/auth`;
|
||||
url += `settings/auth`;
|
||||
}
|
||||
break;
|
||||
case 'notification_template':
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
<div class="Section-messageBar" ng-if="vm.show_auditor_bar">
|
||||
<i class="fa fa-warning"></i>
|
||||
<span translate>System auditors have read-only permissions in this section.</span>
|
||||
<button class="Section-messageBar--close" ng-click="vm.closeMessageBar()"><i class="fa fa-times-circle"></i></button>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="configuration-panel">
|
||||
<div ng-cloak id="htmlTemplate" class="Panel">
|
||||
<div class="Form-header">
|
||||
<div class="Form-title Form-title--uppercase" translate>CONFIGURE {{ BRAND_NAME }}</div>
|
||||
</div>
|
||||
<div class="row Form-tabRow">
|
||||
<div class="col-lg-12">
|
||||
<div class="Form-tabHolder"ng-class="{'Form-tabHolder--licenseSelected': vm.activeTab === 'license'}">
|
||||
<div id="auth_tab"
|
||||
class="Form-tab"
|
||||
ng-click="vm.activeTabCheck('auth')"
|
||||
ng-class="{'is-selected': vm.activeTab === 'auth' }"
|
||||
translate>
|
||||
Authentication
|
||||
</div>
|
||||
<div id="jobs_tab"
|
||||
class="Form-tab"
|
||||
ng-click="vm.activeTabCheck('jobs')"
|
||||
ng-class="{'is-selected': vm.activeTab === 'jobs' }"
|
||||
translate>
|
||||
Jobs
|
||||
</div>
|
||||
<div id="system_tab"
|
||||
class="Form-tab"
|
||||
ng-click="vm.activeTabCheck('system')"
|
||||
ng-class="{'is-selected': vm.activeTab === 'system' }"
|
||||
translate>
|
||||
System
|
||||
</div>
|
||||
<div id="ui_tab"
|
||||
class="Form-tab"
|
||||
ng-click="vm.activeTabCheck('ui')"
|
||||
ng-class="{'is-selected': vm.activeTab === 'ui' }"
|
||||
translate>
|
||||
User Interface
|
||||
</div>
|
||||
<div id="license_tab"
|
||||
class="Form-tab"
|
||||
ng-show="vm.product === 'Tower'"
|
||||
ng-click="vm.activeTabCheck('license')"
|
||||
ng-class="{'is-selected': vm.activeTab === 'license' }"
|
||||
translate>
|
||||
License
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ui-view="auth" ng-show="vm.activeTab === 'auth'"></div>
|
||||
<div ui-view="jobs" ng-show="vm.activeTab === 'jobs'"></div>
|
||||
<div ui-view="system" ng-show="vm.activeTab === 'system'"></div>
|
||||
<div ui-view="ui" ng-show="vm.activeTab === 'ui'"></div>
|
||||
<div ui-view="license" ng-show="vm.product === 'Tower' && vm.activeTab === 'license'"></div>
|
||||
<div id="FormModal-dialog"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,62 +0,0 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
import {templateUrl} from '../shared/template-url/template-url.factory';
|
||||
import ConfigurationController from './configuration.controller';
|
||||
import { N_ } from '../i18n';
|
||||
|
||||
// Import form controllers
|
||||
import ConfigurationAuthController from './auth-form/configuration-auth.controller';
|
||||
import ConfigurationJobsController from './jobs-form/configuration-jobs.controller';
|
||||
import ConfigurationSystemController from './system-form/configuration-system.controller';
|
||||
import ConfigurationUiController from './ui-form/configuration-ui.controller';
|
||||
|
||||
export default {
|
||||
name: 'configuration',
|
||||
route: '/configuration/:currentTab',
|
||||
params: {
|
||||
currentTab: {
|
||||
value: 'auth',
|
||||
dynamic: true,
|
||||
isOptional: true
|
||||
}
|
||||
|
||||
},
|
||||
ncyBreadcrumb: {
|
||||
label: N_("EDIT CONFIGURATION")
|
||||
},
|
||||
resolve: {
|
||||
configDataResolve: ['ConfigurationService', function(ConfigurationService){
|
||||
return ConfigurationService.getConfigurationOptions();
|
||||
}]
|
||||
},
|
||||
views: {
|
||||
'': {
|
||||
templateUrl: templateUrl('configuration/configuration'),
|
||||
controller: ConfigurationController,
|
||||
controllerAs: 'vm'
|
||||
},
|
||||
'auth@configuration': {
|
||||
templateUrl: templateUrl('configuration/auth-form/configuration-auth'),
|
||||
controller: ConfigurationAuthController,
|
||||
controllerAs: 'authVm'
|
||||
},
|
||||
'jobs@configuration': {
|
||||
templateUrl: templateUrl('configuration/jobs-form/configuration-jobs'),
|
||||
controller: ConfigurationJobsController,
|
||||
controllerAs: 'jobsVm'
|
||||
},
|
||||
'system@configuration': {
|
||||
templateUrl: templateUrl('configuration/system-form/configuration-system'),
|
||||
controller: ConfigurationSystemController,
|
||||
controllerAs: 'systemVm'
|
||||
},
|
||||
'ui@configuration': {
|
||||
templateUrl: templateUrl('configuration/ui-form/configuration-ui'),
|
||||
controller: ConfigurationUiController,
|
||||
controllerAs: 'uiVm'
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -7,84 +7,44 @@
|
||||
export default [
|
||||
'$scope',
|
||||
'$rootScope',
|
||||
'$state',
|
||||
'$stateParams',
|
||||
'$timeout',
|
||||
'$q',
|
||||
'configurationAzureForm',
|
||||
'configurationGithubForm',
|
||||
'configurationGithubOrgForm',
|
||||
'configurationGithubTeamForm',
|
||||
'configurationGoogleForm',
|
||||
'configurationLdapForm',
|
||||
'configurationLdap1Form',
|
||||
'configurationLdap2Form',
|
||||
'configurationLdap3Form',
|
||||
'configurationLdap4Form',
|
||||
'configurationLdap5Form',
|
||||
'configurationRadiusForm',
|
||||
'configurationTacacsForm',
|
||||
'configurationSamlForm',
|
||||
'ConfigurationService',
|
||||
'ConfigurationUtils',
|
||||
'SettingsUtils',
|
||||
'CreateSelect2',
|
||||
'GenerateForm',
|
||||
'i18n',
|
||||
'ParseTypeChange',
|
||||
function(
|
||||
function (
|
||||
$scope,
|
||||
$rootScope,
|
||||
$state,
|
||||
$stateParams,
|
||||
$timeout,
|
||||
$q,
|
||||
configurationAzureForm,
|
||||
configurationGithubForm,
|
||||
configurationGithubOrgForm,
|
||||
configurationGithubTeamForm,
|
||||
configurationGoogleForm,
|
||||
configurationLdapForm,
|
||||
configurationLdap1Form,
|
||||
configurationLdap2Form,
|
||||
configurationLdap3Form,
|
||||
configurationLdap4Form,
|
||||
configurationLdap5Form,
|
||||
configurationRadiusForm,
|
||||
configurationTacacsForm,
|
||||
configurationSamlForm,
|
||||
ConfigurationService,
|
||||
ConfigurationUtils,
|
||||
SettingsUtils,
|
||||
CreateSelect2,
|
||||
GenerateForm,
|
||||
i18n,
|
||||
ParseTypeChange
|
||||
) {
|
||||
var authVm = this;
|
||||
const authVm = this;
|
||||
const generator = GenerateForm;
|
||||
const formTracker = $scope.$parent.vm.formTracker; // track the current active form
|
||||
|
||||
var generator = GenerateForm;
|
||||
var formTracker = $scope.$parent.vm.formTracker;
|
||||
var dropdownValue = 'azure';
|
||||
var activeAuthForm = 'azure';
|
||||
var ldapDropdownValue = '';
|
||||
authVm.activeAuthForm = 'azure';
|
||||
authVm.activeTab = 'azure';
|
||||
authVm.ldapDropdownValue = '';
|
||||
authVm.githubDropdownValue = 'github';
|
||||
|
||||
let codeInputInitialized = false;
|
||||
|
||||
// Default active form
|
||||
if ($stateParams.currentTab === '' || $stateParams.currentTab === 'auth') {
|
||||
formTracker.setCurrentAuth(activeAuthForm);
|
||||
const formDefs = $scope.$parent.formDefs;
|
||||
|
||||
// Default active authform
|
||||
if ($stateParams.form === 'auth') {
|
||||
formTracker.setCurrentAuth(authVm.activeAuthForm);
|
||||
}
|
||||
|
||||
const getActiveAuthForm = () => {
|
||||
if (authVm.dropdownValue === 'ldap') {
|
||||
return `ldap${authVm.ldapDropdownValue}`;
|
||||
}
|
||||
return authVm.dropdownValue;
|
||||
};
|
||||
|
||||
|
||||
const activeForm = function(revertDropdown) {
|
||||
authVm.activeForm = function(tab) {
|
||||
if(!_.get($scope.$parent, [formTracker.currentFormName(), '$dirty'])) {
|
||||
authVm.activeAuthForm = getActiveAuthForm();
|
||||
authVm.activeTab = tab;
|
||||
authVm.activeAuthForm = getActiveAuthForm(tab);
|
||||
formTracker.setCurrentAuth(authVm.activeAuthForm);
|
||||
startCodeMirrors();
|
||||
} else {
|
||||
@ -97,7 +57,8 @@ export default [
|
||||
onClick: function() {
|
||||
$scope.$parent.vm.populateFromApi();
|
||||
$scope.$parent[formTracker.currentFormName()].$setPristine();
|
||||
authVm.activeAuthForm = getActiveAuthForm();
|
||||
authVm.activeTab = tab;
|
||||
authVm.activeAuthForm = getActiveAuthForm(tab);
|
||||
formTracker.setCurrentAuth(authVm.activeAuthForm);
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}
|
||||
@ -108,15 +69,13 @@ export default [
|
||||
.then(function() {
|
||||
$scope.$parent[formTracker.currentFormName()].$setPristine();
|
||||
$scope.$parent.vm.populateFromApi();
|
||||
authVm.activeAuthForm = getActiveAuthForm();
|
||||
authVm.activeTab = tab;
|
||||
authVm.activeAuthForm = getActiveAuthForm(tab);
|
||||
formTracker.setCurrentAuth(authVm.activeAuthForm);
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}).catch(() => {
|
||||
event.preventDefault();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
if (revertDropdown) {
|
||||
revertDropdown();
|
||||
}
|
||||
});
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
@ -128,31 +87,9 @@ export default [
|
||||
authVm.ldapSelected = (authVm.activeAuthForm.indexOf('ldap') !== -1);
|
||||
};
|
||||
|
||||
const changeAuthDropdown = (previousVal) => {
|
||||
activeForm(() => {
|
||||
authVm.dropdownValue = previousVal;
|
||||
CreateSelect2({
|
||||
element: '#configure-dropdown-nav',
|
||||
multiple: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const changeLdapDropdown = (previousVal) => {
|
||||
activeForm(() => {
|
||||
authVm.ldapDropdownValue = previousVal;
|
||||
CreateSelect2({
|
||||
element: '#configure-ldap-dropdown',
|
||||
multiple: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var dropdownOptions = [
|
||||
authVm.dropdownOptions = [
|
||||
{label: i18n._('Azure AD'), value: 'azure'},
|
||||
{label: i18n._('GitHub'), value: 'github'},
|
||||
{label: i18n._('GitHub Org'), value: 'github_org'},
|
||||
{label: i18n._('GitHub Team'), value: 'github_team'},
|
||||
{label: i18n._('Google OAuth2'), value: 'google_oauth'},
|
||||
{label: i18n._('LDAP'), value: 'ldap'},
|
||||
{label: i18n._('RADIUS'), value: 'radius'},
|
||||
@ -160,7 +97,7 @@ export default [
|
||||
{label: i18n._('TACACS+'), value: 'tacacs'}
|
||||
];
|
||||
|
||||
var ldapDropdownOptions = [
|
||||
authVm.ldapDropdownOptions = [
|
||||
{label: i18n._('Default'), value: ''},
|
||||
{label: i18n._('LDAP 1 (Optional)'), value: '1'},
|
||||
{label: i18n._('LDAP 2 (Optional)'), value: '2'},
|
||||
@ -169,6 +106,12 @@ export default [
|
||||
{label: i18n._('LDAP 5 (Optional)'), value: '5'},
|
||||
];
|
||||
|
||||
authVm.githubDropdownOptions = [
|
||||
{label: i18n._('GitHub (Default)'), value: 'github'},
|
||||
{label: i18n._('GitHub Org'), value: 'github_org'},
|
||||
{label: i18n._('GitHub Team'), value: 'github_team'},
|
||||
];
|
||||
|
||||
CreateSelect2({
|
||||
element: '#configure-dropdown-nav',
|
||||
multiple: false,
|
||||
@ -179,74 +122,79 @@ export default [
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
CreateSelect2({
|
||||
element: '#configure-github-dropdown',
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
var authForms = [
|
||||
{
|
||||
formDef: configurationAzureForm,
|
||||
formDef: formDefs.azure,
|
||||
id: 'auth-azure-form',
|
||||
name: 'azure'
|
||||
},
|
||||
{
|
||||
formDef: configurationGithubForm,
|
||||
formDef: formDefs.github,
|
||||
id: 'auth-github-form',
|
||||
name: 'github'
|
||||
},
|
||||
{
|
||||
formDef: configurationGithubOrgForm,
|
||||
formDef: formDefs.github_org,
|
||||
id: 'auth-github-org-form',
|
||||
name: 'github_org'
|
||||
},
|
||||
{
|
||||
formDef: configurationGithubTeamForm,
|
||||
formDef: formDefs.github_team,
|
||||
id: 'auth-github-team-form',
|
||||
name: 'github_team'
|
||||
},
|
||||
{
|
||||
formDef: configurationGoogleForm,
|
||||
formDef: formDefs.google_oauth,
|
||||
id: 'auth-google-form',
|
||||
name: 'google_oauth'
|
||||
},
|
||||
{
|
||||
formDef: configurationRadiusForm,
|
||||
formDef: formDefs.radius,
|
||||
id: 'auth-radius-form',
|
||||
name: 'radius'
|
||||
},
|
||||
{
|
||||
formDef: configurationTacacsForm,
|
||||
formDef: formDefs.tacacs,
|
||||
id: 'auth-tacacs-form',
|
||||
name: 'tacacs'
|
||||
},
|
||||
{
|
||||
formDef: configurationSamlForm,
|
||||
formDef: formDefs.saml,
|
||||
id: 'auth-saml-form',
|
||||
name: 'saml'
|
||||
},
|
||||
{
|
||||
formDef: configurationLdapForm,
|
||||
formDef: formDefs.ldap,
|
||||
id: 'auth-ldap-form',
|
||||
name: 'ldap'
|
||||
},
|
||||
{
|
||||
formDef: configurationLdap1Form,
|
||||
formDef: formDefs.ldap1,
|
||||
id: 'auth-ldap1-form',
|
||||
name: 'ldap1'
|
||||
},
|
||||
{
|
||||
formDef: configurationLdap2Form,
|
||||
formDef: formDefs.ldap2,
|
||||
id: 'auth-ldap2-form',
|
||||
name: 'ldap2'
|
||||
},
|
||||
{
|
||||
formDef: configurationLdap3Form,
|
||||
formDef: formDefs.ldap3,
|
||||
id: 'auth-ldap3-form',
|
||||
name: 'ldap3'
|
||||
},
|
||||
{
|
||||
formDef: configurationLdap4Form,
|
||||
formDef: formDefs.ldap4,
|
||||
id: 'auth-ldap4-form',
|
||||
name: 'ldap4'
|
||||
},
|
||||
{
|
||||
formDef: configurationLdap5Form,
|
||||
formDef: formDefs.ldap5,
|
||||
id: 'auth-ldap5-form',
|
||||
name: 'ldap5'
|
||||
},
|
||||
@ -256,11 +204,11 @@ export default [
|
||||
_.each(forms, function(form) {
|
||||
var keys = _.keys(form.fields);
|
||||
_.each(keys, function(key) {
|
||||
if($scope.$parent.configDataResolve[key].type === 'choice') {
|
||||
if($scope.configDataResolve[key].type === 'choice') {
|
||||
// Create options for dropdowns
|
||||
var optionsGroup = key + '_options';
|
||||
$scope.$parent[optionsGroup] = [];
|
||||
_.each($scope.$parent.configDataResolve[key].choices, function(choice){
|
||||
_.each($scope.configDataResolve[key].choices, function(choice){
|
||||
$scope.$parent[optionsGroup].push({
|
||||
name: choice[0],
|
||||
label: choice[1],
|
||||
@ -274,15 +222,28 @@ export default [
|
||||
form.buttons.save.disabled = $rootScope.user_is_system_auditor;
|
||||
});
|
||||
|
||||
function startCodeMirrors(key) {
|
||||
$scope.$parent.$parent.parseType = 'json';
|
||||
|
||||
_.each(authForms, function(form) {
|
||||
// Generate the forms
|
||||
generator.inject(form.formDef, {
|
||||
id: form.id,
|
||||
mode: 'edit',
|
||||
scope: $scope.$parent.$parent,
|
||||
related: true,
|
||||
noPanel: true
|
||||
});
|
||||
});
|
||||
|
||||
function startCodeMirrors (key) {
|
||||
var form = _.find(authForms, f => f.name === $scope.authVm.activeAuthForm);
|
||||
|
||||
if(!key){
|
||||
// Attach codemirror to fields that need it
|
||||
_.each(form.formDef.fields, function(field) {
|
||||
// Codemirror balks at empty values so give it one
|
||||
if($scope.$parent[field.name] === null && field.codeMirror) {
|
||||
$scope.$parent[field.name] = '{}';
|
||||
if($scope.$parent.$parent[field.name] === null && field.codeMirror) {
|
||||
$scope.$parent.$parent[field.name] = '{}';
|
||||
}
|
||||
if(field.codeMirror) {
|
||||
createIt(field.name);
|
||||
@ -295,11 +256,11 @@ export default [
|
||||
|
||||
function createIt(name){
|
||||
ParseTypeChange({
|
||||
scope: $scope.$parent,
|
||||
scope: $scope.$parent.$parent,
|
||||
variable: name,
|
||||
parse_variable: 'parseType',
|
||||
field_id: form.formDef.name + '_' + name,
|
||||
readOnly: $scope.$parent.configDataResolve[name] && $scope.$parent.configDataResolve[name].disabled ? true : false
|
||||
readOnly: $scope.configDataResolve[name] && $scope.configDataResolve[name].disabled ? true : false
|
||||
});
|
||||
$scope.parseTypeChange('parseType', name);
|
||||
}
|
||||
@ -307,35 +268,22 @@ export default [
|
||||
|
||||
function addFieldInfo(form, key) {
|
||||
_.extend(form.fields[key], {
|
||||
awPopOver: ($scope.$parent.configDataResolve[key].defined_in_file) ?
|
||||
null: $scope.$parent.configDataResolve[key].help_text,
|
||||
label: $scope.$parent.configDataResolve[key].label,
|
||||
awPopOver: ($scope.configDataResolve[key].defined_in_file) ?
|
||||
null: $scope.configDataResolve[key].help_text,
|
||||
label: $scope.configDataResolve[key].label,
|
||||
name: key,
|
||||
toggleSource: key,
|
||||
dataPlacement: 'top',
|
||||
placeholder: ConfigurationUtils.formatPlaceholder($scope.$parent.configDataResolve[key].placeholder, key) || null,
|
||||
dataTitle: $scope.$parent.configDataResolve[key].label,
|
||||
required: $scope.$parent.configDataResolve[key].required,
|
||||
placeholder: SettingsUtils.formatPlaceholder($scope.configDataResolve[key].placeholder, key) || null,
|
||||
dataTitle: $scope.configDataResolve[key].label,
|
||||
required: $scope.configDataResolve[key].required,
|
||||
ngDisabled: $rootScope.user_is_system_auditor,
|
||||
disabled: $scope.$parent.configDataResolve[key].disabled || null,
|
||||
readonly: $scope.$parent.configDataResolve[key].readonly || null,
|
||||
definedInFile: $scope.$parent.configDataResolve[key].defined_in_file || null
|
||||
disabled: $scope.configDataResolve[key].disabled || null,
|
||||
readonly: $scope.configDataResolve[key].readonly || null,
|
||||
definedInFile: $scope.configDataResolve[key].defined_in_file || null
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$parent.parseType = 'json';
|
||||
|
||||
_.each(authForms, function(form) {
|
||||
// Generate the forms
|
||||
generator.inject(form.formDef, {
|
||||
id: form.id,
|
||||
mode: 'edit',
|
||||
scope: $scope.$parent,
|
||||
related: true,
|
||||
noPanel: true
|
||||
});
|
||||
});
|
||||
|
||||
// Flag to avoid re-rendering and breaking Select2 dropdowns on tab switching
|
||||
var dropdownRendered = false;
|
||||
|
||||
@ -409,7 +357,7 @@ export default [
|
||||
});
|
||||
|
||||
$scope.$on('populated', function() {
|
||||
let tab = $stateParams.currentTab;
|
||||
let tab = $stateParams.form;
|
||||
|
||||
if (tab === 'auth') {
|
||||
startCodeMirrors();
|
||||
@ -427,23 +375,24 @@ export default [
|
||||
});
|
||||
|
||||
$scope.$on('codeMirror_populated', function() {
|
||||
let tab = $stateParams.currentTab;
|
||||
let tab = $stateParams.form;
|
||||
if (tab === 'auth') {
|
||||
startCodeMirrors();
|
||||
codeInputInitialized = true;
|
||||
}
|
||||
});
|
||||
|
||||
function getActiveAuthForm (tab) {
|
||||
if (tab === 'ldap') {
|
||||
return `ldap${authVm.ldapDropdownValue}`;
|
||||
} else if (tab === 'github') {
|
||||
return authVm.githubDropdownValue;
|
||||
}
|
||||
return tab;
|
||||
}
|
||||
|
||||
angular.extend(authVm, {
|
||||
changeAuthDropdown: changeAuthDropdown,
|
||||
changeLdapDropdown: changeLdapDropdown,
|
||||
activeAuthForm: activeAuthForm,
|
||||
authForms: authForms,
|
||||
dropdownOptions: dropdownOptions,
|
||||
dropdownValue: dropdownValue,
|
||||
ldapDropdownValue: ldapDropdownValue,
|
||||
ldapDropdownOptions: ldapDropdownOptions,
|
||||
});
|
||||
}
|
||||
];
|
||||
@ -1,19 +1,20 @@
|
||||
<div class="tab-pane Configuration-container" id="configuration_edit">
|
||||
|
||||
<div class="Form-nav--dropdownContainer">
|
||||
<div class="Form-nav--dropdownLabel" translate>Sub Category</div>
|
||||
<div class="Form-nav--dropdown">
|
||||
<select
|
||||
id="configure-dropdown-nav"
|
||||
class="form-control"
|
||||
ng-model="authVm.dropdownValue"
|
||||
ng-options="opt.value as opt.label for opt in authVm.dropdownOptions"
|
||||
ng-change="authVm.changeAuthDropdown('{{authVm.dropdownValue}}')">
|
||||
</select>
|
||||
<div class="row Form-tabRow">
|
||||
<div class="col-lg-12">
|
||||
<div class="Form-tabHolder">
|
||||
<div ng-repeat="opt in authVm.dropdownOptions"
|
||||
class="Form-tab"
|
||||
ng-click="authVm.activeForm(opt.value)"
|
||||
ng-class="{'is-selected': authVm.activeTab === opt.value }"
|
||||
translate>
|
||||
{{opt.label}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="Form-nav--ldapDropdownContainer" ng-show="authVm.dropdownValue === 'ldap'">
|
||||
<div class="Form-nav--dropdownContainer" ng-show="authVm.activeTab === 'ldap'">
|
||||
<div class="Form-nav--dropdownLabel" translate>LDAP Server</div>
|
||||
<div class="Form-nav--dropdown">
|
||||
<select
|
||||
@ -21,12 +22,23 @@
|
||||
class="form-control"
|
||||
ng-model="authVm.ldapDropdownValue"
|
||||
ng-options="opt.value as opt.label for opt in authVm.ldapDropdownOptions"
|
||||
ng-change="authVm.changeLdapDropdown('{{authVm.ldapDropdownValue}}')">
|
||||
ng-change="authVm.activeForm('ldap')">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr ng-show="authVm.dropdownValue === 'ldap'"/>
|
||||
<div class="Form-nav--dropdownContainer" ng-show="authVm.activeTab === 'github'">
|
||||
<div class="Form-nav--dropdownLabel" translate>GitHub Category</div>
|
||||
<div class="Form-nav--dropdown">
|
||||
<select
|
||||
id="configure-github-dropdown"
|
||||
class="form-control"
|
||||
ng-model="authVm.githubDropdownValue"
|
||||
ng-options="opt.value as opt.label for opt in authVm.githubDropdownOptions"
|
||||
ng-change="authVm.activeForm('github')">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
@ -7,12 +7,8 @@
|
||||
export default [
|
||||
'$scope',
|
||||
'$rootScope',
|
||||
'$state',
|
||||
'$stateParams',
|
||||
'$timeout',
|
||||
'ConfigurationJobsForm',
|
||||
'ConfigurationService',
|
||||
'ConfigurationUtils',
|
||||
'CreateSelect2',
|
||||
'GenerateForm',
|
||||
'ParseTypeChange',
|
||||
@ -20,26 +16,27 @@ export default [
|
||||
function(
|
||||
$scope,
|
||||
$rootScope,
|
||||
$state,
|
||||
$stateParams,
|
||||
$timeout,
|
||||
ConfigurationJobsForm,
|
||||
ConfigurationService,
|
||||
ConfigurationUtils,
|
||||
CreateSelect2,
|
||||
GenerateForm,
|
||||
ParseTypeChange,
|
||||
i18n
|
||||
) {
|
||||
var generator = GenerateForm;
|
||||
const generator = GenerateForm;
|
||||
var form = ConfigurationJobsForm;
|
||||
const formTracker = $scope.$parent.vm.formTracker;
|
||||
|
||||
if ($stateParams.form === 'jobs') {
|
||||
formTracker.setCurrentAuth('jobs');
|
||||
}
|
||||
|
||||
let tab;
|
||||
let codeInputInitialized = false;
|
||||
|
||||
$scope.$parent.AD_HOC_COMMANDS_options = [];
|
||||
_.each($scope.$parent.configDataResolve.AD_HOC_COMMANDS.default, function(command) {
|
||||
$scope.$parent.AD_HOC_COMMANDS_options.push({
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS_options = [];
|
||||
_.each($scope.$parent.configDataResolve.AD_HOC_COMMANDS.default, function (command) {
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS_options.push({
|
||||
name: command,
|
||||
label: command,
|
||||
value: command
|
||||
@ -74,18 +71,20 @@ export default [
|
||||
generator.inject(form, {
|
||||
id: 'configure-jobs-form',
|
||||
mode: 'edit',
|
||||
scope: $scope.$parent,
|
||||
scope: $scope.$parent.$parent,
|
||||
related: false,
|
||||
noPanel: true
|
||||
});
|
||||
|
||||
$scope.$parent.$parent.parseType = 'json';
|
||||
|
||||
function initializeCodeInput () {
|
||||
let name = 'AWX_TASK_ENV';
|
||||
|
||||
ParseTypeChange({
|
||||
scope: $scope.$parent,
|
||||
scope: $scope.$parent.$parent,
|
||||
variable: name,
|
||||
parseType: 'application/json',
|
||||
parse_variable: 'parseType',
|
||||
field_id: `configuration_jobs_template_${name}`
|
||||
});
|
||||
|
||||
@ -93,15 +92,14 @@ export default [
|
||||
}
|
||||
|
||||
function loadAdHocCommands () {
|
||||
$scope.$parent.AD_HOC_COMMANDS_values = $scope.$parent.AD_HOC_COMMANDS.map(value => value);
|
||||
$scope.$parent.AD_HOC_COMMANDS = $scope.$parent.AD_HOC_COMMANDS.map(value => ({
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS_values = $scope.$parent.$parent.AD_HOC_COMMANDS.map(value => value);
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS = $scope.$parent.$parent.AD_HOC_COMMANDS.map(value => ({
|
||||
value,
|
||||
name: value,
|
||||
label: value
|
||||
}));
|
||||
|
||||
$scope.$parent.AD_HOC_COMMANDS_options = $scope.$parent.AD_HOC_COMMANDS.map(tag => tag);
|
||||
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS_options = $scope.$parent.$parent.AD_HOC_COMMANDS.map(tag => tag);
|
||||
CreateSelect2({
|
||||
element: '#configuration_jobs_template_AD_HOC_COMMANDS',
|
||||
multiple: true,
|
||||
@ -112,7 +110,7 @@ export default [
|
||||
}
|
||||
|
||||
function revertAdHocCommands () {
|
||||
$scope.$parent.AD_HOC_COMMANDS = $scope.$parent.configDataResolve.AD_HOC_COMMANDS.default.map(value => ({
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS = $scope.$parent.configDataResolve.AD_HOC_COMMANDS.default.map(value => ({
|
||||
value,
|
||||
name: value,
|
||||
label: value
|
||||
@ -125,60 +123,36 @@ export default [
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$parent.AD_HOC_COMMANDS_options = $scope.$parent.AD_HOC_COMMANDS.map(tag => tag);
|
||||
$scope.$parent.AD_HOC_COMMANDS_values = $scope.$parent.AD_HOC_COMMANDS.map(tag => tag.value);
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS_options = $scope.$parent.$parent.AD_HOC_COMMANDS.map(tag => tag);
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS_values = $scope.$parent.$parent.AD_HOC_COMMANDS.map(tag => tag.value);
|
||||
CreateSelect2({
|
||||
element: '#configuration_jobs_template_AD_HOC_COMMANDS',
|
||||
multiple: true,
|
||||
addNew: true,
|
||||
placeholder: i18n._('Select commands'),
|
||||
options: $scope.$parent.AD_HOC_COMMANDS_options
|
||||
options: $scope.$parent.$parent.AD_HOC_COMMANDS_options
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Fix for bug where adding selected opts causes form to be $dirty and triggering modal
|
||||
// TODO Find better solution for this bug
|
||||
$timeout(function(){
|
||||
$scope.$parent.configuration_jobs_template_form.$setPristine();
|
||||
}, 1000);
|
||||
|
||||
|
||||
// Managing the state of select2's tags since the behavior is unpredictable otherwise.
|
||||
let commandsElement = $('#configuration_jobs_template_AD_HOC_COMMANDS');
|
||||
|
||||
commandsElement.on('select2:select', event => {
|
||||
let command = event.params.data.text;
|
||||
let commands = $scope.$parent.AD_HOC_COMMANDS_values;
|
||||
let commands = $scope.$parent.$parent.AD_HOC_COMMANDS_values;
|
||||
|
||||
commands.push(command);
|
||||
});
|
||||
|
||||
commandsElement.on('select2:unselect', event => {
|
||||
let command = event.params.data.text;
|
||||
let commands = $scope.$parent.AD_HOC_COMMANDS_values;
|
||||
let commands = $scope.$parent.$parent.AD_HOC_COMMANDS_values;
|
||||
|
||||
$scope.$parent.AD_HOC_COMMANDS_values = commands.filter(value => value !== command);
|
||||
$scope.$parent.$parent.AD_HOC_COMMANDS_values = commands.filter(value => value !== command);
|
||||
});
|
||||
|
||||
$scope.$on('AD_HOC_COMMANDS_reverted', () => revertAdHocCommands());
|
||||
|
||||
/*
|
||||
* Controllers for each tab are initialized when configuration is opened. A listener
|
||||
* on the URL itself is necessary to determine which tab is active. If a non-active
|
||||
* tab initializes a codemirror, it doesn't display properly until the user navigates
|
||||
* to the tab and it's been clicked.
|
||||
*/
|
||||
$scope.$on('$locationChangeStart', (event, url) => {
|
||||
let parts = url.split('/');
|
||||
tab = parts[parts.length - 1];
|
||||
|
||||
if (tab === 'jobs' && !codeInputInitialized) {
|
||||
initializeCodeInput();
|
||||
codeInputInitialized = true;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Necessary to listen for revert clicks and relaunch the codemirror instance.
|
||||
*/
|
||||
@ -194,8 +168,7 @@ export default [
|
||||
* direct load of this tab or if the user comes from a different tab.
|
||||
*/
|
||||
$scope.$on('populated', () => {
|
||||
tab = $stateParams.currentTab;
|
||||
|
||||
tab = $stateParams.form;
|
||||
if (tab === 'jobs') {
|
||||
initializeCodeInput();
|
||||
codeInputInitialized = true;
|
||||
@ -1,6 +1,4 @@
|
||||
<div class="tab-pane Configuration-container" id="configuration_edit">
|
||||
<!-- <div ui-view="form"></div>
|
||||
<div ng-cloak id="htmlTemplate"> -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div id="configure-jobs-form"></div>
|
||||
@ -1,14 +1,9 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
import defaultStrings from '~assets/default.strings.json';
|
||||
|
||||
export default [
|
||||
'$scope', '$rootScope', '$state', '$stateParams', '$timeout', '$q', 'Alert',
|
||||
'ConfigurationService', 'ConfigurationUtils', 'CreateDialog', 'CreateSelect2', 'i18n', 'ParseTypeChange', 'ProcessErrors', 'Store',
|
||||
'Wait', 'configDataResolve', 'ToJSON', 'ConfigService', 'ngToast',
|
||||
'$scope', '$rootScope', '$state', '$stateParams', '$q',
|
||||
'SettingsService', 'SettingsUtils', 'CreateDialog', 'i18n', 'ProcessErrors', 'Store',
|
||||
'Wait', 'configDataResolve', 'ToJSON', 'ConfigService',
|
||||
//Form definitions
|
||||
'configurationAzureForm',
|
||||
'configurationGithubForm',
|
||||
@ -29,10 +24,11 @@ export default [
|
||||
'systemMiscForm',
|
||||
'ConfigurationJobsForm',
|
||||
'ConfigurationUiForm',
|
||||
'ngToast',
|
||||
function(
|
||||
$scope, $rootScope, $state, $stateParams, $timeout, $q, Alert,
|
||||
ConfigurationService, ConfigurationUtils, CreateDialog, CreateSelect2, i18n, ParseTypeChange, ProcessErrors, Store,
|
||||
Wait, configDataResolve, ToJSON, ConfigService, ngToast,
|
||||
$scope, $rootScope, $state, $stateParams, $q,
|
||||
SettingsService, SettingsUtils, CreateDialog, i18n, ProcessErrors, Store,
|
||||
Wait, configDataResolve, ToJSON, ConfigService,
|
||||
//Form definitions
|
||||
configurationAzureForm,
|
||||
configurationGithubForm,
|
||||
@ -52,13 +48,15 @@ export default [
|
||||
systemLoggingForm,
|
||||
systemMiscForm,
|
||||
ConfigurationJobsForm,
|
||||
ConfigurationUiForm
|
||||
ConfigurationUiForm,
|
||||
ngToast
|
||||
) {
|
||||
var vm = this;
|
||||
const vm = this;
|
||||
|
||||
vm.product = defaultStrings.BRAND_NAME;
|
||||
vm.activeTab = $stateParams.form;
|
||||
|
||||
var formDefs = {
|
||||
const formDefs = {
|
||||
'azure': configurationAzureForm,
|
||||
'github': configurationGithubForm,
|
||||
'github_org': configurationGithubOrgForm,
|
||||
@ -80,8 +78,19 @@ export default [
|
||||
'ui': ConfigurationUiForm
|
||||
};
|
||||
|
||||
$scope.configDataResolve = configDataResolve;
|
||||
$scope.formDefs = formDefs;
|
||||
|
||||
// check if it's auditor, show messageBar
|
||||
$scope.show_auditor_bar = false;
|
||||
if($rootScope.user_is_system_auditor && Store('show_auditor_bar') !== false) {
|
||||
$scope.show_auditor_bar = true;
|
||||
} else {
|
||||
$scope.show_auditor_bar = false;
|
||||
}
|
||||
|
||||
var populateFromApi = function() {
|
||||
ConfigurationService.getCurrentValues()
|
||||
SettingsService.getCurrentValues()
|
||||
.then(function(data) {
|
||||
var currentKeys = _.keys(data);
|
||||
$scope.requiredLogValues = {};
|
||||
@ -113,12 +122,12 @@ export default [
|
||||
} else if (isLdapUserSearch || isLdapGroupSearch) {
|
||||
$scope[key] = JSON.stringify(data[key]);
|
||||
} else {
|
||||
$scope[key] = ConfigurationUtils.arrayToList(data[key], key);
|
||||
$scope[key] = SettingsUtils.arrayToList(data[key], key);
|
||||
}
|
||||
|
||||
} else {
|
||||
//handle nested objects
|
||||
if(ConfigurationUtils.isEmpty(data[key])) {
|
||||
if(SettingsUtils.isEmpty(data[key])) {
|
||||
$scope[key] = '{}';
|
||||
} else {
|
||||
$scope[key] = JSON.stringify(data[key]);
|
||||
@ -172,31 +181,6 @@ export default [
|
||||
},
|
||||
};
|
||||
|
||||
// Default to auth form and tab
|
||||
if ($stateParams.currentTab === '') {
|
||||
$state.go('configuration', {
|
||||
currentTab: 'auth'
|
||||
}, {
|
||||
location: true,
|
||||
inherit: false,
|
||||
notify: false,
|
||||
reload: false
|
||||
});
|
||||
}
|
||||
|
||||
var currentForm = '';
|
||||
var currentTab = function() {
|
||||
if ($stateParams.currentTab === '' || $stateParams.currentTab === 'auth') {
|
||||
return 'auth';
|
||||
} else if ($stateParams.currentTab !== '' && $stateParams.currentTab !== 'auth') {
|
||||
formTracker.setCurrent($stateParams.currentTab);
|
||||
return $stateParams.currentTab;
|
||||
}
|
||||
};
|
||||
var activeTab = currentTab();
|
||||
|
||||
$scope.configDataResolve = configDataResolve;
|
||||
|
||||
var triggerModal = function(msg, title, buttons) {
|
||||
if ($scope.removeModalReady) {
|
||||
$scope.removeModalReady();
|
||||
@ -221,127 +205,6 @@ export default [
|
||||
});
|
||||
};
|
||||
|
||||
function activeTabCheck(setForm) {
|
||||
if(!$scope[formTracker.currentFormName()] || !$scope[formTracker.currentFormName()].$dirty) {
|
||||
active(setForm);
|
||||
} else {
|
||||
var msg = i18n._('You have unsaved changes. Would you like to proceed <strong>without</strong> saving?');
|
||||
var title = i18n._('Warning: Unsaved Changes');
|
||||
var buttons = [{
|
||||
label: i18n._("Discard changes"),
|
||||
"class": "btn Form-cancelButton",
|
||||
"id": "formmodal-cancel-button",
|
||||
onClick: function() {
|
||||
clearApiErrors();
|
||||
populateFromApi();
|
||||
$scope[formTracker.currentFormName()].$setPristine();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
active(setForm);
|
||||
}
|
||||
}, {
|
||||
label: i18n._("Save changes"),
|
||||
onClick: function() {
|
||||
vm.formSave().then(() => {
|
||||
$scope[formTracker.currentFormName()].$setPristine();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
active(setForm);
|
||||
}).catch(()=> {
|
||||
event.preventDefault();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
});
|
||||
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
"id": "formmodal-save-button"
|
||||
}];
|
||||
triggerModal(msg, title, buttons);
|
||||
}
|
||||
}
|
||||
|
||||
function active(setForm) {
|
||||
// Authentication and System's sub-module dropdowns handled first:
|
||||
if (setForm === 'auth') {
|
||||
// Default to 'azure' on first load
|
||||
if (formTracker.currentAuth === '') {
|
||||
formTracker.setCurrentAuth('azure');
|
||||
} else {
|
||||
// If returning to auth tab reset current form to previously viewed
|
||||
formTracker.setCurrentAuth(formTracker.currentAuth);
|
||||
}
|
||||
} else if (setForm === 'system') {
|
||||
if (formTracker.currentSystem === '') {
|
||||
formTracker.setCurrentSystem('misc');
|
||||
} else {
|
||||
// If returning to system tab reset current form to previously viewed
|
||||
formTracker.setCurrentSystem(formTracker.currentSystem);
|
||||
}
|
||||
}
|
||||
|
||||
vm.activeTab = setForm;
|
||||
|
||||
if (setForm !== 'license') {
|
||||
if (setForm === 'auth') {
|
||||
formTracker.setCurrentAuth(formTracker.currentAuth);
|
||||
} else if (setForm === 'system') {
|
||||
formTracker.setCurrentSystem(formTracker.currentSystem);
|
||||
} else {
|
||||
formTracker.setCurrent(setForm);
|
||||
}
|
||||
|
||||
$state.go('configuration', {
|
||||
currentTab: setForm
|
||||
}, {
|
||||
location: true,
|
||||
inherit: false,
|
||||
notify: false,
|
||||
reload: false
|
||||
});
|
||||
} else {
|
||||
$state.go('configuration.license', {
|
||||
currentTab: setForm
|
||||
}, {
|
||||
location: true,
|
||||
inherit: false,
|
||||
notify: false,
|
||||
reload: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var formCancel = function() {
|
||||
if ($scope[formTracker.currentFormName()].$dirty === true) {
|
||||
var msg = i18n._('You have unsaved changes. Would you like to proceed <strong>without</strong> saving?');
|
||||
var title = i18n._('Warning: Unsaved Changes');
|
||||
var buttons = [{
|
||||
label: i18n._("Discard changes"),
|
||||
"class": "btn Form-cancelButton",
|
||||
"id": "formmodal-cancel-button",
|
||||
onClick: function() {
|
||||
clearApiErrors();
|
||||
populateFromApi();
|
||||
$scope[formTracker.currentFormName()].$setPristine();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}
|
||||
}, {
|
||||
label: i18n._("Save changes"),
|
||||
onClick: function() {
|
||||
vm.formSave().then(() => {
|
||||
$scope[formTracker.currentFormName()].$setPristine();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}).catch(()=> {
|
||||
event.preventDefault();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
});
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
"id": "formmodal-save-button"
|
||||
}];
|
||||
triggerModal(msg, title, buttons);
|
||||
} else {
|
||||
$state.go('setup');
|
||||
}
|
||||
};
|
||||
|
||||
function loginUpdate() {
|
||||
// Updates the logo and app config so that logos and info are properly shown
|
||||
// on logout after modifying.
|
||||
@ -370,7 +233,7 @@ export default [
|
||||
Wait('start');
|
||||
var payload = {};
|
||||
payload[key] = $scope.configDataResolve[key].default;
|
||||
ConfigurationService.patchConfiguration(payload)
|
||||
SettingsService.patchConfiguration(payload)
|
||||
.then(function() {
|
||||
$scope[key] = $scope.configDataResolve[key].default;
|
||||
|
||||
@ -446,7 +309,6 @@ export default [
|
||||
var getFormPayload = function() {
|
||||
var keys = _.keys(formDefs[formTracker.getCurrent()].fields);
|
||||
var payload = {};
|
||||
|
||||
_.each(keys, function(key) {
|
||||
if($scope.configDataResolve[key].type === 'choice' || multiselectDropdowns.indexOf(key) !== -1) {
|
||||
//Parse dropdowns and dropdowns labeled as lists
|
||||
@ -471,10 +333,10 @@ export default [
|
||||
}
|
||||
} else if($scope.configDataResolve[key].type === 'list' && $scope[key] !== null) {
|
||||
// Parse lists
|
||||
payload[key] = ConfigurationUtils.listToArray($scope[key], key);
|
||||
payload[key] = SettingsUtils.listToArray($scope[key], key);
|
||||
}
|
||||
else if($scope.configDataResolve[key].type === 'nested object') {
|
||||
if($scope[key] === '') {
|
||||
if(!$scope[key]) {
|
||||
payload[key] = {};
|
||||
} else {
|
||||
// payload[key] = JSON.parse($scope[key]);
|
||||
@ -494,11 +356,11 @@ export default [
|
||||
return payload;
|
||||
};
|
||||
|
||||
var formSave = function() {
|
||||
vm.formSave = function() {
|
||||
var saveDeferred = $q.defer();
|
||||
clearApiErrors();
|
||||
Wait('start');
|
||||
ConfigurationService.patchConfiguration(getFormPayload())
|
||||
SettingsService.patchConfiguration(getFormPayload())
|
||||
.then(function(data) {
|
||||
loginUpdate();
|
||||
|
||||
@ -532,7 +394,94 @@ export default [
|
||||
return saveDeferred.promise;
|
||||
};
|
||||
|
||||
vm.formCancel = function() {
|
||||
if ($scope[formTracker.currentFormName()].$dirty === true) {
|
||||
var msg = i18n._('You have unsaved changes. Would you like to proceed <strong>without</strong> saving?');
|
||||
var title = i18n._('Warning: Unsaved Changes');
|
||||
var buttons = [{
|
||||
label: i18n._("Discard changes"),
|
||||
"class": "btn Form-cancelButton",
|
||||
"id": "formmodal-cancel-button",
|
||||
onClick: function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
$state.go('settings');
|
||||
}
|
||||
}, {
|
||||
label: i18n._("Save changes"),
|
||||
onClick: function() {
|
||||
vm.formSave()
|
||||
.then(function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
$state.go('settings');
|
||||
});
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
"id": "formmodal-save-button"
|
||||
}];
|
||||
triggerModal(msg, title, buttons);
|
||||
} else {
|
||||
$state.go('settings');
|
||||
}
|
||||
};
|
||||
|
||||
vm.resetAllConfirm = function() {
|
||||
var buttons = [{
|
||||
label: i18n._("Cancel"),
|
||||
"class": "btn btn-default",
|
||||
"id": "formmodal-cancel-button",
|
||||
onClick: function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}
|
||||
}, {
|
||||
label: i18n._("Confirm Reset"),
|
||||
onClick: function() {
|
||||
resetAll();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
"id": "formmodal-reset-button"
|
||||
}];
|
||||
var msg = i18n._('This will reset all configuration values to their factory defaults. Are you sure you want to proceed?');
|
||||
var title = i18n._('Confirm factory reset');
|
||||
triggerModal(msg, title, buttons);
|
||||
};
|
||||
|
||||
vm.closeMessageBar = function() {
|
||||
var msg = 'Are you sure you want to hide the notification bar?';
|
||||
var title = 'Warning: Closing notification bar';
|
||||
var buttons = [{
|
||||
label: "Cancel",
|
||||
"class": "btn Form-cancelButton",
|
||||
"id": "formmodal-cancel-button",
|
||||
onClick: function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}
|
||||
}, {
|
||||
label: "OK",
|
||||
onClick: function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
updateMessageBarPrefs();
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
"id": "formmodal-save-button"
|
||||
}];
|
||||
triggerModal(msg, title, buttons);
|
||||
};
|
||||
|
||||
vm.getCurrentFormTitle = function() {
|
||||
switch($stateParams.form) {
|
||||
case 'auth':
|
||||
return 'AUTHENTICATION';
|
||||
case 'jobs':
|
||||
return 'JOBS';
|
||||
case 'system':
|
||||
return 'SYSTEM';
|
||||
case 'ui':
|
||||
return 'USER INTERFACE';
|
||||
case 'license':
|
||||
return 'LICENSE';
|
||||
}
|
||||
};
|
||||
|
||||
$scope.toggleForm = function(key) {
|
||||
if($rootScope.user_is_system_auditor) {
|
||||
@ -545,7 +494,7 @@ export default [
|
||||
Wait('start');
|
||||
var payload = {};
|
||||
payload[key] = $scope[key];
|
||||
ConfigurationService.patchConfiguration(payload)
|
||||
SettingsService.patchConfiguration(payload)
|
||||
.then(function() {
|
||||
//TODO consider updating form values with returned data here
|
||||
})
|
||||
@ -564,7 +513,7 @@ export default [
|
||||
});
|
||||
};
|
||||
|
||||
var resetAll = function() {
|
||||
function resetAll () {
|
||||
var keys = _.keys(formDefs[formTracker.getCurrent()].fields);
|
||||
var payload = {};
|
||||
clearApiErrors();
|
||||
@ -573,7 +522,7 @@ export default [
|
||||
});
|
||||
|
||||
Wait('start');
|
||||
ConfigurationService.patchConfiguration(payload)
|
||||
SettingsService.patchConfiguration(payload)
|
||||
.then(function() {
|
||||
populateFromApi();
|
||||
$scope[formTracker.currentFormName()].$setPristine();
|
||||
@ -610,76 +559,17 @@ export default [
|
||||
.finally(function() {
|
||||
Wait('stop');
|
||||
});
|
||||
};
|
||||
|
||||
var resetAllConfirm = function() {
|
||||
var buttons = [{
|
||||
label: i18n._("Cancel"),
|
||||
"class": "btn btn-default",
|
||||
"id": "formmodal-cancel-button",
|
||||
onClick: function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}
|
||||
}, {
|
||||
label: i18n._("Confirm Reset"),
|
||||
onClick: function() {
|
||||
resetAll();
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
"id": "formmodal-reset-button"
|
||||
}];
|
||||
var msg = i18n._('This will reset all configuration values to their factory defaults. Are you sure you want to proceed?');
|
||||
var title = i18n._('Confirm factory reset');
|
||||
triggerModal(msg, title, buttons);
|
||||
};
|
||||
|
||||
var show_auditor_bar;
|
||||
if($rootScope.user_is_system_auditor && Store('show_auditor_bar') !== false) {
|
||||
show_auditor_bar = true;
|
||||
} else {
|
||||
show_auditor_bar = false;
|
||||
}
|
||||
|
||||
var updateMessageBarPrefs = function() {
|
||||
vm.show_auditor_bar = false;
|
||||
Store('show_auditor_bar', vm.show_auditor_bar);
|
||||
};
|
||||
|
||||
var closeMessageBar = function() {
|
||||
var msg = 'Are you sure you want to hide the notification bar?';
|
||||
var title = 'Warning: Closing notification bar';
|
||||
var buttons = [{
|
||||
label: "Cancel",
|
||||
"class": "btn Form-cancelButton",
|
||||
"id": "formmodal-cancel-button",
|
||||
onClick: function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}
|
||||
}, {
|
||||
label: "OK",
|
||||
onClick: function() {
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
updateMessageBarPrefs();
|
||||
},
|
||||
"class": "btn btn-primary",
|
||||
"id": "formmodal-save-button"
|
||||
}];
|
||||
triggerModal(msg, title, buttons);
|
||||
};
|
||||
function updateMessageBarPrefs () {
|
||||
$scope.show_auditor_bar = false;
|
||||
Store('show_auditor_bar', $scope.show_auditor_bar);
|
||||
}
|
||||
|
||||
angular.extend(vm, {
|
||||
activeTab: activeTab,
|
||||
activeTabCheck: activeTabCheck,
|
||||
closeMessageBar: closeMessageBar,
|
||||
currentForm: currentForm,
|
||||
formCancel: formCancel,
|
||||
formTracker: formTracker,
|
||||
formSave: formSave,
|
||||
getFormPayload: getFormPayload,
|
||||
populateFromApi: populateFromApi,
|
||||
resetAllConfirm: resetAllConfirm,
|
||||
show_auditor_bar: show_auditor_bar,
|
||||
triggerModal: triggerModal,
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
<div class="Section-messageBar" ng-if="show_auditor_bar">
|
||||
<i class="fa fa-warning"></i>
|
||||
<span translate>System auditors have read-only permissions in this section.</span>
|
||||
<button class="Section-messageBar--close" ng-click="vm.closeMessageBar()"><i class="fa fa-times-circle"></i></button>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="configuration-panel">
|
||||
<div ng-cloak id="htmlTemplate" class="Panel">
|
||||
<div class="Form-header">
|
||||
<div class="Form-title Form-title--uppercase" translate>{{ vm.getCurrentFormTitle() }}</div>
|
||||
</div>
|
||||
<div ui-view="auth" ng-if="vm.activeTab === 'auth'"></div>
|
||||
<div ui-view="jobs" ng-if="vm.activeTab === 'jobs'"></div>
|
||||
<div ui-view="system" ng-if="vm.activeTab === 'system'"></div>
|
||||
<div ui-view="ui" ng-if="vm.activeTab === 'ui'"></div>
|
||||
<div ui-view="license" ng-show="vm.product === 'Tower' && vm.activeTab === 'license'"></div>
|
||||
<div id="FormModal-dialog"></div>
|
||||
</div>
|
||||
</div>
|
||||
56
awx/ui/client/src/configuration/forms/settings-form.route.js
Normal file
56
awx/ui/client/src/configuration/forms/settings-form.route.js
Normal file
@ -0,0 +1,56 @@
|
||||
import {templateUrl} from '../../shared/template-url/template-url.factory';
|
||||
import { N_ } from '../../i18n';
|
||||
import SettingsFormController from './settings-form.controller';
|
||||
|
||||
// Import form controllers
|
||||
import SettingsAuthController from './auth-form/configuration-auth.controller';
|
||||
import SettingsJobsController from './jobs-form/configuration-jobs.controller';
|
||||
import SettingsSystemController from './system-form/configuration-system.controller';
|
||||
import SettingsUiController from './ui-form/configuration-ui.controller';
|
||||
|
||||
export default {
|
||||
name: 'settings.form',
|
||||
route: '/:form',
|
||||
ncyBreadcrumb: {
|
||||
label: N_("{{ vm.getCurrentFormTitle() }}")
|
||||
},
|
||||
views: {
|
||||
'@': {
|
||||
templateUrl: templateUrl('configuration/forms/settings-form'),
|
||||
controller: SettingsFormController,
|
||||
controllerAs: 'vm'
|
||||
},
|
||||
'auth@settings.form': {
|
||||
templateUrl: templateUrl('configuration/forms/auth-form/configuration-auth'),
|
||||
controller: SettingsAuthController,
|
||||
controllerAs: 'authVm'
|
||||
},
|
||||
'jobs@settings.form': {
|
||||
templateUrl: templateUrl('configuration/forms/jobs-form/configuration-jobs'),
|
||||
controller: SettingsJobsController,
|
||||
controllerAs: 'jobsVm'
|
||||
},
|
||||
'system@settings.form': {
|
||||
templateUrl: templateUrl('configuration/forms/system-form/configuration-system'),
|
||||
controller: SettingsSystemController,
|
||||
controllerAs: 'systemVm'
|
||||
},
|
||||
'ui@settings.form': {
|
||||
templateUrl: templateUrl('configuration/forms/ui-form/configuration-ui'),
|
||||
controller: SettingsUiController,
|
||||
controllerAs: 'uiVm'
|
||||
},
|
||||
'license@settings.form': {
|
||||
templateUrl: templateUrl('license/license'),
|
||||
controller: 'licenseController'
|
||||
},
|
||||
},
|
||||
onEnter: ['$state', 'ConfigService', '$stateParams', (state, configService, stateParams) => {
|
||||
return configService.getConfig()
|
||||
.then(config => {
|
||||
if (_.get(config, 'license_info.license_type') === 'open' && stateParams.form === 'license') {
|
||||
return state.go('settings');
|
||||
}
|
||||
});
|
||||
}],
|
||||
};
|
||||
@ -5,13 +5,11 @@
|
||||
*************************************************/
|
||||
|
||||
export default [
|
||||
'$rootScope', '$scope', '$state', '$stateParams', '$timeout',
|
||||
'AngularCodeMirror',
|
||||
'$rootScope', '$scope', '$stateParams',
|
||||
'systemActivityStreamForm',
|
||||
'systemLoggingForm',
|
||||
'systemMiscForm',
|
||||
'ConfigurationService',
|
||||
'ConfigurationUtils',
|
||||
'SettingsUtils',
|
||||
'CreateSelect2',
|
||||
'GenerateForm',
|
||||
'i18n',
|
||||
@ -20,13 +18,11 @@ export default [
|
||||
'ngToast',
|
||||
'$filter',
|
||||
function(
|
||||
$rootScope, $scope, $state, $stateParams, $timeout,
|
||||
AngularCodeMirror,
|
||||
$rootScope, $scope, $stateParams,
|
||||
systemActivityStreamForm,
|
||||
systemLoggingForm,
|
||||
systemMiscForm,
|
||||
ConfigurationService,
|
||||
ConfigurationUtils,
|
||||
SettingsUtils,
|
||||
CreateSelect2,
|
||||
GenerateForm,
|
||||
i18n,
|
||||
@ -39,16 +35,15 @@ export default [
|
||||
|
||||
var generator = GenerateForm;
|
||||
var formTracker = $scope.$parent.vm.formTracker;
|
||||
var dropdownValue = 'misc';
|
||||
var activeSystemForm = 'misc';
|
||||
|
||||
if ($stateParams.currentTab === 'system') {
|
||||
if ($stateParams.form === 'system') {
|
||||
formTracker.setCurrentSystem(activeSystemForm);
|
||||
}
|
||||
|
||||
var activeForm = function() {
|
||||
var activeForm = function(tab) {
|
||||
if(!_.get($scope.$parent, [formTracker.currentFormName(), '$dirty'])) {
|
||||
systemVm.activeSystemForm = systemVm.dropdownValue;
|
||||
systemVm.activeSystemForm = tab;
|
||||
formTracker.setCurrentSystem(systemVm.activeSystemForm);
|
||||
} else {
|
||||
var msg = i18n._('You have unsaved changes. Would you like to proceed <strong>without</strong> saving?');
|
||||
@ -60,7 +55,7 @@ export default [
|
||||
onClick: function() {
|
||||
$scope.$parent.vm.populateFromApi();
|
||||
$scope.$parent[formTracker.currentFormName()].$setPristine();
|
||||
systemVm.activeSystemForm = systemVm.dropdownValue;
|
||||
systemVm.activeSystemForm = tab;
|
||||
formTracker.setCurrentSystem(systemVm.activeSystemForm);
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
}
|
||||
@ -71,7 +66,7 @@ export default [
|
||||
.then(function() {
|
||||
$scope.$parent[formTracker.currentFormName()].$setPristine();
|
||||
$scope.$parent.vm.populateFromApi();
|
||||
systemVm.activeSystemForm = systemVm.dropdownValue;
|
||||
systemVm.activeSystemForm = tab;
|
||||
formTracker.setCurrentSystem(systemVm.activeSystemForm);
|
||||
$('#FormModal-dialog').dialog('close');
|
||||
});
|
||||
@ -85,16 +80,11 @@ export default [
|
||||
};
|
||||
|
||||
var dropdownOptions = [
|
||||
{label: i18n._('Misc. System'), value: 'misc'},
|
||||
{label: i18n._('Activity Stream'), value: 'activity_stream'},
|
||||
{label: i18n._('Logging'), value: 'logging'},
|
||||
{label: i18n._('Misc. System'), value: 'misc'}
|
||||
];
|
||||
|
||||
CreateSelect2({
|
||||
element: '#system-configure-dropdown-nav',
|
||||
multiple: false,
|
||||
});
|
||||
|
||||
var systemForms = [{
|
||||
formDef: systemLoggingForm,
|
||||
id: 'system-logging-form'
|
||||
@ -110,12 +100,12 @@ export default [
|
||||
_.each(forms, function(form) {
|
||||
var keys = _.keys(form.fields);
|
||||
_.each(keys, function(key) {
|
||||
if($scope.$parent.configDataResolve[key].type === 'choice') {
|
||||
if($scope.configDataResolve[key].type === 'choice') {
|
||||
// Create options for dropdowns
|
||||
var optionsGroup = key + '_options';
|
||||
$scope.$parent[optionsGroup] = [];
|
||||
_.each($scope.$parent.configDataResolve[key].choices, function(choice){
|
||||
$scope.$parent[optionsGroup].push({
|
||||
$scope.$parent.$parent[optionsGroup] = [];
|
||||
_.each($scope.configDataResolve[key].choices, function(choice){
|
||||
$scope.$parent.$parent[optionsGroup].push({
|
||||
name: choice[0],
|
||||
label: choice[1],
|
||||
value: choice[0]
|
||||
@ -130,29 +120,29 @@ export default [
|
||||
|
||||
function addFieldInfo(form, key) {
|
||||
_.extend(form.fields[key], {
|
||||
awPopOver: ($scope.$parent.configDataResolve[key].defined_in_file) ?
|
||||
null: $scope.$parent.configDataResolve[key].help_text,
|
||||
label: $scope.$parent.configDataResolve[key].label,
|
||||
awPopOver: ($scope.configDataResolve[key].defined_in_file) ?
|
||||
null: $scope.configDataResolve[key].help_text,
|
||||
label: $scope.configDataResolve[key].label,
|
||||
name: key,
|
||||
toggleSource: key,
|
||||
dataPlacement: 'top',
|
||||
placeholder: ConfigurationUtils.formatPlaceholder($scope.$parent.configDataResolve[key].placeholder, key) || null,
|
||||
dataTitle: $scope.$parent.configDataResolve[key].label,
|
||||
required: $scope.$parent.configDataResolve[key].required,
|
||||
placeholder: SettingsUtils.formatPlaceholder($scope.configDataResolve[key].placeholder, key) || null,
|
||||
dataTitle: $scope.configDataResolve[key].label,
|
||||
required: $scope.configDataResolve[key].required,
|
||||
ngDisabled: $rootScope.user_is_system_auditor,
|
||||
disabled: $scope.$parent.configDataResolve[key].disabled || null,
|
||||
readonly: $scope.$parent.configDataResolve[key].readonly || null,
|
||||
definedInFile: $scope.$parent.configDataResolve[key].defined_in_file || null
|
||||
disabled: $scope.configDataResolve[key].disabled || null,
|
||||
readonly: $scope.configDataResolve[key].readonly || null,
|
||||
definedInFile: $scope.configDataResolve[key].defined_in_file || null
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$parent.parseType = 'json';
|
||||
$scope.$parent.$parent.parseType = 'json';
|
||||
|
||||
_.each(systemForms, function(form) {
|
||||
generator.inject(form.formDef, {
|
||||
id: form.id,
|
||||
mode: 'edit',
|
||||
scope: $scope.$parent,
|
||||
scope: $scope.$parent.$parent,
|
||||
related: true,
|
||||
noPanel: true
|
||||
});
|
||||
@ -173,16 +163,17 @@ export default [
|
||||
});
|
||||
|
||||
function populateLogAggregator(flag){
|
||||
if($scope.$parent.LOG_AGGREGATOR_TYPE !== null) {
|
||||
$scope.$parent.LOG_AGGREGATOR_TYPE = _.find($scope.$parent.LOG_AGGREGATOR_TYPE_options, { value: $scope.$parent.LOG_AGGREGATOR_TYPE });
|
||||
|
||||
if($scope.$parent.$parent.LOG_AGGREGATOR_TYPE !== null) {
|
||||
$scope.$parent.$parent.LOG_AGGREGATOR_TYPE = _.find($scope.$parent.$parent.LOG_AGGREGATOR_TYPE_options, { value: $scope.$parent.$parent.LOG_AGGREGATOR_TYPE });
|
||||
}
|
||||
|
||||
if($scope.$parent.LOG_AGGREGATOR_PROTOCOL !== null) {
|
||||
$scope.$parent.LOG_AGGREGATOR_PROTOCOL = _.find($scope.$parent.LOG_AGGREGATOR_PROTOCOL_options, { value: $scope.$parent.LOG_AGGREGATOR_PROTOCOL });
|
||||
if($scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL !== null) {
|
||||
$scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL = _.find($scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL_options, { value: $scope.$parent.$parent.LOG_AGGREGATOR_PROTOCOL });
|
||||
}
|
||||
|
||||
if($scope.$parent.LOG_AGGREGATOR_LEVEL !== null) {
|
||||
$scope.$parent.LOG_AGGREGATOR_LEVEL = _.find($scope.$parent.LOG_AGGREGATOR_LEVEL_options, { value: $scope.$parent.LOG_AGGREGATOR_LEVEL });
|
||||
if($scope.$parent.$parent.LOG_AGGREGATOR_LEVEL !== null) {
|
||||
$scope.$parent.$parent.LOG_AGGREGATOR_LEVEL = _.find($scope.$parent.$parent.LOG_AGGREGATOR_LEVEL_options, { value: $scope.$parent.$parent.LOG_AGGREGATOR_LEVEL });
|
||||
}
|
||||
|
||||
if(flag !== undefined){
|
||||
@ -196,18 +187,12 @@ export default [
|
||||
multiple: false,
|
||||
placeholder: i18n._('Select types'),
|
||||
});
|
||||
$scope.$parent.configuration_logging_template_form.LOG_AGGREGATOR_TYPE.$setPristine();
|
||||
$scope.$parent.configuration_logging_template_form.LOG_AGGREGATOR_PROTOCOL.$setPristine();
|
||||
$scope.$parent.configuration_logging_template_form.LOG_AGGREGATOR_LEVEL.$setPristine();
|
||||
$scope.$parent.$parent.configuration_logging_template_form.LOG_AGGREGATOR_TYPE.$setPristine();
|
||||
$scope.$parent.$parent.configuration_logging_template_form.LOG_AGGREGATOR_PROTOCOL.$setPristine();
|
||||
$scope.$parent.$parent.configuration_logging_template_form.LOG_AGGREGATOR_LEVEL.$setPristine();
|
||||
}
|
||||
}
|
||||
|
||||
// Fix for bug where adding selected opts causes form to be $dirty and triggering modal
|
||||
// TODO Find better solution for this bug
|
||||
$timeout(function(){
|
||||
$scope.$parent.configuration_logging_template_form.$setPristine();
|
||||
}, 1000);
|
||||
|
||||
$scope.$parent.vm.testLogging = function() {
|
||||
Rest.setUrl("/api/v2/settings/logging/test/");
|
||||
Rest.post($scope.$parent.vm.getFormPayload())
|
||||
@ -241,7 +226,6 @@ export default [
|
||||
activeForm: activeForm,
|
||||
activeSystemForm: activeSystemForm,
|
||||
dropdownOptions: dropdownOptions,
|
||||
dropdownValue: dropdownValue,
|
||||
systemForms: systemForms
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<div class="tab-pane Configuration-container">
|
||||
<div class="row Form-tabRow">
|
||||
<div class="col-lg-12">
|
||||
<div class="Form-tabHolder">
|
||||
<div ng-repeat="opt in systemVm.dropdownOptions"
|
||||
class="Form-tab"
|
||||
ng-click="systemVm.activeForm(opt.value)"
|
||||
ng-class="{'is-selected': systemVm.activeSystemForm === opt.value }"
|
||||
translate>
|
||||
{{opt.label}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div ng-show="systemVm.activeSystemForm === 'misc'">
|
||||
<div id="system-misc-form">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="systemVm.activeSystemForm === 'activity_stream'">
|
||||
<div id="system-activity-stream-form">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="systemVm.activeSystemForm === 'logging'">
|
||||
<div class="form-group Form-formGroup">
|
||||
<label class="Form-inputLabelContainer" for="LOG_AGGREGATOR_ENABLED">
|
||||
<span class="Form-inputLabel">
|
||||
Enable External Logging
|
||||
</span>
|
||||
<a id="awp-LOG_AGGREGATOR_ENABLED" href="" aw-pop-over="Enable sending logs to external log aggregator." data-placement="top" over-title="Enable External Logging" class="help-link" tabindex="-1">
|
||||
<i class="fa fa-question-circle"></i>
|
||||
</a>
|
||||
</label>
|
||||
<div class="ScheduleToggle" ng-class="{'is-on': LOG_AGGREGATOR_ENABLED, 'ScheduleToggle--disabled': (!LOG_AGGREGATOR_ENABLED && (!requiredLogValues.LOG_AGGREGATOR_HOST || requiredLogValues.LOG_AGGREGATOR_HOST === '' || !requiredLogValues.LOG_AGGREGATOR_TYPE || requiredLogValues.LOG_AGGREGATOR_TYPE === '')) || $rootScope.user_is_system_auditor}">
|
||||
<button ng-show="LOG_AGGREGATOR_ENABLED" class="ScheduleToggle-switch is-on" ng-click="toggleForm('LOG_AGGREGATOR_ENABLED')" ng-disabled="$rootScope.user_is_system_auditor">ON</button>
|
||||
<button ng-show="!LOG_AGGREGATOR_ENABLED" class="ScheduleToggle-switch" ng-click="toggleForm('LOG_AGGREGATOR_ENABLED')" ng-disabled="!requiredLogValues.LOG_AGGREGATOR_HOST || requiredLogValues.LOG_AGGREGATOR_HOST === '' || !requiredLogValues.LOG_AGGREGATOR_TYPE || requiredLogValues.LOG_AGGREGATOR_TYPE === '' || $rootScope.user_is_system_auditor">OFF</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="system-logging-form">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -7,37 +7,36 @@
|
||||
export default [
|
||||
'$scope',
|
||||
'$rootScope',
|
||||
'$state',
|
||||
'$timeout',
|
||||
'ConfigurationUiForm',
|
||||
'ConfigurationService',
|
||||
'CreateSelect2',
|
||||
'GenerateForm',
|
||||
'i18n',
|
||||
'$stateParams',
|
||||
function(
|
||||
$scope,
|
||||
$rootScope,
|
||||
$state,
|
||||
$timeout,
|
||||
ConfigurationUiForm,
|
||||
ConfigurationService,
|
||||
CreateSelect2,
|
||||
GenerateForm,
|
||||
i18n
|
||||
i18n,
|
||||
$stateParams
|
||||
) {
|
||||
var uiVm = this;
|
||||
var generator = GenerateForm;
|
||||
var form = ConfigurationUiForm;
|
||||
|
||||
const formTracker = $scope.$parent.vm.formTracker;
|
||||
if ($stateParams.form === 'ui') {
|
||||
formTracker.setCurrentAuth('ui');
|
||||
}
|
||||
|
||||
var keys = _.keys(form.fields);
|
||||
_.each(keys, function(key) {
|
||||
if($scope.$parent.configDataResolve[key].type === 'choice') {
|
||||
if($scope.configDataResolve[key].type === 'choice') {
|
||||
// Create options for dropdowns
|
||||
var optionsGroup = key + '_options';
|
||||
$scope.$parent[optionsGroup] = [];
|
||||
_.each($scope.$parent.configDataResolve[key].choices, function(choice){
|
||||
$scope.$parent[optionsGroup].push({
|
||||
$scope.$parent.$parent[optionsGroup] = [];
|
||||
_.each($scope.configDataResolve[key].choices, function(choice){
|
||||
$scope.$parent.$parent[optionsGroup].push({
|
||||
name: choice[0],
|
||||
label: choice[1],
|
||||
value: choice[0]
|
||||
@ -52,25 +51,25 @@
|
||||
|
||||
function addFieldInfo(form, key) {
|
||||
_.extend(form.fields[key], {
|
||||
awPopOver: ($scope.$parent.configDataResolve[key].defined_in_file) ?
|
||||
null: $scope.$parent.configDataResolve[key].help_text,
|
||||
label: $scope.$parent.configDataResolve[key].label,
|
||||
awPopOver: ($scope.configDataResolve[key].defined_in_file) ?
|
||||
null: $scope.configDataResolve[key].help_text,
|
||||
label: $scope.configDataResolve[key].label,
|
||||
name: key,
|
||||
toggleSource: key,
|
||||
dataPlacement: 'top',
|
||||
dataTitle: $scope.$parent.configDataResolve[key].label,
|
||||
required: $scope.$parent.configDataResolve[key].required,
|
||||
dataTitle: $scope.configDataResolve[key].label,
|
||||
required: $scope.configDataResolve[key].required,
|
||||
ngDisabled: $rootScope.user_is_system_auditor,
|
||||
disabled: $scope.$parent.configDataResolve[key].disabled || null,
|
||||
readonly: $scope.$parent.configDataResolve[key].readonly || null,
|
||||
definedInFile: $scope.$parent.configDataResolve[key].defined_in_file || null
|
||||
disabled: $scope.configDataResolve[key].disabled || null,
|
||||
readonly: $scope.configDataResolve[key].readonly || null,
|
||||
definedInFile: $scope.configDataResolve[key].defined_in_file || null
|
||||
});
|
||||
}
|
||||
|
||||
generator.inject(form, {
|
||||
id: 'configure-ui-form',
|
||||
mode: 'edit',
|
||||
scope: $scope.$parent,
|
||||
scope: $scope.$parent.$parent,
|
||||
related: true,
|
||||
noPanel: true
|
||||
});
|
||||
@ -79,8 +78,8 @@
|
||||
var dropdownRendered = false;
|
||||
|
||||
function populatePendoTrackingState(flag){
|
||||
if($scope.$parent.PENDO_TRACKING_STATE !== null) {
|
||||
$scope.$parent.PENDO_TRACKING_STATE = _.find($scope.$parent.PENDO_TRACKING_STATE_options, { value: $scope.$parent.PENDO_TRACKING_STATE });
|
||||
if($scope.$parent.$parent.PENDO_TRACKING_STATE !== null) {
|
||||
$scope.$parent.$parent.PENDO_TRACKING_STATE = _.find($scope.$parent.$parent.PENDO_TRACKING_STATE_options, { value: $scope.$parent.$parent.PENDO_TRACKING_STATE });
|
||||
}
|
||||
|
||||
if(flag !== undefined){
|
||||
@ -104,10 +103,5 @@
|
||||
$scope.$on('populated', function(){
|
||||
populatePendoTrackingState(false);
|
||||
});
|
||||
|
||||
angular.extend(uiVm, {
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
];
|
||||
@ -1,52 +0,0 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2016 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import {templateUrl} from '../shared/template-url/template-url.factory';
|
||||
import { N_ } from '../i18n';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'configuration.license',
|
||||
route: '/license',
|
||||
// templateUrl: templateUrl('license/license'),
|
||||
// controller: 'licenseController',
|
||||
data: {},
|
||||
ncyBreadcrumb: {
|
||||
label: N_('LICENSE')
|
||||
},
|
||||
onEnter: ['$state', 'ConfigService', (state, configService) => {
|
||||
return configService.getConfig()
|
||||
.then(config => {
|
||||
if (_.get(config, 'license_info.license_type') === 'open') {
|
||||
return state.go('setup');
|
||||
}
|
||||
});
|
||||
}],
|
||||
views: {
|
||||
'license@configuration': {
|
||||
templateUrl: templateUrl('license/license'),
|
||||
controller: 'licenseController'
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
features: ['CheckLicense', '$rootScope',
|
||||
function(CheckLicense, $rootScope) {
|
||||
if($rootScope.licenseMissing === undefined){
|
||||
return CheckLicense.notify();
|
||||
}
|
||||
|
||||
}],
|
||||
config: ['ConfigService', 'CheckLicense', '$rootScope',
|
||||
function(ConfigService, CheckLicense, $rootScope) {
|
||||
ConfigService.delete();
|
||||
return ConfigService.getConfig()
|
||||
.then(function(config){
|
||||
$rootScope.licenseMissing = (CheckLicense.valid(config.license_info) === false) ? true : false;
|
||||
return config;
|
||||
});
|
||||
}]
|
||||
},
|
||||
};
|
||||
@ -4,40 +4,43 @@
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import configurationService from './configuration.service';
|
||||
import ConfigurationUtils from './configurationUtils.service';
|
||||
import configurationRoute from './configuration.route';
|
||||
import licenseRoute from './license.route';
|
||||
import configurationController from './configuration.controller.js';
|
||||
import settingsService from './settings.service';
|
||||
import settingsUtils from './settingsUtils.service';
|
||||
|
||||
// Import forms
|
||||
//authorization sub-forms
|
||||
import configurationAzureForm from './auth-form/sub-forms/auth-azure.form.js';
|
||||
import configurationGithubForm from './auth-form/sub-forms/auth-github.form.js';
|
||||
import configurationGithubOrgForm from './auth-form/sub-forms/auth-github-org.form';
|
||||
import configurationGithubTeamForm from './auth-form/sub-forms/auth-github-team.form';
|
||||
import configurationGoogleForm from './auth-form/sub-forms/auth-google-oauth2.form';
|
||||
import configurationLdapForm from './auth-form/sub-forms/auth-ldap.form.js';
|
||||
import configurationLdap1Form from './auth-form/sub-forms/auth-ldap1.form.js';
|
||||
import configurationLdap2Form from './auth-form/sub-forms/auth-ldap2.form.js';
|
||||
import configurationLdap3Form from './auth-form/sub-forms/auth-ldap3.form.js';
|
||||
import configurationLdap4Form from './auth-form/sub-forms/auth-ldap4.form.js';
|
||||
import configurationLdap5Form from './auth-form/sub-forms/auth-ldap5.form.js';
|
||||
import configurationRadiusForm from './auth-form/sub-forms/auth-radius.form.js';
|
||||
import configurationTacacsForm from './auth-form/sub-forms/auth-tacacs.form.js';
|
||||
import configurationSamlForm from './auth-form/sub-forms/auth-saml.form';
|
||||
import configurationAzureForm from './forms/auth-form/sub-forms/auth-azure.form.js';
|
||||
import configurationGithubForm from './forms/auth-form/sub-forms/auth-github.form.js';
|
||||
import configurationGithubOrgForm from './forms/auth-form/sub-forms/auth-github-org.form';
|
||||
import configurationGithubTeamForm from './forms/auth-form/sub-forms/auth-github-team.form';
|
||||
import configurationGoogleForm from './forms/auth-form/sub-forms/auth-google-oauth2.form';
|
||||
import configurationLdapForm from './forms/auth-form/sub-forms/auth-ldap.form.js';
|
||||
import configurationLdap1Form from './forms/auth-form/sub-forms/auth-ldap1.form.js';
|
||||
import configurationLdap2Form from './forms/auth-form/sub-forms/auth-ldap2.form.js';
|
||||
import configurationLdap3Form from './forms/auth-form/sub-forms/auth-ldap3.form.js';
|
||||
import configurationLdap4Form from './forms/auth-form/sub-forms/auth-ldap4.form.js';
|
||||
import configurationLdap5Form from './forms/auth-form/sub-forms/auth-ldap5.form.js';
|
||||
import configurationRadiusForm from './forms/auth-form/sub-forms/auth-radius.form.js';
|
||||
import configurationTacacsForm from './forms/auth-form/sub-forms/auth-tacacs.form.js';
|
||||
import configurationSamlForm from './forms/auth-form/sub-forms/auth-saml.form';
|
||||
|
||||
//system sub-forms
|
||||
import systemActivityStreamForm from './system-form/sub-forms/system-activity-stream.form.js';
|
||||
import systemLoggingForm from './system-form/sub-forms/system-logging.form.js';
|
||||
import systemMiscForm from './system-form/sub-forms/system-misc.form.js';
|
||||
import systemActivityStreamForm from './forms/system-form/sub-forms/system-activity-stream.form.js';
|
||||
import systemLoggingForm from './forms/system-form/sub-forms/system-logging.form.js';
|
||||
import systemMiscForm from './forms/system-form/sub-forms/system-misc.form.js';
|
||||
|
||||
import configurationJobsForm from './jobs-form/configuration-jobs.form';
|
||||
import configurationUiForm from './ui-form/configuration-ui.form';
|
||||
import configurationJobsForm from './forms/jobs-form/configuration-jobs.form';
|
||||
import configurationUiForm from './forms/ui-form/configuration-ui.form';
|
||||
|
||||
// Wrapper form route
|
||||
import settingsFormRoute from './forms/settings-form.route';
|
||||
|
||||
import settingsRoute from './settings.route';
|
||||
import settingsController from './settings.controller.js';
|
||||
|
||||
export default
|
||||
angular.module('configuration', [])
|
||||
.controller('ConfigurationController', configurationController)
|
||||
.controller('SettingsController', settingsController)
|
||||
//auth forms
|
||||
.factory('configurationAzureForm', configurationAzureForm)
|
||||
.factory('configurationGithubForm', configurationGithubForm)
|
||||
@ -63,9 +66,9 @@ angular.module('configuration', [])
|
||||
.factory('ConfigurationUiForm', configurationUiForm)
|
||||
|
||||
//helpers and services
|
||||
.factory('ConfigurationUtils', ConfigurationUtils)
|
||||
.service('ConfigurationService', configurationService)
|
||||
.factory('SettingsUtils', settingsUtils)
|
||||
.service('SettingsService', settingsService)
|
||||
.run(['$stateExtender', function($stateExtender) {
|
||||
$stateExtender.addState(configurationRoute);
|
||||
$stateExtender.addState(licenseRoute);
|
||||
$stateExtender.addState(settingsFormRoute);
|
||||
$stateExtender.addState(settingsRoute);
|
||||
}]);
|
||||
|
||||
13
awx/ui/client/src/configuration/settings.controller.js
Normal file
13
awx/ui/client/src/configuration/settings.controller.js
Normal file
@ -0,0 +1,13 @@
|
||||
import defaultStrings from '~assets/default.strings.json';
|
||||
|
||||
export default [ '$state',
|
||||
function ($state) {
|
||||
const vm = this;
|
||||
|
||||
vm.product = defaultStrings.BRAND_NAME;
|
||||
|
||||
vm.goToCard = (card) => {
|
||||
$state.go('settings.form', { form: card });
|
||||
};
|
||||
}
|
||||
];
|
||||
17
awx/ui/client/src/configuration/settings.partial.html
Normal file
17
awx/ui/client/src/configuration/settings.partial.html
Normal file
@ -0,0 +1,17 @@
|
||||
<at-card-group>
|
||||
<at-card title="Authentication" ng-click="vm.goToCard('auth')">
|
||||
Enable simplified login for your Tower applications
|
||||
</at-card>
|
||||
<at-card title="Jobs" ng-click="vm.goToCard('jobs')">
|
||||
Update settings pertaining to Jobs within Tower
|
||||
</at-card>
|
||||
<at-card title="System" ng-click="vm.goToCard('system')">
|
||||
Define system-level features and functions
|
||||
</at-card>
|
||||
<at-card title="User Interface" ng-click="vm.goToCard('ui')">
|
||||
Set preferences for data collection, logos, and logins
|
||||
</at-card>
|
||||
<at-card title="License" ng-show="vm.product === 'Tower'" ng-click="vm.goToCard('license')">
|
||||
View and edit your license information
|
||||
</at-card>
|
||||
</at-card-group>
|
||||
40
awx/ui/client/src/configuration/settings.route.js
Normal file
40
awx/ui/client/src/configuration/settings.route.js
Normal file
@ -0,0 +1,40 @@
|
||||
import { N_ } from '../i18n';
|
||||
import {templateUrl} from '../shared/template-url/template-url.factory';
|
||||
import SettingsController from './settings.controller';
|
||||
// Import form controllers
|
||||
|
||||
export default {
|
||||
name: 'settings',
|
||||
route: '/settings',
|
||||
ncyBreadcrumb: {
|
||||
label: N_("SETTINGS")
|
||||
},
|
||||
resolve: {
|
||||
configDataResolve: ['SettingsService', function(SettingsService){
|
||||
return SettingsService.getConfigurationOptions();
|
||||
}],
|
||||
features: ['CheckLicense', '$rootScope',
|
||||
function(CheckLicense, $rootScope) {
|
||||
if($rootScope.licenseMissing === undefined){
|
||||
return CheckLicense.notify();
|
||||
}
|
||||
|
||||
}],
|
||||
config: ['ConfigService', 'CheckLicense', '$rootScope',
|
||||
function(ConfigService, CheckLicense, $rootScope) {
|
||||
ConfigService.delete();
|
||||
return ConfigService.getConfig()
|
||||
.then(function(config){
|
||||
$rootScope.licenseMissing = (CheckLicense.valid(config.license_info) === false) ? true : false;
|
||||
return config;
|
||||
});
|
||||
}],
|
||||
},
|
||||
views: {
|
||||
'': {
|
||||
templateUrl: templateUrl('configuration/settings'),
|
||||
controller: SettingsController,
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1,49 +0,0 @@
|
||||
<div class="tab-pane Configuration-container">
|
||||
<div class="Form-nav--dropdownContainer">
|
||||
<div class="Form-nav--dropdownLabel">Sub Category</div>
|
||||
<div class="Form-nav--dropdown">
|
||||
<select
|
||||
id="system-configure-dropdown-nav"
|
||||
class="form-control"
|
||||
ng-model="systemVm.dropdownValue"
|
||||
ng-options="opt.value as opt.label for opt in systemVm.dropdownOptions"
|
||||
ng-change="systemVm.activeForm()">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<!-- <div id="configure-system-form"></div> -->
|
||||
<div ng-show="systemVm.activeSystemForm === 'misc'">
|
||||
<div id="system-misc-form">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="systemVm.activeSystemForm === 'activity_stream'">
|
||||
<div id="system-activity-stream-form">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="systemVm.activeSystemForm === 'logging'">
|
||||
<div class="form-group Form-formGroup">
|
||||
<label class="Form-inputLabelContainer" for="LOG_AGGREGATOR_ENABLED">
|
||||
<span class="Form-inputLabel" translate>
|
||||
Enable External Logging
|
||||
</span>
|
||||
<a id="awp-LOG_AGGREGATOR_ENABLED" href="" aw-pop-over="Enable sending logs to external log aggregator." data-placement="top" over-title="Enable External Logging" class="help-link" tabindex="-1">
|
||||
<i class="fa fa-question-circle"></i>
|
||||
</a>
|
||||
</label>
|
||||
<div class="ScheduleToggle" ng-class="{'is-on': LOG_AGGREGATOR_ENABLED, 'ScheduleToggle--disabled': (!LOG_AGGREGATOR_ENABLED && (!requiredLogValues.LOG_AGGREGATOR_HOST || requiredLogValues.LOG_AGGREGATOR_HOST === '' || !requiredLogValues.LOG_AGGREGATOR_TYPE || requiredLogValues.LOG_AGGREGATOR_TYPE === '')) || $rootScope.user_is_system_auditor}">
|
||||
<button ng-show="LOG_AGGREGATOR_ENABLED" class="ScheduleToggle-switch is-on" ng-click="toggleForm('LOG_AGGREGATOR_ENABLED')" ng-disabled="$rootScope.user_is_system_auditor">ON</button>
|
||||
<button ng-show="!LOG_AGGREGATOR_ENABLED" class="ScheduleToggle-switch" ng-click="toggleForm('LOG_AGGREGATOR_ENABLED')" ng-disabled="!requiredLogValues.LOG_AGGREGATOR_HOST || requiredLogValues.LOG_AGGREGATOR_HOST === '' || !requiredLogValues.LOG_AGGREGATOR_TYPE || requiredLogValues.LOG_AGGREGATOR_TYPE === '' || $rootScope.user_is_system_auditor">OFF</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="system-logging-form">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -86,8 +86,8 @@ angular.module('AWDirectives', ['RestServices', 'Utilities'])
|
||||
// Accepts image and returns base64 information with basic validation
|
||||
// Can eventually expand to handle all uploads with different endpoints and handlers
|
||||
//
|
||||
.directive('imageUpload', ['ConfigurationUtils', 'i18n', '$rootScope',
|
||||
function(ConfigurationUtils, i18n, $rootScope) {
|
||||
.directive('imageUpload', ['SettingsUtils', 'i18n', '$rootScope',
|
||||
function(SettingsUtils, i18n, $rootScope) {
|
||||
var browseText = i18n._('BROWSE'),
|
||||
placeholderText = i18n._('Choose file'),
|
||||
uploadedText = i18n._('Current Image: '),
|
||||
@ -157,7 +157,7 @@ function(ConfigurationUtils, i18n, $rootScope) {
|
||||
scope.fileChange = function(file) {
|
||||
filePickerError.html('');
|
||||
|
||||
ConfigurationUtils.imageProcess(file[0])
|
||||
SettingsUtils.imageProcess(file[0])
|
||||
.then(function(result) {
|
||||
scope.$parent[fieldKey] = result;
|
||||
filePickerText.val(file[0].name);
|
||||
|
||||
@ -48,7 +48,6 @@ export default
|
||||
scrollbarStyle: null
|
||||
}
|
||||
};
|
||||
|
||||
scope[fld + 'codeMirror'] = AngularCodeMirror(readOnly);
|
||||
scope[fld + 'codeMirror'].addModes(variableEditModes);
|
||||
scope[fld + 'codeMirror'].showTextArea({
|
||||
@ -61,7 +60,6 @@ export default
|
||||
onChange: onChange
|
||||
});
|
||||
}
|
||||
|
||||
// Hide the textarea and show a CodeMirror editor
|
||||
createField(onChange, onReady, fld);
|
||||
|
||||
|
||||
@ -14,6 +14,17 @@ const commands = [{
|
||||
return this.navigate();
|
||||
},
|
||||
selectSubcategory (name) {
|
||||
const spinny = 'div.spinny';
|
||||
const categoryName = `//*[text() = '${name}']`;
|
||||
|
||||
this.api.useXpath();
|
||||
this.api.waitForElementVisible(categoryName);
|
||||
this.api.click(categoryName);
|
||||
this.api.useCss();
|
||||
|
||||
return this;
|
||||
},
|
||||
selectDropDownContainer (name) {
|
||||
const spinny = 'div.spinny';
|
||||
const select = '#configure-dropdown-nav';
|
||||
const arrow = `${select} + span span[class$="arrow"]`;
|
||||
|
||||
@ -18,7 +18,10 @@ const navigation = {
|
||||
notifications: 'i[class$="fa-bell"]',
|
||||
managementJobs: 'i[class$="fa-wrench"]',
|
||||
instanceGroups: 'i[class$="fa-server"]',
|
||||
settings: 'i[class$="fa-cog"]',
|
||||
settings: 'i[class*="fa-cog"]',
|
||||
settingsSubPane: '.at-SettingsSubPane',
|
||||
settingsSubPaneSystem: 'a[href="#/settings/system"]',
|
||||
settingsSubPaneAuth: 'a[href="#/settings/auth"]'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
module.exports = {
|
||||
'expected LDAP codemirror fields are rendered when returning from another tab': client => {
|
||||
const authTab = '#auth_tab';
|
||||
const authView = 'div[ui-view="auth"]';
|
||||
const ldapForm = '#configuration_ldap_template_form';
|
||||
const systemTab = '#system_tab';
|
||||
const systemView = 'div[ui-view="system"]';
|
||||
|
||||
const { navigation } = client.page.dashboard().section;
|
||||
@ -14,20 +12,23 @@ module.exports = {
|
||||
|
||||
navigation
|
||||
.waitForElementVisible('@settings')
|
||||
.click('@settings');
|
||||
.moveToElement('@settings', 0, 0)
|
||||
.waitForElementVisible('@settingsSubPaneSystem')
|
||||
.click('@settingsSubPaneSystem');
|
||||
|
||||
configuration.waitForElementVisible(authView);
|
||||
|
||||
configuration.waitForElementVisible(systemTab);
|
||||
configuration.click(systemTab);
|
||||
configuration.waitForElementNotVisible(authView);
|
||||
configuration.waitForElementVisible(systemView);
|
||||
|
||||
configuration.waitForElementVisible(authTab);
|
||||
configuration.click(authTab);
|
||||
configuration.waitForElementNotVisible(systemView);
|
||||
navigation
|
||||
.waitForElementVisible('@settings')
|
||||
.moveToElement('@settings', 0, 0)
|
||||
.waitForElementVisible('@settingsSubPane')
|
||||
.waitForElementVisible('@settingsSubPaneAuth')
|
||||
.click('@settingsSubPaneAuth');
|
||||
|
||||
configuration.waitForElementVisible(authView);
|
||||
|
||||
// works as xpath const categoryName =
|
||||
// `//*[@id="configuration_edit"]/div[1]/div/div/div[4]`;
|
||||
configuration.selectSubcategory('LDAP');
|
||||
configuration.waitForElementVisible(ldapForm);
|
||||
|
||||
@ -41,7 +42,7 @@ module.exports = {
|
||||
'AUTH_LDAP_TEAM_MAP',
|
||||
];
|
||||
|
||||
const ldapCodeMirrors = `${ldapForm} div[class^="CodeMirror"] textarea`;
|
||||
const ldapCodeMirrors = `${ldapForm} div[class^="CodeMirror"] textarea`;
|
||||
|
||||
client.elements('css selector', ldapCodeMirrors, ({ value }) => {
|
||||
client.assert.equal(value.length, expectedCodemirrorFields.length);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user