diff --git a/awx/ui_next/src/components/AddRole/AddResourceRole.jsx b/awx/ui_next/src/components/AddRole/AddResourceRole.jsx index 95cb910295..2f12953afa 100644 --- a/awx/ui_next/src/components/AddRole/AddResourceRole.jsx +++ b/awx/ui_next/src/components/AddRole/AddResourceRole.jsx @@ -144,7 +144,7 @@ class AddResourceRole extends React.Component { currentStepId, maxEnabledStep, } = this.state; - const { onClose, roles, i18n } = this.props; + const { onClose, roles, i18n, resource } = this.props; // Object roles can be user only, so we remove them when // showing role choices for team access @@ -235,18 +235,24 @@ class AddResourceRole extends React.Component { t`Choose the type of resource that will be receiving new roles. For example, if you'd like to add new roles to a set of users please choose Users and click Next. You'll be able to select the specific resources in the next step.` )} + this.handleResourceSelect('users')} /> - this.handleResourceSelect('teams')} - /> + {resource?.type === 'credential' && + !resource?.organization ? null : ( + this.handleResourceSelect('teams')} + /> + )} ), enableNext: selectedResource !== null, @@ -329,10 +335,12 @@ AddResourceRole.propTypes = { onClose: PropTypes.func.isRequired, onSave: PropTypes.func.isRequired, roles: PropTypes.shape(), + resource: PropTypes.shape(), }; AddResourceRole.defaultProps = { roles: {}, + resource: {}, }; export { AddResourceRole as _AddResourceRole }; diff --git a/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx b/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx index 76f5dbb87e..a681999391 100644 --- a/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx +++ b/awx/ui_next/src/components/AddRole/AddResourceRole.test.jsx @@ -221,4 +221,22 @@ describe('<_AddResourceRole />', () => { expect(TeamsAPI.associateRole).toHaveBeenCalledTimes(2); expect(handleSave).toHaveBeenCalled(); }); + + test('should not display team as a choice in case credential does not have organization', () => { + const spy = jest.spyOn(_AddResourceRole.prototype, 'handleResourceSelect'); + const wrapper = mountWithContexts( + {}} + onSave={() => {}} + roles={roles} + resource={{ type: 'credential', organization: null }} + />, + { context: { network: { handleHttpError: () => {} } } } + ).find('AddResourceRole'); + const selectableCardWrapper = wrapper.find('SelectableCard'); + expect(selectableCardWrapper.length).toBe(1); + selectableCardWrapper.first().simulate('click'); + expect(spy).toHaveBeenCalledWith('users'); + expect(wrapper.state('selectedResource')).toBe('users'); + }); }); diff --git a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx index 4568c477e4..b5b1765d45 100644 --- a/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx +++ b/awx/ui_next/src/components/ResourceAccessList/ResourceAccessList.jsx @@ -155,6 +155,7 @@ function ResourceAccessList({ i18n, apiModel, resource }) { fetchAccessRecords(); }} roles={resource.summary_fields.object_roles} + resource={resource} /> )} {showDeleteModal && ( diff --git a/awx/ui_next/src/components/SelectableCard/SelectableCard.jsx b/awx/ui_next/src/components/SelectableCard/SelectableCard.jsx index db9f5008ed..338c089c53 100644 --- a/awx/ui_next/src/components/SelectableCard/SelectableCard.jsx +++ b/awx/ui_next/src/components/SelectableCard/SelectableCard.jsx @@ -31,7 +31,14 @@ const Description = styled.p` font-size: 14px; `; -function SelectableCard({ label, description, onClick, isSelected, dataCy }) { +function SelectableCard({ + label, + description, + onClick, + isSelected, + dataCy, + ariaLabel, +}) { return ( @@ -55,12 +63,14 @@ SelectableCard.propTypes = { description: PropTypes.string, onClick: PropTypes.func.isRequired, isSelected: PropTypes.bool, + ariaLabel: PropTypes.string, }; SelectableCard.defaultProps = { label: '', description: '', isSelected: false, + ariaLabel: '', }; export default SelectableCard; diff --git a/awx/ui_next/src/screens/Credential/Credential.jsx b/awx/ui_next/src/screens/Credential/Credential.jsx index e06dce231e..42c18a0d41 100644 --- a/awx/ui_next/src/screens/Credential/Credential.jsx +++ b/awx/ui_next/src/screens/Credential/Credential.jsx @@ -56,15 +56,12 @@ function Credential({ i18n, setBreadcrumb }) { id: 99, }, { name: i18n._(t`Details`), link: `/credentials/${id}/details`, id: 0 }, - ]; - - if (credential && credential.organization) { - tabsArray.push({ + { name: i18n._(t`Access`), link: `/credentials/${id}/access`, id: 1, - }); - } + }, + ]; let showCardHeader = true; @@ -108,14 +105,12 @@ function Credential({ i18n, setBreadcrumb }) { , - credential.organization && ( - - - - ), + + + , {!hasContentLoading && ( diff --git a/awx/ui_next/src/screens/Credential/Credential.test.jsx b/awx/ui_next/src/screens/Credential/Credential.test.jsx index 7cb192ac0c..ed3404c1a6 100644 --- a/awx/ui_next/src/screens/Credential/Credential.test.jsx +++ b/awx/ui_next/src/screens/Credential/Credential.test.jsx @@ -31,7 +31,7 @@ describe('', () => { wrapper = mountWithContexts( {}} />); }); await waitForElement(wrapper, 'ContentLoading', el => el.length === 0); - await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 2); + await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 3); }); test('initially renders org-based credential succesfully', async () => { diff --git a/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx b/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx index 5f8066b904..55190e3a5f 100644 --- a/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx +++ b/awx/ui_next/src/screens/Credential/CredentialDetail/CredentialDetail.jsx @@ -78,7 +78,7 @@ function CredentialDetail({ i18n, credential }) { {} ), }; - }, [credentialId, credential_type]), + }, [credentialId, credential_type.id]), { fields: [], managedByTower: true,