diff --git a/awx/ui_next/src/api/index.js b/awx/ui_next/src/api/index.js
index 9d76cc8bd8..526cb7c35c 100644
--- a/awx/ui_next/src/api/index.js
+++ b/awx/ui_next/src/api/index.js
@@ -1,7 +1,7 @@
import AdHocCommands from './models/AdHocCommands';
import Config from './models/Config';
-import CredentialTypes from './models/CredentialTypes'
-import Credentials from './models/Credentials'
+import CredentialTypes from './models/CredentialTypes';
+import Credentials from './models/Credentials';
import InstanceGroups from './models/InstanceGroups';
import Inventories from './models/Inventories';
import InventorySources from './models/InventorySources';
diff --git a/awx/ui_next/src/api/models/JobTemplates.js b/awx/ui_next/src/api/models/JobTemplates.js
index 9941ad220d..e84df42ec1 100644
--- a/awx/ui_next/src/api/models/JobTemplates.js
+++ b/awx/ui_next/src/api/models/JobTemplates.js
@@ -46,11 +46,16 @@ class JobTemplates extends InstanceGroupsMixin(NotificationsMixin(Base)) {
}
associateCredentials(id, credential) {
- return this.http.post(`${this.baseUrl}${id}/credentials/`, { id: credential });
+ return this.http.post(`${this.baseUrl}${id}/credentials/`, {
+ id: credential,
+ });
}
disassociateCredentials(id, credential) {
- return this.http.post(`${this.baseUrl}${id}/credentials/`, { id: credential, disassociate: true });
+ return this.http.post(`${this.baseUrl}${id}/credentials/`, {
+ id: credential,
+ disassociate: true,
+ });
}
}
diff --git a/awx/ui_next/src/components/Lookup/CredentialsLookup.jsx b/awx/ui_next/src/components/Lookup/CredentialsLookup.jsx
index 1648d7d910..a57b3a76eb 100644
--- a/awx/ui_next/src/components/Lookup/CredentialsLookup.jsx
+++ b/awx/ui_next/src/components/Lookup/CredentialsLookup.jsx
@@ -16,67 +16,73 @@ const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
class CredentialsLookup extends React.Component {
constructor(props) {
- super(props)
+ super(props);
this.state = {
credentials: props.credentials,
- selectedCredentialType: {label: "Machine", id: 1, kind: 'ssh'},
- credentialTypes: []
- }
+ selectedCredentialType: { label: 'Machine', id: 1, kind: 'ssh' },
+ credentialTypes: [],
+ };
- this.handleCredentialTypeSelect = this.handleCredentialTypeSelect.bind(this);
+ this.handleCredentialTypeSelect = this.handleCredentialTypeSelect.bind(
+ this
+ );
this.loadCredentials = this.loadCredentials.bind(this);
this.loadCredentialTypes = this.loadCredentialTypes.bind(this);
this.toggleCredential = this.toggleCredential.bind(this);
}
componentDidMount() {
- this.loadCredentials({page: 1, page_size: 5, order_by:'name'})
+ this.loadCredentials({ page: 1, page_size: 5, order_by: 'name' });
this.loadCredentialTypes();
}
componentDidUpdate(prevState) {
- const {selectedType} = this.state
+ const { selectedType } = this.state;
if (prevState.selectedType !== selectedType) {
Promise.all([this.loadCredentials()]);
}
}
async loadCredentialTypes() {
- const {onError} =this.props
+ const { onError } = this.props;
try {
- const { data } = await CredentialTypesAPI.read()
- const acceptableTypes = ["machine", "cloud", "net", "ssh", "vault"]
- const credentialTypes =[]
- data.results
- .forEach(cred => {
- acceptableTypes.forEach(aT => {
- if (aT === cred.kind) {
- // This object has several repeated values as some of it's children
- // require different field values.
- cred = {
- id: cred.id, kind: cred.kind, type: cred.namespace,
- value: cred.name, label: cred.name, isDisabled: false
- }
- credentialTypes.push(cred)
- }})
- })
- this.setState({ credentialTypes })
- } catch (err){
- onError(err)
- }
- }
+ const { data } = await CredentialTypesAPI.read();
+ const acceptableTypes = ['machine', 'cloud', 'net', 'ssh', 'vault'];
+ const credentialTypes = [];
+ data.results.forEach(cred => {
+ acceptableTypes.forEach(aT => {
+ if (aT === cred.kind) {
+ // This object has several repeated values as some of it's children
+ // require different field values.
+ cred = {
+ id: cred.id,
+ kind: cred.kind,
+ type: cred.namespace,
+ value: cred.name,
+ label: cred.name,
+ isDisabled: false,
+ };
+ credentialTypes.push(cred);
+ }
+ });
+ });
+ this.setState({ credentialTypes });
+ } catch (err) {
+ onError(err);
+ }
+ }
async loadCredentials(params) {
const { selectedCredentialType } = this.state;
- params.credential_type = selectedCredentialType.id || 1
- return CredentialsAPI.read(params)
+ params.credential_type = selectedCredentialType.id || 1;
+ return CredentialsAPI.read(params);
}
handleCredentialTypeSelect(value, type) {
- const {credentialTypes} = this.state
- const selectedType = credentialTypes.filter(item => item.label === type)
- this.setState({selectedCredentialType: selectedType[0]})
+ const { credentialTypes } = this.state;
+ const selectedType = credentialTypes.filter(item => item.label === type);
+ this.setState({ selectedCredentialType: selectedType[0] });
}
toggleCredential(item) {
@@ -84,26 +90,31 @@ class CredentialsLookup extends React.Component {
const { onChange } = this.props;
const index = stateToUpdate.findIndex(
credential => credential.id === item.id
- )
+ );
if (index > -1) {
- const newCredentialsList = stateToUpdate.filter(cred => cred.id !== item.id)
+ const newCredentialsList = stateToUpdate.filter(
+ cred => cred.id !== item.id
+ );
this.setState({ credentials: newCredentialsList });
- onChange(newCredentialsList)
+ onChange(newCredentialsList);
return;
}
- const credentialTypeOccupied = stateToUpdate.some(cred => cred.kind === item.kind);
- if (selectedCredentialType.value === "Vault" || !credentialTypeOccupied ) {
- item.credentialType = selectedCredentialType
- this.setState({ credentials: [...stateToUpdate, item] })
- onChange([...stateToUpdate, item])
+ const credentialTypeOccupied = stateToUpdate.some(
+ cred => cred.kind === item.kind
+ );
+ if (selectedCredentialType.value === 'Vault' || !credentialTypeOccupied) {
+ item.credentialType = selectedCredentialType;
+ this.setState({ credentials: [...stateToUpdate, item] });
+ onChange([...stateToUpdate, item]);
} else {
- const credsList = [...stateToUpdate]
- const occupyingCredIndex = stateToUpdate.findIndex(occupyingCred =>
- occupyingCred.kind === item.kind)
- credsList.splice(occupyingCredIndex, 1, item)
- this.setState({ credentials: credsList })
- onChange(credsList)
+ const credsList = [...stateToUpdate];
+ const occupyingCredIndex = stateToUpdate.findIndex(
+ occupyingCred => occupyingCred.kind === item.kind
+ );
+ credsList.splice(occupyingCredIndex, 1, item);
+ this.setState({ credentials: credsList });
+ onChange(credsList);
}
}
@@ -112,21 +123,18 @@ class CredentialsLookup extends React.Component {
const { credentials, selectedCredentialType, credentialTypes } = this.state;
return (
-
- {tooltip && (
-
-
-
- )}
- {credentialTypes && (
-
+ {tooltip && (
+
+
+
+ )}
+ {credentialTypes && (
+
- )}
-
+ )}
+
);
}
}
diff --git a/awx/ui_next/src/components/Lookup/Lookup.jsx b/awx/ui_next/src/components/Lookup/Lookup.jsx
index 4342bf5fbe..599a0576ae 100644
--- a/awx/ui_next/src/components/Lookup/Lookup.jsx
+++ b/awx/ui_next/src/components/Lookup/Lookup.jsx
@@ -21,9 +21,9 @@ import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components';
-import AnsibleSelect from '../AnsibleSelect'
+import AnsibleSelect from '../AnsibleSelect';
import PaginatedDataList from '../PaginatedDataList';
-import VerticalSeperator from '../VerticalSeparator'
+import VerticalSeperator from '../VerticalSeparator';
import DataListToolbar from '../DataListToolbar';
import CheckboxListItem from '../CheckboxListItem';
import SelectedList from '../SelectedList';
@@ -68,13 +68,13 @@ class Lookup extends React.Component {
results: [],
count: 0,
error: null,
- isDropdownOpen: false
+ isDropdownOpen: false,
};
- this.qsConfig = getQSConfig(props.qsNamespace, {
- page: 1,
- page_size: 5,
- order_by: props.sortedColumnKey,
- });
+ this.qsConfig = getQSConfig(props.qsNamespace, {
+ page: 1,
+ page_size: 5,
+ order_by: props.sortedColumnKey,
+ });
this.handleModalToggle = this.handleModalToggle.bind(this);
this.toggleSelected = this.toggleSelected.bind(this);
this.saveModal = this.saveModal.bind(this);
@@ -84,8 +84,7 @@ class Lookup extends React.Component {
}
componentDidMount() {
- const {onLoadCredentialTypes} = this.props
- ;
+ const { onLoadCredentialTypes } = this.props;
if (onLoadCredentialTypes) {
Promise.all([onLoadCredentialTypes(), this.getData()]);
} else {
@@ -95,21 +94,23 @@ class Lookup extends React.Component {
componentDidUpdate(prevProps) {
const { location, selectedCategory } = this.props;
- if ((location !== prevProps.location) ||
- (prevProps.selectedCategory !== selectedCategory)) {
+ if (
+ location !== prevProps.location ||
+ prevProps.selectedCategory !== selectedCategory
+ ) {
this.getData();
}
}
toggleDropdown() {
const { isDropdownOpen } = this.state;
- this.setState({isDropdownOpen: !isDropdownOpen})
+ this.setState({ isDropdownOpen: !isDropdownOpen });
}
assertCorrectValueType() {
const { multiple, value, selectCategoryOptions } = this.props;
if (selectCategoryOptions) {
- return
+ return;
}
if (!multiple && Array.isArray(value)) {
throw new Error(
@@ -130,30 +131,37 @@ class Lookup extends React.Component {
this.setState({ error: false });
try {
- const { data } = await getItems(queryParams);
+ const { data } = await getItems(queryParams);
const { results, count } = data;
- this.setState({
- results,
- count,
- });
+ this.setState({
+ results,
+ count,
+ });
} catch (err) {
this.setState({ error: true });
}
}
toggleSelected(row) {
- const { name, onLookupSave, multiple, onToggleItem, selectCategoryOptions } = this.props;
const {
- lookupSelectedItems: updatedSelectedItems, isModalOpen
+ name,
+ onLookupSave,
+ multiple,
+ onToggleItem,
+ selectCategoryOptions,
+ } = this.props;
+ const {
+ lookupSelectedItems: updatedSelectedItems,
+ isModalOpen,
} = this.state;
const selectedIndex = updatedSelectedItems.findIndex(
selectedRow => selectedRow.id === row.id
- );
+ );
if (multiple) {
if (selectCategoryOptions) {
- onToggleItem(row, isModalOpen)
+ onToggleItem(row, isModalOpen);
}
if (selectedIndex > -1) {
updatedSelectedItems.splice(selectedIndex, 1);
@@ -171,8 +179,8 @@ class Lookup extends React.Component {
// This handles the case where the user removes chips from the lookup input
// while the modal is closed
if (!isModalOpen) {
- onLookupSave(updatedSelectedItems, name)
- };
+ onLookupSave(updatedSelectedItems, name);
+ }
}
handleModalToggle() {
@@ -190,7 +198,7 @@ class Lookup extends React.Component {
} else {
this.clearQSParams();
if (selectCategory) {
- selectCategory(null, "Machine");
+ selectCategory(null, 'Machine');
}
}
this.setState(prevState => ({
@@ -201,11 +209,12 @@ class Lookup extends React.Component {
saveModal() {
const { onLookupSave, name, multiple } = this.props;
const { lookupSelectedItems } = this.state;
- const value = multiple ? lookupSelectedItems : lookupSelectedItems[0] || null;
-
- this.handleModalToggle();
- onLookupSave(value, name);
+ const value = multiple
+ ? lookupSelectedItems
+ : lookupSelectedItems[0] || null;
+ this.handleModalToggle();
+ onLookupSave(value, name);
}
clearQSParams() {
@@ -237,12 +246,12 @@ class Lookup extends React.Component {
required,
i18n,
selectCategoryOptions,
- selectedCategory
+ selectedCategory,
} = this.props;
const header = lookupHeader || i18n._(t`Items`);
const canDelete = !required || (multiple && value.length > 1);
const chips = () => {
- return (selectCategoryOptions && selectCategoryOptions.length > 0) ? (
+ return selectCategoryOptions && selectCategoryOptions.length > 0 ? (
{(multiple ? value : [value]).map(chip => (
))}
- )
- }
+ );
+ };
return (
@@ -305,11 +314,19 @@ class Lookup extends React.Component {
,
]}
>
- {(selectCategoryOptions && selectCategoryOptions.length > 0) && (
+ {selectCategoryOptions && selectCategoryOptions.length > 0 && (
Selected Category
-
+
)}
i.id === item.id)
- : lookupSelectedItems.some(i => i.id === item.id)}
+ isSelected={
+ selectCategoryOptions
+ ? value.some(i => i.id === item.id)
+ : lookupSelectedItems.some(i => i.id === item.id)
+ }
onSelect={() => this.toggleSelected(item)}
- isRadio={!multiple || ((selectCategoryOptions && selectCategoryOptions.length) && selectedCategory.value !== "Vault")}
+ isRadio={
+ !multiple ||
+ (selectCategoryOptions &&
+ selectCategoryOptions.length &&
+ selectedCategory.value !== 'Vault')
+ }
/>
)}
renderToolbar={props => }
@@ -340,7 +365,9 @@ class Lookup extends React.Component {
showOverflowAfter={5}
onRemove={this.toggleSelected}
isReadOnly={!canDelete}
- isCredentialList={selectCategoryOptions && selectCategoryOptions.length > 0}
+ isCredentialList={
+ selectCategoryOptions && selectCategoryOptions.length > 0
+ }
/>
)}
{error ? error
: ''}
diff --git a/awx/ui_next/src/components/SelectedList/SelectedList.jsx b/awx/ui_next/src/components/SelectedList/SelectedList.jsx
index e773404054..661eeec382 100644
--- a/awx/ui_next/src/components/SelectedList/SelectedList.jsx
+++ b/awx/ui_next/src/components/SelectedList/SelectedList.jsx
@@ -27,34 +27,34 @@ class SelectedList extends Component {
onRemove,
displayKey,
isReadOnly,
- isCredentialList
+ isCredentialList,
} = this.props;
- const chips = isCredentialList ? selected.map(item => (
- onRemove(item)}
- credential={item}
- >
- {item[displayKey]}
-
- )) : selected.map(item => (
- onRemove(item)}
- >
- {item[displayKey]}
-
- ))
+ const chips = isCredentialList
+ ? selected.map(item => (
+ onRemove(item)}
+ credential={item}
+ >
+ {item[displayKey]}
+
+ ))
+ : selected.map(item => (
+ onRemove(item)}
+ >
+ {item[displayKey]}
+
+ ));
return (
{label}
-
- {chips}
-
+ {chips}
);
diff --git a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx
index 9d25ad3fc7..979c2f9728 100644
--- a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx
+++ b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx
@@ -34,7 +34,7 @@ function JobTemplateAdd({ history, i18n }) {
await Promise.all([
submitLabels(id, labels, organizationId),
submitInstanceGroups(id, instanceGroups),
- submitCredentials(id, credentials)
+ submitCredentials(id, credentials),
]);
history.push(`/templates/${type}/${id}/details`);
} catch (error) {
@@ -65,8 +65,8 @@ function JobTemplateAdd({ history, i18n }) {
function submitCredentials(templateId, credentials = []) {
const associateCredentials = credentials.map(cred =>
JobTemplatesAPI.associateCredentials(templateId, cred.id)
- )
- return Promise.all(associateCredentials)
+ );
+ return Promise.all(associateCredentials);
}
function handleCancel() {
diff --git a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx
index 5272a46149..b6cfc65fd6 100644
--- a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx
+++ b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.jsx
@@ -120,7 +120,7 @@ class JobTemplateEdit extends Component {
await Promise.all([
this.submitLabels(labels, organizationId),
this.submitInstanceGroups(instanceGroups, initialInstanceGroups),
- this.submitCredentials(credentials)
+ this.submitCredentials(credentials),
]);
history.push(this.detailsUrl);
} catch (formSubmitError) {
@@ -163,7 +163,7 @@ class JobTemplateEdit extends Component {
const associatePromises = await added.map(group =>
JobTemplatesAPI.associateInstanceGroup(template.id, group.id)
);
- return Promise.all([...disassociatePromises, ...associatePromises, ]);
+ return Promise.all([...disassociatePromises, ...associatePromises]);
}
async submitCredentials(newCredentials) {
@@ -178,9 +178,9 @@ class JobTemplateEdit extends Component {
const disassociatePromise = await Promise.all(disassociateCredentials);
const associateCredentials = added.map(cred =>
JobTemplatesAPI.associateCredentials(template.id, cred.id)
- )
- const associatePromise = Promise.all(associateCredentials)
- return Promise.all([disassociatePromise, associatePromise])
+ );
+ const associatePromise = Promise.all(associateCredentials);
+ return Promise.all([disassociatePromise, associatePromise]);
}
handleCancel() {
diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
index df37d1319a..310db6f5be 100644
--- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
+++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
@@ -27,7 +27,7 @@ import {
InventoryLookup,
InstanceGroupsLookup,
ProjectLookup,
- CredentialsLookup
+ CredentialsLookup,
} from '@components/Lookup';
import { JobTemplatesAPI } from '@api';
import LabelSelect from './LabelSelect';
@@ -86,8 +86,7 @@ class JobTemplateForm extends Component {
const { validateField } = this.props;
this.setState({ contentError: null, hasContentLoading: true });
// TODO: determine when LabelSelect has finished loading labels
- Promise.all([this.loadRelatedInstanceGroups(),
- ]).then(() => {
+ Promise.all([this.loadRelatedInstanceGroups()]).then(() => {
this.setState({ hasContentLoading: false });
validateField('project');
});
@@ -329,8 +328,10 @@ class JobTemplateForm extends Component {
this.setState({ contentError: err })}
credentials={template.summary_fields.credentials}
- onChange={value => (form.setFieldValue('credentials', value))}
- tooltip={i18n._(t`Select credentials that allow Tower to access the nodes this job will be ran against. You can only select one credential of each type. For machine credentials (SSH), checking "Prompt on launch" without selecting credentials will require you to select a machine credential at run time. If you select credentials and check "Prompt on launch", the selected credential(s) become the defaults that can be updated at run time.`)}
+ onChange={value => form.setFieldValue('credentials', value)}
+ tooltip={i18n._(
+ t`Select credentials that allow Tower to access the nodes this job will be ran against. You can only select one credential of each type. For machine credentials (SSH), checking "Prompt on launch" without selecting credentials will require you to select a machine credential at run time. If you select credentials and check "Prompt on launch", the selected credential(s) become the defaults that can be updated at run time.`
+ )}
/>
)}
/>
@@ -604,7 +605,7 @@ const FormikApp = withFormik({
initialInstanceGroups: [],
instanceGroups: [],
initialCredentials: summary_fields.credentials || [],
- credentials: []
+ credentials: [],
};
},
handleSubmit: (values, { props }) => props.handleSubmit(values),