diff --git a/awx/ui/client/features/credentials/add-credentials.controller.js b/awx/ui/client/features/credentials/add-credentials.controller.js index 60294a63bd..c28ca76e56 100644 --- a/awx/ui/client/features/credentials/add-credentials.controller.js +++ b/awx/ui/client/features/credentials/add-credentials.controller.js @@ -1,6 +1,6 @@ const DEFAULT_ORGANIZATION_PLACEHOLDER = 'SELECT AN ORGANIZATION'; -function AddCredentialsController (models, $state) { +function AddCredentialsController (models, organizationList, $state) { let vm = this || {}; let me = models.me; @@ -23,6 +23,7 @@ function AddCredentialsController (models, $state) { omit: ['user', 'team', 'inputs'] }); + vm.form.organization._model = organization; vm.form.organization._placeholder = DEFAULT_ORGANIZATION_PLACEHOLDER; vm.form.credential_type._data = credentialType.get('results'); @@ -52,6 +53,7 @@ function AddCredentialsController (models, $state) { AddCredentialsController.$inject = [ 'resolvedModels', + 'OrganizationList', '$state' ]; diff --git a/awx/ui/client/features/credentials/add-edit-credentials.view.html b/awx/ui/client/features/credentials/add-edit-credentials.view.html index 186056af2b..2b7f0b022e 100644 --- a/awx/ui/client/features/credentials/add-edit-credentials.view.html +++ b/awx/ui/client/features/credentials/add-edit-credentials.view.html @@ -1,4 +1,6 @@ - + {{ vm.panelTitle }} diff --git a/awx/ui/client/features/credentials/index.js b/awx/ui/client/features/credentials/index.js index e8c5670cbe..7a74b39657 100644 --- a/awx/ui/client/features/credentials/index.js +++ b/awx/ui/client/features/credentials/index.js @@ -1,7 +1,4 @@ -import PermissionsList from '../../src/access/permissions-list.controller'; -import CredentialForm from '../../src/credentials/credentials.form'; -import CredentialList from '../../src/credentials/credentials.list'; -import ListController from '../../src/credentials/list/credentials-list.controller'; +import LegacyCredentials from './legacy.credentials'; import AddController from './add-credentials.controller.js'; import EditController from './edit-credentials.controller.js'; import { N_ } from '../../src/i18n'; @@ -33,42 +30,10 @@ CredentialsResolve.$inject = [ 'OrganizationModel' ]; -function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceProvider) { - let pathService = pathServiceProvider.$get(); +function CredentialsConfig ($stateExtenderProvider, legacyProvider, pathProvider) { + let path = pathProvider.$get(); let stateExtender = $stateExtenderProvider.$get(); - - stateExtender.addState({ - name: 'credentials', - route: '/credentials', - ncyBreadcrumb: { - label: N_('CREDENTIALS') - }, - views: { - '@': { - templateUrl: pathService.getViewPath('credentials/index') - }, - 'list@credentials': { - templateProvider: function(CredentialList, generateList) { - let html = generateList.build({ - list: CredentialList, - mode: 'edit' - }); - - return html; - }, - controller: ListController - } - }, - searchPrefix: 'credential', - resolve: { - Dataset: ['CredentialList', 'QuerySet', '$stateParams', 'GetBasePath', - function(list, qs, $stateParams, GetBasePath) { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return qs.search(path, $stateParams[`${list.iterator}_search`]); - } - ] - } - }); + let legacy = legacyProvider.$get(); stateExtender.addState({ name: 'credentials.add', @@ -78,7 +43,7 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP }, views: { 'add@credentials': { - templateUrl: pathService.getViewPath('credentials/add-edit-credentials'), + templateUrl: path.getViewPath('credentials/add-edit-credentials'), controller: AddController, controllerAs: 'vm' } @@ -96,7 +61,7 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP }, views: { 'edit@credentials': { - templateUrl: pathService.getViewPath('credentials/add-edit-credentials'), + templateUrl: path.getViewPath('credentials/add-edit-credentials'), controller: EditController, controllerAs: 'vm' } @@ -106,178 +71,21 @@ function CredentialsConfig ($stateProvider, $stateExtenderProvider, pathServiceP } }); - stateExtender.addState({ - name: "credentials.edit.permissions", - url: "/permissions?{permission_search:queryset}", - resolve: { - ListDefinition: () => { - return { - name: 'permissions', - disabled: '(organization === undefined ? true : false)', - // Do not transition the state if organization is undefined - ngClick: `(organization === undefined ? true : false)||$state.go('credentials.edit.permissions')`, - awToolTip: '{{permissionsTooltip}}', - dataTipWatch: 'permissionsTooltip', - awToolTipTabEnabledInEditMode: true, - dataPlacement: 'right', - basePath: 'api/v2/credentials/{{$stateParams.id}}/access_list/', - search: { - order_by: 'username' - }, - type: 'collection', - title: N_('Permissions'), - iterator: 'permission', - index: false, - open: false, - actions: { - add: { - ngClick: "$state.go('.add')", - label: 'Add', - awToolTip: N_('Add a permission'), - actionClass: 'btn List-buttonSubmit', - buttonContent: '+ ' + N_('ADD'), - ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)' - } - }, - fields: { - username: { - key: true, - label: N_('User'), - linkBase: 'users', - class: 'col-lg-3 col-md-3 col-sm-3 col-xs-4' - }, - role: { - label: N_('Role'), - type: 'role', - nosort: true, - class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4' - }, - team_roles: { - label: N_('Team Roles'), - type: 'team_roles', - nosort: true, - class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4' - } - } - }; - }, - Dataset: ['QuerySet', '$stateParams', (qs, $stateParams) => { - let id = $stateParams.credential_id; - let path = `api/v2/credentials/${id}/access_list/`; - - return qs.search(path, $stateParams[`permission_search`]); - } - ] - }, - params: { - permission_search: { - value: { - page_size: "20", - order_by: "username" - }, - dynamic:true, - squash:"" - } - }, - ncyBreadcrumb: { - parent: "credentials.edit", - label: "PERMISSIONS" - }, - views: { - 'related': { - templateProvider: function(CredentialForm, GenerateForm) { - let html = GenerateForm.buildCollection({ - mode: 'edit', - related: `permissions`, - form: typeof(CredentialForm) === 'function' ? - CredentialForm() : CredentialForm - }); - return html; - }, - controller: 'PermissionsList' - } - } - }); - - stateExtender.addState({ - name: 'credentials.edit.permissions.add', - url: '/add-permissions', - resolve: { - usersDataset: [ - 'addPermissionsUsersList', - 'QuerySet', - '$stateParams', - 'GetBasePath', - (list, qs, $stateParams, GetBasePath) => { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return qs.search(path, $stateParams.user_search); - - } - ], - teamsDataset: [ - 'addPermissionsTeamsList', - 'QuerySet', - '$stateParams', - 'GetBasePath', - (list, qs, $stateParams, GetBasePath) => { - let path = GetBasePath(list.basePath) || GetBasePath(list.name); - return qs.search(path, $stateParams.team_search); - } - ], - resourceData: ['CredentialModel', '$stateParams', (Credential, $stateParams) => { - return new Credential('get', $stateParams.credential_id) - .then(credential => ({ data: credential.get() })); - }], - }, - params: { - user_search: { - value: { - order_by: 'username', - page_size: 5 - }, - dynamic: true - }, - team_search: { - value: { - order_by: 'name', - page_size: 5 - }, - dynamic: true - } - }, - ncyBreadcrumb: { - skip: true - }, - views: { - 'modal@credentials.edit': { - template: ` - - ` - } - }, - onExit: $state => { - if ($state.transition) { - $('#add-permissions-modal').modal('hide'); - $('.modal-backdrop').remove(); - $('body').removeClass('modal-open'); - } - } - }); + stateExtender.addState(legacy.getStateConfiguration('list')); + stateExtender.addState(legacy.getStateConfiguration('edit-permissions')); + stateExtender.addState(legacy.getStateConfiguration('add-permissions')); + stateExtender.addState(legacy.getStateConfiguration('add-organization')); } CredentialsConfig.$inject = [ - '$stateProvider', - '$stateExtenderProvider', - 'PathServiceProvider' + '$stateExtenderProvider', + 'LegacyCredentialsServiceProvider', + 'PathServiceProvider' ]; angular .module('at.features.credentials', []) .config(CredentialsConfig) .controller('AddController', AddController) - .controller('EditController', EditController); + .controller('EditController', EditController) + .service('LegacyCredentialsService', LegacyCredentials); diff --git a/awx/ui/client/features/credentials/legacy.credentials.js b/awx/ui/client/features/credentials/legacy.credentials.js new file mode 100644 index 0000000000..3527c23f8b --- /dev/null +++ b/awx/ui/client/features/credentials/legacy.credentials.js @@ -0,0 +1,279 @@ +import PermissionsList from '../../src/access/permissions-list.controller'; +import CredentialForm from '../../src/credentials/credentials.form'; +import CredentialList from '../../src/credentials/credentials.list'; +import OrganizationList from '../../src/organizations/organizations.list'; +import ListController from '../../src/credentials/list/credentials-list.controller'; +import { N_ } from '../../src/i18n'; + +function LegacyCredentialsService (pathService) { + this.list = { + name: 'credentials', + route: '/credentials', + ncyBreadcrumb: { + label: N_('CREDENTIALS') + }, + views: { + '@': { + templateUrl: pathService.getViewPath('credentials/index') + }, + 'list@credentials': { + templateProvider: function(CredentialList, generateList) { + let html = generateList.build({ + list: CredentialList, + mode: 'edit' + }); + + return html; + }, + controller: ListController + } + }, + searchPrefix: 'credential', + resolve: { + Dataset: ['CredentialList', 'QuerySet', '$stateParams', 'GetBasePath', + function(list, qs, $stateParams, GetBasePath) { + let path = GetBasePath(list.basePath) || GetBasePath(list.name); + return qs.search(path, $stateParams[`${list.iterator}_search`]); + } + ] + } + }; + + this.editPermissions = { + name: 'credentials.edit.permissions', + url: '/permissions?{permission_search:queryset}', + resolve: { + ListDefinition: () => { + return { + name: 'permissions', + disabled: 'organization === undefined', + ngClick: `organization === undefined || $state.go('credentials.edit.permissions')`, + awToolTip: '{{permissionsTooltip}}', + dataTipWatch: 'permissionsTooltip', + awToolTipTabEnabledInEditMode: true, + dataPlacement: 'right', + basePath: 'api/v2/credentials/{{$stateParams.id}}/access_list/', + search: { + order_by: 'username' + }, + type: 'collection', + title: N_('Permissions'), + iterator: 'permission', + index: false, + open: false, + actions: { + add: { + ngClick: `$state.go('.add')`, + label: 'Add', + awToolTip: N_('Add a permission'), + actionClass: 'btn List-buttonSubmit', + buttonContent: '+ ' + N_('ADD'), + ngShow: '(credential_obj.summary_fields.user_capabilities.edit || canAdd)' + } + }, + fields: { + username: { + key: true, + label: N_('User'), + linkBase: 'users', + class: 'col-lg-3 col-md-3 col-sm-3 col-xs-4' + }, + role: { + label: N_('Role'), + type: 'role', + nosort: true, + class: 'col-lg-4 col-md-4 col-sm-4 col-xs-4' + }, + team_roles: { + label: N_('Team Roles'), + type: 'team_roles', + nosort: true, + class: 'col-lg-5 col-md-5 col-sm-5 col-xs-4' + } + } + }; + }, + Dataset: ['QuerySet', '$stateParams', (qs, $stateParams) => { + let id = $stateParams.credential_id; + let path = `api/v2/credentials/${id}/access_list/`; + + return qs.search(path, $stateParams[`permission_search`]); + } + ] + }, + params: { + permission_search: { + value: { + page_size: '20', + order_by: 'username' + }, + dynamic:true, + squash:'' + } + }, + ncyBreadcrumb: { + parent: 'credentials.edit', + label: 'PERMISSIONS' + }, + views: { + 'related': { + templateProvider: function(CredentialForm, GenerateForm) { + let html = GenerateForm.buildCollection({ + mode: 'edit', + related: `permissions`, + form: typeof(CredentialForm) === 'function' ? + CredentialForm() : CredentialForm + }); + return html; + }, + controller: 'PermissionsList' + } + } + }; + + this.addPermissions = { + name: 'credentials.edit.permissions.add', + url: '/add-permissions', + resolve: { + usersDataset: [ + 'addPermissionsUsersList', + 'QuerySet', + '$stateParams', + 'GetBasePath', + (list, qs, $stateParams, GetBasePath) => { + let path = GetBasePath(list.basePath) || GetBasePath(list.name); + return qs.search(path, $stateParams.user_search); + + } + ], + teamsDataset: [ + 'addPermissionsTeamsList', + 'QuerySet', + '$stateParams', + 'GetBasePath', + (list, qs, $stateParams, GetBasePath) => { + let path = GetBasePath(list.basePath) || GetBasePath(list.name); + return qs.search(path, $stateParams.team_search); + } + ], + resourceData: ['CredentialModel', '$stateParams', (Credential, $stateParams) => { + return new Credential('get', $stateParams.credential_id) + .then(credential => ({ data: credential.get() })); + }], + }, + params: { + user_search: { + value: { + order_by: 'username', + page_size: 5 + }, + dynamic: true + }, + team_search: { + value: { + order_by: 'name', + page_size: 5 + }, + dynamic: true + } + }, + ncyBreadcrumb: { + skip: true + }, + views: { + 'modal@credentials.edit': { + template: ` + + ` + } + }, + onExit: $state => { + if ($state.transition) { + $('#add-permissions-modal').modal('hide'); + $('.modal-backdrop').remove(); + $('body').removeClass('modal-open'); + } + } + }; + + this.organization = { + params: { + organization_search: { + value: { + page_size: 5, + order_by: 'name' + }, + dynamic:true, + squash:'' + } + }, + data: { + basePath: 'organizations', + formChildState:true + }, + ncyBreadcrumb: { + skip: true + }, + views: { + 'organization@credentials.add': { + templateProvider: (ListDefinition, generateList) => { + let html = generateList.build({ + mode: 'lookup', + list: ListDefinition, + input_type: 'radio' + }); + + return `${html}`; + } + } + }, + resolve: { + ListDefinition: ['OrganizationList', function(list) { + return list; + }], + Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', + (list, qs, $stateParams, GetBasePath) => { + return qs.search( + GetBasePath('organizations'), + $stateParams[`${list.iterator}_search`] + ); + } + ] + }, + onExit: function($state) { + if ($state.transition) { + $('#form-modal').modal('hide'); + $('.modal-backdrop').remove(); + $('body').removeClass('modal-open'); + } + } + }; + + this.getStateConfiguration = (name) => { + switch (name) { + case 'list': + return this.list; + case 'edit-permissions': + return this.editPermissions; + case 'add-permissions': + return this.addPermissions; + case 'add-organization': + this.organization.name = 'credentials.add.organization'; + this.organization.url = '/organization'; + return this.organization; + default: + throw new Error(`Legacy state configuration for ${name} does not exist`); + }; + }; +} + +LegacyCredentialsService.$inject = [ + 'PathService' +]; + +export default LegacyCredentialsService; diff --git a/awx/ui/client/lib/components/_index.less b/awx/ui/client/lib/components/_index.less index dc1a201c5b..f7b6d078a3 100644 --- a/awx/ui/client/lib/components/_index.less +++ b/awx/ui/client/lib/components/_index.less @@ -3,6 +3,7 @@ @import 'modal/_index'; @import 'panel/_index'; @import 'popover/_index'; +@import 'search/_index'; @import 'tabs/_index'; @import 'table/_index'; @import 'utility/_index'; diff --git a/awx/ui/client/lib/components/action/link.directive.js b/awx/ui/client/lib/components/action/link.directive.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/awx/ui/client/lib/components/action/link.partial.html b/awx/ui/client/lib/components/action/link.partial.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/awx/ui/client/lib/components/index.js b/awx/ui/client/lib/components/index.js index a227872c69..b75e6beca4 100644 --- a/awx/ui/client/lib/components/index.js +++ b/awx/ui/client/lib/components/index.js @@ -10,7 +10,6 @@ import inputMessage from './input/message.directive'; import inputNumber from './input/number.directive'; import inputSelect from './input/select.directive'; import inputSecret from './input/secret.directive'; -import inputSearch from './input/search.directive'; import inputText from './input/text.directive'; import inputTextarea from './input/textarea.directive'; import inputTextareaSecret from './input/textarea-secret.directive'; @@ -19,6 +18,8 @@ import panel from './panel/panel.directive'; import panelHeading from './panel/heading.directive'; import panelBody from './panel/body.directive'; import popover from './popover/popover.directive'; +import search from './search/search.directive'; +import searchKey from './search/key.directive'; import tab from './tabs/tab.directive'; import tabGroup from './tabs/group.directive'; import table from './table/table.directive'; @@ -39,7 +40,6 @@ angular .directive('atInputNumber', inputNumber) .directive('atInputSecret', inputSecret) .directive('atInputSelect', inputSelect) - .directive('atInputSearch', inputSearch) .directive('atInputText', inputText) .directive('atInputTextarea', inputTextarea) .directive('atInputTextareaSecret', inputTextareaSecret) @@ -48,6 +48,8 @@ angular .directive('atPanelHeading', panelHeading) .directive('atPanelBody', panelBody) .directive('atPopover', popover) + .directive('atSearch', search) + .directive('atSearchKey', searchKey) .directive('atTab', tab) .directive('atTabGroup', tabGroup) .directive('atTable', table) diff --git a/awx/ui/client/lib/components/input/_index.less b/awx/ui/client/lib/components/input/_index.less index 9d52ea1c03..bff0e535d6 100644 --- a/awx/ui/client/lib/components/input/_index.less +++ b/awx/ui/client/lib/components/input/_index.less @@ -172,42 +172,6 @@ margin: 0; } -.at-InputSearch-group--left { - padding-right: @at-margin-item-column; -} - -.at-InputSearch-group--right { - padding-left: 0; -} - -.at-InputSearch-well { - margin: @at-margin-top-search-key 0 0 0; - padding: @at-padding-well; -} - -.at-InputSearch-well { - margin: @at-margin-top-search-key 0 0 0; - padding: @at-padding-well; -} - -.at-InputSearch-toggle { - width: 100%; - - &, &:focus, &:visited, &:active { - background: @at-color-default; - cursor: pointer; - } -} - -.at-InputSearch-toggle--active { - &, &:hover, &:focus, &:visited, &:active { - border: @at-color-search-key-active; - background: @at-color-search-key-active; - color: @at-color-default; - cursor: pointer; - } -} - .at-InputSelect { position: relative; width: 100%; diff --git a/awx/ui/client/lib/components/input/lookup.directive.js b/awx/ui/client/lib/components/input/lookup.directive.js index 801e4b55e8..0b520136c7 100644 --- a/awx/ui/client/lib/components/input/lookup.directive.js +++ b/awx/ui/client/lib/components/input/lookup.directive.js @@ -3,11 +3,7 @@ function atInputLookupLink (scope, element, attrs, controllers) { let inputController = controllers[1]; scope.ns = 'lookup'; - scope[scope.ns] = { - modal: {}, - search: {}, - table: {} - }; + scope[scope.ns] = { modal: {} }; if (scope.tab === '1') { element.find('input')[0].focus(); @@ -16,32 +12,38 @@ function atInputLookupLink (scope, element, attrs, controllers) { inputController.init(scope, element, formController); } -function AtInputLookupController (baseInputController) { +function AtInputLookupController (baseInputController, $state) { let vm = this || {}; let scope; let modal; - let search; - let table; vm.init = (_scope_, element, form) => { baseInputController.call(vm, 'input', _scope_, element, form); scope = _scope_; + scope.$watch('organization', () => { + if (scope.organization) { + scope.state._value = scope.organization; + scope.state._displayValue = scope.organization_name; + } + }); + modal = scope.lookup.modal; - search = scope.lookup.search; - table = scope.lookup.table; vm.check(); }; vm.search = () => { - modal.show(`Select ${scope.state.label}`); + $state.go('credentials.add.organization'); }; } -AtInputLookupController.$inject = ['BaseInputController']; +AtInputLookupController.$inject = [ + 'BaseInputController', + '$state' +]; function atInputLookup (pathService) { return { diff --git a/awx/ui/client/lib/components/input/lookup.partial.html b/awx/ui/client/lib/components/input/lookup.partial.html index dc168d9d77..6f5797486b 100644 --- a/awx/ui/client/lib/components/input/lookup.partial.html +++ b/awx/ui/client/lib/components/input/lookup.partial.html @@ -13,7 +13,7 @@ - - - - +
diff --git a/awx/ui/client/lib/components/modal/modal.directive.js b/awx/ui/client/lib/components/modal/modal.directive.js index b5072affa6..2733bb2e1e 100644 --- a/awx/ui/client/lib/components/modal/modal.directive.js +++ b/awx/ui/client/lib/components/modal/modal.directive.js @@ -2,11 +2,10 @@ const DEFAULT_ANIMATION_DURATION = 150; function atModalLink (scope, el, attrs, controllers) { let modalController = controllers[0]; - let container = el[0]; let property = `scope.${scope.ns}.modal`; let done = scope.$watch(property, () => { - modalController.init(scope, container); + modalController.init(scope, el); done(); }); } @@ -14,11 +13,13 @@ function atModalLink (scope, el, attrs, controllers) { function AtModalController (eventService) { let vm = this; - let container; + let overlay; + let modal; let listeners; - vm.init = (scope, _container_) => { - container = _container_; + vm.init = (scope, el) => { + overlay = el[0]; + modal = el.find('.at-Modal-window')[0]; vm.modal = scope[scope.ns].modal; vm.modal.show = vm.show; @@ -35,36 +36,34 @@ function AtModalController (eventService) { [window, 'click', vm.clickToHide] ]); - container.style.display = 'block'; - container.style.opacity = 1; + overlay.style.display = 'block'; + overlay.style.opacity = 1; }; vm.hide = () => { - container.style.opacity = 0; + overlay.style.opacity = 0; eventService.remove(listeners); - setTimeout(() => { - container.style.display = 'none'; - vm.modal.message = ''; - vm.modal.title = ''; - }, DEFAULT_ANIMATION_DURATION); + setTimeout(() => overlay.style.display = 'none', DEFAULT_ANIMATION_DURATION); }; vm.clickToHide = event => { - if (vm.clickIsOutsideContainer(event)) { - console.log('outside'); - } else { - console.log('inside'); + if (vm.clickIsOutsideModal(event)) { + vm.hide(); } }; - vm.clickIsOutsideContainer = e => { - let pos = container.getBoundingClientRect(); - let ex = e.clientX; - let ey = e.clientY; + vm.clickIsOutsideModal = e => { + let m = modal.getBoundingClientRect(); + let cx = e.clientX; + let cy = e.clientY; + + if (cx < m.left || cx > m.right || cy > m.bottom || cy < m.top) { + return true; + } - console.log(e, pos); + return false; }; } diff --git a/awx/ui/client/lib/components/modal/modal.partial.html b/awx/ui/client/lib/components/modal/modal.partial.html index 1547b1d857..66db4d9d49 100644 --- a/awx/ui/client/lib/components/modal/modal.partial.html +++ b/awx/ui/client/lib/components/modal/modal.partial.html @@ -1,6 +1,6 @@